Compare commits

...

151 Commits

Author SHA1 Message Date
Jon Hunter
addce432b9 misc: mods: Add missing conftest.h
The MODS dmabuf driver is missing the conftest.h header and so the
conftest changes are not being applied as expected.

Bug 4991705

Change-Id: Ia6e17a717619cdf74bb0eeb441467c81342514e2
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3505943
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-12-10 07:53:59 -08:00
Jon Hunter
255dac6de5 crypto: tegra: Update crypto_engine_ctx handling
In Linux v6.6, the crypto_engine_ctx structure was removed and the
crypto_engine_ops was moved from this structure to the crypto_alg
structure. The Tegra Security Engine driver was updated accordingly to
populate the crypto_engine_ops in the appropriate structure depending
on whether the crypto_engine_ctx structure is present or not.

Currently conftest is using the presence of the crypto_engine_ctx
structure to decide where to populate the crypto_engine_ops. While
this works, it is possible that a kernel older than v6.6 also includes
a backport of commit e5e7eb023f24 ("crypto: engine - Move
crypto_engine_ops from request into crypto_alg") that moves the ops
to the crypto_alg structure. Although backporting this commit alone
should not cause any problems, it is better to detect if this commit
is present rather than relying on the presence of crypto_engine_ctx
structure.

To detect the presence of commit e5e7eb023f24 we can simply detect if
one of the functions added and exported by this commit is present.
For example, the function crypto_engine_register_aead() was added and
exported by this commit. Therefore, update conftest to detect if
commit e5e7eb023f24 is present and then update the Tegra Security
Engine accordingly.

Bug 5564561

Change-Id: I3f7688e6e954a158094a9a2fdf73354f765ed680
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499816
(cherry picked from commit c1631d32f8d80cd31f54e7297c542f308a281d25)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3494992
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Hiteshkumar Patel <hiteshkumarg@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-09 09:39:12 -08:00
Jon Hunter
0fcc21d871 conftest: Fix return types for timer functions
The function hrtimer_setup() returns void and the function
timer_delete() returns int, and so correct the return types
for the respective conftest functions.

JIRA LINQPJ14-47

Change-Id: I569f4fae0bf01f894583570116125a44a1757ff3
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3342808
(cherry picked from commit b9d81360d102ca2f573a9cdeafb0868d82edf77d)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499794
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2025-12-04 09:42:24 -08:00
Jon Hunter
2ec6cdcc9b drivers: Update timer APIs for Linux v6.15
In Linux v6.15, the timer APIs hrtimer_init() and del_timer() have been
removed. The hrtimer_setup() was added in Linux v6.13 to replace
hrtimer_init() and hrtimer_init() have finally been removed. The
functions del_timer()/del_timer_sync() were renamed to
timer_delete()/timer_delete_sync() in Linux v6.15. Use conftest to
detect these changes and update the drivers as necessary.

JIRA LINQPJ14-47

Change-Id: Id3994900384aad4b91155507cda91e04898ab12c
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3336168
(cherry picked from commit ce90abdb8137610988f291cd02ed8cf97bca673f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499760
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:41:48 -08:00
Jon Hunter
48373c24ad video: tegra: nvmap: Fix build for Linux v6.15
In Linux v6.15, the function ioremap_prot() was updated to pass a
variable of type pgprot_t instead of an unsigned long. Add a conftest
test to check for this and update the NVMAP driver accordlingly to fix
the build for Linux v6.15.

JIRA LINQPJ14-47

Change-Id: Icff9f63bf5c914997b69076435dd9e2432f343a3
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3332454
(cherry picked from commit b464d75b06c7976ae73e5d7a8660b49e29e1df77)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499759
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-12-04 09:41:43 -08:00
Jon Hunter
8e9d8552c3 net: nvethernet: Fix build for Linux v6.15
In Linux v6,15, a 'speed' argument was added to the phy_loopback()
function. Add a conftest test to detect this change and update the
nvethernet driver accordingly. Note that if 'speed' is set to 0 when
calling phy_loopback(), then phy_loopback() behaves the same way as it
did before this argument was added. So by default set speed to 0 for the
nvethernet driver.

JIRA LINQPJ14-47

Change-Id: I55f775e672bfa1a00c9ccbd825c82be1868b0b52
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3330685
(cherry picked from commit 5ba2674826bc9e39b320fd79afd7d52709a39eca)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499758
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:41:37 -08:00
Jon Hunter
13ad68519d ufs: Fix Tegra UFS for Linux v6.15
In Linux v6.15, the pwr_change_notify() function was updated making the
3rd argument of type const. Add a conftest to detect this and update the
Tegra UFS driver accordingly.

JIRA LINQPJ14-47

Change-Id: I83f22bf0961200d9078fb35d408dac9149d786d2
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3330680
(cherry picked from commit d9c16e70c4bf468a5ddab8a434693a8e7b442625)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499757
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2025-12-04 09:41:31 -08:00
Jon Hunter
3d26747166 blk: vblk: Fix build for Linux v6.15
In Linux v6.15, the 'request_queue' parameter was removed from the
function blk_rq_map_sg(). Add a conftest to check for this and update
the Tegra HV VBLK driver accordingly.

JIRA LINQPJ14-47

Change-Id: I140200fe7acbaebb383abd7939153178f0ca484a
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3330664
(cherry picked from commit a20fde1ade16dbfbac3f48327c360ca0a7c36545)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3475292
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2025-12-04 09:41:25 -08:00
Jon Hunter
3fba8947fb drm/tegra: Fix build for Linux v6.14
In Linux v6.14, the 'date' field was removed from the 'drm_driver'
structure. Add a test to conftest to detect this and update the Tegra
DRM driver accordingly.

Jira LINQPJ14-6

Change-Id: Ia3024321f12f8448d382deba996407f9d3232567
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3297069
(cherry picked from commit 12d50906f3800c37a35be59b49157797ed529159)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499756
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:41:20 -08:00
Jon Hunter
34b4ec7938 nvmap: Fix build for Linux v6.14
In Linux v6.14, the 'page_list' argument was dropped from the
__alloc_pages_bulk() function. Add a test to conftest to check for this
and update the NVMAP driver accordlingly to fix the build.

Jira LINQPJ14-6

Change-Id: Id3513890a9d948cb42abf7449d9fb3aa95edcf96
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3297065
(cherry picked from commit a7d79ff243f922e112bc85a0830455e3e422a04c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499755
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:41:14 -08:00
Jon Hunter
774a1ec13d ufs: Fix Tegra UFS for Linux v6.13
In Linux v6.13, the quirk definition 'UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS'
was removed and replaced with a function pointer than can be used to set
the DMA mask as needed for a given device. Update the Tegra UFS driver
to fix support for Linux v6.13. Note that prior to Linux v6.13, the flag
'UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS' would set the DMA mask to 32-bits
and so this change is equivalent to the configuration of prior kernels.

Bug 4991705

Change-Id: I859331e9eea918d2438d68b871642fee5e4148e0
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3283447
(cherry picked from commit 65cd166a825e33cb77c0f7ca8ae146a3e296fda6)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499754
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:41:07 -08:00
Jon Hunter
d9b938131d nvmap: Fix build for Linux v6.13
In Linux v6.13, commit b129125e1f96 ("arm64: asm-offsets: remove
DMA_{TO,FROM}_DEVICE") removes the definitions DMA_TO/FROM_DEVICE from
the assembly header file 'asm-offsets.h' which is used by the functions
__dma_map_area() and __dma_unmap_area() in nvmap_cache_maint.S.

From reviewing the NVMAP code, the function __dma_unmap_area() is never
used and so we can simply remove this. Split the __dma_map_area() into
two functions __dma_map_area_to_device() and
__dma_map_area_from_device() to avoid having to pass the direction.

Bug 4991895

Change-Id: I4a0f658401beff5c5e5457de72050b21acf820fa
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261710
(cherry picked from commit de3a6ce1cbff438cba468c5cf817e3fe297d47a0)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499753
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-12-04 09:41:02 -08:00
Jon Hunter
5c780b2c63 drivers: Fix MODULE_IMPORT_NS for Linux v6.13
In Linux v6.13, commit cdd30ebb1b9f ("module: Convert symbol namespace
to string literal") updated the MODULE_IMPORT_NS macro to take a string
literal as an argument in Linux v6.13. Use conftest to detect if
MODULE_IMPORT_NS takes a string literal as an argument and update the
various drivers accordingly.

Bug 4991705

Change-Id: I8f34860648965dc2334e2916d5404522510778ff
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263798
(cherry picked from commit 2e3d9e2ad27ffc6743ad1f0bca06b9a802182a7a)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499752
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:40:56 -08:00
Jon Hunter
5e815ff501 spi: Fix build for Linux v6.13
Commit 0809a9ccac4a ("spi: remove {devm_}spi_alloc_master/slave()")
removed devm_spi_alloc_master() and this breaks building the Tegra124
and Tegra210 SPI drivers for Linux v6.13. Commit b8d3b056a78d ("spi:
introduce new helpers with using modern naming") previously added new
helpers in Linux v6.2 which should be instead. Add a test for conftest
to detect if the kernel supports the function devm_spi_alloc_host()
and if so use this function.

Bug 4991705

Change-Id: I1d639297ef7adfdcde50927360607639b45a4a60
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261698
(cherry picked from commit c2219d8e43ca7e6509179206796b34c09ba1dbd1)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499751
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:40:51 -08:00
Jon Hunter
aee51acfea drm/tegra: Fix aperture support for Linux v6.13
In Linux v6.13, commit 689274a56c0c ("drm: Remove DRM aperture helpers")
removed the DRM aperture helper functions and drivers should simply use
the existing video helpers. Update the Tegra DRM driver to use
aperture_remove_all_conflicting_devices() if available to align with
upstream.

Bug 4991705

Change-Id: Ie4b78a4ea519ffcaaf972417ec2cbe7c436eb808
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261694
(cherry picked from commit 671f7a39d26449bcbf8fe242bdff7534b9aece63)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3475287
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:40:44 -08:00
Jon Hunter
0a8d8b47c7 drivers: gpu: Fix IOMMU support for Linux v6.13
In Linux v6.13, commit f6440fcc9c7b ("iommu: Remove
iommu_domain_alloc()") removed iommu_domain_alloc() and was replaced by
iommu_paging_domain_alloc(). Use conftest to detect if the function
iommu_paging_domain_alloc() is supported by the kernel and update the
Tegra DRM and Host1x drivers accordingly.

Bug 4991705

Change-Id: I86221d96232396fdb6bdccf40c412e029881c513
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261695
(cherry picked from commit e374ac996dceee884296c9f1e53fdd0f281b3e0c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499750
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-12-04 09:40:37 -08:00
Jon Hunter
0980dbb86e drm/tegra: Fix genpd support for Linux v6.13
In Linux v6.13, commit d6caca30a548 ("OPP: Drop redundant
*_opp_attach|detach_genpd()") removed devm_pm_opp_attach_genpd(). This
has been replaced by devm_pm_domain_attach_list(). Use conftest to
detect the presence of devm_pm_domain_attach_list() and update the Tegra
DRM driver accordingly.

Bug 4991705

Change-Id: I5a3bd258d3fce5b09fd4ba84adad166e4cf47cfb
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261693
(cherry picked from commit 4c08d4e516a89751afc8410553ccebff983e29d0)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499749
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:40:31 -08:00
Jon Hunter
c07615fe6a thermal: tegra-oc-event: Fix build for Linux v6.13
When compiling the tegra-oc-event driver with Linux v6.13 the build
fails with the following error:

 drivers/thermal/tegra234-oc-event.c:127:48: error: missing braces around
  initialiser [-Werror=missing-braces]
  127 | static const struct attribute_group oc1_data = {
      |                                                ^

The 'NULL' initialiser is not needed in the above structure because it
is not any array. Fix the build for Linux v6.13 by removing the NULL
initialisers from the appropriate structure declarations.

Bug 4991705

Change-Id: I2ddb99a316aa0124e9a4c1850ba1ea87d16abcbc
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261689
(cherry picked from commit c3d634abe95c557551311acfbad602cd8824b4dc)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263393
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Yi-Wei Wang <yiweiw@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-12-04 09:40:25 -08:00
Jon Hunter
814fdf0d88 cpuidle: Fix build for Linux v6.13
Commit ef4c675dc296 ("genirq: Unexport nr_irqs") unexported 'nr_irqs' in
Linux v6.13 and this breaks the build for the cpuidle-debugfs driver.
For Linux v6.13 the number of IRQs can be queried by using the function
irq_get_nr_irqs() instead. Fix the build by using conftest to detect if
the function irq_get_nr_irqs() and use this function if it is present.

Bug 4991705

Change-Id: I98d477896fcf9e8d2e1afa21e2f7ba4d071ab442
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261690
(cherry picked from commit 3fd3699807afd1503c72e1d2a1610ef0e4862197)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3499748
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-12-04 09:40:19 -08:00
Jerry Chang
ac523e2cad media: i2c: imx477: remove 4-lane config
Raspberry PI HQ IMX477 only has 2-lanes for camera
cable and connector design, 4-lanes will never work

Bug 5331483

Change-Id: I419bb6a4ba2778e1a4b73d1749ec1da263bd3101
Signed-off-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3490068
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
2025-12-04 05:54:31 -08:00
yunzhao
9dc6ab65c2 vi5:fix channel status inconsistency
set chan->is_streaming status to vi5_channel_stop_streaming to prevent
an error when restarting streaming next time after a failure.

Bug 5318702

Change-Id: I129811f932e8fb99c60d82f4cb1846adb87e1b34
Signed-off-by: yunzhao <yunzhao@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3500460
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Jackie Chen <jackchen@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
2025-12-01 23:24:00 -08:00
Shubhi Garg
e4ded64e88 oot: fix mutex unlocking in vrs rtc
Kernel throws a dump trace upon setting wakealarm time on VRS RTC.
We are unlocking mutex twice in a single API call. Delete one instance
which is not required.

[  590.301592] Call trace:
[  590.304035]  __mutex_unlock_slowpath.isra.0+0x1d4/0x2d0
[  590.309274]  mutex_unlock+0x60/0x80
[  590.312766]  0xffff80007ce0e6ec
[  590.315909]  __rtc_set_alarm+0x100/0x200
[  590.319751]  rtc_timer_enqueue+0x168/0x2e8
[  590.331275]  dev_attr_store+0x20/0x601e8
[  590.335117]  sysfs_kf_write+0x4c/0x88
[  590.338609]  kernfs_fop_write_iter+0x144/0x1d8
[  590.343149]  vfs_write+0x254/0x398
[  590.353626]  invoke_syscall+0x50/0x14040
[  590.357468]  el0_svc_common.constprop.0+0x48/0x100
[  590.362357]  do_el0_svc+0x24/0x40
[  590.365501]  el0_svc+0x34/0xc8
[  590.372835]  el0t_64_sync+0x194/0x19830/0x140
[  590.376679] ---[ end trace 0000000000000000 ]---

Bug 4715238

Change-Id: I7e070772c81474eb22859f2a00934211e6dad834
Signed-off-by: Shubhi Garg <shgarg@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3258911
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3502098
2025-12-01 05:38:59 -08:00
Wayne Wang(SW-TEGRA)
2f7421c40b nvethernet: add mutex lock for osi mdio
There is chance to hit race condition when doing mdio read/write from
different application.

This would lead to PHY not work properly intermittently.

Bug 5211090

Change-Id: I62afbc1d206fd4cf02a0b58036e8d38ca84968ac
Signed-off-by: Wayne Wang(SW-TEGRA) <waywang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/3453343
(cherry picked from commit 1442bbd24a8fe0423fc67b5b004b2a07d604c109)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3477850
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
2025-11-25 20:09:00 -08:00
Ankur Pawar
1d659b240c Camera: fix kernel warning after VI timeout
VI return timeout status when no frames are
received from camera sensor. During the error
recovery, the v4l2 buffers are set to
VB2_BUF_STATE_ERROR, this causes kernel warning.
As per the v4l2 framework correct buffer state
for timeout is VB2_BUF_STATE_QUEUED.

Bug 5512645

Change-Id: Iafc720b1ba74f04490d7d14e2e9014bd599b3cba
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3462547
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-10-07 05:53:55 -07:00
Jon Hunter
d6685995db video: tegra: nvmap: Fix build for Linux v5.17+
Building NVMAP is failing for Linux v5.17, v5.18 and v5.19 and the
following error is observed ...

 drivers/video/tegra/nvmap/nvmap_alloc.c: In function
  ‘handle_page_alloc’:
 drivers/video/tegra/nvmap/nvmap_alloc.c:521:14:
  error: implicit declaration of function ‘mmget_not_zero’; did you mean
  ‘min_not_zero’? [-Werror=implicit-function-declaration]
    521 |         if (!mmget_not_zero(mm))
        |              ^~~~~~~~~~~~~~
        |              min_not_zero

The function 'mmget_not_zero' is present in these kernels and for all
kernels is defined in the header file 'include/linux/sched/mm.h'. Ensure
that this header is included by the NVMAP driver to fix the build.

Bug 5222690

Change-Id: I98dcac3bb19d37bc0f5e9bd85d49a8cfe0923061
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3454945
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ashish Mhetre <amhetre@nvidia.com>
2025-09-22 02:53:55 -07:00
Ketan Patil
1c59063ce7 video: tegra: nvmap: Avoid double updation of RSS counter
The RSS counter is updated during buffer allocation as well as mmap,
which is leading to double updation. Fix this by decrementing the RSS
counter during page fault while increment it back during unmap flow.

Bug 5222690

Change-Id: I77972185f20d9d710571cc07ae1c5188060bfa1f
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3442670
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: Ajay Nandakumar Mannargudi <anandakumarm@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-09-16 15:54:39 -07:00
Ketan Patil
8e1a6b2dd1 video: tegra: nvmap: Remove use of add_mm_counter
add_mm_counter is not an exported function, so instead use
atomic_long_add_return/percpu_counter_add to directly modify RSS stat
counters.

Bug 5222690

Change-Id: I51a68d932aeb04f96e51a4a3c286ee5c8efc789a
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3446982
Reviewed-by: Ajay Nandakumar Mannargudi <anandakumarm@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-09-16 15:54:33 -07:00
Jon Hunter
69f69d9b7f i2c: tegra-slave: Fix build for Linux v6.11
In Linux v6.11, the 'platform_driver' structure 'remove' callback was
updated to return void instead of 'int'. Update the Tegra I2C Slave
driver accordingly to fix the build for Linux v6.11+ kernels.

Bug 4749580
Bug 5440303

Change-Id: Ic1d7d9b320e324b4847011af625e7e8e3f88d28a
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3440226
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-08-27 06:08:57 -07:00
Ketan Patil
2ca91098aa video: tegra: nvmap: Account NvMap memory for OOM Decisions
Account NvMap allocated memory into both RSS and CG tracking to make
efficient OOM kill decisions during memory pressure.

NvMap allocates memory via kernel APIs like alloc_pages, the kernel
memory is not accounted on behalf of process who requests the
allocation. Hence in case OOM, the OOM killer never kills the process
who has allocated memory via NvMap even though this process might be
holding most of the memory.

Solve this issue using following approach:
- Use __GFP_ACCOUNT and __GFP_NORETRY flag
-  __GFP_NORETRY will not let the current allocation flow to go into OOM
path, so that it will never trigger OOM.
- __GFP_ACCOUNT causes the allocation to be accounted to kmemcg. So any
allocation done by NvMap will be definitely accounted to kmemcg and
cgroups can be used to define memory limits.
- Add RSS counting for the process which allocates by NvMap, so that OOM
score for that process will get updated and OOM killer can pick this
process based upon the OOM score.
- Every process that has a reference to NvMap Handle would have the
memory size accounted into its RSS. On releasing the reference to
handle, the RSS would be reduced.

Bug 5222690

Change-Id: I3fa9b76ec9fc8d7f805111cb96e11e2ab1db42ce
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3427871
Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-08-22 04:09:39 -07:00
Chenjian
a196aadaf7 mfd: clear interrupt status in probe
VRS RTC may assert interrupt if battery mounted. Clear the status
registers before interrupt enabled to prevent bad logic.

Bug 3910065
Bug 3742306

Change-Id: I02dc6ce9352b1f1932cc539e6988375da4098014
Signed-off-by: Chenjian <jackchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2833620
(cherry picked from commit a50dd0a752641a30d84a5edfed426a12f2641acc)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2839704
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3418233
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: Shubhi Garg <shgarg@nvidia.com>
Tested-by: Kevin Fu <chunhuaif@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-08-13 22:53:57 -07:00
Akhil R
858da4d574 i2c: tegra-slave: Add I2C Tegra slave driver
Add back the removed i2c-tegra-slave-byte driver and add support
for it in kernel v6.1

Though not enabled in device tree by default, I2C slave driver is
used by customers and developers for various debug and application
use cases.

Bug 4288065
Bug 4061232
Bug 5440303

Change-Id: Idd012303f51456492a8392e51aee1edc8dcb487c
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3048842
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
(cherry picked from commit 75ea3b11d0)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3351662
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-08-08 04:54:36 -07:00
Shubham Chandra
b36ca8daa3 media: camera: modify error log to info log
v4l2-compliance has a negative test for image size,
resulting in an error log. Modify this error log to
info to avoid reporting kernel error/warning failure.

Bug 5143480

Change-Id: I5ec459f97c5b09e130293b59c19c1eb3ea9a53ee
Signed-off-by: Shubham Chandra <shubhamc@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3396425
(cherry picked from commit bac969836ec107b17489a782103517684691fddc)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3395179
(cherry picked from commit 97058881b98459a100562cc41a148d7e3240059b)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3415602
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Nithin Varghese <nvarghese@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
2025-07-24 22:38:54 -07:00
Jerry Chang
8d112b32e5 vi5: fix vi5_channel_error_recover memory leak
release chan->request_iova and also chan->emb_buf memory

Bug 5371485

Change-Id: I6e2642733a222a85b2f7d6814716835afc921948
Signed-off-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3397753
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2025-07-09 03:09:15 -07:00
snchen
6dcfde2bf7 vi5: reset capture_reqs_enqueued for stream on/off
Fix capture failed while repeatedly stop/starting streaming
by the VIDIOC_STREAMOFF/VIDIOC_STREAMON

bug 5262740

Change-Id: I1ab61497a1e8e2bfc83e62befc708d9be0662b82
Signed-off-by: snchen <snchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3356037
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-06-15 23:08:57 -07:00
Dara Ramesh
b4b7c24bfe adsp: cleanup legacy code
The legacy ADSP applications, such as file access and lpthread,
as well as the actmon driver, are no longer supported on T26x/T23x.

Bug 5174542

Change-Id: I3e70f11e0c09a7178f069c2423ad068dc765eea8
Signed-off-by: Dara Ramesh <dramesh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3359415
(cherry picked from commit 7522cb86599a2e9b1696dc3c6f878a421c7b84e9)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3382804
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-06-10 05:25:02 -07:00
Robert Lin
0652332c19 nvethernet: defer WOL enablement.
This change defers WOL enablement to the moment
before suspending so the network retains connected
after enabling WOL.

ethtool -s eth0 wol g

Bug 4450559

Change-Id: Ib5e59052fb72a9c4f88667ab6182633af545b99d
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3271298
Tested-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
2025-05-28 17:54:30 -07:00
Ashish Mhetre
e2b9c86688 platform: tegra: Check if MC channel is enabled
In MC-HWPM driver, check if MC channel is enabled before accessing its
registers.

Bug 5279654

Change-Id: I41e3d277a75d0a1045e47f148e2b9eb63f29b279
Signed-off-by: Ashish Mhetre <amhetre@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3369527
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
2025-05-26 00:53:54 -07:00
Jon Hunter
2f83033498 media: camera: Use conftest for CSI2 config
In Linux v5.18, commits 20c238dfb26c ("media: v4l2-mediabus: Drop legacy
V4L2_MBUS_CSI2_*_LANE flags"), 5a6ac3f4b46f ("media: v4l2-mediabus: Drop
legacy V4L2_MBUS_CSI2_CHANNEL_* flags") and b9f7caa7753a ("media:
v4l2-mediabus: Drop V4L2_MBUS_CSI2_CONTINUOUS_CLOCK flag") removed
various CSI2 flags. It turns out that out of these flags we only need to
actually set the number of lanes and the other flags are redundant. The
configuration was moved by commit 94d964e58ad6 ("media: v4l2-fwnode:
Move bus config structure to v4l2_mediabus.h") to the structure
v4l2_mbus_config_mipi_csi2 which itself is under the structure
v4l2_fwnode_endpoint. Use conftest to detect if the structure
v4l2_mbus_config_mipi_csi2 is present and avoid using kernel version
checks.

Bug 4425688

Change-Id: Icd597492e48831326c203a6556176ac3767472a3
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3354475
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
2025-05-02 08:54:03 -07:00
Laxman Dewangan
3713d89fdb prod: Add support for legacy and next-gen prod via config
Instead of using the Linux kernel version, use the
configs coming from core kernel to find out whether
legacy or next-gen prod configuration method is used.

This will help on porting changes on any kernel and
configuring via core kernel configs.

Bug 3389584

Change-Id: I19c242c573dd63c7dbecbf87d4ba807857dcf4fb
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3013911
(cherry picked from commit 1dd2ef3473)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3087161
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-04-16 12:09:22 -07:00
Laxman Dewangan
e748c978d5 prod: rename config TEGRA_PROD_ENABLE to TEGRA_PROD_LEGACY
To support the new method of the prod implementation,
rename the older config TEGRA_PROD_ENABLE to
TEGRA_PROD_LEGACY for differentating with new implementation.

Bug 3389584

Change-Id: I3ae0f3f32b4fdfa05ce352963cb0dcdbea489ec2
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3013910
(cherry picked from commit 3d64e97531)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3339973
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
2025-04-16 12:09:18 -07:00
Jon Hunter
3d806c0cd2 gpu/drm: tegra: Fix support for Linux v6.12
In Linux v6.12, commit 641bb4394f40 ("fs: move FMODE_UNSIGNED_OFFSET to
fop_flags") moves the setting of the FMODE_UNSIGNED_OFFSET into the
various drivers and renames this flag. This change is causing various
tests to fail because opening the DRM device is failing.

Use the presence of the new FOP_UNSIGNED_OFFSET flag in the kernel to
determine if we need to set this flag in the Tegra DRM driver.

Bug 4876974

Change-Id: Ie72a9340187b1c206f0cda6d7e3dab44d603a41c
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3269063
(cherry picked from commit a680b4881fb8e6ace46f409c33307f3bc10366a4)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3338872
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Tested-by: Ilies Chergui <ichergui@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ilies Chergui <ichergui@nvidia.com>
2025-04-11 14:08:53 -07:00
Ken Chang
785d9aa288 tegra-cec: poll WR_LOCK for TX data sync
After programming the TX Register, it takes 3-4 clock cycles for TX
data synchronization to the CEC core domain. The TX_EMPTY interrupt
should not be cleared until this data synchronization is complete.

Enable CEC HW feature to automatically clears the TX_EMPTY interrupt
after TX data synchronization is complete. It takes time for HW to
clear the interrupt and TX_EMPTY can still appear high, hence SW
needs to poll WR_LOCK until it goes to 0. This will avoid SW to
attempt the next TX block during the same TX_EMPTY interrupt.

Also read RX_REGISTER based on the buffer occupancy which is
indicated by the CEC_RX_BUFFER_STAT_0 register.

Bug 4954851

Change-Id: I3ec3792c9ae3b8a00c800c921cf4e4d09369e6b9
Signed-off-by: Ken Chang <kenc@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322519
(cherry picked from commit 94cf6106402dc833dbaa4305c3e1a8f85fd80d0e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3336992
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-04-11 06:40:40 -07:00
Jerry Chang
7bca2b2466 tegra: rtcpu: revise copyright
incorrect use of NVIDIA Properitary License in Linux driver code

Bug 5197152

Change-Id: Id23b8cbd4fd6315664c77d7f42014206d1ef8d5c
Signed-off-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3330623
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-04-01 12:23:51 -07:00
Thierry Reding
eca775e222 gpu: host1x: Set up device DMA parameters
In order to store device DMA parameters, the DMA framework depends on
the device's dma_parms field to point at a valid memory location. Add
backing storage for this in struct host1x_memory_context and point to
it.

Reported-by: Jonathan Hunter <jonathanh@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240916133320.368620-1-thierry.reding@gmail.com
(cherry picked from commit b4ad4ef374d66cc8df3188bb1ddb65bce5fc9e50)

Bug 4876974

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Change-Id: I0a7f9c9f49a5e4580193d5814ff4a6a15f8014c8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3268196
(cherry picked from commit 027ee6a9a0b3848fbaae21c788064f59072c0978)
Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3326864
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-03-26 09:24:38 -07:00
Paritosh Dixit
8e353eecd4 bluetooth: realtek: Add option to disable driver
The RealTek drivers do not build against all Linux distributions because
some Linux distributions have back-ported upstream changes and so the
KERNEL_VERSION checks in the driver do not work for these distributions.

Add compilation flags for these drivers so that we can skip the building
of these drivers for certain Linux distributions.

Bug 5180190

Change-Id: I48101b5b9e199c6887a2cbde916d7df5ae1c53a7
Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3325283
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-03-26 09:24:34 -07:00
Paritosh Dixit
f2f943a0d3 block: virt-storage: Add option to disable drivers
The tegra-virt-storage driver is currently not used for the L4T in the
rel-36 codeline. Add an option to disable building the driver. It
provides flexibility to disable the driver in case there are build
issues with 3rd-party distro kernels.

Bug 5180190

Change-Id: If58d8e782c564aa7b5229dc96093050c19882011
Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3323464
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
2025-03-26 09:24:30 -07:00
Laxman Dewangan
1e837fca66 camera: Use conftest to find if media_entity_remote_pad() present
Use conftest to determine if media_entity_remote_pad()
function is present or not

This function is removed by commit b2e44430b634 ("media:
mc-entity: Rename media_entity_remote_pad to media_pad_remote_pad_first")
in Linux 6.0

Bug 4387902

Change-Id: I816016731ac44a3c093438310f8e60bd166f2fd7
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3037917
(cherry picked from commit b40e45535e)
Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3322771
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-03-26 09:24:26 -07:00
Akhil R
4b72ba2c83 crypto: tegra: Do not use IV for AES ECB
It may happen that the variable req->iv may have stale values or
zero sized buffer by default and may end up getting used during
encryption/decryption. This in turn may corrupt the results or break
the operation. Ensure not use IV for algorithms like AES ECB where IV
is not expected.

Bug 4883011

Change-Id: I309ad26f99fe54005ff71b270b3b115dc62ac168
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3319062
Reviewed-by: svcacv <svcacv@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-03-19 12:24:33 -07:00
Akhil R
15d7ca57b1 crypto: tegra: Reserve keyslots to allocate dynamically
The HW supports only storing 15 keys at a time. This limits the number
of tfms that can work without failutes. Reserve keyslots to solve this
and use the reserved ones during the encryption/decryption operation.
This allow users to have the capability of hardware protected keys
and faster operations if there are limited number of tfms while not
halting the operation if there are more tfms.

Bug 4883011

Change-Id: I220f1e8205dde1f078be6ed4cb09b699b6d5dfa2
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263283
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-03-19 12:24:29 -07:00
Akhil R
2f3c077115 crypto: tegra: Use separate buffer setkey
Use a separate buffer for setkey operation. setkey() is called
asynchronous to crypto engine APIs. This causes concurrency issues in
the tegra engine oprations.

Bug 4883011

Change-Id: I1ec7d0a041ee8a0a0bf350d2f3e9915091993034
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3263282
Tested-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2025-03-19 12:24:25 -07:00
Brad Griffis
efeb1061bb Revert "crypto: tegra: Use separate buffer for each host1x command"
This reverts commit f6c3d49e92.

Reason for revert: Optimize implementation and align with upstream.

Bug 4883011

Change-Id: I32fe35daa30ddb5a272dbeee0c3316134e9ca55b
Signed-off-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3321697
Tested-by: Akhil R <akhilrajeev@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Akhil R <akhilrajeev@nvidia.com>
2025-03-19 12:24:21 -07:00
Jon Hunter
a2b53ade55 virt: hvc_sysfs: Fix build for Linux v6.13
In Linux v6.13, commit 94a20fb9af16 ("sysfs: treewide: constify
attribute callback of bin_attribute::mmap()") changed the type of the
'struct bin_attribute' argument of the bin_attribute:mmap function
pointer to const. Use conftest to detect if this argument is const or
not in the kernel the driver is being compiled against to fix the build.

Bug 4991705

Change-Id: I791d6c9dde50f1444d0339ebd8a18434045f9026
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261699
(cherry picked from commit fae042552e211199a160e5d6a82a67edd7b7e03c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3321698
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-03-19 10:23:57 -07:00
Jerry Chang
63a08013a0 capture-ivc: fix multi-cam race condition
add semaphore to avoid multi-cam race condition

Bug 4425972

Change-Id: I6e01ccb0596efed32ed53618ccf80c1e751b4f29
Signed-off-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3315501
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Shan Neng Chen <snchen@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Shan Neng Chen <snchen@nvidia.com>
2025-03-19 02:09:49 -07:00
Sushil Kumar Singh
dd71f62c3a nvethernet: disable HSI error reporting if EPL is disabled.
Issue:
During iperf test on pegasus board on customer observed below error periodically
nvethernet 6810000.ethernet: Failed to report error: reporter ID: 0x0, Error code: 0x1002, return: -19

Fix:
Disable HSI error reporting from hsi work queue function
for L4T platforms if safety component EPL is not supported.

Bug 4090612

Change-Id: Ifc51dd93fb16c1dbf7e42c648ca14443bb40550b
Signed-off-by: Sushil Kumar Singh <sushilkumars@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2931249
(cherry picked from commit 983ddcae450c36cde9ec79433e16a4ed5aa89319)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3313872
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Tested-by: Wayne Wang (SW-TEGRA) <waywang@nvidia.com>
2025-03-10 09:51:36 -07:00
spatki
598f951b93 tsec: add firmware desc path as module fw
During SC7 tsec driver is unable to find the desc file for the
tsec fw and thus tsec boot fails. This might result into system
hang. Hence this change adds the tsec fw desc file path as the
module firmware so that the firmware is available to it during
SC7.

Bug 5053273

Change-Id: I4f2c9bb5288dac6973f574159fdebc48009edf2a
Signed-off-by: spatki <spatki@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3308515
Reviewed-by: Nikesh Oswal <noswal@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-02-25 04:53:52 -08:00
Narayan Reddy
b03396851a nvethernet: move err injec code to vltest
issue: HSI error injection logic is enabled by default
and is exposed as an ioctl which is a safety-related concern.

fix: move HSI error injection code only for
VLTEST build

Jira NET-1235
Bug 4449611
Bug 4910958

Signed-off-by: Narayan Reddy <narayanr@nvidia.com>
Change-Id: I4a15a40807466693ce673a3b9b00f51c077f2bd8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3078250
(cherry picked from commit e01c63215d861b6de8f4a26596a4e5e9450878a3)
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3292992
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2025-02-07 00:24:31 -08:00
Sanath Kumar Gampa
00761e184e linux:nvidia: macsec sysfs nodes only if enabled
Issue: Accessing the macsec sysfs nodes is leading to crash when macsec
is disabled in DT

Fix: Do not create sysfs nodes if macsec is not enabled in DT. Also
update the instance_id reading as part of ether_probe which will be
executed even when macsec is disabled

Bug 4431523
Bug 4910958

Change-Id: I354ac142b9d49852a0d5c7557a7368e1c36b0f63
Signed-off-by: Sanath Kumar Gampa <sgampa@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/3043469
(cherry picked from commit acf3356b8e9cbd7c0f9e34a0ead3591e83f65b60)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/3081473
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3292924
Reviewed-by: Narayana Reddy P <narayanr@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2025-02-07 00:24:27 -08:00
Shobek Attupurath
d641168e9e rtl8852ce: Add Nvidia changes to driver v126
- Update paths for sourcetree
- Reduce log level
- Update roam parameters

Bug 5023692
Bug 4957055

Change-Id: I9b6eed09790bc94d6976d4d680a2aa080085130a
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3284274
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
2025-01-29 09:54:54 -08:00
Shobek Attupurath
88c9f54b6f rtl8852ce: Update driver to version v1.19.16_nv-126
Update driver version to v1.19.16_nv-126-g455ab52c9.20241107_Certified_Module
to enable roaming and fix issues with roaming

Bug 5023692
Bug 4957055

Change-Id: I7d021f599c6483e15828a564a016e4037b238c90
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3284273
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-01-29 09:54:49 -08:00
Jon Hunter
f82cb5bdc8 Revert "tty: wch: update copyright headers"
This reverts commit a9ae1a62f2.

Reason for revert: Modifies original copyright and license

Change-Id: I08cfac80a758229a43cec4c22c110af1581656a2
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3291558
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2025-01-27 10:08:50 -08:00
Ankit patel
a9ae1a62f2 tty: wch: update copyright headers
Update copyright header to GPLv2, removed proprietary copyright headers

Bug 5065840

Change-Id: Ib0b8be01f3c0a4fc963244d7b49489960420dc27
Signed-off-by: Ankit patel <anpatel@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3289171
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-01-23 05:23:59 -08:00
Revanth Kumar Uppala
a736931748 R8168: Configure Root Port MPS and MRRS in r8168 driver
This patch ensures that the Maximum Payload Size (MPS) and Maximum Read Request Size (MRRS) settings of the root port associated with r8168 ethernet endpoint are properly configured after overwritten by kernel when pcie_bus_perf is enabled.

Bug 4607316

Change-Id: I7f7b83f74e4ac2104345bd568d9d2e7c03a1441e
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3273562
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
(cherry picked from commit 6c00bf9297134760f10974383ae4169589e16fa6)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3285723
2025-01-19 20:23:53 -08:00
Manish Bhardwaj
a08c7112e7 ivc: fix ivc driver issue for noble kernel
Bug 4377196

Change-Id: I4acc2d4e419f0ee95be760910f27da592369875c
Signed-off-by: Manish Bhardwaj <mbhardwaj@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3026287
(cherry picked from commit 54e431bcc9)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3283409
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Paritosh Dixit <paritoshd@nvidia.com>
2025-01-15 06:08:50 -08:00
Ankur Pawar
3ff44d5400 media: i2c: IMX390: modify mode table
-Add gain, exposure and short exposure functions.
-Modify WDR and SDR mode table as per the settings
 provided by Sony in their camera SDK.
-Analog gain is fixed in mode table. Driver will only
 update digital gain.

Bug 4774547

Change-Id: Ia04f42062d6f1e56f16c7fbcc6e671529cb714b6
Signed-off-by: Ankur Pawar <ankurp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3189759
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shubham Chandra <shubhamc@nvidia.com>
2025-01-14 12:09:33 -08:00
Jon Hunter
74c0a6d16d drivers: Drop inline from driver remove wrapper
The driver remove function is a function pointer and therefore, it does
not make sense to define the function as an 'inline'. Update the
coccinelle script and drivers to remove the inline statement.

Bug 4749580

Change-Id: Ia03691b75c4edffe609f27468b911a92a5ddbd68
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3233980
(cherry picked from commit 2c3a31c9b72785ee35ad079422b624f59a35f622)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3276870
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-01-06 06:09:10 -08:00
Jon Hunter
66afcf9c40 misc: tegra-cec: Fix build for Linux v6.11+
In Linux v6.11, the 'platform_driver' structure 'remove' callback was
updated to return void instead of 'int'. Update the Tegra CEC driver
as necessary to fix this.

Bug 4749580

Change-Id: I3cd34f41e519240ff48378e79bb654cf78767085
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3276923
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2025-01-03 11:23:59 -08:00
Prafull Suryawanshi
0cac4c3b02 tegra-cec: remove pre-t23x support.
This change removes pre-t23x support and removing
dependency on tegra-dc module for tegra-cec driver.

Verification:
Verified on orin-slt with basic cec tx-rx data with TV.

bug 4954851

Change-Id: Ie820ba706ac5e66da282e411a4ae74bd0e6cb58b
Signed-off-by: Prafull Suryawanshi <prafulls@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3264311
Reviewed-by: Shu Zhong <shuz@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Vinod Atyam <vatyam@nvidia.com>
2024-12-22 21:39:26 -08:00
Gerrit Code Review
b55e16ed87 Merge "tegra-cec: Merge remote-tracking branch 'origin/dev/dev-cec-2' into HEAD" into rel-36 2024-12-22 21:39:22 -08:00
Prafull Suryawanshi
79045f2dc7 tegra-cec: Merge remote-tracking branch 'origin/dev/dev-cec-2' into HEAD
This merge imports tegra-cec driver from linux-nvidia repo to nvidia-oot repo
with maintaining git history of tegra-cec from start.

bug 4954851

Change-Id: Icb8d066df5eeaa083a70a7f6657caf1c1593ec17
Signed-off-by: Prafull Suryawanshi <prafulls@nvidia.com>
2024-12-20 03:58:24 +00:00
Prateek Patel
6d4080d2bb drivers: cec: fix cert_c defect
Add a sanity check on cec->soc, which could be NULL.

CID 490328

Bug 3512545

Change-Id: Ibd334c5637a85342ed5307eecb697416f32e0360
Signed-off-by: Prateek Patel <prpatel@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2710156
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
GVS: Gerrit_Virtual_Submit
2024-12-20 03:54:00 +00:00
prafulls
3e3bd3b5f0 misc: tegra-cec: replace dev_err with dev_info.
The probe retry message shall not be error message.
Replacing it with dev_info to fix kernel warning test.

bug 3578262

Change-Id: I8fd016e11b6edc14a402214a44c1e916bcc0d16e
Signed-off-by: prafulls <prafulls@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2685084
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Shu Zhong <shuz@nvidia.com>
GVS: Gerrit_Virtual_Submit
2024-12-20 03:54:00 +00:00
Prafull Suryawanshi
bcd8f08d84 misc: tegra-cec: add T23x support.
This change includes below -
1. For T23x, CEC engine is moved to AON partition. As AON partition
   does not powergate, skip all powergate/unpowergate calls for t23x.
2. The clock on which CEC engine operates, 32k/rtc_clk, it is always
   running clock in AON partition. So skip clock enable/disable APIs.
3. This change also skips calls to TEGRA DC engine which is not available
   from T23x.
4. RX Buffer size is increased to 64 depth from 1 depth. So new register is
   provided to program depth so that interrupt gets triggered when certain
   depth is filled. By default it is 64 depth so program it to 1 depth
   to match old behavior.
5. When tegradc is absent, read physical address from SPARE register which
   will be populated by UEFI.
6. This change also adds new register definitions in header file which
   needs to program when adding support for CEC SC7 wakeup.
7. Timing registers updated for T23x as per HW guidelines.
8. Some initialization code is changed for T23x.
9. Add devicetree binding documentation.

bug 200727002

Change-Id: I71c2d323632c61e4c4b82bcdbca9e72179761224
Signed-off-by: Prafull Suryawanshi <prafulls@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2523595
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Shu Zhong <shuz@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2024-12-20 03:54:00 +00:00
Ankit Patel
61e8cccc41 drivers: use overlay instead of relative path
Modified misc/tegra-cec and video/tegra/dc NVIDIA git repo Makefile, Now
overlay macro will be used instead of relative path from kernel source
tree, to find the included header file.

Bug 200606454

Signed-off-by: Ankit Patel <anpatel@nvidia.com>
Change-Id: I684388e9c81be94915c05db3cdae8b6100c6db91
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2521240
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Naveen Kumar S
9152cfd9e9 video: tegra: dc: add pm_runtime support
Add genpd/pm_runtime support to handle power domains
in Tegra Display driver. Also updated CEC and HDA_DC
drivers to add pm_runtime calls.

Added new APIs in CEC and SOR drivers to abstract
calls to pm_runtime and tegra_powergate APIs based
on specific Kernel version. Guarded powergate_id
with CONFIG_TEGRA_POWERGATE since its not needed
when pm_runtime APIs are used, and the powergate IDs
are defined in tegra_powergate.h which is not used
in K5.9.

Removed pm_runtime autosuspend setting since display
driver doesn't assign PM suspend/resume hooks at
present. Suspend/resume calls are linked to platform
device callbacks.

Removed pm_runtime_enable() call in dc_common probe
since there's logically no need of power-domains
in dc_common and also there is no power-domains node
in display_hub node in device-tree. Same with DSI.

All the power-domains handled by each DC are listed
in "power-domains" and "power-domain-names" properties
under respective dc nodes in device tree.

bug 200601926

Change-Id: I0fc9d21ff56185a69de6e0663b5932a93cf40e2b
Signed-off-by: Naveen Kumar S <nkumars@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2358953
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Shu Zhong <shuz@nvidia.com>
Reviewed-by: Ujwal Patel <ujwalp@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2024-12-20 03:54:00 +00:00
Naveen Kumar S
b55afecfc2 misc: tegra-cec: fix access_ok() API's parameters
This change fixes below follow-up issues with the earlier fix
to access_ok() API done as part of
https://git-master.nvidia.com/r/c/linux-nvidia/+/2361042:

1. Definition of VERIFY_READ and VERIFY_WRITE have been removed
after K4.14. Hence, used them only for kernel versions < K5.4.
2. Changed access_type parameter of tegra_cec_access_ok() API
to bool. WRITE or READ will be chosen based on the bool value.
3. In the last CL, VERIFY_WRITE was changed to VERIFY_READ in
two access_ok() calls by mistake. Corrected them in this CL.
4. Defined access_type variable with attribute __maybe_unused
since gcc doesn't seem to consider a variable as used if only
passed as function parameter.

bug 200601926

Change-Id: I9f3540cd028280ca679b4b69d5b4a72aa943b2ae
Signed-off-by: Naveen Kumar S <nkumars@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2394585
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Shu Zhong <shuz@nvidia.com>
Reviewed-by: Ujwal Patel <ujwalp@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
2024-12-20 03:54:00 +00:00
Naveen Kumar S
80d0f3b9fa misc: tegra-cec: update access_ok() parameters
Starting K5.9, the access type parameter (read/write) of
access_ok() API has been removed. And also, the address
parameter has been updated to "void *" type from "unsigned
long". Introduced API tegra_access_ok() to abstract the
difference in parameters across different kernel versions.

bug 200601926

Change-Id: I0d72e03f5e0c56eb935107eaf306bc2d68ed13e3
Signed-off-by: Naveen Kumar S <nkumars@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2361042
Reviewed-by: Shu Zhong <shuz@nvidia.com>
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Arun Swain <arswain@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
GVS: Gerrit_Virtual_Submit
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Bitan Biswas
b36167f31c nvidia: drivers: fix linux-5.7-rc5 build
Fix build linux-5.7-rc5 errors including following:
	- change timespec to timespec64. replace getnstimeofday
	  with ktime_get_ts64
	- replace usage of macro FIELD_SIZEOF with sizeof_field in ethtool.c
	  nvethernet and eqos files.
	- support 2 arguments for of_get_phy_mode call

bug 200617764

Change-Id: I46067d7d36d08ee9556b2722e9ccec707b8853d4
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2347244
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Ankit Patel
3c80738a18 headers : move/modified header for User-space ABI
copied/moved/modified headers from the driver directory to the
include/uapi directory, which have IOCTL components required to
get access from user space as per Linux kernel user-space ABI.

Bug 2062672

Signed-off-by: Ankit Patel <anpatel@nvidia.com>
Change-Id: Ie70b2839e0a1031a685ff3e4bb93c73741645f44
(cherry picked from commit 348c5ff55d7499222f154aea9e9893e6cfa677ce)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2318682
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Nicolin Chen
4625e85131 media: tegra: Remove temp WAR for function calls
There are two type of temp WARs in the nvidia repo:
1) Some functions are defined in driver files that depend on
   CONFIG_TEGRA_GRHOST_NVCSI. So these function call should
   have dependency protection in the header file.

2) The powergate header file is adding an unnecessary define
   check for tegra194-powergate.h and this broke two places
   that were referring one of the defines in it.

So this change fix the WARs above by:
a) Removing those temp WARs by adding dummy NOP functions for
   those platofrms that don't have CONFIG_TEGRA_GRHOST_NVCSI.
b) Removing the define check in tegra194-powergate.h and the
   version check when referring TEGRA194_POWER_DOMAIN_DISP.

Bug 2284925

Change-Id: Iad86bfe20f2981b3d31bccf5f51184799fe7e289
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1803439
GVS: Gerrit_Virtual_Submit
Reviewed-by: David Bang <dbang@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Chun Xu
9ff4833af1 tegra-cec: add interface to get post_recovery
Provide IOCTL interface for usersapce to get whether current boot is from
booting from recovery.

Bug 200394215

Change-Id: I45f492b766a75542ff470366001f92fa2fd65d23
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1780659
(cherry picked from commit 8a4bda6d7e0904ce9c0cafabac4aefb49e879b8b)
Reviewed-on: https://git-master.nvidia.com/r/1792946
GVS: Gerrit_Virtual_Submit
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Chun Xu
cf3a533906 tegra_cec: suppport dump registers and snoop mode
Provide dump registers and changingRX snoop mode interface.

Bug 200382184

Change-Id: Idb55d22112bc6be9de89b8ff8e060e73de469507
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1765068
(cherry picked from commit 3310df0f117d792d3d0bfab6326592851faaeed7)
Reviewed-on: https://git-master.nvidia.com/r/1641846
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Chun Xu
23461a3851 CEC: add timeout and recovery in CEC frame sending
To avoid hang on CEC frame sending, introduce timeout and recovery.

Bug 2151251

Change-Id: Ia7c87ee874734c3ed976f3a9142ecc7e2509ec43
Reviewed-on: https://git-master.nvidia.com/r/1741606
(cherry picked from commit e0010f8fb4443cc146a84d76b8666ee831010f56)
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1764220
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Aly Hirani
4ca144139b misc: tegra_cec: fixing return values for wait
This change fixes the code that was checking the return value for
the wait_event_interruptible_timeout.

Change-Id: Ief6c180f1df9994dd6caa776e08cdb26e15bb32b
Signed-off-by: Aly Hirani <ahirani@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1742938
(cherry picked from commit 8e4b55aa0571a10acf106d21f7c70b2d8b8108c6)
Reviewed-on: https://git-master.nvidia.com/r/1746696
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Aly Hirani
0e3c13c2f1 misc: tegra_cec: Add timeout for wait_event
Bug 2151251

Change-Id: I75d16b33d1596242c28d693f824a51d72934a5c3
Signed-off-by: Aly Hirani <ahirani@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1742040
(cherry picked from commit c94751ec8838dd9edd5b2dafd5c308ecefe6a8b3)
Reviewed-on: https://git-master.nvidia.com/r/1746695
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Ishwarya Balaji Gururajan
80169e7ded misc: tegra-cec: remove NVDISPLAY ifdefs
remove NVDISPLAY ifdefs and replace it with runtime APIs

Jira TDS-2761

Change-Id: I920fe5402a91d1780b07aadf542cc15361f73398
Signed-off-by: Ishwarya Balaji Gururajan <igururajan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1653842
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Chun Xu
a89f31f800 misc: tegra-cec: add T194 CEC device
Bug 2039509
Bug 200375853

Change-Id: Iebe1956a94cbf0209b11ad8c66d8fc5b7335549a
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1641039
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
Reviewed-by: Naveen Kumar S <nkumars@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Mitch Luban <mluban@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
2024-12-20 03:54:00 +00:00
Ishan Mittal
a550d6f899 drivers: Fix references to nvidia/
drivers inside platform tegra and nvdisp
point to display repo.
changing that to nvidia/

Bug 200295104

Change-Id: I91e0356555c251df3eae98218a69f4bc7e3cd208
Signed-off-by: Ishan Mittal <imittal@nvidia.com>
2024-12-20 03:54:00 +00:00
Chun Xu
74524fa09b misc: tegra-cec: dump read/write buffer for debug
Dump read/write buffer with dev_dbg for debug.

TDS-2199

Change-Id: I1fa3dec9e2ccd78023c464085fd2f6e3f49a87f2
Signed-off-by: Chun Xu <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1485394
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Prafull Suryawanshi <prafulls@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Spencer Sutterlin <ssutterlin@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
2024-12-20 03:54:00 +00:00
Nicolin Chen
f79ab92d84 misc: tegra_cec: add missing cancel_work_sync()
This patch just adds missing cancel_work_sync()
in the exit path of the probe().

Bug 1887171
Bug 200289389

Change-Id: I7d42ae6d035f87b5ad1b726cbe5274fbd9755f4e
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-on: http://git-master/r/1463243
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sachin Nikam <snikam@nvidia.com>
2024-12-20 03:54:00 +00:00
Vince Hsu
5845f087dd misc: tegra_cec: turn some prints into debug level
To prevent too many bufferred message from flushing out to serial when
we turn on/off display and blocking other high priority task due to
disabled IRQ, we change some prints to debug level to workaround that
problem as a short-term solution. The long-term will be implemented
later.

bug 200205349

Change-Id: I6609844d5c2ee58b2df6a51e9537bb7dd1448995
Signed-off-by: Vince Hsu <vinceh@nvidia.com>
Reviewed-on: http://git-master/r/1326683
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Chun Xu <chunx@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com>
2024-12-20 03:54:00 +00:00
Santosh Reddy Galma
482bd11f32 misc: tegra-cec: fix power domains API for cec
use generic APIs tegra_unpowergate_partition() and
tegra_powergate_partition() to unpowergate DISP power
domain needed for CEC without enabling disp clocks so
that display pll clocks are disabled in idle state even
though DISP partition is awake.

Bug 1810989

Change-Id: I37428b9012729a4458724314732f80a571057fd6
Signed-off-by: Santosh Reddy Galma <galmar@nvidia.com>
Reviewed-on: http://git-master/r/1317241
(cherry picked from commit dffb3d3b5fb67cb6920fdbfc72cd3d6c37f0061c)
2024-12-20 03:54:00 +00:00
Chun XU
4f6189525b misc: tegra_cec: add recover IOCTL
Provide error recovery from IOCTL to user space.

Bug 1866338

Change-Id: I705ada6c8d4cb13f1c882993468f467da2908fdf
Signed-off-by: Chun XU <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1300499
(cherry picked from commit a646f4903c8794641432fa838a27ee5584944eb5)
2024-12-20 03:54:00 +00:00
Chun XU
c061b057db misc: tegra_cec: turn on TV ASAP
Turn on the TV as soon as possible for better user experience
by sending <Text View On> and <ACTIVE SOURCE> CEC commands if
the previous reboot is not recovery. If the previous reboot
reason is recovery, don't send <Text View On> to avoid turning
on TV when there is an auto OTA on-going.

CEC driver uses RESERVED2 logical address as the source address.
Later, the upper layer will send OneTouchPlay command by using
its valid logical address.

Bug 200253563

Change-Id: Iecd759bb50c1f21549f55906e68e3faab905f86b
Signed-off-by: Chun XU <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1277092
(cherry picked from commit 2beab2dcfc4e40712004500df99633d59ae0e70c)
2024-12-20 03:54:00 +00:00
Mikko Perttunen
0a6fb5c3c9 misc: tegra-cec: Use per-chip powergate IDs
Powergate identifiers are different on Tegra210 and Tegra186,
so add per-SoC match data to use the correct value on each
SoC.

bug 200257351

Change-Id: I81b938386ab9cbaec735baac44ee74fccf39731c
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/1297136
(cherry picked from commit 5438b348e036c31dcf9db0d1364fa6c6ac053428)
2024-12-20 03:54:00 +00:00
Spencer Sutterlin
9807746899 misc: tegra_cec: fix cec_logical_addr_store print
Bug 1637415

Change-Id: Ib165165b67f5ea3723914270215de06df48f6591
Signed-off-by: Spencer Sutterlin <ssutterlin@nvidia.com>
Reviewed-on: http://git-master/r/679245
(cherry picked from commit e9eef85a417a85461d0e7c018fcec2f2838254c2)
2024-12-20 03:54:00 +00:00
Chun XU
5203c51530 misc: tegra-cec: add /sys/devices/platform symlink
Create a symlink for tegra_cec if it is not under platform bus or
it has been created with different name.

Bug 200214224
Bug 200185815
Bug 1764073

Change-Id: Ib2f89db016982ca916894c37e47bbdf177fb617e
Signed-off-by: Chun XU <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1175137
(cherry picked from commit 506e6370d234c4770afb22372ef1955faa7822cf)
2024-12-20 03:54:00 +00:00
Chun XU
293e6c6256 misc: tegra-cec: tegra_nvdisp_powergate_partition
Use tegra_nvdisp_unpowergate_partition/tegra_nvdisp_powergate_partition
in Tegra CEC driver to control DISA power domain.

Bug 200214236
Bug 200214232
Bug 200185815

Change-Id: Ib860570f901278e9211b5262fddf8c63a700c5f9
Signed-off-by: Chun XU <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1176912
(cherry picked from commit 8e9f75ac1dadf04a8f89a74dac3e67cd1a06f886)
2024-12-20 03:54:00 +00:00
Ankit Pashiney
912ff2686c misc: Tegra CEC Support
Bug 1258710

Change-Id: Ie449d4b8a28388087b601a0332eb065488a32009
Signed-off-by: Ankit Pashiney <apashiney@nvidia.com>
Reviewed-on: http://git-master/r/215363
(cherry picked from commit e156fdeb84a7f750b602c746489538f5b29837cd)
Reviewed-on: http://git-master/r/1164171
(cherry picked from commit 64c30ff47c90f4dbf659570e9aaeea1270b9f756)
2024-12-20 03:54:00 +00:00
Chun XU
290c0854e2 misc: tegra-cec: enable DISA temporarily in init
Unpowergate DISA power domain if it is powergated during CEC driver initialization.

Bug 200175747

Change-Id: I8b3d879fe0c33eaef74c1b4d3b549559c4977e4d
Signed-off-by: Chun XU <chunx@nvidia.com>
Reviewed-on: http://git-master/r/1142593
Reviewed-on: http://git-master/r/1164149
(cherry picked from commit c341176715597fe8268b20b291bcef07bb429500)
2024-12-20 03:54:00 +00:00
Mitch Luban
ec2330c577 drivers: cec: add T186 support for cec
Bug 200148417

Change-Id: I4a57303097c0687c903f284504df10930924f1ae
Signed-off-by: Mitch Luban <mluban@nvidia.com>
Reviewed-on: http://git-master/r/840657
Reviewed-on: http://git-master/r/1164148
(cherry picked from commit be0d9f8be8a19525c2e4794d08f0932bc53128ee)
2024-12-20 03:54:00 +00:00
Xia Yang
42e7733cc7 misc: tegra-cec: Short-circuit init on suspend
Bug 1591149

Initialization of cec engine is slow.
Short-circuit the init in event of suspend.

Change-Id: Ibfbd6f36883a7bf45fdb5137120b041a52f42086
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/714423
(cherry picked from commit d5f4a6602678c87e8caa5032e43f2415c314d800)
Reviewed-on: http://git-master/r/716496
Reviewed-on: http://git-master/r/1164147
(cherry picked from commit 82a640a1ea11e850f769b78b5d0c531731b1ffd8)
2024-12-20 03:54:00 +00:00
Toby Butzon
2c5db18fa0 misc: tegra_cec: enable input filtering
Bug 1605426

Change-Id: I7fdfd3eee37f91f016fcbfe573d761f551560dde
Signed-off-by: Toby Butzon <tbutzon@nvidia.com>
Reviewed-on: http://git-master/r/682207
(cherry picked from commit fb8396c2f5cc02e72dae45d9421d17565b607921)
Reviewed-on: http://git-master/r/708747
(cherry picked from commit 1c18321a0e97b6fd2568b418ea353f6716b5a2e4)
2024-12-20 03:54:00 +00:00
Spencer Sutterlin
43ca60174f misc: tegra_cec: fix sparse warning
Fix sparse warning by adding static keyword to functions

Bug 200032218

Change-Id: I0fe65173eb0295f5b981fa44f381683efe9a980b
Signed-off-by: Spencer Sutterlin <ssutterlin@nvidia.com>
Reviewed-on: http://git-master/r/592290
Reviewed-on: http://git-master/r/1164145
(cherry picked from commit 74cfb080d07bc8e5758dfb83c4ce7507f16e4c9a)
2024-12-20 03:54:00 +00:00
Xia Yang
6432b7db50 misc: tegra_cec: add DT matching entry
Auxdata still have to be provided in of_platform_populate()
during early boot device detection to get the device correctly
named as "tegra_cec".  Failing to do so will result in device
probe failure as of_device_make_bus_id() will name the device
as "[phys_base].tegra_cec" and cause clock assignment failure.

Bug 200013561

Change-Id: Ib0f898f89146cba7f02cffb768c6a2eb558400ce
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/433871
Reviewed-on: http://git-master/r/1164144
(cherry picked from commit 43402b18ee6def21d7d55420f5acd22403e86f1d)
2024-12-20 03:54:00 +00:00
Xia Yang
4026c9868c tegra: cec: Driver rework
Change write() to work per frame.
Change write() to return -1 on error and set up errno

write() API:
-Userspace is responsible for re-transmission.
-Read from user-space byte by byte, each byte representing
 a block, up to 16 bytes as specified by HDMI standard.
-Return 0 on success transmission, -1 otherwise, with errno
 setup as follows:
  EIO - TX_REGISTER_UNDERRUN, should not happen, otherwise
      driver is have serious timing issue.
  ECOMM - BUS arbitration failure or anomaly BUS activity.
      Transmission is abandoned.
  ECONNRESET - For broadcast message only, someone on the BUS
      asserted NAK during transmission.
  EHOSTUNREACH - For direct message only, message was not ACK'd.
      (Required by logical address allocation)
  EMSGSIZE - Message size > 16 bit.
  EFAULT - Page fault accessing message buffer.
  EINTR - call interrupted by singal.

read() API is unchanged, works per packet with no error report.

Change-Id: Iabdd92b5658dd63c7b500a7ec88d79a64c8c0a43
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/304664
(cherry picked from commit 6ab7a446c4a3e8e4970ceec5a3c715453a24e4a5)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/347779
Reviewed-on: http://git-master/r/1164143
(cherry picked from commit 67a6c2d3cfbeeca5cb5ed57aae53f34d07decd4f)
2024-12-20 03:54:00 +00:00
Ankita Garg
5025d29c00 misc: cec: Add sysfs node to set logical addr
Sysfs node takes string of decimal representation of logical address
Logical address must be in bit-map form, e.g., "0x10" for address 4

Bug 1395893

Change-Id: I899fe80e1ebcc9957ac6efe3c4f6d07873b2a8db
Signed-off-by: Ankita Garg <ankitag@nvidia.com>
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/303968
(cherry picked from commit ff2b08c0dc1d6ff3c1d7cac012cdccfa17c6399c)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346043
Reviewed-on: http://git-master/r/1164142
(cherry picked from commit 706ba72c2cb9f05450a10110d70f2462b52046d2)
2024-12-20 03:54:00 +00:00
Xia Yang
ab709208e8 misc: cec: Fix bug potentially cause system hang
Remove wait_event_interruptible() from interrupt context
Change init_done to be atomic_t and reset as early as possible

Bug 1395893

Change-Id: Ib0cf423a3405293000b0c0d9aa105da5bba22e53
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/304631
(cherry picked from commit ef034436a3c8aaf7a9ce5dd9ebaf8dc90dbcce4b)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346042
Reviewed-on: http://git-master/r/1164141
(cherry picked from commit 76e681f957b27323227c9990679631636084b6ae)
2024-12-20 03:54:00 +00:00
Deepak Nibade
b38ef51b1a misc: cec: cancel workqueue in suspend
cancel the workqueue in suspend method before turning
  off the clock

Bug 1360341

Change-Id: I126da686a6ba0c5eec55b67df1e9f962ce16fc48
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/280159
(cherry picked from commit 7cc6da6e41c7889f7ed8da7833d293b3b884bc0e)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346041
Reviewed-on: http://git-master/r/1164140
(cherry picked from commit e57647e7daacd5a3c22016cbe3f01ddb800d702c)
2024-12-20 03:54:00 +00:00
Shridhar Rasal
353c499996 misc: cec: add wait_event for CEC ops
Add wait_event to make sure that CEC functions
do not execute until CEC init completes

Bug 1283088

Change-Id: I1d26360326338f549a14cbf109a24c2935ebe472
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-on: http://git-master/r/232566
(cherry picked from commit 6e94e976c1e2121d81d19018b79a97d353b11d70)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346039
Reviewed-on: http://git-master/r/1164139
(cherry picked from commit 794145e9f8c16c7e36119f3652dd185cf12eb5dc)
2024-12-20 03:54:00 +00:00
Shridhar Rasal
a8422afe1a misc: cec: add worker handler for resume
HDMI CEC needs 1 sec delay for reset hardware in resume
Adding work handler for CEC init

Bug 1283088

Change-Id: I4498584ec93c1a5eefddfad9966cb5a1e7776e6e
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-on: http://git-master/r/228332
(cherry picked from commit 596245cee4b2c239843c2f920d83c21721af2ffb)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346038
Reviewed-on: http://git-master/r/1164138
(cherry picked from commit f62afdb0cb72a087442db6ed450b52925d20f9b6)
2024-12-20 03:54:00 +00:00
Ankita Garg
b268d2ef29 misc: tegra-cec: Updates for T124
In T124, the RX_REGISTER_FULL interrupt is cleared
by reading the RX_REGISTER instead of writing to the
INT_STAT register as before.

Bug 1364229

Change-Id: Ib080a48910304553b0752a3ede55ab0d7653dd77
Signed-off-by: Ankita Garg <ankitag@nvidia.com>
Reviewed-on: http://git-master/r/275982
Reviewed-on: http://git-master/r/1164137
(cherry picked from commit b890e7f50d3d032fc3ede4c4935fdf2c4501f063)
2024-12-20 03:54:00 +00:00
Benjamin Lu
9723602a96 misc: cec: fix warnings
tegra_cec.c: fix warnings as compilation fails after enabling warning as
errors flag

Bug 1258710

Change-Id: Iecd3051d482f5a7488c9f95f6124ad39371f0bd9
Signed-off-by: Benjamin Lu <benjaminl@nvidia.com>
Reviewed-on: http://git-master/r/1164136
(cherry picked from commit 8112e3cd46d11eca51e95cc2fed66d2f7946553a)
2024-12-20 03:54:00 +00:00
Ankit Pashiney
9f3804e6cd misc: tegra-cec: Initial CEC Driver for T3x platform
READ API:
	read API ignores count and will always return 16 bit data.
	read API expects user to supply it with min of 16 bits data
	it returns CEC packet in following format
	bit 0-7: data
	bit 8: EOM
	bit 9: ACK

WRITE API:
	write API ignores count and will always accept 32 bit data.
	write API expects user to supply it with min of 32 bits data
	it accepts CEC packet supllied in following format
	bit 0-7: data
	bit 8: EOM
	bit 12: Address mode, 0 = Direct, 1 = Broadcast
	bit 16: Generate Start bit, 0 = Disable, 1 = Enable
	bit 17: Retry frame, 0 = Disable, 1 = Enable

	Logical address is set to 4, as of now there is no mechanism to change this
	address from userspace.

Driver is disabled by default in Kconfig

Bug 200198493

Change-Id: Ia3835cec0bb717e63dabca5c5fcb1236847bf492
Reviewed-on: http://git-master/r/1164135
(cherry picked from commit 955ec819872e66c4732b38cd74c7ff3a302d95f2)
Signed-off-by: Chun XU <chunx@nvidia.com>
2024-12-20 03:54:00 +00:00
Mahesh Kumar
472d0dfdf3 platform: dce: fix ipc_client_unregister race cond
This patch fixes a race condition between
tegra_dce_unregister_ipc_client and dce_client_ipc_wakeup.

If dce_client_ipc_wakeup is called just after unregistering
it'll result in accessing already freed data structures and
kernel crash. This patch adds a check to validate if the client_ipc
struct is valid before accessing its members.

Bug 4913921

Change-Id: Ie7f25379d7254d1f1ad4fb17baafee353f6d9eca
Signed-off-by: Mahesh Kumar <mahkumar@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3239873
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com>
(cherry picked from commit 91a3402525e79bc59c7367743740c17a91e8752e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3256954
(cherry picked from commit 6bce903d9e8c8de4c2017abc33191a983343a0c2)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261855
Reviewed-by: svcacv <svcacv@nvidia.com>
2024-12-18 16:53:59 -08:00
Jon Hunter
322d0bafa1 drm/tegra: Remove 'unaligned.h' header
In Linux v6.12, commit 5f60d5f6bbc1 ("move asm/unaligned.h to
linux/unaligned.h") moved the 'unaligned.h' header file. The
'unaligned.h' is not needed by the Tegra DRM RISC-V driver and so remove
this header.

Bug 4876974

Change-Id: If5993d6ea8291557de6fd41e4f55552bae45505b
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3252432
(cherry picked from commit 39a93d3dddc622247cec3571bd7124f04cdb95eb)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270385
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-12-18 10:09:43 -08:00
Jon Hunter
39da18ef67 drm/tegra: Fix build for Linux v6.12
In Linux v6.12, commit 446d0f4849b1 ("drm: Remove struct
drm_mode_config_funcs.output_poll_changed") removes
'output_poll_changed' function pointer from 'drm_mode_config_funcs'
structure and commit b5757a5be2fa ("drm: Remove struct
drm_driver.lastclose") removes 'lastclose' from the 'drm_driver'
structure. This is breaking build the Tegra DRM out-of-tree driver for
Linux v6.12.

Fix this by partially back-porting commit 71ec16f45ef8 ("drm/tegra:
Implement fbdev emulation as in-kernel client") from Linux v6.4 which
removed the use of the 'output_poll_changed' and 'lastclose' function
pointers from the Tegra DRM driver. Note that it is safe to partially
back-port this for now because we don't use the frame-buffer support in
the Tegra DRM driver for Tegra234+ devices.

To keep the Tegra DRM out-of-tree driver aligned with upstream, the
remaining parts of commit '71ec16f45ef8' will be back-ported in another
change that will be part of a bigger change to align the frame-buffer
support with the upstream driver. For now just fix the build for Linux
v6.12.

Bug 4876974

Change-Id: Idc9b1c198c067ccb59f1337866154c9a8f0a5623
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3267797
(cherry picked from commit a4ea0faa3a68ceb99dcaa596608099b3dffa667c)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270384
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-12-18 10:09:39 -08:00
Jon Hunter
8a10ebd740 drivers: Fix build for Linux v6.12
In Linux v6.12 the definition 'no_llseek' was finally removed. Since
Linux v6.0 it had been redefined as NULL. Add a test to conftest to
determine if 'no_llseek' is present and if not then it is no longer
necessary to populate this and we can leave as NULL.

Bug 4876974

Change-Id: I051fdb285b32260b5913dad89cabe0be04253f67
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3222106
(cherry picked from commit 7bf81a5b445b01a2adc8b947a29e9ca7db325c6f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270383
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-12-18 10:09:34 -08:00
Jon Hunter
aef3f30099 bt: realtek: Fix build for Linux v6.12
In Linux v6.12, commit 5f60d5f6bbc1 ("move asm/unaligned.h to
linux/unaligned.h") moved the 'unaligned.h' header file. The 'rtk_bt.c'
source file does not need this header and so it can be removed. It is
needed in the 'rtk_misc.c' header and so fix this accordingly.

Bug 4876974

Change-Id: Iabeb6d8a95e131a8b6bc2d1e2b97e8539babf19f
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3252433
(cherry picked from commit 1f8df590e6a8f881fb7025d85095e812d4a98dfa)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3270382
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-12-18 10:09:30 -08:00
Jerry Chang
51f89ad89e kernel: camera: add DOL support formats
add 10-bit and 12-bit DOL support formats

Bug 4962075

Change-Id: Ie631d6a079754aab6321eb485a5168e7fb3eb9a0
Signed-off-by: Jerry Chang <jerchang@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3251864
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shan Neng Chen <snchen@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
2024-12-06 04:09:03 -08:00
Mikko Perttunen
03dd3ecc10 gpu: host1x-fence: Fix fence leak in fence_extract
The fence_extract IOCTL handler was only putting the fence object
on the error path. Add a put to the success path as well.

Bug 4799184

Change-Id: Ib9fa3280320f16e1cf5588bd7b58900644601649
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3261313
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Santosh BS <santoshb@nvidia.com>
2024-12-05 22:24:05 -08:00
Praveen AC
57dc20f5a8 virtual_i2c_mux:Add virtual i2c mux support for other Hawks.
Add virtual i2c bus support for 2nd,3rd & 4th Hawks
to read/write EEPROM data while streaming.

Bug 4807682

Change-Id: I3cd05718a38ed11dd23fd67fee1efb8c7054af71
Signed-off-by: Praveen AC <pac@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3210317
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ankur Pawar <ankurp@nvidia.com>
2024-11-28 15:24:29 -08:00
robelin
18c864a0ad net: wireless: Enable WOW for rtl8822ce driver
Enable the support for wake on wifi on rtl8822ce device

Bug 4878693

Change-Id: I6f863fdd466e458073693ba3f91695c5f8e6df25
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3244351
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
Tested-by: Robert Lin <robelin@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-by: Robert Lin <robelin@nvidia.com>
2024-11-22 05:24:29 -08:00
Akhil R
f6c3d49e92 crypto: tegra: Use separate buffer for each host1x command
Allocate separate buffer for each host1x command. The single buffer used
for host1x commands can get corrupted when independent crypto operations
overlap.

Bug 4883011

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: I43029364c8e65e5014a5b7068cb45225c039aaf8
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3248913
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-11-20 21:09:00 -08:00
Shobek Attupurath
7791d0db52 rtk_btusb: Add support for RTL8852CE Azurewave modules
1. Add support for RTL8852CE modules with PID 1675 and 3586
2. Move RTK_DBG to KERN_DEBUG

Bug 4915378

Change-Id: I194a67878f306931db058e4b113ddf279f655d9a
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3242459
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Shobek Attupurath <sattupurath@nvidia.com>
2024-11-15 12:02:49 -08:00
Shobek Attupurath
9c30467627 rtk_btusb: Fix potential buffer overflow in cfg_list_item struct
The `cfg_list_item` struct previously defined the `data` array with a zero-length,
which can lead to buffer overflow issues detected by the `fortify_memcpy_chk` function.
So change the zero-length array to a flexible array length.

Bug 4915378

Change-Id: I3420406e73a9eec892665380bb15d680df12e751
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3237079
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
2024-11-15 12:02:45 -08:00
Shobek Attupurath
3d15bb40b5 rtk_btusb: Update driver version to 3.1.65ab490.20240531-141726
- Update driver to 3.1.65ab490.20240531-141726
- Add support for 8852CE

Bug 4915378

Change-Id: Ib3f695047ee306fd07db424239c985195619aad1
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3237077
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
2024-11-15 12:02:41 -08:00
Mikko Perttunen
7ea5704ca3 gpu: host1x: When out of memory contexts, wait for free context
Instead of immediately returning an error when trying to allocate
a context device and none are free, log a warning and stall the
submit until a usable context becomes available.

Bug 4712458

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: I964c906e94a8624ded04a5f3851f8c3dbbe76d8b
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3227750
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Dane Liu <danel@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-11-13 20:55:13 -08:00
Mikko Perttunen
276418c013 gpu: host1x: Memory context stealing
Currently, each process holding an open TegraDRM channel reserves
for itself one of the limited number of hardware memory contexts.
Attempting to allocate a channel when all contexts are in use
results in failure.

While we cannot have more contexts than the hardware supports in
active use, idle channels don't necessarily need to have a backing
memory context. As such, in this patch, we add another layer
to allow hardware memory contexts to be "stolen away" by channels
that are in active use, from idle processes.

The way this is implemented, is by keeping track of memory
mappings on each abstracted memory context. If we need to
steal that memory context's backing hardware context, we unmap
everything from it and give it away. When that abstracted
memory context is needed again (re-activated), we attempt
to allocate or steal another hardware context and re-map
the previously unmapped buffers.

Unfortunately, this means additional overhead and unpredictability
at submit time. Submit can fail if we cannot re-allocate a
backing memory context. Future work includes a provision for
un-stealable backing hardware memory contexts for processes
requiring more determinism, as well as optimization and cosmetic
improvements.

Bug 4403250
Bug 4399310

Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Change-Id: I3d13e3476f1bff3c4757152254496cddaaafd76a
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3058905
Reviewed-by: Santosh BS <santoshb@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3227749
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Dane Liu <danel@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
2024-11-13 20:55:08 -08:00
N V S Abhishek
c28e187068 tegra: nvmap: Reduce reported freemem from QueryHeapParams
Reduce free memory reported by QueryHeapParams by 0.1% to avoid
OOM issues for Iovmm_heap. For the overall free memory reported
by the query heap params api, page align it to the previous page
to avoid any failures in allocattr due to page align of requested
size, when requested size is equal to reported free size. Update
allocattr api as well so that it checks the available free memory
before allocating.

Bug 4719292

Change-Id: I7ecd69216d58c36ee5d0750107546601400e722d
Signed-off-by: N V S Abhishek <nabhishek@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3165599
(cherry picked from commit 3fdb84d2c8)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3230712
Reviewed-by: Pritesh Raithatha <praithatha@nvidia.com>
Reviewed-by: Ketan Patil <ketanp@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-11-12 09:54:49 -08:00
Paritosh Dixit
696fd39c49 nvidia-oot: Add .gitignore
Add .gitignore so that git status does not show build artifacts.

Bug 4814000

Change-Id: Iae3ef2be2107db92350038131628903c12b1f1c7
Signed-off-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3240531
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-10-31 06:08:59 -07:00
Revanth Kumar Uppala
b595c01b8f Revert "r8168: Enable CONFIG_SOC_LAN"
This reverts commit 2a23a19bb4.

Reason for revert: Throughput reduced with this change

Change-Id: I37098400ba1d5ec2d8e52d3feed1c6e18402527b
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3232363
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-10-23 08:55:40 -07:00
Akhil R
3415677f0f crypto: tegra: Fix size of buffer allocated
Allocate the buffer based on the request instead of a fixed buffer
length. In operations which may require larger buffer size, a fixed
buffer may fail. Similar patch was added for AES algorithms. Fix the
same for HASH algorithms as well.

Bug 4908156

Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Change-Id: Idd2c1ceae1a85434a5a51154a17dce8c927bb66c
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3234055
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
2024-10-22 10:08:57 -07:00
Jon Hunter
91416b264c media: camera: Fix build for Linux v6.8+
In Linux v6.8, the 'g_frame_interval' and 's_frame_interval' function
pointers were removed from the 'v4l2_subdev_video_ops' structure and
replaced by 'get_frame_interval' and 'set_frame_interval' that were
added to the 'v4l2_subdev_pad_ops' structure.

This change was previously fixed for the Tegra CSI driver by adding the
necessary conftest changes. A new update to the Tegra Cam V4L2 causes
the build to fail for Linux v6.8+ kernels because of the same issue. Fix
up the Tegra Cam V4L2 driver in the same way as the Tegra CSI driver,
but update the name of the conftest test to indicate that this is
applicable for both the 'get_frame_interval' and 'set_frame_interval'
function pointers.

Bug 4448428
Bug 4807063

Change-Id: Ica47f3aaece0bf81e2adc3c431056ea51b64a893
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3231775
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-10-18 13:10:39 -07:00
Jon Hunter
f00b8b2cd4 net: rtl8852ce: Add option to skip driver build
The RealTek drivers do not build against all Linux distributions because
some Linux distributions have back-ported upstream changes and so the
KERNEL_VERSION checks in the driver do not work for these distributions.

Add a compilation flag for the rtl8852ce driver so that we can skip
building of this driver for certain Linux distributions.

Bug 4667769

Change-Id: Ie4ec2308b458e4d5e6a3fa29d5e247c5a709172d
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3231107
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-10-18 06:23:56 -07:00
Praveen AC
c3b8c1cd3e [t23x][camera]: Fix VIDIOC_G/S_PARM v4l2-compliance test fail.
Implemented VIDIOC_G/S_PARM ioctl calls to fix
v4l2-compliance test fail.

Bug 4807063

Change-Id: Ia03b161b5659c710976084f277064a44d10aec15
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3221436
Reviewed-by: Praveen AC <pac@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Narendra Kondapalli <nkondapalli@nvidia.com>
Tested-by: Praveen AC <pac@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-10-16 12:07:46 -07:00
Jon Hunter
5be6f3693d video: tegra: nvmap: Fix build for Linux v6.12
In Linux v6.12, commit ("4ffca5a96678 mm: support only one page_type per
page") removed the definition PAGE_MAPCOUNT_RESERVE and this breaks the
build for NVMAP. The function 'page_has_type()' was added in Linux v5.0
and performs the necessary check and so use this instead to fix the
build.

Bug 4593750

Change-Id: Iaa7393ae11de9730b4ec876a971223e62a7f3f7d
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3217428
(cherry picked from commit eb1d2c65ecfcaef3d184300b3987fb82cfe8c0e6)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3226683
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-10-10 09:54:52 -07:00
Jon Hunter
43f2b77b06 misc: nvsciipc: Fix build for Linux v6.12
In Linux v6.12, commit 88a2f6468d01 ("struct fd: representation change")
removed the 'struct file' pointer from 'struct fd'. This breaks building
the NVSCIIPC driver that tries to directly access the 'file' pointer
from the 'fd' structure. Fix this by using the helper macros 'fd_empty'
and 'fd_file' as necessary to fix the build.

Bug 4593750

Change-Id: I0f84736b408f533a732476175a8745091bc8542f
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3217429
(cherry picked from commit 0f21c4134eb08dfcafad832d97308f2d98601f1d)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3226681
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-10-10 09:54:44 -07:00
Jon Hunter
7cdcfd844e video: tegra: dc: Correct GPIO definitions
In Linux v6.12, commit 8c045ca534d0 ("gpiolib: legacy: Kill GPIOF_DIR_*
definitions") removed the GPIOF_DIR_* definitions and updated drivers to
use the equivalent GPIOF_* definitions instead. The GPIOF_* definitions
were added in Linux v3.0 and so update the appropriate drivers to use
these definitions.

Note that when calling devm_gpio_request_one() with GPIOF_DIR_OUT for
the flags, then because no explicit output level is specified, the GPIO
driver core defaults to low. Hence, in this case we replace
GPIOF_DIR_OUT with GPIOF_OUT_INIT_LOW.

Bug 4593750

Change-Id: I05664fd4e0abf5755c9514dffe64b239266c92fa
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3217397
(cherry picked from commit 0c4fc214d92f2a3c91e9c3b9d1245b4c1ee968f4)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3226680
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-10-10 09:54:40 -07:00
Jon Hunter
d60febb08a pwm: tegra-tachometer: Fix build for Linux v6.12
In Linux v6.12, commit f9ecc2febf6f ("pwm: Don't export pwm_capture()")
made pwm_capture an internal function and this broke the build for the
Tegra Tachometer driver. The pwm_capture() function simply calls the
drivers '.capture' callback and so fix this by directly calling the
function pwm_tegra_tacho_capture() instead. Note that the rpm_show()
function is also moved to after the declaration of the
pwm_tegra_tacho_capture() function.

Bug 4876974

Change-Id: Idf7fbc16382a9077c651755d9907ded7652610cc
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3217391
(cherry picked from commit 1f752196cab197f708d75bf7a319e23716a685e0)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3226679
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-10-10 09:54:36 -07:00
Jon Hunter
d8c5cf13b7 net: rtl8852ce: Don't build driver for Linux v6.6+
Building the rtl8852ce driver with various different Linux v6.x kernels
fail for various reasons.

For Linux v6.6 the build fails with errors such as ...

 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sta.c: In function
  'phl_cmd_set_seciv_hdl':
 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sta.c:4907:16: error:
   implicit conversion from 'enum rtw_hal_status' to
   'enum rtw_phl_status' [-Werror=enum-conversion]
 4907 |         return rtw_hal_set_dctrl_tbl_seciv((void*)phl_info->hal,
      |                                             sta, sta->sec_iv);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For Linux v6.8 the build fails with the above and the following ...

 drivers/net/wireless/realtek/rtl8852ce/phl/phl_sta.c:301:5: error:
  no previous declaration for '_phl_get_macid'
  [-Werror=missing-declarations]
  301 | u16 _phl_get_macid(struct phl_info_t *phl_info,
      |     ^~~~~~~~~~~~~~

For Linux v6.10 the build fails with the above and the following ...

 drivers/net/wireless/realtek/rtl8852ce/core/rtw_ap.c:6265:9: error:
  suggest braces around empty body in an 'else' statement
  [-Werror=empty-body]
 6265 |         ;
      |         ^

 drivers/net/wireless/realtek/rtl8852ce/core/rtw_sta_mgt.c:742:1: error:
  'static' is not at beginning of declaration
   [-Werror=old-style-declaration]
 742 | u32 static _rtw_free_core_stainfo(_adapter *padapter , struct
     |                                   sta_info *psta, u8 aid,
     |                                    const u8 *hwaddr)
     | ^~~

For Linux v6.12, the driver build is completely broken because of the
following build error ...

 drivers/net/wireless/realtek/rtl8852ce/os_dep/linux/wifi_regd.c:1007:17:
  error: too few arguments to function 'cfg80211_cac_event'
 1007 |                 cfg80211_cac_event(evt->netdev, &evt->chandef,
      |                                    evt->event, GFP_KERNEL);
      |                 ^~~~~~~~~~~~~~~~~~

For Linux v6.6+ mark the driver as broken and do not build this for
Linux v6.6+ kernels until these issues are addressed.

Bug 4667769

Change-Id: Id6b060f6b39ba4ef64d6388e06ef1e038c19206f
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3226276
Reviewed-by: svcacv <svcacv@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-10-09 15:53:58 -07:00
ruppala
2a23a19bb4 r8168: Enable CONFIG_SOC_LAN
Enable CONFIG_SOC_LAN for ethernet to support pcie_bus_perf
kernel command line option.

Bug 4607316

Change-Id: I724364a5804d796c13f837f73254e686f59dc0b4
Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3163034
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
2024-10-06 22:54:04 -07:00
Shobek Attupurath
ffedd6a1c6 rtl8852ce: Add Nvidia changes to v1.19.16.1-0-g1fe335ba1.20240815_PC
1. Update makefiles to add Nvidia source path
2. Change file permissions to 0644
3. Delete files with .orig extensions

Bug 4667769
Bug 4667981

Change-Id: I0df6f3073780daf6879c4165cd97fd62fd0a4b65
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195548
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
Tested-by: Shobek Attupurath <sattupurath@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
2024-10-04 15:54:29 -07:00
Shobek Attupurath
90e380eaf4 rtl8852ce: Add base driver v1.19.16.1-0-g1fe335ba1.20240815_PC
- support Android-14
- support Linux kernel 6.9
- support 6G regulation
- support Thermal protection
- support TX shortcut to reduce CPU loading
- fix some coverity issues
- Use RTW regulatory version rtk_8852CE_M.2_2230-67-52
- default enable con-current and MCC

Bug 4667769
Bug 4667981

Change-Id: Iee069ecdd1f00a0b78285d0a4ef5778ed9ace478
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3195535
Tested-by: Shobek Attupurath <sattupurath@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Shobek Attupurath <sattupurath@nvidia.com>
2024-10-04 15:54:24 -07:00
Yi-Wei Wang
3741667390 i2c: nvvrs11: Report power in milliWatts
The unit of the voltage is in milliVolts and the current is in Amperes
for VRS11. So, the power can be reported in milliWatts which provides
higher resolution for better profiling.

Bug 200718059

Change-Id: I0ae52dafa4c7dcc751d9c65b410205163a4fbc45
Signed-off-by: Yi-Wei Wang <yiweiw@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3223011
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
2024-10-03 05:24:14 -07:00
Johnny Liu
93b1b8542e conftest: update tests for devfreq and thermal
Introduce the following three tests:
1. devfreq_dev_profile_has_is_cooling_device
2. devfreq_has_freq_table
3. thermal_zone_for_each_trip

Bug 4854967

Signed-off-by: Johnny Liu <johnliu@nvidia.com>
Change-Id: I5fe2f7102f667a31d61550487a153590584ed638
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3213844
(cherry picked from commit ae9d7ea9479637e77732bc1842a5488653157d21)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3221294
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Tested-by: Paritosh Dixit <paritoshd@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-by: Paritosh Dixit <paritoshd@nvidia.com>
2024-10-01 04:23:56 -07:00
Johnny Liu
c580fd0d06 devfreq: use conftest for conditional module build
Some distros might use old kernel source but with some latest upstream
kernel patches backported to their kernel source tree. To deal with this
scenario and avoid kernel compilation failure, use conftest to check the
existence of features against the kernel source tree which the OOT
modules are built upon and do the conditional build based on the test
result generated with the conftest tool.

Use NV_DEVFREQ_HAS_FREQ_TABLE to determine whether freq_table field is
there in struct devfreq data strcuture, and choose the correct path for
building the module.

Use tegra_wmark-specific devfreq_get_freq_range always to avoid kernel
version check and conftest check. Since devfreq_get_freq_range exists in
the devfreq-specific governor.h (e.g. drivers/devfreq/governor.h) file
instead of globabl linux kernel include header files
(e.g. include/linux/devfreq.h), conftest cannot be used to the existence
of devfreq_get_freq_range kernel function.

Bug 4884092

Change-Id: I5bde4c712f59f38de74c1d8d95135c9b25d621b1
Signed-off-by: Johnny Liu <johnliu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3220896
Tested-by: Paritosh Dixit <paritoshd@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Jon Hunter <jonathanh@nvidia.com>
2024-10-01 02:08:56 -07:00
snchen
b2db309d50 kernel: camera: add bayer raw14 format.
Add raw14 bayer format driver support

bug 4335141

Change-Id: I45c4fb2f692a98cf33d81415104e815c14340a68
Signed-off-by: snchen <snchen@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3176545
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: Anubhav Rai <arai@nvidia.com>
Reviewed-by: Bibek Basu <bbasu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-09-30 06:12:52 -07:00
Jon Hunter
93ba193a32 pci: endpoint: Update drivers for Linux v6.11
For Linux v6.11, the 'pci_epc_event_ops' structure 'core_init' callback
was renamed to 'epc_init' and a new 'epc_deinit' callback was added.

Update the PCI endpoint drivers for Linux v6.11 by:

 1. Adding tests to conftest to detect the presence of 'epc_init' and
    'epc_deinit'.
 2. Update the drivers as necessary to use the appropriate callback
    depending upon what is present in the kernel.

Bug 4749580

Change-Id: Ife7e2d5d18332bf84f22142c9727dc1ece913c49
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3186686
(cherry picked from commit b0ff4f1358)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3219305
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
2024-09-26 06:11:21 -07:00
Jon Hunter
15ca4ff659 drivers: Fix platform_driver remove for Linux v6.11
In Linux v6.11, the 'platform_driver' structure 'remove' callback was
updated to return void instead of 'int'. Update all the impacted drivers
as necessary to fix this.

Bug 4749580

Change-Id: I3bb5c549777f7ccad0e3f870373fdd25726ad7ed
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3182878
(cherry picked from commit 951b2423a8)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3210788
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-09-11 04:39:43 -07:00
Jon Hunter
c463c63993 scripts: Add scripts for platform_driver remove
In Linux v6.11, the 'platform_driver' structure 'remove' callback was
updated to return void instead of 'int'. This change impacts all OOT
platform drivers and so instead of editing each manually, add a
coccinelle script to handle updating all platform drivers. This script
is ran by executing the following command ...

 $ spatch --in-place \
   --sp-file /path/to/scripts/coccinelle/platform_driver_remove.cocci
   <driver-source-directory>

Finally, add a test to the conftest script that is used to detect if the
platform driver 'remove' callback returns 'void'.

Bug 4749580

Change-Id: I53d25cc36cc3be97a6eeeb4ccbdf9b7dfda338a9
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3176834
(cherry picked from commit 24826db83f)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3202689
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
2024-09-11 04:39:39 -07:00
Ketan Patil
cc74d1fe1b video: tegra: nvmap: Fix data race between create and destroy client
nvmap uses pid of group_leader task to indicate a client process. During
create_client operation, whenever any client with the same group_leader
pid already exists in clients list of nvmap_device, then nvmap
increments the count field of nvmap_client struct. Otherwise, create a
new nvmap_client. Both of the operations i.e. checking the list for
client and incrementing the counter happen inside lock. On the other
hand, during nvmap_release, first the counter is decremented and checked
if it's zero or not. If it's zero then the lock is taken and client is
removed from client list of nvmap_device. As both the operations i.e.
decrementing the counter value and removing client from list (if the
counter becomes 0) are not happening inside a lock, it's resulting into
the following data race scenario.
1) nvmap_release on existing client process 1
   - decrement client's counter
   - counter value has become zero
   - client is yet to be removed from the dev->clients list
   - context switch happen to __nvmap_create_client as another
namespace/thread with same with same group_leader pid is created.
2) __nvmap_create_client
   - as the client with same pid exists in dev->client list, it
increments counter value to 1, instead of creating a new client struct.
   - context switch happen to nvmap_release from step 1
3) nvmap_release
   - It calls destroy_client and remove the client from dev->client
list.
   - Completes rest of the operations in destroy_client and returns.
   - Context switch to remaining operations from step 2
4) nvmap_release
   - Now, when the nvmap_release will be called for the thread/namespace
which was created in step 2, then list_del operation would fail as the
client struct was already removed from dev->client list.

Fix the above issue by doing both operations i.e. decrementing the
counter value and removing the client struct from dev->client list in a
single lock.

Bug 4829958

Change-Id: I87ebbcb45b18114d0ec75520443bee010f88d59e
Signed-off-by: Ketan Patil <ketanp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3209794
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
Reviewed-by: Pritesh Raithatha <praithatha@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ashish Mhetre <amhetre@nvidia.com>
2024-09-10 07:08:58 -07:00
1260 changed files with 1212077 additions and 11328 deletions

25
.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: GPL-2.0
#
# Use command 'git ls-files -i --exclude-standard' to ensure that no
# tracked files are ignored.
#
*.o
*.o.*
*.a
*.s
*.ko
*.so
*.so.dbg
*.mod.c
*.i
*.symtypes
*.order
*.patch
modules.builtin
Module.symvers
*.dwo
*.mod
*.cmd
*mods.dtb*

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
LINUXINCLUDE += -I$(srctree.nvidia-oot)/include
LINUXINCLUDE += -I$(srctree.nvidia-oot)/drivers/gpu/host1x/hw/
@@ -12,8 +12,10 @@ ifdef CONFIG_PSTORE
obj-m += block/tegra_oops_virt_storage/
endif
ifdef CONFIG_BT
ifneq ($(NV_OOT_BLUETOOTH_REALTEK_SKIP_BUILD),y)
obj-m += bluetooth/realtek/
endif
endif
obj-m += c2c/
obj-m += clink/
obj-m += cpuidle/

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -802,9 +804,21 @@ static const struct of_device_id tegra_hv_vblk_oops_match[] = {
MODULE_DEVICE_TABLE(of, tegra_hv_vblk_oops_match);
#endif /* CONFIG_OF */
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_hv_vblk_oops_remove_wrapper(struct platform_device *pdev)
{
tegra_hv_vblk_oops_remove(pdev);
}
#else
static int tegra_hv_vblk_oops_remove_wrapper(struct platform_device *pdev)
{
return tegra_hv_vblk_oops_remove(pdev);
}
#endif
static struct platform_driver tegra_hv_vblk_oops_driver = {
.probe = tegra_hv_vblk_oops_probe,
.remove = tegra_hv_vblk_oops_remove,
.remove = tegra_hv_vblk_oops_remove_wrapper,
.driver = {
.name = OOPS_DRV_NAME,
.owner = THIS_MODULE,

View File

@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Makefile for Virtual Storage Driver
@@ -8,6 +8,7 @@
LINUX_VERSION := $(shell expr $(VERSION) \* 256 + $(PATCHLEVEL))
LINUX_VERSION_6_11 := $(shell expr 6 \* 256 + 11)
ifneq ($(NV_OOT_BLOCK_TEGRA_VIRT_STORAGE_SKIP_BUILD),y)
# Use dummy driver for Kernel versions greater than or equal to Linux v6.11
ifeq ($(shell test $(LINUX_VERSION) -lt $(LINUX_VERSION_6_11); echo $$?),0)
tegra_vblk-y += tegra_hv_vblk.o
@@ -16,4 +17,5 @@ tegra_vblk-y += tegra_hv_mmc.o
tegra_vblk-y += tegra_hv_scsi.o
tegra_vblk-y += tegra_hv_ufs.o
obj-m += tegra_vblk.o
endif
endif
endif

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -145,7 +145,11 @@ static void vblk_put_req(struct vsc_request *req)
(vblkdev->queue_state == VBLK_QUEUE_SUSPENDED)) {
complete(&vblkdev->req_queue_empty);
}
#if defined(NV_TIMER_DELETE_PRESENT) /* Linux v6.15 */
timer_delete(&req->timer);
#else
del_timer(&req->timer);
#endif
}
}
@@ -534,8 +538,12 @@ static bool submit_bio_req(struct vblk_dev *vblkdev)
}
sg_init_table(vsc_req->sg_lst,
bio_req->nr_phys_segments);
#if defined(NV_BLK_RQ_MAP_SG_HAS_NO_QUEUE_ARG) /* Linux v6.15 */
sg_cnt = blk_rq_map_sg(bio_req, vsc_req->sg_lst);
#else
sg_cnt = blk_rq_map_sg(vblkdev->queue, bio_req,
vsc_req->sg_lst);
#endif
vsc_req->sg_num_ents = sg_nents(vsc_req->sg_lst);
if (dma_map_sg(vblkdev->device, vsc_req->sg_lst,
vsc_req->sg_num_ents, DMA_BIDIRECTIONAL) == 0) {
@@ -1563,9 +1571,21 @@ static struct of_device_id tegra_hv_vblk_match[] = {
MODULE_DEVICE_TABLE(of, tegra_hv_vblk_match);
#endif /* CONFIG_OF */
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_hv_vblk_remove_wrapper(struct platform_device *pdev)
{
tegra_hv_vblk_remove(pdev);
}
#else
static int tegra_hv_vblk_remove_wrapper(struct platform_device *pdev)
{
return tegra_hv_vblk_remove(pdev);
}
#endif
static struct platform_driver tegra_hv_vblk_driver = {
.probe = tegra_hv_vblk_probe,
.remove = tegra_hv_vblk_remove,
.remove = tegra_hv_vblk_remove_wrapper,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,

View File

@@ -1,22 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
CONFIG_BTUSB_AUTOSUSPEND = n
CONFIG_BTUSB_WAKEUP_HOST = n
CONFIG_BTCOEX = y
ifeq ($(CONFIG_BTUSB_AUTOSUSPEND), y)
EXTRA_CFLAGS += -DCONFIG_BTUSB_AUTOSUSPEND
endif
ifeq ($(CONFIG_BTUSB_WAKEUP_HOST), y)
EXTRA_CFLAGS += -DCONFIG_BTUSB_WAKEUP_HOST
endif
ifeq ($(CONFIG_BTCOEX), y)
EXTRA_CFLAGS += -DCONFIG_BTCOEX
endif
obj-m := rtk_btusb.o
rtk_btusb-objs := rtk_coex.o \
rtk_misc.o \
rtk_bt.o
ifneq ($(KERNELRELEASE),)
obj-m := rtk_btusb.o
rtk_btusb-y = rtk_coex.o rtk_misc.o rtk_bt.o
else
PWD := $(shell pwd)
KVER := $(shell uname -r)
KDIR := /lib/modules/$(KVER)/build
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod.c *.mod.o *.ko *.symvers *.order *.a
endif

View File

@@ -1,8 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
@@ -17,12 +31,11 @@
#include <linux/dcache.h>
#include <linux/reboot.h>
#include <net/sock.h>
#include <asm/unaligned.h>
#include "rtk_bt.h"
#include "rtk_misc.h"
#define VERSION "3.1.6fd4e69.20220818-105856"
#define VERSION "3.1.65ab490.20240531-141726"
#ifdef BTCOEX
#include "rtk_coex.h"
@@ -35,95 +48,64 @@ static DEFINE_SEMAPHORE(switch_sem);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 7, 1)
static bool reset = 0;
static bool reset = true;
#endif
static struct usb_driver btusb_driver;
static struct usb_device_id btusb_table[] = {
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static u16 iso_min_conn_handle = 0x1b;
#endif
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Generic Bluetooth USB interface */
{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
{}
};
static const struct usb_device_id blacklist_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0bda,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x13d3,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0489,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x1358,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04ca,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x2ff8,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0b05,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0930,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x10ec,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04c5,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0cb5,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0cb8,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04b8,
}, { }
};
@@ -148,20 +130,6 @@ static struct btusb_data *rtk_alloc(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, btusb_table);
static int inc_tx(struct btusb_data *data)
{
unsigned long flags;
int rv;
spin_lock_irqsave(&data->txlock, flags);
rv = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!rv)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
return rv;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
static inline void btusb_free_frags(struct btusb_data *data)
{
@@ -204,7 +172,11 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
@@ -259,15 +231,26 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
bt_cb(skb)->expect -= len;
if (skb->len == HCI_ACL_HDR_SIZE) {
__le16 dlen = hci_acl_hdr(skb)->dlen;
struct hci_acl_hdr *h = hci_acl_hdr(skb);
__le16 dlen = h->dlen;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
__u16 handle = __le16_to_cpu(h->handle) & 0xfff;
if(handle >= iso_min_conn_handle) {
bt_cb(skb)->pkt_type = HCI_ISODATA_PKT;
}
#endif
/* Complete ACL header */
bt_cb(skb)->expect = __le16_to_cpu(dlen);
@@ -293,10 +276,42 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
return err;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
static int btrtl_usb_recv_isoc(u16 pos, u8 *data, u8 *p, int len,
u16 wMaxPacketSize)
{
u8 *prev;
if (pos >= HCI_SCO_HDR_SIZE && pos >= wMaxPacketSize &&
len == wMaxPacketSize && !(pos % wMaxPacketSize) &&
wMaxPacketSize >= 10 && p[0] == data[0] && p[1] == data[1]) {
prev = data + (pos - wMaxPacketSize);
/* Detect the sco data of usb isoc pkt duplication. */
if (!memcmp(p + 2, prev + 2, 8))
return -EILSEQ;
if (wMaxPacketSize >= 12 &&
p[2] == prev[6] && p[3] == prev[7] &&
p[4] == prev[4] && p[5] == prev[5] &&
p[6] == prev[10] && p[7] == prev[11] &&
p[8] == prev[8] && p[9] == prev[9]) {
return -EILSEQ;
}
}
return 0;
}
#endif
static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
{
struct sk_buff *skb;
int err = 0;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
u16 wMaxPacketSize = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize);
#endif
spin_lock(&data->rxlock);
skb = data->sco_skb;
@@ -316,7 +331,24 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
/* Gaps in audio could be heard while streaming WBS using USB
* alt settings 3 on some platforms.
* Add the function to detect it.
*/
if (test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags)) {
err = btrtl_usb_recv_isoc(skb->len, skb->data, buffer,
len, wMaxPacketSize);
if (err)
break;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
@@ -347,6 +379,21 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
return err;
}
#else
static int inc_tx(struct btusb_data *data)
{
unsigned long flags;
int rv;
spin_lock_irqsave(&data->txlock, flags);
rv = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!rv)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
return rv;
}
#endif
static void btusb_intr_complete(struct urb *urb)
@@ -626,6 +673,51 @@ retry:
}
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
int mtu, struct btusb_data *data)
{
int i = 0, offset = 0;
unsigned int interval;
BT_DBG("len %d mtu %d", len, mtu);
/* For mSBC ALT 6 settings some Realtek chips need to transmit the data
* continuously without the zero length of USB packets.
*/
if (btrealtek_test_flag(data->hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP))
goto ignore_usb_alt6_packet_flow;
/* For mSBC ALT 6 setting the host will send the packet at continuous
* flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
* 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
* To maintain the rate we send 63bytes of usb packets alternatively for
* 7ms and 8ms to maintain the rate as 7.5ms.
*/
if (data->usb_alt6_packet_flow) {
interval = 7;
data->usb_alt6_packet_flow = false;
} else {
interval = 6;
data->usb_alt6_packet_flow = true;
}
for (i = 0; i < interval; i++) {
urb->iso_frame_desc[i].offset = offset;
urb->iso_frame_desc[i].length = offset;
}
ignore_usb_alt6_packet_flow:
if (len && i < BTUSB_MAX_ISOC_FRAMES) {
urb->iso_frame_desc[i].offset = offset;
urb->iso_frame_desc[i].length = len;
i++;
}
urb->number_of_packets = i;
}
#endif
static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
{
int i, offset = 0;
@@ -675,6 +767,12 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 2, 14)
usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
hdev, data->isoc_rx_ep->bInterval);
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
#else
urb->dev = data->udev;
urb->pipe = pipe;
urb->context = hdev;
@@ -684,6 +782,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
urb->transfer_buffer = buf;
urb->transfer_buffer_length = size;
#endif
__fill_isoc_descriptor(urb, size,
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
@@ -734,8 +833,8 @@ static void btusb_isoc_tx_complete(struct urb *urb)
struct sk_buff *skb = urb->context;
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
RTKBT_DBG("%s: urb %p status %d count %d",__func__,
urb, urb->status, urb->actual_length);
RTKBT_DBG("%s: urb %p status %d count %d", __func__,
urb, urb->status, urb->actual_length);
if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done;
@@ -751,6 +850,49 @@ done:
kfree_skb(skb);
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static int rtl_read_iso_handle_range(struct hci_dev *hdev)
{
struct sk_buff *skb;
struct __rp {
u8 status;
u8 min_handle[2];
} *rp;
int ret = -EIO;
skb = __hci_cmd_sync(hdev, 0xfdab, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
return PTR_ERR(skb);
}
/* FIXME: if the return status is not zero, __hci_cmd_sync() would
* return an error and we would not reach here.
*/
if (skb->data[0]) {
RTKBT_ERR("%s: Read failed, status %0x", hdev->name,
skb->data[0]);
goto err;
}
if (skb->len < sizeof(*rp)) {
RTKBT_WARN("%s: The len %u of rp is too short", __func__,
skb->len);
goto err;
}
rp = (void *)skb->data;
iso_min_conn_handle = (u16)rp->min_handle[1] << 8 | rp->min_handle[0];
RTKBT_DBG("ISO handle range (handle >= %04x)", iso_min_conn_handle);
kfree_skb(skb);
return 0;
err:
kfree_skb(skb);
return ret;
}
#endif
static int btusb_open(struct hci_dev *hdev)
{
struct btusb_data *data = GET_DRV_DATA(hdev);
@@ -775,6 +917,10 @@ static int btusb_open(struct hci_dev *hdev)
goto failed;
/*******************************/
err = setup_btrealtek_flag(data->intf, hdev);
if (err < 0)
RTKBT_WARN("setup_btrealtek_flag incorrect!");
RTKBT_INFO("%s set HCI UP RUNNING", __func__);
if (test_and_set_bit(HCI_UP, &hdev->flags))
goto done;
@@ -817,6 +963,32 @@ failed:
return err;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static int btusb_setup(struct hci_dev *hdev)
{
rtl_read_iso_handle_range(hdev);
return 0;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static int btusb_shutdown(struct hci_dev *hdev)
{
struct sk_buff *skb;
int ret;
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
bt_dev_err(hdev, "HCI reset during shutdown failed");
return ret;
}
kfree_skb(skb);
return 0;
}
#endif
static void btusb_stop_traffic(struct btusb_data *data)
{
mdelay(URB_CANCELING_DELAY_MS); // Added by Realtek
@@ -920,8 +1092,152 @@ static const char pkt_ind[][8] = {
[HCI_COMMAND_PKT] = "cmd",
[HCI_ACLDATA_PKT] = "acl",
[HCI_SCODATA_PKT] = "sco",
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
[HCI_ISODATA_PKT] = "iso",
#endif
};
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct usb_ctrlrequest *dr;
struct urb *urb;
unsigned int pipe;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
dr = kmalloc(sizeof(*dr), GFP_KERNEL);
if (!dr) {
usb_free_urb(urb);
return ERR_PTR(-ENOMEM);
}
dr->bRequestType = data->cmdreq_type;
dr->bRequest = 0;
dr->wIndex = 0;
dr->wValue = 0;
dr->wLength = __cpu_to_le16(skb->len);
pipe = usb_sndctrlpipe(data->udev, 0x00);
usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
skb->data, skb->len, btusb_tx_complete, skb);
skb->dev = (void *)hdev;
return urb;
}
static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
unsigned int pipe;
if (!data->bulk_tx_ep)
return ERR_PTR(-ENODEV);
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
usb_fill_bulk_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_tx_complete, skb);
skb->dev = (void *)hdev;
return urb;
}
static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
unsigned int pipe;
if (!data->isoc_tx_ep)
return ERR_PTR(-ENODEV);
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
usb_fill_int_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_isoc_tx_complete,
skb, data->isoc_tx_ep->bInterval);
urb->transfer_flags = URB_ISO_ASAP;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
if (data->isoc_altsetting == 6)
__fill_isoc_descriptor_msbc(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize),
data);
else
__fill_isoc_descriptor(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
#else
__fill_isoc_descriptor(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
#endif
skb->dev = (void *)hdev;
return urb;
}
static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
int err;
usb_anchor_urb(urb, &data->tx_anchor);
err = usb_submit_urb(urb, GFP_KERNEL);
if (err < 0) {
if (err != -EPERM && err != -ENODEV)
RTKBT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
kfree(urb->setup_packet);
usb_unanchor_urb(urb);
} else {
usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
return err;
}
static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
unsigned long flags;
bool suspending;
spin_lock_irqsave(&data->txlock, flags);
suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!suspending)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
if (!suspending)
return submit_tx_urb(hdev, urb);
usb_anchor_urb(urb, &data->deferred);
schedule_work(&data->waker);
usb_free_urb(urb);
return 0;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -931,14 +1247,20 @@ int btusb_send_frame(struct sk_buff *skb)
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
#endif
struct urb *urb;
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
struct btusb_data *data = GET_DRV_DATA(hdev);
struct usb_ctrlrequest *dr;
struct urb *urb;
unsigned int pipe;
int err;
#endif
//RTKBT_DBG("%s", hdev->name);
// RTKBT_DBG("%s", hdev->name);
/* After Kernel version 4.4.0, move the check into the
* hci_send_frame function before calling hdev->send
*/
#if HCI_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
/* If the parameter is wrong, the hdev isn't the correct
* one. Then no HCI commands can be sent.
@@ -946,13 +1268,15 @@ int btusb_send_frame(struct sk_buff *skb)
RTKBT_ERR("HCI is not running");
return -EBUSY;
}
#endif
/* Before kernel/hci version 3.13.0, the skb->dev is set before
* entering btusb_send_frame(). So there is no need to set it here.
*
* The skb->dev will be used in the callbacks when urb transfer
* completes. See btusb_tx_complete() and btusb_isoc_tx_complete() */
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) && \
HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
skb->dev = (void *)hdev;
#endif
@@ -963,6 +1287,14 @@ int btusb_send_frame(struct sk_buff *skb)
#ifdef BTCOEX
rtk_btcoex_parse_cmd(skb->data, skb->len);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
urb = alloc_ctrl_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.cmd_tx++;
return submit_or_queue_tx_urb(hdev, urb);
#else
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -988,11 +1320,24 @@ int btusb_send_frame(struct sk_buff *skb)
hdev->stat.cmd_tx++;
break;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
case HCI_ISODATA_PKT:
#endif
case HCI_ACLDATA_PKT:
print_acl(skb, 1);
#ifdef BTCOEX
rtk_btcoex_parse_l2cap_data_tx(skb->data, skb->len);
if(bt_cb(skb)->pkt_type == HCI_ACLDATA_PKT)
rtk_btcoex_parse_l2cap_data_tx(skb->data, skb->len);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.acl_tx++;
return submit_or_queue_tx_urb(hdev, urb);
#else
if (!data->bulk_tx_ep)
return -ENODEV;
@@ -1009,7 +1354,22 @@ int btusb_send_frame(struct sk_buff *skb)
hdev->stat.acl_tx++;
break;
#endif
case HCI_SCODATA_PKT:
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
if (hci_conn_num(hdev, SCO_LINK) < 1)
return -ENODEV;
urb = alloc_isoc_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb);
}
return -EILSEQ;
#else
if (!data->isoc_tx_ep || SCO_NUM < 1)
return -ENODEV;
@@ -1035,6 +1395,7 @@ int btusb_send_frame(struct sk_buff *skb)
default:
return -EILSEQ;
}
err = inc_tx(data);
@@ -1057,12 +1418,14 @@ skip_waking:
} else {
usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
done:
usb_free_urb(urb);
return err;
#endif
}
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
static void btusb_destruct(struct hci_dev *hdev)
{
@@ -1181,6 +1544,9 @@ static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data,
BT_DBG("Looking for Alt no :%d", alt);
if (!intf)
return NULL;
for (i = 0; i < intf->num_altsetting; i++) {
if (intf->altsetting[i].desc.bAlternateSetting == alt)
return &intf->altsetting[i];
@@ -1221,7 +1587,14 @@ static void btusb_work(struct work_struct *work)
new_alts = data->sco_num;
}
} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
new_alts = btusb_find_altsetting(data, 6) ? 6 : 1;
if (btusb_find_altsetting(data, 6))
new_alts = 6;
else if (btusb_find_altsetting(data, 3) &&
hdev->sco_mtu >= 72 &&
test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags))
new_alts = 3;
else
new_alts = 1;
}
if (btusb_switch_alt_setting(hdev, new_alts) < 0)
@@ -1421,7 +1794,7 @@ static int rtkbt_pm_notify(struct notifier_block *notifier,
result = __rtk_send_hci_cmd(udev, cmd, 3);
kfree(cmd);
msleep(100); /* From FW colleague's recommendation */
result = download_lps_patch(intf);
result = download_special_patch(intf, "lps_");
#endif
#ifdef RTKBT_TV_POWERON_WHITELIST
@@ -1540,13 +1913,23 @@ static int btusb_probe(struct usb_interface *intf,
struct usb_device *udev;
udev = interface_to_usbdev(intf);
RTKBT_DBG("btusb_probe intf->cur_altsetting->desc.bInterfaceNumber %d",
RTKBT_INFO("btusb_probe intf->cur_altsetting->desc.bInterfaceNumber %d",
intf->cur_altsetting->desc.bInterfaceNumber);
/* interface numbers are hardcoded in the spec */
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
if (!id->driver_info) {
const struct usb_device_id *match;
match = usb_match_id(intf, blacklist_table);
if (match)
id = match;
else
return -ENODEV;
}
/*******************************/
flag1 = device_can_wakeup(&udev->dev);
flag2 = device_may_wakeup(&udev->dev);
@@ -1636,6 +2019,13 @@ static int btusb_probe(struct usb_interface *intf,
hdev->flush = btusb_flush;
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
hdev->setup = btusb_setup;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
hdev->shutdown = btusb_shutdown;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
hci_set_drvdata(hdev, data);
@@ -1645,10 +2035,14 @@ static int btusb_probe(struct usb_interface *intf,
hdev->owner = THIS_MODULE;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 7, 1)
if (!reset)
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
RTKBT_DBG("set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);");
#endif
/* Interface numbers are hardcoded in the specification */

View File

@@ -1,12 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __RTK_BT_H__
#define __RTK_BT_H__
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -30,14 +41,17 @@
/* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */
#define HCI_VERSION_CODE LINUX_VERSION_CODE
#ifdef CONFIG_BTCOEX
#define CONFIG_BTCOEX 1
#define CONFIG_BTUSB_WAKEUP_HOST 0
#if CONFIG_BTCOEX
#define BTCOEX
#endif
/***********************************
** Realtek - For rtk_btusb driver **
***********************************/
#ifdef CONFIG_BTUSB_WAKEUP_HOST
#if CONFIG_BTUSB_WAKEUP_HOST
#define BTUSB_WAKEUP_HOST
#endif
@@ -84,6 +98,7 @@ int btusb_send_frame(struct sk_buff *skb);
#define BTUSB_ISOC_RUNNING 2
#define BTUSB_SUSPENDING 3
#define BTUSB_DID_ISO_RESUME 4
#define BTUSB_USE_ALT3_FOR_WBS 15
struct btusb_data {
struct hci_dev *hdev;
@@ -125,6 +140,7 @@ struct btusb_data {
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
unsigned int air_mode;
bool usb_alt6_packet_flow;
#endif
int isoc_altsetting;
int suspend_count;
@@ -136,6 +152,3 @@ struct btusb_data {
struct notifier_block shutdown_notifier;
void *context;
};
#endif /* __RTK_BT_H__ */

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __RTK_COEX_H__
#define __RTK_COEX_H__
#include <net/bluetooth/hci_core.h>
#include <linux/list.h>
@@ -38,6 +49,13 @@
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
#define HCI_EV_LE_CIS_EST 0x19
#define HCI_EV_LE_CREATE_BIG_CPL 0x1b
#define HCI_EV_LE_TERM_BIG_CPL 0x1c
#define HCI_EV_LE_BIG_SYNC_EST 0x1d
#define HCI_EV_LE_BIG_SYNC_LOST 0x1e
#define HCI_EV_LE_REMOVE_ISO_DATA_PATH 0x23
//vendor cmd to fw
#define HCI_VENDOR_ENABLE_PROFILE_REPORT_COMMAND 0xfc18
#define HCI_VENDOR_SET_PROFILE_REPORT_LEGACY_COMMAND 0xfc19
@@ -140,7 +158,11 @@ enum {
profile_hogp = 5,
profile_voice = 6,
profile_sink = 7,
profile_max = 8
profile_lea_src = 8,
profile_opprx = 9,
profile_lea_snk = 10,
profile_a2dpsink = 11,
profile_max = 12
};
#define A2DP_SIGNAL 0x01
@@ -159,7 +181,10 @@ typedef struct {
//profile info for each connection
typedef struct rtl_hci_conn {
struct list_head list;
uint16_t handle;
u16 big_handle;
u16 handle;
u8 direction;
u8 remove_path;
struct delayed_work a2dp_count_work;
struct delayed_work pan_count_work;
struct delayed_work hogp_count_work;
@@ -170,7 +195,7 @@ typedef struct rtl_hci_conn {
uint8_t type; // 0:l2cap, 1:sco/esco, 2:le
uint16_t profile_bitmap;
uint16_t profile_status;
int8_t profile_refcount[8];
int8_t profile_refcount[profile_max];
} rtk_conn_prof, *prtk_conn_prof;
#ifdef RTB_SOFTWARE_MAILBOX
@@ -204,21 +229,40 @@ struct rtl_btinfo_ctl {
};
#endif /* RTB_SOFTWARE_MAILBOX */
#define HCI_PT_CMD 0x01
#define HCI_PT_EVT 0x02
#define HCI_PT_L2SIG_RX 0x03
#define HCI_PT_L2SIG_TX 0x04
#define HCI_PT_L2DATA_RX 0x05
#define HCI_PT_L2DATA_TX 0x06
struct rtl_hci_hdr {
struct list_head list;
u8 type;
u16 len;
};
#define MAX_LEN_OF_HCI_EV 32
#define NUM_RTL_HCI_EV 32
struct rtl_hci_ev {
__u8 data[MAX_LEN_OF_HCI_EV];
__u16 len;
struct list_head list;
u8 type;
u16 len;
/* private */
__u8 data[MAX_LEN_OF_HCI_EV];
};
#define L2_MAX_SUBSEC_LEN 128
#define L2_MAX_PKTS 16
struct rtl_l2_buff {
__u8 data[L2_MAX_SUBSEC_LEN];
__u16 len;
__u16 out;
struct list_head list;
u8 type;
u16 len;
/* private */
__u8 data[L2_MAX_SUBSEC_LEN];
__u16 out;
};
struct rtl_coex_struct {
@@ -236,18 +280,18 @@ struct rtl_coex_struct {
struct delayed_work sock_work;
#endif
struct workqueue_struct *fw_wq;
struct workqueue_struct *timer_wq;
struct delayed_work fw_work;
struct delayed_work l2_work;
struct delayed_work cmd_work;
#ifdef RTB_SOFTWARE_MAILBOX
struct sock *sk;
#endif
struct urb *urb;
spinlock_t spin_lock_sock;
spinlock_t spin_lock_profile;
struct mutex profile_mutex;
struct mutex conn_mutex;
uint16_t profile_bitmap;
uint16_t profile_status;
int8_t profile_refcount[8];
int8_t profile_refcount[profile_max];
uint8_t ispairing;
uint8_t isinquirying;
uint8_t ispaging;
@@ -266,11 +310,8 @@ struct rtl_coex_struct {
uint8_t wifi_on;
uint8_t sock_open;
#endif
unsigned long cmd_last_tx;
/* hci ev buff */
struct list_head ev_used_list;
struct list_head ev_free_list;
unsigned long cmd_last_tx;
spinlock_t rxlock;
__u8 pkt_type;
@@ -279,16 +320,18 @@ struct rtl_coex_struct {
__u16 elen;
__u8 back_buff[HCI_MAX_EVENT_SIZE];
/* l2cap rx buff */
struct list_head l2_used_list;
struct list_head ev_free_list;
struct list_head l2_free_list;
struct list_head hci_pkt_list;
/* buff addr and size */
spinlock_t buff_lock;
unsigned long pages_addr;
unsigned long buff_size;
#define RTL_COEX_RUNNING (1 << 0)
#define RTL_COEX_RUNNING 1
#define RTL_COEX_PKT_COUNTING 2
#define RTL_COEX_CONN_REMOVING 3
unsigned long flags;
};
@@ -363,6 +406,3 @@ void rtk_btcoex_close(void);
void rtk_btcoex_probe(struct hci_dev *hdev);
void rtk_btcoex_init(void);
void rtk_btcoex_exit(void);
#endif /* __RTK_COEX_H__ */

View File

@@ -1,8 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB download firmware driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
@@ -16,8 +30,14 @@
#include <linux/usb.h>
#include <linux/dcache.h>
#include <linux/in.h>
#include <linux/version.h>
#include <net/sock.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
#include <linux/unaligned.h>
#else
#include <asm/unaligned.h>
#endif
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -30,8 +50,7 @@
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/poll.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
#include <linux/pm_runtime.h>
@@ -84,6 +103,7 @@ static struct list_head list_extracfgs;
#define HCI_VENDOR_READ_RTK_ROM_VERISION 0xfc6d
#define HCI_VENDOR_READ_LMP_VERISION 0x1001
#define HCI_VENDOR_READ_CMD 0xfc61
#define HCI_VENDOR_WRITE_CMD 0xfc62
#define ROM_LMP_NONE 0x0000
#define ROM_LMP_8723a 0x1200
@@ -92,6 +112,9 @@ static struct list_head list_extracfgs;
#define ROM_LMP_8761a 0X8761
#define ROM_LMP_8822b 0X8822
#define ROM_LMP_8852a 0x8852
#define ROM_LMP_8851b 0x8851
#define ROM_LMP_8922a 0x8922
#define ROM_LMP_8723c 0x8703
#define PATCH_SNIPPETS 0x01
#define PATCH_DUMMY_HEADER 0x02
@@ -163,41 +186,30 @@ static const uint8_t RTK_EPATCH_SIGNATURE_NEW[8] =
//Extension Section IGNATURE:0x77FD0451
static const uint8_t Extension_Section_SIGNATURE[4] = { 0x51, 0x04, 0xFD, 0x77 };
static uint16_t project_id[] = {
ROM_LMP_8723a,
ROM_LMP_8723b,
ROM_LMP_8821a,
ROM_LMP_8761a,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_8822b,
ROM_LMP_8723b, /* RTL8723DU */
ROM_LMP_8821a, /* RTL8821CU */
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_8822b, /* RTL8822CU */
ROM_LMP_8761a, /* index 14 for 8761BU */
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_8852a, /* index 18 for 8852AU */
ROM_LMP_8723b, /* index 19 for 8723FU */
ROM_LMP_8852a, /* index 20 for 8852BU */
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_8852a, /* index 25 for 8852CU */
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_NONE,
ROM_LMP_8822b, /* index 33 for 8822EU */
static const struct {
__u16 lmp_subver;
__u8 id;
} project_id_to_lmp_subver[] = {
{ ROM_LMP_8723a, 0 },
{ ROM_LMP_8723b, 1 },
{ ROM_LMP_8821a, 2 },
{ ROM_LMP_8761a, 3 },
{ ROM_LMP_8723c, 7 },
{ ROM_LMP_8822b, 8 }, /* 8822B */
{ ROM_LMP_8723b, 9 }, /* 8723D */
{ ROM_LMP_8821a, 10 }, /* 8821C */
{ ROM_LMP_8822b, 13 }, /* 8822C */
{ ROM_LMP_8761a, 14 }, /* 8761B */
{ ROM_LMP_8852a, 18 }, /* 8852A */
{ ROM_LMP_8723b, 19 }, /* 8733B */
{ ROM_LMP_8852a, 20 }, /* 8852B */
{ ROM_LMP_8852a, 25 }, /* 8852C */
{ ROM_LMP_8822b, 33 }, /* 8822E */
{ ROM_LMP_8851b, 36 }, /* 8851B */
{ ROM_LMP_8852a, 42 }, /* 8852D */
{ ROM_LMP_8922a, 44 }, /* 8922A */
{ ROM_LMP_8852a, 47 }, /* 8852BT */
{ ROM_LMP_8761a, 51 }, /* 8761C */
};
enum rtk_endpoit {
@@ -215,10 +227,16 @@ enum rtk_endpoit {
#define RTL8822CU 0x73
#define RTL8761BU 0x74
#define RTL8852AU 0x75
#define RTL8723FU 0x76
#define RTL8733BU 0x76
#define RTL8852BU 0x77
#define RTL8852CU 0x78
#define RTL8822EU 0x79
#define RTL8851BU 0x7A
#define RTL8852DU 0x7B
#define RTL8922AU 0x7C
#define RTL8852BTU 0x7D
#define RTL8761CU 0x80
#define RTL8723CU 0x81
typedef struct {
uint16_t prod_id;
@@ -279,7 +297,7 @@ static uint8_t g_key_id = 0;
static dev_data *dev_data_find(struct usb_interface *intf);
static patch_info *get_patch_entry(struct usb_device *udev);
static int load_firmware(dev_data * dev_entry, uint8_t ** buff);
static int load_firmware(dev_data *dev_entry, xchange_data *xdata);
static void init_xdata(xchange_data * xdata, dev_data * dev_entry);
static int check_fw_version(xchange_data * xdata);
static int download_data(xchange_data * xdata);
@@ -344,6 +362,8 @@ static patch_info fw_patch_table[] = {
{0xb009, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", RTL8723DU}, /* RTL8723DU */
{0x0231, 0x8723, "mp_rtl8723du_fw", "rtl8723du_fw", "rtl8723du_config", RTL8723DU}, /* RTL8723DU for LiteOn */
{0xb703, 0x8703, "mp_rtl8723cu_fw", "rtl8723cu_fw", "rtl8723cu_config", RTL8723CU}, /* RTL8723CU */
{0xb820, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", RTL8821CU}, /* RTL8821CU */
{0xc820, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", RTL8821CU}, /* RTL8821CU */
{0xc821, 0x8821, "mp_rtl8821cu_fw", "rtl8821cu_fw", "rtl8821cu_config", RTL8821CU}, /* RTL8821CE */
@@ -377,6 +397,7 @@ static patch_info fw_patch_table[] = {
{0xc82e, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", RTL8822CU}, /* RTL8822CU */
{0xc81d, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", RTL8822CU}, /* RTL8822CU */
{0xd820, 0x8822, "mp_rtl8821du_fw", "rtl8821du_fw", "rtl8821du_config", RTL8822CU}, /* RTL8821DU */
{0x053b, 0x8822, "mp_rtl8821du_fw", "rtl8821du_fw", "rtl8821du_config", RTL8822CU}, /* RTL8821DU for Epson*/
{0xc822, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", RTL8822CU}, /* RTL8822CE */
{0xc82b, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", RTL8822CU}, /* RTL8822CE */
@@ -405,6 +426,7 @@ static patch_info fw_patch_table[] = {
{0xc03f, 0x8822, "mp_rtl8822cu_fw", "rtl8822cu_fw", "rtl8822cu_config", RTL8822CU}, /* RTL8822CE-VS */
{0x8771, 0x8761, "mp_rtl8761b_fw", "rtl8761bu_fw", "rtl8761bu_config", RTL8761BU}, /* RTL8761BU only */
{0x876e, 0x8761, "mp_rtl8761b_fw", "rtl8761bu_fw", "rtl8761bu_config", RTL8761BU}, /* RTL8761BUE */
{0xa725, 0x8761, "mp_rtl8761b_fw", "rtl8725au_fw", "rtl8725au_config", RTL8761BU}, /* RTL8725AU */
{0xa72A, 0x8761, "mp_rtl8761b_fw", "rtl8725au_fw", "rtl8725au_config", RTL8761BU}, /* RTL8725AU BT only */
@@ -425,14 +447,13 @@ static patch_info fw_patch_table[] = {
{0xc125, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xe852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xb852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xc852, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xc549, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xc127, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0x3565, 0x8852, "mp_rtl8852au_fw", "rtl8852au_fw", "rtl8852au_config", RTL8852AU}, /* RTL8852AE */
{0xb733, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", RTL8723FU}, /* RTL8723FU */
{0xb73a, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", RTL8723FU}, /* RTL8723FU */
{0xf72b, 0x8723, "mp_rtl8723fu_fw", "rtl8723fu_fw", "rtl8723fu_config", RTL8723FU}, /* RTL8723FU */
{0xb733, 0x8723, "mp_rtl8733bu_fw", "rtl8733bu_fw", "rtl8733bu_config", RTL8733BU}, /* RTL8733BU */
{0xb73a, 0x8723, "mp_rtl8733bu_fw", "rtl8733bu_fw", "rtl8733bu_config", RTL8733BU}, /* RTL8733BU */
{0xf72b, 0x8723, "mp_rtl8733bu_fw", "rtl8733bu_fw", "rtl8733bu_config", RTL8733BU}, /* RTL8733BU */
{0x8851, 0x8852, "mp_rtl8851au_fw", "rtl8851au_fw", "rtl8851au_config", RTL8852BU}, /* RTL8851AU */
{0xa85b, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", RTL8852BU}, /* RTL8852BU */
@@ -453,6 +474,7 @@ static patch_info fw_patch_table[] = {
{0x1670, 0x8852, "mp_rtl8852bu_fw", "rtl8852bu_fw", "rtl8852bu_config", RTL8852BU}, /* RTL8852BE */
{0xc85a, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CU */
{0xc85d, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CU */
{0x0852, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0x5852, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0xc85c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
@@ -460,10 +482,29 @@ static patch_info fw_patch_table[] = {
{0x886c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0x887c, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0x4007, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0x1675, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0x3586, 0x8852, "mp_rtl8852cu_fw", "rtl8852cu_fw", "rtl8852cu_config", RTL8852CU}, /* RTL8852CE */
{0xe822, 0x8822, "mp_rtl8822eu_fw", "rtl8822eu_fw", "rtl8822eu_config", RTL8822EU}, /* RTL8822EU */
{0xa82a, 0x8822, "mp_rtl8822eu_fw", "rtl8822eu_fw", "rtl8822eu_config", RTL8822EU}, /* RTL8822EU */
{0xb851, 0x8851, "mp_rtl8851bu_fw", "rtl8851bu_fw", "rtl8851bu_config", RTL8851BU}, /* RTL8851BU */
{0xd85a, 0x8852, "mp_rtl8852du_fw", "rtl8852du_fw", "rtl8852du_config", RTL8852DU}, /* RTL8852DU */
{0x892a, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AU */
{0x8922, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xa890, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xa891, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xa892, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xd922, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xb85f, 0x8922, "mp_rtl8922au_fw", "rtl8922au_fw", "rtl8922au_config", RTL8922AU}, /* RTL8922AE */
{0xc852, 0x8852, "mp_rtl8852btu_fw", "rtl8852btu_fw", "rtl8852btu_config", RTL8852BTU}, /* RTL8852BTU */
{0x8520, 0x8852, "mp_rtl8852btu_fw", "rtl8852btu_fw", "rtl8852btu_config", RTL8852BTU}, /* RTL8852BTE */
{0xc761, 0x8761, "mp_rtl8761cu_fw", "rtl8761cu_mx_fw", "rtl8761cu_mx_config", RTL8761CU}, /* RTL8761CU */
/* NOTE: must append patch entries above the null entry */
{0, 0, NULL, NULL, NULL, 0}
};
@@ -746,6 +787,7 @@ static inline int get_max_patch_size(u8 chip_type)
max_patch_size = 25 * 1024;
break;
case RTL8723DU:
case RTL8723CU:
case RTL8822CU:
case RTL8761BU:
case RTL8821CU:
@@ -754,10 +796,11 @@ static inline int get_max_patch_size(u8 chip_type)
case RTL8852AU:
max_patch_size = 0x114D0 + 529; /* 69.2KB */
break;
case RTL8723FU:
case RTL8733BU:
max_patch_size = 0xC4Cf + 529; /* 49.2KB */
break;
case RTL8852BU:
case RTL8851BU:
max_patch_size = 0x104D0 + 529; /* 65KB */
break;
case RTL8852CU:
@@ -766,6 +809,18 @@ static inline int get_max_patch_size(u8 chip_type)
case RTL8822EU:
max_patch_size = 0x24620 + 529; /* 145KB */
break;
case RTL8852DU:
max_patch_size = 0x20D90 + 529; /* 131KB */
break;
case RTL8922AU:
max_patch_size = 0x23810 + 529; /* 142KB */
break;
case RTL8852BTU:
max_patch_size = 0x27E00 + 529; /* 159.5KB */
break;
case RTL8761CU:
max_patch_size = 1024 * 1024; /* 1MB */
break;
default:
max_patch_size = 40 * 1024;
break;
@@ -774,11 +829,64 @@ static inline int get_max_patch_size(u8 chip_type)
return max_patch_size;
}
static int rtk_vendor_write(dev_data * dev_entry)
{
int ret_val;
xchange_data *xdata = NULL;
unsigned char cmd_buf[] = {0x31, 0x90, 0xd0, 0x29, 0x80, 0x00, 0x00,
0x00, 0x00};
xdata = kzalloc(sizeof(xchange_data), GFP_KERNEL);
if (NULL == xdata) {
ret_val = 0xFE;
RTKBT_DBG("NULL == xdata");
return -1;
}
init_xdata(xdata, dev_entry);
xdata->cmd_hdr->opcode = cpu_to_le16(HCI_VENDOR_WRITE_CMD);
xdata->cmd_hdr->plen = 9;
memcpy(xdata->send_pkt, &(xdata->cmd_hdr->opcode), 2);
memcpy(xdata->send_pkt+2, &(xdata->cmd_hdr->plen), 1);
memcpy(xdata->send_pkt+3, cmd_buf, sizeof(cmd_buf));
xdata->pkt_len = CMD_HDR_LEN + 9;
ret_val = send_hci_cmd(xdata);
if (ret_val < 0) {
RTKBT_ERR("%s: Failed to send HCI command.", __func__);
goto end;
}
ret_val = rcv_hci_evt(xdata);
if (ret_val < 0) {
RTKBT_ERR("%s: Failed to receive HCI event.", __func__);
goto end;
}
ret_val = 0;
end:
if (xdata != NULL) {
if (xdata->send_pkt)
kfree(xdata->send_pkt);
if (xdata->rcv_pkt)
kfree(xdata->rcv_pkt);
kfree(xdata);
}
return ret_val;
}
static int check_fw_chip_ver(dev_data * dev_entry, xchange_data * xdata)
{
int ret_val;
uint16_t chip = 0;
uint16_t chip_ver = 0;
uint16_t lmp_subver, hci_rev;
patch_info *patch_entry;
struct hci_rp_read_local_version *read_ver_rsp;
chip = rtk_vendor_read(dev_entry, READ_CHIP_TYPE);
if(chip == 0x8822) {
@@ -801,9 +909,16 @@ static int check_fw_chip_ver(dev_data * dev_entry, xchange_data * xdata)
gEVersion = rtk_get_eversion(dev_entry);
}
return ret_val;
} else {
patch_entry = xdata->dev_entry->patch_entry;
read_ver_rsp = (struct hci_rp_read_local_version *)(xdata->rsp_para);
lmp_subver = le16_to_cpu(read_ver_rsp->lmp_subver);
hci_rev = le16_to_cpu(read_ver_rsp->hci_rev);
if (lmp_subver == 0x8852 && hci_rev == 0x000d)
ret_val = rtk_vendor_write(dev_entry);
}
return 0;
return ret_val;
}
int download_patch(struct usb_interface *intf)
@@ -836,7 +951,7 @@ int download_patch(struct usb_interface *intf)
if (ret_val != 0 )
goto patch_end;
xdata->fw_len = load_firmware(dev_entry, &xdata->fw_data);
xdata->fw_len = load_firmware(dev_entry, xdata);
if (xdata->fw_len <= 0) {
RTKBT_ERR("load firmware failed!");
ret_val = -1;
@@ -875,7 +990,7 @@ int download_patch(struct usb_interface *intf)
ret_val = 0;
patch_fail:
kfree(fw_buf);
vfree(fw_buf);
patch_end:
if (xdata != NULL) {
if (xdata->send_pkt)
@@ -893,7 +1008,7 @@ patch_end:
* -1: error
* 0: download patch successfully
* >0: patch already exists */
int download_lps_patch(struct usb_interface *intf)
int download_special_patch(struct usb_interface *intf, const char *special_name)
{
dev_data *dev_entry;
patch_info *pinfo;
@@ -935,15 +1050,18 @@ int download_lps_patch(struct usb_interface *intf)
}
goto patch_end;
}
memset(name1, 0, sizeof(name1));
memset(name2, 0, sizeof(name2));
origin_name1 = dev_entry->patch_entry->patch_name;
origin_name2 = dev_entry->patch_entry->config_name;
snprintf(name1, sizeof(name1), "lps_%s", origin_name1);
snprintf(name2, sizeof(name2), "lps_%s", origin_name2);
memcpy(name1, special_name, strlen(special_name));
strncat(name1, origin_name1, sizeof(name1) - 1 - strlen(special_name));
memcpy(name2, special_name, strlen(special_name));
strncat(name2, origin_name2, sizeof(name2) - 1 - strlen(special_name));
dev_entry->patch_entry->patch_name = name1;
dev_entry->patch_entry->config_name = name2;
RTKBT_INFO("Loading %s and %s", name1, name2);
xdata->fw_len = load_firmware(dev_entry, &xdata->fw_data);
xdata->fw_len = load_firmware(dev_entry, xdata);
dev_entry->patch_entry->patch_name = origin_name1;
dev_entry->patch_entry->config_name = origin_name2;
if (xdata->fw_len <= 0) {
@@ -955,11 +1073,13 @@ int download_lps_patch(struct usb_interface *intf)
fw_buf = xdata->fw_data;
pinfo = dev_entry->patch_entry;
/*
if (!pinfo) {
RTKBT_ERR("%s: No patch entry", __func__);
result = -1;
goto patch_fail;
}
*/
max_patch_size = get_max_patch_size(pinfo->chip_type);
if (xdata->fw_len > max_patch_size) {
result = -1;
@@ -998,6 +1118,39 @@ patch_end:
}
#endif
int setup_btrealtek_flag(struct usb_interface *intf, struct hci_dev *hdev)
{
dev_data *dev_entry;
patch_info *pinfo;
int ret_val = 0;
dev_entry = dev_data_find(intf);
if (NULL == dev_entry) {
ret_val = -1;
RTKBT_ERR("%s: NULL == dev_entry", __func__);
return ret_val;
}
pinfo = dev_entry->patch_entry;
if (!pinfo) {
RTKBT_ERR("%s: No patch entry", __func__);
ret_val = -1;
return ret_val;
}
switch (pinfo->chip_type){
case RTL8852CU:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
btrealtek_set_flag(hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP);
#endif
break;
default:
break;
}
return ret_val;
}
#if defined RTKBT_SUSPEND_WAKEUP || defined RTKBT_SHUTDOWN_WAKEUP || defined RTKBT_SWITCH_PATCH
int set_scan(struct usb_interface *intf)
{
@@ -1045,7 +1198,7 @@ end:
dev_data *dev_data_find(struct usb_interface * intf)
{
dev_data *dev_entry;
dev_data *dev_entry = NULL;
list_for_each_entry(dev_entry, &dev_data_list, list_node) {
if (dev_entry->intf == intf) {
@@ -1088,6 +1241,7 @@ static int is_mac(u8 chip_type, u16 offset)
switch (chip_type) {
case RTL8822BU:
case RTL8723DU:
case RTL8723CU:
case RTL8821CU:
if (offset == 0x0044)
return 1;
@@ -1095,10 +1249,15 @@ static int is_mac(u8 chip_type, u16 offset)
case RTL8822CU:
case RTL8761BU:
case RTL8852AU:
case RTL8723FU:
case RTL8733BU:
case RTL8852BU:
case RTL8852CU:
case RTL8822EU:
case RTL8851BU:
case RTL8852DU:
case RTL8922AU:
case RTL8852BTU:
case RTL8761CU:
if (offset == 0x0030)
return 1;
break;
@@ -1116,15 +1275,21 @@ static uint16_t get_mac_offset(u8 chip_type)
switch (chip_type) {
case RTL8822BU:
case RTL8723DU:
case RTL8723CU:
case RTL8821CU:
return 0x0044;
case RTL8822CU:
case RTL8761BU:
case RTL8852AU:
case RTL8723FU:
case RTL8733BU:
case RTL8852BU:
case RTL8852CU:
case RTL8822EU:
case RTL8851BU:
case RTL8852DU:
case RTL8922AU:
case RTL8852BTU:
case RTL8761CU:
return 0x0030;
case RTLPREVIOUS:
return 0x003c;
@@ -1452,14 +1617,12 @@ static uint8_t *rtb_get_patch_header(int *len,
}
break;
default:
RTKBT_ERR("Wrong Opcode");
goto wrong_opcode;
RTKBT_INFO("Unknown Opcode. Ignore");
}
section_pos += (SECTION_HEADER_SIZE + section_hdr.section_len);
}
*len = patch_len;
wrong_opcode:
return NULL;
}
@@ -1743,7 +1906,7 @@ static int rtk_vendor_read(dev_data * dev_entry, uint8_t class)
xchange_data *xdata = NULL;
unsigned char cmd_ct_buf[] = {0x10, 0x38, 0x04, 0x28, 0x80};
unsigned char cmd_cv_buf[] = {0x10, 0x3A, 0x04, 0x28, 0x80};
unsigned char cmd_sec_buf[] = {0x10, 0xA4, 0x0D, 0x00, 0xb0};
unsigned char cmd_sec_buf[] = {0x10, 0xA4, 0xAD, 0x00, 0xb0};
xdata = kzalloc(sizeof(xchange_data), GFP_KERNEL);
if (NULL == xdata) {
@@ -1811,7 +1974,6 @@ static int rtk_vendor_read(dev_data * dev_entry, uint8_t class)
}
}
read_end:
if (xdata != NULL) {
if (xdata->send_pkt)
@@ -1823,7 +1985,57 @@ read_end:
return ret_val;
}
int load_firmware(dev_data * dev_entry, uint8_t ** buff)
static int needs_hci_upgrade(xchange_data *xdata, u8 *buf, u32 buf_len)
{
struct {
u8 status;
u8 subopcode;
u8 ota;
} __attribute__((packed)) *evt_params;
#define UPG_DL_BLOCK_SIZE 128
#define UPG_SUBCMD_CODE 0x01
u8 len = UPG_DL_BLOCK_SIZE;
u8 *cmd_params;
int ret;
cmd_params = xdata->req_para;
evt_params = (void *)xdata->rsp_para;
xdata->cmd_hdr->opcode = cpu_to_le16(0xfdbb);
if (buf_len < len)
len = buf_len;
xdata->cmd_hdr->plen = 1 + len;
xdata->pkt_len = sizeof(*xdata->cmd_hdr) + xdata->cmd_hdr->plen;
*cmd_params++ = UPG_SUBCMD_CODE;
memcpy(cmd_params, buf, len);
ret = send_hci_cmd(xdata);
if (ret < 0)
return ret;
ret = rcv_hci_evt(xdata);
if (ret < 0)
return ret;
if (evt_params->status) {
RTKBT_ERR("needs_hci_upgrade: status %02x", evt_params->status);
return -1;
}
if (evt_params->subopcode != UPG_SUBCMD_CODE) {
RTKBT_ERR("needs_hci_upgrade: return subopcode %02x",
evt_params->subopcode);
return -2;
}
RTKBT_INFO("needs_hci_upgrade: state %02x", evt_params->ota);
return evt_params->ota;
}
/* buff: points to the allocated buffer that stores extracted fw and config
* This function returns the total length of extracted fw and config
*/
int load_firmware(dev_data *dev_entry, xchange_data *xdata)
{
const struct firmware *fw;
struct usb_device *udev;
@@ -1835,12 +2047,13 @@ int load_firmware(dev_data * dev_entry, uint8_t ** buff)
uint8_t need_download_fw = 1;
uint16_t lmp_version;
struct rtk_epatch_entry current_entry = { 0 };
struct list_head *pos, *next;
struct patch_node *tmp;
struct patch_node patch_node_hdr;
int i;
RTKBT_DBG("load_firmware start");
udev = dev_entry->udev;
patch_entry = dev_entry->patch_entry;
lmp_version = patch_entry->lmp_sub;
@@ -1853,16 +2066,13 @@ int load_firmware(dev_data * dev_entry, uint8_t ** buff)
ret_val = request_firmware(&fw, fw_name, &udev->dev);
if (ret_val < 0) {
RTKBT_ERR("request_firmware error");
fw_len = 0;
kfree(config_file_buf);
config_file_buf = NULL;
goto fw_fail;
}
INIT_LIST_HEAD(&patch_node_hdr.list);
epatch_buf = kzalloc(fw->size, GFP_KERNEL);
if (NULL == epatch_buf)
epatch_buf = vzalloc(fw->size);
if (!epatch_buf)
goto alloc_fail;
memcpy(epatch_buf, fw->data, fw->size);
@@ -1874,137 +2084,174 @@ int load_firmware(dev_data * dev_entry, uint8_t ** buff)
if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) == 0) {
RTKBT_ERR("8723a Check signature error!");
need_download_fw = 0;
} else {
if (!(buf = kzalloc(buf_len, GFP_KERNEL))) {
RTKBT_ERR("Can't alloc memory for fw&config");
buf_len = -1;
} else {
RTKBT_DBG("8723a, fw copy direct");
memcpy(buf, epatch_buf, fw->size);
if (config_len) {
memcpy(&buf[buf_len - config_len],
config_file_buf, config_len);
}
}
goto sign_err;
}
} else {
RTKBT_ERR("This is not 8723a, use new patch style!");
/* Get version from ROM */
gEVersion = rtk_get_eversion(dev_entry);
RTKBT_DBG("%s: New gEVersion %d", __func__, gEVersion);
if (gEVersion == 0xFE) {
RTKBT_ERR("%s: Read ROM version failure", __func__);
need_download_fw = 0;
fw_len = 0;
goto alloc_fail;
buf = vzalloc(buf_len);
if (!buf) {
RTKBT_ERR("Can't alloc memory for fw&config");
buf_len = -1;
goto alloc_buf_err;
}
/* check Signature and Extension Section Field */
if (((memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) != 0) && (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE_NEW, 8) != 0))||
memcmp(epatch_buf + buf_len - config_len - 4,
Extension_Section_SIGNATURE, 4) != 0) {
RTKBT_ERR("Check SIGNATURE error! do not download fw");
need_download_fw = 0;
} else {
proj_id =
rtk_get_fw_project_id(epatch_buf + buf_len -
config_len - 5);
RTKBT_DBG("8723a, fw copy direct");
memcpy(buf, epatch_buf, fw->size);
if (config_len)
memcpy(&buf[buf_len - config_len], config_file_buf,
config_len);
if (lmp_version != project_id[proj_id]) {
RTKBT_ERR
("lmp_version is %x, project_id is %x, does not match!!!",
lmp_version, project_id[proj_id]);
need_download_fw = 0;
} else {
RTKBT_DBG
("lmp_version is %x, project_id is %x, match!",
lmp_version, project_id[proj_id]);
goto done;
}
if(memcmp(epatch_buf, RTK_EPATCH_SIGNATURE_NEW, 8) == 0) {
int key_id = rtk_vendor_read(dev_entry, READ_SEC_PROJ);
RTKBT_DBG("%s: key id %d", __func__, key_id);
if (key_id < 0) {
RTKBT_ERR("%s: Read key id failure", __func__);
need_download_fw = 0;
fw_len = 0;
goto alloc_fail;
}
rtb_get_patch_header(&buf_len, &patch_node_hdr, epatch_buf, key_id);
if(buf_len == 0)
goto alloc_fail;
RTKBT_DBG("buf_len = 0x%x", buf_len);
buf_len += config_len;
} else {
rtk_get_patch_entry(epatch_buf, &current_entry);
RTKBT_ERR("This is not 8723a, use new patch style!");
if (current_entry.patch_length == 0)
goto alloc_fail;
/* Get version from ROM */
gEVersion = rtk_get_eversion(dev_entry);
RTKBT_DBG("%s: New gEVersion %d", __func__, gEVersion);
if (gEVersion == 0xFE) {
RTKBT_ERR("%s: Read ROM version failure", __func__);
need_download_fw = 0;
goto alloc_fail;
}
buf_len = current_entry.patch_length + config_len;
RTKBT_DBG("buf_len = 0x%x", buf_len);
}
/* check Signature and Extension Section Field */
if ((memcmp(epatch_buf, RTK_EPATCH_SIGNATURE, 8) &&
memcmp(epatch_buf, RTK_EPATCH_SIGNATURE_NEW, 8)) ||
memcmp(epatch_buf + buf_len - config_len - 4,
Extension_Section_SIGNATURE, 4) != 0) {
RTKBT_ERR("Check SIGNATURE error! do not download fw");
need_download_fw = 0;
goto sign_err;
}
if (!(buf = kzalloc(buf_len, GFP_KERNEL))) {
RTKBT_ERR
("Can't alloc memory for multi fw&config");
buf_len = -1;
} else {
if(memcmp(epatch_buf, RTK_EPATCH_SIGNATURE_NEW, 8) == 0) {
int tmp_len = 0;
list_for_each_safe(pos, next, &patch_node_hdr.list)
{
tmp = list_entry(pos, struct patch_node, list);
RTKBT_DBG("len = 0x%x", tmp->len);
memcpy(buf + tmp_len, tmp->payload, tmp->len);
tmp_len += tmp->len;
list_del_init(pos);
kfree(tmp);
}
if (config_len) {
memcpy(&buf
[buf_len - config_len],
config_file_buf,
config_len);
}
} else {
memcpy(buf,
epatch_buf +
current_entry.start_offset,
current_entry.patch_length);
memcpy(buf + current_entry.patch_length - 4, epatch_buf + 8, 4); /*fw version */
if (config_len) {
memcpy(&buf
[buf_len - config_len],
config_file_buf,
config_len);
}
}
}
}
proj_id = rtk_get_fw_project_id(epatch_buf + buf_len - config_len - 5);
for (i = 0; i < ARRAY_SIZE(project_id_to_lmp_subver); i++) {
if (proj_id == project_id_to_lmp_subver[i].id &&
lmp_version == project_id_to_lmp_subver[i].lmp_subver) {
break;
}
}
if (i >= ARRAY_SIZE(project_id_to_lmp_subver)) {
RTKBT_ERR("lmp_version %04x, project_id %u, does not match!!!",
lmp_version, proj_id);
need_download_fw = 0;
goto proj_id_err;
}
RTKBT_DBG("lmp_version is %04x, project_id is %u, match!",
lmp_version, proj_id);
if (memcmp(epatch_buf, RTK_EPATCH_SIGNATURE_NEW, 8) == 0) {
int key_id = rtk_vendor_read(dev_entry, READ_SEC_PROJ);
int tmp_len = 0;
RTKBT_DBG("%s: key id %d", __func__, key_id);
if (key_id < 0) {
RTKBT_ERR("%s: Read key id failure", __func__);
need_download_fw = 0;
fw_len = 0;
goto extract_err;
}
rtb_get_patch_header(&buf_len, &patch_node_hdr, epatch_buf,
key_id);
if (!buf_len)
goto extract_err;
RTKBT_DBG("buf_len = 0x%x", buf_len);
buf_len += config_len;
buf = vzalloc(buf_len);
if (!buf) {
RTKBT_ERR("Can't alloc memory for multi fw&config");
buf_len = -1;
goto alloc_buf_err;
}
list_for_each_safe(pos, next, &patch_node_hdr.list) {
tmp = list_entry(pos, struct patch_node, list);
RTKBT_DBG("len = 0x%x", tmp->len);
memcpy(buf + tmp_len, tmp->payload, tmp->len);
tmp_len += tmp->len;
list_del_init(pos);
kfree(tmp);
}
if (config_len)
memcpy(&buf[buf_len - config_len], config_file_buf,
config_len);
} else {
rtk_get_patch_entry(epatch_buf, &current_entry);
if (current_entry.patch_length == 0)
goto extract_err;
buf_len = current_entry.patch_length + config_len;
RTKBT_DBG("buf_len = 0x%x", buf_len);
buf = vzalloc(buf_len);
if (!buf) {
RTKBT_ERR("Can't alloc memory for multi fw&config");
buf_len = -1;
goto alloc_buf_err;
}
memcpy(buf, epatch_buf + current_entry.start_offset,
current_entry.patch_length);
/* Copy fw version */
memcpy(buf + current_entry.patch_length - 4, epatch_buf + 8, 4);
if (config_len)
memcpy(&buf[buf_len - config_len], config_file_buf,
config_len);
}
if (patch_entry->chip_type == RTL8761CU) {
if (needs_hci_upgrade(xdata, buf, buf_len) <= 0) {
if (config_len > 0) {
memmove(buf, buf + buf_len - config_len,
config_len);
buf_len = config_len;
} else {
#define FAKE_SEG_LEN 16
if (buf_len > FAKE_SEG_LEN)
buf_len = FAKE_SEG_LEN;
memset(buf, 0, buf_len);
}
} else {
/* It does not need to download config when upgrading */
buf_len -= config_len;
}
}
done:
RTKBT_DBG("fw:%s exists, config file:%s exists",
(buf_len > 0) ? "" : "not", (config_len > 0) ? "" : "not");
if (buf && (buf_len > 0) && (need_download_fw)) {
buf_len > 0 ? "" : "not", config_len > 0 ? "" : "not");
if (buf && buf_len > 0 && need_download_fw) {
fw_len = buf_len;
*buff = buf;
xdata->fw_data = buf;
}
RTKBT_DBG("load_firmware done");
alloc_buf_err:
extract_err:
/* Make sure all the patch nodes freed */
list_for_each_safe(pos, next, &patch_node_hdr.list) {
tmp = list_entry(pos, struct patch_node, list);
list_del_init(pos);
kfree(tmp);
}
proj_id_err:
sign_err:
alloc_fail:
release_firmware(fw);
if (epatch_buf)
kfree(epatch_buf);
vfree(epatch_buf);
fw_fail:
if (config_file_buf)
kfree(config_file_buf);
fw_fail:
if (fw_len == 0)
kfree(buf);
vfree(buf);
return fw_len;
}
@@ -2149,7 +2396,7 @@ int download_data(xchange_data * xdata)
uint8_t *pcur;
int pkt_len, frag_num, frag_len;
int i, ret_val;
int j;
int j = 0;
RTKBT_DBG("download_data start");
@@ -2161,12 +2408,11 @@ int download_data(xchange_data * xdata)
frag_len = PATCH_SEG_MAX;
for (i = 0; i < frag_num; i++) {
if (i > 0x7f)
j = (i & 0x7f) + 1;
else
j = i;
cmd_para->index = j++;
if(cmd_para->index == 0x7f)
j = 1;
cmd_para->index = j;
if (i == (frag_num - 1)) {
cmd_para->index |= DATA_END;
frag_len = xdata->fw_len % PATCH_SEG_MAX;

View File

@@ -1,11 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB download firmware driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef __RTK_MISC_H__
#define __RTK_MISC_H__
#include <linux/kernel.h>
#include <linux/module.h>
@@ -14,6 +26,8 @@
#include <linux/usb.h>
#include <linux/suspend.h>
#define CONFIG_BTUSB_AUTOSUSPEND 0
/* Download LPS patch when host suspends or power off
* LPS patch name: lps_rtl8xxx_fw
* LPS config name: lps_rtl8xxx_config
@@ -45,7 +59,9 @@
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 33)
#define USB_RPM
#define USB_RPM 1
#else
#define USB_RPM 0
#endif
#define CONFIG_NEEDS_BINDING
@@ -56,7 +72,7 @@
#endif
/* USB SS */
#if (defined CONFIG_BTUSB_AUTOSUSPEND) && (defined USB_RPM)
#if (CONFIG_BTUSB_AUTOSUSPEND && USB_RPM)
#define BTUSB_RPM
#endif
@@ -82,12 +98,41 @@ struct api_context {
int status;
};
int download_lps_patch(struct usb_interface *intf);
int download_special_patch(struct usb_interface *intf, const char *special_name);
#endif
int setup_btrealtek_flag(struct usb_interface *intf, struct hci_dev *hdev);
enum {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
REALTEK_ALT6_CONTINUOUS_TX_CHIP,
#endif
__REALTEK_NUM_FLAGS,
};
struct btrealtek_data {
DECLARE_BITMAP(flags, __REALTEK_NUM_FLAGS);
};
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0)
static inline void *hci_get_priv(struct hci_dev *hdev)
{
return (char *)hdev + sizeof(*hdev);
}
#endif
#define btrealtek_set_flag(hdev, nr) \
do { \
struct btrealtek_data *realtek = hci_get_priv((hdev)); \
set_bit((nr), realtek->flags); \
} while (0)
#define btrealtek_get_flag(hdev) \
(((struct btrealtek_data *)hci_get_priv(hdev))->flags)
#define btrealtek_test_flag(hdev, nr) test_bit((nr), btrealtek_get_flag(hdev))
#if defined RTKBT_SUSPEND_WAKEUP || defined RTKBT_SHUTDOWN_WAKEUP || defined RTKBT_SWITCH_PATCH
int set_scan(struct usb_interface *intf);
#endif
#endif /* __RTK_MISC_H__ */

View File

@@ -1,10 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
*
* Module to force cpuidle states through debugfs files.
*
*/
#include <nvidia/conftest.h>
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
@@ -26,9 +26,16 @@ static void suspend_all_device_irqs(void)
{
struct irq_data *data;
struct irq_desc *desc;
unsigned int nirqs;
int irq;
for (irq = 0, data = irq_get_irq_data(irq); irq < nr_irqs;
#if defined(NV_IRQ_GET_NR_IRQS_PRESENT) /* Linux v6.13 */
nirqs = irq_get_nr_irqs();
#else
nirqs = nr_irqs;
#endif
for (irq = 0, data = irq_get_irq_data(irq); irq < nirqs;
irq++, data = irq_get_irq_data(irq)) {
if (!data)
continue;
@@ -44,9 +51,16 @@ static void resume_all_device_irqs(void)
{
struct irq_data *data;
struct irq_desc *desc;
unsigned int nirqs;
int irq;
for (irq = 0, data = irq_get_irq_data(irq); irq < nr_irqs;
#if defined(NV_IRQ_GET_NR_IRQS_PRESENT)
nirqs = irq_get_nr_irqs();
#else
nirqs = nr_irqs;
#endif
for (irq = 0, data = irq_get_irq_data(irq); irq < nirqs;
irq++, data = irq_get_irq_data(irq)) {
if (!data)
continue;

View File

@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/cpu_cooling.h>
#include <linux/cpuidle.h>
@@ -226,9 +228,21 @@ static const struct of_device_id tegra_auto_cpuidle_of[] = {
{ },
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_auto_cpuidle_remove_wrapper(struct platform_device *pdev)
{
tegra_auto_cpuidle_remove(pdev);
}
#else
static int tegra_auto_cpuidle_remove_wrapper(struct platform_device *pdev)
{
return tegra_auto_cpuidle_remove(pdev);
}
#endif
static struct platform_driver tegra_auto_cpuidle_driver __refdata = {
.probe = tegra_auto_cpuidle_probe,
.remove = tegra_auto_cpuidle_remove,
.remove = tegra_auto_cpuidle_remove_wrapper,
.driver = {
.owner = THIS_MODULE,
.name = "cpuidle_tegra_auto",

View File

@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Copyright (c) 2019-2024, NVIDIA Corporation. All Rights Reserved.
*
* Cryptographic API.
*/
#include <nvidia/conftest.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
@@ -5209,9 +5210,21 @@ static const struct dev_pm_ops tegra_hv_pm_ops = {
};
#endif /* CONFIG_PM */
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_hv_vse_safety_remove_wrapper(struct platform_device *pdev)
{
tegra_hv_vse_safety_remove(pdev);
}
#else
static int tegra_hv_vse_safety_remove_wrapper(struct platform_device *pdev)
{
return tegra_hv_vse_safety_remove(pdev);
}
#endif
static struct platform_driver tegra_hv_vse_safety_driver = {
.probe = tegra_hv_vse_safety_probe,
.remove = tegra_hv_vse_safety_remove,
.remove = tegra_hv_vse_safety_remove_wrapper,
.shutdown = tegra_hv_vse_safety_shutdown,
.driver = {
.name = "tegra_hv_vse_safety",

View File

@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* Support for Tegra NVRNG Engine Error Handling.
*/
#include <nvidia/conftest.h>
#include <asm/io.h>
#include <linux/acpi.h>
#include <linux/clk.h>
@@ -357,9 +359,21 @@ static const struct of_device_id tegra_se_nvrng_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_se_nvrng_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_se_nvrng_remove_wrapper(struct platform_device *pdev)
{
tegra_se_nvrng_remove(pdev);
}
#else
static int tegra_se_nvrng_remove_wrapper(struct platform_device *pdev)
{
return tegra_se_nvrng_remove(pdev);
}
#endif
static struct platform_driver tegra_se_nvrng_driver = {
.probe = tegra_se_nvrng_probe,
.remove = tegra_se_nvrng_remove,
.remove = tegra_se_nvrng_remove_wrapper,
.driver = {
.name = "tegra-se-nvrng",
.owner = THIS_MODULE,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver to handle block cipher algorithms using NVIDIA Security Engine.
*/
@@ -25,7 +25,7 @@
#include "tegra-se.h"
struct tegra_aes_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
struct crypto_engine_ctx enginectx;
#endif
struct tegra_se *se;
@@ -33,6 +33,9 @@ struct tegra_aes_ctx {
u32 ivsize;
u32 key1_id;
u32 key2_id;
u32 keylen;
u8 key1[AES_MAX_KEY_SIZE];
u8 key2[AES_MAX_KEY_SIZE];
};
struct tegra_aes_reqctx {
@@ -42,10 +45,12 @@ struct tegra_aes_reqctx {
u32 crypto_config;
u32 len;
u32 *iv;
u32 keylen;
u8 key[AES_MAX_KEY_SIZE];
};
struct tegra_aead_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
struct crypto_engine_ctx enginectx;
#endif
struct tegra_se *se;
@@ -53,6 +58,7 @@ struct tegra_aead_ctx {
u32 alg;
u32 keylen;
u32 key_id;
u8 key[AES_MAX_KEY_SIZE];
};
struct tegra_aead_reqctx {
@@ -64,20 +70,22 @@ struct tegra_aead_reqctx {
unsigned int cryptlen;
unsigned int authsize;
bool encrypt;
u32 config;
u32 crypto_config;
u32 config;
u32 key_id;
u32 iv[4];
u8 authdata[16];
};
struct tegra_cmac_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
struct crypto_engine_ctx enginectx;
#endif
struct tegra_se *se;
unsigned int alg;
u32 key_id;
u32 keylen;
u8 key[AES_MAX_KEY_SIZE];
struct crypto_shash *fallback_tfm;
};
@@ -92,6 +100,8 @@ struct tegra_cmac_reqctx {
u32 config;
u32 key_id;
u32 *iv;
u32 keylen;
u8 key[AES_MAX_KEY_SIZE];
u32 result[CMAC_RESULT_REG_COUNT];
};
@@ -269,7 +279,7 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
struct tegra_aes_reqctx *rctx = skcipher_request_ctx(req);
struct tegra_se *se = ctx->se;
unsigned int cmdlen;
unsigned int cmdlen, key1_id, key2_id;
int ret;
/* Set buffer size as a multiple of AES_BLOCK_SIZE*/
@@ -279,8 +289,10 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
if (!rctx->datbuf.buf)
return -ENOMEM;
rctx->iv = (u32 *)req->iv;
rctx->iv = (ctx->alg == SE_ALG_ECB) ? NULL : (u32 *)req->iv;
rctx->len = req->cryptlen;
key1_id = ctx->key1_id;
key2_id = ctx->key2_id;
/* Pad input to AES Block size */
if (ctx->alg != SE_ALG_XTS) {
@@ -290,18 +302,48 @@ static int tegra_aes_do_one_req(struct crypto_engine *engine, void *areq)
scatterwalk_map_and_copy(rctx->datbuf.buf, req->src, 0, req->cryptlen, 0);
rctx->config = tegra234_aes_cfg(ctx->alg, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, rctx->encrypt);
if (!key1_id) {
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key1,
ctx->keylen, ctx->alg, &key1_id);
if (ret)
goto out;
}
rctx->crypto_config |= SE_AES_KEY_INDEX(key1_id);
if (ctx->alg == SE_ALG_XTS) {
if (!key2_id) {
ret = tegra_key_submit_reserved_xts(ctx->se, ctx->key2,
ctx->keylen, ctx->alg, &key2_id);
if (ret)
goto out;
}
rctx->crypto_config |= SE_AES_KEY2_INDEX(key2_id);
}
/* Prepare the command and submit for execution */
cmdlen = tegra_aes_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
/* Copy the result */
tegra_aes_update_iv(req, ctx);
scatterwalk_map_and_copy(rctx->datbuf.buf, req->dst, 0, req->cryptlen, 1);
out:
/* Free the buffer */
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
if (tegra_key_is_reserved(key1_id))
tegra_key_invalidate_reserved(ctx->se, key1_id, ctx->alg);
if (tegra_key_is_reserved(key2_id))
tegra_key_invalidate_reserved(ctx->se, key2_id, ctx->alg);
crypto_finalize_skcipher_request(se->engine, req, ret);
return 0;
@@ -315,7 +357,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm)
const char *algname;
int ret;
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
se_alg = container_of(alg, struct tegra_se_alg, alg.skcipher.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.skcipher);
@@ -327,6 +369,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm)
ctx->se = se_alg->se_dev;
ctx->key1_id = 0;
ctx->key2_id = 0;
ctx->keylen = 0;
algname = crypto_tfm_alg_name(&tfm->base);
ret = se_algname_to_algid(algname);
@@ -337,7 +380,7 @@ static int tegra_aes_cra_init(struct crypto_skcipher *tfm)
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_aes_do_one_req;
@@ -361,13 +404,20 @@ static int tegra_aes_setkey(struct crypto_skcipher *tfm,
const u8 *key, u32 keylen)
{
struct tegra_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key1_id);
if (ret) {
ctx->keylen = keylen;
memcpy(ctx->key1, key, keylen);
}
return 0;
}
static int tegra_xts_setkey(struct crypto_skcipher *tfm,
@@ -385,11 +435,17 @@ static int tegra_xts_setkey(struct crypto_skcipher *tfm,
ret = tegra_key_submit(ctx->se, key, len,
ctx->alg, &ctx->key1_id);
if (ret)
return ret;
if (ret) {
ctx->keylen = len;
memcpy(ctx->key1, key, len);
}
return tegra_key_submit(ctx->se, key + len, len,
ret = tegra_key_submit(ctx->se, key + len, len,
ctx->alg, &ctx->key2_id);
if (ret) {
ctx->keylen = len;
memcpy(ctx->key2, key + len, len);
}
return 0;
}
@@ -460,12 +516,6 @@ static int tegra_aes_crypt(struct skcipher_request *req, bool encrypt)
return 0;
rctx->encrypt = encrypt;
rctx->config = tegra234_aes_cfg(ctx->alg, encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(ctx->alg, encrypt);
rctx->crypto_config |= SE_AES_KEY_INDEX(ctx->key1_id);
if (ctx->key2_id)
rctx->crypto_config |= SE_AES_KEY2_INDEX(ctx->key2_id);
return crypto_transfer_skcipher_request_to_engine(ctx->se->engine, req);
}
@@ -483,7 +533,7 @@ static int tegra_aes_decrypt(struct skcipher_request *req)
static struct tegra_se_alg tegra_aes_algs[] = {
{
.alg.skcipher = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_aes_cra_init,
@@ -504,14 +554,14 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_aes_do_one_req,
#endif
}
}, {
.alg.skcipher = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_aes_cra_init,
@@ -531,14 +581,14 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_aes_do_one_req,
#endif
}
}, {
.alg.skcipher = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_aes_cra_init,
@@ -559,14 +609,14 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_aes_do_one_req,
#endif
}
}, {
.alg.skcipher = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_aes_cra_init,
@@ -586,7 +636,7 @@ static struct tegra_se_alg tegra_aes_algs[] = {
.cra_alignmask = (__alignof__(u64) - 1),
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_aes_do_one_req,
#endif
@@ -751,11 +801,11 @@ static int tegra_gcm_do_gmac(struct tegra_aead_ctx *ctx, struct tegra_aead_reqct
rctx->config = tegra234_aes_cfg(SE_ALG_GMAC, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GMAC, rctx->encrypt) |
SE_AES_KEY_INDEX(ctx->key_id);
SE_AES_KEY_INDEX(rctx->key_id);
cmdlen = tegra_gmac_prep_cmd(se, rctx);
return tegra_se_host1x_submit(se, cmdlen);
return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
}
static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx *rctx)
@@ -772,7 +822,7 @@ static int tegra_gcm_do_crypt(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
/* Prepare command and submit */
cmdlen = tegra_gcm_crypt_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -791,11 +841,11 @@ static int tegra_gcm_do_final(struct tegra_aead_ctx *ctx, struct tegra_aead_reqc
rctx->config = tegra234_aes_cfg(SE_ALG_GCM_FINAL, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_GCM_FINAL, rctx->encrypt) |
SE_AES_KEY_INDEX(ctx->key_id);
SE_AES_KEY_INDEX(rctx->key_id);
/* Prepare command and submit */
cmdlen = tegra_gcm_prep_final_cmd(se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -918,12 +968,12 @@ static int tegra_ccm_do_cbcmac(struct tegra_aead_ctx *ctx, struct tegra_aead_req
rctx->config = tegra234_aes_cfg(SE_ALG_CBC_MAC, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CBC_MAC,
rctx->encrypt) |
SE_AES_KEY_INDEX(ctx->key_id);
SE_AES_KEY_INDEX(rctx->key_id);
/* Prepare command and submit */
cmdlen = tegra_cbcmac_prep_cmd(se, rctx);
return tegra_se_host1x_submit(se, cmdlen);
return tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
}
static int tegra_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize)
@@ -1105,7 +1155,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx
rctx->config = tegra234_aes_cfg(SE_ALG_CTR, rctx->encrypt);
rctx->crypto_config = tegra234_aes_crypto_cfg(SE_ALG_CTR, rctx->encrypt) |
SE_AES_KEY_INDEX(ctx->key_id);
SE_AES_KEY_INDEX(rctx->key_id);
/* Copy authdata in the top of buffer for encryption/decryption */
if (rctx->encrypt)
@@ -1130,7 +1180,7 @@ static int tegra_ccm_do_ctr(struct tegra_aead_ctx *ctx, struct tegra_aead_reqctx
/* Prepare command and submit */
cmdlen = tegra_ctr_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
if (ret)
return ret;
@@ -1175,6 +1225,7 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
rctx->dst_sg = req->dst;
rctx->assoclen = req->assoclen;
rctx->authsize = crypto_aead_authsize(tfm);
rctx->key_id = ctx->key_id;
if (rctx->encrypt)
rctx->cryptlen = req->cryptlen;
@@ -1200,6 +1251,13 @@ static int tegra_ccm_do_one_req(struct crypto_engine *engine, void *areq)
if (ret)
goto out;
if (!ctx->key_id) {
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
ctx->keylen, ctx->alg, &rctx->key_id);
if (ret)
goto out;
}
if (rctx->encrypt) {
/* CBC MAC Operation */
@@ -1231,6 +1289,9 @@ outbuf_err:
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
if (tegra_key_is_reserved(rctx->key_id))
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
@@ -1248,6 +1309,7 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
rctx->dst_sg = req->dst;
rctx->assoclen = req->assoclen;
rctx->authsize = crypto_aead_authsize(tfm);
rctx->key_id = ctx->key_id;
if (rctx->encrypt)
rctx->cryptlen = req->cryptlen;
@@ -1273,6 +1335,13 @@ static int tegra_gcm_do_one_req(struct crypto_engine *engine, void *areq)
memcpy(rctx->iv, req->iv, GCM_AES_IV_SIZE);
rctx->iv[3] = (1 << 24);
if (!ctx->key_id) {
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
ctx->keylen, ctx->alg, &rctx->key_id);
if (ret)
goto out;
}
/* If there is associated data perform GMAC operation */
if (rctx->assoclen) {
ret = tegra_gcm_do_gmac(ctx, rctx);
@@ -1303,7 +1372,9 @@ outbuf_err:
dma_free_coherent(ctx->se->dev, rctx->inbuf.size,
rctx->inbuf.buf, rctx->inbuf.addr);
/* Finalize the request if there are no errors */
if (tegra_key_is_reserved(rctx->key_id))
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
crypto_finalize_aead_request(ctx->se->engine, req, ret);
return 0;
@@ -1319,7 +1390,7 @@ static int tegra_ccm_cra_init(struct crypto_aead *tfm)
algname = crypto_tfm_alg_name(&tfm->base);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
se_alg = container_of(alg, struct tegra_se_alg, alg.aead.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.aead);
@@ -1329,6 +1400,7 @@ static int tegra_ccm_cra_init(struct crypto_aead *tfm)
ctx->se = se_alg->se_dev;
ctx->key_id = 0;
ctx->keylen = 0;
ret = se_algname_to_algid(algname);
if (ret < 0) {
@@ -1338,7 +1410,7 @@ static int tegra_ccm_cra_init(struct crypto_aead *tfm)
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_ccm_do_one_req;
@@ -1357,7 +1429,7 @@ static int tegra_gcm_cra_init(struct crypto_aead *tfm)
algname = crypto_tfm_alg_name(&tfm->base);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
se_alg = container_of(alg, struct tegra_se_alg, alg.aead.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.aead);
@@ -1367,6 +1439,7 @@ static int tegra_gcm_cra_init(struct crypto_aead *tfm)
ctx->se = se_alg->se_dev;
ctx->key_id = 0;
ctx->keylen = 0;
ret = se_algname_to_algid(algname);
if (ret < 0) {
@@ -1376,7 +1449,7 @@ static int tegra_gcm_cra_init(struct crypto_aead *tfm)
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_gcm_do_one_req;
@@ -1453,13 +1526,20 @@ static int tegra_aead_setkey(struct crypto_aead *tfm,
const u8 *key, u32 keylen)
{
struct tegra_aead_ctx *ctx = crypto_aead_ctx(tfm);
int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
return -EINVAL;
}
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
if (ret) {
ctx->keylen = keylen;
memcpy(ctx->key, key, keylen);
}
return 0;
}
static unsigned int tegra_cmac_prep_cmd(struct tegra_se *se, struct tegra_cmac_reqctx *rctx)
@@ -1558,7 +1638,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
rctx->datbuf.size = (req->nbytes + rctx->residue.size) - nresidue;
rctx->total_len += rctx->datbuf.size;
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
rctx->crypto_config = SE_AES_KEY_INDEX(ctx->key_id);
rctx->crypto_config = SE_AES_KEY_INDEX(rctx->key_id);
/*
* Keep one block and residue bytes in residue and
@@ -1572,6 +1652,11 @@ static int tegra_cmac_do_update(struct ahash_request *req)
return 0;
}
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
/* Copy the previous residue first */
if (rctx->residue.size)
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
@@ -1595,7 +1680,7 @@ static int tegra_cmac_do_update(struct ahash_request *req)
cmdlen = tegra_cmac_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
/*
* If this is not the final update, copy the intermediate results
* from the registers so that it can be used in the next 'update'
@@ -1618,17 +1703,29 @@ static int tegra_cmac_do_final(struct ahash_request *req)
if (!req->nbytes && !rctx->total_len && ctx->fallback_tfm) {
return crypto_shash_tfm_digest(ctx->fallback_tfm,
rctx->datbuf.buf, 0, req->result);
NULL, 0, req->result);
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
rctx->datbuf.size = rctx->residue.size;
rctx->total_len += rctx->residue.size;
rctx->config = tegra234_aes_cfg(SE_ALG_CMAC, 0);
if (rctx->residue.size) {
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf) {
ret = -ENOMEM;
goto out_free;
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
}
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
/* Prepare command and submit */
cmdlen = tegra_cmac_prep_cmd(se, rctx);
ret = tegra_se_host1x_submit(se, cmdlen);
ret = tegra_se_host1x_submit(se, se->cmdbuf, cmdlen);
if (ret)
goto out;
@@ -1640,8 +1737,10 @@ static int tegra_cmac_do_final(struct ahash_request *req)
writel(0, se->base + se->hw->regs->result + (i * 4));
out:
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
rctx->datbuf.buf, rctx->datbuf.addr);
if (rctx->residue.size)
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
out_free:
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm) * 2,
rctx->residue.buf, rctx->residue.addr);
return ret;
@@ -1654,7 +1753,14 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
struct tegra_se *se = ctx->se;
int ret;
int ret = -EINVAL;
if (!ctx->key_id) {
ret = tegra_key_submit_reserved_aes(ctx->se, ctx->key,
ctx->keylen, ctx->alg, &rctx->key_id);
if (ret)
goto out;
}
if (rctx->task & SHA_UPDATE) {
ret = tegra_cmac_do_update(req);
@@ -1665,6 +1771,9 @@ static int tegra_cmac_do_one_req(struct crypto_engine *engine, void *areq)
ret = tegra_cmac_do_final(req);
rctx->task &= ~SHA_FINAL;
}
out:
if (tegra_key_is_reserved(rctx->key_id))
tegra_key_invalidate_reserved(ctx->se, rctx->key_id, ctx->alg);
crypto_finalize_hash_request(se->engine, req, ret);
@@ -1700,7 +1809,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm)
int ret;
algname = crypto_tfm_alg_name(tfm);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash);
@@ -1710,6 +1819,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm)
ctx->se = se_alg->se_dev;
ctx->key_id = 0;
ctx->keylen = 0;
ret = se_algname_to_algid(algname);
if (ret < 0) {
@@ -1719,7 +1829,7 @@ static int tegra_cmac_cra_init(struct crypto_tfm *tfm)
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_cmac_do_one_req;
@@ -1757,34 +1867,24 @@ static int tegra_cmac_init(struct ahash_request *req)
rctx->residue.buf = dma_alloc_coherent(se->dev, rctx->blk_size * 2,
&rctx->residue.addr, GFP_KERNEL);
if (!rctx->residue.buf)
goto resbuf_fail;
return -ENOMEM;
rctx->residue.size = 0;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
goto datbuf_fail;
rctx->datbuf.size = 0;
rctx->key_id = ctx->key_id;
/* Clear any previous result */
for (i = 0; i < CMAC_RESULT_REG_COUNT; i++)
writel(0, se->base + se->hw->regs->result + (i * 4));
return 0;
datbuf_fail:
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
rctx->residue.addr);
resbuf_fail:
return -ENOMEM;
}
static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_cmac_ctx *ctx = crypto_ahash_ctx(tfm);
int ret;
if (aes_check_keylen(keylen)) {
dev_dbg(ctx->se->dev, "invalid key length (%d)\n", keylen);
@@ -1794,7 +1894,13 @@ static int tegra_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
if (ctx->fallback_tfm)
crypto_shash_setkey(ctx->fallback_tfm, key, keylen);
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
if (ret) {
ctx->keylen = keylen;
memcpy(ctx->key, key, keylen);
}
return 0;
}
static int tegra_cmac_update(struct ahash_request *req)
@@ -1863,7 +1969,7 @@ static int tegra_cmac_import(struct ahash_request *req, const void *in)
static struct tegra_se_alg tegra_aead_algs[] = {
{
.alg.aead = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_gcm_cra_init,
@@ -1883,14 +1989,14 @@ static struct tegra_se_alg tegra_aead_algs[] = {
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_gcm_do_one_req,
#endif
}
}, {
.alg.aead = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_ccm_cra_init,
@@ -1911,7 +2017,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_ccm_do_one_req,
#endif
@@ -1922,7 +2028,7 @@ static struct tegra_se_alg tegra_aead_algs[] = {
static struct tegra_se_alg tegra_cmac_algs[] = {
{
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_cmac_init,
@@ -1947,7 +2053,7 @@ static struct tegra_se_alg tegra_cmac_algs[] = {
.cra_init = tegra_cmac_cra_init,
.cra_exit = tegra_cmac_cra_exit,
},
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_cmac_do_one_req,
#endif
@@ -1955,7 +2061,7 @@ static struct tegra_se_alg tegra_cmac_algs[] = {
}
};
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
int tegra_init_aes(struct tegra_se *se)
{
struct aead_engine_alg *aead_alg;

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver to handle HASH algorithms using NVIDIA Security Engine.
*/
@@ -23,7 +23,7 @@
#include "tegra-se.h"
struct tegra_sha_ctx {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
struct crypto_engine_ctx enginectx;
#endif
struct tegra_se *se;
@@ -335,6 +335,11 @@ static int tegra_sha_do_update(struct ahash_request *req)
return 0;
}
rctx->datbuf.buf = dma_alloc_coherent(ctx->se->dev, rctx->datbuf.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
return -ENOMEM;
/* Copy the previous residue first */
if (rctx->residue.size)
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
@@ -361,7 +366,7 @@ static int tegra_sha_do_update(struct ahash_request *req)
size = tegra_sha_prep_cmd(ctx->se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(ctx->se, size);
ret = tegra_se_host1x_submit(ctx->se, ctx->se->cmdbuf, size);
/*
* If this is not the final update, copy the intermediate results
@@ -371,6 +376,9 @@ static int tegra_sha_do_update(struct ahash_request *req)
if (!(rctx->task & SHA_FINAL))
tegra_sha_copy_hash_result(ctx->se, rctx);
dma_free_coherent(ctx->se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
return ret;
}
@@ -383,16 +391,25 @@ static int tegra_sha_do_final(struct ahash_request *req)
u32 *cpuvaddr = se->cmdbuf->addr;
int size, ret = 0;
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
rctx->datbuf.size = rctx->residue.size;
rctx->total_len += rctx->residue.size;
rctx->config = tegra_sha_get_config(rctx->alg) |
SE_SHA_DST_MEMORY;
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
if (rctx->residue.size) {
rctx->datbuf.buf = dma_alloc_coherent(se->dev, rctx->residue.size,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf) {
ret = -ENOMEM;
goto out_free;
}
ret = tegra_se_host1x_submit(se, size);
memcpy(rctx->datbuf.buf, rctx->residue.buf, rctx->residue.size);
}
size = tegra_sha_prep_cmd(se, cpuvaddr, rctx);
ret = tegra_se_host1x_submit(se, se->cmdbuf, size);
if (ret)
goto out;
@@ -400,8 +417,10 @@ static int tegra_sha_do_final(struct ahash_request *req)
memcpy(req->result, rctx->digest.buf, rctx->digest.size);
out:
dma_free_coherent(se->dev, SE_SHA_BUFLEN,
rctx->datbuf.buf, rctx->datbuf.addr);
if (rctx->residue.size)
dma_free_coherent(se->dev, rctx->datbuf.size,
rctx->datbuf.buf, rctx->datbuf.addr);
out_free:
dma_free_coherent(se->dev, crypto_ahash_blocksize(tfm),
rctx->residue.buf, rctx->residue.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
@@ -469,7 +488,7 @@ static int tegra_sha_cra_init(struct crypto_tfm *tfm)
int ret;
algname = crypto_tfm_alg_name(tfm);
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash.base);
#else
se_alg = container_of(alg, struct tegra_se_alg, alg.ahash);
@@ -492,7 +511,7 @@ static int tegra_sha_cra_init(struct crypto_tfm *tfm)
ctx->alg = ret;
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifndef NV_CRYPTO_ENGINE_OPS_PRESENT
ctx->enginectx.op.prepare_request = NULL;
ctx->enginectx.op.unprepare_request = NULL;
ctx->enginectx.op.do_one_request = tegra_sha_do_one_req;
@@ -540,19 +559,11 @@ static int tegra_sha_init(struct ahash_request *req)
if (!rctx->residue.buf)
goto resbuf_fail;
rctx->datbuf.buf = dma_alloc_coherent(se->dev, SE_SHA_BUFLEN,
&rctx->datbuf.addr, GFP_KERNEL);
if (!rctx->datbuf.buf)
goto datbuf_fail;
return 0;
datbuf_fail:
dma_free_coherent(se->dev, rctx->blk_size, rctx->residue.buf,
rctx->residue.addr);
resbuf_fail:
dma_free_coherent(se->dev, SE_SHA_BUFLEN, rctx->datbuf.buf,
rctx->datbuf.addr);
dma_free_coherent(se->dev, rctx->digest.size, rctx->digest.buf,
rctx->digest.addr);
digbuf_fail:
return -ENOMEM;
}
@@ -573,13 +584,18 @@ static int tegra_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen)
{
struct tegra_sha_ctx *ctx = crypto_ahash_ctx(tfm);
int ret;
if (aes_check_keylen(keylen))
return tegra_hmac_fallback_setkey(ctx, key, keylen);
ctx->fallback = false;
return tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
ret = tegra_key_submit(ctx->se, key, keylen, ctx->alg, &ctx->key_id);
if (ret)
return tegra_hmac_fallback_setkey(ctx, key, keylen);
return 0;
}
static int tegra_sha_update(struct ahash_request *req)
@@ -670,7 +686,7 @@ static int tegra_sha_import(struct ahash_request *req, const void *in)
static struct tegra_se_alg tegra_hash_algs[] = {
{
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -694,14 +710,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -725,14 +741,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -756,14 +772,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -787,14 +803,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -818,14 +834,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -849,14 +865,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -880,14 +896,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -911,14 +927,14 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
}
}, {
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -942,7 +958,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
@@ -950,7 +966,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
}, {
.alg_base = "sha224",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -975,7 +991,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
@@ -983,7 +999,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
}, {
.alg_base = "sha256",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -1008,7 +1024,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
@@ -1016,7 +1032,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
}, {
.alg_base = "sha384",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -1041,7 +1057,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
@@ -1049,7 +1065,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
}, {
.alg_base = "sha512",
.alg.ahash = {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
.base = {
#endif
.init = tegra_sha_init,
@@ -1074,7 +1090,7 @@ static struct tegra_se_alg tegra_hash_algs[] = {
.cra_init = tegra_sha_cra_init,
.cra_exit = tegra_sha_cra_exit,
}
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
},
.op.do_one_request = tegra_sha_do_one_req,
#endif
@@ -1117,7 +1133,7 @@ static int tegra_hash_kac_manifest(u32 user, u32 alg, u32 keylen)
int tegra_init_hash(struct tegra_se *se)
{
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
struct ahash_engine_alg *alg;
#else
struct ahash_alg *alg;
@@ -1132,7 +1148,7 @@ int tegra_init_hash(struct tegra_se *se)
ret = CRYPTO_REGISTER(ahash, alg);
if (ret) {
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
dev_err(se->dev, "failed to register %s\n",
alg->base.halg.base.cra_name);
#else

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver file to manage keys of NVIDIA Security Engine.
*/
@@ -115,11 +115,15 @@ static int tegra_key_insert(struct tegra_se *se, const u8 *key,
u32 keylen, u16 slot, u32 alg)
{
const u32 *keyval = (u32 *)key;
u32 *addr = se->cmdbuf->addr, size;
u32 *addr = se->keybuf->addr, size;
int ret;
mutex_lock(&kslt_lock);
size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg);
ret = tegra_se_host1x_submit(se, se->keybuf, size);
mutex_unlock(&kslt_lock);
return tegra_se_host1x_submit(se, size);
return ret;
}
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
@@ -143,7 +147,7 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3
if (!tegra_key_in_kslt(*keyid)) {
*keyid = tegra_keyslot_alloc();
if (!(*keyid)) {
dev_err(se->dev, "failed to allocate key slot\n");
dev_dbg(se->dev, "failed to allocate key slot\n");
return -ENOMEM;
}
}
@@ -154,3 +158,20 @@ int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u3
return 0;
}
void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg)
{
u8 zkey[AES_MAX_KEY_SIZE] = {0};
if (!keyid)
return;
/* Overwrite the key with 0s */
tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
}
inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
return tegra_key_insert(se, key, keylen, *keyid, alg);
}

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Crypto driver for NVIDIA Security Engine in Tegra Chips
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
@@ -141,7 +143,7 @@ static struct tegra_se_cmdbuf *tegra_se_host1x_bo_alloc(struct tegra_se *se, ssi
return cmdbuf;
}
int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size)
{
struct host1x_job *job;
int ret;
@@ -160,9 +162,9 @@ int tegra_se_host1x_submit(struct tegra_se *se, u32 size)
job->engine_fallback_streamid = se->stream_id;
job->engine_streamid_offset = SE_STREAM_ID;
se->cmdbuf->words = size;
cmdbuf->words = size;
host1x_job_add_gather(job, &se->cmdbuf->bo, size, 0);
host1x_job_add_gather(job, &cmdbuf->bo, size, 0);
ret = host1x_job_pin(job, se->dev);
if (ret) {
@@ -220,14 +222,22 @@ static int tegra_se_client_init(struct host1x_client *client)
goto syncpt_put;
}
se->keybuf = tegra_se_host1x_bo_alloc(se, SZ_4K);
if (!se->cmdbuf) {
ret = -ENOMEM;
goto cmdbuf_put;
}
ret = se->hw->init_alg(se);
if (ret) {
dev_err(se->dev, "failed to register algorithms\n");
goto cmdbuf_put;
goto keybuf_put;
}
return 0;
keybuf_put:
tegra_se_cmdbuf_put(&se->keybuf->bo);
cmdbuf_put:
tegra_se_cmdbuf_put(&se->cmdbuf->bo);
syncpt_put:
@@ -384,13 +394,25 @@ static const struct of_device_id tegra_se_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_se_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_se_remove_wrapper(struct platform_device *pdev)
{
tegra_se_remove(pdev);
}
#else
static int tegra_se_remove_wrapper(struct platform_device *pdev)
{
return tegra_se_remove(pdev);
}
#endif
static struct platform_driver tegra_se_driver = {
.driver = {
.name = "tegra-se",
.of_match_table = tegra_se_of_match,
},
.probe = tegra_se_probe,
.remove = tegra_se_remove,
.remove = tegra_se_remove_wrapper,
};
static int tegra_se_host1x_probe(struct host1x_device *dev)

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Header file for NVIDIA Security Engine driver.
*/
@@ -342,24 +342,26 @@
#define SE_CRYPTO_CTR_REG_COUNT 4
#define SE_MAX_KEYSLOT 15
#define SE_MAX_MEM_ALLOC SZ_4M
#define SE_SHA_BUFLEN 0x2000
#define TEGRA_AES_RESERVED_KSLT 14
#define TEGRA_XTS_RESERVED_KSLT 15
#define SHA_FIRST BIT(0)
#define SHA_UPDATE BIT(1)
#define SHA_FINAL BIT(2)
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#define CRYPTO_REGISTER(alg, x) \
crypto_engine_register_##alg(x)
#else
#define CRYPTO_REGISTER(alg, x) \
crypto_register_##alg(x)
#if NV_IS_EXPORT_SYMBOL_PRESENT_crypto_engine_register_aead /* Linux v6.6 */
#define NV_CRYPTO_ENGINE_OPS_PRESENT
#endif
#ifdef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
#define CRYPTO_REGISTER(alg, x) \
crypto_engine_register_##alg(x)
#define CRYPTO_UNREGISTER(alg, x) \
crypto_engine_unregister_##alg(x)
#else
#define CRYPTO_REGISTER(alg, x) \
crypto_register_##alg(x)
#define CRYPTO_UNREGISTER(alg, x) \
crypto_unregister_##alg(x)
#endif
@@ -401,14 +403,14 @@ struct tegra_se_alg {
const char *alg_base;
union {
#ifndef NV_CONFTEST_REMOVE_STRUCT_CRYPTO_ENGINE_CTX
struct skcipher_alg skcipher;
struct aead_alg aead;
struct ahash_alg ahash;
#else
#ifdef NV_CRYPTO_ENGINE_OPS_PRESENT
struct skcipher_engine_alg skcipher;
struct aead_engine_alg aead;
struct ahash_engine_alg ahash;
#else
struct skcipher_alg skcipher;
struct aead_alg aead;
struct ahash_alg ahash;
#endif
} alg;
};
@@ -443,6 +445,7 @@ struct tegra_se {
struct host1x_client client;
struct host1x_channel *channel;
struct tegra_se_cmdbuf *cmdbuf;
struct tegra_se_cmdbuf *keybuf;
struct crypto_engine *engine;
struct host1x_syncpt *syncpt;
struct device *dev;
@@ -525,7 +528,31 @@ void tegra_deinit_hash(struct tegra_se *se);
int tegra_key_submit(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, u32 size);
int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid);
void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg);
int tegra_se_host1x_submit(struct tegra_se *se, struct tegra_se_cmdbuf *cmdbuf, u32 size);
static inline int tegra_key_submit_reserved_aes(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
*keyid = TEGRA_AES_RESERVED_KSLT;
return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
}
static inline int tegra_key_submit_reserved_xts(struct tegra_se *se, const u8 *key,
u32 keylen, u32 alg, u32 *keyid)
{
*keyid = TEGRA_XTS_RESERVED_KSLT;
return tegra_key_submit_reserved(se, key, keylen, alg, keyid);
}
static inline bool tegra_key_is_reserved(u32 keyid)
{
return ((keyid == TEGRA_AES_RESERVED_KSLT) ||
(keyid == TEGRA_XTS_RESERVED_KSLT));
}
/* HOST1x OPCODES */
static inline u32 host1x_opcode_setpayload(unsigned int payload)

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023, NVIDIA Corporation. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/devfreq.h>
#include <linux/devfreq/tegra_wmark.h>
#include <linux/device.h>
@@ -13,11 +15,7 @@
#include <linux/slab.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
#include <drivers-private/devfreq/k519/governor.h>
#else
#include <drivers-private/devfreq/governor.h>
#endif
/**
* struct tegra_wmark_data - governor private data stored in struct devfreq
@@ -65,12 +63,12 @@ struct tegra_wmark_data {
static int devfreq_get_freq_index(struct devfreq *df, unsigned long freq)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
unsigned long *freq_table = df->profile->freq_table;
unsigned int max_state = df->profile->max_state;
#else
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
unsigned long *freq_table = df->freq_table;
unsigned int max_state = df->max_state;
#else
unsigned long *freq_table = df->profile->freq_table;
unsigned int max_state = df->profile->max_state;
#endif
int i;
@@ -86,12 +84,12 @@ static int devfreq_tegra_wmark_target_freq(struct devfreq *df, unsigned long *fr
{
struct tegra_wmark_data *govdata = df->governor_data;
struct devfreq_tegra_wmark_data *drvdata = df->data;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
unsigned long *freq_table = df->profile->freq_table;
unsigned int max_state = df->profile->max_state;
#else
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
unsigned long *freq_table = df->freq_table;
unsigned int max_state = df->max_state;
#else
unsigned long *freq_table = df->profile->freq_table;
unsigned int max_state = df->profile->max_state;
#endif
int target_index = 0;
@@ -119,7 +117,6 @@ static int devfreq_tegra_wmark_target_freq(struct devfreq *df, unsigned long *fr
return 0;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
static s32 devfreq_pm_qos_read_value(struct devfreq *df, enum dev_pm_qos_req_type type)
{
struct device *dev = df->dev.parent;
@@ -153,8 +150,13 @@ static void devfreq_get_freq_range(struct devfreq *df,
{
s32 qos_min_freq, qos_max_freq;
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
*min_freq = df->freq_table[0];
*max_freq = df->freq_table[df->max_state - 1];
#else
*min_freq = df->profile->freq_table[0];
*max_freq = df->profile->freq_table[df->profile->max_state - 1];
#endif
qos_min_freq = devfreq_pm_qos_read_value(df, DEV_PM_QOS_MIN_FREQUENCY);
qos_max_freq = devfreq_pm_qos_read_value(df, DEV_PM_QOS_MAX_FREQUENCY);
@@ -168,7 +170,6 @@ static void devfreq_get_freq_range(struct devfreq *df,
*min_freq = max(*min_freq, df->scaling_min_freq);
*max_freq = min(*max_freq, df->scaling_max_freq);
}
#endif
static void devfreq_update_wmark_threshold(struct devfreq *df)
{
@@ -176,10 +177,10 @@ static void devfreq_update_wmark_threshold(struct devfreq *df)
struct devfreq_tegra_wmark_data *drvdata = df->data;
struct devfreq_tegra_wmark_config wmark_config;
unsigned long curr_freq, prev_freq, min_freq, max_freq;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
unsigned long *freq_table = df->profile->freq_table;
#else
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
unsigned long *freq_table = df->freq_table;
#else
unsigned long *freq_table = df->profile->freq_table;
#endif
int err;
@@ -225,10 +226,10 @@ static ssize_t up_freq_margin_store(struct device *dev,
struct devfreq *df = to_devfreq(dev);
struct tegra_wmark_data *govdata;
unsigned int freq_margin;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
unsigned int max_state = df->profile->max_state;
#else
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
unsigned int max_state = df->max_state;
#else
unsigned int max_state = df->profile->max_state;
#endif
int ret;
@@ -270,10 +271,10 @@ static ssize_t down_freq_margin_store(struct device *dev,
struct devfreq *df = to_devfreq(dev);
struct tegra_wmark_data *govdata;
unsigned int freq_margin;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 19, 0)
unsigned int max_state = df->profile->max_state;
#else
#if defined(NV_DEVFREQ_HAS_FREQ_TABLE)
unsigned int max_state = df->max_state;
#else
unsigned int max_state = df->profile->max_state;
#endif
int ret;

View File

@@ -197,7 +197,7 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP)
if (!tegra_ivc_empty(ivc, &ivc->rx.map))
if (tegra_ivc_empty(ivc, &ivc->rx.map))
#else
if (tegra_ivc_empty(ivc, ivc->rx.channel))
#endif
@@ -229,7 +229,7 @@ static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
#if defined(NV_TEGRA_IVC_STRUCT_HAS_IOSYS_MAP)
if (!tegra_ivc_full(ivc, &ivc->tx.map))
if (tegra_ivc_full(ivc, &ivc->tx.map))
#else
if (tegra_ivc_full(ivc, ivc->tx.channel))
#endif

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2012 Avionic Design GmbH
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2012-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -3295,11 +3295,23 @@ static int tegra_dc_remove(struct platform_device *pdev)
return 0;
}
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_dc_remove_wrapper(struct platform_device *pdev)
{
tegra_dc_remove(pdev);
}
#else
static int tegra_dc_remove_wrapper(struct platform_device *pdev)
{
return tegra_dc_remove(pdev);
}
#endif
struct platform_driver tegra_dc_driver = {
.driver = {
.name = "tegra-dc",
.of_match_table = tegra_dc_of_match,
},
.probe = tegra_dc_probe,
.remove = tegra_dc_remove,
.remove = tegra_dc_remove_wrapper,
};

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 NVIDIA Corporation
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -708,6 +708,18 @@ static const struct of_device_id tegra_dpaux_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_dpaux_remove_wrapper(struct platform_device *pdev)
{
tegra_dpaux_remove(pdev);
}
#else
static int tegra_dpaux_remove_wrapper(struct platform_device *pdev)
{
return tegra_dpaux_remove(pdev);
}
#endif
struct platform_driver tegra_dpaux_driver = {
.driver = {
.name = "tegra-dpaux",
@@ -715,7 +727,7 @@ struct platform_driver tegra_dpaux_driver = {
.pm = &tegra_dpaux_pm_ops,
},
.probe = tegra_dpaux_probe,
.remove = tegra_dpaux_remove,
.remove = tegra_dpaux_remove_wrapper,
};
struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)

View File

@@ -16,7 +16,11 @@
#include <linux/pm_runtime.h>
#include <linux/version.h>
#if defined(NV_APERTURE_REMOVE_ALL_CONFLICTING_DEVICES_PRESENT) /* Linux v6.0 */
#include <linux/aperture.h>
#else
#include <drm/drm_aperture.h>
#endif
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
@@ -61,9 +65,6 @@ static int tegra_atomic_check(struct drm_device *drm,
static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
.fb_create = tegra_fb_create,
#ifdef CONFIG_DRM_FBDEV_EMULATION
.output_poll_changed = drm_fb_helper_output_poll_changed,
#endif
.atomic_check = tegra_atomic_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -805,6 +806,9 @@ static const struct file_operations tegra_drm_fops = {
.read = drm_read,
.compat_ioctl = drm_compat_ioctl,
.llseek = noop_llseek,
#if defined(NV_FOP_UNSIGNED_OFFSET_PRESENT) /* Linux v6.12 */
.fop_flags = FOP_UNSIGNED_OFFSET,
#endif
};
static int tegra_drm_context_cleanup(int id, void *p, void *data)
@@ -886,7 +890,6 @@ static const struct drm_driver tegra_drm_driver = {
DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_SYNCOBJ,
.open = tegra_drm_open,
.postclose = tegra_drm_postclose,
.lastclose = drm_fb_helper_lastclose,
#if defined(CONFIG_DEBUG_FS)
.debugfs_init = tegra_debugfs_init,
@@ -908,7 +911,9 @@ static const struct drm_driver tegra_drm_driver = {
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
#if defined(NV_DRM_DRIVER_STRUCT_HAS_DATE) /* Linux v6.14 */
.date = DRIVER_DATE,
#endif
.major = DRIVER_MAJOR,
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
@@ -1183,6 +1188,9 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev)
static int host1x_drm_probe(struct host1x_device *dev)
{
#if defined(NV_IOMMU_PAGING_DOMAIN_ALLOC_PRESENT) /* Linux v6.11 */
struct device *dma_dev = dev->dev.parent;
#endif
struct tegra_drm *tegra;
struct drm_device *drm;
int err;
@@ -1197,8 +1205,13 @@ static int host1x_drm_probe(struct host1x_device *dev)
goto put;
}
#if defined(NV_IOMMU_PAGING_DOMAIN_ALLOC_PRESENT) /* Linux v6.11 */
if (host1x_drm_wants_iommu(dev) && device_iommu_mapped(dma_dev)) {
tegra->domain = iommu_paging_domain_alloc(dma_dev);
#else
if (host1x_drm_wants_iommu(dev) && iommu_present(&platform_bus_type)) {
tegra->domain = iommu_domain_alloc(&platform_bus_type);
#endif
if (!tegra->domain) {
err = -ENOMEM;
goto free;
@@ -1228,15 +1241,11 @@ static int host1x_drm_probe(struct host1x_device *dev)
drm->mode_config.funcs = &tegra_drm_mode_config_funcs;
drm->mode_config.helper_private = &tegra_drm_mode_config_helpers;
err = tegra_drm_fb_prepare(drm);
if (err < 0)
goto config;
drm_kms_helper_poll_init(drm);
err = host1x_device_init(dev);
if (err < 0)
goto fbdev;
goto poll;
/*
* Now that all display controller have been initialized, the maximum
@@ -1305,7 +1314,9 @@ static int host1x_drm_probe(struct host1x_device *dev)
drm_mode_config_reset(drm);
if (drm->mode_config.num_crtc > 0) {
#if defined(NV_DRM_APERTURE_REMOVE_FRAMEBUFFERS_HAS_NO_PRIMARY_ARG) /* Linux v6.5 */
#if defined(NV_APERTURE_REMOVE_ALL_CONFLICTING_DEVICES_PRESENT) /* Linux v6.0 */
err = aperture_remove_all_conflicting_devices(tegra_drm_driver.name);
#elif defined(NV_DRM_APERTURE_REMOVE_FRAMEBUFFERS_HAS_NO_PRIMARY_ARG) /* Linux v6.5 */
err = drm_aperture_remove_framebuffers(&tegra_drm_driver);
#elif defined(NV_DRM_APERTURE_REMOVE_FRAMEBUFFERS_HAS_DRM_DRIVER_ARG) /* Linux v5.15 */
err = drm_aperture_remove_framebuffers(false, &tegra_drm_driver);
@@ -1316,18 +1327,12 @@ static int host1x_drm_probe(struct host1x_device *dev)
goto hub;
}
err = tegra_drm_fb_init(drm);
err = drm_dev_register(drm, 0);
if (err < 0)
goto hub;
err = drm_dev_register(drm, 0);
if (err < 0)
goto fb;
return 0;
fb:
tegra_drm_fb_exit(drm);
hub:
if (tegra->hub)
tegra_display_hub_cleanup(tegra->hub);
@@ -1340,10 +1345,8 @@ device:
}
host1x_device_exit(dev);
fbdev:
poll:
drm_kms_helper_poll_fini(drm);
tegra_drm_fb_free(drm);
config:
drm_mode_config_cleanup(drm);
domain:
if (tegra->domain)
@@ -1364,7 +1367,6 @@ static int host1x_drm_remove(struct host1x_device *dev)
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
tegra_drm_fb_exit(drm);
drm_atomic_helper_shutdown(drm);
drm_mode_config_cleanup(drm);

View File

@@ -130,7 +130,7 @@ static inline struct device *
tegra_drm_context_get_memory_device(struct tegra_drm_context *context)
{
if (context->memory_context)
return &context->memory_context->dev;
return context->memory_context->context_dev;
else
return context->client->base.dev;
}

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 NVIDIA Corporation
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -1692,11 +1692,23 @@ static const struct of_device_id tegra_dsi_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_dsi_remove_wrapper(struct platform_device *pdev)
{
tegra_dsi_remove(pdev);
}
#else
static int tegra_dsi_remove_wrapper(struct platform_device *pdev)
{
return tegra_dsi_remove(pdev);
}
#endif
struct platform_driver tegra_dsi_driver = {
.driver = {
.name = "tegra-dsi",
.of_match_table = tegra_dsi_of_match,
},
.probe = tegra_dsi_probe,
.remove = tegra_dsi_remove,
.remove = tegra_dsi_remove_wrapper,
};

View File

@@ -3,7 +3,7 @@
* NVIDIA Tegra DRM GEM helper functions
*
* Copyright (C) 2012 Sascha Hauer, Pengutronix
* Copyright (C) 2013-2023 NVIDIA CORPORATION, All rights reserved.
* Copyright (C) 2013-2024 NVIDIA CORPORATION, All rights reserved.
*
* Based on the GEM/CMA helpers
*
@@ -24,7 +24,11 @@
#include "drm.h"
#include "gem.h"
#if defined(NV_MODULE_IMPORT_NS_CALLS_STRINGIFY)
MODULE_IMPORT_NS(DMA_BUF);
#else
MODULE_IMPORT_NS("DMA_BUF");
#endif
static unsigned int sg_dma_count_chunks(struct scatterlist *sgl, unsigned int nents)
{

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2013, NVIDIA Corporation.
* SPDX-FileCopyrightText: Copyright (c) 2012-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/iommu.h>
@@ -392,6 +394,18 @@ static const struct dev_pm_ops tegra_gr2d_pm = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void gr2d_remove_wrapper(struct platform_device *pdev)
{
gr2d_remove(pdev);
}
#else
static int gr2d_remove_wrapper(struct platform_device *pdev)
{
return gr2d_remove(pdev);
}
#endif
struct platform_driver tegra_gr2d_driver = {
.driver = {
.name = "tegra-gr2d",
@@ -399,5 +413,5 @@ struct platform_driver tegra_gr2d_driver = {
.pm = &tegra_gr2d_pm,
},
.probe = gr2d_probe,
.remove = gr2d_remove,
.remove = gr2d_remove_wrapper,
};

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 Avionic Design GmbH
* Copyright (C) 2013 NVIDIA Corporation
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/host1x-next.h>
@@ -47,6 +49,9 @@ struct gr3d {
unsigned int nclocks;
struct reset_control_bulk_data resets[RST_GR3D_MAX];
unsigned int nresets;
#if defined(NV_DEVM_PM_DOMAIN_ATTACH_LIST_PRESENT) /* Linux v6.13 */
struct dev_pm_domain_list *pd_list;
#endif
DECLARE_BITMAP(addr_regs, GR3D_NUM_REGS);
};
@@ -370,13 +375,21 @@ static int gr3d_power_up_legacy_domain(struct device *dev, const char *name,
return 0;
}
#if !defined(NV_DEVM_PM_DOMAIN_ATTACH_LIST_PRESENT) /* Linux v6.13 */
static void gr3d_del_link(void *link)
{
device_link_del(link);
}
#endif
static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
{
#if defined(NV_DEVM_PM_DOMAIN_ATTACH_LIST_PRESENT) /* Linux v6.13 */
struct dev_pm_domain_attach_data pd_data = {
.pd_names = (const char *[]) { "3d0", "3d1" },
.num_pd_names = 2,
};
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
static const char * const opp_genpd_names[] = { "3d0", "3d1", NULL };
#else
@@ -386,6 +399,7 @@ static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
struct device **opp_virt_devs, *pd_dev;
struct device_link *link;
unsigned int i;
#endif
int err;
err = of_count_phandle_with_args(dev->of_node, "power-domains",
@@ -419,6 +433,11 @@ static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
if (dev->pm_domain)
return 0;
#if defined(NV_DEVM_PM_DOMAIN_ATTACH_LIST_PRESENT) /* Linux v6.13 */
err = devm_pm_domain_attach_list(dev, &pd_data, &gr3d->pd_list);
if (err < 0)
return err;
#else
err = devm_pm_opp_attach_genpd(dev, opp_genpd_names, &opp_virt_devs);
if (err)
return err;
@@ -441,6 +460,7 @@ static int gr3d_init_power(struct device *dev, struct gr3d *gr3d)
if (err)
return err;
}
#endif
return 0;
}
@@ -631,6 +651,18 @@ static const struct dev_pm_ops tegra_gr3d_pm = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void gr3d_remove_wrapper(struct platform_device *pdev)
{
gr3d_remove(pdev);
}
#else
static int gr3d_remove_wrapper(struct platform_device *pdev)
{
return gr3d_remove(pdev);
}
#endif
struct platform_driver tegra_gr3d_driver = {
.driver = {
.name = "tegra-gr3d",
@@ -638,5 +670,5 @@ struct platform_driver tegra_gr3d_driver = {
.pm = &tegra_gr3d_pm,
},
.probe = gr3d_probe,
.remove = gr3d_remove,
.remove = gr3d_remove_wrapper,
};

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2012 Avionic Design GmbH
* Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2012-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -1909,11 +1909,23 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
return 0;
}
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_hdmi_remove_wrapper(struct platform_device *pdev)
{
tegra_hdmi_remove(pdev);
}
#else
static int tegra_hdmi_remove_wrapper(struct platform_device *pdev)
{
return tegra_hdmi_remove(pdev);
}
#endif
struct platform_driver tegra_hdmi_driver = {
.driver = {
.name = "tegra-hdmi",
.of_match_table = tegra_hdmi_of_match,
},
.probe = tegra_hdmi_probe,
.remove = tegra_hdmi_remove,
.remove = tegra_hdmi_remove_wrapper,
};

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2017 NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@@ -1215,11 +1217,23 @@ static const struct of_device_id tegra_display_hub_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_display_hub_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_display_hub_remove_wrapper(struct platform_device *pdev)
{
tegra_display_hub_remove(pdev);
}
#else
static int tegra_display_hub_remove_wrapper(struct platform_device *pdev)
{
return tegra_display_hub_remove(pdev);
}
#endif
struct platform_driver tegra_display_hub_driver = {
.driver = {
.name = "tegra-display-hub",
.of_match_table = tegra_display_hub_of_match,
},
.probe = tegra_display_hub_probe,
.remove = tegra_display_hub_remove,
.remove = tegra_display_hub_remove_wrapper,
};

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPDX-FileCopyrightText: Copyright (c) 2015-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
* SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -964,6 +966,18 @@ static const struct dev_pm_ops nvdec_pm_ops = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void nvdec_remove_wrapper(struct platform_device *pdev)
{
nvdec_remove(pdev);
}
#else
static int nvdec_remove_wrapper(struct platform_device *pdev)
{
return nvdec_remove(pdev);
}
#endif
struct platform_driver tegra_nvdec_driver = {
.driver = {
.name = "tegra-nvdec",
@@ -971,7 +985,7 @@ struct platform_driver tegra_nvdec_driver = {
.pm = &nvdec_pm_ops
},
.probe = nvdec_probe,
.remove = nvdec_remove,
.remove = nvdec_remove_wrapper,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPDX-FileCopyrightText: Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -757,6 +759,18 @@ static const struct dev_pm_ops nvenc_pm_ops = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void nvenc_remove_wrapper(struct platform_device *pdev)
{
nvenc_remove(pdev);
}
#else
static int nvenc_remove_wrapper(struct platform_device *pdev)
{
return nvenc_remove(pdev);
}
#endif
struct platform_driver tegra_nvenc_driver = {
.driver = {
.name = "tegra-nvenc",
@@ -764,7 +778,7 @@ struct platform_driver tegra_nvenc_driver = {
.pm = &nvenc_pm_ops
},
.probe = nvenc_probe,
.remove = nvenc_remove,
.remove = nvenc_remove_wrapper,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPDX-FileCopyrightText: Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -734,6 +736,18 @@ static const struct dev_pm_ops nvjpg_pm_ops = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void nvjpg_remove_wrapper(struct platform_device *pdev)
{
nvjpg_remove(pdev);
}
#else
static int nvjpg_remove_wrapper(struct platform_device *pdev)
{
return nvjpg_remove(pdev);
}
#endif
struct platform_driver tegra_nvjpg_driver = {
.driver = {
.name = "tegra-nvjpg",
@@ -741,7 +755,7 @@ struct platform_driver tegra_nvjpg_driver = {
.pm = &nvjpg_pm_ops
},
.probe = nvjpg_probe,
.remove = nvjpg_remove,
.remove = nvjpg_remove_wrapper,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPDX-FileCopyrightText: Copyright (c) 2021-2023, NVIDIA Corporation.
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/devfreq.h>
@@ -632,6 +634,18 @@ static const struct dev_pm_ops ofa_pm_ops = {
pm_runtime_force_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void ofa_remove_wrapper(struct platform_device *pdev)
{
ofa_remove(pdev);
}
#else
static int ofa_remove_wrapper(struct platform_device *pdev)
{
return ofa_remove(pdev);
}
#endif
struct platform_driver tegra_ofa_driver = {
.driver = {
.name = "tegra-ofa",
@@ -639,7 +653,7 @@ struct platform_driver tegra_ofa_driver = {
.pm = &ofa_pm_ops
},
.probe = ofa_probe,
.remove = ofa_remove,
.remove = ofa_remove_wrapper,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)

View File

@@ -1,9 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022, NVIDIA Corporation.
*/
#include <asm/unaligned.h>
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/dev_printk.h>
#include <linux/device.h>

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 NVIDIA Corporation
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -4082,6 +4082,18 @@ static const struct dev_pm_ops tegra_sor_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_sor_suspend, tegra_sor_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_sor_remove_wrapper(struct platform_device *pdev)
{
tegra_sor_remove(pdev);
}
#else
static int tegra_sor_remove_wrapper(struct platform_device *pdev)
{
return tegra_sor_remove(pdev);
}
#endif
struct platform_driver tegra_sor_driver = {
.driver = {
.name = "tegra-sor",
@@ -4089,5 +4101,5 @@ struct platform_driver tegra_sor_driver = {
.pm = &tegra_sor_pm_ops,
},
.probe = tegra_sor_probe,
.remove = tegra_sor_remove,
.remove = tegra_sor_remove_wrapper,
};

View File

@@ -240,9 +240,14 @@ static int submit_write_reloc(struct tegra_drm_context *context, struct gather_b
struct drm_tegra_submit_buf *buf, struct tegra_drm_mapping *mapping)
{
/* TODO check that target_offset is within bounds */
dma_addr_t iova = mapping->iova + buf->reloc.target_offset;
dma_addr_t iova = buf->reloc.target_offset;
u32 written_ptr;
if (mapping->bo_map)
iova += mapping->iova;
else
iova += mapping->ctx_map->mapping->phys;
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
if (buf->flags & DRM_TEGRA_SUBMIT_RELOC_SECTOR_LAYOUT)
iova |= BIT_ULL(39);
@@ -526,9 +531,6 @@ static void release_job(struct host1x_job *job)
struct tegra_drm_submit_data *job_data = job->user_data;
u32 i;
if (job->memory_context)
host1x_memory_context_put(job->memory_context);
if (IS_ENABLED(CONFIG_TRACING) && job_data->timestamps.virt) {
u64 *timestamps = job_data->timestamps.virt;
@@ -542,6 +544,11 @@ static void release_job(struct host1x_job *job)
for (i = 0; i < job_data->num_used_mappings; i++)
tegra_drm_mapping_put(job_data->used_mappings[i].mapping);
if (job->memory_context) {
host1x_memory_context_inactive(job->memory_context);
host1x_memory_context_put(job->memory_context);
}
kfree(job_data->used_mappings);
kfree(job_data);
@@ -581,6 +588,7 @@ static int submit_init_profiling(struct tegra_drm_context *context,
int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
struct drm_file *file)
{
struct host1x_memory_context *active_memctx = NULL;
struct tegra_drm_file *fpriv = file->driver_priv;
struct drm_tegra_channel_submit *args = data;
static atomic_t next_job_id = ATOMIC_INIT(1);
@@ -604,6 +612,17 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
return -EINVAL;
}
if (context->memory_context) {
err = host1x_memory_context_active(context->memory_context);
if (err) {
mutex_unlock(&fpriv->lock);
SUBMIT_ERR(context, "failed to activate memory context");
return err;
}
active_memctx = context->memory_context;
}
if (args->flags & ~(DRM_TEGRA_SUBMIT_SECONDARY_SYNCPT)) {
SUBMIT_ERR(context, "invalid flags '%#x'", args->flags);
goto unlock;
@@ -704,7 +723,8 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
}
if (supported) {
job->memory_context = context->memory_context;
job->memory_context = active_memctx;
active_memctx = NULL;
host1x_memory_context_get(job->memory_context);
}
} else if (context->client->ops->get_streamid_offset) {
@@ -825,6 +845,8 @@ put_bo:
unlock:
if (syncobj)
drm_syncobj_put(syncobj);
if (active_memctx)
host1x_memory_context_inactive(active_memctx);
mutex_unlock(&fpriv->lock);
return err;

View File

@@ -17,7 +17,11 @@ static void tegra_drm_mapping_release(struct kref *ref)
struct tegra_drm_mapping *mapping =
container_of(ref, struct tegra_drm_mapping, ref);
host1x_bo_unpin(mapping->map);
if (mapping->ctx_map)
host1x_memory_context_unmap(mapping->ctx_map);
else
host1x_bo_unpin(mapping->bo_map);
host1x_bo_put(mapping->bo);
kfree(mapping);
@@ -33,12 +37,12 @@ static void tegra_drm_channel_context_close(struct tegra_drm_context *context)
struct tegra_drm_mapping *mapping;
unsigned long id;
if (context->memory_context)
host1x_memory_context_put(context->memory_context);
xa_for_each(&context->mappings, id, mapping)
tegra_drm_mapping_put(mapping);
if (context->memory_context)
host1x_memory_context_put(context->memory_context);
xa_destroy(&context->mappings);
host1x_channel_put(context->channel);
@@ -234,15 +238,26 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_f
goto put_gem;
}
mapping->map = host1x_bo_pin(tegra_drm_context_get_memory_device(context),
mapping->bo, direction, NULL);
if (IS_ERR(mapping->map)) {
err = PTR_ERR(mapping->map);
goto put_gem;
}
if (context->memory_context) {
mapping->ctx_map = host1x_memory_context_map(
context->memory_context, mapping->bo, direction);
mapping->iova = mapping->map->phys;
mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->gem.size;
if (IS_ERR(mapping->ctx_map)) {
err = PTR_ERR(mapping->ctx_map);
goto put_gem;
}
} else {
mapping->bo_map = host1x_bo_pin(context->client->base.dev,
mapping->bo, direction, NULL);
if (IS_ERR(mapping->bo_map)) {
err = PTR_ERR(mapping->bo_map);
goto put_gem;
}
mapping->iova = mapping->bo_map->phys;
mapping->iova_end = mapping->iova + host1x_to_tegra_bo(mapping->bo)->gem.size;
}
err = xa_alloc(&context->mappings, &args->mapping, mapping, XA_LIMIT(1, U32_MAX),
GFP_KERNEL);
@@ -254,7 +269,10 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, struct drm_f
return 0;
unpin:
host1x_bo_unpin(mapping->map);
if (mapping->ctx_map)
host1x_memory_context_unmap(mapping->ctx_map);
else
host1x_bo_unpin(mapping->bo_map);
put_gem:
host1x_bo_put(mapping->bo);
free:

View File

@@ -27,7 +27,8 @@ struct tegra_drm_file {
struct tegra_drm_mapping {
struct kref ref;
struct host1x_bo_mapping *map;
struct host1x_bo_mapping *bo_map;
struct host1x_context_mapping *ctx_map;
struct host1x_bo *bo;
dma_addr_t iova;

View File

@@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* SPDX-FileCopyrightText: Copyright (C) 2015-2024 NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -831,6 +833,18 @@ static const struct dev_pm_ops vic_pm_ops = {
#endif
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void vic_remove_wrapper(struct platform_device *pdev)
{
vic_remove(pdev);
}
#else
static int vic_remove_wrapper(struct platform_device *pdev)
{
return vic_remove(pdev);
}
#endif
struct platform_driver tegra_vic_driver = {
.driver = {
.name = "tegra-vic",
@@ -838,7 +852,7 @@ struct platform_driver tegra_vic_driver = {
.pm = &vic_pm_ops
},
.probe = vic_probe,
.remove = vic_remove,
.remove = vic_remove_wrapper,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC)

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023, NVIDIA Corporation.
*/
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
@@ -563,6 +563,18 @@ static const struct dev_pm_ops virt_engine_pm_ops = {
#endif
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void virt_engine_remove_wrapper(struct platform_device *pdev)
{
virt_engine_remove(pdev);
}
#else
static int virt_engine_remove_wrapper(struct platform_device *pdev)
{
return virt_engine_remove(pdev);
}
#endif
struct platform_driver tegra_virt_engine_driver = {
.driver = {
.name = "tegra-host1x-virtual-engine",
@@ -570,5 +582,5 @@ struct platform_driver tegra_virt_engine_driver = {
.pm = &virt_engine_pm_ops,
},
.probe = virt_engine_probe,
.remove = virt_engine_remove,
.remove = virt_engine_remove_wrapper,
};

View File

@@ -172,6 +172,8 @@ static int dev_file_ioctl_fence_extract(struct host1x *host1x, void __user *data
goto put_fence;
}
dma_fence_put(fence);
return 0;
put_fence:

View File

@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021-2024, NVIDIA Corporation.
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pid.h>
@@ -17,13 +19,14 @@ int host1x_memory_context_list_init(struct host1x *host1x)
{
struct host1x_memory_context_list *cdl = &host1x->context_list;
struct device_node *node = host1x->dev->of_node;
struct host1x_memory_context *ctx;
struct host1x_hw_memory_context *ctx;
unsigned int i;
int err;
cdl->devs = NULL;
cdl->len = 0;
mutex_init(&cdl->lock);
INIT_LIST_HEAD(&cdl->waiters);
err = of_property_count_u32_elems(node, "iommu-map");
if (err < 0)
@@ -54,6 +57,7 @@ int host1x_memory_context_list_init(struct host1x *host1x)
ctx->dev.bus = &host1x_context_device_bus_type;
ctx->dev.parent = host1x->dev;
ctx->dev.dma_parms = &ctx->dma_parms;
dma_set_max_seg_size(&ctx->dev, UINT_MAX);
err = device_add(&ctx->dev);
@@ -103,62 +107,288 @@ void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl)
cdl->len = 0;
}
struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
static bool hw_usable_for_dev(struct host1x_hw_memory_context *hw, struct device *dev)
{
return hw->dev.iommu->iommu_dev == dev->iommu->iommu_dev;
}
static struct host1x_hw_memory_context *host1x_memory_context_alloc_hw_locked(struct host1x *host1x,
struct device *dev,
struct pid *pid)
{
struct host1x_memory_context_list *cdl = &host1x->context_list;
struct host1x_memory_context *free = NULL;
struct host1x_hw_memory_context *free = NULL, *can_steal = NULL;
struct host1x_memory_context *ctx;
int i;
if (!cdl->len)
return ERR_PTR(-EOPNOTSUPP);
mutex_lock(&cdl->lock);
for (i = 0; i < cdl->len; i++) {
struct host1x_memory_context *cd = &cdl->devs[i];
struct host1x_hw_memory_context *cd = &cdl->devs[i];
if (cd->dev.iommu->iommu_dev != dev->iommu->iommu_dev)
if (!hw_usable_for_dev(cd, dev))
continue;
if (cd->owner == pid) {
refcount_inc(&cd->ref);
mutex_unlock(&cdl->lock);
return cd;
} else if (!cd->owner && !free) {
free = cd;
} else if (!cd->active) {
can_steal = cd;
}
}
if (!free) {
mutex_unlock(&cdl->lock);
if (free)
goto found;
/* Steal */
if (!can_steal)
return ERR_PTR(-EBUSY);
list_for_each_entry(ctx, &can_steal->owners, entry) {
struct host1x_context_mapping *mapping;
ctx->hw = NULL;
ctx->context_dev = NULL;
list_for_each_entry(mapping, &ctx->mappings, entry) {
host1x_bo_unpin(mapping->mapping);
mapping->mapping = NULL;
}
}
put_pid(can_steal->owner);
free = can_steal;
found:
refcount_set(&free->ref, 1);
free->owner = get_pid(pid);
mutex_unlock(&cdl->lock);
INIT_LIST_HEAD(&free->owners);
return free;
}
static void host1x_memory_context_hw_put(struct host1x_hw_memory_context *cd)
{
if (refcount_dec_and_test(&cd->ref)) {
put_pid(cd->owner);
cd->owner = NULL;
}
}
struct host1x_memory_context *host1x_memory_context_alloc(
struct host1x *host1x, struct device *dev, struct pid *pid)
{
struct host1x_memory_context_list *cdl = &host1x->context_list;
struct host1x_memory_context *ctx;
if (!cdl->len)
return ERR_PTR(-EOPNOTSUPP);
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return ERR_PTR(-ENOMEM);
ctx->host = host1x;
ctx->dev = dev;
ctx->pid = get_pid(pid);
refcount_set(&ctx->ref, 1);
INIT_LIST_HEAD(&ctx->mappings);
return ctx;
}
EXPORT_SYMBOL_GPL(host1x_memory_context_alloc);
void host1x_memory_context_get(struct host1x_memory_context *cd)
struct hw_alloc_waiter {
struct completion wait; /* Completion to wait for free hw context */
struct list_head entry;
struct device *dev;
};
int host1x_memory_context_active(struct host1x_memory_context *ctx)
{
refcount_inc(&cd->ref);
struct host1x_memory_context_list *cdl = &ctx->host->context_list;
struct host1x_context_mapping *mapping;
struct host1x_hw_memory_context *hw;
struct hw_alloc_waiter waiter;
bool retrying = false;
int err = 0;
mutex_lock(&cdl->lock);
retry:
if (!ctx->hw) {
hw = host1x_memory_context_alloc_hw_locked(ctx->host, ctx->dev, ctx->pid);
if (PTR_ERR(hw) == -EBUSY) {
/* All contexts busy. Wait for free context. */
if (!retrying)
dev_warn(ctx->dev, "%s: all memory contexts are busy, waiting\n",
current->comm);
init_completion(&waiter.wait);
waiter.dev = ctx->dev;
list_add(&waiter.entry, &cdl->waiters);
mutex_unlock(&cdl->lock);
err = wait_for_completion_interruptible(&waiter.wait);
mutex_lock(&cdl->lock);
list_del(&waiter.entry);
if (err)
goto unlock;
retrying = true;
goto retry;
}
if (IS_ERR(hw)) {
err = PTR_ERR(hw);
goto unlock;
}
ctx->hw = hw;
ctx->context_dev = &hw->dev;
list_add(&ctx->entry, &hw->owners);
list_for_each_entry(mapping, &ctx->mappings, entry) {
mapping->mapping = host1x_bo_pin(
&hw->dev, mapping->bo, mapping->direction, NULL);
if (IS_ERR(mapping->mapping)) {
err = PTR_ERR(mapping->mapping);
mapping->mapping = NULL;
goto unpin;
}
}
}
ctx->hw->active++;
mutex_unlock(&cdl->lock);
return 0;
unpin:
list_for_each_entry(mapping, &ctx->mappings, entry) {
if (mapping->mapping)
host1x_bo_unpin(mapping->mapping);
}
host1x_memory_context_hw_put(ctx->hw);
list_del(&ctx->entry);
ctx->hw = NULL;
unlock:
mutex_unlock(&cdl->lock);
return err;
}
EXPORT_SYMBOL_GPL(host1x_memory_context_active);
struct host1x_context_mapping *host1x_memory_context_map(
struct host1x_memory_context *ctx, struct host1x_bo *bo, enum dma_data_direction direction)
{
struct host1x_memory_context_list *cdl = &ctx->host->context_list;
struct host1x_context_mapping *m;
struct host1x_bo_mapping *bo_m;
m = kzalloc(sizeof(*m), GFP_KERNEL);
if (!m)
return ERR_PTR(-ENOMEM);
m->host = ctx->host;
m->bo = bo;
m->direction = direction;
mutex_lock(&cdl->lock);
if (ctx->hw) {
bo_m = host1x_bo_pin(&ctx->hw->dev, bo, direction, NULL);
if (IS_ERR(bo_m)) {
mutex_unlock(&cdl->lock);
kfree(m);
return ERR_CAST(bo_m);
}
m->mapping = bo_m;
}
list_add(&m->entry, &ctx->mappings);
mutex_unlock(&cdl->lock);
return m;
}
EXPORT_SYMBOL_GPL(host1x_memory_context_map);
void host1x_memory_context_unmap(struct host1x_context_mapping *m)
{
struct host1x_memory_context_list *cdl = &m->host->context_list;
mutex_lock(&cdl->lock);
list_del(&m->entry);
mutex_unlock(&cdl->lock);
if (m->mapping)
host1x_bo_unpin(m->mapping);
kfree(m);
}
EXPORT_SYMBOL_GPL(host1x_memory_context_unmap);
void host1x_memory_context_inactive(struct host1x_memory_context *ctx)
{
struct host1x_memory_context_list *cdl = &ctx->host->context_list;
struct hw_alloc_waiter *waiter;
mutex_lock(&cdl->lock);
if (--ctx->hw->active == 0) {
/* Hardware context becomes eligible for stealing */
list_for_each_entry(waiter, &cdl->waiters, entry) {
if (!hw_usable_for_dev(ctx->hw, waiter->dev))
continue;
complete(&waiter->wait);
/*
* Need to wake up all waiters -- there could be multiple from
* the same process that can use the same freed hardware context.
*/
}
}
mutex_unlock(&cdl->lock);
}
EXPORT_SYMBOL_GPL(host1x_memory_context_inactive);
void host1x_memory_context_get(struct host1x_memory_context *ctx)
{
refcount_inc(&ctx->ref);
}
EXPORT_SYMBOL_GPL(host1x_memory_context_get);
void host1x_memory_context_put(struct host1x_memory_context *cd)
void host1x_memory_context_put(struct host1x_memory_context *ctx)
{
struct host1x_memory_context_list *cdl = &cd->host->context_list;
struct host1x_memory_context_list *cdl = &ctx->host->context_list;
if (refcount_dec_and_mutex_lock(&cd->ref, &cdl->lock)) {
put_pid(cd->owner);
cd->owner = NULL;
if (refcount_dec_and_mutex_lock(&ctx->ref, &cdl->lock)) {
if (ctx->hw) {
list_del(&ctx->entry);
host1x_memory_context_hw_put(ctx->hw);
ctx->hw = NULL;
WARN_ON(!list_empty(&ctx->mappings));
}
put_pid(ctx->pid);
mutex_unlock(&cdl->lock);
kfree(ctx);
}
}
EXPORT_SYMBOL_GPL(host1x_memory_context_put);

View File

@@ -2,7 +2,7 @@
/*
* Host1x context devices
*
* Copyright (c) 2020, NVIDIA Corporation.
* SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#ifndef __HOST1X_CONTEXT_H
@@ -17,8 +17,24 @@ extern struct bus_type host1x_context_device_bus_type;
struct host1x_memory_context_list {
struct mutex lock;
struct host1x_memory_context *devs;
struct host1x_hw_memory_context *devs;
unsigned int len;
struct list_head waiters;
};
struct host1x_hw_memory_context {
struct host1x *host;
refcount_t ref;
struct pid *owner;
struct device_dma_parameters dma_parms;
struct device dev;
u64 dma_mask;
u32 stream_id;
struct list_head owners;
unsigned int active;
};
#ifdef CONFIG_IOMMU_API

View File

@@ -2,7 +2,7 @@
/*
* Tegra host1x driver
*
* Copyright (c) 2010-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
* SPDX-FileCopyrightText: Copyright (c) 2010-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -620,9 +620,16 @@ static struct iommu_domain *host1x_iommu_attach(struct host1x *host)
if (err < 0)
goto put_group;
#if defined(NV_IOMMU_PAGING_DOMAIN_ALLOC_PRESENT) /* Linux v6.11 */
host->domain = iommu_paging_domain_alloc(host->dev);
if (IS_ERR(host->domain)) {
err = PTR_ERR(host->domain);
host->domain = NULL;
#else
host->domain = iommu_domain_alloc(&platform_bus_type);
if (!host->domain) {
err = -ENOMEM;
#endif
goto put_cache;
}
@@ -1102,6 +1109,18 @@ static const struct dev_pm_ops host1x_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(host1x_runtime_suspend, host1x_runtime_resume)
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void host1x_remove_wrapper(struct platform_device *pdev)
{
host1x_remove(pdev);
}
#else
static int host1x_remove_wrapper(struct platform_device *pdev)
{
return host1x_remove(pdev);
}
#endif
static struct platform_driver tegra_host1x_driver = {
.driver = {
.name = "tegra-host1x",
@@ -1109,7 +1128,7 @@ static struct platform_driver tegra_host1x_driver = {
.pm = &host1x_pm_ops,
},
.probe = host1x_probe,
.remove = host1x_remove,
.remove = host1x_remove_wrapper,
};
static struct platform_driver * const drivers[] = {

View File

@@ -12,6 +12,7 @@
#include <trace/events/host1x.h>
#include "../channel.h"
#include "../context.h"
#include "../dev.h"
#include "../intr.h"
#include "../job.h"
@@ -89,7 +90,7 @@ static void submit_setclass(struct host1x_job *job, u32 next_class)
* firmware stream ID.
*/
if (job->memory_context)
stream_id = job->memory_context->stream_id;
stream_id = job->memory_context->hw->stream_id;
else
stream_id = job->engine_fallback_streamid;

View File

@@ -495,12 +495,26 @@ int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
struct host1x_memory_context {
struct host1x *host;
refcount_t ref;
struct pid *owner;
struct device *dev; /* Owning engine */
struct pid *pid;
struct device dev;
u64 dma_mask;
u32 stream_id;
refcount_t ref;
struct host1x_hw_memory_context *hw;
struct device *context_dev; /* Context device */
struct list_head entry; /* Entry in hw_memory_context's list */
struct list_head mappings; /* List of mappings */
};
struct host1x_context_mapping {
struct host1x *host;
struct host1x_bo_mapping *mapping;
struct host1x_bo *bo;
enum dma_data_direction direction;
struct list_head entry;
};
#ifdef CONFIG_IOMMU_API
@@ -509,6 +523,11 @@ struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
struct pid *pid);
void host1x_memory_context_get(struct host1x_memory_context *cd);
void host1x_memory_context_put(struct host1x_memory_context *cd);
int host1x_memory_context_active(struct host1x_memory_context *cd);
void host1x_memory_context_inactive(struct host1x_memory_context *cd);
struct host1x_context_mapping *host1x_memory_context_map(
struct host1x_memory_context *ctx, struct host1x_bo *bo, enum dma_data_direction direction);
void host1x_memory_context_unmap(struct host1x_context_mapping *m);
#else
static inline struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
struct pid *pid)
@@ -523,6 +542,25 @@ static inline void host1x_memory_context_get(struct host1x_memory_context *cd)
static inline void host1x_memory_context_put(struct host1x_memory_context *cd)
{
}
static inline int host1x_memory_context_active(struct host1x_memory_context *cd)
{
return -ENODEV;
}
static inline void host1x_memory_context_inactive(struct host1x_memory_context *cd)
{
}
static inline struct host1x_context_mapping *host1x_memory_context_map(
struct host1x_memory_context *ctx, struct host1x_bo *bo, enum dma_data_direction direction)
{
return ERR_PTR(-ENODEV);
}
static inline void host1x_memory_context_unmap(struct host1x_context_mapping *m)
{
}
#endif
int host1x_actmon_read_avg_count(struct host1x_client *client);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 NVIDIA Corporation
* SPDX-FileCopyrightText: Copyright (c) 2013-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
@@ -20,6 +20,8 @@
* OF THIS SOFTWARE.
*/
#include <nvidia/conftest.h>
#include <linux/clk.h>
#include <linux/host1x-next.h>
#include <linux/io.h>
@@ -546,11 +548,23 @@ static int tegra_mipi_remove(struct platform_device *pdev)
return 0;
}
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_mipi_remove_wrapper(struct platform_device *pdev)
{
tegra_mipi_remove(pdev);
}
#else
static int tegra_mipi_remove_wrapper(struct platform_device *pdev)
{
return tegra_mipi_remove(pdev);
}
#endif
struct platform_driver tegra_mipi_driver = {
.driver = {
.name = "tegra-mipi",
.of_match_table = tegra_mipi_of_match,
},
.probe = tegra_mipi_probe,
.remove = tegra_mipi_remove,
.remove = tegra_mipi_remove_wrapper,
};

View File

@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
# Copyright (c) 2022-2025, NVIDIA CORPORATION. All rights reserved.
obj-m += i2c-nvvrs11.o
obj-m += i2c-tegra-slave-byte.o

View File

@@ -2,7 +2,7 @@
/*
* Voltage Regulator Specification: VRS11 High Current Voltage Regulator
*
* Copyright (C) 2022-2023 NVIDIA CORPORATION. All rights reserved.
* Copyright (C) 2022-2024 NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -120,8 +120,8 @@ static ssize_t show_loopA_rail_power(struct device *dev,
if (current_A < 0)
return current_A;
power = (voltage_A * current_A)/1000;
return sprintf(buf, "%u W\n", power);
power = (voltage_A * current_A);
return sprintf(buf, "%u mW\n", power);
}
static ssize_t show_loopB_rail_name(struct device *dev,
@@ -180,9 +180,9 @@ static ssize_t show_loopB_rail_power(struct device *dev,
if (current_B < 0)
return current_B;
power = (voltage_B * current_B)/1000;
power = (voltage_B * current_B);
return sprintf(buf, "%u W\n", power);
return sprintf(buf, "%u mW\n", power);
}
static DEVICE_ATTR(loopA_rail_name, S_IRUGO, show_loopA_rail_name, NULL);

View File

@@ -0,0 +1,475 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
#define I2C_SL_CNFG 0x20
#define I2C_SL_CNFG_ENABLE_SL BIT(3)
#define I2C_SL_CNFG_NEW_SL BIT(2)
#define I2C_SL_RCVD 0x24
#define I2C_SL_STATUS 0x28
#define I2C_SL_STATUS_END_TRANS BIT(4)
#define I2C_SL_STATUS_SL_IRQ BIT(3)
#define I2C_SL_STATUS_RCVD BIT(2)
#define I2C_SL_STATUS_RNW BIT(1)
#define I2C_SL_ADDR1 0x2c
#define I2C_SL_ADDR2 0x30
#define I2C_SL_ADDR2_MASK 0x1FFFF
#define I2C_7BIT_ADDR_MASK 0x7F
#define I2C_TLOW_SEXT 0x34
#define I2C_SL_DELAY_COUNT 0x3c
#define I2C_SL_DELAY_COUNT_RESET 0x1e
#define I2C_SL_INT_MASK 0x40
#define I2C_SL_INT_SOURCE 0x44
#define I2C_SL_INT_SET 0x48
#define I2C_FIFO_CONTROL 0x5c
#define I2C_INTERRUPT_MASK_REGISTER 0x64
#define I2C_INTERRUPT_STATUS_REGISTER 0x68
#define I2C_INTERRUPT_SOURCE_REGISTER 0x70
#define I2C_INTERRUPT_SLV_WR2RD BIT(26)
#define I2C_INTERRUPT_SET_REGISTER 0x74
#define I2C_CONFIG_LOAD 0x8c
#define I2C_TIMEOUT_CONFIG_LOAD BIT(2)
#define I2C_CONFIG_LOAD_SLV BIT(1)
#define I2C_CONFIG_LOAD_TIMEOUT 1000000
#define I2C_CLKEN_OVERRIDE 0x90
#define I2C_DEBUG_CONTROL 0xa4
struct tegra_i2cslv_dev {
struct device *dev;
struct i2c_adapter adap;
struct clk *div_clk;
struct reset_control *rstc;
void __iomem *base;
struct i2c_client *slave;
raw_spinlock_t xfer_lock;
};
static inline u32 tegra_i2cslv_readl(struct tegra_i2cslv_dev *i2cslv_dev,
unsigned long reg)
{
return readl(i2cslv_dev->base + reg);
}
static inline void tegra_i2cslv_writel(struct tegra_i2cslv_dev *i2cslv_dev,
unsigned long val, unsigned long reg)
{
writel(val, i2cslv_dev->base + reg);
}
static void tegra_i2cslv_dump_reg(struct tegra_i2cslv_dev *i2cslv_dev)
{
dev_warn(i2cslv_dev->dev, "I2C_I2C_SL_INT_SOURCE_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_SL_INT_SOURCE));
dev_warn(i2cslv_dev->dev, "I2C_INTERRUPT_STATUS_REGISTER_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_INTERRUPT_STATUS_REGISTER));
dev_warn(i2cslv_dev->dev, "I2C_I2C_SL_STATUS_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_SL_STATUS));
dev_warn(i2cslv_dev->dev, "I2C_INTERRUPT_SOURCE_REGISTER 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_INTERRUPT_SOURCE_REGISTER));
dev_warn(i2cslv_dev->dev, "I2C_I2C_SL_CNFG_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_SL_CNFG));
dev_warn(i2cslv_dev->dev, "I2C_SL_ADDR1 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_SL_ADDR1));
dev_warn(i2cslv_dev->dev, "I2C_INTERRUPT_MASK_REGISTER_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_INTERRUPT_MASK_REGISTER));
dev_warn(i2cslv_dev->dev, "I2C_I2C_SL_INT_MASK_0 0x%x\n",
tegra_i2cslv_readl(i2cslv_dev, I2C_SL_INT_MASK));
}
static int tegra_i2cslv_load_config(struct tegra_i2cslv_dev *i2cslv_dev)
{
u32 i2c_load_config_reg, val;
int ret;
i2c_load_config_reg = tegra_i2cslv_readl(i2cslv_dev, I2C_CONFIG_LOAD);
i2c_load_config_reg |= I2C_CONFIG_LOAD_SLV;
tegra_i2cslv_writel(i2cslv_dev, i2c_load_config_reg, I2C_CONFIG_LOAD);
ret = readl_poll_timeout_atomic(i2cslv_dev->base +
I2C_CONFIG_LOAD, val,
!(val & I2C_CONFIG_LOAD_SLV),
1000, I2C_CONFIG_LOAD_TIMEOUT);
if (ret)
dev_err(i2cslv_dev->dev, "ERR unable to load i2cslv config\n");
return ret;
}
/* tegra_i2cslv_handle_rx - To get the data byte from bus and provide the
* data to client driver
*/
static void tegra_i2cslv_handle_rx(struct tegra_i2cslv_dev *i2cslv_dev,
const unsigned long i2c_int_src,
const unsigned long i2c_slv_src)
{
u8 value;
if (i2c_slv_src & I2C_SL_STATUS_END_TRANS) {
/* clear the interrupts to release the SCL line */
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_END_TRANS |
I2C_SL_STATUS_SL_IRQ, I2C_SL_STATUS);
i2c_slave_event(i2cslv_dev->slave, I2C_SLAVE_STOP, &value);
} else {
value = (u8)tegra_i2cslv_readl(i2cslv_dev, I2C_SL_RCVD);
/* Send the received data to client driver */
i2c_slave_event(i2cslv_dev->slave, I2C_SLAVE_WRITE_RECEIVED, &value);
/* clear the interrupt to release the SCL line */
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_SL_IRQ, I2C_SL_STATUS);
}
}
/* tegra_i2cslv_handle_tx - To get the data byte fron client driver and
* send it to master over bus.
*/
static void tegra_i2cslv_handle_tx(struct tegra_i2cslv_dev *i2cslv_dev,
const unsigned long i2c_int_src,
const unsigned long i2c_slv_src)
{
u8 value;
if (i2c_slv_src & I2C_SL_STATUS_END_TRANS) {
/* clear the interrupt to release the SCL line */
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_END_TRANS |
I2C_SL_STATUS_SL_IRQ, I2C_SL_STATUS);
i2c_slave_event(i2cslv_dev->slave, I2C_SLAVE_STOP, &value);
} else {
/* clear the interrupt to release the SCL line */
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_SL_IRQ, I2C_SL_STATUS);
/* Get the data byte from client driver*/
i2c_slave_event(i2cslv_dev->slave, I2C_SLAVE_READ_PROCESSED, &value);
tegra_i2cslv_writel(i2cslv_dev, value, I2C_SL_RCVD);
}
}
static int tegra_i2cslv_init(struct tegra_i2cslv_dev *i2cslv_dev)
{
u32 reg;
int ret;
ret = clk_enable(i2cslv_dev->div_clk);
if (ret < 0) {
dev_err(i2cslv_dev->dev, "Enable div-clk failed: %d\n", ret);
return ret;
}
/* Reset the controller */
reset_control_assert(i2cslv_dev->rstc);
udelay(2);
reset_control_deassert(i2cslv_dev->rstc);
/* Program the 7-bit slave address */
tegra_i2cslv_writel(i2cslv_dev, i2cslv_dev->slave->addr &
I2C_7BIT_ADDR_MASK, I2C_SL_ADDR1);
/* Specify its 7-bit address mode */
reg = tegra_i2cslv_readl(i2cslv_dev, I2C_SL_ADDR2);
reg &= ~(I2C_SL_ADDR2_MASK);
tegra_i2cslv_writel(i2cslv_dev, reg, I2C_SL_ADDR2);
/* Unmask WR2RD interrupt, just to clear it */
tegra_i2cslv_writel(i2cslv_dev, (I2C_INTERRUPT_SLV_WR2RD),
I2C_INTERRUPT_MASK_REGISTER);
tegra_i2cslv_writel(i2cslv_dev, (I2C_SL_STATUS_END_TRANS |
I2C_SL_STATUS_SL_IRQ | I2C_SL_STATUS_RCVD),
I2C_SL_INT_MASK);
reg = tegra_i2cslv_readl(i2cslv_dev, I2C_SL_CNFG);
reg |= (I2C_SL_CNFG_NEW_SL | I2C_SL_CNFG_ENABLE_SL);
tegra_i2cslv_writel(i2cslv_dev, reg, I2C_SL_CNFG);
return tegra_i2cslv_load_config(i2cslv_dev);
}
static void tegra_i2cslv_deinit(struct tegra_i2cslv_dev *i2cslv_dev)
{
tegra_i2cslv_writel(i2cslv_dev, 0, I2C_INTERRUPT_MASK_REGISTER);
tegra_i2cslv_writel(i2cslv_dev, 0, I2C_SL_INT_MASK);
clk_disable(i2cslv_dev->div_clk);
}
static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id)
{
struct tegra_i2cslv_dev *i2cslv_dev = dev_id;
u32 i2c_int_src, i2c_slv_int_src, i2c_slv_sts;
u8 value;
unsigned long flags;
raw_spin_lock_irqsave(&i2cslv_dev->xfer_lock, flags);
i2c_int_src = tegra_i2cslv_readl(i2cslv_dev,
I2C_INTERRUPT_SOURCE_REGISTER);
i2c_slv_int_src = tegra_i2cslv_readl(i2cslv_dev, I2C_SL_INT_SOURCE);
i2c_slv_sts = tegra_i2cslv_readl(i2cslv_dev, I2C_SL_STATUS);
/* Address received */
if ((i2c_slv_int_src & I2C_SL_STATUS_SL_IRQ) &&
(i2c_slv_int_src & I2C_SL_STATUS_RCVD)) {
/* End of transfer of previous transaction, just clear it */
if (i2c_slv_int_src & I2C_SL_STATUS_END_TRANS) {
i2c_slave_event(i2cslv_dev->slave, I2C_SLAVE_STOP,
&value);
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_END_TRANS,
I2C_SL_STATUS);
}
/* Clear the interrupt */
tegra_i2cslv_writel(i2cslv_dev, I2C_SL_STATUS_SL_IRQ |
I2C_SL_STATUS_RCVD, I2C_SL_STATUS);
/* if RNW, master issued read. */
if (i2c_slv_sts & I2C_SL_STATUS_RNW) {
i2c_slave_event(i2cslv_dev->slave,
I2C_SLAVE_READ_REQUESTED, &value);
tegra_i2cslv_writel(i2cslv_dev, value,
I2C_SL_RCVD);
} else {
i2c_slave_event(i2cslv_dev->slave,
I2C_SLAVE_WRITE_REQUESTED, &value);
}
goto done;
}
if (unlikely(i2c_int_src & I2C_INTERRUPT_SLV_WR2RD)) {
/* Clear WR2RD interrupt */
tegra_i2cslv_writel(i2cslv_dev, I2C_INTERRUPT_SLV_WR2RD,
I2C_INTERRUPT_STATUS_REGISTER);
goto done;
}
if ((i2c_slv_int_src & I2C_SL_STATUS_SL_IRQ)) {
if (!(i2c_slv_sts & I2C_SL_STATUS_RNW)) {
/* Master write and Slave receive */
tegra_i2cslv_handle_rx(i2cslv_dev, i2c_int_src,
i2c_slv_int_src);
goto done;
} else if (i2c_slv_sts & I2C_SL_STATUS_RNW) {
/* Master read and slave write */
tegra_i2cslv_handle_tx(i2cslv_dev, i2c_int_src,
i2c_slv_int_src);
goto done;
}
} else {
dev_err(i2cslv_dev->dev, "Slave IRQ not set\n");
goto err;
}
err:
tegra_i2cslv_dump_reg(i2cslv_dev);
tegra_i2cslv_init(i2cslv_dev);
done:
raw_spin_unlock_irqrestore(&i2cslv_dev->xfer_lock, flags);
return IRQ_HANDLED;
}
static int tegra_reg_slave(struct i2c_client *slave)
{
struct tegra_i2cslv_dev *i2cslv_dev =
i2c_get_adapdata(slave->adapter);
int ret;
if (i2cslv_dev->slave)
return -EBUSY;
if (slave->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT;
i2cslv_dev->slave = slave;
ret = clk_enable(i2cslv_dev->div_clk);
if (ret < 0) {
dev_err(i2cslv_dev->dev, "Enable div-clk failed: %d\n", ret);
return ret;
}
return tegra_i2cslv_init(i2cslv_dev);
}
static int tegra_unreg_slave(struct i2c_client *slave)
{
struct tegra_i2cslv_dev *i2cslv_dev =
i2c_get_adapdata(slave->adapter);
WARN_ON(!i2cslv_dev->slave);
tegra_i2cslv_deinit(i2cslv_dev);
i2cslv_dev->slave = NULL;
return 0;
}
static u32 tegra_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SLAVE;
}
static const struct i2c_algorithm tegra_i2cslv_algo = {
.functionality = tegra_i2c_func,
.reg_slave = tegra_reg_slave,
.unreg_slave = tegra_unreg_slave,
};
static int tegra_i2cslv_probe(struct platform_device *pdev)
{
struct tegra_i2cslv_dev *i2cslv_dev;
struct i2c_adapter *adap;
int irq, ret;
i2cslv_dev = devm_kzalloc(&pdev->dev, sizeof(*i2cslv_dev), GFP_KERNEL);
if (!i2cslv_dev)
return -ENOMEM;
i2cslv_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(i2cslv_dev->base))
return PTR_ERR(i2cslv_dev->base);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "failed to get IRQ %d\n", irq);
return irq;
}
i2cslv_dev->div_clk = devm_clk_get(&pdev->dev, "div-clk");
if (IS_ERR(i2cslv_dev->div_clk)) {
dev_err(&pdev->dev, "missing controller clock");
return PTR_ERR(i2cslv_dev->div_clk);
}
i2cslv_dev->rstc = devm_reset_control_get(&pdev->dev, "i2c");
if (IS_ERR(i2cslv_dev->rstc)) {
dev_err(&pdev->dev, "missing controller reset\n");
return PTR_ERR(i2cslv_dev->rstc);
}
i2cslv_dev->dev = &pdev->dev;
raw_spin_lock_init(&i2cslv_dev->xfer_lock);
adap = &i2cslv_dev->adap;
adap->algo = &tegra_i2cslv_algo;
adap->class = I2C_CLASS_DEPRECATED;
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(adap, i2cslv_dev);
platform_set_drvdata(pdev, i2cslv_dev);
strscpy(adap->name, pdev->name, sizeof(adap->name));
ret = clk_prepare(i2cslv_dev->div_clk);
if (ret < 0) {
dev_err(&pdev->dev, "clock prepare failed %d\n", ret);
return ret;
}
ret = devm_request_irq(&pdev->dev, irq, tegra_i2cslv_isr,
0, dev_name(&pdev->dev), i2cslv_dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", irq);
clk_unprepare(i2cslv_dev->div_clk);
return ret;
}
ret = i2c_add_adapter(&i2cslv_dev->adap);
if (ret) {
dev_err(&pdev->dev, "Failed to add I2C adapter\n");
clk_unprepare(i2cslv_dev->div_clk);
return ret;
}
return 0;
}
static int tegra_i2cslv_remove(struct platform_device *pdev)
{
struct tegra_i2cslv_dev *i2cslv_dev = platform_get_drvdata(pdev);
i2c_del_adapter(&i2cslv_dev->adap);
clk_unprepare(i2cslv_dev->div_clk);
return 0;
}
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_i2cslv_remove_wrapper(struct platform_device *pdev)
{
tegra_i2cslv_remove(pdev);
}
#else
static int tegra_i2cslv_remove_wrapper(struct platform_device *pdev)
{
return tegra_i2cslv_remove(pdev);
}
#endif
#ifdef CONFIG_PM_SLEEP
static int tegra_i2cslv_suspend(struct device *dev)
{
struct tegra_i2cslv_dev *i2cslv_dev = dev_get_drvdata(dev);
unsigned long flags;
raw_spin_lock_irqsave(&i2cslv_dev->xfer_lock, flags);
tegra_i2cslv_deinit(i2cslv_dev);
raw_spin_unlock_irqrestore(&i2cslv_dev->xfer_lock, flags);
return 0;
}
static int tegra_i2cslv_resume(struct device *dev)
{
struct tegra_i2cslv_dev *i2cslv_dev = dev_get_drvdata(dev);
unsigned long flags;
int ret;
raw_spin_lock_irqsave(&i2cslv_dev->xfer_lock, flags);
ret = tegra_i2cslv_init(i2cslv_dev);
raw_spin_unlock_irqrestore(&i2cslv_dev->xfer_lock, flags);
return ret;
}
#endif
static const struct dev_pm_ops tegra_i2cslv_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tegra_i2cslv_suspend, tegra_i2cslv_resume)
};
static const struct of_device_id tegra_i2cslv_of_match[] = {
{.compatible = "nvidia,tegra-i2c-slave-byte",},
{}
};
MODULE_DEVICE_TABLE(of, tegra_i2cslv_of_match);
static struct platform_driver tegra_i2cslv_driver = {
.probe = tegra_i2cslv_probe,
.remove = tegra_i2cslv_remove_wrapper,
.driver = {
.name = "tegra-i2cslv",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(tegra_i2cslv_of_match),
.pm = &tegra_i2cslv_pm_ops,
},
};
module_platform_driver(tegra_i2cslv_driver);
MODULE_AUTHOR("Shardar Shariff Md <smohammed@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra I2C slave driver");
MODULE_LICENSE("GPL v2");

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
/*
* Copyright (c) 2020-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
* imx477_mode_tbls.h - imx477 sensor mode tables
*/
#ifndef __IMX477_I2C_TABLES__
@@ -575,249 +575,9 @@ static const imx477_reg imx477_mode_1920x1080_60fps[] = {
{IMX477_TABLE_END, 0x0000}
};
static const imx477_reg imx477_mode_3840x2160_30fps_4lane[] = {
{0x0112, 0x0A},
{0x0113, 0x0A},
{0x0114, 0x03},
{0x0342, 0x16},
{0x0343, 0xC8},
{0x0340, 0x12},
{0x0341, 0xC0},
{0x0344, 0x00},
{0x0345, 0x00},
{0x0346, 0x01},
{0x0347, 0xB8},
{0x0348, 0x0F},
{0x0349, 0xD7},
{0x034A, 0x0A},
{0x034B, 0x27},
{0x00E3, 0x00},
{0x00E4, 0x00},
{0x00FC, 0x0A},
{0x00FD, 0x0A},
{0x00FE, 0x0A},
{0x00FF, 0x0A},
{0x0E13, 0x00},
{0x0220, 0x00},
{0x0221, 0x11},
{0x0381, 0x01},
{0x0383, 0x01},
{0x0385, 0x01},
{0x0387, 0x01},
{0x0900, 0x00},
{0x0901, 0x11},
{0x0902, 0x02},
{0x3140, 0x02},
{0x3C00, 0x00},
{0x3C01, 0x03},
{0x3C02, 0xDC},
{0x3F0D, 0x00},
{0x5748, 0x07},
{0x5749, 0xFF},
{0x574A, 0x00},
{0x574B, 0x00},
{0x7B75, 0x0E},
{0x7B76, 0x09},
{0x7B77, 0x0C},
{0x7B78, 0x06},
{0x7B79, 0x3B},
{0x7B53, 0x01},
{0x9369, 0x5A},
{0x936B, 0x55},
{0x936D, 0x28},
{0x9304, 0x03},
{0x9305, 0x00},
{0x9E9A, 0x2F},
{0x9E9B, 0x2F},
{0x9E9C, 0x2F},
{0x9E9D, 0x00},
{0x9E9E, 0x00},
{0x9E9F, 0x00},
{0xA2A9, 0x60},
{0xA2B7, 0x00},
{0x0401, 0x00},
{0x0404, 0x00},
{0x0405, 0x10},
{0x0408, 0x00},
{0x0409, 0x6C},
{0x040A, 0x00},
{0x040B, 0x00},
{0x040C, 0x0F},
{0x040D, 0x00},
{0x040E, 0x08},
{0x040F, 0x70},
{0x034C, 0x0F},
{0x034D, 0x00},
{0x034E, 0x08},
{0x034F, 0x70},
{0x0301, 0x05},
{0x0303, 0x02},
{0x0305, 0x02},
{0x0306, 0x00},
{0x0307, 0xAF},
{0x0309, 0x0A},
{0x030B, 0x01},
{0x030D, 0x02},
{0x030E, 0x00},
{0x030F, 0x7D},
{0x0310, 0x01},
{0x0820, 0x17},
{0x0821, 0x70},
{0x0822, 0x00},
{0x0823, 0x00},
{0x080A, 0x00},
{0x080B, 0x97},
{0x080C, 0x00},
{0x080D, 0x5F},
{0x080E, 0x00},
{0x080F, 0x9F},
{0x0810, 0x00},
{0x0811, 0x6F},
{0x0812, 0x00},
{0x0813, 0x6F},
{0x0814, 0x00},
{0x0815, 0x57},
{0x0816, 0x01},
{0x0817, 0x87},
{0x0818, 0x00},
{0x0819, 0x4F},
{0xE04C, 0x00},
{0xE04D, 0x9F},
{0xE04E, 0x00},
{0xE04F, 0x1F},
{0x3E20, 0x01},
{0x3E37, 0x00},
{0x3F50, 0x00},
{0x3F56, 0x00},
{0x3F57, 0xA7},
{IMX477_TABLE_WAIT_MS, IMX477_WAIT_MS},
{IMX477_TABLE_END, 0x0000}
};
static const imx477_reg imx477_mode_1920x1080_60fps_4lane[] = {
{0x0112, 0x0A},
{0x0113, 0x0A},
{0x0114, 0x03},
{0x0342, 0x0C},
{0x0343, 0x04},
{0x0340, 0x11},
{0x0341, 0xC6},
{0x0344, 0x00},
{0x0345, 0x00},
{0x0346, 0x01},
{0x0347, 0xB8},
{0x0348, 0x0F},
{0x0349, 0xD7},
{0x034A, 0x0A},
{0x034B, 0x27},
{0x00E3, 0x00},
{0x00E4, 0x00},
{0x00FC, 0x0A},
{0x00FD, 0x0A},
{0x00FE, 0x0A},
{0x00FF, 0x0A},
{0x0220, 0x00},
{0x0221, 0x11},
{0x0381, 0x01},
{0x0383, 0x01},
{0x0385, 0x01},
{0x0387, 0x01},
{0x0900, 0x01},
{0x0901, 0x22},
{0x0902, 0x02},
{0x3140, 0x02},
{0x3C00, 0x00},
{0x3C01, 0x01},
{0x3C02, 0x9C},
{0x3F0D, 0x00},
{0x5748, 0x00},
{0x5749, 0x00},
{0x574A, 0x00},
{0x574B, 0xA4},
{0x7B75, 0x0E},
{0x7B76, 0x09},
{0x7B77, 0x08},
{0x7B78, 0x06},
{0x7B79, 0x34},
{0x7B53, 0x00},
{0x9369, 0x73},
{0x936B, 0x64},
{0x936D, 0x5F},
{0x9304, 0x03},
{0x9305, 0x80},
{0x9E9A, 0x2F},
{0x9E9B, 0x2F},
{0x9E9C, 0x2F},
{0x9E9D, 0x00},
{0x9E9E, 0x00},
{0x9E9F, 0x00},
{0xA2A9, 0x27},
{0xA2B7, 0x03},
{0x0401, 0x00},
{0x0404, 0x00},
{0x0405, 0x10},
{0x0408, 0x00},
{0x0409, 0x36},
{0x040A, 0x00},
{0x040B, 0x00},
{0x040C, 0x07},
{0x040D, 0x80},
{0x040E, 0x04},
{0x040F, 0x38},
{0x034C, 0x07},
{0x034D, 0x80},
{0x034E, 0x04},
{0x034F, 0x38},
{0x0301, 0x05},
{0x0303, 0x02},
{0x0305, 0x02},
{0x0306, 0x00},
{0x0307, 0xAF},
{0x0309, 0x0A},
{0x030B, 0x01},
{0x030D, 0x02},
{0x030E, 0x00},
{0x030F, 0x7D},
{0x0310, 0x01},
{0x0820, 0x17},
{0x0821, 0x70},
{0x0822, 0x00},
{0x0823, 0x00},
{0x080A, 0x00},
{0x080B, 0x97},
{0x080C, 0x00},
{0x080D, 0x5F},
{0x080E, 0x00},
{0x080F, 0x9F},
{0x0810, 0x00},
{0x0811, 0x6F},
{0x0812, 0x00},
{0x0813, 0x6F},
{0x0814, 0x00},
{0x0815, 0x57},
{0x0816, 0x01},
{0x0817, 0x87},
{0x0818, 0x00},
{0x0819, 0x4F},
{0xE04C, 0x00},
{0xE04D, 0x9F},
{0xE04E, 0x00},
{0xE04F, 0x1F},
{0x3E20, 0x01},
{0x3E37, 0x00},
{0x3F50, 0x00},
{0x3F56, 0x00},
{0x3F57, 0x58},
{0X3FF9, 0x01},
{IMX477_TABLE_WAIT_MS, IMX477_WAIT_MS},
{IMX477_TABLE_END, 0x0000}
};
enum {
IMX477_MODE_3840x2160_30FPS,
IMX477_MODE_1920x1080_60FPS,
IMX477_MODE_3840x2160_30FPS_4LANE,
IMX477_MODE_1920x1080_60FPS_4LANE,
IMX477_MODE_COMMON,
IMX477_START_STREAM,
IMX477_STOP_STREAM,
@@ -826,8 +586,6 @@ enum {
static const imx477_reg *mode_table[] = {
[IMX477_MODE_3840x2160_30FPS] = imx477_mode_3840x2160_30fps,
[IMX477_MODE_1920x1080_60FPS] = imx477_mode_1920x1080_60fps,
[IMX477_MODE_3840x2160_30FPS_4LANE] = imx477_mode_3840x2160_30fps_4lane,
[IMX477_MODE_1920x1080_60FPS_4LANE] = imx477_mode_1920x1080_60fps_4lane,
[IMX477_MODE_COMMON] = imx477_mode_common,
[IMX477_START_STREAM] = imx477_start,
[IMX477_STOP_STREAM] = imx477_stop,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* imx390.c - imx390 sensor driver
* Copyright (c) 2020, RidgeRun. All rights reserved.
@@ -23,32 +23,17 @@
#include "../platform/tegra/camera/camera_gpio.h"
#include "imx390_mode_tbls.h"
/* imx390 - sensor parameters */
#define IMX390_MIN_GAIN (0)
#define IMX390_MAX_GAIN (978)
#define IMX390_ANALOG_GAIN_C0 (1024)
#define IMX390_SHIFT_8_BITS (8)
#define IMX390_MIN_COARSE_EXPOSURE (1)
#define IMX390_MAX_COARSE_DIFF (10)
#define IMX390_MASK_LSB_2_BITS 0x0003
#define IMX390_MASK_LSB_8_BITS 0x00ff
#define IMX390_MIN_FRAME_LENGTH (3092)
#define IMX390_MAX_FRAME_LENGTH (0x1FFFF)
/* imx390 sensor register address */
#define IMX390_MODEL_ID_ADDR_MSB 0x0000
#define IMX390_MODEL_ID_ADDR_LSB 0x0001
#define IMX390_ANALOG_GAIN_ADDR_MSB 0x0204
#define IMX390_ANALOG_GAIN_ADDR_LSB 0x0205
#define IMX390_DIGITAL_GAIN_ADDR_MSB 0x020e
#define IMX390_DIGITAL_GAIN_ADDR_LSB 0x020f
#define IMX390_FRAME_LENGTH_ADDR_MSB 0x0340
#define IMX390_FRAME_LENGTH_ADDR_LSB 0x0341
#define IMX390_COARSE_INTEG_TIME_ADDR_MSB 0x0202
#define IMX390_COARSE_INTEG_TIME_ADDR_LSB 0x0203
#define IMX390_FINE_INTEG_TIME_ADDR_MSB 0x0200
#define IMX390_FINE_INTEG_TIME_ADDR_LSB 0x0201
#define IMX390_GROUP_HOLD_ADDR 0x0104
#define IMX390_PGA_GAIN_SP1H 0x0024
#define IMX390_COARSE_TIME_SHS1_ADDR_MSB 0x000E
#define IMX390_COARSE_TIME_SHS1_ADDR_MID 0x000D
#define IMX390_COARSE_TIME_SHS1_ADDR_LSB 0x000C
#define IMX390_COARSE_TIME_SHS2_ADDR_MSB 0x0012
#define IMX390_COARSE_TIME_SHS2_ADDR_MID 0x0011
#define IMX390_COARSE_TIME_SHS2_ADDR_LSB 0x0010
#define IMX390_GROUP_HOLD_ADDR 0x0008
#define IMX390_DEFAULT_FRAME_LENGTH (1250)
static const struct of_device_id imx390_of_match[] = {
{.compatible = "sony,imx390",},
@@ -59,6 +44,7 @@ MODULE_DEVICE_TABLE(of, imx390_of_match);
static const u32 ctrl_cid_list[] = {
TEGRA_CAMERA_CID_GAIN,
TEGRA_CAMERA_CID_EXPOSURE,
TEGRA_CAMERA_CID_EXPOSURE_SHORT,
TEGRA_CAMERA_CID_FRAME_RATE,
TEGRA_CAMERA_CID_HDR_EN,
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
@@ -79,31 +65,38 @@ static const struct regmap_config sensor_regmap_config = {
.cache_type = REGCACHE_NONE,
};
static inline void imx390_get_frame_length_regs(imx390_reg *regs,
u32 frame_length)
static inline void imx390_get_coarse_time_regs_shs1(imx390_reg *regs,
u32 coarse_time)
{
regs->addr = IMX390_FRAME_LENGTH_ADDR_MSB;
regs->val = (frame_length >> 8) & 0xff;
(regs + 1)->addr = IMX390_FRAME_LENGTH_ADDR_LSB;
(regs + 1)->val = (frame_length) & 0xff;
regs->addr = IMX390_COARSE_TIME_SHS1_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x0f;
(regs + 1)->addr = IMX390_COARSE_TIME_SHS1_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS1_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx390_get_coarse_integ_time_regs(imx390_reg *regs,
u32 coarse_time)
static inline void imx390_get_coarse_time_regs_shs2(imx390_reg *regs,
u32 coarse_time)
{
regs->addr = IMX390_COARSE_INTEG_TIME_ADDR_MSB;
regs->val = (coarse_time >> 8) & 0xff;
(regs + 1)->addr = IMX390_COARSE_INTEG_TIME_ADDR_LSB;
(regs + 1)->val = (coarse_time) & 0xff;
regs->addr = IMX390_COARSE_TIME_SHS2_ADDR_MSB;
regs->val = (coarse_time >> 16) & 0x0f;
(regs + 1)->addr = IMX390_COARSE_TIME_SHS2_ADDR_MID;
(regs + 1)->val = (coarse_time >> 8) & 0xff;
(regs + 2)->addr = IMX390_COARSE_TIME_SHS2_ADDR_LSB;
(regs + 2)->val = (coarse_time) & 0xff;
}
static inline void imx390_get_gain_reg(imx390_reg *reg, u16 gain)
static inline void imx390_get_gain_reg(imx390_reg *regs, u16 gain)
{
reg->addr = IMX390_ANALOG_GAIN_ADDR_MSB;
reg->val = (gain >> IMX390_SHIFT_8_BITS) & IMX390_MASK_LSB_2_BITS;
(reg + 1)->addr = IMX390_ANALOG_GAIN_ADDR_LSB;
(reg + 1)->val = (gain) & IMX390_MASK_LSB_8_BITS;
regs->addr = IMX390_PGA_GAIN_SP1H + 1;
regs->val = (gain >> 8) & 0x03;
(regs + 1)->addr = IMX390_PGA_GAIN_SP1H;
(regs + 1)->val = gain & 0xff;
}
static inline int imx390_read_reg(struct camera_common_data *s_data,
@@ -125,7 +118,7 @@ static inline int imx390_write_reg(struct camera_common_data *s_data,
err = regmap_write(s_data->regmap, addr, val);
if (err)
dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x",
dev_err(s_data->dev, "%s: i2c write failed, 0x%x = %x\n",
__func__, addr, val);
return err;
@@ -169,25 +162,146 @@ static int imx390_write_table(struct imx390 *priv, const imx390_reg table[])
static int imx390_set_group_hold(struct tegracam_device *tc_dev, bool val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
int err;
err = imx390_write_reg(s_data,
IMX390_GROUP_HOLD_ADDR, val);
if (err) {
dev_dbg(dev,
"%s: Group hold control error\n", __func__);
return err;
}
return 0;
}
static int imx390_set_gain(struct tegracam_device *tc_dev, s64 val)
{
struct camera_common_data *s_data = tc_dev->s_data;
struct device *dev = tc_dev->dev;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode_prop_idx];
imx390_reg reg_list[2];
int err, i;
u16 gain;
gain = (u16)(val / mode->control_properties.step_gain_val);
dev_dbg(dev, "%s: val: %lld db: %d\n", __func__, val, gain);
imx390_get_gain_reg(reg_list, gain);
for (i = 0; i < 2; i++) {
err = imx390_write_reg(s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0;
fail:
dev_info(dev, "%s: GAIN control error\n", __func__);
return err;
}
static int imx390_set_frame_rate(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tc_dev->priv;
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
priv->frame_length = IMX390_MIN_FRAME_LENGTH;
priv->frame_length = IMX390_DEFAULT_FRAME_LENGTH;
return 0;
}
static int imx390_set_exposure(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode];
imx390_reg reg_list[3];
int err;
u32 coarse_time;
u32 shs1;
int i;
/* coarse time in lines */
coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] *
priv->frame_length / mode->control_properties.exposure_factor);
shs1 = priv->frame_length - coarse_time;
/* 0 to 3 are prohibited */
if (shs1 < 4)
shs1 = 4;
/* over VMAX-5 is prohibited */
if (shs1 > priv->frame_length - 5)
shs1 = priv->frame_length - 5;
imx390_get_coarse_time_regs_shs1(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
imx390_get_coarse_time_regs_shs2(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
dev_dbg(tc_dev->dev, "%s: val=%lld shs1=%u coarse_time=%u frame_len=%u\n",
__func__, val, shs1, coarse_time, priv->frame_length);
return 0;
fail:
dev_dbg(&priv->i2c_client->dev,
"%s: set coarse time error\n", __func__);
return err;
}
static int imx390_set_exposure_short(struct tegracam_device *tc_dev, s64 val)
{
struct imx390 *priv = (struct imx390 *)tegracam_get_privdata(tc_dev);
struct camera_common_data *s_data = tc_dev->s_data;
const struct sensor_mode_properties *mode =
&s_data->sensor_props.sensor_modes[s_data->mode];
imx390_reg reg_list[3];
int err;
u32 coarse_time;
u32 shs1;
int i;
/* coarse time in lines */
coarse_time = (u32) (val * s_data->frmfmt[s_data->mode].framerates[0] *
priv->frame_length / mode->control_properties.exposure_factor);
shs1 = priv->frame_length - coarse_time;
/* 0 to 3 are prohibited */
if (shs1 < 4)
shs1 = 4;
/* over VMAX-5 is prohibited */
if (shs1 > priv->frame_length - 5)
shs1 = priv->frame_length - 5;
imx390_get_coarse_time_regs_shs2(reg_list, shs1);
for (i = 0; i < 3; i++) {
err = imx390_write_reg(priv->s_data, reg_list[i].addr,
reg_list[i].val);
if (err)
goto fail;
}
return 0;
fail:
dev_dbg(&priv->i2c_client->dev,
"%s: set coarse time error\n", __func__);
return err;
}
static struct tegracam_ctrl_ops imx390_ctrl_ops = {
@@ -195,6 +309,7 @@ static struct tegracam_ctrl_ops imx390_ctrl_ops = {
.ctrl_cid_list = ctrl_cid_list,
.set_gain = imx390_set_gain,
.set_exposure = imx390_set_exposure,
.set_exposure_short = imx390_set_exposure_short,
.set_frame_rate = imx390_set_frame_rate,
.set_group_hold = imx390_set_group_hold,
};
@@ -207,6 +322,7 @@ static int imx390_power_on(struct camera_common_data *s_data)
struct device *dev = s_data->dev;
dev_err(dev, "%s: power on\n", __func__);
if (pdata && pdata->power_on) {
err = pdata->power_on(pw);
if (err)

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2021-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2021-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* Copyright (c) 2020, RidgeRun. All rights reserved.
*
@@ -42,11 +42,6 @@ static const u32 ctrl_cid_list[] = {
TEGRA_CAMERA_CID_SENSOR_MODE_ID,
};
enum imx477_Config {
TWO_LANE_CONFIG,
FOUR_LANE_CONFIG,
};
struct imx477 {
struct i2c_client *i2c_client;
struct v4l2_subdev *subdev;
@@ -54,7 +49,6 @@ struct imx477 {
u32 frame_length;
struct camera_common_data *s_data;
struct tegracam_device *tc_dev;
enum imx477_Config config;
};
static const struct regmap_config sensor_regmap_config = {
@@ -600,30 +594,14 @@ static int imx477_set_mode(struct tegracam_device *tc_dev)
struct camera_common_data *s_data = tc_dev->s_data;
unsigned int mode_index = 0;
int err = 0;
const char *config;
struct device_node *mode;
uint offset = ARRAY_SIZE(imx477_frmfmt);
dev_dbg(tc_dev->dev, "%s:\n", __func__);
mode = of_get_child_by_name(tc_dev->dev->of_node, "mode0");
err = of_property_read_string(mode, "num_lanes", &config);
if (config[0] == '4')
priv->config = FOUR_LANE_CONFIG;
else if (config[0] == '2')
priv->config = TWO_LANE_CONFIG;
else
dev_err(tc_dev->dev, "Unsupported config\n");
err = imx477_write_table(priv, mode_table[IMX477_MODE_COMMON]);
if (err)
return err;
mode_index = s_data->mode;
if (priv->config == FOUR_LANE_CONFIG)
err = imx477_write_table(priv, mode_table[mode_index + offset]);
else
err = imx477_write_table(priv, mode_table[mode_index]);
err = imx477_write_table(priv, mode_table[mode_index]);
if (err)
return err;

View File

@@ -15,7 +15,10 @@
#include <linux/version.h>
#define DESER_A (0)
#define ENABLE_IMU (0xFE)
#define ENABLE_CC1 (0xFE)
#define ENABLE_CC2 (0xFB)
#define ENABLE_CC3 (0xEF)
#define ENABLE_CC4 (0xBF)
#define ENABLE_ALL_CC (0xAA)
#define DESER_ADDR (0x52)
#define DESER_CC_REG (0x0003)
@@ -27,10 +30,31 @@ static int virtual_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
int ret = 0;
/* Do select 1st channel, to access IMUs from 1st Hawk */
if (!chan) {
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_IMU);
if (ret)
pr_err("%s: Failed to do i2c address trans for IMUs\n",__func__);
switch (chan) {
case 0:
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_CC1);
if (ret)
pr_err("%s: Failed to do i2c address trans for CC1\n", __func__);
break;
case 1:
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_CC2);
if (ret)
pr_err("%s: Failed to do i2c address trans for CC2\n", __func__);
break;
case 2:
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_CC3);
if (ret)
pr_err("%s: Failed to do i2c address trans for CC3\n", __func__);
break;
case 3:
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_CC4);
if (ret)
pr_err("%s: Failed to do i2c address trans for CC4\n", __func__);
break;
default:
pr_err("%s: No channels matched chan = %d\n", __func__, chan);
ret = -EINVAL;
break;
}
return ret;
@@ -41,11 +65,10 @@ static int virtual_i2c_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
int ret = 0;
/* Enable all control channels */
if (!chan) {
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_ALL_CC);
if (ret)
pr_err("%s: Failed to do i2c address trans for IMUs\n",__func__);
}
ret = max96712_write_reg_Dser(DESER_ADDR, DESER_A, DESER_CC_REG, ENABLE_ALL_CC);
if (ret)
pr_err("%s: Failed to do i2c address trans for IMUs\n",__func__);
return ret;
}

View File

@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
*/
// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -1125,6 +1123,18 @@ MODULE_DEVICE_TABLE(of, cam_fsync_of_match);
static SIMPLE_DEV_PM_OPS(cam_fsync_pm, cam_fsync_suspend, cam_fsync_resume);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void cam_fsync_remove_wrapper(struct platform_device *pdev)
{
cam_fsync_remove(pdev);
}
#else
static int cam_fsync_remove_wrapper(struct platform_device *pdev)
{
return cam_fsync_remove(pdev);
}
#endif
static struct platform_driver cam_fsync_driver = {
.driver = {
.name = "cam_fsync",
@@ -1133,7 +1143,7 @@ static struct platform_driver cam_fsync_driver = {
.pm = &cam_fsync_pm,
},
.probe = cam_fsync_probe,
.remove = cam_fsync_remove,
.remove = cam_fsync_remove_wrapper,
};
module_platform_driver(cam_fsync_driver);

View File

@@ -1,19 +1,8 @@
// SPDX-License-Identifier: GPL-2.0 only
/* SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/types.h>
#include <media/tegra-v4l2-camera.h>
#include <media/camera_common.h>
@@ -39,6 +28,26 @@
#define HDR_ENABLE 0x1
static const struct camera_common_colorfmt camera_common_color_fmts[] = {
{
MEDIA_BUS_FMT_SBGGR14_1X14,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SBGGR14,
},
{
MEDIA_BUS_FMT_SRGGB14_1X14,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SRGGB14,
},
{
MEDIA_BUS_FMT_SGRBG14_1X14,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SGRBG14,
},
{
MEDIA_BUS_FMT_SGBRG14_1X14,
V4L2_COLORSPACE_SRGB,
V4L2_PIX_FMT_SGBRG14
},
{
MEDIA_BUS_FMT_SRGGB12_1X12,
V4L2_COLORSPACE_SRGB,
@@ -966,12 +975,12 @@ int camera_common_get_mbus_config(struct v4l2_subdev *sd,
* then return an error
*/
cfg->type = V4L2_MBUS_CSI2_DPHY;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0)
#if defined(NV_V4L2_FWNODE_ENDPOINT_STRUCT_HAS_V4L2_MBUS_CONFIG_MIPI_CSI2) /* Linux v5.18 */
cfg->bus.mipi_csi2.num_data_lanes = 4;
#else
cfg->flags = V4L2_MBUS_CSI2_4_LANE |
V4L2_MBUS_CSI2_CHANNEL_0 |
V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
#else
cfg->bus.mipi_csi2.num_data_lanes = 4;
#endif
return 0;

View File

@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* NVIDIA Tegra CSI Device
*
* Copyright (c) 2015-2024, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -687,7 +686,7 @@ static int tegra_csi_set_format(struct v4l2_subdev *subdev,
}
static int tegra_csi_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *vfi)
@@ -721,13 +720,13 @@ static int tegra_csi_enum_mbus_code(struct v4l2_subdev *sd,
static struct v4l2_subdev_video_ops tegra_csi_video_ops = {
.s_stream = tegra_csi_s_stream,
.g_input_status = tegra_csi_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = tegra_csi_g_frame_interval,
#endif
};
static struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_FRAME_INTERVAL)
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = tegra_csi_g_frame_interval,
#endif
.get_fmt = tegra_csi_get_format,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017-2023 NVIDIA Corporation. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/**
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-isp-channel.c
@@ -523,7 +523,9 @@ static long isp_channel_ioctl(
static const struct file_operations isp_channel_fops = {
.owner = THIS_MODULE,
#if defined(NV_NO_LLSEEK_PRESENT)
.llseek = no_llseek,
#endif
.unlocked_ioctl = isp_channel_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = isp_channel_ioctl,

View File

@@ -616,7 +616,9 @@ static long vi_channel_ioctl(
static const struct file_operations vi_channel_fops = {
.owner = THIS_MODULE,
#if defined(NV_NO_LLSEEK_PRESENT)
.llseek = no_llseek,
#endif
.unlocked_ioctl = vi_channel_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = vi_channel_ioctl,

View File

@@ -1,17 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/**
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-vi.c
@@ -19,6 +7,8 @@
* @brief VI channel operations for the T234 Camera RTCPU platform.
*/
#include <nvidia/conftest.h>
#include <linux/completion.h>
#include <linux/nospec.h>
#include <linux/nvhost.h>
@@ -1726,9 +1716,21 @@ static const struct of_device_id capture_vi_of_match[] = {
};
MODULE_DEVICE_TABLE(of, capture_vi_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void capture_vi_remove_wrapper(struct platform_device *pdev)
{
capture_vi_remove(pdev);
}
#else
static int capture_vi_remove_wrapper(struct platform_device *pdev)
{
return capture_vi_remove(pdev);
}
#endif
static struct platform_driver capture_vi_driver = {
.probe = capture_vi_probe,
.remove = capture_vi_remove,
.remove = capture_vi_remove_wrapper,
.driver = {
.owner = THIS_MODULE,
.name = "tegra-camrtc-capture-vi",
@@ -1760,6 +1762,10 @@ static void __exit capture_vi_exit(void)
module_init(capture_vi_init);
module_exit(capture_vi_exit);
#if defined(NV_MODULE_IMPORT_NS_CALLS_STRINGIFY)
MODULE_IMPORT_NS(DMA_BUF);
#else
MODULE_IMPORT_NS("DMA_BUF");
#endif
MODULE_DESCRIPTION("tegra fusa-capture driver");
MODULE_LICENSE("GPL");

View File

@@ -1,8 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* sensor_common.c - utilities for tegra sensor drivers
* SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* Copyright (c) 2017-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <media/sensor_common.h>
@@ -243,6 +254,14 @@ static int extract_pixel_format(
*format = V4L2_PIX_FMT_SGBRG12;
else if (strncmp(pixel_t, "bayer_grbg12", size) == 0)
*format = V4L2_PIX_FMT_SGRBG12;
else if (strncmp(pixel_t, "bayer_bggr14", size) == 0)
*format = V4L2_PIX_FMT_SBGGR14;
else if (strncmp(pixel_t, "bayer_rggb14", size) == 0)
*format = V4L2_PIX_FMT_SRGGB14;
else if (strncmp(pixel_t, "bayer_gbrg14", size) == 0)
*format = V4L2_PIX_FMT_SGBRG14;
else if (strncmp(pixel_t, "bayer_grbg14", size) == 0)
*format = V4L2_PIX_FMT_SGRBG14;
else if (strncmp(pixel_t, "rgb_rgb88824", size) == 0)
*format = V4L2_PIX_FMT_RGB24;
else if (strncmp(pixel_t, "bayer_wdr_pwl_rggb12", size) == 0)
@@ -253,6 +272,16 @@ static int extract_pixel_format(
*format = V4L2_PIX_FMT_SGRBG12;
else if (strncmp(pixel_t, "bayer_wdr_dol_rggb10", size) == 0)
*format = V4L2_PIX_FMT_SRGGB10;
else if (strncmp(pixel_t, "bayer_wdr_dol_gbrg10", size) == 0)
*format = V4L2_PIX_FMT_SGBRG10;
else if (strncmp(pixel_t, "bayer_wdr_dol_grbg10", size) == 0)
*format = V4L2_PIX_FMT_SGRBG10;
else if (strncmp(pixel_t, "bayer_wdr_dol_rggb12", size) == 0)
*format = V4L2_PIX_FMT_SRGGB12;
else if (strncmp(pixel_t, "bayer_wdr_dol_gbrg12", size) == 0)
*format = V4L2_PIX_FMT_SGBRG12;
else if (strncmp(pixel_t, "bayer_wdr_dol_grbg12", size) == 0)
*format = V4L2_PIX_FMT_SGRBG12;
#if 0 /* disable for Canonical kenrel */
else if (strncmp(pixel_t, "bayer_xbggr10p", size) == 0)
*format = V4L2_PIX_FMT_XBGGR10P;

View File

@@ -1,9 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2018-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* tegracam_v4l2 - tegra camera framework for v4l2 support
*
* Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved.
*/
#include <nvidia/conftest.h>
#include <linux/types.h>
#include <media/tegra-v4l2-camera.h>
#include <media/tegracam_core.h>
@@ -112,9 +114,30 @@ static int v4l2sd_g_input_status(struct v4l2_subdev *sd, u32 *status)
return 0;
}
static int cam_g_frame_interval(struct v4l2_subdev *sd,
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
struct v4l2_subdev_state *sd_state,
#endif
struct v4l2_subdev_frame_interval *ival)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct camera_common_data *s_data = to_camera_common_data(&client->dev);
if (!s_data)
return -EINVAL;
ival->interval.denominator = s_data->frmfmt[s_data->mode_prop_idx].framerates[0];
ival->interval.numerator = 1;
return 0;
}
static struct v4l2_subdev_video_ops v4l2sd_video_ops = {
.s_stream = v4l2sd_stream,
.g_input_status = v4l2sd_g_input_status,
#if !defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.g_frame_interval = cam_g_frame_interval,
.s_frame_interval = cam_g_frame_interval,
#endif
};
static struct v4l2_subdev_core_ops v4l2sd_core_ops = {
@@ -161,6 +184,10 @@ static int v4l2sd_set_fmt(struct v4l2_subdev *sd,
}
static struct v4l2_subdev_pad_ops v4l2sd_pad_ops = {
#if defined(NV_V4L2_SUBDEV_PAD_OPS_STRUCT_HAS_GET_SET_FRAME_INTERVAL)
.get_frame_interval = cam_g_frame_interval,
.set_frame_interval = cam_g_frame_interval,
#endif
.set_fmt = v4l2sd_set_fmt,
.get_fmt = v4l2sd_get_fmt,
.enum_mbus_code = camera_common_enum_mbus_code,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* NVIDIA Tegra Video Input Device
*/
@@ -471,6 +471,7 @@ void tegra_channel_init_ring_buffer(struct tegra_channel *chan)
chan->capture_descr_index = 0;
chan->capture_descr_sequence = 0;
chan->queue_error = false;
chan->capture_reqs_enqueued = 0;
}
EXPORT_SYMBOL(tegra_channel_init_ring_buffer);
@@ -702,11 +703,12 @@ tegra_channel_queue_setup(struct vb2_queue *vq,
* of the requested image size. Although this did not harm the
* flow, according to "v4l2-compliance", we need to check if
* the requested size is invalid.
* Printing this error as info, to avoid kernel error/warning failure.
*/
if (*nplanes) {
if (sizes[0] < chan->format.sizeimage) {
pr_err("%s: sizes[0] = %d chan->format.sizeimage = %d ...\n"
,__func__,sizes[0],chan->format.sizeimage);
pr_info("%s: sizes[0] = %d, chan->format.sizeimage = %d, for num_planes = %d ...\n"
, __func__, sizes[0], chan->format.sizeimage, *nplanes);
return -EINVAL;
}
} else {
@@ -1017,6 +1019,7 @@ static void tegra_channel_stop_streaming(struct vb2_queue *vq)
if (vi->fops) {
vi->fops->vi_stop_streaming(vq);
atomic_set(&chan->is_streaming, DISABLE);
vi->fops->vi_power_off(chan);
}
@@ -1945,7 +1948,7 @@ int tegra_channel_init_subdevices(struct tegra_channel *chan)
int len = 0;
/* set_stream of CSI */
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
#if defined(NV_MEDIA_ENTITY_REMOTE_PAD_PRESENT) /* Linux 6.0 */
pad = media_entity_remote_pad(&chan->pad);
#else
pad = media_pad_remote_pad_first(&chan->pad);
@@ -1975,7 +1978,7 @@ int tegra_channel_init_subdevices(struct tegra_channel *chan)
if (!(pad->flags & MEDIA_PAD_FL_SINK))
break;
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
#if defined(NV_MEDIA_ENTITY_REMOTE_PAD_PRESENT) /* Linux 6.0 */
pad = media_entity_remote_pad(pad);
#else
pad = media_pad_remote_pad_first(pad);
@@ -2281,10 +2284,32 @@ static long tegra_channel_default_ioctl(struct file *file, void *fh,
return ret;
}
/* Implemented vidioc_s_parm and vidioc_g_parm ioctl to support multiple frame
* rates */
static int tegra_channel_s_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_s_parm_cap(chan->video, sd, a);
}
static int tegra_channel_g_parm(struct file *file, void *fh,
struct v4l2_streamparm *a)
{
struct tegra_channel *chan = video_drvdata(file);
struct v4l2_subdev *sd = chan->subdev_on_csi;
return v4l2_g_parm_cap(chan->video, sd, a);
}
static const struct v4l2_ioctl_ops tegra_channel_ioctl_ops = {
.vidioc_querycap = tegra_channel_querycap,
.vidioc_enum_framesizes = tegra_channel_enum_framesizes,
.vidioc_enum_frameintervals = tegra_channel_enum_frameintervals,
.vidioc_s_parm = tegra_channel_s_parm,
.vidioc_g_parm = tegra_channel_g_parm,
.vidioc_enum_fmt_vid_cap = tegra_channel_enum_format,
.vidioc_g_fmt_vid_cap = tegra_channel_get_format,
.vidioc_s_fmt_vid_cap = tegra_channel_set_format,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES.
/* SPDX-FileCopyrightText: Copyright (c) 2016-2025 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* Tegra Video Input 5 device common APIs
@@ -594,15 +594,22 @@ static void vi5_capture_dequeue(struct tegra_channel *chan,
uncorr_err:
spin_lock_irqsave(&chan->capture_state_lock, flags);
chan->capture_state = CAPTURE_ERROR;
if (err == -ETIMEDOUT) {
chan->capture_state = CAPTURE_TIMEOUT;
buf->vb2_state = VB2_BUF_STATE_QUEUED;
} else {
chan->capture_state = CAPTURE_ERROR;
buf->vb2_state = VB2_BUF_STATE_ERROR;
}
spin_unlock_irqrestore(&chan->capture_state_lock, flags);
buf->vb2_state = VB2_BUF_STATE_ERROR;
rel_buf:
vi5_release_buffer(chan, buf);
}
static void vi5_unit_get_device_handle(struct platform_device *pdev,
uint32_t csi_stream_id, struct device **dev);
static int vi5_channel_error_recover(struct tegra_channel *chan,
bool queue_error)
{
@@ -620,6 +627,25 @@ static int vi5_channel_error_recover(struct tegra_channel *chan,
dev_err(&chan->video->dev, "vi capture release failed\n");
goto done;
}
/* Release capture requests */
if (chan->request[vi_port] != NULL) {
dma_free_coherent(chan->tegra_vi_channel[vi_port]->rtcpu_dev,
chan->capture_queue_depth * sizeof(struct capture_descriptor),
chan->request[vi_port], chan->request_iova[vi_port]);
}
chan->request[vi_port] = NULL;
/* Release emd data buffers */
if (chan->emb_buf_size > 0) {
struct device *vi_unit_dev;
vi5_unit_get_device_handle(chan->vi->ndev, chan->port[0], &vi_unit_dev);
dma_free_coherent(vi_unit_dev, chan->emb_buf_size,
chan->emb_buf_addr, chan->emb_buf);
chan->emb_buf_size = 0;
}
vi_channel_close_ex(chan->vi_channel_id[vi_port],
chan->tegra_vi_channel[vi_port]);
chan->tegra_vi_channel[vi_port] = NULL;
@@ -637,7 +663,10 @@ static int vi5_channel_error_recover(struct tegra_channel *chan,
buf = dequeue_dequeue_buffer(chan);
if (!buf)
break;
buf->vb2_state = VB2_BUF_STATE_ERROR;
if (chan->capture_state == CAPTURE_TIMEOUT)
buf->vb2_state = VB2_BUF_STATE_QUEUED;
else
buf->vb2_state = VB2_BUF_STATE_ERROR;
vi5_capture_dequeue(chan, buf);
}

View File

@@ -1,8 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
/* SPDX-License-Identifier: GPL-2.0-only
* SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES.
* All rights reserved.
*
* NVIDIA Tegra Video Input Device Driver VI5 formats
*
* Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved.
* Author: Bhanu Murthy V <bmurthyv@nvidia.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __VI5_FORMATS_H_
@@ -91,6 +97,16 @@ static const struct tegra_video_format vi5_video_formats[] = {
TEGRA_VIDEO_FORMAT(RAW8, 8, SBGGR8_1X8, 1, 1, T_R8,
RAW8, SBGGR8, "BGBG.. GRGR.."),
/* RAW 14 */
TEGRA_VIDEO_FORMAT(RAW14, 14, SRGGB14_1X14, 2, 1, T_R16,
RAW14, SRGGB14, "RGRG.. GBGB.."),
TEGRA_VIDEO_FORMAT(RAW14, 14, SGRBG14_1X14, 2, 1, T_R16,
RAW14, SGRBG14, "GRGR.. BGBG.."),
TEGRA_VIDEO_FORMAT(RAW14, 14, SGBRG14_1X14, 2, 1, T_R16,
RAW14, SGBRG14, "GBGB.. RGRG.."),
TEGRA_VIDEO_FORMAT(RAW14, 14, SBGGR14_1X14, 2, 1, T_R16,
RAW14, SBGGR14, "BGBG.. GRGR.."),
/* RAW 10 */
TEGRA_VIDEO_FORMAT(RAW10, 10, SRGGB10_1X10, 2, 1, T_R16,
RAW10, SRGGB10, "RGRG.. GBGB.."),

View File

@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2023-2024, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved. */
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* cam_cdi_tsc.c - tsc driver.
*/
@@ -645,6 +645,18 @@ MODULE_DEVICE_TABLE(of, cdi_tsc_of_match);
static SIMPLE_DEV_PM_OPS(cdi_tsc_pm, cdi_tsc_suspend, cdi_tsc_resume);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void cdi_tsc_remove_wrapper(struct platform_device *pdev)
{
cdi_tsc_remove(pdev);
}
#else
static int cdi_tsc_remove_wrapper(struct platform_device *pdev)
{
return cdi_tsc_remove(pdev);
}
#endif
static struct platform_driver cdi_tsc_driver = {
.driver = {
.name = "cdi_tsc",
@@ -653,7 +665,7 @@ static struct platform_driver cdi_tsc_driver = {
.pm = &cdi_tsc_pm,
},
.probe = cdi_tsc_probe,
.remove = cdi_tsc_remove,
.remove = cdi_tsc_remove_wrapper,
};
module_platform_driver(cdi_tsc_driver);

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -330,9 +330,21 @@ static const struct of_device_id cdi_gpio_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, cdi_gpio_dt_ids);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void cdi_gpio_remove_wrapper(struct platform_device *pdev)
{
cdi_gpio_remove(pdev);
}
#else
static int cdi_gpio_remove_wrapper(struct platform_device *pdev)
{
return cdi_gpio_remove(pdev);
}
#endif
static struct platform_driver cdi_gpio_driver = {
.probe = cdi_gpio_probe,
.remove = cdi_gpio_remove,
.remove = cdi_gpio_remove_wrapper,
.driver = {
.name = "cdi-gpio",
.of_match_table = cdi_gpio_dt_ids,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2015-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -1776,9 +1776,14 @@ static int cdi_mgr_probe(struct platform_device *pdev)
for (i = 0; i < ARRAY_SIZE(cdi_mgr->gpios); i++) {
pin = &cdi_mgr->gpios[i];
pin->mgr = cdi_mgr;
#if defined(NV_HRTIMER_SETUP_PRESENT) /* Linux v6.13 */
hrtimer_setup(&pin->timers.timer, &cdi_mgr_intr_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
#else
hrtimer_init(&pin->timers.timer, CLOCK_MONOTONIC,
HRTIMER_MODE_ABS);
pin->timers.timer.function = &cdi_mgr_intr_timer;
#endif
}
if (pdev->dev.of_node) {
@@ -2084,6 +2089,18 @@ static const struct of_device_id cdi_mgr_of_match[] = {
};
MODULE_DEVICE_TABLE(of, cdi_mgr_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void cdi_mgr_remove_wrapper(struct platform_device *pdev)
{
cdi_mgr_remove(pdev);
}
#else
static int cdi_mgr_remove_wrapper(struct platform_device *pdev)
{
return cdi_mgr_remove(pdev);
}
#endif
static struct platform_driver cdi_mgr_driver = {
.driver = {
.name = "cdi-mgr",
@@ -2092,7 +2109,7 @@ static struct platform_driver cdi_mgr_driver = {
.pm = &cdi_mgr_pm_ops,
},
.probe = cdi_mgr_probe,
.remove = cdi_mgr_remove,
.remove = cdi_mgr_remove_wrapper,
};
module_platform_driver(cdi_mgr_driver);

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2016-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -254,6 +254,18 @@ static const struct dev_pm_ops cdi_pwm_pm_ops = {
.runtime_resume = cdi_pwm_resume,
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void cdi_pwm_remove_wrapper(struct platform_device *pdev)
{
cdi_pwm_remove(pdev);
}
#else
static int cdi_pwm_remove_wrapper(struct platform_device *pdev)
{
return cdi_pwm_remove(pdev);
}
#endif
static struct platform_driver cdi_pwm_driver = {
.driver = {
.name = "cdi-pwm",
@@ -262,7 +274,7 @@ static struct platform_driver cdi_pwm_driver = {
.pm = &cdi_pwm_pm_ops,
},
.probe = cdi_pwm_probe,
.remove = cdi_pwm_remove,
.remove = cdi_pwm_remove_wrapper,
};
module_platform_driver(cdi_pwm_driver);

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -330,9 +330,21 @@ static const struct of_device_id isc_gpio_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, isc_gpio_dt_ids);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void isc_gpio_remove_wrapper(struct platform_device *pdev)
{
isc_gpio_remove(pdev);
}
#else
static int isc_gpio_remove_wrapper(struct platform_device *pdev)
{
return isc_gpio_remove(pdev);
}
#endif
static struct platform_driver isc_gpio_driver = {
.probe = isc_gpio_probe,
.remove = isc_gpio_remove,
.remove = isc_gpio_remove_wrapper,
.driver = {
.name = "isc-gpio",
.of_match_table = isc_gpio_dt_ids,

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2015-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -1204,6 +1204,18 @@ static const struct of_device_id isc_mgr_of_match[] = {
};
MODULE_DEVICE_TABLE(of, isc_mgr_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void isc_mgr_remove_wrapper(struct platform_device *pdev)
{
isc_mgr_remove(pdev);
}
#else
static int isc_mgr_remove_wrapper(struct platform_device *pdev)
{
return isc_mgr_remove(pdev);
}
#endif
static struct platform_driver isc_mgr_driver = {
.driver = {
.name = "isc-mgr",
@@ -1212,7 +1224,7 @@ static struct platform_driver isc_mgr_driver = {
.pm = &isc_mgr_pm_ops,
},
.probe = isc_mgr_probe,
.remove = isc_mgr_remove,
.remove = isc_mgr_remove_wrapper,
};
module_platform_driver(isc_mgr_driver);

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2016-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2016-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -254,6 +254,18 @@ static const struct dev_pm_ops isc_pwm_pm_ops = {
.runtime_resume = isc_pwm_resume,
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void isc_pwm_remove_wrapper(struct platform_device *pdev)
{
isc_pwm_remove(pdev);
}
#else
static int isc_pwm_remove_wrapper(struct platform_device *pdev)
{
return isc_pwm_remove(pdev);
}
#endif
static struct platform_driver isc_pwm_driver = {
.driver = {
.name = "isc-pwm",
@@ -262,7 +274,7 @@ static struct platform_driver isc_pwm_driver = {
.pm = &isc_pwm_pm_ops,
},
.probe = isc_pwm_probe,
.remove = isc_pwm_remove,
.remove = isc_pwm_remove_wrapper,
};
module_platform_driver(isc_pwm_driver);

View File

@@ -2,7 +2,7 @@
/*
* Voltage Regulator Specification: Power Sequencer MFD Driver
*
* Copyright (C) 2020-2023 NVIDIA CORPORATION. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include <nvidia/conftest.h>
@@ -228,6 +228,14 @@ static int nvvrs_pseq_probe(struct i2c_client *client,
return ret;
}
/* When battery mounted, the chip may have IRQ asserted. */
/* Clear it before IRQ requested. */
ret = nvvrs_pseq_irq_clear(nvvrs_chip);
if (ret < 0) {
dev_err(nvvrs_chip->dev, "Failed to clear IRQ: %d\n", ret);
return ret;
}
nvvrs_pseq_irq_chip.irq_drv_data = nvvrs_chip;
ret = devm_regmap_add_irq_chip(nvvrs_chip->dev, nvvrs_chip->rmap, client->irq,
IRQF_ONESHOT | IRQF_SHARED, 0,

View File

@@ -17,3 +17,4 @@ endif
obj-m += bluedroid_pm.o
obj-m += nvscic2c-pcie/
obj-m += ioctl_example.o
obj-m += tegra-cec/

View File

@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (C) 2019-2023 NVIDIA CORPORATION. All rights reserved.
#include <nvidia/conftest.h>
// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -267,7 +265,11 @@ static ssize_t lpm_write_proc(struct file *file, const char __user *buffer,
bluedroid_pm_gpio_set_value(
bluedroid_pm->ext_wake, 1);
__pm_stay_awake(&bluedroid_pm->wake_lock);
#if defined(NV_TIMER_DELETE_PRESENT) /* Linux v6.15 */
timer_delete(&bluedroid_pm_timer);
#else
del_timer(&bluedroid_pm_timer);
#endif
set_bit(BT_WAKE, &bluedroid_pm->flags);
} else {
kfree(buf);
@@ -539,7 +541,11 @@ static int bluedroid_pm_remove(struct platform_device *pdev)
wakeup_source_destroy(&bluedroid_pm->wake_lock);
gpio_free(bluedroid_pm->ext_wake);
remove_bt_proc_interface();
#if defined(NV_TIMER_DELETE_PRESENT) /* Linux v6.15 */
timer_delete(&bluedroid_pm_timer);
#else
del_timer(&bluedroid_pm_timer);
#endif
}
if ((gpio_is_valid(bluedroid_pm->gpio_reset)) ||
(gpio_is_valid(bluedroid_pm->gpio_shutdown)) ||
@@ -627,9 +633,21 @@ static struct of_device_id bdroid_of_match[] = {
};
MODULE_DEVICE_TABLE(of, bdroid_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void bluedroid_pm_remove_wrapper(struct platform_device *pdev)
{
bluedroid_pm_remove(pdev);
}
#else
static int bluedroid_pm_remove_wrapper(struct platform_device *pdev)
{
return bluedroid_pm_remove(pdev);
}
#endif
static struct platform_driver bluedroid_pm_driver = {
.probe = bluedroid_pm_probe,
.remove = bluedroid_pm_remove,
.remove = bluedroid_pm_remove_wrapper,
.suspend = bluedroid_pm_suspend,
.resume = bluedroid_pm_resume,
.shutdown = bluedroid_pm_shutdown,

View File

@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/* SPDX-FileCopyrightText: Copyright (c) 2014-2023, NVIDIA CORPORATION. All rights reserved. */
/* SPDX-FileCopyrightText: Copyright (c) 2014-2025, NVIDIA CORPORATION. All rights reserved. */
#include <nvidia/conftest.h>
#include <linux/dma-buf.h>
#include <linux/module.h>
@@ -8,7 +10,11 @@
#include "mods_internal.h"
#if defined(NV_MODULE_IMPORT_NS_CALLS_STRINGIFY)
MODULE_IMPORT_NS(DMA_BUF);
#else
MODULE_IMPORT_NS("DMA_BUF");
#endif
static struct device *dummy_device;

View File

@@ -171,7 +171,8 @@ allocate_outbound_area(struct pci_epf *epf, size_t win_size,
return ret;
}
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_EPC_DEINIT) || \
defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Linux v6.11 || Nvidia Internal */
static void
clear_inbound_translation(struct pci_epf *epf)
{
@@ -494,7 +495,8 @@ deinit_work(struct work_struct *work)
* @DRV_MODE_EPC would have already gone then by the time
* struct pci_epc_event_ops.core_deinit is called.
*/
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_EPC_DEINIT) || \
defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Linux v6.11 || Nvidia Internal */
static int
nvscic2c_pcie_epf_core_deinit(struct pci_epf *epf)
{
@@ -522,6 +524,13 @@ nvscic2c_pcie_epf_core_deinit(struct pci_epf *epf)
return 0;
}
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_EPC_DEINIT)
static void nvscic2c_pcie_epf_epc_deinit(struct pci_epf *epf)
{
WARN_ON(nvscic2c_pcie_epf_core_deinit(epf));
}
#endif
#endif
/* Handle link message from @DRV_MODE_EPC. */
@@ -734,8 +743,14 @@ get_driverdata(const struct pci_epf_device_id *id,
}
static const struct pci_epc_event_ops nvscic2c_event_ops = {
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_EPC_INIT) /* Linux v6.11 */
.epc_init = nvscic2c_pcie_epf_core_init,
#else
.core_init = nvscic2c_pcie_epf_core_init,
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
#endif
#if defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_EPC_DEINIT) /* Linux v6.11 */
.epc_deinit = nvscic2c_pcie_epf_epc_deinit,
#elif defined(NV_PCI_EPC_EVENT_OPS_STRUCT_HAS_CORE_DEINIT) /* Nvidia Internal */
.core_deinit = nvscic2c_pcie_epf_core_deinit,
#endif
};

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#define pr_fmt(fmt) "nvscic2c-pcie: vmap-pin: " fmt
@@ -380,4 +380,8 @@ err:
return ret;
}
#if defined(NV_MODULE_IMPORT_NS_CALLS_STRINGIFY)
MODULE_IMPORT_NS(DMA_BUF);
#else
MODULE_IMPORT_NS("DMA_BUF");
#endif

View File

@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* SPDX-FileCopyrightText: Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
/*
* This is NvSciIpc kernel driver. At present its only use is to support
@@ -84,11 +82,20 @@ NvSciError NvSciIpcEndpointValidateAuthTokenLinuxCurrent(
}
f = fdget((int)authToken);
#if defined(NV_FD_EMPTY_PRESENT) /* Linux v6.12 */
if (fd_empty(f)) {
#else
if (!f.file) {
#endif
ERR("invalid auth token\n");
return NvSciError_BadParameter;
}
#if defined(NV_FD_FILE_PRESENT) /* Linux v6.12 */
filp = fd_file(f);
#else
filp = f.file;
#endif
devlen = strlen(filp->f_path.dentry->d_name.name);
#if DEBUG_VALIDATE_TOKEN
@@ -678,7 +685,9 @@ static const struct file_operations nvsciipc_fops = {
.open = nvsciipc_dev_open,
.release = nvsciipc_dev_release,
.unlocked_ioctl = nvsciipc_dev_ioctl,
#if defined(NV_NO_LLSEEK_PRESENT)
.llseek = no_llseek,
#endif
.read = nvsciipc_dbg_read,
};
@@ -822,9 +831,21 @@ exit:
return 0;
}
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void nvsciipc_remove_wrapper(struct platform_device *pdev)
{
nvsciipc_remove(pdev);
}
#else
static int nvsciipc_remove_wrapper(struct platform_device *pdev)
{
return nvsciipc_remove(pdev);
}
#endif
static struct platform_driver nvsciipc_driver = {
.probe = nvsciipc_probe,
.remove = nvsciipc_remove,
.remove = nvsciipc_remove_wrapper,
.driver = {
.name = MODULE_NAME,
},

View File

@@ -0,0 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved.
subdir-ccflags-y = -Werror
obj-m += tegra_cec.o

View File

@@ -0,0 +1,860 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/ktime.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/of_device.h>
#include <linux/version.h>
#include <linux/reset.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/clk/tegra.h>
#include <linux/of.h>
#if defined(CONFIG_TEGRA_POWERGATE)
#include <soc/tegra/tegra_powergate.h>
#endif
#include "tegra_cec.h"
#define LOGICAL_ADDRESS_RESERVED2 0xD
#define LOGICAL_ADDRESS_TV 0x0
#define LOGICAL_ADDRESS_BROADCAST 0xF
#define TEXT_VIEW_ON 0x0D
#define ACTIVE_SOURCE 0x82
/*
* 400 ms is the time it takes for one 16 byte message to be
* transferred and 5 is the maximum number of retries. Add
* another 100 ms as a margin.
*/
#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
static bool post_recovery, text_view_on_sent;
static u8 text_view_on_command[] = {
LOGICAL_ADDRESS_RESERVED2 << 4 | LOGICAL_ADDRESS_TV,
TEXT_VIEW_ON
};
static u8 active_source_command[] = {
LOGICAL_ADDRESS_RESERVED2 << 4 | LOGICAL_ADDRESS_BROADCAST,
ACTIVE_SOURCE,
0x00,
0x00
};
static ssize_t cec_logical_addr_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
static ssize_t cec_logical_addr_show(struct device *dev,
struct device_attribute *attr, char *buf);
static DEVICE_ATTR(cec_logical_addr_config, S_IWUSR | S_IRUGO,
cec_logical_addr_show, cec_logical_addr_store);
/* keeping this for debug support to track register read/writes */
struct tegra_cec *tegra_cec_global;
/* Try again in case of reset control failure */
static int reset_retry_count = 5;
static void tegra_cec_writel(u32 value, void __iomem *addr)
{
writel(value, addr);
}
static u32 tegra_cec_readl(const void __iomem *addr)
{
return readl(addr);
}
static int tegra_cec_open(struct inode *inode, struct file *file)
{
struct miscdevice *miscdev = file->private_data;
struct tegra_cec *cec = container_of(miscdev,
struct tegra_cec, misc_dev);
int ret = 0;
dev_dbg(cec->dev, "%s\n", __func__);
ret = wait_event_interruptible(cec->init_waitq,
atomic_read(&cec->init_done) == 1);
if (ret)
return ret;
file->private_data = cec;
return ret;
}
static int tegra_cec_release(struct inode *inode, struct file *file)
{
struct tegra_cec *cec = file->private_data;
dev_dbg(cec->dev, "%s\n", __func__);
return 0;
}
static inline void tegra_cec_native_tx(const struct tegra_cec *cec, u32 block)
{
u32 tx_reg, retry;
tegra_cec_writel(block, cec->cec_base + TEGRA_CEC_TX_REGISTER);
tx_reg = tegra_cec_readl(cec->cec_base + TEGRA_CEC_TX_REGISTER);
retry = 10;
while ((tx_reg & 0x80000000) && retry--) {
udelay(31); // one clock cycle = 30.5us
tx_reg = tegra_cec_readl(cec->cec_base + TEGRA_CEC_TX_REGISTER);
}
}
static inline void tegra_cec_error_recovery(struct tegra_cec *cec)
{
u32 hw_ctrl;
hw_ctrl = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
tegra_cec_writel(0x0, cec->cec_base + TEGRA_CEC_HW_CONTROL);
tegra_cec_writel(0xFFFFFFFE, cec->cec_base + TEGRA_CEC_INT_STAT);
tegra_cec_writel(hw_ctrl, cec->cec_base + TEGRA_CEC_HW_CONTROL);
}
static
int tegra_cec_native_write_l(struct tegra_cec *cec, const u8 *buf, size_t cnt)
{
int ret;
size_t i;
u32 start, mode, eom;
u32 mask;
/*
* In case previous transmission was interrupted by signal,
* driver will try to complete the frame anyway. However,
* this means we have to wait for it to finish before beginning
* subsequent transmission.
*/
ret = wait_event_interruptible_timeout(cec->tx_waitq, cec->tx_wake == 1,
msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
if (ret == 0)
return -ETIME;
else if (ret < 0)
return ret;
mode = TEGRA_CEC_LADDR_MODE(buf[0]) << TEGRA_CEC_TX_REG_ADDR_MODE_SHIFT;
cec->tx_wake = 0;
cec->tx_error = 0;
cec->tx_buf_cur = 0;
cec->tx_buf_cnt = cnt;
for (i = 0; i < cnt; i++) {
start = i == 0 ? (1 << TEGRA_CEC_TX_REG_START_BIT_SHIFT) : 0;
eom = i == cnt-1 ? (1 << TEGRA_CEC_TX_REG_EOM_SHIFT) : 0;
cec->tx_buf[i] = start | mode | eom | buf[i];
}
mask = tegra_cec_readl(cec->cec_base + TEGRA_CEC_INT_MASK);
tegra_cec_writel(mask | TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
cec->cec_base + TEGRA_CEC_INT_MASK);
ret = wait_event_interruptible_timeout(cec->tx_waitq, cec->tx_wake == 1,
msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
if (ret > 0) {
ret = cec->tx_error;
} else if (ret == 0) {
dev_err(cec->dev, "timeout in %s:%d.", __func__, __LINE__);
tegra_cec_error_recovery(cec);
cec->tx_wake = 1;
ret = -ETIME;
}
return ret;
}
static ssize_t tegra_cec_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
u8 tx_buf[TEGRA_CEC_FRAME_MAX_LENGTH];
struct tegra_cec *cec = file->private_data;
ssize_t ret;
if (count == 0 || count > TEGRA_CEC_FRAME_MAX_LENGTH)
return -EMSGSIZE;
ret = wait_event_interruptible(cec->init_waitq,
atomic_read(&cec->init_done) == 1);
if (ret)
return ret;
if (copy_from_user(tx_buf, buf, count))
return -EFAULT;
mutex_lock(&cec->tx_lock);
ret = tegra_cec_native_write_l(cec, tx_buf, count);
mutex_unlock(&cec->tx_lock);
if (ret)
return ret;
else {
dev_dbg(cec->dev, "%s: %*phC", __func__, (int)count, tx_buf);
return count;
}
}
static ssize_t tegra_cec_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
struct tegra_cec *cec = file->private_data;
ssize_t ret;
ret = wait_event_interruptible(cec->init_waitq,
atomic_read(&cec->init_done) == 1);
if (ret)
return ret;
if (cec->rx_wake == 0)
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(cec->rx_waitq, cec->rx_wake == 1);
if (ret)
return ret;
count = sizeof(cec->rx_fifo[0]) * (cec->rx_fifo_data);
if (copy_to_user(buffer, &(cec->rx_fifo[0]), count))
return -EFAULT;
dev_dbg(cec->dev, "%s: %*phC", __func__, (int)count,
&(cec->rx_fifo[0]));
memset(&(cec->rx_fifo[0]), 0, count);
cec->rx_wake = 0;
cec->rx_fifo_data = 0;
return count;
}
static irqreturn_t tegra_cec_irq_handler(int irq, void *data)
{
struct device *dev = data;
struct tegra_cec *cec = dev_get_drvdata(dev);
u32 status, mask, i;
status = tegra_cec_readl(cec->cec_base + TEGRA_CEC_INT_STAT);
mask = tegra_cec_readl(cec->cec_base + TEGRA_CEC_INT_MASK);
status &= mask;
if (!status)
goto out;
if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN) {
dev_err(dev, "TX underrun, interrupt timing issue!\n");
tegra_cec_error_recovery(cec);
tegra_cec_writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
cec->cec_base + TEGRA_CEC_INT_MASK);
cec->tx_error = -EIO;
cec->tx_wake = 1;
wake_up_interruptible(&cec->tx_waitq);
goto out;
} else if ((status & TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED) ||
(status & TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED)) {
tegra_cec_error_recovery(cec);
tegra_cec_writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
cec->cec_base + TEGRA_CEC_INT_MASK);
cec->tx_error = -ECOMM;
cec->tx_wake = 1;
wake_up_interruptible(&cec->tx_waitq);
goto out;
} else if (status & TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED) {
tegra_cec_writel((TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED),
cec->cec_base + TEGRA_CEC_INT_STAT);
if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD) {
tegra_cec_error_recovery(cec);
cec->tx_error = TEGRA_CEC_LADDR_MODE(cec->tx_buf[0]) ?
-ECONNRESET : -EHOSTUNREACH;
}
cec->tx_wake = 1;
wake_up_interruptible(&cec->tx_waitq);
goto out;
} else if (status & TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD)
dev_warn(dev, "TX NAKed on the fly!\n");
if (status & TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY) {
if (cec->tx_buf_cur == cec->tx_buf_cnt)
tegra_cec_writel(mask & ~TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY,
cec->cec_base + TEGRA_CEC_INT_MASK);
else
tegra_cec_native_tx(cec,
cec->tx_buf[cec->tx_buf_cur++]);
}
if (status & (TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN |
TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED |
TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED |
TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED)) {
tegra_cec_writel((TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN |
TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED |
TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED |
TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED),
cec->cec_base + TEGRA_CEC_INT_STAT);
} else if (status & TEGRA_CEC_INT_STAT_RX_REGISTER_FULL) {
/*
Read TEGRA_CEC_RX_BUFFER_STAT_0 which have total number of blocks,
then read every block continuously from TEGRA_CEC_RX_REGISTER.
TEGRA_CEC_INT_STAT_RX_REGISTER_FULL sets only once and not for
every block if there are more than 1 block in FIFO.
*/
cec->rx_fifo_data =
tegra_cec_readl(cec->cec_base + TEGRA_CEC_RX_BUFFER_STAT_0);
for (i = 0; i < cec->rx_fifo_data; i++) {
cec->rx_fifo[i] =
readw(cec->cec_base + TEGRA_CEC_RX_REGISTER);
}
tegra_cec_writel(TEGRA_CEC_INT_STAT_RX_REGISTER_FULL,
cec->cec_base + TEGRA_CEC_INT_STAT);
cec->rx_wake = 1;
wake_up_interruptible(&cec->rx_waitq);
}
out:
return IRQ_HANDLED;
}
static int tegra_cec_dump_registers(struct tegra_cec *cec)
{
int value, i;
dev_info(cec->dev, "base address = %llx\n", (u64)cec->cec_base);
for (i = 0; i <= TEGRA_CEC_RX_OPCODE_4; i += 4) {
value = tegra_cec_readl(cec->cec_base + i);
dev_info(cec->dev, "offset %08x: %08x\n", i, value);
}
return i;
}
static int tegra_cec_set_rx_snoop(struct tegra_cec *cec, u32 enable)
{
u32 state;
if (!atomic_read(&cec->init_done))
return -EAGAIN;
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
if (((state & TEGRA_CEC_HWCTRL_RX_SNOOP) != 0) ^ (enable != 0)) {
state ^= TEGRA_CEC_HWCTRL_RX_SNOOP;
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
}
return 0;
}
static int tegra_cec_get_rx_snoop(struct tegra_cec *cec, u32 *state)
{
if (!atomic_read(&cec->init_done))
return -EAGAIN;
*state = (readl(cec->cec_base + TEGRA_CEC_HW_CONTROL) & TEGRA_CEC_HWCTRL_RX_SNOOP) >> 15;
return 0;
}
static int tegra_cec_access_ok(bool write, unsigned long arg, size_t size)
{
int err = 0;
#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
u8 __maybe_unused access_type = write ? VERIFY_WRITE : VERIFY_READ;
err = !access_ok(access_type, arg, size);
#else
err = !access_ok((void *)arg, size);
#endif
return err;
}
static long tegra_cec_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int err;
u32 state;
struct tegra_cec *cec = file->private_data;
if (_IOC_TYPE(cmd) != TEGRA_CEC_IOC_MAGIC)
return -EINVAL;
switch (cmd) {
case TEGRA_CEC_IOCTL_ERROR_RECOVERY:
mutex_lock(&cec->recovery_lock);
tegra_cec_error_recovery(cec);
mutex_unlock(&cec->recovery_lock);
break;
case TEGRA_CEC_IOCTL_DUMP_REGISTERS:
tegra_cec_dump_registers(cec);
break;
case TEGRA_CEC_IOCTL_SET_RX_SNOOP:
err = tegra_cec_access_ok(false, arg, sizeof(u32));
if (err)
return -EFAULT;
if (copy_from_user((u32 *) &state, (u32 *) arg, sizeof(u32)))
return -EFAULT;
tegra_cec_set_rx_snoop(cec, state);
break;
case TEGRA_CEC_IOCTL_GET_RX_SNOOP:
err = tegra_cec_access_ok(true, arg, sizeof(u32));
if (err)
return -EFAULT;
err = tegra_cec_get_rx_snoop(cec, &state);
if (!err) {
if (copy_to_user((u32 *) arg, &state, sizeof(u32)))
return -EFAULT;
}
break;
case TEGRA_CEC_IOCTL_GET_POST_RECOVERY:
err = tegra_cec_access_ok(true, arg, sizeof(u32));
if (err)
return -EFAULT;
if (copy_to_user((bool *) arg, &post_recovery, sizeof(bool)))
return -EFAULT;
break;
default:
dev_err(cec->dev, "unsupported ioctl\n");
return -EINVAL;
}
return 0;
}
static const struct file_operations tegra_cec_fops = {
.owner = THIS_MODULE,
.open = tegra_cec_open,
.release = tegra_cec_release,
.read = tegra_cec_read,
.write = tegra_cec_write,
.unlocked_ioctl = tegra_cec_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = tegra_cec_ioctl,
#endif
};
static int tegra_cec_send_one_touch_play(struct tegra_cec *cec)
{
int res = 0;
u8 phy_address[2] = {0};
u32 state = 0;
text_view_on_sent = true;
/*
* UEFI writes physical address at register TEGRA_CEC_HW_SPARE during boot.
*/
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_SPARE);
phy_address[0] = state & 0x000F;
phy_address[1] = state & 0x00F0;
dev_info(cec->dev, "physical address: %02x:%02x.\n",
phy_address[0], phy_address[1]);
if ((phy_address[0] == 0) && (phy_address[1] == 0)) {
dev_err(cec->dev, "Can't find physical address.\n");
return 0;
}
active_source_command[2] = phy_address[0];
active_source_command[3] = phy_address[1];
mutex_lock(&cec->tx_lock);
res = tegra_cec_native_write_l(cec, text_view_on_command,
sizeof(text_view_on_command));
dev_notice(cec->dev, "Sent <Text View On> res: %d.\n", res);
if (!res) {
res = tegra_cec_native_write_l(cec, active_source_command,
sizeof(active_source_command));
dev_notice(cec->dev,
"Broadcast <Active Source> res: %d.\n", res);
}
mutex_unlock(&cec->tx_lock);
return res;
}
static void tegra_cec_init(struct tegra_cec *cec)
{
u32 state;
cec->rx_wake = 0;
cec->tx_wake = 1;
cec->tx_buf_cnt = 0;
cec->tx_buf_cur = 0;
cec->tx_error = 0;
tegra_cec_global = cec;
dev_notice(cec->dev, "%s started\n", __func__);
tegra_cec_writel(0x00, cec->cec_base + TEGRA_CEC_HW_CONTROL);
tegra_cec_writel(0x00, cec->cec_base + TEGRA_CEC_INT_MASK);
#ifdef CONFIG_PM
if (wait_event_interruptible_timeout(cec->suspend_waitq,
atomic_xchg(&cec->init_cancel, 0) == 1,
msecs_to_jiffies(1000)) > 0)
return;
#else
msleep(1000);
#endif
tegra_cec_writel(0x00, cec->cec_base + TEGRA_CEC_SW_CONTROL);
cec->logical_addr = TEGRA_CEC_HWCTRL_RX_LADDR_UNREG;
state = TEGRA_CEC_HWCTRL_AUTO_CLR_TX_EMPTY_INTR |
TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr);
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
tegra_cec_writel(0x1, cec->cec_base + TEGRA_CEC_MESSAGE_FILTER_CTRL);
state = (0xff << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_LO_TIME_MASK) |
(0x22 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_SAMPLE_TIME_MASK) |
(0xe0 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_DURATION_MASK) |
(0x41 << TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MIN_DURATION_MASK);
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_RX_TIMING_1);
state = (0x7 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_ADDITIONAL_FRAME_MASK) |
(0x1 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_NEW_FRAME_MASK) |
(0x3 << TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_RETRY_FRAME_MASK);
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_TX_TIMING_2);
/*
* By default, keep RX buffer depth to 2 bytes like previous chips.
* Value 1 = 2 bytes (1 fifo depth)
* Value 0x40 = 128 bytes (64 fifo depth)
*/
tegra_cec_writel(0x1, cec->cec_base + TEGRA_CEC_RX_BUFFER_AFULL_CFG_0);
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
state |= TEGRA_CEC_HWCTRL_TX_RX_MODE;
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
tegra_cec_writel(TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN |
TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD |
TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED |
TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED |
TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED |
TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN,
cec->cec_base + TEGRA_CEC_INT_MASK);
atomic_set(&cec->init_done, 1);
wake_up_interruptible(&cec->init_waitq);
if (!text_view_on_sent && !post_recovery)
tegra_cec_send_one_touch_play(cec);
dev_notice(cec->dev, "%s Done.\n", __func__);
}
static void tegra_cec_init_worker(struct work_struct *work)
{
struct tegra_cec *cec = container_of(work, struct tegra_cec, work);
tegra_cec_init(cec);
}
static ssize_t cec_logical_addr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tegra_cec *cec = dev_get_drvdata(dev);
if (!atomic_read(&cec->init_done))
return -EAGAIN;
if (buf)
return sprintf(buf, "0x%x\n", (u32)cec->logical_addr);
return 1;
}
static ssize_t cec_logical_addr_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
ssize_t ret;
u32 state;
u16 addr;
struct tegra_cec *cec;
if (!buf || !count)
return -EINVAL;
cec = dev_get_drvdata(dev);
if (!atomic_read(&cec->init_done))
return -EAGAIN;
ret = kstrtou16(buf, 0, &addr);
if (ret)
return ret;
dev_info(dev, "set logical address: 0x%x\n", (u32)addr);
cec->logical_addr = addr;
// clear TX_RX_MODE
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
state &= ~TEGRA_CEC_HWCTRL_TX_RX_MODE;
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
// write logical address
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
state &= ~TEGRA_CEC_HWCTRL_RX_LADDR_MASK;
state |= TEGRA_CEC_HWCTRL_RX_LADDR(cec->logical_addr);
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
// enable tx_rx mode
state = tegra_cec_readl(cec->cec_base + TEGRA_CEC_HW_CONTROL);
state |= TEGRA_CEC_HWCTRL_TX_RX_MODE;
tegra_cec_writel(state, cec->cec_base + TEGRA_CEC_HW_CONTROL);
return count;
}
static int tegra_cec_probe(struct platform_device *pdev)
{
struct tegra_cec *cec;
struct resource *res;
int ret = 0;
struct reset_control *rst = NULL;
cec = devm_kzalloc(&pdev->dev, sizeof(struct tegra_cec), GFP_KERNEL);
if (!cec)
return -ENOMEM;
if (reset_retry_count != 0) {
rst = devm_reset_control_get(&pdev->dev, "cec");
if (IS_ERR(rst)) {
/* BPMP reset mechanism not available, return and retry again */
dev_info(&pdev->dev, "reset control is not found, deferring probe to retry again.\n");
devm_kfree(&pdev->dev, cec);
reset_retry_count--;
return -EPROBE_DEFER;
}
/* take CEC engine out of reset */
if (reset_control_reset(rst) != 0) {
dev_info(&pdev->dev, "reset control reset failed, deferring probe to retry again.\n");
devm_kfree(&pdev->dev, cec);
reset_retry_count--;
return -EPROBE_DEFER;
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev,
"Unable to allocate resources for device.\n");
ret = -EBUSY;
goto cec_error;
}
if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
pdev->name)) {
dev_err(&pdev->dev,
"Unable to request mem region for device.\n");
ret = -EBUSY;
goto cec_error;
}
cec->tegra_cec_irq = platform_get_irq(pdev, 0);
if (cec->tegra_cec_irq <= 0) {
ret = -EBUSY;
goto cec_error;
}
cec->cec_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!cec->cec_base) {
dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
ret = -EBUSY;
goto cec_error;
}
dev_info(&pdev->dev, "dt=%d start=0x%08llX end=0x%08llX irq=%d\n",
(pdev->dev.of_node != NULL),
res->start, res->end,
cec->tegra_cec_irq);
atomic_set(&cec->init_done, 0);
mutex_init(&cec->tx_lock);
mutex_init(&cec->recovery_lock);
cec->dev = &pdev->dev;
/* set context info. */
init_waitqueue_head(&cec->rx_waitq);
init_waitqueue_head(&cec->tx_waitq);
init_waitqueue_head(&cec->init_waitq);
#ifdef CONFIG_PM
init_waitqueue_head(&cec->suspend_waitq);
atomic_set(&cec->init_cancel, 0);
#endif
platform_set_drvdata(pdev, cec);
/* clear out the hardware. */
INIT_WORK(&cec->work, tegra_cec_init_worker);
schedule_work(&cec->work);
device_init_wakeup(&pdev->dev, 1);
cec->misc_dev.minor = MISC_DYNAMIC_MINOR;
cec->misc_dev.name = TEGRA_CEC_NAME;
cec->misc_dev.fops = &tegra_cec_fops;
cec->misc_dev.parent = &pdev->dev;
if (misc_register(&cec->misc_dev)) {
printk(KERN_WARNING "Couldn't register device , %s.\n", TEGRA_CEC_NAME);
goto cec_error;
}
ret = devm_request_irq(&pdev->dev, cec->tegra_cec_irq,
tegra_cec_irq_handler, 0x0, "cec_irq", &pdev->dev);
if (ret) {
dev_err(&pdev->dev,
"Unable to request interrupt for device (err=%d).\n", ret);
goto cec_error;
}
/*
* Create a symlink for tegra_cec if it is not under platform bus or
* it has been created with different name.
*/
if ((pdev->dev.parent != &platform_bus) ||
strcmp(dev_name(&pdev->dev), TEGRA_CEC_NAME)) {
ret = sysfs_create_link(&platform_bus.kobj,
&pdev->dev.kobj, TEGRA_CEC_NAME);
if (ret)
dev_warn(&pdev->dev, "Could not create sysfs link.\n");
}
ret = sysfs_create_file(
&pdev->dev.kobj, &dev_attr_cec_logical_addr_config.attr);
dev_info(&pdev->dev, "cec_add_sysfs ret=%d\n", ret);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to add sysfs: %d\n", ret);
goto cec_error;
}
dev_notice(&pdev->dev, "probed\n");
return 0;
cec_error:
cancel_work_sync(&cec->work);
return ret;
}
static void tegra_cec_remove(struct platform_device *pdev)
{
struct tegra_cec *cec = platform_get_drvdata(pdev);
misc_deregister(&cec->misc_dev);
cancel_work_sync(&cec->work);
}
#ifdef CONFIG_PM
static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state)
{
struct tegra_cec *cec = platform_get_drvdata(pdev);
atomic_set(&cec->init_cancel, 1);
wmb();
wake_up_interruptible(&cec->suspend_waitq);
/* cancel the work queue */
cancel_work_sync(&cec->work);
atomic_set(&cec->init_done, 0);
atomic_set(&cec->init_cancel, 0);
/*
* Wakeup from SC7 on CEC is broken for T234 in HW.
* Don't do anything for this while going to suspend.
*/
dev_notice(&pdev->dev, "suspended\n");
return 0;
}
static int tegra_cec_resume(struct platform_device *pdev)
{
struct tegra_cec *cec = platform_get_drvdata(pdev);
dev_notice(&pdev->dev, "Resuming\n");
/*
* Wakeup from SC7 on CEC is broken for T234 in HW.
* Don't do anything after exiting suspend.
*/
schedule_work(&cec->work);
return 0;
}
#endif
static struct of_device_id tegra_cec_of_match[] = {
{ .compatible = "nvidia,tegra234-cec"},
{},
};
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_cec_remove_wrapper(struct platform_device *pdev)
{
tegra_cec_remove(pdev);
}
#else
static int tegra_cec_remove_wrapper(struct platform_device *pdev)
{
tegra_cec_remove(pdev);
return 0;
}
#endif
static struct platform_driver tegra_cec_driver = {
.driver = {
.name = TEGRA_CEC_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(tegra_cec_of_match),
},
.probe = tegra_cec_probe,
.remove = tegra_cec_remove_wrapper,
#ifdef CONFIG_PM
.suspend = tegra_cec_suspend,
.resume = tegra_cec_resume,
#endif
};
module_platform_driver(tegra_cec_driver);
MODULE_DESCRIPTION("NVIDIA TEGRA CEC Driver");
MODULE_AUTHOR("NVIDIA");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,167 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022-2025, NVIDIA CORPORATION. All rights reserved.
#ifndef TEGRA_CEC_H
#define TEGRA_CEC_H
#include <linux/pm.h>
#include <asm/atomic.h>
#include <uapi/misc/tegra_cec.h>
#define TEGRA_CEC_FRAME_MAX_LENGTH 16
#define TEGRA_CEC_RX_FIFO_LENGTH 64
struct tegra_cec {
struct device *dev;
struct miscdevice misc_dev;
struct clk *clk;
struct mutex tx_lock;
struct mutex recovery_lock;
void __iomem *cec_base;
int tegra_cec_irq;
wait_queue_head_t rx_waitq;
wait_queue_head_t tx_waitq;
wait_queue_head_t init_waitq;
atomic_t init_done;
#ifdef CONFIG_PM
wait_queue_head_t suspend_waitq;
atomic_t init_cancel;
#endif
u16 logical_addr;
struct work_struct work;
unsigned int rx_wake;
unsigned int tx_wake;
long tx_error;
u32 tx_buf[TEGRA_CEC_FRAME_MAX_LENGTH];
u8 tx_buf_cur;
u8 tx_buf_cnt;
struct reset_control *reset;
u16 rx_fifo[TEGRA_CEC_RX_FIFO_LENGTH];
u16 rx_fifo_data;
};
#define TEGRA_CEC_LADDR_BROADCAST 0xF
#define TEGRA_CEC_LADDR_MASK 0xF
#define TEGRA_CEC_LADDR_WIDTH 4
#define TEGRA_CEC_LADDR_MODE(blk) \
((blk & TEGRA_CEC_LADDR_MASK) == TEGRA_CEC_LADDR_BROADCAST)
/*CEC Timing registers*/
#define TEGRA_CEC_SW_CONTROL 0X000
#define TEGRA_CEC_HW_CONTROL 0X004
#define TEGRA_CEC_INPUT_FILTER 0X008
#define TEGRA_CEC_TX_REGISTER 0X010
#define TEGRA_CEC_RX_REGISTER 0X014
#define TEGRA_CEC_RX_TIMING_0 0X018
#define TEGRA_CEC_RX_TIMING_1 0X01C
#define TEGRA_CEC_RX_TIMING_2 0X020
#define TEGRA_CEC_TX_TIMING_0 0X024
#define TEGRA_CEC_TX_TIMING_1 0X028
#define TEGRA_CEC_TX_TIMING_2 0X02C
#define TEGRA_CEC_INT_STAT 0X030
#define TEGRA_CEC_INT_MASK 0X034
#define TEGRA_CEC_HW_DEBUG_RX 0X038
#define TEGRA_CEC_HW_DEBUG_TX 0X03C
#define TEGRA_CEC_HW_SPARE 0X040
#define TEGRA_CEC_WAKE_STAT_0 0x044
#define TEGRA_CEC_WAKE_MASK_0 0x048
#define TEGRA_CEC_RX_BUFFER_AFULL_CFG_0 0x04c
#define TEGRA_CEC_RX_BUFFER_STAT_0 0x050
#define TEGRA_CEC_RX_TIMING_3_0 0x054
#define TEGRA_CEC_MESSAGE_FILTER_CTRL 0X058
#define TEGRA_CEC_RX_PHYSICAL_ADDR_0 0X05C
#define TEGRA_CEC_RX_OPCODE_0 0x060
#define TEGRA_CEC_RX_OPCODE_1 0x064
#define TEGRA_CEC_RX_OPCODE_2 0x068
#define TEGRA_CEC_RX_OPCODE_3 0x06c
#define TEGRA_CEC_RX_OPCODE_4 0x070
#define TEGRA_CEC_MAX_LOGICAL_ADDR 15
#define TEGRA_CEC_HWCTRL_RX_LADDR_UNREG 0x0
#define TEGRA_CEC_HWCTRL_RX_LADDR_MASK 0x7FFF
#define TEGRA_CEC_HWCTRL_RX_LADDR(x) \
((x<<0) & TEGRA_CEC_HWCTRL_RX_LADDR_MASK)
#define TEGRA_CEC_HWCTRL_RX_SNOOP (1<<15)
#define TEGRA_CEC_HWCTRL_RX_NAK_MODE (1<<16)
#define TEGRA_CEC_HWCTRL_TX_NAK_MODE (1<<24)
#define TEGRA_CEC_HWCTRL_AUTO_CLR_TX_EMPTY_INTR (1<<29)
#define TEGRA_CEC_HWCTRL_FAST_SIM_MODE (1<<30)
#define TEGRA_CEC_HWCTRL_TX_RX_MODE (1<<31)
#define TEGRA_CEC_INPUT_FILTER_MODE (1<<31)
#define TEGRA_CEC_INPUT_FILTER_FIFO_LENGTH_MASK 0
#define TEGRA_CEC_TX_REG_DATA_SHIFT 0
#define TEGRA_CEC_TX_REG_EOM_SHIFT 8
#define TEGRA_CEC_TX_REG_ADDR_MODE_SHIFT 12
#define TEGRA_CEC_TX_REG_START_BIT_SHIFT 16
#define TEGRA_CEC_TX_REG_RETRY_BIT_SHIFT 17
#define TEGRA_CEC_RX_REGISTER_MASK 0
#define TEGRA_CEC_RX_REGISTER_EOM (1<<8)
#define TEGRA_CEC_RX_REGISTER_ACK (1<<9)
#define TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_LO_TIME_MASK 0
#define TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_LO_TIME_MASK 8
#define TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MAX_DURATION_MASK 16
#define TEGRA_CEC_RX_TIMING_0_RX_START_BIT_MIN_DURATION_MASK 24
#define TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_LO_TIME_MASK 0
#define TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_SAMPLE_TIME_MASK 8
#define TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MAX_DURATION_MASK 16
#define TEGRA_CEC_RX_TIMING_1_RX_DATA_BIT_MIN_DURATION_MASK 24
#define TEGRA_CEC_RX_TIMING_2_RX_END_OF_BLOCK_TIME_MASK 0
#define TEGRA_CEC_TX_TIMING_0_TX_START_BIT_LO_TIME_MASK 0
#define TEGRA_CEC_TX_TIMING_0_TX_START_BIT_DURATION_MASK 8
#define TEGRA_CEC_TX_TIMING_0_TX_BUS_XITION_TIME_MASK 16
#define TEGRA_CEC_TX_TIMING_0_TX_BUS_ERROR_LO_TIME_MASK 24
#define TEGRA_CEC_TX_TIMING_1_TX_LO_DATA_BIT_LO_TIME_MASK 0
#define TEGRA_CEC_TX_TIMING_1_TX_HI_DATA_BIT_LO_TIME_MASK 8
#define TEGRA_CEC_TX_TIMING_1_TX_DATA_BIT_DURATION_MASK 16
#define TEGRA_CEC_TX_TIMING_1_TX_ACK_NAK_BIT_SAMPLE_TIME_MASK 24
#define TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_ADDITIONAL_FRAME_MASK 0
#define TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_NEW_FRAME_MASK 4
#define TEGRA_CEC_TX_TIMING_2_BUS_IDLE_TIME_RETRY_FRAME_MASK 8
#define TEGRA_CEC_INT_STAT_TX_REGISTER_EMPTY (1<<0)
#define TEGRA_CEC_INT_STAT_TX_REGISTER_UNDERRUN (1<<1)
#define TEGRA_CEC_INT_STAT_TX_FRAME_OR_BLOCK_NAKD (1<<2)
#define TEGRA_CEC_INT_STAT_TX_ARBITRATION_FAILED (1<<3)
#define TEGRA_CEC_INT_STAT_TX_BUS_ANOMALY_DETECTED (1<<4)
#define TEGRA_CEC_INT_STAT_TX_FRAME_TRANSMITTED (1<<5)
#define TEGRA_CEC_INT_STAT_RX_REGISTER_FULL (1<<8)
#define TEGRA_CEC_INT_STAT_RX_REGISTER_OVERRUN (1<<9)
#define TEGRA_CEC_INT_STAT_RX_START_BIT_DETECTED (1<<10)
#define TEGRA_CEC_INT_STAT_RX_BUS_ANOMALY_DETECTED (1<<11)
#define TEGRA_CEC_INT_STAT_RX_BUS_ERROR_DETECTED (1<<12)
#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_H2L (1<<13)
#define TEGRA_CEC_INT_STAT_FILTERED_RX_DATA_PIN_TRANSITION_L2H (1<<14)
#define TEGRA_CEC_INT_MASK_TX_REGISTER_EMPTY (1<<0)
#define TEGRA_CEC_INT_MASK_TX_REGISTER_UNDERRUN (1<<1)
#define TEGRA_CEC_INT_MASK_TX_FRAME_OR_BLOCK_NAKD (1<<2)
#define TEGRA_CEC_INT_MASK_TX_ARBITRATION_FAILED (1<<3)
#define TEGRA_CEC_INT_MASK_TX_BUS_ANOMALY_DETECTED (1<<4)
#define TEGRA_CEC_INT_MASK_TX_FRAME_TRANSMITTED (1<<5)
#define TEGRA_CEC_INT_MASK_RX_REGISTER_FULL (1<<8)
#define TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN (1<<9)
#define TEGRA_CEC_INT_MASK_RX_START_BIT_DETECTED (1<<10)
#define TEGRA_CEC_INT_MASK_RX_BUS_ANOMALY_DETECTED (1<<11)
#define TEGRA_CEC_INT_MASK_RX_BUS_ERROR_DETECTED (1<<12)
#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_H2L (1<<13)
#define TEGRA_CEC_INT_MASK_FILTERED_RX_DATA_PIN_TRANSITION_L2H (1<<14)
#define TEGRA_CEC_HW_DEBUG_TX_DURATION_COUNT_MASK 0
#define TEGRA_CEC_HW_DEBUG_TX_TXBIT_COUNT_MASK 17
#define TEGRA_CEC_HW_DEBUG_TX_STATE_MASK 21
#define TEGRA_CEC_HW_DEBUG_TX_FORCELOOUT (1<<25)
#define TEGRA_CEC_HW_DEBUG_TX_TXDATABIT_SAMPLE_TIMER (1<<26)
#define TEGRA_CEC_NAME "tegra_cec"
#endif /* TEGRA_CEC_H */

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -726,9 +726,21 @@ static struct of_device_id tegra_virt_mtd_match[] = {
MODULE_DEVICE_TABLE(of, tegra_virt_mtd_match);
#endif /* CONFIG_OF */
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void tegra_virt_mtd_remove_wrapper(struct platform_device *pdev)
{
tegra_virt_mtd_remove(pdev);
}
#else
static int tegra_virt_mtd_remove_wrapper(struct platform_device *pdev)
{
return tegra_virt_mtd_remove(pdev);
}
#endif
static struct platform_driver tegra_virt_mtd_driver = {
.probe = tegra_virt_mtd_probe,
.remove = tegra_virt_mtd_remove,
.remove = tegra_virt_mtd_remove_wrapper,
.driver = {
.name = "Virtual MTD device",
.owner = THIS_MODULE,

View File

@@ -291,7 +291,7 @@ inline u32 ttcan_read_ecr(struct ttcan_controller *ttcan)
return ttcan_read32(ttcan, ADR_MTTCAN_ECR);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
#if !defined(CONFIG_TEGRA_PROD_NEXT_GEN)
static void tegra_mttcan_config_prod_settings(struct mttcan_priv *priv)
{
struct ttcan_controller *ttcan = priv->ttcan;

View File

@@ -287,7 +287,7 @@ struct ttcan_controller {
struct list_head rx_q1;
struct list_head rx_b;
struct list_head tx_evt;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
#if !defined(CONFIG_TEGRA_PROD_NEXT_GEN)
struct tegra_prod *prod_list;
#else
struct tegra_prod_cfg_list *prod_list;

View File

@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -12,7 +10,7 @@
#define CAN_MSG_FLUSH_TIMEOUT 100
static void mttcan_start(struct net_device *dev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
#if defined(CONFIG_TEGRA_PROD_NEXT_GEN)
#define MTTCAN_PROD_FIELD(name, rindex, roffset, fname) \
{ \
.field_name = name, \
@@ -1879,7 +1877,7 @@ static int mttcan_probe(struct platform_device *pdev)
if (ret)
goto exit_free_device;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
#if !defined(CONFIG_TEGRA_PROD_NEXT_GEN)
priv->ttcan->prod_list = devm_tegra_prod_get(&pdev->dev);
#else
priv->ttcan->prod_list = devm_tegra_prod_get_list(&pdev->dev, &mttcan_prod_dev_info);
@@ -1935,7 +1933,11 @@ static int mttcan_remove(struct platform_device *pdev)
dev_info(&dev->dev, "%s\n", __func__);
#if defined(NV_TIMER_DELETE_PRESENT) /* Linux v6.15 */
timer_delete_sync(&priv->timer);
#else
del_timer_sync(&priv->timer);
#endif
mttcan_delete_sys_files(&dev->dev);
unregister_mttcan_dev(dev);
mttcan_unprepare_clock(priv);
@@ -2009,6 +2011,18 @@ static int mttcan_resume(struct platform_device *pdev)
}
#endif
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void mttcan_remove_wrapper(struct platform_device *pdev)
{
mttcan_remove(pdev);
}
#else
static int mttcan_remove_wrapper(struct platform_device *pdev)
{
return mttcan_remove(pdev);
}
#endif
static struct platform_driver mttcan_plat_driver = {
.driver = {
.name = KBUILD_MODNAME,
@@ -2016,7 +2030,7 @@ static struct platform_driver mttcan_plat_driver = {
.of_match_table = of_match_ptr(mttcan_of_table),
},
.probe = mttcan_probe,
.remove = mttcan_remove,
.remove = mttcan_remove_wrapper,
#ifdef CONFIG_PM
.suspend = mttcan_suspend,
.resume = mttcan_resume,

View File

@@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: GPL-2.0
nvethernetrm

View File

@@ -59,5 +59,9 @@ nvethernet-objs:= ether_linux.o \
include $(srctree.nvidia-oot)/drivers/net/ethernet/nvidia/nvethernet/nvethernetrm/include/config.tmk
ifeq ($(NV_BUILD_CONFIGURATION_IS_VLTEST),1)
ccflags-y += -DNV_VLTEST_BUILD
endif
# Undefine HSI_SUPPORT if CONFIG_TEGRA_EPL is not defined.
ccflags-y += $(if $(CONFIG_TEGRA_EPL),,-UHSI_SUPPORT)

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-FileCopyrightText: Copyright (c) 2019-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-FileCopyrightText: Copyright (c) 2019-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
@@ -339,8 +339,9 @@ static inline void ether_hsi_work_func(struct work_struct *work)
mutex_unlock(&pdata->hsi_lock);
}
if (osi_core->hsi.report_err == OSI_ENABLE ||
osi_core->hsi.macsec_report_err == OSI_ENABLE)
if (osi_core->hsi.enabled == OSI_ENABLE &&
(osi_core->hsi.report_err == OSI_ENABLE ||
osi_core->hsi.macsec_report_err == OSI_ENABLE))
ether_common_isr_thread(0, (void *)pdata);
schedule_delayed_work(&pdata->ether_hsi_work,
@@ -2448,15 +2449,18 @@ static int ether_mdio_write(struct mii_bus *bus, int phyaddr, int phyreg,
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY write\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr, (unsigned int)phyreg, phydata);
mutex_unlock(&pdata->osi_mdio_lock);
return osi_write_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg, phydata);
return ret;
}
/**
@@ -2478,15 +2482,18 @@ static int ether_mdio_read(struct mii_bus *bus, int phyaddr, int phyreg)
{
struct net_device *ndev = bus->priv;
struct ether_priv_data *pdata = netdev_priv(ndev);
int ret = 0;
if (!pdata->clks_enable) {
dev_err(pdata->dev,
"%s:No clks available, skipping PHY read\n", __func__);
return -ENODEV;
}
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr, (unsigned int)phyreg);
mutex_unlock(&pdata->osi_mdio_lock);
return osi_read_phy_reg(pdata->osi_core, (unsigned int)phyaddr,
(unsigned int)phyreg);
return ret;
}
#if defined(NV_MII_BUS_STRUCT_HAS_WRITE_C45) /* Linux v6.3 */
@@ -2949,7 +2956,11 @@ static int ether_close(struct net_device *ndev)
int i;
#ifdef ETHER_NVGRO
#if defined(NV_TIMER_DELETE_PRESENT) /* Linux v6.15 */
timer_delete_sync(&pdata->nvgro_timer);
#else
del_timer_sync(&pdata->nvgro_timer);
#endif
/* TODO: purge the queues */
#endif
@@ -3797,7 +3808,9 @@ static int ether_handle_priv_rmdio_ioctl(struct ether_priv_data *pdata,
dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d\n",
__func__, mii_data->phy_id, prtad, devad);
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_read_phy_reg(pdata->osi_core, prtad, devad);
mutex_unlock(&pdata->osi_mdio_lock);
if (ret < 0) {
dev_err(pdata->dev, "%s: Data read failed\n", __func__);
return -EFAULT;
@@ -3825,6 +3838,7 @@ static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
{
struct mii_ioctl_data *mii_data = if_mii(ifr);
unsigned int prtad, devad;
int ret = 0;
if (mdio_phy_id_is_c45(mii_data->phy_id)) {
prtad = mdio_phy_id_prtad(mii_data->phy_id);
@@ -3838,8 +3852,11 @@ static int ether_handle_priv_wmdio_ioctl(struct ether_priv_data *pdata,
dev_dbg(pdata->dev, "%s: phy_id:%d regadd: %d devaddr:%d val:%d\n",
__func__, mii_data->phy_id, prtad, devad, mii_data->val_in);
return osi_write_phy_reg(pdata->osi_core, prtad, devad,
mii_data->val_in);
mutex_lock(&pdata->osi_mdio_lock);
ret = osi_write_phy_reg(pdata->osi_core, prtad, devad, mii_data->val_in);
mutex_unlock(&pdata->osi_mdio_lock);
return ret;
}
/**
@@ -5790,6 +5807,13 @@ static int ether_parse_dt(struct ether_priv_data *pdata)
}
}
/* Read MAC instance id */
ret = of_property_read_u32(np, "nvidia,instance_id", &osi_core->instance_id);
if (ret != 0) {
dev_info(dev, "DT instance_id missing\n");
return -EINVAL;
}
if (osi_dma->num_dma_chans != osi_core->num_mtl_queues) {
dev_err(dev, "mismatch in numbers of DMA channel and MTL Q\n");
return -EINVAL;
@@ -6540,6 +6564,8 @@ static int ether_probe(struct platform_device *pdev)
osi_core->osd = pdata;
osi_dma->osd = pdata;
mutex_init(&pdata->osi_mdio_lock);
osi_core->num_mtl_queues = num_mtl_queues;
osi_dma->num_dma_chans = num_dma_chans;
@@ -6647,10 +6673,16 @@ static int ether_probe(struct platform_device *pdev)
chan = osi_dma->dma_chans[i];
atomic_set(&pdata->tx_napi[chan]->tx_usecs_timer_armed,
OSI_DISABLE);
#if defined(NV_HRTIMER_SETUP_PRESENT) /* Linux v6.13 */
hrtimer_setup(&pdata->tx_napi[chan]->tx_usecs_timer,
ether_tx_usecs_hrtimer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
#else
hrtimer_init(&pdata->tx_napi[chan]->tx_usecs_timer,
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
pdata->tx_napi[chan]->tx_usecs_timer.function =
ether_tx_usecs_hrtimer;
#endif
}
ret = register_netdev(ndev);
@@ -6823,6 +6855,107 @@ static void ether_shutdown(struct platform_device *pdev)
}
#ifdef CONFIG_PM
#ifndef OSI_STRIPPED_LIB
/**
* @brief Revert the WOL settings
*
* Alogorithm: Create a struct ethtool_wolinfo to disable WOL settings
*
* @param[in] dev: Platform device associated with platform driver.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static inline int ether_revert_wol(struct device *dev)
{
int ret = 0;
u32 wolopts = 0;
struct net_device *ndev = dev_get_drvdata(dev);
struct ether_priv_data *pdata = netdev_priv(ndev);
swap(pdata->wol.wolopts, wolopts);
ret = ether_set_wol_impl(ndev, &pdata->wol);
pdata->wol.wolopts = wolopts;
if (ret)
dev_err(pdata->dev, "Fail to enable PHY network functionality %d\n", ret);
return ret;
}
/**
* @brief Ethernet platform driver prepare callback.
*
* Alogorithm: Configure the defer WOL settings if enabled by user
*
* @param[in] dev: Platform device associated with platform driver.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_prepare(struct device *dev)
{
int ret = 0;
struct net_device *ndev = dev_get_drvdata(dev);
struct ether_priv_data *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phydev;
if (pdata->wol.wolopts) {
ret = ether_set_wol_impl(ndev, &pdata->wol);
if (ret)
goto ether_prepare_fail;
ret = enable_irq_wake(phydev->irq);
if (ret) {
dev_err(pdata->dev, "PHY enable irq wake failed, %d\n",
ret);
goto ether_prepare_fail;
}
/* enable device wake on WoL set */
device_init_wakeup(&ndev->dev, true);
}
ether_prepare_fail:
if (unlikely(ret))
ether_revert_wol(dev);
return ret;
}
/**
* @brief Ethernet platform driver complete callback.
*
* Alogorithm: Revert the defer WOL settings if enabled by user
*
* @param[in] dev: Platform device associated with platform driver.
*/
static void ether_complete(struct device *dev)
{
int ret;
struct net_device *ndev = dev_get_drvdata(dev);
struct ether_priv_data *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phydev;
if (pdata->wol.wolopts) {
ret = ether_revert_wol(dev);
if (ret) {
dev_err(pdata->dev, "Fail to enable PHY network functionality %d\n", ret);
return;
}
ret = disable_irq_wake(phydev->irq);
if (ret) {
dev_info(pdata->dev,
"PHY disable irq wake failed, %d\n",
ret);
}
/* disable device wake on WoL reset */
device_init_wakeup(&ndev->dev, false);
}
return;
}
#endif /* !(OSI_STRIPPED_LIB) */
/**
* @brief Ethernet platform driver resume call.
*
@@ -7027,10 +7160,14 @@ static int ether_resume_noirq(struct device *dev)
return ret;
}
return 0;
return ret;
}
static const struct dev_pm_ops ether_pm_ops = {
#ifndef OSI_STRIPPED_LIB
.prepare = ether_prepare,
.complete = ether_complete,
#endif /* !OSI_STRIPPED_LIB */
.suspend = ether_suspend_noirq,
.resume = ether_resume_noirq,
};
@@ -7048,12 +7185,24 @@ static const struct of_device_id ether_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ether_of_match);
#if defined(NV_PLATFORM_DRIVER_STRUCT_REMOVE_RETURNS_VOID) /* Linux v6.11 */
static void ether_remove_wrapper(struct platform_device *pdev)
{
ether_remove(pdev);
}
#else
static int ether_remove_wrapper(struct platform_device *pdev)
{
return ether_remove(pdev);
}
#endif
/**
* @brief Ethernet platform driver instance
*/
static struct platform_driver ether_driver = {
.probe = ether_probe,
.remove = ether_remove,
.remove = ether_remove_wrapper,
.shutdown = ether_shutdown,
.driver = {
.name = "nvethernet",

View File

@@ -668,6 +668,10 @@ struct ether_priv_data {
struct tasklet_struct lane_restart_task;
/** xtra sw error counters */
struct ether_xtra_stat_counters xstats;
/** wol configs */
struct ethtool_wolinfo wol;
/** MDIO lock for OSI function calls **/
struct mutex osi_mdio_lock;
};
/**
@@ -678,6 +682,21 @@ struct ether_priv_data {
* @note Network device needs to created.
*/
void ether_set_ethtool_ops(struct net_device *ndev);
/**
* @brief Configure WOL settings in PHY subsystem
*
* @param[in] ndev pointer to net device structure.
* @param[in] wol pointer to ethtool_wolinfo structure.
*
* @note MAC and PHY need to be initialized.
*
* @retval zero on success and -ve number on failure.
*/
int ether_set_wol_impl(struct net_device *ndev, struct ethtool_wolinfo *wol);
/**
* @brief Creates Ethernet sysfs group
*

View File

@@ -1336,6 +1336,38 @@ static int ether_set_eee(struct net_device *ndev,
return 0;
}
/**
* @brief Configure WOL settings in PHY subsystem
*
* Algorithm: Call phy subsystem to enable or disable
* Wake On Lan settings based on wol param
*
* @param[in] ndev pointer to net device structure.
* @param[in] wol pointer to ethtool_wolinfo structure.
*
* @note MAC and PHY need to be initialized.
*
* @retval zero on success and -ve number on failure.
*/
int ether_set_wol_impl(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
struct ether_priv_data *pdata = netdev_priv(ndev);
struct phy_device *phydev = pdata->phydev;
if (!phydev) {
netdev_err(pdata->ndev,
"%s: phydev is null check iface up status\n",
__func__);
return -ENOTSUPP;
}
if (!phy_interrupt_is_valid(phydev))
return -ENOTSUPP;
return phy_ethtool_set_wol(pdata->phydev, wol);
}
/**
* @brief This function is invoked by kernel when user request to set
* pmt parameters for remote wakeup or magic wakeup
@@ -1351,46 +1383,24 @@ static int ether_set_eee(struct net_device *ndev,
*/
static int ether_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
int ret = 0;
struct ether_priv_data *pdata = netdev_priv(ndev);
int ret;
if (!wol)
return -EINVAL;
if (!pdata->phydev) {
netdev_err(pdata->ndev,
"%s: phydev is null check iface up status\n",
__func__);
return -ENOTSUPP;
}
if (!phy_interrupt_is_valid(pdata->phydev))
return -ENOTSUPP;
ret = phy_ethtool_set_wol(pdata->phydev, wol);
if (ret < 0)
return ret;
/* Disable WOL on demand.
* Enabling WOL will to deferred to before system suspend.
*/
if (wol->wolopts) {
ret = enable_irq_wake(pdata->phydev->irq);
if (ret) {
dev_err(pdata->dev, "PHY enable irq wake failed, %d\n",
ret);
return ret;
}
/* enable device wake on WoL set */
device_init_wakeup(&ndev->dev, true);
} else {
ret = disable_irq_wake(pdata->phydev->irq);
if (ret) {
dev_info(pdata->dev,
"PHY disable irq wake failed, %d\n",
ret);
}
/* disable device wake on WoL reset */
device_init_wakeup(&ndev->dev, false);
}
/* The WOL request to the PHY layer is defered, and will apply on
* it only when the system is going to suspend. */
memcpy(&pdata->wol, wol, sizeof(struct ethtool_wolinfo));
} else {
/* Set wolopts to 0 to implicitly say that WOL is disabled */
pdata->wol.wolopts = 0;
ret = ether_set_wol_impl(ndev, wol);
}
return ret;
}
@@ -1411,6 +1421,7 @@ static int ether_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
static void ether_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
{
struct ether_priv_data *pdata = netdev_priv(ndev);
u32 wolopts;
if (!wol)
return;
@@ -1422,13 +1433,20 @@ static void ether_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
return;
}
wol->supported = 0;
wol->wolopts = 0;
if (!phy_interrupt_is_valid(pdata->phydev))
return;
phy_ethtool_get_wol(pdata->phydev, wol);
wolopts = pdata->wol.wolopts;
pdata->wol.supported = 0;
pdata->wol.wolopts = 0;
phy_ethtool_get_wol(pdata->phydev, &pdata->wol);
if (wolopts & WAKE_MAGIC) {
pdata->wol.wolopts |= WAKE_MAGIC;
}
memcpy(wol, &pdata->wol, sizeof(struct ethtool_wolinfo));
}
/**

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved */
/* Copyright (c) 2019-2025, NVIDIA CORPORATION. All rights reserved */
#ifdef MACSEC_SUPPORT
#include "ether_linux.h"

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019-2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved */
// SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved
#ifndef OSI_STRIPPED_LIB
#include "ether_linux.h"
@@ -290,7 +290,11 @@ static int ether_test_phy_loopback(struct ether_priv_data *pdata)
if (!pdata->phydev)
return -ENODEV;
#if defined(NV_PHY_LOOPBACK_HAS_SPEED_ARG) /* Linux v6.15 */
ret = phy_loopback(pdata->phydev, true, 0);
#else
ret = phy_loopback(pdata->phydev, true);
#endif
if (ret != 0 && ret != -EBUSY)
return ret;
@@ -406,7 +410,11 @@ void ether_selftest_run(struct net_device *dev,
case ETHER_LOOPBACK_PHY:
ret = -EOPNOTSUPP;
if (dev->phydev)
#if defined(NV_PHY_LOOPBACK_HAS_SPEED_ARG) /* Linux v6.15 */
ret = phy_loopback(dev->phydev, true, 0);
#else
ret = phy_loopback(dev->phydev, true);
#endif
if (!ret)
break;
/* Fallthrough */
@@ -439,7 +447,11 @@ void ether_selftest_run(struct net_device *dev,
case ETHER_LOOPBACK_PHY:
ret = -EOPNOTSUPP;
if (dev->phydev)
#if defined(NV_PHY_LOOPBACK_HAS_SPEED_ARG) /* Linux v6.15 */
ret = phy_loopback(dev->phydev, false, 0);
#else
ret = phy_loopback(dev->phydev, false);
#endif
if (!ret)
break;
/* Fallthrough */

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2019-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved */
/* Copyright (c) 2019-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved */
#include "ether_linux.h"
#include "macsec.h"
@@ -2543,8 +2543,7 @@ static DEVICE_ATTR(nvgro_dump, 0644,
ether_nvgro_dump_show, NULL);
#endif
#ifdef HSI_SUPPORT
#if (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
#if defined HSI_SUPPORT && defined(NV_VLTEST_BUILD) && (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
static int hsi_inject_err_fsi(unsigned int inst_id,
struct epl_error_report_frame error_report,
void *data)
@@ -2562,7 +2561,6 @@ static int hsi_inject_err_fsi(unsigned int inst_id,
return ret;
}
#endif
/**
* @brief Shows HSI feature enabled status
@@ -2611,10 +2609,8 @@ static ssize_t hsi_enable_store(struct device *dev,
struct osi_core_priv_data *osi_core = pdata->osi_core;
struct osi_ioctl ioctl_data = {};
int ret = 0;
#if (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
u32 inst_id = osi_core->instance_id;
u32 ip_type[2] = {IP_EQOS, IP_MGBE};
#endif
if (osi_core->use_virtualization == OSI_ENABLE) {
dev_err(pdata->dev, "Not supported with Ethernet virtualization enabled\n");
@@ -2636,7 +2632,6 @@ static ssize_t hsi_enable_store(struct device *dev,
} else {
osi_core->hsi.enabled = OSI_ENABLE;
dev_info(pdata->dev, "HSI Enabled\n");
#if (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
if (osi_core->instance_id == OSI_INSTANCE_ID_EQOS)
inst_id = 0;
@@ -2646,7 +2641,6 @@ static ssize_t hsi_enable_store(struct device *dev,
dev_err(pdata->dev, "Err inj callback registration failed: %d",
ret);
}
#endif
}
} else if (strncmp(buf, "disable", 7) == OSI_NONE) {
ioctl_data.arg1_u32 = OSI_DISABLE;
@@ -2657,7 +2651,6 @@ static ssize_t hsi_enable_store(struct device *dev,
} else {
osi_core->hsi.enabled = OSI_DISABLE;
dev_info(pdata->dev, "HSI Disabled\n");
#if (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
if (osi_core->instance_id == OSI_INSTANCE_ID_EQOS)
inst_id = 0;
@@ -2666,7 +2659,6 @@ static ssize_t hsi_enable_store(struct device *dev,
dev_err(pdata->dev, "Err inj callback deregistration failed: %d",
ret);
}
#endif
}
} else {
dev_err(pdata->dev,
@@ -2728,13 +2720,40 @@ static struct attribute *ether_sysfs_attrs[] = {
&dev_attr_nvgro_stats.attr,
&dev_attr_nvgro_dump.attr,
#endif
#ifdef HSI_SUPPORT
#if defined HSI_SUPPORT && defined(NV_VLTEST_BUILD) && (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
&dev_attr_hsi_enable.attr,
#endif
#endif /* OSI_STRIPPED_LIB */
NULL
};
/**
* @brief Attributes for nvethernet sysfs without MACSEC
*/
static struct attribute *ether_sysfs_attrs_without_macsec[] = {
#ifndef OSI_STRIPPED_LIB
#ifdef OSI_DEBUG
&dev_attr_desc_dump_enable.attr,
#endif /* OSI_DEBUG */
&dev_attr_mac_loopback.attr,
&dev_attr_ptp_mode.attr,
&dev_attr_ptp_sync.attr,
&dev_attr_frp.attr,
&dev_attr_uphy_gbe_mode.attr,
&dev_attr_phy_iface_mode.attr,
#ifdef ETHER_NVGRO
&dev_attr_nvgro_pkt_age_msec.attr,
&dev_attr_nvgro_timer_interval.attr,
&dev_attr_nvgro_stats.attr,
&dev_attr_nvgro_dump.attr,
#endif
#endif /* OSI_STRIPPED_LIB */
#if defined HSI_SUPPORT && defined(NV_VLTEST_BUILD) && (IS_ENABLED(CONFIG_TEGRA_HSIERRRPTINJ))
&dev_attr_hsi_enable.attr,
#endif
NULL
};
/**
* @brief Ethernet sysfs attribute group
*/
@@ -2743,6 +2762,14 @@ static struct attribute_group ether_attribute_group = {
.attrs = ether_sysfs_attrs,
};
/**
* @brief Ethernet sysfs attribute group without macsec
*/
static struct attribute_group ether_attribute_group_wo_macsec = {
.name = "nvethernet",
.attrs = ether_sysfs_attrs_without_macsec,
};
#ifndef OSI_STRIPPED_LIB
#ifdef CONFIG_DEBUG_FS
static char *timestamp_system_source(unsigned int source)
@@ -3331,7 +3358,10 @@ int ether_sysfs_register(struct ether_priv_data *pdata)
#endif /* OSI_STRIPPED_LIB */
/* Create nvethernet sysfs group under /sys/devices/<ether_device>/ */
return sysfs_create_group(&dev->kobj, &ether_attribute_group);
if (pdata->macsec_pdata)
return sysfs_create_group(&dev->kobj, &ether_attribute_group);
else
return sysfs_create_group(&dev->kobj, &ether_attribute_group_wo_macsec);
}
void ether_sysfs_unregister(struct ether_priv_data *pdata)
@@ -3343,5 +3373,8 @@ void ether_sysfs_unregister(struct ether_priv_data *pdata)
#endif
#endif /* OSI_STRIPPED_LIB */
/* Remove nvethernet sysfs group under /sys/devices/<ether_device>/ */
sysfs_remove_group(&dev->kobj, &ether_attribute_group);
if (pdata->macsec_pdata)
sysfs_remove_group(&dev->kobj, &ether_attribute_group);
else
sysfs_remove_group(&dev->kobj, &ether_attribute_group_wo_macsec);
}

View File

@@ -28435,7 +28435,8 @@ rtl8168_init_one(struct pci_dev *pdev,
struct rtl8168_private *tp;
void __iomem *ioaddr = NULL;
static int board_idx = -1;
u16 desired_mps = 128;
u32 desired_mrrs = 512;
int rc;
assert(pdev != NULL);
@@ -28598,6 +28599,22 @@ rtl8168_init_one(struct pci_dev *pdev,
rtl8168_hw_reset(dev);
/* Set Maximum Payload Size (MPS) */
rc = pcie_set_mps(pdev->bus->self, desired_mps);
if (rc) {
dev_err(&pdev->bus->self->dev, "Failed to set MPS to %u (error %d)\n",
desired_mps, rc);
return rc;
}
/* Set Maximum Read Request Size (MRRS) */
rc = pcie_set_readrq(pdev->bus->self, desired_mrrs);
if (rc) {
dev_err(&pdev->bus->self->dev, "Failed to set MRRS to %u (error %d)\n",
desired_mrrs, rc);
return rc;
}
/* Get production from EEPROM */
if (((tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 ||
tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_29 ||

Some files were not shown because too many files have changed in this diff Show More