From: Sasha Levin Date: Sun, 25 Dec 2022 03:33:07 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v5.15.86~80 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b79062f35f36cd683e518f3ee50e40e16f89c3f3;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/acct-fix-potential-integer-overflow-in-encode_comp_t.patch b/queue-5.15/acct-fix-potential-integer-overflow-in-encode_comp_t.patch new file mode 100644 index 00000000000..fe47f466c3f --- /dev/null +++ b/queue-5.15/acct-fix-potential-integer-overflow-in-encode_comp_t.patch @@ -0,0 +1,51 @@ +From 397b38a7f116e7a8ac577edf069127f347a726e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 May 2021 22:06:31 +0800 +Subject: acct: fix potential integer overflow in encode_comp_t() + +From: Zheng Yejian + +[ Upstream commit c5f31c655bcc01b6da53b836ac951c1556245305 ] + +The integer overflow is descripted with following codes: + > 317 static comp_t encode_comp_t(u64 value) + > 318 { + > 319 int exp, rnd; + ...... + > 341 exp <<= MANTSIZE; + > 342 exp += value; + > 343 return exp; + > 344 } + +Currently comp_t is defined as type of '__u16', but the variable 'exp' is +type of 'int', so overflow would happen when variable 'exp' in line 343 is +greater than 65535. + +Link: https://lkml.kernel.org/r/20210515140631.369106-3-zhengyejian1@huawei.com +Signed-off-by: Zheng Yejian +Cc: Hanjun Guo +Cc: Randy Dunlap +Cc: Vlastimil Babka +Cc: Zhang Jinhao +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/acct.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/kernel/acct.c b/kernel/acct.c +index 23a7ab8e6cbc..2b5cc63eb295 100644 +--- a/kernel/acct.c ++++ b/kernel/acct.c +@@ -331,6 +331,8 @@ static comp_t encode_comp_t(unsigned long value) + exp++; + } + ++ if (exp > (((comp_t) ~0U) >> MANTSIZE)) ++ return (comp_t) ~0U; + /* + * Clean it up and polish it off. + */ +-- +2.35.1 + diff --git a/queue-5.15/acpica-fix-error-code-path-in-acpi_ds_call_control_m.patch b/queue-5.15/acpica-fix-error-code-path-in-acpi_ds_call_control_m.patch new file mode 100644 index 00000000000..fe0aad15b72 --- /dev/null +++ b/queue-5.15/acpica-fix-error-code-path-in-acpi_ds_call_control_m.patch @@ -0,0 +1,68 @@ +From f49ead307e06876cb94839e84708c470fb13f05d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 18:42:36 +0100 +Subject: ACPICA: Fix error code path in acpi_ds_call_control_method() + +From: Rafael J. Wysocki + +[ Upstream commit 404ec60438add1afadaffaed34bb5fe4ddcadd40 ] + +A use-after-free in acpi_ps_parse_aml() after a failing invocaion of +acpi_ds_call_control_method() is reported by KASAN [1] and code +inspection reveals that next_walk_state pushed to the thread by +acpi_ds_create_walk_state() is freed on errors, but it is not popped +from the thread beforehand. Thus acpi_ds_get_current_walk_state() +called by acpi_ps_parse_aml() subsequently returns it as the new +walk state which is incorrect. + +To address this, make acpi_ds_call_control_method() call +acpi_ds_pop_walk_state() to pop next_walk_state from the thread before +returning an error. + +Link: https://lore.kernel.org/linux-acpi/20221019073443.248215-1-chenzhongjin@huawei.com/ # [1] +Reported-by: Chen Zhongjin +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Chen Zhongjin +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpica/dsmethod.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c +index 8e011e59b9b4..ee1832ba39a2 100644 +--- a/drivers/acpi/acpica/dsmethod.c ++++ b/drivers/acpi/acpica/dsmethod.c +@@ -517,7 +517,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); + if (!info) { + status = AE_NO_MEMORY; +- goto cleanup; ++ goto pop_walk_state; + } + + info->parameters = &this_walk_state->operands[0]; +@@ -529,7 +529,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + + ACPI_FREE(info); + if (ACPI_FAILURE(status)) { +- goto cleanup; ++ goto pop_walk_state; + } + + next_walk_state->method_nesting_depth = +@@ -575,6 +575,12 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, + + return_ACPI_STATUS(status); + ++pop_walk_state: ++ ++ /* On error, pop the walk state to be deleted from thread */ ++ ++ acpi_ds_pop_walk_state(thread); ++ + cleanup: + + /* On error, we must terminate the method properly */ +-- +2.35.1 + diff --git a/queue-5.15/acpica-fix-use-after-free-in-acpi_ut_copy_ipackage_t.patch b/queue-5.15/acpica-fix-use-after-free-in-acpi_ut_copy_ipackage_t.patch new file mode 100644 index 00000000000..af4a75c5490 --- /dev/null +++ b/queue-5.15/acpica-fix-use-after-free-in-acpi_ut_copy_ipackage_t.patch @@ -0,0 +1,70 @@ +From 6384cee12e2f44c22bb8cd3278cf2cfec4ed53fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 16:05:14 +0800 +Subject: ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage() + +From: Li Zetao + +[ Upstream commit 470188b09e92d83c5a997f25f0e8fb8cd2bc3469 ] + +There is an use-after-free reported by KASAN: + + BUG: KASAN: use-after-free in acpi_ut_remove_reference+0x3b/0x82 + Read of size 1 at addr ffff888112afc460 by task modprobe/2111 + CPU: 0 PID: 2111 Comm: modprobe Not tainted 6.1.0-rc7-dirty + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), + Call Trace: + + kasan_report+0xae/0xe0 + acpi_ut_remove_reference+0x3b/0x82 + acpi_ut_copy_iobject_to_iobject+0x3be/0x3d5 + acpi_ds_store_object_to_local+0x15d/0x3a0 + acpi_ex_store+0x78d/0x7fd + acpi_ex_opcode_1A_1T_1R+0xbe4/0xf9b + acpi_ps_parse_aml+0x217/0x8d5 + ... + + +The root cause of the problem is that the acpi_operand_object +is freed when acpi_ut_walk_package_tree() fails in +acpi_ut_copy_ipackage_to_ipackage(), lead to repeated release in +acpi_ut_copy_iobject_to_iobject(). The problem was introduced +by "8aa5e56eeb61" commit, this commit is to fix memory leak in +acpi_ut_copy_iobject_to_iobject(), repeatedly adding remove +operation, lead to "acpi_operand_object" used after free. + +Fix it by removing acpi_ut_remove_reference() in +acpi_ut_copy_ipackage_to_ipackage(). acpi_ut_copy_ipackage_to_ipackage() +is called to copy an internal package object into another internal +package object, when it fails, the memory of acpi_operand_object +should be freed by the caller. + +Fixes: 8aa5e56eeb61 ("ACPICA: Utilities: Fix memory leak in acpi_ut_copy_iobject_to_iobject") +Signed-off-by: Li Zetao +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpica/utcopy.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c +index d9877153f400..fdd503bb69c4 100644 +--- a/drivers/acpi/acpica/utcopy.c ++++ b/drivers/acpi/acpica/utcopy.c +@@ -916,13 +916,6 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, + status = acpi_ut_walk_package_tree(source_obj, dest_obj, + acpi_ut_copy_ielement_to_ielement, + walk_state); +- if (ACPI_FAILURE(status)) { +- +- /* On failure, delete the destination package object */ +- +- acpi_ut_remove_reference(dest_obj); +- } +- + return_ACPI_STATUS(status); + } + +-- +2.35.1 + diff --git a/queue-5.15/af_unix-call-proto_unregister-in-the-error-path-in-a.patch b/queue-5.15/af_unix-call-proto_unregister-in-the-error-path-in-a.patch new file mode 100644 index 00000000000..677d9c6b29f --- /dev/null +++ b/queue-5.15/af_unix-call-proto_unregister-in-the-error-path-in-a.patch @@ -0,0 +1,37 @@ +From cfb9104394f5d2525237d90b2c7a37aad83af3d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 23:01:58 +0800 +Subject: af_unix: call proto_unregister() in the error path in af_unix_init() + +From: Yang Yingliang + +[ Upstream commit 73e341e0281a35274629e9be27eae2f9b1b492bf ] + +If register unix_stream_proto returns error, unix_dgram_proto needs +be unregistered. + +Fixes: 94531cfcbe79 ("af_unix: Add unix_stream_proto for sockmap") +Signed-off-by: Yang Yingliang +Reviewed-by: Simon Horman +Reviewed-by: Kuniyuki Iwashima +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index a579e28bd213..545823c1d5ed 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -3401,6 +3401,7 @@ static int __init af_unix_init(void) + rc = proto_register(&unix_stream_proto, 1); + if (rc != 0) { + pr_crit("%s: Cannot create unix_sock SLAB cache!\n", __func__); ++ proto_unregister(&unix_dgram_proto); + goto out; + } + +-- +2.35.1 + diff --git a/queue-5.15/alpha-fix-syscall-entry-in-audut_syscall-case.patch b/queue-5.15/alpha-fix-syscall-entry-in-audut_syscall-case.patch new file mode 100644 index 00000000000..ae3daa4f490 --- /dev/null +++ b/queue-5.15/alpha-fix-syscall-entry-in-audut_syscall-case.patch @@ -0,0 +1,40 @@ +From 9f4d46b3ec71532682bc3e1067bd60241a9a835f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Sep 2021 18:18:48 -0400 +Subject: alpha: fix syscall entry in !AUDUT_SYSCALL case + +From: Al Viro + +[ Upstream commit f7b2431a6d22f7a91c567708e071dfcd6d66db14 ] + +We only want to take the slow path if SYSCALL_TRACE or SYSCALL_AUDIT is +set; on !AUDIT_SYSCALL configs the current tree hits it whenever _any_ +thread flag (including NEED_RESCHED, NOTIFY_SIGNAL, etc.) happens to +be set. + +Fixes: a9302e843944 "alpha: Enable system-call auditing support" +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/alpha/kernel/entry.S | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S +index e227f3a29a43..c41a5a9c3b9f 100644 +--- a/arch/alpha/kernel/entry.S ++++ b/arch/alpha/kernel/entry.S +@@ -469,8 +469,10 @@ entSys: + #ifdef CONFIG_AUDITSYSCALL + lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT + and $3, $6, $3 +-#endif + bne $3, strace ++#else ++ blbs $3, strace /* check for SYSCALL_TRACE in disguise */ ++#endif + beq $4, 1f + ldq $27, 0($5) + 1: jsr $26, ($27), sys_ni_syscall +-- +2.35.1 + diff --git a/queue-5.15/alpha-fix-tif_notify_signal-handling.patch b/queue-5.15/alpha-fix-tif_notify_signal-handling.patch new file mode 100644 index 00000000000..0fc7e246fad --- /dev/null +++ b/queue-5.15/alpha-fix-tif_notify_signal-handling.patch @@ -0,0 +1,35 @@ +From d0490f0595a98153558f0b1dca301d57c4886b71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Sep 2021 18:08:56 -0400 +Subject: alpha: fix TIF_NOTIFY_SIGNAL handling + +From: Al Viro + +[ Upstream commit e2c7554cc6d85f95e3c6635f270ec839ab9fe05e ] + +it needs to be added to _TIF_WORK_MASK, or we might not reach +do_work_pending() in the first place... + +Fixes: 5a9a8897c253a "alpha: add support for TIF_NOTIFY_SIGNAL" +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + arch/alpha/include/asm/thread_info.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h +index 2592356e3215..0ce1eee0924b 100644 +--- a/arch/alpha/include/asm/thread_info.h ++++ b/arch/alpha/include/asm/thread_info.h +@@ -77,7 +77,7 @@ register struct thread_info *__current_thread_info __asm__("$8"); + + /* Work to do on interrupt/exception return. */ + #define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ +- _TIF_NOTIFY_RESUME) ++ _TIF_NOTIFY_RESUME | _TIF_NOTIFY_SIGNAL) + + /* Work to do on any return to userspace. */ + #define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \ +-- +2.35.1 + diff --git a/queue-5.15/alsa-asihpi-fix-missing-pci_disable_device.patch b/queue-5.15/alsa-asihpi-fix-missing-pci_disable_device.patch new file mode 100644 index 00000000000..df9853cc6fa --- /dev/null +++ b/queue-5.15/alsa-asihpi-fix-missing-pci_disable_device.patch @@ -0,0 +1,37 @@ +From 8574dfb8b3d77d669d20090abf7b7c324b4b9ac2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 10:14:29 +0800 +Subject: ALSA: asihpi: fix missing pci_disable_device() + +From: Liu Shixin + +[ Upstream commit 9d86515c3d4c0564a0c31a2df87d735353a1971e ] + +pci_disable_device() need be called while module exiting, switch to use +pcim_enable(), pci_disable_device() will be called in pcim_release(). + +Fixes: 3285ea10e9b0 ("ALSA: asihpi - Interrelated HPI tidy up.") +Signed-off-by: Liu Shixin +Link: https://lore.kernel.org/r/20221126021429.3029562-1-liushixin2@huawei.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/asihpi/hpioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c +index bb31b7fe867d..477a5b4b50bc 100644 +--- a/sound/pci/asihpi/hpioctl.c ++++ b/sound/pci/asihpi/hpioctl.c +@@ -361,7 +361,7 @@ int asihpi_adapter_probe(struct pci_dev *pci_dev, + pci_dev->device, pci_dev->subsystem_vendor, + pci_dev->subsystem_device, pci_dev->devfn); + +- if (pci_enable_device(pci_dev) < 0) { ++ if (pcim_enable_device(pci_dev) < 0) { + dev_err(&pci_dev->dev, + "pci_enable_device failed, disabling device\n"); + return -EIO; +-- +2.35.1 + diff --git a/queue-5.15/alsa-mts64-fix-possible-null-ptr-defer-in-snd_mts64_.patch b/queue-5.15/alsa-mts64-fix-possible-null-ptr-defer-in-snd_mts64_.patch new file mode 100644 index 00000000000..0cdee5c83a9 --- /dev/null +++ b/queue-5.15/alsa-mts64-fix-possible-null-ptr-defer-in-snd_mts64_.patch @@ -0,0 +1,103 @@ +From dfa0d4e99ba7591edaff710037daf654f108287a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 14:10:04 +0800 +Subject: ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt + +From: Gaosheng Cui + +[ Upstream commit cf2ea3c86ad90d63d1c572b43e1ca9276b0357ad ] + +I got a null-ptr-defer error report when I do the following tests +on the qemu platform: + +make defconfig and CONFIG_PARPORT=m, CONFIG_PARPORT_PC=m, +CONFIG_SND_MTS64=m + +Then making test scripts: +cat>test_mod1.sh< + snd_mts64_interrupt+0x24/0xa0 [snd_mts64] + parport_irq_handler+0x37/0x50 [parport] + __handle_irq_event_percpu+0x39/0x190 + handle_irq_event_percpu+0xa/0x30 + handle_irq_event+0x2f/0x50 + handle_edge_irq+0x99/0x1b0 + __common_interrupt+0x5d/0x100 + common_interrupt+0xa0/0xc0 + + + asm_common_interrupt+0x22/0x40 + RIP: 0010:_raw_write_unlock_irqrestore+0x11/0x30 + parport_claim+0xbd/0x230 [parport] + snd_mts64_probe+0x14a/0x465 [snd_mts64] + platform_probe+0x3f/0xa0 + really_probe+0x129/0x2c0 + __driver_probe_device+0x6d/0xc0 + driver_probe_device+0x1a/0xa0 + __device_attach_driver+0x7a/0xb0 + bus_for_each_drv+0x62/0xb0 + __device_attach+0xe4/0x180 + bus_probe_device+0x82/0xa0 + device_add+0x550/0x920 + platform_device_add+0x106/0x220 + snd_mts64_attach+0x2e/0x80 [snd_mts64] + port_check+0x14/0x20 [parport] + bus_for_each_dev+0x6e/0xc0 + __parport_register_driver+0x7c/0xb0 [parport] + snd_mts64_module_init+0x31/0x1000 [snd_mts64] + do_one_initcall+0x3c/0x1f0 + do_init_module+0x46/0x1c6 + load_module+0x1d8d/0x1e10 + __do_sys_finit_module+0xa2/0xf0 + do_syscall_64+0x37/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + + Kernel panic - not syncing: Fatal exception in interrupt + Rebooting in 1 seconds.. + +The mts wa not initialized during interrupt, we add check for +mts to fix this bug. + +Fixes: 68ab801e32bb ("[ALSA] Add snd-mts64 driver for ESI Miditerminal 4140") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221206061004.1222966-1-cuigaosheng1@huawei.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/drivers/mts64.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c +index d3bc9e8c407d..f0d34cf70c3e 100644 +--- a/sound/drivers/mts64.c ++++ b/sound/drivers/mts64.c +@@ -815,6 +815,9 @@ static void snd_mts64_interrupt(void *private) + u8 status, data; + struct snd_rawmidi_substream *substream; + ++ if (!mts) ++ return; ++ + spin_lock(&mts->lock); + ret = mts64_read(mts->pardev->port); + data = ret & 0x00ff; +-- +2.35.1 + diff --git a/queue-5.15/alsa-pcm-fix-undefined-behavior-in-bit-shift-for-snd.patch b/queue-5.15/alsa-pcm-fix-undefined-behavior-in-bit-shift-for-snd.patch new file mode 100644 index 00000000000..995128e492d --- /dev/null +++ b/queue-5.15/alsa-pcm-fix-undefined-behavior-in-bit-shift-for-snd.patch @@ -0,0 +1,92 @@ +From 99427072b8c81a34cb19f19065bcd25a5e49bcba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 19:00:44 +0800 +Subject: ALSA: pcm: fix undefined behavior in bit shift for + SNDRV_PCM_RATE_KNOT + +From: Baisong Zhong + +[ Upstream commit b5172e62458f8e6ff359e5f096044a488db90ac5 ] + +Shifting signed 32-bit value by 31 bits is undefined, so changing +significant bit to unsigned. The UBSAN warning calltrace like below: + +UBSAN: shift-out-of-bounds in sound/core/pcm_native.c:2676:21 +left shift of 1 by 31 places cannot be represented in type 'int' +... +Call Trace: + + dump_stack_lvl+0x8d/0xcf + ubsan_epilogue+0xa/0x44 + __ubsan_handle_shift_out_of_bounds+0x1e7/0x208 + snd_pcm_open_substream+0x9f0/0xa90 + snd_pcm_oss_open.part.26+0x313/0x670 + snd_pcm_oss_open+0x30/0x40 + soundcore_open+0x18b/0x2e0 + chrdev_open+0xe2/0x270 + do_dentry_open+0x2f7/0x620 + path_openat+0xd66/0xe70 + do_filp_open+0xe3/0x170 + do_sys_openat2+0x357/0x4a0 + do_sys_open+0x87/0xd0 + do_syscall_64+0x34/0x80 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Baisong Zhong +Link: https://lore.kernel.org/r/20221121110044.3115686-1-zhongbaisong@huawei.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + include/sound/pcm.h | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/include/sound/pcm.h b/include/sound/pcm.h +index e08bf475d02d..181df0452ae2 100644 +--- a/include/sound/pcm.h ++++ b/include/sound/pcm.h +@@ -106,24 +106,24 @@ struct snd_pcm_ops { + #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) + + /* If you change this don't forget to change rates[] table in pcm_native.c */ +-#define SNDRV_PCM_RATE_5512 (1<<0) /* 5512Hz */ +-#define SNDRV_PCM_RATE_8000 (1<<1) /* 8000Hz */ +-#define SNDRV_PCM_RATE_11025 (1<<2) /* 11025Hz */ +-#define SNDRV_PCM_RATE_16000 (1<<3) /* 16000Hz */ +-#define SNDRV_PCM_RATE_22050 (1<<4) /* 22050Hz */ +-#define SNDRV_PCM_RATE_32000 (1<<5) /* 32000Hz */ +-#define SNDRV_PCM_RATE_44100 (1<<6) /* 44100Hz */ +-#define SNDRV_PCM_RATE_48000 (1<<7) /* 48000Hz */ +-#define SNDRV_PCM_RATE_64000 (1<<8) /* 64000Hz */ +-#define SNDRV_PCM_RATE_88200 (1<<9) /* 88200Hz */ +-#define SNDRV_PCM_RATE_96000 (1<<10) /* 96000Hz */ +-#define SNDRV_PCM_RATE_176400 (1<<11) /* 176400Hz */ +-#define SNDRV_PCM_RATE_192000 (1<<12) /* 192000Hz */ +-#define SNDRV_PCM_RATE_352800 (1<<13) /* 352800Hz */ +-#define SNDRV_PCM_RATE_384000 (1<<14) /* 384000Hz */ +- +-#define SNDRV_PCM_RATE_CONTINUOUS (1<<30) /* continuous range */ +-#define SNDRV_PCM_RATE_KNOT (1<<31) /* supports more non-continuos rates */ ++#define SNDRV_PCM_RATE_5512 (1U<<0) /* 5512Hz */ ++#define SNDRV_PCM_RATE_8000 (1U<<1) /* 8000Hz */ ++#define SNDRV_PCM_RATE_11025 (1U<<2) /* 11025Hz */ ++#define SNDRV_PCM_RATE_16000 (1U<<3) /* 16000Hz */ ++#define SNDRV_PCM_RATE_22050 (1U<<4) /* 22050Hz */ ++#define SNDRV_PCM_RATE_32000 (1U<<5) /* 32000Hz */ ++#define SNDRV_PCM_RATE_44100 (1U<<6) /* 44100Hz */ ++#define SNDRV_PCM_RATE_48000 (1U<<7) /* 48000Hz */ ++#define SNDRV_PCM_RATE_64000 (1U<<8) /* 64000Hz */ ++#define SNDRV_PCM_RATE_88200 (1U<<9) /* 88200Hz */ ++#define SNDRV_PCM_RATE_96000 (1U<<10) /* 96000Hz */ ++#define SNDRV_PCM_RATE_176400 (1U<<11) /* 176400Hz */ ++#define SNDRV_PCM_RATE_192000 (1U<<12) /* 192000Hz */ ++#define SNDRV_PCM_RATE_352800 (1U<<13) /* 352800Hz */ ++#define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */ ++ ++#define SNDRV_PCM_RATE_CONTINUOUS (1U<<30) /* continuous range */ ++#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuos rates */ + + #define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ + SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ +-- +2.35.1 + diff --git a/queue-5.15/alsa-pcm-set-missing-stop_operating-flag-at-undoing-.patch b/queue-5.15/alsa-pcm-set-missing-stop_operating-flag-at-undoing-.patch new file mode 100644 index 00000000000..bc40f9b1f5e --- /dev/null +++ b/queue-5.15/alsa-pcm-set-missing-stop_operating-flag-at-undoing-.patch @@ -0,0 +1,46 @@ +From a3b2e68035cb9e48e2e481b0abe2190a9bf9276f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 14:21:22 +0100 +Subject: ALSA: pcm: Set missing stop_operating flag at undoing trigger start + +From: Takashi Iwai + +[ Upstream commit 5c8cc93b06d1ff860327a273abf3ac006290d242 ] + +When a PCM trigger-start fails at snd_pcm_do_start(), PCM core tries +to undo the action at snd_pcm_undo_start() by issuing the trigger STOP +manually. At that point, we forgot to set the stop_operating flag, +hence the sync-stop won't be issued at the next prepare or other +calls. + +This patch adds the missing stop_operating flag at +snd_pcm_undo_start(). + +Fixes: 1e850beea278 ("ALSA: pcm: Add the support for sync-stop operation") +Link: https://lore.kernel.org/r/b4e71631-4a94-613-27b2-fb595792630@carlh.net +Link: https://lore.kernel.org/r/20221205132124.11585-2-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/pcm_native.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c +index f38c2e5e9a29..44e06ef4ff0b 100644 +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -1419,8 +1419,10 @@ static int snd_pcm_do_start(struct snd_pcm_substream *substream, + static void snd_pcm_undo_start(struct snd_pcm_substream *substream, + snd_pcm_state_t state) + { +- if (substream->runtime->trigger_master == substream) ++ if (substream->runtime->trigger_master == substream) { + substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); ++ substream->runtime->stop_operating = true; ++ } + } + + static void snd_pcm_post_start(struct snd_pcm_substream *substream, +-- +2.35.1 + diff --git a/queue-5.15/alsa-seq-fix-undefined-behavior-in-bit-shift-for-snd.patch b/queue-5.15/alsa-seq-fix-undefined-behavior-in-bit-shift-for-snd.patch new file mode 100644 index 00000000000..0e8a5d315a0 --- /dev/null +++ b/queue-5.15/alsa-seq-fix-undefined-behavior-in-bit-shift-for-snd.patch @@ -0,0 +1,66 @@ +From 011b2682574749df13c537eaaea32cc59b3574ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 19:16:30 +0800 +Subject: ALSA: seq: fix undefined behavior in bit shift for + SNDRV_SEQ_FILTER_USE_EVENT + +From: Baisong Zhong + +[ Upstream commit cf59e1e4c79bf741905484cdb13c130b53576a16 ] + +Shifting signed 32-bit value by 31 bits is undefined, so changing +significant bit to unsigned. The UBSAN warning calltrace like below: + +UBSAN: shift-out-of-bounds in sound/core/seq/seq_clientmgr.c:509:22 +left shift of 1 by 31 places cannot be represented in type 'int' +... +Call Trace: + + dump_stack_lvl+0x8d/0xcf + ubsan_epilogue+0xa/0x44 + __ubsan_handle_shift_out_of_bounds+0x1e7/0x208 + snd_seq_deliver_single_event.constprop.21+0x191/0x2f0 + snd_seq_deliver_event+0x1a2/0x350 + snd_seq_kernel_client_dispatch+0x8b/0xb0 + snd_seq_client_notify_subscription+0x72/0xa0 + snd_seq_ioctl_subscribe_port+0x128/0x160 + snd_seq_kernel_client_ctl+0xce/0xf0 + snd_seq_oss_create_client+0x109/0x15b + alsa_seq_oss_init+0x11c/0x1aa + do_one_initcall+0x80/0x440 + kernel_init_freeable+0x370/0x3c3 + kernel_init+0x1b/0x190 + ret_from_fork+0x1f/0x30 + + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Baisong Zhong +Link: https://lore.kernel.org/r/20221121111630.3119259-1-zhongbaisong@huawei.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + include/uapi/sound/asequencer.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/include/uapi/sound/asequencer.h b/include/uapi/sound/asequencer.h +index a75e14edc957..dbd60f48b4b0 100644 +--- a/include/uapi/sound/asequencer.h ++++ b/include/uapi/sound/asequencer.h +@@ -344,10 +344,10 @@ typedef int __bitwise snd_seq_client_type_t; + #define KERNEL_CLIENT ((__force snd_seq_client_type_t) 2) + + /* event filter flags */ +-#define SNDRV_SEQ_FILTER_BROADCAST (1<<0) /* accept broadcast messages */ +-#define SNDRV_SEQ_FILTER_MULTICAST (1<<1) /* accept multicast messages */ +-#define SNDRV_SEQ_FILTER_BOUNCE (1<<2) /* accept bounce event in error */ +-#define SNDRV_SEQ_FILTER_USE_EVENT (1<<31) /* use event filter */ ++#define SNDRV_SEQ_FILTER_BROADCAST (1U<<0) /* accept broadcast messages */ ++#define SNDRV_SEQ_FILTER_MULTICAST (1U<<1) /* accept multicast messages */ ++#define SNDRV_SEQ_FILTER_BOUNCE (1U<<2) /* accept bounce event in error */ ++#define SNDRV_SEQ_FILTER_USE_EVENT (1U<<31) /* use event filter */ + + struct snd_seq_client_info { + int client; /* client number to inquire */ +-- +2.35.1 + diff --git a/queue-5.15/amdgpu-pm-prevent-array-underflow-in-vega20_odn_edit.patch b/queue-5.15/amdgpu-pm-prevent-array-underflow-in-vega20_odn_edit.patch new file mode 100644 index 00000000000..9c518383012 --- /dev/null +++ b/queue-5.15/amdgpu-pm-prevent-array-underflow-in-vega20_odn_edit.patch @@ -0,0 +1,38 @@ +From 9b50202ce6da70c4bdb248dd98ff5b605807ae93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 15:56:57 +0300 +Subject: amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table() + +From: Dan Carpenter + +[ Upstream commit d27252b5706e51188aed7647126e44dcf9e940c1 ] + +In the PP_OD_EDIT_VDDC_CURVE case the "input_index" variable is capped at +2 but not checked for negative values so it results in an out of bounds +read. This value comes from the user via sysfs. + +Fixes: d5bf26539494 ("drm/amd/powerplay: added vega20 overdrive support V3") +Signed-off-by: Dan Carpenter +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +index 85d55ab4e369..299b5c838bf7 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +@@ -2961,7 +2961,8 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + data->od8_settings.od8_settings_array; + OverDriveTable_t *od_table = + &(data->smc_state_table.overdrive_table); +- int32_t input_index, input_clk, input_vol, i; ++ int32_t input_clk, input_vol, i; ++ uint32_t input_index; + int od8_id; + int ret; + +-- +2.35.1 + diff --git a/queue-5.15/apparmor-fix-a-memleak-in-multi_transaction_new.patch b/queue-5.15/apparmor-fix-a-memleak-in-multi_transaction_new.patch new file mode 100644 index 00000000000..752ebda6fcc --- /dev/null +++ b/queue-5.15/apparmor-fix-a-memleak-in-multi_transaction_new.patch @@ -0,0 +1,42 @@ +From ecad61c14f59849b3ef3de349d28ad7afd572d21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 09:15:03 +0800 +Subject: apparmor: fix a memleak in multi_transaction_new() + +From: Gaosheng Cui + +[ Upstream commit c73275cf6834787ca090317f1d20dbfa3b7f05aa ] + +In multi_transaction_new(), the variable t is not freed or passed out +on the failure of copy_from_user(t->data, buf, size), which could lead +to a memleak. + +Fix this bug by adding a put_multi_transaction(t) in the error path. + +Fixes: 1dea3b41e84c5 ("apparmor: speed up transactional queries") +Signed-off-by: Gaosheng Cui +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/apparmorfs.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c +index a891705b1d57..8c7719108d7f 100644 +--- a/security/apparmor/apparmorfs.c ++++ b/security/apparmor/apparmorfs.c +@@ -867,8 +867,10 @@ static struct multi_transaction *multi_transaction_new(struct file *file, + if (!t) + return ERR_PTR(-ENOMEM); + kref_init(&t->count); +- if (copy_from_user(t->data, buf, size)) ++ if (copy_from_user(t->data, buf, size)) { ++ put_multi_transaction(t); + return ERR_PTR(-EFAULT); ++ } + + return t; + } +-- +2.35.1 + diff --git a/queue-5.15/apparmor-fix-abi-check-to-include-v8-abi.patch b/queue-5.15/apparmor-fix-abi-check-to-include-v8-abi.patch new file mode 100644 index 00000000000..76d010ecf8f --- /dev/null +++ b/queue-5.15/apparmor-fix-abi-check-to-include-v8-abi.patch @@ -0,0 +1,42 @@ +From 80eacb75a180b2d114f85a005f5dd9640fdfd3d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 May 2022 18:57:12 -0700 +Subject: apparmor: Fix abi check to include v8 abi + +From: John Johansen + +[ Upstream commit 1b5a6198f5a9d0aa5497da0dc4bcd4fc166ee516 ] + +The v8 abi is supported by the kernel but the userspace supported +version check does not allow for it. This was missed when v8 was added +due to a bug in the userspace compiler which was setting an older abi +version for v8 encoding (which is forward compatible except on the +network encoding). However it is possible to detect the network +encoding by checking the policydb network support which the code +does. The end result was that missing the abi flag worked until +userspace was fixed and began correctly checking for the v8 abi +version. + +Fixes: 56974a6fcfef ("apparmor: add base infastructure for socket mediation") +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/policy_unpack.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c +index 03c9609ca407..d5b3a062d1d1 100644 +--- a/security/apparmor/policy_unpack.c ++++ b/security/apparmor/policy_unpack.c +@@ -964,7 +964,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns) + * if not specified use previous version + * Mask off everything that is not kernel abi version + */ +- if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) { ++ if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v8)) { + audit_iface(NULL, NULL, NULL, "unsupported interface version", + e, error); + return error; +-- +2.35.1 + diff --git a/queue-5.15/apparmor-fix-lockdep-warning-when-removing-a-namespa.patch b/queue-5.15/apparmor-fix-lockdep-warning-when-removing-a-namespa.patch new file mode 100644 index 00000000000..b7648847c25 --- /dev/null +++ b/queue-5.15/apparmor-fix-lockdep-warning-when-removing-a-namespa.patch @@ -0,0 +1,56 @@ +From 2ad0738de88d325395e3dd4bafff88ad2a921ff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 03:39:55 -0700 +Subject: apparmor: fix lockdep warning when removing a namespace + +From: John Johansen + +[ Upstream commit 9c4557efc558a68e4cd973490fd936d6e3414db8 ] + +Fix the following lockdep warning + +[ 1119.158984] ============================================ +[ 1119.158988] WARNING: possible recursive locking detected +[ 1119.158996] 6.0.0-rc1+ #257 Tainted: G E N +[ 1119.158999] -------------------------------------------- +[ 1119.159001] bash/80100 is trying to acquire lock: +[ 1119.159007] ffff88803e79b4a0 (&ns->lock/1){+.+.}-{4:4}, at: destroy_ns.part.0+0x43/0x140 +[ 1119.159028] + but task is already holding lock: +[ 1119.159030] ffff8881009764a0 (&ns->lock/1){+.+.}-{4:4}, at: aa_remove_profiles+0x3f0/0x640 +[ 1119.159040] + other info that might help us debug this: +[ 1119.159042] Possible unsafe locking scenario: + +[ 1119.159043] CPU0 +[ 1119.159045] ---- +[ 1119.159047] lock(&ns->lock/1); +[ 1119.159051] lock(&ns->lock/1); +[ 1119.159055] + *** DEADLOCK *** + +Which is caused by an incorrect lockdep nesting notation + +Fixes: feb3c766a3ab ("apparmor: fix possible recursive lock warning in __aa_create_ns") +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/policy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c +index 4c010c9a6af1..fcf22577f606 100644 +--- a/security/apparmor/policy.c ++++ b/security/apparmor/policy.c +@@ -1125,7 +1125,7 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, + + if (!name) { + /* remove namespace - can only happen if fqname[0] == ':' */ +- mutex_lock_nested(&ns->parent->lock, ns->level); ++ mutex_lock_nested(&ns->parent->lock, ns->parent->level); + __aa_bump_ns_revision(ns); + __aa_remove_ns(ns); + mutex_unlock(&ns->parent->lock); +-- +2.35.1 + diff --git a/queue-5.15/apparmor-fix-memleak-in-alloc_ns.patch b/queue-5.15/apparmor-fix-memleak-in-alloc_ns.patch new file mode 100644 index 00000000000..3a52fc748a8 --- /dev/null +++ b/queue-5.15/apparmor-fix-memleak-in-alloc_ns.patch @@ -0,0 +1,38 @@ +From aa0f553b85cc6848db7ea8927e70465cb34fab2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 20:33:20 +0800 +Subject: apparmor: Fix memleak in alloc_ns() + +From: Xiu Jianfeng + +[ Upstream commit e9e6fa49dbab6d84c676666f3fe7d360497fd65b ] + +After changes in commit a1bd627b46d1 ("apparmor: share profile name on +replacement"), the hname member of struct aa_policy is not valid slab +object, but a subset of that, it can not be freed by kfree_sensitive(), +use aa_policy_destroy() to fix it. + +Fixes: a1bd627b46d1 ("apparmor: share profile name on replacement") +Signed-off-by: Xiu Jianfeng +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/policy_ns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c +index 70921d95fb40..53d24cf63893 100644 +--- a/security/apparmor/policy_ns.c ++++ b/security/apparmor/policy_ns.c +@@ -121,7 +121,7 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name) + return ns; + + fail_unconfined: +- kfree_sensitive(ns->base.hname); ++ aa_policy_destroy(&ns->base); + fail_ns: + kfree_sensitive(ns); + return NULL; +-- +2.35.1 + diff --git a/queue-5.15/apparmor-use-pointer-to-struct-aa_label-for-lbs_cred.patch b/queue-5.15/apparmor-use-pointer-to-struct-aa_label-for-lbs_cred.patch new file mode 100644 index 00000000000..48798e7bae4 --- /dev/null +++ b/queue-5.15/apparmor-use-pointer-to-struct-aa_label-for-lbs_cred.patch @@ -0,0 +1,41 @@ +From 50a6619da3380d9c6de02b9709b54f2a16841ddc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 08:46:04 +0800 +Subject: apparmor: Use pointer to struct aa_label for lbs_cred + +From: Xiu Jianfeng + +[ Upstream commit 37923d4321b1e38170086da2c117f78f2b0f49c6 ] + +According to the implementations of cred_label() and set_cred_label(), +we should use pointer to struct aa_label for lbs_cred instead of struct +aa_task_ctx, this patch fixes it. + +Fixes: bbd3662a8348 ("Infrastructure management of the cred security blob") +Signed-off-by: Xiu Jianfeng +Signed-off-by: John Johansen +Signed-off-by: Sasha Levin +--- + security/apparmor/lsm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c +index f72406fe1bf2..10274eb90fa3 100644 +--- a/security/apparmor/lsm.c ++++ b/security/apparmor/lsm.c +@@ -1170,10 +1170,10 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb + #endif + + /* +- * The cred blob is a pointer to, not an instance of, an aa_task_ctx. ++ * The cred blob is a pointer to, not an instance of, an aa_label. + */ + struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { +- .lbs_cred = sizeof(struct aa_task_ctx *), ++ .lbs_cred = sizeof(struct aa_label *), + .lbs_file = sizeof(struct aa_file_ctx), + .lbs_task = sizeof(struct aa_task_ctx), + }; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-370-fix-assigned-addresses-for-every-.patch b/queue-5.15/arm-dts-armada-370-fix-assigned-addresses-for-every-.patch new file mode 100644 index 00000000000..64d3f153686 --- /dev/null +++ b/queue-5.15/arm-dts-armada-370-fix-assigned-addresses-for-every-.patch @@ -0,0 +1,40 @@ +From 129e057c6734f1f3edf0aeaec40bfd4a1c09f611 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:49 +0200 +Subject: ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit d9208b0fa2e803d16b28d91bf1d46b7ee9ea13c6 ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: a09a0b7c6ff1 ("arm: mvebu: add PCIe Device Tree informations for Armada 370") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-370.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi +index 46e6d3ed8f35..c042c416a94a 100644 +--- a/arch/arm/boot/dts/armada-370.dtsi ++++ b/arch/arm/boot/dts/armada-370.dtsi +@@ -74,7 +74,7 @@ pcie0: pcie@1,0 { + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-375-fix-assigned-addresses-for-every-.patch b/queue-5.15/arm-dts-armada-375-fix-assigned-addresses-for-every-.patch new file mode 100644 index 00000000000..6f8d1330a76 --- /dev/null +++ b/queue-5.15/arm-dts-armada-375-fix-assigned-addresses-for-every-.patch @@ -0,0 +1,40 @@ +From 0feaeab4680a2f44729fb7eb57036a3a213a71d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:51 +0200 +Subject: ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 823956d2436f70ced74c0fe8ab99facd8abfc060 ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: 4de59085091f ("ARM: mvebu: add Device Tree description of the Armada 375 SoC") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-375.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi +index 7f2f24a29e6c..352a2f7ba311 100644 +--- a/arch/arm/boot/dts/armada-375.dtsi ++++ b/arch/arm/boot/dts/armada-375.dtsi +@@ -582,7 +582,7 @@ pcie0: pcie@1,0 { + + pcie1: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-38x-fix-assigned-addresses-for-every-.patch b/queue-5.15/arm-dts-armada-38x-fix-assigned-addresses-for-every-.patch new file mode 100644 index 00000000000..c144861d1e5 --- /dev/null +++ b/queue-5.15/arm-dts-armada-38x-fix-assigned-addresses-for-every-.patch @@ -0,0 +1,81 @@ +From 217ef6237e248c9d885eb0abca51292a7a5afcb9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:52 +0200 +Subject: ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 44f47b7a8fa4678ce4c38ea74837e4996b9df6d6 ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: 0d3d96ab0059 ("ARM: mvebu: add Device Tree description of the Armada 380/385 SoCs") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-380.dtsi | 4 ++-- + arch/arm/boot/dts/armada-385.dtsi | 6 +++--- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi +index cff1269f3fbf..7146cc8f082a 100644 +--- a/arch/arm/boot/dts/armada-380.dtsi ++++ b/arch/arm/boot/dts/armada-380.dtsi +@@ -79,7 +79,7 @@ pcie@1,0 { + /* x1 port */ + pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -98,7 +98,7 @@ pcie@2,0 { + /* x1 port */ + pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi +index f0022d10c715..f081f7cb66e5 100644 +--- a/arch/arm/boot/dts/armada-385.dtsi ++++ b/arch/arm/boot/dts/armada-385.dtsi +@@ -84,7 +84,7 @@ pcie1: pcie@1,0 { + /* x1 port */ + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -103,7 +103,7 @@ pcie2: pcie@2,0 { + /* x1 port */ + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -125,7 +125,7 @@ pcie3: pcie@3,0 { + */ + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-38x-fix-compatible-string-for-gpios.patch b/queue-5.15/arm-dts-armada-38x-fix-compatible-string-for-gpios.patch new file mode 100644 index 00000000000..20dfe385654 --- /dev/null +++ b/queue-5.15/arm-dts-armada-38x-fix-compatible-string-for-gpios.patch @@ -0,0 +1,56 @@ +From 7b259ddae6ac0f39b4ecd9d84845eeec63ad3155 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 20:33:27 +0200 +Subject: ARM: dts: armada-38x: Fix compatible string for gpios +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit c4de4667f15d04ef5920bacf41e514ec7d1ef03d ] + +Armada 38x supports per CPU interrupts for gpios, like Armada XP. Pre-XP +variants like Armada 370 do not support per CPU interrupts for gpios. + +So change compatible string for Armada 38x from "marvell,armada-370-gpio" +which indicates pre-XP variant to "marvell,armadaxp-gpio" which indicates +XP variant or new. + +Driver gpio-mvebu.c which handles both pre-XP and XP variants already +provides support for per CPU interrupts on XP and newer variants. + +Signed-off-by: Pali Rohár +Fixes: 7cb2acb3fbae ("ARM: dts: mvebu: Add PWM properties for armada-38x") +Acked-by: Uwe Kleine-König +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-38x.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi +index df3c8d1d8f64..9343de6947b3 100644 +--- a/arch/arm/boot/dts/armada-38x.dtsi ++++ b/arch/arm/boot/dts/armada-38x.dtsi +@@ -292,7 +292,7 @@ sata3_pins: sata-pins-3 { + }; + + gpio0: gpio@18100 { +- compatible = "marvell,armada-370-gpio", ++ compatible = "marvell,armadaxp-gpio", + "marvell,orion-gpio"; + reg = <0x18100 0x40>, <0x181c0 0x08>; + reg-names = "gpio", "pwm"; +@@ -310,7 +310,7 @@ gpio0: gpio@18100 { + }; + + gpio1: gpio@18140 { +- compatible = "marvell,armada-370-gpio", ++ compatible = "marvell,armadaxp-gpio", + "marvell,orion-gpio"; + reg = <0x18140 0x40>, <0x181c8 0x08>; + reg-names = "gpio", "pwm"; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-39x-fix-assigned-addresses-for-every-.patch b/queue-5.15/arm-dts-armada-39x-fix-assigned-addresses-for-every-.patch new file mode 100644 index 00000000000..f0bab94f7b2 --- /dev/null +++ b/queue-5.15/arm-dts-armada-39x-fix-assigned-addresses-for-every-.patch @@ -0,0 +1,58 @@ +From 75f67e297b0d518dd86580522299d56537735c04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:53 +0200 +Subject: ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 69236d2391b4d7324b11c3252921571577892e7b ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: 538da83ddbea ("ARM: mvebu: add Device Tree files for Armada 39x SoC and board") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-39x.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi +index e0b7c2099831..9525e7b7f436 100644 +--- a/arch/arm/boot/dts/armada-39x.dtsi ++++ b/arch/arm/boot/dts/armada-39x.dtsi +@@ -453,7 +453,7 @@ pcie@1,0 { + /* x1 port */ + pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -472,7 +472,7 @@ pcie@2,0 { + /* x1 port */ + pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -494,7 +494,7 @@ pcie@3,0 { + */ + pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-39x-fix-compatible-string-for-gpios.patch b/queue-5.15/arm-dts-armada-39x-fix-compatible-string-for-gpios.patch new file mode 100644 index 00000000000..c47592b7f5c --- /dev/null +++ b/queue-5.15/arm-dts-armada-39x-fix-compatible-string-for-gpios.patch @@ -0,0 +1,52 @@ +From 59d61df704eb782b82d6d7fcdd45951a8e0f7412 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 20:33:28 +0200 +Subject: ARM: dts: armada-39x: Fix compatible string for gpios +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit d10886a4e6f85ee18d47a1066a52168461370ded ] + +Armada 39x supports per CPU interrupts for gpios, like Armada XP. + +So add compatible string "marvell,armadaxp-gpio" for Armada 39x GPIO nodes. + +Driver gpio-mvebu.c which handles both pre-XP and XP variants already +provides support for per CPU interrupts on XP and newer variants. + +Signed-off-by: Pali Rohár +Fixes: d81a914fc630 ("ARM: dts: mvebu: armada-39x: add missing nodes describing GPIO's") +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-39x.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi +index 9525e7b7f436..9aad10fd3823 100644 +--- a/arch/arm/boot/dts/armada-39x.dtsi ++++ b/arch/arm/boot/dts/armada-39x.dtsi +@@ -213,7 +213,7 @@ nand_pins: nand-pins { + }; + + gpio0: gpio@18100 { +- compatible = "marvell,orion-gpio"; ++ compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio"; + reg = <0x18100 0x40>; + ngpios = <32>; + gpio-controller; +@@ -227,7 +227,7 @@ gpio0: gpio@18100 { + }; + + gpio1: gpio@18140 { +- compatible = "marvell,orion-gpio"; ++ compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio"; + reg = <0x18140 0x40>; + ngpios = <28>; + gpio-controller; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-armada-xp-fix-assigned-addresses-for-every-p.patch b/queue-5.15/arm-dts-armada-xp-fix-assigned-addresses-for-every-p.patch new file mode 100644 index 00000000000..73009f91fff --- /dev/null +++ b/queue-5.15/arm-dts-armada-xp-fix-assigned-addresses-for-every-p.patch @@ -0,0 +1,146 @@ +From 5c0fcdd2f46fa4388fc0a31f07b1cbf846c11818 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:50 +0200 +Subject: ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit eab276787f456cbea89fabea110fe0728673d308 ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: 9d8f44f02d4a ("arm: mvebu: add PCIe Device Tree informations for Armada XP") +Fixes: 12b69a599745 ("ARM: mvebu: second PCIe unit of Armada XP mv78230 is only x1 capable") +Fixes: 2163e61c92d9 ("ARM: mvebu: fix second and third PCIe unit of Armada XP mv78260") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-xp-mv78230.dtsi | 8 ++++---- + arch/arm/boot/dts/armada-xp-mv78260.dtsi | 16 ++++++++-------- + 2 files changed, 12 insertions(+), 12 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi +index 8558bf6bb54c..d55fe162fc7f 100644 +--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi +@@ -97,7 +97,7 @@ pcie1: pcie@1,0 { + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -115,7 +115,7 @@ pcie2: pcie@2,0 { + + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -133,7 +133,7 @@ pcie3: pcie@3,0 { + + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -151,7 +151,7 @@ pcie4: pcie@4,0 { + + pcie5: pcie@5,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi +index 2d85fe8ac327..fdcc81819940 100644 +--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi ++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi +@@ -112,7 +112,7 @@ pcie1: pcie@1,0 { + + pcie2: pcie@2,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -130,7 +130,7 @@ pcie2: pcie@2,0 { + + pcie3: pcie@3,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>; ++ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>; + reg = <0x1800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -148,7 +148,7 @@ pcie3: pcie@3,0 { + + pcie4: pcie@4,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>; ++ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>; + reg = <0x2000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -166,7 +166,7 @@ pcie4: pcie@4,0 { + + pcie5: pcie@5,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; + reg = <0x2800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -184,7 +184,7 @@ pcie5: pcie@5,0 { + + pcie6: pcie@6,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x84000 0 0x2000>; ++ assigned-addresses = <0x82003000 0 0x84000 0 0x2000>; + reg = <0x3000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -202,7 +202,7 @@ pcie6: pcie@6,0 { + + pcie7: pcie@7,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x88000 0 0x2000>; ++ assigned-addresses = <0x82003800 0 0x88000 0 0x2000>; + reg = <0x3800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -220,7 +220,7 @@ pcie7: pcie@7,0 { + + pcie8: pcie@8,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>; ++ assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>; + reg = <0x4000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +@@ -238,7 +238,7 @@ pcie8: pcie@8,0 { + + pcie9: pcie@9,0 { + device_type = "pci"; +- assigned-addresses = <0x82000800 0 0x42000 0 0x2000>; ++ assigned-addresses = <0x82004800 0 0x42000 0 0x2000>; + reg = <0x4800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-dove-fix-assigned-addresses-for-every-pcie-r.patch b/queue-5.15/arm-dts-dove-fix-assigned-addresses-for-every-pcie-r.patch new file mode 100644 index 00000000000..b5762ae3de3 --- /dev/null +++ b/queue-5.15/arm-dts-dove-fix-assigned-addresses-for-every-pcie-r.patch @@ -0,0 +1,40 @@ +From 5a6b368c009701bdbb9fb6ed4aa90b954c6823be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 00:30:48 +0200 +Subject: ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit dcc7d8c72b64a479b8017e4332d99179deb8802d ] + +BDF of resource in DT assigned-addresses property of Marvell PCIe Root Port +(PCI-to-PCI bridge) should match BDF in address part in that DT node name +as specified resource belongs to Marvell PCIe Root Port itself. + +Fixes: 74ecaa403a74 ("ARM: dove: add PCIe controllers to SoC DT") +Signed-off-by: Pali Rohár +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/dove.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi +index 89e0bdaf3a85..726d353eda68 100644 +--- a/arch/arm/boot/dts/dove.dtsi ++++ b/arch/arm/boot/dts/dove.dtsi +@@ -129,7 +129,7 @@ pcie0: pcie@1 { + pcie1: pcie@2 { + device_type = "pci"; + status = "disabled"; +- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>; ++ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>; + reg = <0x1000 0 0 0 0>; + clocks = <&gate_clk 5>; + marvell,pcie-port = <1>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-nuvoton-remove-bogus-unit-addresses-from-fix.patch b/queue-5.15/arm-dts-nuvoton-remove-bogus-unit-addresses-from-fix.patch new file mode 100644 index 00000000000..ad371d94da9 --- /dev/null +++ b/queue-5.15/arm-dts-nuvoton-remove-bogus-unit-addresses-from-fix.patch @@ -0,0 +1,146 @@ +From 15616df79f4c6c3b63d5837b9299c5d1d583cb2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 23:15:52 +0100 +Subject: ARM: dts: nuvoton: Remove bogus unit addresses from fixed-partition + nodes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jonathan Neuschäfer + +[ Upstream commit ea3ce4cf076ba11bb591c8013c5315136cae52c8 ] + +The unit addresses do not correspond to the nodes' reg properties, +because they don't have any. + +Fixes: e42b650f828d ("ARM: dts: nuvoton: Add new device nodes to NPCM750 EVB") +Fixes: ee33e2fb3d70 ("ARM: dts: nuvoton: Add Quanta GBS BMC Device Tree") +Fixes: 59f5abe09f0a ("ARM: dts: nuvoton: Add Quanta GSJ BMC") +Fixes: 14579c76f5ca ("ARM: dts: nuvoton: Add Fii Kudo system") +Signed-off-by: Jonathan Neuschäfer +Reviewed-by: Joel Stanley +Link: https://lore.kernel.org/r/20221031221553.163273-1-j.neuschaefer@gmx.net +Signed-off-by: Joel Stanley +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/nuvoton-npcm730-gbs.dts | 2 +- + arch/arm/boot/dts/nuvoton-npcm730-gsj.dts | 2 +- + arch/arm/boot/dts/nuvoton-npcm730-kudo.dts | 6 +++--- + arch/arm/boot/dts/nuvoton-npcm750-evb.dts | 4 ++-- + arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts | 6 +++--- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts +index eb6eb21cb2a4..33c8d5b3d679 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts +@@ -366,7 +366,7 @@ spi-nor@0 { + spi-max-frequency = <20000000>; + spi-rx-bus-width = <2>; + label = "bmc"; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts +index d4ff49939a3d..bbe18618f5c5 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts +@@ -142,7 +142,7 @@ spi-nor@0 { + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts +index 82a104b2a65f..8e3425cb8e8b 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts +@@ -388,7 +388,7 @@ spi-nor@0 { + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; + label = "bmc"; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -422,7 +422,7 @@ spi-nor@1 { + reg = <1>; + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; +- partitions@88000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -447,7 +447,7 @@ spi-nor@0 { + reg = <0>; + spi-max-frequency = <5000000>; + spi-rx-bus-width = <2>; +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts +index 0334641f8829..cf274c926711 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts +@@ -74,7 +74,7 @@ spi-nor@0 { + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -135,7 +135,7 @@ spi-nor@0 { + spi-rx-bus-width = <2>; + reg = <0>; + spi-max-frequency = <5000000>; +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts +index 767e0ac0df7c..7fe7efee28ac 100644 +--- a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts ++++ b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts +@@ -107,7 +107,7 @@ spi-nor@0 { + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@80000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -146,7 +146,7 @@ spi-nor@1 { + reg = <1>; + npcm,fiu-rx-bus-width = <2>; + +- partitions@88000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +@@ -173,7 +173,7 @@ spi-nor@0 { + reg = <0>; + spi-rx-bus-width = <2>; + +- partitions@A0000000 { ++ partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-qcom-apq8064-fix-coresight-compatible.patch b/queue-5.15/arm-dts-qcom-apq8064-fix-coresight-compatible.patch new file mode 100644 index 00000000000..7dc5c5f91f1 --- /dev/null +++ b/queue-5.15/arm-dts-qcom-apq8064-fix-coresight-compatible.patch @@ -0,0 +1,39 @@ +From 29a176cc2c08c0966ec0b0b96f33f330b3f073e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 21:06:57 +0200 +Subject: ARM: dts: qcom: apq8064: fix coresight compatible + +From: Luca Weiss + +[ Upstream commit a42b1ee868361f1cb0492f1bdaefb43e0751e468 ] + +There's a typo missing the arm, prefix of arm,coresight-etb10. Fix it to +make devicetree validation happier. + +Signed-off-by: Luca Weiss +Fixes: 7a5c275fd821 ("ARM: dts: qcom: Add apq8064 CoreSight components") +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221013190657.48499-3-luca@z3ntu.xyz +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/qcom-apq8064.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi +index d1c1c6aab2b8..0e830476fefd 100644 +--- a/arch/arm/boot/dts/qcom-apq8064.dtsi ++++ b/arch/arm/boot/dts/qcom-apq8064.dtsi +@@ -1571,7 +1571,7 @@ wifi { + }; + + etb@1a01000 { +- compatible = "coresight-etb10", "arm,primecell"; ++ compatible = "arm,coresight-etb10", "arm,primecell"; + reg = <0x1a01000 0x1000>; + + clocks = <&rpmcc RPM_QDSS_CLK>; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-spear600-fix-clcd-interrupt.patch b/queue-5.15/arm-dts-spear600-fix-clcd-interrupt.patch new file mode 100644 index 00000000000..4e288f2b625 --- /dev/null +++ b/queue-5.15/arm-dts-spear600-fix-clcd-interrupt.patch @@ -0,0 +1,37 @@ +From 761943101de590f0a63b9b90dd1857296fbdef55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 18:10:06 +0100 +Subject: arm: dts: spear600: Fix clcd interrupt + +From: Kory Maincent + +[ Upstream commit 0336e2ce34e7a89832b6c214f924eb7bc58940be ] + +Interrupt 12 of the Interrupt controller belongs to the SMI controller, +the right one for the display controller is the interrupt 13. + +Fixes: 8113ba917dfa ("ARM: SPEAr: DT: Update device nodes") +Signed-off-by: Kory Maincent +Acked-by: Viresh Kumar +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/spear600.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi +index fd41243a0b2c..9d5a04a46b14 100644 +--- a/arch/arm/boot/dts/spear600.dtsi ++++ b/arch/arm/boot/dts/spear600.dtsi +@@ -47,7 +47,7 @@ clcd: clcd@fc200000 { + compatible = "arm,pl110", "arm,primecell"; + reg = <0xfc200000 0x1000>; + interrupt-parent = <&vic1>; +- interrupts = <12>; ++ interrupts = <13>; + status = "disabled"; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-stm32-drop-stm32mp15xc.dtsi-from-avenger96.patch b/queue-5.15/arm-dts-stm32-drop-stm32mp15xc.dtsi-from-avenger96.patch new file mode 100644 index 00000000000..2e0d78b7e96 --- /dev/null +++ b/queue-5.15/arm-dts-stm32-drop-stm32mp15xc.dtsi-from-avenger96.patch @@ -0,0 +1,39 @@ +From f387569a2c34a33cf3d2fc14eaafdb3432500ac6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Sep 2022 04:37:45 +0200 +Subject: ARM: dts: stm32: Drop stm32mp15xc.dtsi from Avenger96 + +From: Marek Vasut + +[ Upstream commit 3b835f1b8acef53c8882b25f40f48d7f5982c938 ] + +The Avenger96 is populated with STM32MP157A DHCOR SoM, drop the +stm32mp15xc.dtsi which should only be included in DTs of devices +which are populated with STM32MP15xC/F SoC as the stm32mp15xc.dtsi +enables CRYP block not present in the STM32MP15xA/D SoC . + +Fixes: 7e76f82acd9e1 ("ARM: dts: stm32: Split Avenger96 into DHCOR SoM and Avenger96 board") +Signed-off-by: Marek Vasut +Reviewed-by: Patrice Chotard +Reviewed-by: Manivannan Sadhasivam +Signed-off-by: Alexandre Torgue +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts +index 2e3c9fbb4eb3..275167f26fd9 100644 +--- a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts ++++ b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts +@@ -13,7 +13,6 @@ + /dts-v1/; + + #include "stm32mp157.dtsi" +-#include "stm32mp15xc.dtsi" + #include "stm32mp15xx-dhcor-som.dtsi" + #include "stm32mp15xx-dhcor-avenger96.dtsi" + +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-stm32-fix-av96-wlan-regulator-gpio-property.patch b/queue-5.15/arm-dts-stm32-fix-av96-wlan-regulator-gpio-property.patch new file mode 100644 index 00000000000..5c611711f1b --- /dev/null +++ b/queue-5.15/arm-dts-stm32-fix-av96-wlan-regulator-gpio-property.patch @@ -0,0 +1,38 @@ +From 1c584128afe25c60c43d519b3e2e200768b057ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 12:00:57 +0200 +Subject: ARM: dts: stm32: Fix AV96 WLAN regulator gpio property + +From: Marek Vasut + +[ Upstream commit d5d577e3d50713ad11d98dbdaa48bb494346c26d ] + +The WLAN regulator uses 'gpios' property instead of 'gpio' to specify +regulator enable GPIO. While the former is also currently handled by +the Linux kernel regulator-fixed driver, the later is the correct one +per DT bindings. Update the DT to use the later. + +Fixes: 7dd5cbba42c93 ("ARM: dts: stm32: Enable WiFi on AV96") +Signed-off-by: Marek Vasut +Signed-off-by: Alexandre Torgue +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +index 8eb51d84b698..d3375ad8c91f 100644 +--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi ++++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi +@@ -100,7 +100,7 @@ wlan_pwr: regulator-wlan { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + +- gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>; ++ gpio = <&gpioz 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-turris-omnia-add-ethernet-aliases.patch b/queue-5.15/arm-dts-turris-omnia-add-ethernet-aliases.patch new file mode 100644 index 00000000000..98f6b9be349 --- /dev/null +++ b/queue-5.15/arm-dts-turris-omnia-add-ethernet-aliases.patch @@ -0,0 +1,43 @@ +From f99c25954553a8b46dc7fc57822789ed0de3864d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 15:09:26 +0200 +Subject: ARM: dts: turris-omnia: Add ethernet aliases +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit f1f3e530c59a7e8c5f06172f4c28b945a6b4bfb8 ] + +This allows bootloader to correctly pass MAC addresses used by bootloader +to individual interfaces into kernel device tree. + +Signed-off-by: Pali Rohár +Fixes: 26ca8b52d6e1 ("ARM: dts: add support for Turris Omnia") +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-385-turris-omnia.dts | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts +index 01b0dfd55d70..86e8a4680273 100644 +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -23,6 +23,12 @@ chosen { + stdout-path = &uart0; + }; + ++ aliases { ++ ethernet0 = ð0; ++ ethernet1 = ð1; ++ ethernet2 = ð2; ++ }; ++ + memory { + device_type = "memory"; + reg = <0x00000000 0x40000000>; /* 1024 MB */ +-- +2.35.1 + diff --git a/queue-5.15/arm-dts-turris-omnia-add-switch-port-6-node.patch b/queue-5.15/arm-dts-turris-omnia-add-switch-port-6-node.patch new file mode 100644 index 00000000000..9c7cf9b9deb --- /dev/null +++ b/queue-5.15/arm-dts-turris-omnia-add-switch-port-6-node.patch @@ -0,0 +1,49 @@ +From e9a0c69a0210eec5290221bb45987b3703bf54bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 14:21:02 +0200 +Subject: ARM: dts: turris-omnia: Add switch port 6 node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit f87db2005f73876602211af0ee156817019b6bda ] + +Switch port 6 is connected to eth0, so add appropriate device tree node for it. + +Fixes: 26ca8b52d6e1 ("ARM: dts: add support for Turris Omnia") +Signed-off-by: Pali Rohár +Reviewed-by: Andrew Lunn +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-385-turris-omnia.dts | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts +index 86e8a4680273..e7649c795699 100644 +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -456,7 +456,17 @@ fixed-link { + }; + }; + +- /* port 6 is connected to eth0 */ ++ ports@6 { ++ reg = <6>; ++ label = "cpu"; ++ ethernet = <ð0>; ++ phy-mode = "rgmii-id"; ++ ++ fixed-link { ++ speed = <1000>; ++ full-duplex; ++ }; ++ }; + }; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm-mmp-fix-timer_read-delay.patch b/queue-5.15/arm-mmp-fix-timer_read-delay.patch new file mode 100644 index 00000000000..55464e94359 --- /dev/null +++ b/queue-5.15/arm-mmp-fix-timer_read-delay.patch @@ -0,0 +1,59 @@ +From 0935817290cf89213fe358dd198ee553c1b382c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 3 Dec 2022 16:51:17 -0800 +Subject: ARM: mmp: fix timer_read delay + +From: Doug Brown + +[ Upstream commit e348b4014c31041e13ff370669ba3348c4d385e3 ] + +timer_read() was using an empty 100-iteration loop to wait for the +TMR_CVWR register to capture the latest timer counter value. The delay +wasn't long enough. This resulted in CPU idle time being extremely +underreported on PXA168 with CONFIG_NO_HZ_IDLE=y. + +Switch to the approach used in the vendor kernel, which implements the +capture delay by reading TMR_CVWR a few times instead. + +Fixes: 49cbe78637eb ("[ARM] pxa: add base support for Marvell's PXA168 processor line") +Signed-off-by: Doug Brown +Link: https://lore.kernel.org/r/20221204005117.53452-3-doug@schmorgal.com +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/mach-mmp/time.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c +index 41b2e8abc9e6..708816caf859 100644 +--- a/arch/arm/mach-mmp/time.c ++++ b/arch/arm/mach-mmp/time.c +@@ -43,18 +43,21 @@ + static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE; + + /* +- * FIXME: the timer needs some delay to stablize the counter capture ++ * Read the timer through the CVWR register. Delay is required after requesting ++ * a read. The CR register cannot be directly read due to metastability issues ++ * documented in the PXA168 software manual. + */ + static inline uint32_t timer_read(void) + { +- int delay = 100; ++ uint32_t val; ++ int delay = 3; + + __raw_writel(1, mmp_timer_base + TMR_CVWR(1)); + + while (delay--) +- cpu_relax(); ++ val = __raw_readl(mmp_timer_base + TMR_CVWR(1)); + +- return __raw_readl(mmp_timer_base + TMR_CVWR(1)); ++ return val; + } + + static u64 notrace mmp_read_sched_clock(void) +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-armada-3720-turris-mox-add-missing-interru.patch b/queue-5.15/arm64-dts-armada-3720-turris-mox-add-missing-interru.patch new file mode 100644 index 00000000000..58255c2d71c --- /dev/null +++ b/queue-5.15/arm64-dts-armada-3720-turris-mox-add-missing-interru.patch @@ -0,0 +1,43 @@ +From a0c3b655bd0c24d3ad91d4b19ebcf8a161ab51c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 13:58:26 +0200 +Subject: arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 21aad8ba615e9c39cee6c5d0b76726f63791926c ] + +MCP7940MT-I/MNY RTC has connected interrupt line to GPIO2_5. + +Fixes: 7109d817db2e ("arm64: dts: marvell: add DTS for Turris Mox") +Signed-off-by: Pali Rohár +Reviewed-by: Andrew Lunn +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +index 1cee26479bfe..b276dd77df83 100644 +--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts ++++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +@@ -125,9 +125,12 @@ &i2c0 { + /delete-property/ mrvl,i2c-fast-mode; + status = "okay"; + ++ /* MCP7940MT-I/MNY RTC */ + rtc@6f { + compatible = "microchip,mcp7940x"; + reg = <0x6f>; ++ interrupt-parent = <&gpiosb>; ++ interrupts = <5 0>; /* GPIO2_5 */ + }; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mediatek-mt6797-fix-26m-oscillator-unit-na.patch b/queue-5.15/arm64-dts-mediatek-mt6797-fix-26m-oscillator-unit-na.patch new file mode 100644 index 00000000000..cdcac35a72a --- /dev/null +++ b/queue-5.15/arm64-dts-mediatek-mt6797-fix-26m-oscillator-unit-na.patch @@ -0,0 +1,37 @@ +From 7f47d60c013fdfe2487d10dec5bc192fbfb78f8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:12 +0200 +Subject: arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name + +From: AngeloGioacchino Del Regno + +[ Upstream commit 5f535cc583759c9c60d4cc9b8d221762e2d75387 ] + +Update its unit name to oscillator-26m and remove the unneeded unit +address to fix a unit_address_vs_reg warning. + +Fixes: 464c510f60c6 ("arm64: dts: mediatek: add mt6797 support") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-9-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt6797.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi +index 15616231022a..c3677d77e0a4 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6797.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi +@@ -95,7 +95,7 @@ cpu9: cpu@201 { + }; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mediatek-pumpkin-common-fix-devicetree-war.patch b/queue-5.15/arm64-dts-mediatek-pumpkin-common-fix-devicetree-war.patch new file mode 100644 index 00000000000..130d1ca462d --- /dev/null +++ b/queue-5.15/arm64-dts-mediatek-pumpkin-common-fix-devicetree-war.patch @@ -0,0 +1,55 @@ +From bc786567612af53f94a48076a3728a1da4541950 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:11 +0200 +Subject: arm64: dts: mediatek: pumpkin-common: Fix devicetree warnings + +From: AngeloGioacchino Del Regno + +[ Upstream commit 509438336ce75c8b4e6ce8e8d507dc77d0783bdd ] + +Fix the pinctrl submodes and optee node to remove unneeded unit address, +fixing all unit_address_vs_reg warnings. + +Fixes: 9983822c8cf9 ("arm64: dts: mediatek: add pumpkin board dts") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-8-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi +index fcddec14738d..54514d62398f 100644 +--- a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi ++++ b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi +@@ -17,7 +17,7 @@ chosen { + }; + + firmware { +- optee: optee@4fd00000 { ++ optee: optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; +@@ -210,7 +210,7 @@ pins_cmd_dat { + }; + }; + +- i2c0_pins_a: i2c0@0 { ++ i2c0_pins_a: i2c0 { + pins1 { + pinmux = , + ; +@@ -218,7 +218,7 @@ pins1 { + }; + }; + +- i2c2_pins_a: i2c2@0 { ++ i2c2_pins_a: i2c2 { + pins1 { + pinmux = , + ; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt2712-evb-fix-usb-vbus-regulators-unit-na.patch b/queue-5.15/arm64-dts-mt2712-evb-fix-usb-vbus-regulators-unit-na.patch new file mode 100644 index 00000000000..5207d8546c2 --- /dev/null +++ b/queue-5.15/arm64-dts-mt2712-evb-fix-usb-vbus-regulators-unit-na.patch @@ -0,0 +1,64 @@ +From 4d8e0eb5e4b2998caa43e2ef1a77298438af08d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:10 +0200 +Subject: arm64: dts: mt2712-evb: Fix usb vbus regulators unit names + +From: AngeloGioacchino Del Regno + +[ Upstream commit ec1ae39a8d25cfb067b5459fac7c5b7b9bce6f6a ] + +Update the names to regulator-usb-p{0-3}-vbus to fix unit_address_vs_reg +warnings for those. + +Fixes: 1724f4cc5133 ("arm64: dts: Add USB3 related nodes for MT2712") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-7-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +index b78d441616b1..9d20cabf4f69 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +@@ -50,7 +50,7 @@ extcon_usb1: extcon_iddig1 { + id-gpio = <&pio 14 GPIO_ACTIVE_HIGH>; + }; + +- usb_p0_vbus: regulator@2 { ++ usb_p0_vbus: regulator-usb-p0-vbus { + compatible = "regulator-fixed"; + regulator-name = "p0_vbus"; + regulator-min-microvolt = <5000000>; +@@ -59,7 +59,7 @@ usb_p0_vbus: regulator@2 { + enable-active-high; + }; + +- usb_p1_vbus: regulator@3 { ++ usb_p1_vbus: regulator-usb-p1-vbus { + compatible = "regulator-fixed"; + regulator-name = "p1_vbus"; + regulator-min-microvolt = <5000000>; +@@ -68,7 +68,7 @@ usb_p1_vbus: regulator@3 { + enable-active-high; + }; + +- usb_p2_vbus: regulator@4 { ++ usb_p2_vbus: regulator-usb-p2-vbus { + compatible = "regulator-fixed"; + regulator-name = "p2_vbus"; + regulator-min-microvolt = <5000000>; +@@ -77,7 +77,7 @@ usb_p2_vbus: regulator@4 { + enable-active-high; + }; + +- usb_p3_vbus: regulator@5 { ++ usb_p3_vbus: regulator-usb-p3-vbus { + compatible = "regulator-fixed"; + regulator-name = "p3_vbus"; + regulator-min-microvolt = <5000000>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt2712-evb-fix-vproc-fixed-regulators-unit.patch b/queue-5.15/arm64-dts-mt2712-evb-fix-vproc-fixed-regulators-unit.patch new file mode 100644 index 00000000000..148f453d7f2 --- /dev/null +++ b/queue-5.15/arm64-dts-mt2712-evb-fix-vproc-fixed-regulators-unit.patch @@ -0,0 +1,45 @@ +From be79cc70d97070c6305f80357cdf417d823cf465 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:09 +0200 +Subject: arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names + +From: AngeloGioacchino Del Regno + +[ Upstream commit 377063156893bf6c088309ac799fe5c6dce2822d ] + +Update the names to regulator-vproc-buck{0,1} to fix unit_addres_vs_reg +warnings for those. + +Fixes: f75dd8bdd344 ("arm64: dts: mediatek: add mt2712 cpufreq related device nodes") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-6-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt2712-evb.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +index 7d369fdd3117..b78d441616b1 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts ++++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +@@ -26,14 +26,14 @@ chosen { + stdout-path = "serial0:921600n8"; + }; + +- cpus_fixed_vproc0: fixedregulator@0 { ++ cpus_fixed_vproc0: regulator-vproc-buck0 { + compatible = "regulator-fixed"; + regulator-name = "vproc_buck0"; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1000000>; + }; + +- cpus_fixed_vproc1: fixedregulator@1 { ++ cpus_fixed_vproc1: regulator-vproc-buck1 { + compatible = "regulator-fixed"; + regulator-name = "vproc_buck1"; + regulator-min-microvolt = <1000000>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt2712e-fix-unit-address-for-pinctrl-node.patch b/queue-5.15/arm64-dts-mt2712e-fix-unit-address-for-pinctrl-node.patch new file mode 100644 index 00000000000..afce62d766b --- /dev/null +++ b/queue-5.15/arm64-dts-mt2712e-fix-unit-address-for-pinctrl-node.patch @@ -0,0 +1,42 @@ +From 7d8bf3b80683770d6d4d5d2a62c0ccae4eceacde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:08 +0200 +Subject: arm64: dts: mt2712e: Fix unit address for pinctrl node + +From: AngeloGioacchino Del Regno + +[ Upstream commit 1d4516f53a611b362db7ba7a8889923d469f57e1 ] + +The unit address for the pinctrl node is (0x)1000b000 and not +(0x)10005000, which is the syscfg_pctl_a address instead. + +This fixes the following warning: +arch/arm64/boot/dts/mediatek/mt2712e.dtsi:264.40-267.4: Warning +(unique_unit_address): /syscfg_pctl_a@10005000: duplicate +unit-address (also used in node /pinctrl@10005000) + +Fixes: f0c64340b748 ("arm64: dts: mt2712: add pintcrl device node.") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-5-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +index 1c55689383b8..993a03d7fff1 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +@@ -266,7 +266,7 @@ syscfg_pctl_a: syscfg_pctl_a@10005000 { + reg = <0 0x10005000 0 0x1000>; + }; + +- pio: pinctrl@10005000 { ++ pio: pinctrl@1000b000 { + compatible = "mediatek,mt2712-pinctrl"; + reg = <0 0x1000b000 0 0x1000>; + mediatek,pctl-regmap = <&syscfg_pctl_a>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt2712e-fix-unit_address_vs_reg-warning-fo.patch b/queue-5.15/arm64-dts-mt2712e-fix-unit_address_vs_reg-warning-fo.patch new file mode 100644 index 00000000000..3a01b30c977 --- /dev/null +++ b/queue-5.15/arm64-dts-mt2712e-fix-unit_address_vs_reg-warning-fo.patch @@ -0,0 +1,110 @@ +From 9b3a411645101f71ab3533b901efb1fd39de7b7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:07 +0200 +Subject: arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators + +From: AngeloGioacchino Del Regno + +[ Upstream commit e4495a0a8b3d84816c9a46edf3ce060bbf267475 ] + +Rename the fixed-clock oscillators to remove the unit address. + +This solves unit_address_vs_reg warnings. + +Fixes: 5d4839709c8e ("arm64: dts: mt2712: Add clock controller device nodes") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-4-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt2712e.dtsi | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +index a9cca9c146fd..1c55689383b8 100644 +--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +@@ -160,70 +160,70 @@ sys_clk: dummyclk { + #clock-cells = <0>; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + +- clk32k: oscillator@1 { ++ clk32k: oscillator-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "clk32k"; + }; + +- clkfpc: oscillator@2 { ++ clkfpc: oscillator-50m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "clkfpc"; + }; + +- clkaud_ext_i_0: oscillator@3 { ++ clkaud_ext_i_0: oscillator-aud0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <6500000>; + clock-output-names = "clkaud_ext_i_0"; + }; + +- clkaud_ext_i_1: oscillator@4 { ++ clkaud_ext_i_1: oscillator-aud1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <196608000>; + clock-output-names = "clkaud_ext_i_1"; + }; + +- clkaud_ext_i_2: oscillator@5 { ++ clkaud_ext_i_2: oscillator-aud2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <180633600>; + clock-output-names = "clkaud_ext_i_2"; + }; + +- clki2si0_mck_i: oscillator@6 { ++ clki2si0_mck_i: oscillator-i2s0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si0_mck_i"; + }; + +- clki2si1_mck_i: oscillator@7 { ++ clki2si1_mck_i: oscillator-i2s1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si1_mck_i"; + }; + +- clki2si2_mck_i: oscillator@8 { ++ clki2si2_mck_i: oscillator-i2s2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; + clock-output-names = "clki2si2_mck_i"; + }; + +- clktdmin_mclk_i: oscillator@9 { ++ clktdmin_mclk_i: oscillator-mclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <30000000>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt6779-fix-devicetree-build-warnings.patch b/queue-5.15/arm64-dts-mt6779-fix-devicetree-build-warnings.patch new file mode 100644 index 00000000000..46d66fc2021 --- /dev/null +++ b/queue-5.15/arm64-dts-mt6779-fix-devicetree-build-warnings.patch @@ -0,0 +1,76 @@ +From 0c97d2e9759af65cce46928f614b8d1737d375e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 17:22:06 +0200 +Subject: arm64: dts: mt6779: Fix devicetree build warnings + +From: AngeloGioacchino Del Regno + +[ Upstream commit 4d759c524c15dc4151e40b9e3f368147fda7b789 ] + +Rename fixed-clock oscillators to oscillator-26m and oscillator-32k +and remove the unit address to fix the unit_address_vs_reg warning; +fix the unit address for interrupt and intpol controllers by +removing a leading zero in their unit address. + +This commit fixes the following warnings: + +(unit_address_vs_reg): /oscillator@0: node has a unit name, but +no reg or ranges property +(unit_address_vs_reg): /oscillator@1: node has a unit name, but +no reg or ranges property +(simple_bus_reg): /soc/interrupt-controller@0c000000: simple-bus +unit address format error, expected "c000000" +(simple_bus_reg): /soc/intpol-controller@0c53a650: simple-bus +unit address format error, expected "c53a650" + +Fixes: 4c7a6260775d ("arm64: dts: add dts nodes for MT6779") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221013152212.416661-3-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt6779.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt6779.dtsi b/arch/arm64/boot/dts/mediatek/mt6779.dtsi +index 9bdf5145966c..dde9ce137b4f 100644 +--- a/arch/arm64/boot/dts/mediatek/mt6779.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt6779.dtsi +@@ -88,14 +88,14 @@ pmu { + interrupts = ; + }; + +- clk26m: oscillator@0 { ++ clk26m: oscillator-26m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <26000000>; + clock-output-names = "clk26m"; + }; + +- clk32k: oscillator@1 { ++ clk32k: oscillator-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; +@@ -117,7 +117,7 @@ soc { + compatible = "simple-bus"; + ranges; + +- gic: interrupt-controller@0c000000 { ++ gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <4>; + interrupt-parent = <&gic>; +@@ -138,7 +138,7 @@ ppi_cluster1: interrupt-partition-1 { + + }; + +- sysirq: intpol-controller@0c53a650 { ++ sysirq: intpol-controller@c53a650 { + compatible = "mediatek,mt6779-sysirq", + "mediatek,mt6577-sysirq"; + interrupt-controller; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-mt8183-fix-mali-gpu-clock.patch b/queue-5.15/arm64-dts-mt8183-fix-mali-gpu-clock.patch new file mode 100644 index 00000000000..7015d18c71b --- /dev/null +++ b/queue-5.15/arm64-dts-mt8183-fix-mali-gpu-clock.patch @@ -0,0 +1,47 @@ +From 2193969d86d253cd9e2dacb91cc4f7a29d2e2358 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 12:11:19 +0200 +Subject: arm64: dts: mt8183: Fix Mali GPU clock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Chen-Yu Tsai + +[ Upstream commit ad2631b5645a1d0ca9bf6fecf71f77e3b0071ee5 ] + +The actual clock feeding into the Mali GPU on the MT8183 is from the +clock gate in the MFGCFG block, not CLK_TOP_MFGPLL_CK from the TOPCKGEN +block, which itself is simply a pass-through placeholder for the MFGPLL +in the APMIXEDSYS block. + +Fix the hardware description with the correct clock reference. + +Fixes: a8168cebf1bc ("arm64: dts: mt8183: Add node for the Mali GPU") +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: AngeloGioacchino Del Regno +Tested-by: Nícolas F. R. A. Prado +Link: https://lore.kernel.org/r/20220927101128.44758-2-angelogioacchino.delregno@collabora.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/mediatek/mt8183.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +index 409cf827970c..f4e0bea8ddcb 100644 +--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi ++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi +@@ -1212,7 +1212,7 @@ gpu: gpu@13040000 { + ; + interrupt-names = "job", "mmu", "gpu"; + +- clocks = <&topckgen CLK_TOP_MFGPLL_CK>; ++ clocks = <&mfgcfg CLK_MFG_BG3D>; + + power-domains = + <&spm MT8183_POWER_DOMAIN_MFG_CORE0>, +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-correct-qmp-phy-child-node-name.patch b/queue-5.15/arm64-dts-qcom-correct-qmp-phy-child-node-name.patch new file mode 100644 index 00000000000..aa17129bca2 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-correct-qmp-phy-child-node-name.patch @@ -0,0 +1,298 @@ +From 326b0252c17de724e0a71d1537c205f6185bbfa6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Sep 2021 11:42:47 +0800 +Subject: arm64: dts: qcom: Correct QMP PHY child node name + +From: Shawn Guo + +[ Upstream commit 1351512f29b4348e6b497f6343896c1033d409b4 ] + +Many child nodes of QMP PHY are named without following bindings schema +and causing dtbs_check warnings like below. + +phy@1c06000: 'lane@1c06800' does not match any of the regexes: '^phy@[0-9a-f]+$' + arch/arm64/boot/dts/qcom/msm8998-asus-novago-tp370ql.dt.yaml + arch/arm64/boot/dts/qcom/msm8998-hp-envy-x2.dt.yaml + arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dt.yaml + arch/arm64/boot/dts/qcom/msm8998-mtp.dt.yaml + arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dt.yaml + arch/arm64/boot/dts/qcom/msm8998-oneplus-dumpling.dt.yaml + +Correct them to fix the warnings. + +Signed-off-by: Shawn Guo +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20210929034253.24570-5-shawn.guo@linaro.org +Stable-dep-of: 36a31b3a8d9b ("arm64: dts: qcom: sm8150: fix UFS PHY registers") +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/ipq6018.dtsi | 2 +- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- + arch/arm64/boot/dts/qcom/msm8996.dtsi | 10 +++++----- + arch/arm64/boot/dts/qcom/msm8998.dtsi | 6 +++--- + arch/arm64/boot/dts/qcom/sdm845.dtsi | 10 +++++----- + arch/arm64/boot/dts/qcom/sm8150.dtsi | 6 +++--- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 +++++----- + arch/arm64/boot/dts/qcom/sm8350.dtsi | 2 +- + 8 files changed, 25 insertions(+), 25 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +index ce4c2b4a5fc0..30ac0b2e8c89 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi +@@ -401,7 +401,7 @@ pcie_phy: phy@84000 { + reset-names = "phy", + "common"; + +- pcie_phy0: lane@84200 { ++ pcie_phy0: phy@84200 { + reg = <0x0 0x84200 0x0 0x16c>, /* Serdes Tx */ + <0x0 0x84400 0x0 0x200>, /* Serdes Rx */ + <0x0 0x84800 0x0 0x4f4>; /* PCS: Lane0, COM, PCIE */ +diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +index 6b9ac0550490..9d4019e0949a 100644 +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -106,7 +106,7 @@ ssphy_1: phy@58000 { + reset-names = "phy","common"; + status = "disabled"; + +- usb1_ssphy: lane@58200 { ++ usb1_ssphy: phy@58200 { + reg = <0x00058200 0x130>, /* Tx */ + <0x00058400 0x200>, /* Rx */ + <0x00058800 0x1f8>, /* PCS */ +@@ -149,7 +149,7 @@ ssphy_0: phy@78000 { + reset-names = "phy","common"; + status = "disabled"; + +- usb0_ssphy: lane@78200 { ++ usb0_ssphy: phy@78200 { + reg = <0x00078200 0x130>, /* Tx */ + <0x00078400 0x200>, /* Rx */ + <0x00078800 0x1f8>, /* PCS */ +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 70187fd03a26..40174220e8e2 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -618,7 +618,7 @@ pcie_phy: phy@34000 { + reset-names = "phy", "common", "cfg"; + status = "disabled"; + +- pciephy_0: lane@35000 { ++ pciephy_0: phy@35000 { + reg = <0x00035000 0x130>, + <0x00035200 0x200>, + <0x00035400 0x1dc>; +@@ -631,7 +631,7 @@ pciephy_0: lane@35000 { + reset-names = "lane0"; + }; + +- pciephy_1: lane@36000 { ++ pciephy_1: phy@36000 { + reg = <0x00036000 0x130>, + <0x00036200 0x200>, + <0x00036400 0x1dc>; +@@ -644,7 +644,7 @@ pciephy_1: lane@36000 { + reset-names = "lane1"; + }; + +- pciephy_2: lane@37000 { ++ pciephy_2: phy@37000 { + reg = <0x00037000 0x130>, + <0x00037200 0x200>, + <0x00037400 0x1dc>; +@@ -1763,7 +1763,7 @@ ufsphy: phy@627000 { + reset-names = "ufsphy"; + status = "disabled"; + +- ufsphy_lane: lanes@627400 { ++ ufsphy_lane: phy@627400 { + reg = <0x627400 0x12c>, + <0x627600 0x200>, + <0x627c00 0x1b4>; +@@ -2618,7 +2618,7 @@ usb3phy: phy@7410000 { + reset-names = "phy", "common"; + status = "disabled"; + +- ssusb_phy_0: lane@7410200 { ++ ssusb_phy_0: phy@7410200 { + reg = <0x07410200 0x200>, + <0x07410400 0x130>, + <0x07410600 0x1a8>; +diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi +index 228339f81c32..5350b911f4f6 100644 +--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi +@@ -994,7 +994,7 @@ pcie_phy: phy@1c06000 { + vdda-phy-supply = <&vreg_l1a_0p875>; + vdda-pll-supply = <&vreg_l2a_1p2>; + +- pciephy: lane@1c06800 { ++ pciephy: phy@1c06800 { + reg = <0x01c06200 0x128>, <0x01c06400 0x1fc>, <0x01c06800 0x20c>; + #phy-cells = <0>; + +@@ -1066,7 +1066,7 @@ ufsphy: phy@1da7000 { + reset-names = "ufsphy"; + resets = <&ufshc 0>; + +- ufsphy_lanes: lanes@1da7400 { ++ ufsphy_lanes: phy@1da7400 { + reg = <0x01da7400 0x128>, + <0x01da7600 0x1fc>, + <0x01da7c00 0x1dc>, +@@ -1999,7 +1999,7 @@ usb3phy: phy@c010000 { + <&gcc GCC_USB3PHY_PHY_BCR>; + reset-names = "phy", "common"; + +- usb1_ssphy: lane@c010200 { ++ usb1_ssphy: phy@c010200 { + reg = <0xc010200 0x128>, + <0xc010400 0x200>, + <0xc010c00 0x20c>, +diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi +index ea7a272d267a..ed293f635f14 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi +@@ -2064,7 +2064,7 @@ pcie0_phy: phy@1c06000 { + + status = "disabled"; + +- pcie0_lane: lanes@1c06200 { ++ pcie0_lane: phy@1c06200 { + reg = <0 0x01c06200 0 0x128>, + <0 0x01c06400 0 0x1fc>, + <0 0x01c06800 0 0x218>, +@@ -2174,7 +2174,7 @@ pcie1_phy: phy@1c0a000 { + + status = "disabled"; + +- pcie1_lane: lanes@1c06200 { ++ pcie1_lane: phy@1c06200 { + reg = <0 0x01c0a800 0 0x800>, + <0 0x01c0a800 0 0x800>, + <0 0x01c0b800 0 0x400>; +@@ -2302,7 +2302,7 @@ ufs_mem_phy: phy@1d87000 { + reset-names = "ufsphy"; + status = "disabled"; + +- ufs_mem_phy_lanes: lanes@1d87400 { ++ ufs_mem_phy_lanes: phy@1d87400 { + reg = <0 0x01d87400 0 0x108>, + <0 0x01d87600 0 0x1e0>, + <0 0x01d87c00 0 0x1dc>, +@@ -3699,7 +3699,7 @@ usb_1_qmpphy: phy@88e9000 { + <&gcc GCC_USB3_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + +- usb_1_ssphy: lanes@88e9200 { ++ usb_1_ssphy: phy@88e9200 { + reg = <0 0x088e9200 0 0x128>, + <0 0x088e9400 0 0x200>, + <0 0x088e9c00 0 0x218>, +@@ -3732,7 +3732,7 @@ usb_2_qmpphy: phy@88eb000 { + <&gcc GCC_USB3_PHY_SEC_BCR>; + reset-names = "phy", "common"; + +- usb_2_ssphy: lane@88eb200 { ++ usb_2_ssphy: phy@88eb200 { + reg = <0 0x088eb200 0 0x128>, + <0 0x088eb400 0 0x1fc>, + <0 0x088eb800 0 0x218>, +diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi +index f347f752d536..74c4acb8598b 100644 +--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi +@@ -1692,7 +1692,7 @@ ufs_mem_phy: phy@1d87000 { + reset-names = "ufsphy"; + status = "disabled"; + +- ufs_mem_phy_lanes: lanes@1d87400 { ++ ufs_mem_phy_lanes: phy@1d87400 { + reg = <0 0x01d87400 0 0x108>, + <0 0x01d87600 0 0x1e0>, + <0 0x01d87c00 0 0x1dc>, +@@ -3010,7 +3010,7 @@ usb_1_qmpphy: phy@88e9000 { + <&gcc GCC_USB3_PHY_PRIM_BCR>; + reset-names = "phy", "common"; + +- usb_1_ssphy: lanes@88e9200 { ++ usb_1_ssphy: phy@88e9200 { + reg = <0 0x088e9200 0 0x200>, + <0 0x088e9400 0 0x200>, + <0 0x088e9c00 0 0x218>, +@@ -3043,7 +3043,7 @@ usb_2_qmpphy: phy@88eb000 { + <&gcc GCC_USB3_PHY_SEC_BCR>; + reset-names = "phy", "common"; + +- usb_2_ssphy: lane@88eb200 { ++ usb_2_ssphy: phy@88eb200 { + reg = <0 0x088eb200 0 0x200>, + <0 0x088eb400 0 0x200>, + <0 0x088eb800 0 0x800>, +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index 9a95c15c7e8b..bcc948f6f326 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -1463,7 +1463,7 @@ pcie0_phy: phy@1c06000 { + + status = "disabled"; + +- pcie0_lane: lanes@1c06200 { ++ pcie0_lane: phy@1c06200 { + reg = <0 0x1c06200 0 0x170>, /* tx */ + <0 0x1c06400 0 0x200>, /* rx */ + <0 0x1c06800 0 0x1f0>, /* pcs */ +@@ -1569,7 +1569,7 @@ pcie1_phy: phy@1c0e000 { + + status = "disabled"; + +- pcie1_lane: lanes@1c0e200 { ++ pcie1_lane: phy@1c0e200 { + reg = <0 0x1c0e200 0 0x170>, /* tx0 */ + <0 0x1c0e400 0 0x200>, /* rx0 */ + <0 0x1c0ea00 0 0x1f0>, /* pcs */ +@@ -1677,7 +1677,7 @@ pcie2_phy: phy@1c16000 { + + status = "disabled"; + +- pcie2_lane: lanes@1c16200 { ++ pcie2_lane: phy@1c16200 { + reg = <0 0x1c16200 0 0x170>, /* tx0 */ + <0 0x1c16400 0 0x200>, /* rx0 */ + <0 0x1c16a00 0 0x1f0>, /* pcs */ +@@ -1756,7 +1756,7 @@ ufs_mem_phy: phy@1d87000 { + reset-names = "ufsphy"; + status = "disabled"; + +- ufs_mem_phy_lanes: lanes@1d87400 { ++ ufs_mem_phy_lanes: phy@1d87400 { + reg = <0 0x01d87400 0 0x108>, + <0 0x01d87600 0 0x1e0>, + <0 0x01d87c00 0 0x1dc>, +@@ -2336,7 +2336,7 @@ usb_2_qmpphy: phy@88eb000 { + <&gcc GCC_USB3_PHY_SEC_BCR>; + reset-names = "phy", "common"; + +- usb_2_ssphy: lanes@88eb200 { ++ usb_2_ssphy: phy@88eb200 { + reg = <0 0x088eb200 0 0x200>, + <0 0x088eb400 0 0x200>, + <0 0x088eb800 0 0x800>; +diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi +index c0a3ea47302f..d6dc55687c2a 100644 +--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi +@@ -1123,7 +1123,7 @@ ufs_mem_phy: phy@1d87000 { + reset-names = "ufsphy"; + status = "disabled"; + +- ufs_mem_phy_lanes: lanes@1d87400 { ++ ufs_mem_phy_lanes: phy@1d87400 { + reg = <0 0x01d87400 0 0x108>, + <0 0x01d87600 0 0x1e0>, + <0 0x01d87c00 0 0x1dc>, +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-ipq6018-cp01-c1-use-blspi1-pins.patch b/queue-5.15/arm64-dts-qcom-ipq6018-cp01-c1-use-blspi1-pins.patch new file mode 100644 index 00000000000..5e69f314efd --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-ipq6018-cp01-c1-use-blspi1-pins.patch @@ -0,0 +1,40 @@ +From d24ba681bfa5105159e6385cb1dfe2b1b17313bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Oct 2022 14:46:26 +0200 +Subject: arm64: dts: qcom: ipq6018-cp01-c1: use BLSPI1 pins + +From: Krzysztof Kozlowski + +[ Upstream commit 4871d3c38893c8a585e3e96364b7fb91cda8322e ] + +When BLSPI1 (originally SPI0, later renamed in commit f82c48d46852 +("arm64: dts: qcom: ipq6018: correct QUP peripheral labels")) was added, +the device node lacked respective pin configuration assignment. + +Fixes: 5bf635621245 ("arm64: dts: ipq6018: Add a few device nodes") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Bjorn Andersson +Reviewed-by: Konrad Dybcio +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221006124659.217540-2-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +index 5aec18308712..5310259d03dc 100644 +--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts ++++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts +@@ -37,6 +37,8 @@ &i2c_1 { + + &spi_0 { + cs-select = <0>; ++ pinctrl-0 = <&spi_0_pins>; ++ pinctrl-names = "default"; + status = "okay"; + + m25p80@0 { +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-msm8916-drop-mss-fallback-compatible.patch b/queue-5.15/arm64-dts-qcom-msm8916-drop-mss-fallback-compatible.patch new file mode 100644 index 00000000000..c17475756a3 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8916-drop-mss-fallback-compatible.patch @@ -0,0 +1,52 @@ +From 7243ac7c1cc40b7257a0023efbce4c992a7ce900 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Jul 2022 16:03:40 +0200 +Subject: arm64: dts: qcom: msm8916: Drop MSS fallback compatible + +From: Stephan Gerhold + +[ Upstream commit ff02ac621634e82c0c34d02a79d402ae700cdfd0 ] + +MSM8916 was originally using the "qcom,q6v5-pil" compatible for the +MSS remoteproc. Later it was decided to use SoC-specific compatibles +instead, so "qcom,msm8916-mss-pil" is now the preferred compatible. + +Commit 60a05ed059a0 ("arm64: dts: qcom: msm8916: Add MSM8916-specific +compatibles to SCM/MSS") updated the MSM8916 device tree to make use of +the new compatible but still kept the old "qcom,q6v5-pil" as fallback. + +This is inconsistent with other SoCs and conflicts with the description +in the binding documentation (which says that only one compatible should +be present). Also, it has no functional advantage since older kernels +could not handle this DT anyway (e.g. "power-domains" in the MSS node is +only supported by kernels that also support "qcom,msm8916-mss-pil"). + +Make this consistent with other SoCs by using only the +"qcom,msm8916-mss-pil" compatible. + +Fixes: 60a05ed059a0 ("arm64: dts: qcom: msm8916: Add MSM8916-specific compatibles to SCM/MSS") +Signed-off-by: Stephan Gerhold +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220718140344.1831731-2-stephan.gerhold@kernkonzept.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/msm8916.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi +index 19e201f52b16..b967dbfba3b8 100644 +--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi +@@ -1307,7 +1307,7 @@ spmi_bus: spmi@200f000 { + }; + + mpss: remoteproc@4080000 { +- compatible = "qcom,msm8916-mss-pil", "qcom,q6v5-pil"; ++ compatible = "qcom,msm8916-mss-pil"; + reg = <0x04080000 0x100>, + <0x04020000 0x040>; + +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-msm8996-add-msm8996-pro-support.patch b/queue-5.15/arm64-dts-qcom-msm8996-add-msm8996-pro-support.patch new file mode 100644 index 00000000000..94be03961a7 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8996-add-msm8996-pro-support.patch @@ -0,0 +1,567 @@ +From 4585b0b6bb312d9433b001915e383ad24398b74f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 17:04:16 +0300 +Subject: arm64: dts: qcom: msm8996: Add MSM8996 Pro support + +From: Yassine Oudjana + +[ Upstream commit 8898c9748a872866f8c2973e719b26bf7c6ab64e ] + +Qualcomm MSM8996 Pro is a variant of MSM8996 with higher frequencies +supported both on CPU and GPU. There are other minor hardware +differencies in the CPU and GPU regulators and bus fabrics. + +However this results in significant differences between 8996 and 8996 +Pro CPU OPP tables. Judging from msm-3.18 there are only few common +frequencies supported by both msm8996 and msm8996pro. Rather than +hacking the tables for msm8996, split msm8996pro support into a separate +file. Later this would allow having additional customizations for the +CBF, CPR, retulators, etc. + +[DB: dropped all non-CPU-OPP changes] + +Fixes: 90173a954a22 ("arm64: dts: qcom: msm8996: Add CPU opps") +Signed-off-by: Yassine Oudjana +[DB: Realigned supported-hw to keep compat with current cpufreq driver] +Signed-off-by: Dmitry Baryshkov +Acked-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220724140421.1933004-3-dmitry.baryshkov@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/msm8996.dtsi | 82 +++---- + arch/arm64/boot/dts/qcom/msm8996pro.dtsi | 266 +++++++++++++++++++++++ + 2 files changed, 307 insertions(+), 41 deletions(-) + create mode 100644 arch/arm64/boot/dts/qcom/msm8996pro.dtsi + +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 6077c3601951..4f472306f10f 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -142,82 +142,82 @@ cluster0_opp: opp_table0 { + /* Nominal fmax for now */ + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-422400000 { + opp-hz = /bits/ 64 <422400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-556800000 { + opp-hz = /bits/ 64 <556800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-652800000 { + opp-hz = /bits/ 64 <652800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-729600000 { + opp-hz = /bits/ 64 <729600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-844800000 { + opp-hz = /bits/ 64 <844800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-960000000 { + opp-hz = /bits/ 64 <960000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1113600000 { + opp-hz = /bits/ 64 <1113600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1228800000 { + opp-hz = /bits/ 64 <1228800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1324800000 { + opp-hz = /bits/ 64 <1324800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1593600000 { + opp-hz = /bits/ 64 <1593600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + }; +@@ -230,127 +230,127 @@ cluster1_opp: opp_table1 { + /* Nominal fmax for now */ + opp-307200000 { + opp-hz = /bits/ 64 <307200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-403200000 { + opp-hz = /bits/ 64 <403200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-556800000 { + opp-hz = /bits/ 64 <556800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-652800000 { + opp-hz = /bits/ 64 <652800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-729600000 { + opp-hz = /bits/ 64 <729600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-806400000 { + opp-hz = /bits/ 64 <806400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-883200000 { + opp-hz = /bits/ 64 <883200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-940800000 { + opp-hz = /bits/ 64 <940800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1036800000 { + opp-hz = /bits/ 64 <1036800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1113600000 { + opp-hz = /bits/ 64 <1113600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1190400000 { + opp-hz = /bits/ 64 <1190400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1248000000 { + opp-hz = /bits/ 64 <1248000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1324800000 { + opp-hz = /bits/ 64 <1324800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1555200000 { + opp-hz = /bits/ 64 <1555200000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1632000000 { + opp-hz = /bits/ 64 <1632000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1708800000 { + opp-hz = /bits/ 64 <1708800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1785600000 { + opp-hz = /bits/ 64 <1785600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1824000000 { + opp-hz = /bits/ 64 <1824000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1920000000 { + opp-hz = /bits/ 64 <1920000000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-1996800000 { + opp-hz = /bits/ 64 <1996800000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-2073600000 { + opp-hz = /bits/ 64 <2073600000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + opp-2150400000 { + opp-hz = /bits/ 64 <2150400000>; +- opp-supported-hw = <0x77>; ++ opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; + }; +diff --git a/arch/arm64/boot/dts/qcom/msm8996pro.dtsi b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi +new file mode 100644 +index 000000000000..63e1b4ec7a36 +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi +@@ -0,0 +1,266 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2022, Linaro Limited ++ */ ++ ++#include "msm8996.dtsi" ++ ++/ { ++ /delete-node/ opp-table-cluster0; ++ /delete-node/ opp-table-cluster1; ++ ++ /* ++ * On MSM8996 Pro the cpufreq driver shifts speed bins into the high ++ * nibble of supported hw, so speed bin 0 becomes 0x10, speed bin 1 ++ * becomes 0x20, speed 2 becomes 0x40. ++ */ ++ ++ cluster0_opp: opp-table-cluster0 { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&speedbin_efuse>; ++ opp-shared; ++ ++ opp-307200000 { ++ opp-hz = /bits/ 64 <307200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-384000000 { ++ opp-hz = /bits/ 64 <384000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-460800000 { ++ opp-hz = /bits/ 64 <460800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-537600000 { ++ opp-hz = /bits/ 64 <537600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-614400000 { ++ opp-hz = /bits/ 64 <614400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-691200000 { ++ opp-hz = /bits/ 64 <691200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-768000000 { ++ opp-hz = /bits/ 64 <768000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-844800000 { ++ opp-hz = /bits/ 64 <844800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-902400000 { ++ opp-hz = /bits/ 64 <902400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-979200000 { ++ opp-hz = /bits/ 64 <979200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1132800000 { ++ opp-hz = /bits/ 64 <1132800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1209600000 { ++ opp-hz = /bits/ 64 <1209600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1286400000 { ++ opp-hz = /bits/ 64 <1286400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1440000000 { ++ opp-hz = /bits/ 64 <1440000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1516800000 { ++ opp-hz = /bits/ 64 <1516800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1593600000 { ++ opp-hz = /bits/ 64 <1593600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1996800000 { ++ opp-hz = /bits/ 64 <1996800000>; ++ opp-supported-hw = <0x20>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2188800000 { ++ opp-hz = /bits/ 64 <2188800000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++ ++ cluster1_opp: opp-table-cluster1 { ++ compatible = "operating-points-v2-kryo-cpu"; ++ nvmem-cells = <&speedbin_efuse>; ++ opp-shared; ++ ++ opp-307200000 { ++ opp-hz = /bits/ 64 <307200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-384000000 { ++ opp-hz = /bits/ 64 <384000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-460800000 { ++ opp-hz = /bits/ 64 <460800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-537600000 { ++ opp-hz = /bits/ 64 <537600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-614400000 { ++ opp-hz = /bits/ 64 <614400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-691200000 { ++ opp-hz = /bits/ 64 <691200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-748800000 { ++ opp-hz = /bits/ 64 <748800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-825600000 { ++ opp-hz = /bits/ 64 <825600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-902400000 { ++ opp-hz = /bits/ 64 <902400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-979200000 { ++ opp-hz = /bits/ 64 <979200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1132800000 { ++ opp-hz = /bits/ 64 <1132800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1209600000 { ++ opp-hz = /bits/ 64 <1209600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1286400000 { ++ opp-hz = /bits/ 64 <1286400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1440000000 { ++ opp-hz = /bits/ 64 <1440000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1516800000 { ++ opp-hz = /bits/ 64 <1516800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1593600000 { ++ opp-hz = /bits/ 64 <1593600000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1670400000 { ++ opp-hz = /bits/ 64 <1670400000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1747200000 { ++ opp-hz = /bits/ 64 <1747200000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1824000000 { ++ opp-hz = /bits/ 64 <1824000000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1900800000 { ++ opp-hz = /bits/ 64 <1900800000>; ++ opp-supported-hw = <0x70>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1977600000 { ++ opp-hz = /bits/ 64 <1977600000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2054400000 { ++ opp-hz = /bits/ 64 <2054400000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2150400000 { ++ opp-hz = /bits/ 64 <2150400000>; ++ opp-supported-hw = <0x30>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2246400000 { ++ opp-hz = /bits/ 64 <2246400000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-2342400000 { ++ opp-hz = /bits/ 64 <2342400000>; ++ opp-supported-hw = <0x10>; ++ clock-latency-ns = <200000>; ++ }; ++ }; ++}; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-msm8996-fix-gpu-opp-table.patch b/queue-5.15/arm64-dts-qcom-msm8996-fix-gpu-opp-table.patch new file mode 100644 index 00000000000..2d552d1cebc --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8996-fix-gpu-opp-table.patch @@ -0,0 +1,52 @@ +From 2e600b917a926173f3572b319f8eda029b94ab69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 17:04:20 +0300 +Subject: arm64: dts: qcom: msm8996: fix GPU OPP table + +From: Dmitry Baryshkov + +[ Upstream commit 0d440d811e6e2f37093e54db55bc27fe66678170 ] + +Fix Adreno OPP table according to the msm-3.18. Enable 624 MHz for the +speed bin 3 and 560 MHz for bins 2 and 3. + +Fixes: 69cc3114ab0f ("arm64: dts: Add Adreno GPU definitions") +Signed-off-by: Dmitry Baryshkov +Acked-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220724140421.1933004-7-dmitry.baryshkov@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/msm8996.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 032c6cd635e2..70187fd03a26 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -995,17 +995,17 @@ gpu_opp_table: opp-table { + compatible ="operating-points-v2"; + + /* +- * 624Mhz and 560Mhz are only available on speed +- * bin (1 << 0). All the rest are available on +- * all bins of the hardware ++ * 624Mhz is only available on speed bins 0 and 3. ++ * 560Mhz is only available on speed bins 0, 2 and 3. ++ * All the rest are available on all bins of the hardware. + */ + opp-624000000 { + opp-hz = /bits/ 64 <624000000>; +- opp-supported-hw = <0x01>; ++ opp-supported-hw = <0x09>; + }; + opp-560000000 { + opp-hz = /bits/ 64 <560000000>; +- opp-supported-hw = <0x01>; ++ opp-supported-hw = <0x0d>; + }; + opp-510000000 { + opp-hz = /bits/ 64 <510000000>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-msm8996-fix-supported-hw-in-cpufreq-o.patch b/queue-5.15/arm64-dts-qcom-msm8996-fix-supported-hw-in-cpufreq-o.patch new file mode 100644 index 00000000000..59100a811ca --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-msm8996-fix-supported-hw-in-cpufreq-o.patch @@ -0,0 +1,113 @@ +From 36be980d34af2129186beb5906f934ad789aa405 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Jul 2022 17:04:18 +0300 +Subject: arm64: dts: qcom: msm8996: fix supported-hw in cpufreq OPP tables + +From: Dmitry Baryshkov + +[ Upstream commit 0154caaa2b748e7414a4ec3c6ee60e8f483b2d4f ] + +Adjust MSM8996 cpufreq tables according to tables in msm-3.18. Some of +the frequencies are not supported on speed bins other than 0. Also other +speed bins support intermediate topmost frequencies, not supported on +speed bin 0. Implement all these differencies. + +Fixes: 90173a954a22 ("arm64: dts: qcom: msm8996: Add CPU opps") +Signed-off-by: Dmitry Baryshkov +Acked-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220724140421.1933004-5-dmitry.baryshkov@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/msm8996.dtsi | 38 ++++++++++++++++++++------- + 1 file changed, 29 insertions(+), 9 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi +index 4f472306f10f..032c6cd635e2 100644 +--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi +@@ -202,22 +202,32 @@ opp-1228800000 { + }; + opp-1324800000 { + opp-hz = /bits/ 64 <1324800000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x5>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1363200000 { ++ opp-hz = /bits/ 64 <1363200000>; ++ opp-supported-hw = <0x2>; + clock-latency-ns = <200000>; + }; + opp-1401600000 { + opp-hz = /bits/ 64 <1401600000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x5>; + clock-latency-ns = <200000>; + }; + opp-1478400000 { + opp-hz = /bits/ 64 <1478400000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1497600000 { ++ opp-hz = /bits/ 64 <1497600000>; ++ opp-supported-hw = <0x04>; + clock-latency-ns = <200000>; + }; + opp-1593600000 { + opp-hz = /bits/ 64 <1593600000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + }; +@@ -328,29 +338,39 @@ opp-1785600000 { + opp-supported-hw = <0x7>; + clock-latency-ns = <200000>; + }; ++ opp-1804800000 { ++ opp-hz = /bits/ 64 <1804800000>; ++ opp-supported-hw = <0x6>; ++ clock-latency-ns = <200000>; ++ }; + opp-1824000000 { + opp-hz = /bits/ 64 <1824000000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; ++ clock-latency-ns = <200000>; ++ }; ++ opp-1900800000 { ++ opp-hz = /bits/ 64 <1900800000>; ++ opp-supported-hw = <0x4>; + clock-latency-ns = <200000>; + }; + opp-1920000000 { + opp-hz = /bits/ 64 <1920000000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-1996800000 { + opp-hz = /bits/ 64 <1996800000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-2073600000 { + opp-hz = /bits/ 64 <2073600000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + opp-2150400000 { + opp-hz = /bits/ 64 <2150400000>; +- opp-supported-hw = <0x7>; ++ opp-supported-hw = <0x1>; + clock-latency-ns = <200000>; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-pm660-use-unique-adc5_vcoin-address-i.patch b/queue-5.15/arm64-dts-qcom-pm660-use-unique-adc5_vcoin-address-i.patch new file mode 100644 index 00000000000..1c7e1f60806 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-pm660-use-unique-adc5_vcoin-address-i.patch @@ -0,0 +1,39 @@ +From b5c5470a47ac12b479da08094eac599087e2f168 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 21:01:45 +0200 +Subject: arm64: dts: qcom: pm660: Use unique ADC5_VCOIN address in node name + +From: Marijn Suijten + +[ Upstream commit 02549ba5de0a09a27616496c3512db5af4ad7862 ] + +The register address in the node name is shadowing vph_pwr@83, whereas +the ADC5_VCOIN register resolves to 0x85. Fix this copy-paste +discrepancy. + +Fixes: 4bf097540506 ("arm64: dts: qcom: pm660: Add VADC and temp alarm nodes") +Signed-off-by: Marijn Suijten +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220926190148.283805-3-marijn.suijten@somainline.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/pm660.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi +index e847d7209afc..affc736d154a 100644 +--- a/arch/arm64/boot/dts/qcom/pm660.dtsi ++++ b/arch/arm64/boot/dts/qcom/pm660.dtsi +@@ -152,7 +152,7 @@ vadc_vph_pwr: vph_pwr@83 { + qcom,pre-scaling = <1 3>; + }; + +- vcoin: vcoin@83 { ++ vcoin: vcoin@85 { + reg = ; + qcom,decimation = <1024>; + qcom,pre-scaling = <1 3>; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sdm630-fix-uart1-pin-bias.patch b/queue-5.15/arm64-dts-qcom-sdm630-fix-uart1-pin-bias.patch new file mode 100644 index 00000000000..77d7b1993b9 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sdm630-fix-uart1-pin-bias.patch @@ -0,0 +1,38 @@ +From 8e51668ab2e993da029667e1c7f6675cae18d4fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 07:44:12 -0400 +Subject: arm64: dts: qcom: sdm630: fix UART1 pin bias + +From: Krzysztof Kozlowski + +[ Upstream commit 780f836fe071a9e8703fe6a05ae00129acf83391 ] + +There is no "bias-no-pull" property. Assume intentions were disabling +bias. + +Fixes: b190fb010664 ("arm64: dts: qcom: sdm630: Add sdm630 dts file") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Douglas Anderson +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221010114417.29859-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sdm630.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi +index 952bb133914f..c2e1a0d9a272 100644 +--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi +@@ -768,7 +768,7 @@ rx-cts-rts { + pins = "gpio17", "gpio18", "gpio19"; + function = "gpio"; + drive-strength = <2>; +- bias-no-pull; ++ bias-disable; + }; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sdm845-cheza-fix-ap-suspend-pin-bias.patch b/queue-5.15/arm64-dts-qcom-sdm845-cheza-fix-ap-suspend-pin-bias.patch new file mode 100644 index 00000000000..b0c569b228f --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sdm845-cheza-fix-ap-suspend-pin-bias.patch @@ -0,0 +1,47 @@ +From 580b3ed0e0f41e9734e238ff6a91f8ab7137d888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 07:44:14 -0400 +Subject: arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias + +From: Krzysztof Kozlowski + +[ Upstream commit 9bce41fab14da8f21027dc9847535ef5e22cbe8b ] + +There is no "bias-no-pull" property. Assume intentions were disabling +bias. + +Fixes: 79e7739f7b87 ("arm64: dts: qcom: sdm845-cheza: add initial cheza dt") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Douglas Anderson +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221010114417.29859-3-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +index dfd1b42c07fd..3566db1d7357 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi +@@ -1299,7 +1299,7 @@ ap_suspend_l_assert: ap_suspend_l_assert { + config { + pins = "gpio126"; + function = "gpio"; +- bias-no-pull; ++ bias-disable; + drive-strength = <2>; + output-low; + }; +@@ -1309,7 +1309,7 @@ ap_suspend_l_deassert: ap_suspend_l_deassert { + config { + pins = "gpio126"; + function = "gpio"; +- bias-no-pull; ++ bias-disable; + drive-strength = <2>; + output-high; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm6125-fix-sdhci-cqe-reg-names.patch b/queue-5.15/arm64-dts-qcom-sm6125-fix-sdhci-cqe-reg-names.patch new file mode 100644 index 00000000000..ff5e99ed021 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm6125-fix-sdhci-cqe-reg-names.patch @@ -0,0 +1,39 @@ +From f00c0b08ebe6c5c72ffd5d3d6949af4b680caae1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 12:36:46 -0400 +Subject: arm64: dts: qcom: sm6125: fix SDHCI CQE reg names + +From: Krzysztof Kozlowski + +[ Upstream commit 3de1172624b3c4ca65730bc34333ab493510b3e1 ] + +SM6125 comes with SDCC (SDHCI controller) v5, so the second range of +registers is cqhci, not core. + +Fixes: cff4bbaf2a2d ("arm64: dts: qcom: Add support for SM6125") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Marijn Suijten +Tested-by: Marijn Suijten # Sony Xperia 10 II +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221026163646.37433-1-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm6125.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi +index f89af5e35112..dc3bddc54eb6 100644 +--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi +@@ -408,7 +408,7 @@ rpm_msg_ram: sram@45f0000 { + sdhc_1: sdhci@4744000 { + compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5"; + reg = <0x04744000 0x1000>, <0x04745000 0x1000>; +- reg-names = "hc", "core"; ++ reg-names = "hc", "cqhci"; + + interrupts = , + ; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8150-fix-ufs-phy-registers.patch b/queue-5.15/arm64-dts-qcom-sm8150-fix-ufs-phy-registers.patch new file mode 100644 index 00000000000..868b25aa422 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8150-fix-ufs-phy-registers.patch @@ -0,0 +1,48 @@ +From daf00065dde1b1c83af7c3e6f89ae479f989b424 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 11:15:04 +0200 +Subject: arm64: dts: qcom: sm8150: fix UFS PHY registers + +From: Johan Hovold + +[ Upstream commit 36a31b3a8d9ba1707a23de8d8dc1ceaef4eda695 ] + +The sizes of the UFS PHY register regions are too small and does +specifically not cover all registers used by the Linux driver. + +As Linux maps these regions as full pages this is currently not an issue +on Linux, but let's update the sizes to match the vendor driver. + +Fixes: 3834a2e92229 ("arm64: dts: qcom: sm8150: Add ufs nodes") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221024091507.20342-2-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8150.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi +index 74c4acb8598b..292e40d6162d 100644 +--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi +@@ -1693,11 +1693,11 @@ ufs_mem_phy: phy@1d87000 { + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x16c>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x16c>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8250-correct-lpass-pin-pull-down.patch b/queue-5.15/arm64-dts-qcom-sm8250-correct-lpass-pin-pull-down.patch new file mode 100644 index 00000000000..deb70662fcf --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8250-correct-lpass-pin-pull-down.patch @@ -0,0 +1,37 @@ +From df3cc57b22ff1c5b7e34e7b7cc201d04e036fa89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 17:34:20 +0200 +Subject: arm64: dts: qcom: sm8250: correct LPASS pin pull down + +From: Krzysztof Kozlowski + +[ Upstream commit 195a0a11d66d6c696cbcf398d6bc3f3a3a462f7c ] + +The pull-down property is actually bias-pull-down. + +Fixes: 3160c1b894d9 ("arm64: dts: qcom: sm8250: add lpass lpi pin controller node") +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Neil Armstrong +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220927153429.55365-4-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index b710bca45648..9a95c15c7e8b 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -1933,7 +1933,7 @@ data { + pins = "gpio7"; + function = "dmic1_data"; + drive-strength = <2>; +- pull-down; ++ bias-pull-down; + input-enable; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8250-drop-bogus-dp-phy-clock.patch b/queue-5.15/arm64-dts-qcom-sm8250-drop-bogus-dp-phy-clock.patch new file mode 100644 index 00000000000..03a148f7f20 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8250-drop-bogus-dp-phy-clock.patch @@ -0,0 +1,38 @@ +From 77a69f88343830352681a19c99a7fee210d5da12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 17:25:10 +0200 +Subject: arm64: dts: qcom: sm8250: drop bogus DP PHY clock + +From: Johan Hovold + +[ Upstream commit bb9f23e46ddcebe1bc68a43a0f7acfc1865a6472 ] + +The QMP pipe clock is used by the USB part of the PHY so drop the +corresponding properties from the DP child node. + +Fixes: 5aa0d1becd5b ("arm64: dts: qcom: sm8250: switch usb1 qmp phy to USB3+DP mode") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221026152511.9661-2-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index e4ba998d0c6e..2051eb8ff18e 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -2312,9 +2312,6 @@ dp_phy: dp-phy@88ea200 { + <0 0x088eaa00 0 0x100>; + #phy-cells = <0>; + #clock-cells = <1>; +- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>; +- clock-names = "pipe0"; +- clock-output-names = "usb3_phy_pipe_clk_src"; + }; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8250-fix-ufs-phy-registers.patch b/queue-5.15/arm64-dts-qcom-sm8250-fix-ufs-phy-registers.patch new file mode 100644 index 00000000000..91e8e22b121 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8250-fix-ufs-phy-registers.patch @@ -0,0 +1,48 @@ +From e880fd779660d61c94c1d9932b46ec5f6a5bd933 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 11:15:05 +0200 +Subject: arm64: dts: qcom: sm8250: fix UFS PHY registers + +From: Johan Hovold + +[ Upstream commit 7f8b37dd4e7bf50160529530d9789b846153df71 ] + +The sizes of the UFS PHY register regions are too small and does +specifically not cover all registers used by the Linux driver. + +As Linux maps these regions as full pages this is currently not an issue +on Linux, but let's update the sizes to match the vendor driver. + +Fixes: b7e2fba06622 ("arm64: dts: qcom: sm8250: Add UFS controller and PHY") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221024091507.20342-3-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8250.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi +index bcc948f6f326..e4ba998d0c6e 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi +@@ -1757,11 +1757,11 @@ ufs_mem_phy: phy@1d87000 { + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x16c>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x16c>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + }; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8250-sony-xperia-edo-fix-touchscree.patch b/queue-5.15/arm64-dts-qcom-sm8250-sony-xperia-edo-fix-touchscree.patch new file mode 100644 index 00000000000..601752d8061 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8250-sony-xperia-edo-fix-touchscree.patch @@ -0,0 +1,38 @@ +From 054134a2fecd7819af7fda6499fa8c9b3e71b0df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 21:29:40 +0200 +Subject: arm64: dts: qcom: sm8250-sony-xperia-edo: fix touchscreen + bias-disable + +From: Krzysztof Kozlowski + +[ Upstream commit 7ff4a646fae3697b039c6b684786a1e309e8445c ] + +The property to disable bias is "bias-disable". + +Fixes: e76c7e1f15fe ("arm64: dts: qcom: sm8250-edo: Add Samsung touchscreen") +Reviewed-by: Konrad Dybcio +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220930192954.242546-3-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +index b15d085db05a..effbd6a9c989 100644 +--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi +@@ -591,7 +591,7 @@ ts_int_default: ts-int-default { + pins = "gpio39"; + function = "gpio"; + drive-strength = <2>; +- bias-disabled; ++ bias-disable; + input-enable; + }; + +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-qcom-sm8350-fix-ufs-phy-registers.patch b/queue-5.15/arm64-dts-qcom-sm8350-fix-ufs-phy-registers.patch new file mode 100644 index 00000000000..4d05a835bb5 --- /dev/null +++ b/queue-5.15/arm64-dts-qcom-sm8350-fix-ufs-phy-registers.patch @@ -0,0 +1,48 @@ +From c49f80ef70609565edab14e98e9d14dba237e609 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 11:15:06 +0200 +Subject: arm64: dts: qcom: sm8350: fix UFS PHY registers + +From: Johan Hovold + +[ Upstream commit b3c7839b698cc617e97dd2e4f1eeb4adc280fe58 ] + +The sizes of the UFS PHY register regions are too small and does +specifically not cover all registers used by the Linux driver. + +As Linux maps these regions as full pages this is currently not an issue +on Linux, but let's update the sizes to match the vendor driver. + +Fixes: 59c7cf814783 ("arm64: dts: qcom: sm8350: Add UFS nodes") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221024091507.20342-4-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8350.dtsi | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi +index d6dc55687c2a..1ef16975d13a 100644 +--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi +@@ -1124,11 +1124,11 @@ ufs_mem_phy: phy@1d87000 { + status = "disabled"; + + ufs_mem_phy_lanes: phy@1d87400 { +- reg = <0 0x01d87400 0 0x108>, +- <0 0x01d87600 0 0x1e0>, +- <0 0x01d87c00 0 0x1dc>, +- <0 0x01d87800 0 0x108>, +- <0 0x01d87a00 0 0x1e0>; ++ reg = <0 0x01d87400 0 0x188>, ++ <0 0x01d87600 0 0x200>, ++ <0 0x01d87c00 0 0x200>, ++ <0 0x01d87800 0 0x188>, ++ <0 0x01d87a00 0 0x200>; + #phy-cells = <0>; + #clock-cells = <0>; + }; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-ti-k3-am65-main-drop-dma-coherent-in-crypt.patch b/queue-5.15/arm64-dts-ti-k3-am65-main-drop-dma-coherent-in-crypt.patch new file mode 100644 index 00000000000..7b1bc0cc53d --- /dev/null +++ b/queue-5.15/arm64-dts-ti-k3-am65-main-drop-dma-coherent-in-crypt.patch @@ -0,0 +1,36 @@ +From 6df4689c9e9b09098f08e7fa68c2c852c07600f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 20:55:18 +0530 +Subject: arm64: dts: ti: k3-am65-main: Drop dma-coherent in crypto node + +From: Jayesh Choudhary + +[ Upstream commit b86833ab3653dbb0dc453eec4eef8615e63de4e2 ] + +crypto driver itself is not dma-coherent. So drop it. + +Fixes: b366b2409c97 ("arm64: dts: ti: k3-am6: Add crypto accelarator node") +Signed-off-by: Jayesh Choudhary +Signed-off-by: Nishanth Menon +Reviewed-by: Manorit Chawdhry +Link: https://lore.kernel.org/r/20221031152520.355653-2-j-choudhary@ti.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-am65-main.dtsi | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +index 82be00069bcd..4f232f575ab2 100644 +--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi +@@ -120,7 +120,6 @@ crypto: crypto@4e00000 { + dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>, + <&main_udmap 0x4001>; + dma-names = "tx", "rx1", "rx2"; +- dma-coherent; + + rng: rng@4e10000 { + compatible = "inside-secure,safexcel-eip76"; +-- +2.35.1 + diff --git a/queue-5.15/arm64-dts-ti-k3-j721e-main-drop-dma-coherent-in-cryp.patch b/queue-5.15/arm64-dts-ti-k3-j721e-main-drop-dma-coherent-in-cryp.patch new file mode 100644 index 00000000000..e9fcc8c0345 --- /dev/null +++ b/queue-5.15/arm64-dts-ti-k3-j721e-main-drop-dma-coherent-in-cryp.patch @@ -0,0 +1,36 @@ +From f99576e2aa101fabc40fc8c290c306073f7a7e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 20:55:19 +0530 +Subject: arm64: dts: ti: k3-j721e-main: Drop dma-coherent in crypto node + +From: Jayesh Choudhary + +[ Upstream commit 26c5012403f3f1fd3bf8f7d3389ee539ae5cc162 ] + +crypto driver itself is not dma-coherent. So drop it. + +Fixes: 8ebcaaae8017 ("arm64: dts: ti: k3-j721e-main: Add crypto accelerator node") +Signed-off-by: Jayesh Choudhary +Signed-off-by: Nishanth Menon +Reviewed-by: Manorit Chawdhry +Link: https://lore.kernel.org/r/20221031152520.355653-3-j-choudhary@ti.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j721e-main.dtsi | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +index 6c81997ee28a..ad21bb1417aa 100644 +--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +@@ -336,7 +336,6 @@ main_crypto: crypto@4e00000 { + dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>, + <&main_udmap 0x4001>; + dma-names = "tx", "rx1", "rx2"; +- dma-coherent; + + rng: rng@4e10000 { + compatible = "inside-secure,safexcel-eip76"; +-- +2.35.1 + diff --git a/queue-5.15/arm64-make-is_ttbrx_addr-noinstr-safe.patch b/queue-5.15/arm64-make-is_ttbrx_addr-noinstr-safe.patch new file mode 100644 index 00000000000..4deb2b0ca24 --- /dev/null +++ b/queue-5.15/arm64-make-is_ttbrx_addr-noinstr-safe.patch @@ -0,0 +1,52 @@ +From 42633bfd09029e6b843d56c4e257f88edaaaf40e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 14:40:42 +0000 +Subject: arm64: make is_ttbrX_addr() noinstr-safe + +From: Mark Rutland + +[ Upstream commit d8c1d798a2e5091128c391c6dadcc9be334af3f5 ] + +We use is_ttbr0_addr() in noinstr code, but as it's only marked as +inline, it's theoretically possible for the compiler to place it +out-of-line and instrument it, which would be problematic. + +Mark is_ttbr0_addr() as __always_inline such that that can safely be +used from noinstr code. For consistency, do the same to is_ttbr1_addr(). +Note that while is_ttbr1_addr() calls arch_kasan_reset_tag(), this is a +macro (and its callees are either macros or __always_inline), so there +is not a risk of transient instrumentation. + +Signed-off-by: Mark Rutland +Cc: Catalin Marinas +Cc: Will Deacon +Link: https://lore.kernel.org/r/20221114144042.3001140-1-mark.rutland@arm.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/processor.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h +index d9bf3d12a2b8..7364530de0a7 100644 +--- a/arch/arm64/include/asm/processor.h ++++ b/arch/arm64/include/asm/processor.h +@@ -240,13 +240,13 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc, + } + #endif + +-static inline bool is_ttbr0_addr(unsigned long addr) ++static __always_inline bool is_ttbr0_addr(unsigned long addr) + { + /* entry assembly clears tags for TTBR0 addrs */ + return addr < TASK_SIZE; + } + +-static inline bool is_ttbr1_addr(unsigned long addr) ++static __always_inline bool is_ttbr1_addr(unsigned long addr) + { + /* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */ + return arch_kasan_reset_tag(addr) >= PAGE_OFFSET; +-- +2.35.1 + diff --git a/queue-5.15/arm64-mm-kfence-only-handle-translation-faults.patch b/queue-5.15/arm64-mm-kfence-only-handle-translation-faults.patch new file mode 100644 index 00000000000..2ca9ffd3c26 --- /dev/null +++ b/queue-5.15/arm64-mm-kfence-only-handle-translation-faults.patch @@ -0,0 +1,66 @@ +From 3c7178d068962382789f82da493a92742c6f4768 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 10:44:11 +0000 +Subject: arm64: mm: kfence: only handle translation faults + +From: Mark Rutland + +[ Upstream commit 0bb1fbffc631064db567ccaeb9ed6b6df6342b66 ] + +Alexander noted that KFENCE only expects to handle faults from invalid page +table entries (i.e. translation faults), but arm64's fault handling logic will +call kfence_handle_page_fault() for other types of faults, including alignment +faults caused by unaligned atomics. This has the unfortunate property of +causing those other faults to be reported as "KFENCE: use-after-free", +which is misleading and hinders debugging. + +Fix this by only forwarding unhandled translation faults to the KFENCE +code, similar to what x86 does already. + +Alexander has verified that this passes all the tests in the KFENCE test +suite and avoids bogus reports on misaligned atomics. + +Link: https://lore.kernel.org/all/20221102081620.1465154-1-zhongbaisong@huawei.com/ +Fixes: 840b23986344 ("arm64, kfence: enable KFENCE for ARM64") +Signed-off-by: Mark Rutland +Reviewed-by: Alexander Potapenko +Tested-by: Alexander Potapenko +Cc: Catalin Marinas +Cc: Marco Elver +Cc: Will Deacon +Link: https://lore.kernel.org/r/20221114104411.2853040-1-mark.rutland@arm.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/mm/fault.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index e38e7dc0f8f5..d09b21faa0b2 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -350,6 +350,11 @@ static bool is_el1_mte_sync_tag_check_fault(unsigned long esr) + return false; + } + ++static bool is_translation_fault(unsigned long esr) ++{ ++ return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT; ++} ++ + static void __do_kernel_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { +@@ -382,7 +387,8 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr, + } else if (addr < PAGE_SIZE) { + msg = "NULL pointer dereference"; + } else { +- if (kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs)) ++ if (is_translation_fault(esr) && ++ kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs)) + return; + + msg = "paging request"; +-- +2.35.1 + diff --git a/queue-5.15/arm64-treat-esr_elx-as-a-64-bit-register.patch b/queue-5.15/arm64-treat-esr_elx-as-a-64-bit-register.patch new file mode 100644 index 00000000000..2526c727db5 --- /dev/null +++ b/queue-5.15/arm64-treat-esr_elx-as-a-64-bit-register.patch @@ -0,0 +1,976 @@ +From a530dabc4d349b7150a3e2d59c1a0b9d4cf17379 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Apr 2022 12:44:42 +0100 +Subject: arm64: Treat ESR_ELx as a 64-bit register + +From: Alexandru Elisei + +[ Upstream commit 8d56e5c5a99ce1d17d39ce5a8260e42c2a2d7682 ] + +In the initial release of the ARM Architecture Reference Manual for +ARMv8-A, the ESR_ELx registers were defined as 32-bit registers. This +changed in 2018 with version D.a (ARM DDI 0487D.a) of the architecture, +when they became 64-bit registers, with bits [63:32] defined as RES0. In +version G.a, a new field was added to ESR_ELx, ISS2, which covers bits +[36:32]. This field is used when the Armv8.7 extension FEAT_LS64 is +implemented. + +As a result of the evolution of the register width, Linux stores it as +both a 64-bit value and a 32-bit value, which hasn't affected correctness +so far as Linux only uses the lower 32 bits of the register. + +Make the register type consistent and always treat it as 64-bit wide. The +register is redefined as an "unsigned long", which is an unsigned +double-word (64-bit quantity) for the LP64 machine (aapcs64 [1], Table 1, +page 14). The type was chosen because "unsigned int" is the most frequent +type for ESR_ELx and because FAR_ELx, which is used together with ESR_ELx +in exception handling, is also declared as "unsigned long". The 64-bit type +also makes adding support for architectural features that use fields above +bit 31 easier in the future. + +The KVM hypervisor will receive a similar update in a subsequent patch. + +[1] https://github.com/ARM-software/abi-aa/releases/download/2021Q3/aapcs64.pdf + +Signed-off-by: Alexandru Elisei +Reviewed-by: Marc Zyngier +Link: https://lore.kernel.org/r/20220425114444.368693-4-alexandru.elisei@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: 0bb1fbffc631 ("arm64: mm: kfence: only handle translation faults") +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/debug-monitors.h | 4 +- + arch/arm64/include/asm/esr.h | 6 +-- + arch/arm64/include/asm/exception.h | 28 +++++----- + arch/arm64/include/asm/system_misc.h | 4 +- + arch/arm64/include/asm/traps.h | 12 ++--- + arch/arm64/kernel/debug-monitors.c | 12 ++--- + arch/arm64/kernel/entry-common.c | 6 +-- + arch/arm64/kernel/fpsimd.c | 6 +-- + arch/arm64/kernel/hw_breakpoint.c | 4 +- + arch/arm64/kernel/kgdb.c | 6 +-- + arch/arm64/kernel/probes/kprobes.c | 4 +- + arch/arm64/kernel/probes/uprobes.c | 4 +- + arch/arm64/kernel/traps.c | 66 +++++++++++------------ + arch/arm64/mm/fault.c | 70 ++++++++++++------------- + 14 files changed, 116 insertions(+), 116 deletions(-) + +diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h +index 657c921fd784..e1e10a24519b 100644 +--- a/arch/arm64/include/asm/debug-monitors.h ++++ b/arch/arm64/include/asm/debug-monitors.h +@@ -76,7 +76,7 @@ struct task_struct; + + struct step_hook { + struct list_head node; +- int (*fn)(struct pt_regs *regs, unsigned int esr); ++ int (*fn)(struct pt_regs *regs, unsigned long esr); + }; + + void register_user_step_hook(struct step_hook *hook); +@@ -87,7 +87,7 @@ void unregister_kernel_step_hook(struct step_hook *hook); + + struct break_hook { + struct list_head node; +- int (*fn)(struct pt_regs *regs, unsigned int esr); ++ int (*fn)(struct pt_regs *regs, unsigned long esr); + u16 imm; + u16 mask; /* These bits are ignored when comparing with imm */ + }; +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index 8f59bbeba7a7..9f91c8906edd 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -324,14 +324,14 @@ + #ifndef __ASSEMBLY__ + #include + +-static inline bool esr_is_data_abort(u32 esr) ++static inline bool esr_is_data_abort(unsigned long esr) + { +- const u32 ec = ESR_ELx_EC(esr); ++ const unsigned long ec = ESR_ELx_EC(esr); + + return ec == ESR_ELx_EC_DABT_LOW || ec == ESR_ELx_EC_DABT_CUR; + } + +-const char *esr_get_class_string(u32 esr); ++const char *esr_get_class_string(unsigned long esr); + #endif /* __ASSEMBLY */ + + #endif /* __ASM_ESR_H */ +diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h +index 339477dca551..0e6535aa78c2 100644 +--- a/arch/arm64/include/asm/exception.h ++++ b/arch/arm64/include/asm/exception.h +@@ -19,9 +19,9 @@ + #define __exception_irq_entry __kprobes + #endif + +-static inline u32 disr_to_esr(u64 disr) ++static inline unsigned long disr_to_esr(u64 disr) + { +- unsigned int esr = ESR_ELx_EC_SERROR << ESR_ELx_EC_SHIFT; ++ unsigned long esr = ESR_ELx_EC_SERROR << ESR_ELx_EC_SHIFT; + + if ((disr & DISR_EL1_IDS) == 0) + esr |= (disr & DISR_EL1_ESR_MASK); +@@ -57,23 +57,23 @@ asmlinkage void call_on_irq_stack(struct pt_regs *regs, + void (*func)(struct pt_regs *)); + asmlinkage void asm_exit_to_user_mode(struct pt_regs *regs); + +-void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs); ++void do_mem_abort(unsigned long far, unsigned long esr, struct pt_regs *regs); + void do_undefinstr(struct pt_regs *regs); + void do_bti(struct pt_regs *regs); +-void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr, ++void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr, + struct pt_regs *regs); +-void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs); +-void do_sve_acc(unsigned int esr, struct pt_regs *regs); +-void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs); +-void do_sysinstr(unsigned int esr, struct pt_regs *regs); +-void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); +-void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr); +-void do_cp15instr(unsigned int esr, struct pt_regs *regs); ++void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs); ++void do_sve_acc(unsigned long esr, struct pt_regs *regs); ++void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs); ++void do_sysinstr(unsigned long esr, struct pt_regs *regs); ++void do_sp_pc_abort(unsigned long addr, unsigned long esr, struct pt_regs *regs); ++void bad_el0_sync(struct pt_regs *regs, int reason, unsigned long esr); ++void do_cp15instr(unsigned long esr, struct pt_regs *regs); + void do_el0_svc(struct pt_regs *regs); + void do_el0_svc_compat(struct pt_regs *regs); +-void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr); +-void do_serror(struct pt_regs *regs, unsigned int esr); ++void do_ptrauth_fault(struct pt_regs *regs, unsigned long esr); ++void do_serror(struct pt_regs *regs, unsigned long esr); + void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags); + +-void panic_bad_stack(struct pt_regs *regs, unsigned int esr, unsigned long far); ++void panic_bad_stack(struct pt_regs *regs, unsigned long esr, unsigned long far); + #endif /* __ASM_EXCEPTION_H */ +diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h +index 305a7157c6a6..0eb7709422e2 100644 +--- a/arch/arm64/include/asm/system_misc.h ++++ b/arch/arm64/include/asm/system_misc.h +@@ -23,9 +23,9 @@ void die(const char *msg, struct pt_regs *regs, int err); + struct siginfo; + void arm64_notify_die(const char *str, struct pt_regs *regs, + int signo, int sicode, unsigned long far, +- int err); ++ unsigned long err); + +-void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, ++void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned long, + struct pt_regs *), + int sig, int code, const char *name); + +diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h +index 54f32a0675df..6e5826470bea 100644 +--- a/arch/arm64/include/asm/traps.h ++++ b/arch/arm64/include/asm/traps.h +@@ -24,7 +24,7 @@ struct undef_hook { + + void register_undef_hook(struct undef_hook *hook); + void unregister_undef_hook(struct undef_hook *hook); +-void force_signal_inject(int signal, int code, unsigned long address, unsigned int err); ++void force_signal_inject(int signal, int code, unsigned long address, unsigned long err); + void arm64_notify_segfault(unsigned long addr); + void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str); + void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str); +@@ -57,7 +57,7 @@ static inline int in_entry_text(unsigned long ptr) + * errors share the same encoding as an all-zeros encoding from a CPU that + * doesn't support RAS. + */ +-static inline bool arm64_is_ras_serror(u32 esr) ++static inline bool arm64_is_ras_serror(unsigned long esr) + { + WARN_ON(preemptible()); + +@@ -77,9 +77,9 @@ static inline bool arm64_is_ras_serror(u32 esr) + * We treat them as Uncontainable. + * Non-RAS SError's are reported as Uncontained/Uncategorized. + */ +-static inline u32 arm64_ras_serror_get_severity(u32 esr) ++static inline unsigned long arm64_ras_serror_get_severity(unsigned long esr) + { +- u32 aet = esr & ESR_ELx_AET; ++ unsigned long aet = esr & ESR_ELx_AET; + + if (!arm64_is_ras_serror(esr)) { + /* Not a RAS error, we can't interpret the ESR. */ +@@ -98,6 +98,6 @@ static inline u32 arm64_ras_serror_get_severity(u32 esr) + return aet; + } + +-bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr); +-void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr); ++bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned long esr); ++void __noreturn arm64_serror_panic(struct pt_regs *regs, unsigned long esr); + #endif +diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c +index 4f3661eeb7ec..bf9fe71589bc 100644 +--- a/arch/arm64/kernel/debug-monitors.c ++++ b/arch/arm64/kernel/debug-monitors.c +@@ -202,7 +202,7 @@ void unregister_kernel_step_hook(struct step_hook *hook) + * So we call all the registered handlers, until the right handler is + * found which returns zero. + */ +-static int call_step_hook(struct pt_regs *regs, unsigned int esr) ++static int call_step_hook(struct pt_regs *regs, unsigned long esr) + { + struct step_hook *hook; + struct list_head *list; +@@ -238,7 +238,7 @@ static void send_user_sigtrap(int si_code) + "User debug trap"); + } + +-static int single_step_handler(unsigned long unused, unsigned int esr, ++static int single_step_handler(unsigned long unused, unsigned long esr, + struct pt_regs *regs) + { + bool handler_found = false; +@@ -299,11 +299,11 @@ void unregister_kernel_break_hook(struct break_hook *hook) + unregister_debug_hook(&hook->node); + } + +-static int call_break_hook(struct pt_regs *regs, unsigned int esr) ++static int call_break_hook(struct pt_regs *regs, unsigned long esr) + { + struct break_hook *hook; + struct list_head *list; +- int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL; ++ int (*fn)(struct pt_regs *regs, unsigned long esr) = NULL; + + list = user_mode(regs) ? &user_break_hook : &kernel_break_hook; + +@@ -312,7 +312,7 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr) + * entirely not preemptible, and we can use rcu list safely here. + */ + list_for_each_entry_rcu(hook, list, node) { +- unsigned int comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK; ++ unsigned long comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK; + + if ((comment & ~hook->mask) == hook->imm) + fn = hook->fn; +@@ -322,7 +322,7 @@ static int call_break_hook(struct pt_regs *regs, unsigned int esr) + } + NOKPROBE_SYMBOL(call_break_hook); + +-static int brk_handler(unsigned long unused, unsigned int esr, ++static int brk_handler(unsigned long unused, unsigned long esr, + struct pt_regs *regs) + { + if (call_break_hook(regs, esr) == DBG_HOOK_HANDLED) +diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c +index 8ecca795aca0..fc91dad1579a 100644 +--- a/arch/arm64/kernel/entry-common.c ++++ b/arch/arm64/kernel/entry-common.c +@@ -273,13 +273,13 @@ extern void (*handle_arch_irq)(struct pt_regs *); + extern void (*handle_arch_fiq)(struct pt_regs *); + + static void noinstr __panic_unhandled(struct pt_regs *regs, const char *vector, +- unsigned int esr) ++ unsigned long esr) + { + arm64_enter_nmi(regs); + + console_verbose(); + +- pr_crit("Unhandled %s exception on CPU%d, ESR 0x%08x -- %s\n", ++ pr_crit("Unhandled %s exception on CPU%d, ESR 0x%016lx -- %s\n", + vector, smp_processor_id(), esr, + esr_get_class_string(esr)); + +@@ -796,7 +796,7 @@ UNHANDLED(el0t, 32, error) + #ifdef CONFIG_VMAP_STACK + asmlinkage void noinstr handle_bad_stack(struct pt_regs *regs) + { +- unsigned int esr = read_sysreg(esr_el1); ++ unsigned long esr = read_sysreg(esr_el1); + unsigned long far = read_sysreg(far_el1); + + arm64_enter_nmi(regs); +diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c +index ff4962750b3d..7a3fcf21b18a 100644 +--- a/arch/arm64/kernel/fpsimd.c ++++ b/arch/arm64/kernel/fpsimd.c +@@ -930,7 +930,7 @@ void fpsimd_release_task(struct task_struct *dead_task) + * would have disabled the SVE access trap for userspace during + * ret_to_user, making an SVE access trap impossible in that case. + */ +-void do_sve_acc(unsigned int esr, struct pt_regs *regs) ++void do_sve_acc(unsigned long esr, struct pt_regs *regs) + { + /* Even if we chose not to use SVE, the hardware could still trap: */ + if (unlikely(!system_supports_sve()) || WARN_ON(is_compat_task())) { +@@ -972,7 +972,7 @@ void do_sve_acc(unsigned int esr, struct pt_regs *regs) + /* + * Trapped FP/ASIMD access. + */ +-void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) ++void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs) + { + /* TODO: implement lazy context saving/restoring */ + WARN_ON(1); +@@ -981,7 +981,7 @@ void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs) + /* + * Raise a SIGFPE for the current process. + */ +-void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs) ++void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs) + { + unsigned int si_code = FPE_FLTUNK; + +diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c +index 712e97c03e54..2a7f21314cde 100644 +--- a/arch/arm64/kernel/hw_breakpoint.c ++++ b/arch/arm64/kernel/hw_breakpoint.c +@@ -617,7 +617,7 @@ NOKPROBE_SYMBOL(toggle_bp_registers); + /* + * Debug exception handlers. + */ +-static int breakpoint_handler(unsigned long unused, unsigned int esr, ++static int breakpoint_handler(unsigned long unused, unsigned long esr, + struct pt_regs *regs) + { + int i, step = 0, *kernel_step; +@@ -751,7 +751,7 @@ static int watchpoint_report(struct perf_event *wp, unsigned long addr, + return step; + } + +-static int watchpoint_handler(unsigned long addr, unsigned int esr, ++static int watchpoint_handler(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { + int i, step = 0, *kernel_step, access, closest_match = 0; +diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c +index 2aede780fb80..cda9c1e9864f 100644 +--- a/arch/arm64/kernel/kgdb.c ++++ b/arch/arm64/kernel/kgdb.c +@@ -232,14 +232,14 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, + return err; + } + +-static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) ++static int kgdb_brk_fn(struct pt_regs *regs, unsigned long esr) + { + kgdb_handle_exception(1, SIGTRAP, 0, regs); + return DBG_HOOK_HANDLED; + } + NOKPROBE_SYMBOL(kgdb_brk_fn) + +-static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) ++static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned long esr) + { + compiled_break = 1; + kgdb_handle_exception(1, SIGTRAP, 0, regs); +@@ -248,7 +248,7 @@ static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) + } + NOKPROBE_SYMBOL(kgdb_compiled_brk_fn); + +-static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) ++static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned long esr) + { + if (!kgdb_single_step) + return DBG_HOOK_ERROR; +diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c +index 6dbcc89f6662..b7404dba0d62 100644 +--- a/arch/arm64/kernel/probes/kprobes.c ++++ b/arch/arm64/kernel/probes/kprobes.c +@@ -332,7 +332,7 @@ static void __kprobes kprobe_handler(struct pt_regs *regs) + } + + static int __kprobes +-kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr) ++kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr) + { + struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + unsigned long addr = instruction_pointer(regs); +@@ -356,7 +356,7 @@ static struct break_hook kprobes_break_ss_hook = { + }; + + static int __kprobes +-kprobe_breakpoint_handler(struct pt_regs *regs, unsigned int esr) ++kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr) + { + kprobe_handler(regs); + return DBG_HOOK_HANDLED; +diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c +index 9be668f3f034..d49aef2657cd 100644 +--- a/arch/arm64/kernel/probes/uprobes.c ++++ b/arch/arm64/kernel/probes/uprobes.c +@@ -166,7 +166,7 @@ int arch_uprobe_exception_notify(struct notifier_block *self, + } + + static int uprobe_breakpoint_handler(struct pt_regs *regs, +- unsigned int esr) ++ unsigned long esr) + { + if (uprobe_pre_sstep_notifier(regs)) + return DBG_HOOK_HANDLED; +@@ -175,7 +175,7 @@ static int uprobe_breakpoint_handler(struct pt_regs *regs, + } + + static int uprobe_single_step_handler(struct pt_regs *regs, +- unsigned int esr) ++ unsigned long esr) + { + struct uprobe_task *utask = current->utask; + +diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c +index fe0cd0568813..f859cc870d5b 100644 +--- a/arch/arm64/kernel/traps.c ++++ b/arch/arm64/kernel/traps.c +@@ -243,7 +243,7 @@ static void arm64_show_signal(int signo, const char *str) + static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); + struct task_struct *tsk = current; +- unsigned int esr = tsk->thread.fault_code; ++ unsigned long esr = tsk->thread.fault_code; + struct pt_regs *regs = task_pt_regs(tsk); + + /* Leave if the signal won't be shown */ +@@ -254,7 +254,7 @@ static void arm64_show_signal(int signo, const char *str) + + pr_info("%s[%d]: unhandled exception: ", tsk->comm, task_pid_nr(tsk)); + if (esr) +- pr_cont("%s, ESR 0x%08x, ", esr_get_class_string(esr), esr); ++ pr_cont("%s, ESR 0x%016lx, ", esr_get_class_string(esr), esr); + + pr_cont("%s", str); + print_vma_addr(KERN_CONT " in ", regs->pc); +@@ -288,7 +288,7 @@ void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, + + void arm64_notify_die(const char *str, struct pt_regs *regs, + int signo, int sicode, unsigned long far, +- int err) ++ unsigned long err) + { + if (user_mode(regs)) { + WARN_ON(regs != current_pt_regs()); +@@ -440,7 +440,7 @@ static int call_undef_hook(struct pt_regs *regs) + return fn ? fn(regs, instr) : 1; + } + +-void force_signal_inject(int signal, int code, unsigned long address, unsigned int err) ++void force_signal_inject(int signal, int code, unsigned long address, unsigned long err) + { + const char *desc; + struct pt_regs *regs = current_pt_regs(); +@@ -507,7 +507,7 @@ void do_bti(struct pt_regs *regs) + } + NOKPROBE_SYMBOL(do_bti); + +-void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr) ++void do_ptrauth_fault(struct pt_regs *regs, unsigned long esr) + { + /* + * Unexpected FPAC exception or pointer authentication failure in +@@ -538,7 +538,7 @@ NOKPROBE_SYMBOL(do_ptrauth_fault); + uaccess_ttbr0_disable(); \ + } + +-static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) ++static void user_cache_maint_handler(unsigned long esr, struct pt_regs *regs) + { + unsigned long tagged_address, address; + int rt = ESR_ELx_SYS64_ISS_RT(esr); +@@ -578,7 +578,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } + +-static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) ++static void ctr_read_handler(unsigned long esr, struct pt_regs *regs) + { + int rt = ESR_ELx_SYS64_ISS_RT(esr); + unsigned long val = arm64_ftr_reg_user_value(&arm64_ftr_reg_ctrel0); +@@ -597,7 +597,7 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } + +-static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) ++static void cntvct_read_handler(unsigned long esr, struct pt_regs *regs) + { + int rt = ESR_ELx_SYS64_ISS_RT(esr); + +@@ -605,7 +605,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } + +-static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) ++static void cntfrq_read_handler(unsigned long esr, struct pt_regs *regs) + { + int rt = ESR_ELx_SYS64_ISS_RT(esr); + +@@ -613,7 +613,7 @@ static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } + +-static void mrs_handler(unsigned int esr, struct pt_regs *regs) ++static void mrs_handler(unsigned long esr, struct pt_regs *regs) + { + u32 sysreg, rt; + +@@ -624,15 +624,15 @@ static void mrs_handler(unsigned int esr, struct pt_regs *regs) + force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0); + } + +-static void wfi_handler(unsigned int esr, struct pt_regs *regs) ++static void wfi_handler(unsigned long esr, struct pt_regs *regs) + { + arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); + } + + struct sys64_hook { +- unsigned int esr_mask; +- unsigned int esr_val; +- void (*handler)(unsigned int esr, struct pt_regs *regs); ++ unsigned long esr_mask; ++ unsigned long esr_val; ++ void (*handler)(unsigned long esr, struct pt_regs *regs); + }; + + static const struct sys64_hook sys64_hooks[] = { +@@ -675,7 +675,7 @@ static const struct sys64_hook sys64_hooks[] = { + }; + + #ifdef CONFIG_COMPAT +-static bool cp15_cond_valid(unsigned int esr, struct pt_regs *regs) ++static bool cp15_cond_valid(unsigned long esr, struct pt_regs *regs) + { + int cond; + +@@ -695,7 +695,7 @@ static bool cp15_cond_valid(unsigned int esr, struct pt_regs *regs) + return aarch32_opcode_cond_checks[cond](regs->pstate); + } + +-static void compat_cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) ++static void compat_cntfrq_read_handler(unsigned long esr, struct pt_regs *regs) + { + int reg = (esr & ESR_ELx_CP15_32_ISS_RT_MASK) >> ESR_ELx_CP15_32_ISS_RT_SHIFT; + +@@ -712,7 +712,7 @@ static const struct sys64_hook cp15_32_hooks[] = { + {}, + }; + +-static void compat_cntvct_read_handler(unsigned int esr, struct pt_regs *regs) ++static void compat_cntvct_read_handler(unsigned long esr, struct pt_regs *regs) + { + int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT; + int rt2 = (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT; +@@ -732,7 +732,7 @@ static const struct sys64_hook cp15_64_hooks[] = { + {}, + }; + +-void do_cp15instr(unsigned int esr, struct pt_regs *regs) ++void do_cp15instr(unsigned long esr, struct pt_regs *regs) + { + const struct sys64_hook *hook, *hook_base; + +@@ -773,7 +773,7 @@ void do_cp15instr(unsigned int esr, struct pt_regs *regs) + NOKPROBE_SYMBOL(do_cp15instr); + #endif + +-void do_sysinstr(unsigned int esr, struct pt_regs *regs) ++void do_sysinstr(unsigned long esr, struct pt_regs *regs) + { + const struct sys64_hook *hook; + +@@ -837,7 +837,7 @@ static const char *esr_class_str[] = { + [ESR_ELx_EC_BRK64] = "BRK (AArch64)", + }; + +-const char *esr_get_class_string(u32 esr) ++const char *esr_get_class_string(unsigned long esr) + { + return esr_class_str[ESR_ELx_EC(esr)]; + } +@@ -846,7 +846,7 @@ const char *esr_get_class_string(u32 esr) + * bad_el0_sync handles unexpected, but potentially recoverable synchronous + * exceptions taken from EL0. + */ +-void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) ++void bad_el0_sync(struct pt_regs *regs, int reason, unsigned long esr) + { + unsigned long pc = instruction_pointer(regs); + +@@ -862,7 +862,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) + DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack) + __aligned(16); + +-void panic_bad_stack(struct pt_regs *regs, unsigned int esr, unsigned long far) ++void panic_bad_stack(struct pt_regs *regs, unsigned long esr, unsigned long far) + { + unsigned long tsk_stk = (unsigned long)current->stack; + unsigned long irq_stk = (unsigned long)this_cpu_read(irq_stack_ptr); +@@ -871,7 +871,7 @@ void panic_bad_stack(struct pt_regs *regs, unsigned int esr, unsigned long far) + console_verbose(); + pr_emerg("Insufficient stack space to handle exception!"); + +- pr_emerg("ESR: 0x%08x -- %s\n", esr, esr_get_class_string(esr)); ++ pr_emerg("ESR: 0x%016lx -- %s\n", esr, esr_get_class_string(esr)); + pr_emerg("FAR: 0x%016lx\n", far); + + pr_emerg("Task stack: [0x%016lx..0x%016lx]\n", +@@ -892,11 +892,11 @@ void panic_bad_stack(struct pt_regs *regs, unsigned int esr, unsigned long far) + } + #endif + +-void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr) ++void __noreturn arm64_serror_panic(struct pt_regs *regs, unsigned long esr) + { + console_verbose(); + +- pr_crit("SError Interrupt on CPU%d, code 0x%08x -- %s\n", ++ pr_crit("SError Interrupt on CPU%d, code 0x%016lx -- %s\n", + smp_processor_id(), esr, esr_get_class_string(esr)); + if (regs) + __show_regs(regs); +@@ -907,9 +907,9 @@ void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr) + unreachable(); + } + +-bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) ++bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned long esr) + { +- u32 aet = arm64_ras_serror_get_severity(esr); ++ unsigned long aet = arm64_ras_serror_get_severity(esr); + + switch (aet) { + case ESR_ELx_AET_CE: /* corrected error */ +@@ -939,7 +939,7 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) + } + } + +-void do_serror(struct pt_regs *regs, unsigned int esr) ++void do_serror(struct pt_regs *regs, unsigned long esr) + { + /* non-RAS errors are not containable */ + if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr)) +@@ -960,7 +960,7 @@ int is_valid_bugaddr(unsigned long addr) + return 1; + } + +-static int bug_handler(struct pt_regs *regs, unsigned int esr) ++static int bug_handler(struct pt_regs *regs, unsigned long esr) + { + switch (report_bug(regs->pc, regs)) { + case BUG_TRAP_TYPE_BUG: +@@ -985,7 +985,7 @@ static struct break_hook bug_break_hook = { + .imm = BUG_BRK_IMM, + }; + +-static int reserved_fault_handler(struct pt_regs *regs, unsigned int esr) ++static int reserved_fault_handler(struct pt_regs *regs, unsigned long esr) + { + pr_err("%s generated an invalid instruction at %pS!\n", + "Kernel text patching", +@@ -1007,7 +1007,7 @@ static struct break_hook fault_break_hook = { + #define KASAN_ESR_SIZE_MASK 0x0f + #define KASAN_ESR_SIZE(esr) (1 << ((esr) & KASAN_ESR_SIZE_MASK)) + +-static int kasan_handler(struct pt_regs *regs, unsigned int esr) ++static int kasan_handler(struct pt_regs *regs, unsigned long esr) + { + bool recover = esr & KASAN_ESR_RECOVER; + bool write = esr & KASAN_ESR_WRITE; +@@ -1050,11 +1050,11 @@ static struct break_hook kasan_break_hook = { + * Initial handler for AArch64 BRK exceptions + * This handler only used until debug_traps_init(). + */ +-int __init early_brk64(unsigned long addr, unsigned int esr, ++int __init early_brk64(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { + #ifdef CONFIG_KASAN_SW_TAGS +- unsigned int comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK; ++ unsigned long comment = esr & ESR_ELx_BRK64_ISS_COMMENT_MASK; + + if ((comment & ~KASAN_BRK_MASK) == KASAN_BRK_IMM) + return kasan_handler(regs, esr) != DBG_HOOK_HANDLED; +diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c +index 9ae24e3b72be..e38e7dc0f8f5 100644 +--- a/arch/arm64/mm/fault.c ++++ b/arch/arm64/mm/fault.c +@@ -43,7 +43,7 @@ + #include + + struct fault_info { +- int (*fn)(unsigned long far, unsigned int esr, ++ int (*fn)(unsigned long far, unsigned long esr, + struct pt_regs *regs); + int sig; + int code; +@@ -53,17 +53,17 @@ struct fault_info { + static const struct fault_info fault_info[]; + static struct fault_info debug_fault_info[]; + +-static inline const struct fault_info *esr_to_fault_info(unsigned int esr) ++static inline const struct fault_info *esr_to_fault_info(unsigned long esr) + { + return fault_info + (esr & ESR_ELx_FSC); + } + +-static inline const struct fault_info *esr_to_debug_fault_info(unsigned int esr) ++static inline const struct fault_info *esr_to_debug_fault_info(unsigned long esr) + { + return debug_fault_info + DBG_ESR_EVT(esr); + } + +-static void data_abort_decode(unsigned int esr) ++static void data_abort_decode(unsigned long esr) + { + pr_alert("Data abort info:\n"); + +@@ -85,11 +85,11 @@ static void data_abort_decode(unsigned int esr) + (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT); + } + +-static void mem_abort_decode(unsigned int esr) ++static void mem_abort_decode(unsigned long esr) + { + pr_alert("Mem abort info:\n"); + +- pr_alert(" ESR = 0x%08x\n", esr); ++ pr_alert(" ESR = 0x%016lx\n", esr); + pr_alert(" EC = 0x%02lx: %s, IL = %u bits\n", + ESR_ELx_EC(esr), esr_get_class_string(esr), + (esr & ESR_ELx_IL) ? 32 : 16); +@@ -99,7 +99,7 @@ static void mem_abort_decode(unsigned int esr) + pr_alert(" EA = %lu, S1PTW = %lu\n", + (esr & ESR_ELx_EA) >> ESR_ELx_EA_SHIFT, + (esr & ESR_ELx_S1PTW) >> ESR_ELx_S1PTW_SHIFT); +- pr_alert(" FSC = 0x%02x: %s\n", (esr & ESR_ELx_FSC), ++ pr_alert(" FSC = 0x%02lx: %s\n", (esr & ESR_ELx_FSC), + esr_to_fault_info(esr)->name); + + if (esr_is_data_abort(esr)) +@@ -229,20 +229,20 @@ int ptep_set_access_flags(struct vm_area_struct *vma, + return 1; + } + +-static bool is_el1_instruction_abort(unsigned int esr) ++static bool is_el1_instruction_abort(unsigned long esr) + { + return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR; + } + +-static bool is_el1_data_abort(unsigned int esr) ++static bool is_el1_data_abort(unsigned long esr) + { + return ESR_ELx_EC(esr) == ESR_ELx_EC_DABT_CUR; + } + +-static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr, ++static inline bool is_el1_permission_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { +- unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; ++ unsigned long fsc_type = esr & ESR_ELx_FSC_TYPE; + + if (!is_el1_data_abort(esr) && !is_el1_instruction_abort(esr)) + return false; +@@ -258,7 +258,7 @@ static inline bool is_el1_permission_fault(unsigned long addr, unsigned int esr, + } + + static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr, +- unsigned int esr, ++ unsigned long esr, + struct pt_regs *regs) + { + unsigned long flags; +@@ -290,7 +290,7 @@ static bool __kprobes is_spurious_el1_translation_fault(unsigned long addr, + } + + static void die_kernel_fault(const char *msg, unsigned long addr, +- unsigned int esr, struct pt_regs *regs) ++ unsigned long esr, struct pt_regs *regs) + { + bust_spinlocks(1); + +@@ -306,7 +306,7 @@ static void die_kernel_fault(const char *msg, unsigned long addr, + } + + #ifdef CONFIG_KASAN_HW_TAGS +-static void report_tag_fault(unsigned long addr, unsigned int esr, ++static void report_tag_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { + /* +@@ -318,11 +318,11 @@ static void report_tag_fault(unsigned long addr, unsigned int esr, + } + #else + /* Tag faults aren't enabled without CONFIG_KASAN_HW_TAGS. */ +-static inline void report_tag_fault(unsigned long addr, unsigned int esr, ++static inline void report_tag_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) { } + #endif + +-static void do_tag_recovery(unsigned long addr, unsigned int esr, ++static void do_tag_recovery(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { + +@@ -337,9 +337,9 @@ static void do_tag_recovery(unsigned long addr, unsigned int esr, + isb(); + } + +-static bool is_el1_mte_sync_tag_check_fault(unsigned int esr) ++static bool is_el1_mte_sync_tag_check_fault(unsigned long esr) + { +- unsigned int fsc = esr & ESR_ELx_FSC; ++ unsigned long fsc = esr & ESR_ELx_FSC; + + if (!is_el1_data_abort(esr)) + return false; +@@ -350,7 +350,7 @@ static bool is_el1_mte_sync_tag_check_fault(unsigned int esr) + return false; + } + +-static void __do_kernel_fault(unsigned long addr, unsigned int esr, ++static void __do_kernel_fault(unsigned long addr, unsigned long esr, + struct pt_regs *regs) + { + const char *msg; +@@ -391,7 +391,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, + die_kernel_fault(msg, addr, esr, regs); + } + +-static void set_thread_esr(unsigned long address, unsigned int esr) ++static void set_thread_esr(unsigned long address, unsigned long esr) + { + current->thread.fault_address = address; + +@@ -439,7 +439,7 @@ static void set_thread_esr(unsigned long address, unsigned int esr) + * exception level). Fail safe by not providing an ESR + * context record at all. + */ +- WARN(1, "ESR 0x%x is not DABT or IABT from EL0\n", esr); ++ WARN(1, "ESR 0x%lx is not DABT or IABT from EL0\n", esr); + esr = 0; + break; + } +@@ -448,7 +448,7 @@ static void set_thread_esr(unsigned long address, unsigned int esr) + current->thread.fault_code = esr; + } + +-static void do_bad_area(unsigned long far, unsigned int esr, ++static void do_bad_area(unsigned long far, unsigned long esr, + struct pt_regs *regs) + { + unsigned long addr = untagged_addr(far); +@@ -499,7 +499,7 @@ static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, + return handle_mm_fault(vma, addr, mm_flags, regs); + } + +-static bool is_el0_instruction_abort(unsigned int esr) ++static bool is_el0_instruction_abort(unsigned long esr) + { + return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; + } +@@ -508,12 +508,12 @@ static bool is_el0_instruction_abort(unsigned int esr) + * Note: not valid for EL1 DC IVAC, but we never use that such that it + * should fault. EL0 cannot issue DC IVAC (undef). + */ +-static bool is_write_abort(unsigned int esr) ++static bool is_write_abort(unsigned long esr) + { + return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); + } + +-static int __kprobes do_page_fault(unsigned long far, unsigned int esr, ++static int __kprobes do_page_fault(unsigned long far, unsigned long esr, + struct pt_regs *regs) + { + const struct fault_info *inf; +@@ -671,7 +671,7 @@ static int __kprobes do_page_fault(unsigned long far, unsigned int esr, + } + + static int __kprobes do_translation_fault(unsigned long far, +- unsigned int esr, ++ unsigned long esr, + struct pt_regs *regs) + { + unsigned long addr = untagged_addr(far); +@@ -683,19 +683,19 @@ static int __kprobes do_translation_fault(unsigned long far, + return 0; + } + +-static int do_alignment_fault(unsigned long far, unsigned int esr, ++static int do_alignment_fault(unsigned long far, unsigned long esr, + struct pt_regs *regs) + { + do_bad_area(far, esr, regs); + return 0; + } + +-static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs) ++static int do_bad(unsigned long far, unsigned long esr, struct pt_regs *regs) + { + return 1; /* "fault" */ + } + +-static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs) ++static int do_sea(unsigned long far, unsigned long esr, struct pt_regs *regs) + { + const struct fault_info *inf; + unsigned long siaddr; +@@ -725,7 +725,7 @@ static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs) + return 0; + } + +-static int do_tag_check_fault(unsigned long far, unsigned int esr, ++static int do_tag_check_fault(unsigned long far, unsigned long esr, + struct pt_regs *regs) + { + /* +@@ -805,7 +805,7 @@ static const struct fault_info fault_info[] = { + { do_bad, SIGKILL, SI_KERNEL, "unknown 63" }, + }; + +-void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs) ++void do_mem_abort(unsigned long far, unsigned long esr, struct pt_regs *regs) + { + const struct fault_info *inf = esr_to_fault_info(esr); + unsigned long addr = untagged_addr(far); +@@ -828,14 +828,14 @@ void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs) + } + NOKPROBE_SYMBOL(do_mem_abort); + +-void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) ++void do_sp_pc_abort(unsigned long addr, unsigned long esr, struct pt_regs *regs) + { + arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN, + addr, esr); + } + NOKPROBE_SYMBOL(do_sp_pc_abort); + +-int __init early_brk64(unsigned long addr, unsigned int esr, ++int __init early_brk64(unsigned long addr, unsigned long esr, + struct pt_regs *regs); + + /* +@@ -855,7 +855,7 @@ static struct fault_info __refdata debug_fault_info[] = { + }; + + void __init hook_debug_fault_code(int nr, +- int (*fn)(unsigned long, unsigned int, struct pt_regs *), ++ int (*fn)(unsigned long, unsigned long, struct pt_regs *), + int sig, int code, const char *name) + { + BUG_ON(nr < 0 || nr >= ARRAY_SIZE(debug_fault_info)); +@@ -888,7 +888,7 @@ static void debug_exception_exit(struct pt_regs *regs) + } + NOKPROBE_SYMBOL(debug_exception_exit); + +-void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr, ++void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr, + struct pt_regs *regs) + { + const struct fault_info *inf = esr_to_debug_fault_info(esr); +-- +2.35.1 + diff --git a/queue-5.15/asoc-codecs-rt298-add-quirk-for-kbl-r-rvp-platform.patch b/queue-5.15/asoc-codecs-rt298-add-quirk-for-kbl-r-rvp-platform.patch new file mode 100644 index 00000000000..33ab2edcc2a --- /dev/null +++ b/queue-5.15/asoc-codecs-rt298-add-quirk-for-kbl-r-rvp-platform.patch @@ -0,0 +1,45 @@ +From bb133bec78213256a7edc5fa16a4b6f0092cfb21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 14:19:43 +0200 +Subject: ASoC: codecs: rt298: Add quirk for KBL-R RVP platform +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Amadeusz Sławiński + +[ Upstream commit 953dbd1cef18ce9ac0d69c1bd735b929fe52a17e ] + +KBL-R RVP platforms also use combojack, so we need to enable that +configuration for them. + +Signed-off-by: Amadeusz Sławiński +Signed-off-by: Cezary Rojewski +Link: https://lore.kernel.org/r/20221010121955.718168-4-cezary.rojewski@intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/rt298.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c +index c592c40a7ab3..604754e4b29f 100644 +--- a/sound/soc/codecs/rt298.c ++++ b/sound/soc/codecs/rt298.c +@@ -1173,6 +1173,13 @@ static const struct dmi_system_id force_combo_jack_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "Geminilake") + } + }, ++ { ++ .ident = "Intel Kabylake R RVP", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Kabylake Client platform") ++ } ++ }, + { } + }; + +-- +2.35.1 + diff --git a/queue-5.15/asoc-dt-bindings-wcd9335-fix-reset-line-polarity-in-.patch b/queue-5.15/asoc-dt-bindings-wcd9335-fix-reset-line-polarity-in-.patch new file mode 100644 index 00000000000..0d7c2859434 --- /dev/null +++ b/queue-5.15/asoc-dt-bindings-wcd9335-fix-reset-line-polarity-in-.patch @@ -0,0 +1,39 @@ +From d3f288f1e58adf9c9d0dd7da3f1063367d3ecb22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 00:46:48 -0700 +Subject: ASoC: dt-bindings: wcd9335: fix reset line polarity in example + +From: Dmitry Torokhov + +[ Upstream commit 34cb111f8a7b98b5fec809dd194003bca20ef1b2 ] + +When resetting the block, the reset line is being driven low and then +high, which means that the line in DTS should be annotated as "active +low". + +Fixes: 1877c9fda1b7 ("ASoC: dt-bindings: add dt bindings for wcd9335 audio codec") +Signed-off-by: Dmitry Torokhov +Acked-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20221027074652.1044235-2-dmitry.torokhov@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + Documentation/devicetree/bindings/sound/qcom,wcd9335.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt +index 5d6ea66a863f..1f75feec3dec 100644 +--- a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt ++++ b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt +@@ -109,7 +109,7 @@ audio-codec@1{ + reg = <1 0>; + interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "intr2" +- reset-gpios = <&msmgpio 64 0>; ++ reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>; + slim-ifc-dev = <&wc9335_ifd>; + clock-names = "mclk", "native"; + clocks = <&rpmcc RPM_SMD_DIV_CLK1>, +-- +2.35.1 + diff --git a/queue-5.15/asoc-mediatek-mt8173-enable-irq-when-pdata-is-ready.patch b/queue-5.15/asoc-mediatek-mt8173-enable-irq-when-pdata-is-ready.patch new file mode 100644 index 00000000000..d4cf1ac774d --- /dev/null +++ b/queue-5.15/asoc-mediatek-mt8173-enable-irq-when-pdata-is-ready.patch @@ -0,0 +1,71 @@ +From efd9e135a3675a24361d789f9fda396aaa63845d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 11:49:16 +0100 +Subject: ASoC: mediatek: mt8173: Enable IRQ when pdata is ready + +From: Ricardo Ribalda + +[ Upstream commit 4cbb264d4e9136acab2c8fd39e39ab1b1402b84b ] + +If the device does not come straight from reset, we might receive an IRQ +before we are ready to handle it. + +Fixes: + +[ 2.334737] Unable to handle kernel read from unreadable memory at virtual address 00000000000001e4 +[ 2.522601] Call trace: +[ 2.525040] regmap_read+0x1c/0x80 +[ 2.528434] mt8173_afe_irq_handler+0x40/0xf0 +... +[ 2.598921] start_kernel+0x338/0x42c + +Signed-off-by: Ricardo Ribalda +Fixes: ee0bcaff109f ("ASoC: mediatek: Add AFE platform driver") +Link: https://lore.kernel.org/r/20221128-mt8173-afe-v1-0-70728221628f@chromium.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +index 31494930433f..8092506facbd 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c ++++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +@@ -1072,16 +1072,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + + afe->dev = &pdev->dev; + +- irq_id = platform_get_irq(pdev, 0); +- if (irq_id <= 0) +- return irq_id < 0 ? irq_id : -ENXIO; +- ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, +- 0, "Afe_ISR_Handle", (void *)afe); +- if (ret) { +- dev_err(afe->dev, "could not request_irq\n"); +- return ret; +- } +- + afe->base_addr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(afe->base_addr)) + return PTR_ERR(afe->base_addr); +@@ -1187,6 +1177,16 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + if (ret) + goto err_cleanup_components; + ++ irq_id = platform_get_irq(pdev, 0); ++ if (irq_id <= 0) ++ return irq_id < 0 ? irq_id : -ENXIO; ++ ret = devm_request_irq(afe->dev, irq_id, mt8173_afe_irq_handler, ++ 0, "Afe_ISR_Handle", (void *)afe); ++ if (ret) { ++ dev_err(afe->dev, "could not request_irq\n"); ++ goto err_pm_disable; ++ } ++ + dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n"); + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/asoc-mediatek-mt8173-fix-debugfs-registration-for-co.patch b/queue-5.15/asoc-mediatek-mt8173-fix-debugfs-registration-for-co.patch new file mode 100644 index 00000000000..7b201426716 --- /dev/null +++ b/queue-5.15/asoc-mediatek-mt8173-fix-debugfs-registration-for-co.patch @@ -0,0 +1,117 @@ +From 84dccacbd40bb42adc7acc5095f31601792c44d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Nov 2021 17:11:08 +0100 +Subject: ASoC: mediatek: mt8173: Fix debugfs registration for components + +From: AngeloGioacchino Del Regno + +[ Upstream commit 8c32984bc7da29828260ac514d5d4967f7e8f62d ] + +When registering the mt8173-afe-pcm driver, we are also adding two +components: one is for the PCM DAIs and one is for the HDMI DAIs, but +when debugfs is enabled, we're getting the following issue: + +[ 17.279176] debugfs: Directory '11220000.audio-controller' with parent 'mtk-rt5650' already present! +[ 17.288345] debugfs: Directory '11220000.audio-controller' with parent 'mtk-rt5650' already present! + +To overcome to that without any potentially big rewrite of this driver, +similarly to what was done in mt8195-afe-pcm, add a debugfs_prefix to +the components before actually adding them. + +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20211111161108.502344-1-angelogioacchino.delregno@collabora.com +Signed-off-by: Mark Brown +Stable-dep-of: 4cbb264d4e91 ("ASoC: mediatek: mt8173: Enable IRQ when pdata is ready") +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 51 ++++++++++++++++++---- + 1 file changed, 43 insertions(+), 8 deletions(-) + +diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +index 6350390414d4..31494930433f 100644 +--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c ++++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +@@ -1054,6 +1054,7 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + int irq_id; + struct mtk_base_afe *afe; + struct mt8173_afe_private *afe_priv; ++ struct snd_soc_component *comp_pcm, *comp_hdmi; + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); + if (ret) +@@ -1142,23 +1143,55 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + if (ret) + goto err_pm_disable; + +- ret = devm_snd_soc_register_component(&pdev->dev, +- &mt8173_afe_pcm_dai_component, +- mt8173_afe_pcm_dais, +- ARRAY_SIZE(mt8173_afe_pcm_dais)); ++ comp_pcm = devm_kzalloc(&pdev->dev, sizeof(*comp_pcm), GFP_KERNEL); ++ if (!comp_pcm) { ++ ret = -ENOMEM; ++ goto err_pm_disable; ++ } ++ ++ ret = snd_soc_component_initialize(comp_pcm, ++ &mt8173_afe_pcm_dai_component, ++ &pdev->dev); + if (ret) + goto err_pm_disable; + +- ret = devm_snd_soc_register_component(&pdev->dev, +- &mt8173_afe_hdmi_dai_component, +- mt8173_afe_hdmi_dais, +- ARRAY_SIZE(mt8173_afe_hdmi_dais)); ++#ifdef CONFIG_DEBUG_FS ++ comp_pcm->debugfs_prefix = "pcm"; ++#endif ++ ++ ret = snd_soc_add_component(comp_pcm, ++ mt8173_afe_pcm_dais, ++ ARRAY_SIZE(mt8173_afe_pcm_dais)); ++ if (ret) ++ goto err_pm_disable; ++ ++ comp_hdmi = devm_kzalloc(&pdev->dev, sizeof(*comp_hdmi), GFP_KERNEL); ++ if (!comp_hdmi) { ++ ret = -ENOMEM; ++ goto err_pm_disable; ++ } ++ ++ ret = snd_soc_component_initialize(comp_hdmi, ++ &mt8173_afe_hdmi_dai_component, ++ &pdev->dev); + if (ret) + goto err_pm_disable; + ++#ifdef CONFIG_DEBUG_FS ++ comp_hdmi->debugfs_prefix = "hdmi"; ++#endif ++ ++ ret = snd_soc_add_component(comp_hdmi, ++ mt8173_afe_hdmi_dais, ++ ARRAY_SIZE(mt8173_afe_hdmi_dais)); ++ if (ret) ++ goto err_cleanup_components; ++ + dev_info(&pdev->dev, "MT8173 AFE driver initialized.\n"); + return 0; + ++err_cleanup_components: ++ snd_soc_unregister_component(&pdev->dev); + err_pm_disable: + pm_runtime_disable(&pdev->dev); + return ret; +@@ -1166,6 +1199,8 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev) + + static int mt8173_afe_pcm_dev_remove(struct platform_device *pdev) + { ++ snd_soc_unregister_component(&pdev->dev); ++ + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + mt8173_afe_runtime_suspend(&pdev->dev); +-- +2.35.1 + diff --git a/queue-5.15/asoc-mediatek-mtk-btcvsd-add-checks-for-write-and-re.patch b/queue-5.15/asoc-mediatek-mtk-btcvsd-add-checks-for-write-and-re.patch new file mode 100644 index 00000000000..95e1e9fe230 --- /dev/null +++ b/queue-5.15/asoc-mediatek-mtk-btcvsd-add-checks-for-write-and-re.patch @@ -0,0 +1,43 @@ +From 499e1d01e34dc3c5431ecb91fa438f95404bc9e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 11:07:50 +0800 +Subject: ASoC: mediatek: mtk-btcvsd: Add checks for write and read of + mtk_btcvsd_snd + +From: Jiasheng Jiang + +[ Upstream commit d067b3378a78c9c3048ac535e31c171b6f5b5846 ] + +As the mtk_btcvsd_snd_write and mtk_btcvsd_snd_read may return error, +it should be better to catch the exception. + +Fixes: 4bd8597dc36c ("ASoC: mediatek: add btcvsd driver") +Signed-off-by: Jiasheng Jiang +Link: https://lore.kernel.org/r/20221116030750.40500-1-jiasheng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/mediatek/common/mtk-btcvsd.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c +index d884bb7c0fc7..1c28b41e4311 100644 +--- a/sound/soc/mediatek/common/mtk-btcvsd.c ++++ b/sound/soc/mediatek/common/mtk-btcvsd.c +@@ -1038,11 +1038,9 @@ static int mtk_pcm_btcvsd_copy(struct snd_soc_component *component, + struct mtk_btcvsd_snd *bt = snd_soc_component_get_drvdata(component); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) +- mtk_btcvsd_snd_write(bt, buf, count); ++ return mtk_btcvsd_snd_write(bt, buf, count); + else +- mtk_btcvsd_snd_read(bt, buf, count); +- +- return 0; ++ return mtk_btcvsd_snd_read(bt, buf, count); + } + + /* kcontrol */ +-- +2.35.1 + diff --git a/queue-5.15/asoc-pcm512x-fix-pm-disable-depth-imbalance-in-pcm51.patch b/queue-5.15/asoc-pcm512x-fix-pm-disable-depth-imbalance-in-pcm51.patch new file mode 100644 index 00000000000..5d97f27109f --- /dev/null +++ b/queue-5.15/asoc-pcm512x-fix-pm-disable-depth-imbalance-in-pcm51.patch @@ -0,0 +1,64 @@ +From ba93a78e7bccdb2c67b793003a0e8c854fc6a599 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:04:02 +0800 +Subject: ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe + +From: Zhang Qilong + +[ Upstream commit 97b801be6f8e53676b9f2b105f54e35c745c1b22 ] + +The pm_runtime_enable will increase power disable depth. Thus +a pairing decrement is needed on the error handling path to +keep it balanced according to context. We fix it by going to +err_pm instead of err_clk. + +Fixes:f086ba9d5389c ("ASoC: pcm512x: Support mastering BCLK/LRCLK using the PLL") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220928160402.126140-1-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/pcm512x.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c +index 60dee41816dc..1c26577f08ee 100644 +--- a/sound/soc/codecs/pcm512x.c ++++ b/sound/soc/codecs/pcm512x.c +@@ -1635,7 +1635,7 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + if (val > 6) { + dev_err(dev, "Invalid pll-in\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + pcm512x->pll_in = val; + } +@@ -1644,7 +1644,7 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + if (val > 6) { + dev_err(dev, "Invalid pll-out\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + pcm512x->pll_out = val; + } +@@ -1653,12 +1653,12 @@ int pcm512x_probe(struct device *dev, struct regmap *regmap) + dev_err(dev, + "Error: both pll-in and pll-out, or none\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + if (pcm512x->pll_in && pcm512x->pll_in == pcm512x->pll_out) { + dev_err(dev, "Error: pll-in == pll-out\n"); + ret = -EINVAL; +- goto err_clk; ++ goto err_pm; + } + } + #endif +-- +2.35.1 + diff --git a/queue-5.15/asoc-pxa-fix-null-pointer-dereference-in-filter.patch b/queue-5.15/asoc-pxa-fix-null-pointer-dereference-in-filter.patch new file mode 100644 index 00000000000..990dc46afa9 --- /dev/null +++ b/queue-5.15/asoc-pxa-fix-null-pointer-dereference-in-filter.patch @@ -0,0 +1,37 @@ +From e0c9e9d175130cf0952099a9d155972d86ad0029 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 16:56:29 +0800 +Subject: ASoC: pxa: fix null-pointer dereference in filter() + +From: Zeng Heng + +[ Upstream commit ec7bf231aaa1bdbcb69d23bc50c753c80fb22429 ] + +kasprintf() would return NULL pointer when kmalloc() fail to allocate. +Need to check the return pointer before calling strcmp(). + +Fixes: 7a824e214e25 ("ASoC: mmp: add audio dma support") +Signed-off-by: Zeng Heng +Link: https://lore.kernel.org/r/20221114085629.1910435-1-zengheng4@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/pxa/mmp-pcm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c +index 5d520e18e512..99b245e3079a 100644 +--- a/sound/soc/pxa/mmp-pcm.c ++++ b/sound/soc/pxa/mmp-pcm.c +@@ -98,7 +98,7 @@ static bool filter(struct dma_chan *chan, void *param) + + devname = kasprintf(GFP_KERNEL, "%s.%d", dma_data->dma_res->name, + dma_data->ssp_id); +- if ((strcmp(dev_name(chan->device->dev), devname) == 0) && ++ if (devname && (strcmp(dev_name(chan->device->dev), devname) == 0) && + (chan->chan_id == dma_data->dma_res->start)) { + found = true; + } +-- +2.35.1 + diff --git a/queue-5.15/asoc-qcom-add-checks-for-devm_kcalloc.patch b/queue-5.15/asoc-qcom-add-checks-for-devm_kcalloc.patch new file mode 100644 index 00000000000..a6af4cce40d --- /dev/null +++ b/queue-5.15/asoc-qcom-add-checks-for-devm_kcalloc.patch @@ -0,0 +1,38 @@ +From c625f4bffd04f91b40bfcd3fe79eaf85037e8d70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 14:05:10 +0000 +Subject: ASoC: qcom: Add checks for devm_kcalloc + +From: Yuan Can + +[ Upstream commit 1bf5ee979076ceb121ee51c95197d890b1cee7f4 ] + +As the devm_kcalloc may return NULL, the return value needs to be checked +to avoid NULL poineter dereference. + +Fixes: 24caf8d9eb10 ("ASoC: qcom: lpass-sc7180: Add platform driver for lpass audio") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221124140510.63468-1-yuancan@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/qcom/lpass-sc7180.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c +index 77a556b27cf0..24a1c121cb2e 100644 +--- a/sound/soc/qcom/lpass-sc7180.c ++++ b/sound/soc/qcom/lpass-sc7180.c +@@ -131,6 +131,9 @@ static int sc7180_lpass_init(struct platform_device *pdev) + + drvdata->clks = devm_kcalloc(dev, variant->num_clks, + sizeof(*drvdata->clks), GFP_KERNEL); ++ if (!drvdata->clks) ++ return -ENOMEM; ++ + drvdata->num_clks = variant->num_clks; + + for (i = 0; i < drvdata->num_clks; i++) +-- +2.35.1 + diff --git a/queue-5.15/ata-add-use-ata_taskfile-error-status-fields.patch b/queue-5.15/ata-add-use-ata_taskfile-error-status-fields.patch new file mode 100644 index 00000000000..e1e6738ec1b --- /dev/null +++ b/queue-5.15/ata-add-use-ata_taskfile-error-status-fields.patch @@ -0,0 +1,684 @@ +From 5f93437fbe3a2d13b1b3738e1b356f7fc0c293ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Feb 2022 21:49:26 +0300 +Subject: ata: add/use ata_taskfile::{error|status} fields + +From: Sergey Shtylyov + +[ Upstream commit efcef265fd83d9a68a68926abecb3e1dd3e260a8 ] + +Add the explicit error and status register fields to 'struct ata_taskfile' +using the anonymous *union*s ('struct ide_taskfile' had that for ages!) and +update the libata taskfile code accordingly. There should be no object code +changes resulting from that... + +Signed-off-by: Sergey Shtylyov +Signed-off-by: Damien Le Moal +Stable-dep-of: 7390896b3484 ("ata: libata: fix NCQ autosense logic") +Signed-off-by: Sasha Levin +--- + drivers/ata/acard-ahci.c | 2 +- + drivers/ata/ahci.c | 4 ++-- + drivers/ata/ahci_qoriq.c | 2 +- + drivers/ata/ahci_xgene.c | 2 +- + drivers/ata/libahci.c | 4 ++-- + drivers/ata/libata-acpi.c | 8 +++---- + drivers/ata/libata-core.c | 12 +++++----- + drivers/ata/libata-eh.c | 42 +++++++++++++++++------------------ + drivers/ata/libata-sata.c | 10 ++++----- + drivers/ata/libata-scsi.c | 22 +++++++++--------- + drivers/ata/libata-sff.c | 6 ++--- + drivers/ata/pata_ep93xx.c | 4 ++-- + drivers/ata/pata_ns87415.c | 4 ++-- + drivers/ata/pata_octeon_cf.c | 4 ++-- + drivers/ata/pata_samsung_cf.c | 2 +- + drivers/ata/sata_highbank.c | 2 +- + drivers/ata/sata_inic162x.c | 10 ++++----- + drivers/ata/sata_rcar.c | 4 ++-- + drivers/ata/sata_svw.c | 10 ++++----- + drivers/ata/sata_vsc.c | 10 ++++----- + include/linux/libata.h | 10 +++++++-- + 21 files changed, 90 insertions(+), 84 deletions(-) + +diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c +index 2a04e8abd397..26e0eb537b4f 100644 +--- a/drivers/ata/acard-ahci.c ++++ b/drivers/ata/acard-ahci.c +@@ -267,7 +267,7 @@ static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) + if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && + !(qc->flags & ATA_QCFLAG_FAILED)) { + ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); +- qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; ++ qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; + } else + ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); + +diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c +index 812731e80f8e..c1bf7117a9ff 100644 +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -735,7 +735,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class, + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context), +@@ -806,7 +806,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class, + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, timing, deadline, &online, +diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c +index 5b46fc9aeb4a..e5ac3d1c214c 100644 +--- a/drivers/ata/ahci_qoriq.c ++++ b/drivers/ata/ahci_qoriq.c +@@ -125,7 +125,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class, + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, timing, deadline, &online, +diff --git a/drivers/ata/ahci_xgene.c b/drivers/ata/ahci_xgene.c +index dffc432b9d54..292099410cf6 100644 +--- a/drivers/ata/ahci_xgene.c ++++ b/drivers/ata/ahci_xgene.c +@@ -365,7 +365,7 @@ static int xgene_ahci_do_hardreset(struct ata_link *link, + do { + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + rc = sata_link_hardreset(link, timing, deadline, online, + ahci_check_ready); +diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c +index 395772fa3943..192115a45dd7 100644 +--- a/drivers/ata/libahci.c ++++ b/drivers/ata/libahci.c +@@ -1552,7 +1552,7 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class, + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + rc = sata_link_hardreset(link, timing, deadline, online, +@@ -2038,7 +2038,7 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) + if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && + !(qc->flags & ATA_QCFLAG_FAILED)) { + ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); +- qc->result_tf.command = (rx_fis + RX_FIS_PIO_SETUP)[15]; ++ qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; + } else + ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); + +diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c +index 7007377880ce..d15f3e908ea4 100644 +--- a/drivers/ata/libata-acpi.c ++++ b/drivers/ata/libata-acpi.c +@@ -554,13 +554,13 @@ static void ata_acpi_gtf_to_tf(struct ata_device *dev, + + tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf->protocol = ATA_PROT_NODATA; +- tf->feature = gtf->tf[0]; /* 0x1f1 */ ++ tf->error = gtf->tf[0]; /* 0x1f1 */ + tf->nsect = gtf->tf[1]; /* 0x1f2 */ + tf->lbal = gtf->tf[2]; /* 0x1f3 */ + tf->lbam = gtf->tf[3]; /* 0x1f4 */ + tf->lbah = gtf->tf[4]; /* 0x1f5 */ + tf->device = gtf->tf[5]; /* 0x1f6 */ +- tf->command = gtf->tf[6]; /* 0x1f7 */ ++ tf->status = gtf->tf[6]; /* 0x1f7 */ + } + + static int ata_acpi_filter_tf(struct ata_device *dev, +@@ -689,7 +689,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, + "(%s) rejected by device (Stat=0x%02x Err=0x%02x)", + tf.command, tf.feature, tf.nsect, tf.lbal, + tf.lbam, tf.lbah, tf.device, descr, +- rtf.command, rtf.feature); ++ rtf.status, rtf.error); + rc = 0; + break; + +@@ -699,7 +699,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, + "(%s) failed (Emask=0x%x Stat=0x%02x Err=0x%02x)", + tf.command, tf.feature, tf.nsect, tf.lbal, + tf.lbam, tf.lbah, tf.device, descr, +- err_mask, rtf.command, rtf.feature); ++ err_mask, rtf.status, rtf.error); + rc = -EIO; + break; + } +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 1c9ad3045606..c430cd3cfa17 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -1185,7 +1185,7 @@ static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors) + ata_dev_warn(dev, + "failed to read native max address (err_mask=0x%x)\n", + err_mask); +- if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED)) ++ if (err_mask == AC_ERR_DEV && (tf.error & ATA_ABORTED)) + return -EACCES; + return -EIO; + } +@@ -1249,7 +1249,7 @@ static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors) + "failed to set max address (err_mask=0x%x)\n", + err_mask); + if (err_mask == AC_ERR_DEV && +- (tf.feature & (ATA_ABORTED | ATA_IDNF))) ++ (tf.error & (ATA_ABORTED | ATA_IDNF))) + return -EACCES; + return -EIO; + } +@@ -1616,7 +1616,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, + + /* perform minimal error analysis */ + if (qc->flags & ATA_QCFLAG_FAILED) { +- if (qc->result_tf.command & (ATA_ERR | ATA_DF)) ++ if (qc->result_tf.status & (ATA_ERR | ATA_DF)) + qc->err_mask |= AC_ERR_DEV; + + if (!qc->err_mask) +@@ -1625,7 +1625,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, + if (qc->err_mask & ~AC_ERR_OTHER) + qc->err_mask &= ~AC_ERR_OTHER; + } else if (qc->tf.command == ATA_CMD_REQ_SENSE_DATA) { +- qc->result_tf.command |= ATA_SENSE; ++ qc->result_tf.status |= ATA_SENSE; + } + + /* finish up */ +@@ -1848,7 +1848,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, + return 0; + } + +- if ((err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) { ++ if ((err_mask == AC_ERR_DEV) && (tf.error & ATA_ABORTED)) { + /* Device or controller might have reported + * the wrong device class. Give a shot at the + * other IDENTIFY if the current one is +@@ -4371,7 +4371,7 @@ static unsigned int ata_dev_init_params(struct ata_device *dev, + /* A clean abort indicates an original or just out of spec drive + and we should continue as we issue the setup based on the + drive reported working geometry */ +- if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED)) ++ if (err_mask == AC_ERR_DEV && (tf.error & ATA_ABORTED)) + err_mask = 0; + + DPRINTK("EXIT, err_mask=%x\n", err_mask); +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index 7aea631edb27..8350abc17290 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -1386,7 +1386,7 @@ unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key) + + err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0); + if (err_mask == AC_ERR_DEV) +- *r_sense_key = tf.feature >> 4; ++ *r_sense_key = tf.error >> 4; + return err_mask; + } + +@@ -1431,12 +1431,12 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc, + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0); + /* Ignore err_mask; ATA_ERR might be set */ +- if (tf.command & ATA_SENSE) { ++ if (tf.status & ATA_SENSE) { + ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal); + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } else { + ata_dev_warn(dev, "request sense failed stat %02x emask %x\n", +- tf.command, err_mask); ++ tf.status, err_mask); + } + } + +@@ -1561,7 +1561,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, + const struct ata_taskfile *tf) + { + unsigned int tmp, action = 0; +- u8 stat = tf->command, err = tf->feature; ++ u8 stat = tf->status, err = tf->error; + + if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) { + qc->err_mask |= AC_ERR_HSM; +@@ -1598,7 +1598,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, + if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { + tmp = atapi_eh_request_sense(qc->dev, + qc->scsicmd->sense_buffer, +- qc->result_tf.feature >> 4); ++ qc->result_tf.error >> 4); + if (!tmp) + qc->flags |= ATA_QCFLAG_SENSE_VALID; + else +@@ -2372,7 +2372,7 @@ static void ata_eh_link_report(struct ata_link *link) + cmd->hob_feature, cmd->hob_nsect, + cmd->hob_lbal, cmd->hob_lbam, cmd->hob_lbah, + cmd->device, qc->tag, data_buf, cdb_buf, +- res->command, res->feature, res->nsect, ++ res->status, res->error, res->nsect, + res->lbal, res->lbam, res->lbah, + res->hob_feature, res->hob_nsect, + res->hob_lbal, res->hob_lbam, res->hob_lbah, +@@ -2380,28 +2380,28 @@ static void ata_eh_link_report(struct ata_link *link) + qc->err_mask & AC_ERR_NCQ ? " " : ""); + + #ifdef CONFIG_ATA_VERBOSE_ERROR +- if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | +- ATA_SENSE | ATA_ERR)) { +- if (res->command & ATA_BUSY) ++ if (res->status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ++ ATA_SENSE | ATA_ERR)) { ++ if (res->status & ATA_BUSY) + ata_dev_err(qc->dev, "status: { Busy }\n"); + else + ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n", +- res->command & ATA_DRDY ? "DRDY " : "", +- res->command & ATA_DF ? "DF " : "", +- res->command & ATA_DRQ ? "DRQ " : "", +- res->command & ATA_SENSE ? "SENSE " : "", +- res->command & ATA_ERR ? "ERR " : ""); ++ res->status & ATA_DRDY ? "DRDY " : "", ++ res->status & ATA_DF ? "DF " : "", ++ res->status & ATA_DRQ ? "DRQ " : "", ++ res->status & ATA_SENSE ? "SENSE " : "", ++ res->status & ATA_ERR ? "ERR " : ""); + } + + if (cmd->command != ATA_CMD_PACKET && +- (res->feature & (ATA_ICRC | ATA_UNC | ATA_AMNF | +- ATA_IDNF | ATA_ABORTED))) ++ (res->error & (ATA_ICRC | ATA_UNC | ATA_AMNF | ATA_IDNF | ++ ATA_ABORTED))) + ata_dev_err(qc->dev, "error: { %s%s%s%s%s}\n", +- res->feature & ATA_ICRC ? "ICRC " : "", +- res->feature & ATA_UNC ? "UNC " : "", +- res->feature & ATA_AMNF ? "AMNF " : "", +- res->feature & ATA_IDNF ? "IDNF " : "", +- res->feature & ATA_ABORTED ? "ABRT " : ""); ++ res->error & ATA_ICRC ? "ICRC " : "", ++ res->error & ATA_UNC ? "UNC " : "", ++ res->error & ATA_AMNF ? "AMNF " : "", ++ res->error & ATA_IDNF ? "IDNF " : "", ++ res->error & ATA_ABORTED ? "ABRT " : ""); + #endif + } + } +diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c +index 8f3ff830ab0c..1e59e5b6b047 100644 +--- a/drivers/ata/libata-sata.c ++++ b/drivers/ata/libata-sata.c +@@ -191,8 +191,8 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis); + + void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf) + { +- tf->command = fis[2]; /* status */ +- tf->feature = fis[3]; /* error */ ++ tf->status = fis[2]; ++ tf->error = fis[3]; + + tf->lbal = fis[4]; + tf->lbam = fis[5]; +@@ -1402,8 +1402,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, + + *tag = buf[0] & 0x1f; + +- tf->command = buf[2]; +- tf->feature = buf[3]; ++ tf->status = buf[2]; ++ tf->error = buf[3]; + tf->lbal = buf[4]; + tf->lbam = buf[5]; + tf->lbah = buf[6]; +@@ -1478,7 +1478,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) + qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; + if (dev->class == ATA_DEV_ZAC && +- ((qc->result_tf.command & ATA_SENSE) || qc->result_tf.auxiliary)) { ++ ((qc->result_tf.status & ATA_SENSE) || qc->result_tf.auxiliary)) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; +diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c +index 061d2f8feeb5..4d8129640d60 100644 +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -671,7 +671,7 @@ static void ata_qc_set_pc_nbytes(struct ata_queued_cmd *qc) + */ + static void ata_dump_status(unsigned id, struct ata_taskfile *tf) + { +- u8 stat = tf->command, err = tf->feature; ++ u8 stat = tf->status, err = tf->error; + + pr_warn("ata%u: status=0x%02x { ", id, stat); + if (stat & ATA_BUSY) { +@@ -867,8 +867,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) + * onto sense key, asc & ascq. + */ + if (qc->err_mask || +- tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { +- ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, ++ tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ++ ata_to_sense_error(qc->ap->print_id, tf->status, tf->error, + &sense_key, &asc, &ascq, verbose); + ata_scsi_set_sense(qc->dev, cmd, sense_key, asc, ascq); + } else { +@@ -897,13 +897,13 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) + * Copy registers into sense buffer. + */ + desc[2] = 0x00; +- desc[3] = tf->feature; /* == error reg */ ++ desc[3] = tf->error; + desc[5] = tf->nsect; + desc[7] = tf->lbal; + desc[9] = tf->lbam; + desc[11] = tf->lbah; + desc[12] = tf->device; +- desc[13] = tf->command; /* == status reg */ ++ desc[13] = tf->status; + + /* + * Fill in Extend bit, and the high order bytes +@@ -918,8 +918,8 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc) + } + } else { + /* Fixed sense format */ +- desc[0] = tf->feature; +- desc[1] = tf->command; /* status */ ++ desc[0] = tf->error; ++ desc[1] = tf->status; + desc[2] = tf->device; + desc[3] = tf->nsect; + desc[7] = 0; +@@ -968,14 +968,14 @@ static void ata_gen_ata_sense(struct ata_queued_cmd *qc) + * onto sense key, asc & ascq. + */ + if (qc->err_mask || +- tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { +- ata_to_sense_error(qc->ap->print_id, tf->command, tf->feature, ++ tf->status & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) { ++ ata_to_sense_error(qc->ap->print_id, tf->status, tf->error, + &sense_key, &asc, &ascq, verbose); + ata_scsi_set_sense(dev, cmd, sense_key, asc, ascq); + } else { + /* Could not decode error */ + ata_dev_warn(dev, "could not decode error status 0x%x err_mask 0x%x\n", +- tf->command, qc->err_mask); ++ tf->status, qc->err_mask); + ata_scsi_set_sense(dev, cmd, ABORTED_COMMAND, 0, 0); + return; + } +@@ -2490,7 +2490,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc) + + /* fill these in, for the case where they are -not- overwritten */ + cmd->sense_buffer[0] = 0x70; +- cmd->sense_buffer[2] = qc->tf.feature >> 4; ++ cmd->sense_buffer[2] = qc->tf.error >> 4; + + ata_qc_reinit(qc); + +diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c +index b71ea4a680b0..8409e53b7b7a 100644 +--- a/drivers/ata/libata-sff.c ++++ b/drivers/ata/libata-sff.c +@@ -457,8 +457,8 @@ void ata_sff_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; + +- tf->command = ata_sff_check_status(ap); +- tf->feature = ioread8(ioaddr->error_addr); ++ tf->status = ata_sff_check_status(ap); ++ tf->error = ioread8(ioaddr->error_addr); + tf->nsect = ioread8(ioaddr->nsect_addr); + tf->lbal = ioread8(ioaddr->lbal_addr); + tf->lbam = ioread8(ioaddr->lbam_addr); +@@ -1837,7 +1837,7 @@ unsigned int ata_sff_dev_classify(struct ata_device *dev, int present, + memset(&tf, 0, sizeof(tf)); + + ap->ops->sff_tf_read(ap, &tf); +- err = tf.feature; ++ err = tf.error; + if (r_err) + *r_err = err; + +diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c +index 46208ececbb6..3fc26026014e 100644 +--- a/drivers/ata/pata_ep93xx.c ++++ b/drivers/ata/pata_ep93xx.c +@@ -416,8 +416,8 @@ static void ep93xx_pata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ep93xx_pata_data *drv_data = ap->host->private_data; + +- tf->command = ep93xx_pata_check_status(ap); +- tf->feature = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_FEATURE); ++ tf->status = ep93xx_pata_check_status(ap); ++ tf->error = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_FEATURE); + tf->nsect = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_NSECT); + tf->lbal = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAL); + tf->lbam = ep93xx_pata_read_reg(drv_data, IDECTRL_ADDR_LBAM); +diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c +index f4949e704356..9dd6bffefb48 100644 +--- a/drivers/ata/pata_ns87415.c ++++ b/drivers/ata/pata_ns87415.c +@@ -264,8 +264,8 @@ void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; + +- tf->command = ns87560_check_status(ap); +- tf->feature = ioread8(ioaddr->error_addr); ++ tf->status = ns87560_check_status(ap); ++ tf->error = ioread8(ioaddr->error_addr); + tf->nsect = ioread8(ioaddr->nsect_addr); + tf->lbal = ioread8(ioaddr->lbal_addr); + tf->lbam = ioread8(ioaddr->lbam_addr); +diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c +index 4cc8a1027888..6c9f2efcedc1 100644 +--- a/drivers/ata/pata_octeon_cf.c ++++ b/drivers/ata/pata_octeon_cf.c +@@ -386,7 +386,7 @@ static void octeon_cf_tf_read16(struct ata_port *ap, struct ata_taskfile *tf) + void __iomem *base = ap->ioaddr.data_addr; + + blob = __raw_readw(base + 0xc); +- tf->feature = blob >> 8; ++ tf->error = blob >> 8; + + blob = __raw_readw(base + 2); + tf->nsect = blob & 0xff; +@@ -398,7 +398,7 @@ static void octeon_cf_tf_read16(struct ata_port *ap, struct ata_taskfile *tf) + + blob = __raw_readw(base + 6); + tf->device = blob & 0xff; +- tf->command = blob >> 8; ++ tf->status = blob >> 8; + + if (tf->flags & ATA_TFLAG_LBA48) { + if (likely(ap->ioaddr.ctl_addr)) { +diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c +index 3da0e8e30286..149d771c61d6 100644 +--- a/drivers/ata/pata_samsung_cf.c ++++ b/drivers/ata/pata_samsung_cf.c +@@ -213,7 +213,7 @@ static void pata_s3c_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; + +- tf->feature = ata_inb(ap->host, ioaddr->error_addr); ++ tf->error = ata_inb(ap->host, ioaddr->error_addr); + tf->nsect = ata_inb(ap->host, ioaddr->nsect_addr); + tf->lbal = ata_inb(ap->host, ioaddr->lbal_addr); + tf->lbam = ata_inb(ap->host, ioaddr->lbam_addr); +diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c +index 8440203e835e..f9bb3be4b939 100644 +--- a/drivers/ata/sata_highbank.c ++++ b/drivers/ata/sata_highbank.c +@@ -400,7 +400,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class, + + /* clear D2H reception area to properly wait for D2H FIS */ + ata_tf_init(link->device, &tf); +- tf.command = ATA_BUSY; ++ tf.status = ATA_BUSY; + ata_tf_to_fis(&tf, 0, 0, d2h_fis); + + do { +diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c +index e517bd8822a5..659f1a903298 100644 +--- a/drivers/ata/sata_inic162x.c ++++ b/drivers/ata/sata_inic162x.c +@@ -559,13 +559,13 @@ static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + void __iomem *port_base = inic_port_base(ap); + +- tf->feature = readb(port_base + PORT_TF_FEATURE); ++ tf->error = readb(port_base + PORT_TF_FEATURE); + tf->nsect = readb(port_base + PORT_TF_NSECT); + tf->lbal = readb(port_base + PORT_TF_LBAL); + tf->lbam = readb(port_base + PORT_TF_LBAM); + tf->lbah = readb(port_base + PORT_TF_LBAH); + tf->device = readb(port_base + PORT_TF_DEVICE); +- tf->command = readb(port_base + PORT_TF_COMMAND); ++ tf->status = readb(port_base + PORT_TF_COMMAND); + } + + static bool inic_qc_fill_rtf(struct ata_queued_cmd *qc) +@@ -582,11 +582,11 @@ static bool inic_qc_fill_rtf(struct ata_queued_cmd *qc) + */ + inic_tf_read(qc->ap, &tf); + +- if (!(tf.command & ATA_ERR)) ++ if (!(tf.status & ATA_ERR)) + return false; + +- rtf->command = tf.command; +- rtf->feature = tf.feature; ++ rtf->status = tf.status; ++ rtf->error = tf.error; + return true; + } + +diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c +index 44b0ed8f6bb8..9759e24f718f 100644 +--- a/drivers/ata/sata_rcar.c ++++ b/drivers/ata/sata_rcar.c +@@ -417,8 +417,8 @@ static void sata_rcar_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; + +- tf->command = sata_rcar_check_status(ap); +- tf->feature = ioread32(ioaddr->error_addr); ++ tf->status = sata_rcar_check_status(ap); ++ tf->error = ioread32(ioaddr->error_addr); + tf->nsect = ioread32(ioaddr->nsect_addr); + tf->lbal = ioread32(ioaddr->lbal_addr); + tf->lbam = ioread32(ioaddr->lbam_addr); +diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c +index f8552559db7f..2e3418a82b44 100644 +--- a/drivers/ata/sata_svw.c ++++ b/drivers/ata/sata_svw.c +@@ -194,24 +194,24 @@ static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) + static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; +- u16 nsect, lbal, lbam, lbah, feature; ++ u16 nsect, lbal, lbam, lbah, error; + +- tf->command = k2_stat_check_status(ap); ++ tf->status = k2_stat_check_status(ap); + tf->device = readw(ioaddr->device_addr); +- feature = readw(ioaddr->error_addr); ++ error = readw(ioaddr->error_addr); + nsect = readw(ioaddr->nsect_addr); + lbal = readw(ioaddr->lbal_addr); + lbam = readw(ioaddr->lbam_addr); + lbah = readw(ioaddr->lbah_addr); + +- tf->feature = feature; ++ tf->error = error; + tf->nsect = nsect; + tf->lbal = lbal; + tf->lbam = lbam; + tf->lbah = lbah; + + if (tf->flags & ATA_TFLAG_LBA48) { +- tf->hob_feature = feature >> 8; ++ tf->hob_feature = error >> 8; + tf->hob_nsect = nsect >> 8; + tf->hob_lbal = lbal >> 8; + tf->hob_lbam = lbam >> 8; +diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c +index 8fa952cb9f7f..87e4ed66b306 100644 +--- a/drivers/ata/sata_vsc.c ++++ b/drivers/ata/sata_vsc.c +@@ -183,24 +183,24 @@ static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) + static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) + { + struct ata_ioports *ioaddr = &ap->ioaddr; +- u16 nsect, lbal, lbam, lbah, feature; ++ u16 nsect, lbal, lbam, lbah, error; + +- tf->command = ata_sff_check_status(ap); ++ tf->status = ata_sff_check_status(ap); + tf->device = readw(ioaddr->device_addr); +- feature = readw(ioaddr->error_addr); ++ error = readw(ioaddr->error_addr); + nsect = readw(ioaddr->nsect_addr); + lbal = readw(ioaddr->lbal_addr); + lbam = readw(ioaddr->lbam_addr); + lbah = readw(ioaddr->lbah_addr); + +- tf->feature = feature; ++ tf->error = error; + tf->nsect = nsect; + tf->lbal = lbal; + tf->lbam = lbam; + tf->lbah = lbah; + + if (tf->flags & ATA_TFLAG_LBA48) { +- tf->hob_feature = feature >> 8; ++ tf->hob_feature = error >> 8; + tf->hob_nsect = nsect >> 8; + tf->hob_lbal = lbal >> 8; + tf->hob_lbam = lbam >> 8; +diff --git a/include/linux/libata.h b/include/linux/libata.h +index e9c79a72f5e6..d890c43cff14 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -565,7 +565,10 @@ struct ata_taskfile { + u8 hob_lbam; + u8 hob_lbah; + +- u8 feature; ++ union { ++ u8 error; ++ u8 feature; ++ }; + u8 nsect; + u8 lbal; + u8 lbam; +@@ -573,7 +576,10 @@ struct ata_taskfile { + + u8 device; + +- u8 command; /* IO operation */ ++ union { ++ u8 status; ++ u8 command; ++ }; + + u32 auxiliary; /* auxiliary field */ + /* from SATA 3.1 and */ +-- +2.35.1 + diff --git a/queue-5.15/ata-libata-fix-ncq-autosense-logic.patch b/queue-5.15/ata-libata-fix-ncq-autosense-logic.patch new file mode 100644 index 00000000000..eadf84601e1 --- /dev/null +++ b/queue-5.15/ata-libata-fix-ncq-autosense-logic.patch @@ -0,0 +1,76 @@ +From 832519fc592ff594ff5ce8c3f37c7683ac453326 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 20:53:06 +0000 +Subject: ata: libata: fix NCQ autosense logic + +From: Niklas Cassel + +[ Upstream commit 7390896b3484d44cbdb8bc4859964314ac66d3c9 ] + +Currently, the logic if we should call ata_scsi_set_sense() +(and set flag ATA_QCFLAG_SENSE_VALID to indicate that we have +successfully added sense data to the struct ata_queued_cmd) +looks like this: + +if (dev->class == ATA_DEV_ZAC && + ((qc->result_tf.status & ATA_SENSE) || qc->result_tf.auxiliary)) + +The problem with this is that a drive can support the NCQ command +error log without supporting NCQ autosense. + +On such a drive, if the failing command has sense data, the status +field in the NCQ command error log will have the ATA_SENSE bit set. + +It is just that this sense data is not included in the NCQ command +error log when NCQ autosense is not supported. Instead the sense +data has to be fetched using the REQUEST SENSE DATA EXT command. + +Therefore, we should only add the sense data if the drive supports +NCQ autosense AND the ATA_SENSE bit is set in the status field. + +Fix this, and at the same time, remove the duplicated ATA_DEV_ZAC +check. The struct ata_taskfile supplied to ata_eh_read_log_10h() +is memset:ed before calling the function, so simply checking if +qc->result_tf.auxiliary is set is sufficient to tell us that the +log actually contained sense data. + +Fixes: d238ffd59d3c ("libata: do not attempt to retrieve sense code twice") +Signed-off-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/libata-sata.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c +index 1e59e5b6b047..b5aa525d8760 100644 +--- a/drivers/ata/libata-sata.c ++++ b/drivers/ata/libata-sata.c +@@ -1413,7 +1413,8 @@ static int ata_eh_read_log_10h(struct ata_device *dev, + tf->hob_lbah = buf[10]; + tf->nsect = buf[12]; + tf->hob_nsect = buf[13]; +- if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id)) ++ if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id) && ++ (tf->status & ATA_SENSE)) + tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16]; + + return 0; +@@ -1477,8 +1478,12 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) + memcpy(&qc->result_tf, &tf, sizeof(tf)); + qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48; + qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; +- if (dev->class == ATA_DEV_ZAC && +- ((qc->result_tf.status & ATA_SENSE) || qc->result_tf.auxiliary)) { ++ ++ /* ++ * If the device supports NCQ autosense, ata_eh_read_log_10h() will have ++ * stored the sense data in qc->result_tf.auxiliary. ++ */ ++ if (qc->result_tf.auxiliary) { + char sense_key, asc, ascq; + + sense_key = (qc->result_tf.auxiliary >> 16) & 0xff; +-- +2.35.1 + diff --git a/queue-5.15/ata-libata-move-ata_-port-link-dev-_dbg-to-standard-.patch b/queue-5.15/ata-libata-move-ata_-port-link-dev-_dbg-to-standard-.patch new file mode 100644 index 00000000000..e3ff957335f --- /dev/null +++ b/queue-5.15/ata-libata-move-ata_-port-link-dev-_dbg-to-standard-.patch @@ -0,0 +1,316 @@ +From 7b321a7ff849e96bf2d56e0131541bab727790c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Dec 2021 08:20:35 +0100 +Subject: ata: libata: move ata_{port,link,dev}_dbg to standard pr_XXX() macros + +From: Hannes Reinecke + +[ Upstream commit 742bef476ca5352b16063161fb73a56629a6d995 ] + +Use standard pr_{debug,info,notice,warn,err} macros instead of the +hand-crafted printk helpers. + +Signed-off-by: Hannes Reinecke +Signed-off-by: Damien Le Moal +Stable-dep-of: 7390896b3484 ("ata: libata: fix NCQ autosense logic") +Signed-off-by: Sasha Levin +--- + drivers/ata/libata-acpi.c | 48 +++++++++++++------------ + drivers/ata/libata-core.c | 61 ------------------------------- + drivers/ata/pata_ixp4xx_cf.c | 6 ++-- + include/linux/libata.h | 69 ++++++++++++++++++++---------------- + 4 files changed, 67 insertions(+), 117 deletions(-) + +diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c +index 7a7d6642edcc..7007377880ce 100644 +--- a/drivers/ata/libata-acpi.c ++++ b/drivers/ata/libata-acpi.c +@@ -650,9 +650,7 @@ static int ata_acpi_run_tf(struct ata_device *dev, + struct ata_taskfile *pptf = NULL; + struct ata_taskfile tf, ptf, rtf; + unsigned int err_mask; +- const char *level; + const char *descr; +- char msg[60]; + int rc; + + if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0) +@@ -666,6 +664,10 @@ static int ata_acpi_run_tf(struct ata_device *dev, + pptf = &ptf; + } + ++ descr = ata_get_cmd_descript(tf.command); ++ if (!descr) ++ descr = "unknown"; ++ + if (!ata_acpi_filter_tf(dev, &tf, pptf)) { + rtf = tf; + err_mask = ata_exec_internal(dev, &rtf, NULL, +@@ -673,40 +675,42 @@ static int ata_acpi_run_tf(struct ata_device *dev, + + switch (err_mask) { + case 0: +- level = KERN_DEBUG; +- snprintf(msg, sizeof(msg), "succeeded"); ++ ata_dev_dbg(dev, ++ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x" ++ "(%s) succeeded\n", ++ tf.command, tf.feature, tf.nsect, tf.lbal, ++ tf.lbam, tf.lbah, tf.device, descr); + rc = 1; + break; + + case AC_ERR_DEV: +- level = KERN_INFO; +- snprintf(msg, sizeof(msg), +- "rejected by device (Stat=0x%02x Err=0x%02x)", +- rtf.command, rtf.feature); ++ ata_dev_info(dev, ++ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x" ++ "(%s) rejected by device (Stat=0x%02x Err=0x%02x)", ++ tf.command, tf.feature, tf.nsect, tf.lbal, ++ tf.lbam, tf.lbah, tf.device, descr, ++ rtf.command, rtf.feature); + rc = 0; + break; + + default: +- level = KERN_ERR; +- snprintf(msg, sizeof(msg), +- "failed (Emask=0x%x Stat=0x%02x Err=0x%02x)", +- err_mask, rtf.command, rtf.feature); ++ ata_dev_err(dev, ++ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x" ++ "(%s) failed (Emask=0x%x Stat=0x%02x Err=0x%02x)", ++ tf.command, tf.feature, tf.nsect, tf.lbal, ++ tf.lbam, tf.lbah, tf.device, descr, ++ err_mask, rtf.command, rtf.feature); + rc = -EIO; + break; + } + } else { +- level = KERN_INFO; +- snprintf(msg, sizeof(msg), "filtered out"); ++ ata_dev_info(dev, ++ "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x" ++ "(%s) filtered out\n", ++ tf.command, tf.feature, tf.nsect, tf.lbal, ++ tf.lbam, tf.lbah, tf.device, descr); + rc = 0; + } +- descr = ata_get_cmd_descript(tf.command); +- +- ata_dev_printk(dev, level, +- "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x (%s) %s\n", +- tf.command, tf.feature, tf.nsect, tf.lbal, +- tf.lbam, tf.lbah, tf.device, +- (descr ? descr : "unknown"), msg); +- + return rc; + } + +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 4d308e3163c3..1c9ad3045606 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -6497,67 +6497,6 @@ const struct ata_port_info ata_dummy_port_info = { + }; + EXPORT_SYMBOL_GPL(ata_dummy_port_info); + +-/* +- * Utility print functions +- */ +-void ata_port_printk(const struct ata_port *ap, const char *level, +- const char *fmt, ...) +-{ +- struct va_format vaf; +- va_list args; +- +- va_start(args, fmt); +- +- vaf.fmt = fmt; +- vaf.va = &args; +- +- printk("%sata%u: %pV", level, ap->print_id, &vaf); +- +- va_end(args); +-} +-EXPORT_SYMBOL(ata_port_printk); +- +-void ata_link_printk(const struct ata_link *link, const char *level, +- const char *fmt, ...) +-{ +- struct va_format vaf; +- va_list args; +- +- va_start(args, fmt); +- +- vaf.fmt = fmt; +- vaf.va = &args; +- +- if (sata_pmp_attached(link->ap) || link->ap->slave_link) +- printk("%sata%u.%02u: %pV", +- level, link->ap->print_id, link->pmp, &vaf); +- else +- printk("%sata%u: %pV", +- level, link->ap->print_id, &vaf); +- +- va_end(args); +-} +-EXPORT_SYMBOL(ata_link_printk); +- +-void ata_dev_printk(const struct ata_device *dev, const char *level, +- const char *fmt, ...) +-{ +- struct va_format vaf; +- va_list args; +- +- va_start(args, fmt); +- +- vaf.fmt = fmt; +- vaf.va = &args; +- +- printk("%sata%u.%02u: %pV", +- level, dev->link->ap->print_id, dev->link->pmp + dev->devno, +- &vaf); +- +- va_end(args); +-} +-EXPORT_SYMBOL(ata_dev_printk); +- + void ata_print_version(const struct device *dev, const char *version) + { + dev_printk(KERN_DEBUG, dev, "version %s\n", version); +diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c +index 99c63087c8ae..17b557c91e1c 100644 +--- a/drivers/ata/pata_ixp4xx_cf.c ++++ b/drivers/ata/pata_ixp4xx_cf.c +@@ -114,7 +114,7 @@ static void ixp4xx_set_piomode(struct ata_port *ap, struct ata_device *adev) + { + struct ixp4xx_pata *ixpp = ap->host->private_data; + +- ata_dev_printk(adev, KERN_INFO, "configured for PIO%d 8bit\n", ++ ata_dev_info(adev, "configured for PIO%d 8bit\n", + adev->pio_mode - XFER_PIO_0); + ixp4xx_set_8bit_timing(ixpp, adev->pio_mode); + } +@@ -132,8 +132,8 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_queued_cmd *qc, + struct ixp4xx_pata *ixpp = ap->host->private_data; + unsigned long flags; + +- ata_dev_printk(adev, KERN_DEBUG, "%s %d bytes\n", (rw == READ) ? "READ" : "WRITE", +- buflen); ++ ata_dev_dbg(adev, "%s %d bytes\n", (rw == READ) ? "READ" : "WRITE", ++ buflen); + spin_lock_irqsave(ap->lock, flags); + + /* set the expansion bus in 16bit mode and restore +diff --git a/include/linux/libata.h b/include/linux/libata.h +index a64e12605d31..e9c79a72f5e6 100644 +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -1471,51 +1471,61 @@ static inline int sata_srst_pmp(struct ata_link *link) + return link->pmp; + } + +-/* +- * printk helpers +- */ +-__printf(3, 4) +-void ata_port_printk(const struct ata_port *ap, const char *level, +- const char *fmt, ...); +-__printf(3, 4) +-void ata_link_printk(const struct ata_link *link, const char *level, +- const char *fmt, ...); +-__printf(3, 4) +-void ata_dev_printk(const struct ata_device *dev, const char *level, +- const char *fmt, ...); ++#define ata_port_printk(level, ap, fmt, ...) \ ++ pr_ ## level ("ata%u: " fmt, (ap)->print_id, ##__VA_ARGS__) + + #define ata_port_err(ap, fmt, ...) \ +- ata_port_printk(ap, KERN_ERR, fmt, ##__VA_ARGS__) ++ ata_port_printk(err, ap, fmt, ##__VA_ARGS__) + #define ata_port_warn(ap, fmt, ...) \ +- ata_port_printk(ap, KERN_WARNING, fmt, ##__VA_ARGS__) ++ ata_port_printk(warn, ap, fmt, ##__VA_ARGS__) + #define ata_port_notice(ap, fmt, ...) \ +- ata_port_printk(ap, KERN_NOTICE, fmt, ##__VA_ARGS__) ++ ata_port_printk(notice, ap, fmt, ##__VA_ARGS__) + #define ata_port_info(ap, fmt, ...) \ +- ata_port_printk(ap, KERN_INFO, fmt, ##__VA_ARGS__) ++ ata_port_printk(info, ap, fmt, ##__VA_ARGS__) + #define ata_port_dbg(ap, fmt, ...) \ +- ata_port_printk(ap, KERN_DEBUG, fmt, ##__VA_ARGS__) ++ ata_port_printk(debug, ap, fmt, ##__VA_ARGS__) ++ ++#define ata_link_printk(level, link, fmt, ...) \ ++do { \ ++ if (sata_pmp_attached((link)->ap) || \ ++ (link)->ap->slave_link) \ ++ pr_ ## level ("ata%u.%02u: " fmt, \ ++ (link)->ap->print_id, \ ++ (link)->pmp, \ ++ ##__VA_ARGS__); \ ++ else \ ++ pr_ ## level ("ata%u: " fmt, \ ++ (link)->ap->print_id, \ ++ ##__VA_ARGS__); \ ++} while (0) + + #define ata_link_err(link, fmt, ...) \ +- ata_link_printk(link, KERN_ERR, fmt, ##__VA_ARGS__) ++ ata_link_printk(err, link, fmt, ##__VA_ARGS__) + #define ata_link_warn(link, fmt, ...) \ +- ata_link_printk(link, KERN_WARNING, fmt, ##__VA_ARGS__) ++ ata_link_printk(warn, link, fmt, ##__VA_ARGS__) + #define ata_link_notice(link, fmt, ...) \ +- ata_link_printk(link, KERN_NOTICE, fmt, ##__VA_ARGS__) ++ ata_link_printk(notice, link, fmt, ##__VA_ARGS__) + #define ata_link_info(link, fmt, ...) \ +- ata_link_printk(link, KERN_INFO, fmt, ##__VA_ARGS__) ++ ata_link_printk(info, link, fmt, ##__VA_ARGS__) + #define ata_link_dbg(link, fmt, ...) \ +- ata_link_printk(link, KERN_DEBUG, fmt, ##__VA_ARGS__) ++ ata_link_printk(debug, link, fmt, ##__VA_ARGS__) ++ ++#define ata_dev_printk(level, dev, fmt, ...) \ ++ pr_ ## level("ata%u.%02u: " fmt, \ ++ (dev)->link->ap->print_id, \ ++ (dev)->link->pmp + (dev)->devno, \ ++ ##__VA_ARGS__) + + #define ata_dev_err(dev, fmt, ...) \ +- ata_dev_printk(dev, KERN_ERR, fmt, ##__VA_ARGS__) ++ ata_dev_printk(err, dev, fmt, ##__VA_ARGS__) + #define ata_dev_warn(dev, fmt, ...) \ +- ata_dev_printk(dev, KERN_WARNING, fmt, ##__VA_ARGS__) ++ ata_dev_printk(warn, dev, fmt, ##__VA_ARGS__) + #define ata_dev_notice(dev, fmt, ...) \ +- ata_dev_printk(dev, KERN_NOTICE, fmt, ##__VA_ARGS__) ++ ata_dev_printk(notice, dev, fmt, ##__VA_ARGS__) + #define ata_dev_info(dev, fmt, ...) \ +- ata_dev_printk(dev, KERN_INFO, fmt, ##__VA_ARGS__) ++ ata_dev_printk(info, dev, fmt, ##__VA_ARGS__) + #define ata_dev_dbg(dev, fmt, ...) \ +- ata_dev_printk(dev, KERN_DEBUG, fmt, ##__VA_ARGS__) ++ ata_dev_printk(debug, dev, fmt, ##__VA_ARGS__) + + void ata_print_version(const struct device *dev, const char *version); + +@@ -2049,11 +2059,8 @@ static inline u8 ata_wait_idle(struct ata_port *ap) + { + u8 status = ata_sff_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); + +-#ifdef ATA_DEBUG + if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) +- ata_port_printk(ap, KERN_DEBUG, "abnormal Status 0x%X\n", +- status); +-#endif ++ ata_port_dbg(ap, "abnormal Status 0x%X\n", status); + + return status; + } +-- +2.35.1 + diff --git a/queue-5.15/bfq-fix-waker_bfqq-inconsistency-crash.patch b/queue-5.15/bfq-fix-waker_bfqq-inconsistency-crash.patch new file mode 100644 index 00000000000..fa550b07c93 --- /dev/null +++ b/queue-5.15/bfq-fix-waker_bfqq-inconsistency-crash.patch @@ -0,0 +1,77 @@ +From 8581f80d1bb6bcc275e1d4cf6dfc6eb6e32f9208 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 10:10:29 -0800 +Subject: bfq: fix waker_bfqq inconsistency crash + +From: Khazhismel Kumykov + +[ Upstream commit a1795c2ccb1e4c49220d2a0d381540024d71647c ] + +This fixes crashes in bfq_add_bfqq_busy due to waker_bfqq being NULL, +but woken_list_node still being hashed. This would happen when +bfq_init_rq() expects a brand new allocated queue to be returned from +bfq_get_bfqq_handle_split() and unconditionally updates waker_bfqq +without resetting woken_list_node. Since we can always return oom_bfqq +when attempting to allocate, we cannot assume waker_bfqq starts as NULL. + +Avoid setting woken_bfqq for oom_bfqq entirely, as it's not useful. + +Crashes would have a stacktrace like: +[160595.656560] bfq_add_bfqq_busy+0x110/0x1ec +[160595.661142] bfq_add_request+0x6bc/0x980 +[160595.666602] bfq_insert_request+0x8ec/0x1240 +[160595.671762] bfq_insert_requests+0x58/0x9c +[160595.676420] blk_mq_sched_insert_request+0x11c/0x198 +[160595.682107] blk_mq_submit_bio+0x270/0x62c +[160595.686759] __submit_bio_noacct_mq+0xec/0x178 +[160595.691926] submit_bio+0x120/0x184 +[160595.695990] ext4_mpage_readpages+0x77c/0x7c8 +[160595.701026] ext4_readpage+0x60/0xb0 +[160595.705158] filemap_read_page+0x54/0x114 +[160595.711961] filemap_fault+0x228/0x5f4 +[160595.716272] do_read_fault+0xe0/0x1f0 +[160595.720487] do_fault+0x40/0x1c8 + +Tested by injecting random failures into bfq_get_queue, crashes go away +completely. + +Fixes: 8ef3fc3a043c ("block, bfq: make shared queues inherit wakers") +Signed-off-by: Khazhismel Kumykov +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221108181030.1611703-1-khazhy@google.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bfq-iosched.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index 7d8fe13573f6..f21b861a0d66 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -6630,6 +6630,12 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + bfqq = bfq_get_bfqq_handle_split(bfqd, bic, bio, + true, is_sync, + NULL); ++ if (unlikely(bfqq == &bfqd->oom_bfqq)) ++ bfqq_already_existing = true; ++ } else ++ bfqq_already_existing = true; ++ ++ if (!bfqq_already_existing) { + bfqq->waker_bfqq = old_bfqq->waker_bfqq; + bfqq->tentative_waker_bfqq = NULL; + +@@ -6643,8 +6649,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq) + if (bfqq->waker_bfqq) + hlist_add_head(&bfqq->woken_list_node, + &bfqq->waker_bfqq->woken_list); +- } else +- bfqq_already_existing = true; ++ } + } + } + +-- +2.35.1 + diff --git a/queue-5.15/binfmt_misc-fix-shift-out-of-bounds-in-check_special.patch b/queue-5.15/binfmt_misc-fix-shift-out-of-bounds-in-check_special.patch new file mode 100644 index 00000000000..2630f52bb56 --- /dev/null +++ b/queue-5.15/binfmt_misc-fix-shift-out-of-bounds-in-check_special.patch @@ -0,0 +1,61 @@ +From ab74c11ae92bc3cbe67bd77eba3b2557e571093f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 10:51:23 +0800 +Subject: binfmt_misc: fix shift-out-of-bounds in check_special_flags + +From: Liu Shixin + +[ Upstream commit 6a46bf558803dd2b959ca7435a5c143efe837217 ] + +UBSAN reported a shift-out-of-bounds warning: + + left shift of 1 by 31 places cannot be represented in type 'int' + Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x8d/0xcf lib/dump_stack.c:106 + ubsan_epilogue+0xa/0x44 lib/ubsan.c:151 + __ubsan_handle_shift_out_of_bounds+0x1e7/0x208 lib/ubsan.c:322 + check_special_flags fs/binfmt_misc.c:241 [inline] + create_entry fs/binfmt_misc.c:456 [inline] + bm_register_write+0x9d3/0xa20 fs/binfmt_misc.c:654 + vfs_write+0x11e/0x580 fs/read_write.c:582 + ksys_write+0xcf/0x120 fs/read_write.c:637 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x34/0x80 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + RIP: 0033:0x4194e1 + +Since the type of Node's flags is unsigned long, we should define these +macros with same type too. + +Signed-off-by: Liu Shixin +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20221102025123.1117184-1-liushixin2@huawei.com +Signed-off-by: Sasha Levin +--- + fs/binfmt_misc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c +index e1eae7ea823a..bb202ad369d5 100644 +--- a/fs/binfmt_misc.c ++++ b/fs/binfmt_misc.c +@@ -44,10 +44,10 @@ static LIST_HEAD(entries); + static int enabled = 1; + + enum {Enabled, Magic}; +-#define MISC_FMT_PRESERVE_ARGV0 (1 << 31) +-#define MISC_FMT_OPEN_BINARY (1 << 30) +-#define MISC_FMT_CREDENTIALS (1 << 29) +-#define MISC_FMT_OPEN_FILE (1 << 28) ++#define MISC_FMT_PRESERVE_ARGV0 (1UL << 31) ++#define MISC_FMT_OPEN_BINARY (1UL << 30) ++#define MISC_FMT_CREDENTIALS (1UL << 29) ++#define MISC_FMT_OPEN_FILE (1UL << 28) + + typedef struct { + struct list_head list; +-- +2.35.1 + diff --git a/queue-5.15/blk-iocost-simplify-ioc_name.patch b/queue-5.15/blk-iocost-simplify-ioc_name.patch new file mode 100644 index 00000000000..c9d35549c9e --- /dev/null +++ b/queue-5.15/blk-iocost-simplify-ioc_name.patch @@ -0,0 +1,53 @@ +From 544655d1492227d5b309feb166eaf7999f2058ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 20:04:53 +0200 +Subject: blk-iocost: simplify ioc_name + +From: Christoph Hellwig + +[ Upstream commit 9df3e65139b923dfe98f76b7057882c7afb2d3e4 ] + +Just directly dereference the disk name instead of going through multiple +hoops to find the same value. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Andreas Herrmann +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20220921180501.1539876-10-hch@lst.de +Signed-off-by: Jens Axboe +Stable-dep-of: d36a9ea5e776 ("block: fix use-after-free of q->q_usage_counter") +Signed-off-by: Sasha Levin +--- + block/blk-iocost.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/block/blk-iocost.c b/block/blk-iocost.c +index 069193dee95b..f5b501888ba4 100644 +--- a/block/blk-iocost.c ++++ b/block/blk-iocost.c +@@ -665,17 +665,13 @@ static struct ioc *q_to_ioc(struct request_queue *q) + return rqos_to_ioc(rq_qos_id(q, RQ_QOS_COST)); + } + +-static const char *q_name(struct request_queue *q) +-{ +- if (blk_queue_registered(q)) +- return kobject_name(q->kobj.parent); +- else +- return ""; +-} +- + static const char __maybe_unused *ioc_name(struct ioc *ioc) + { +- return q_name(ioc->rqos.q); ++ struct gendisk *disk = ioc->rqos.q->disk; ++ ++ if (!disk) ++ return ""; ++ return disk->disk_name; + } + + static struct ioc_gq *pd_to_iocg(struct blkg_policy_data *pd) +-- +2.35.1 + diff --git a/queue-5.15/blk-mq-fix-possible-memleak-when-register-hctx-faile.patch b/queue-5.15/blk-mq-fix-possible-memleak-when-register-hctx-faile.patch new file mode 100644 index 00000000000..e06644979b4 --- /dev/null +++ b/queue-5.15/blk-mq-fix-possible-memleak-when-register-hctx-faile.patch @@ -0,0 +1,86 @@ +From 3eb72ac5bb9ee282c458ae0add628aa5ac946cb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 10:29:40 +0800 +Subject: blk-mq: fix possible memleak when register 'hctx' failed + +From: Ye Bin + +[ Upstream commit 4b7a21c57b14fbcd0e1729150189e5933f5088e9 ] + +There's issue as follows when do fault injection test: +unreferenced object 0xffff888132a9f400 (size 512): + comm "insmod", pid 308021, jiffies 4324277909 (age 509.733s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 08 f4 a9 32 81 88 ff ff ...........2.... + 08 f4 a9 32 81 88 ff ff 00 00 00 00 00 00 00 00 ...2............ + backtrace: + [<00000000e8952bb4>] kmalloc_node_trace+0x22/0xa0 + [<00000000f9980e0f>] blk_mq_alloc_and_init_hctx+0x3f1/0x7e0 + [<000000002e719efa>] blk_mq_realloc_hw_ctxs+0x1e6/0x230 + [<000000004f1fda40>] blk_mq_init_allocated_queue+0x27e/0x910 + [<00000000287123ec>] __blk_mq_alloc_disk+0x67/0xf0 + [<00000000a2a34657>] 0xffffffffa2ad310f + [<00000000b173f718>] 0xffffffffa2af824a + [<0000000095a1dabb>] do_one_initcall+0x87/0x2a0 + [<00000000f32fdf93>] do_init_module+0xdf/0x320 + [<00000000cbe8541e>] load_module+0x3006/0x3390 + [<0000000069ed1bdb>] __do_sys_finit_module+0x113/0x1b0 + [<00000000a1a29ae8>] do_syscall_64+0x35/0x80 + [<000000009cd878b0>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +Fault injection context as follows: + kobject_add + blk_mq_register_hctx + blk_mq_sysfs_register + blk_register_queue + device_add_disk + null_add_dev.part.0 [null_blk] + +As 'blk_mq_register_hctx' may already add some objects when failed halfway, +but there isn't do fallback, caller don't know which objects add failed. +To solve above issue just do fallback when add objects failed halfway in +'blk_mq_register_hctx'. + +Signed-off-by: Ye Bin +Reviewed-by: Ming Lei +Link: https://lore.kernel.org/r/20221117022940.873959-1-yebin@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-mq-sysfs.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c +index 253c857cba47..7074ce8d2d03 100644 +--- a/block/blk-mq-sysfs.c ++++ b/block/blk-mq-sysfs.c +@@ -187,7 +187,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) + { + struct request_queue *q = hctx->queue; + struct blk_mq_ctx *ctx; +- int i, ret; ++ int i, j, ret; + + if (!hctx->nr_ctx) + return 0; +@@ -199,9 +199,16 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx) + hctx_for_each_ctx(hctx, ctx, i) { + ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu); + if (ret) +- break; ++ goto out; + } + ++ return 0; ++out: ++ hctx_for_each_ctx(hctx, ctx, j) { ++ if (j < i) ++ kobject_del(&ctx->kobj); ++ } ++ kobject_del(&hctx->kobj); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/blktrace-fix-output-non-blktrace-event-when-blk_clas.patch b/queue-5.15/blktrace-fix-output-non-blktrace-event-when-blk_clas.patch new file mode 100644 index 00000000000..bd04c4f98cc --- /dev/null +++ b/queue-5.15/blktrace-fix-output-non-blktrace-event-when-blk_clas.patch @@ -0,0 +1,47 @@ +From 4b375b6504c9d8fb1d3b1d1fd77ae6fe82bbc43e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 12:04:10 +0800 +Subject: blktrace: Fix output non-blktrace event when blk_classic option + enabled + +From: Yang Jihong + +[ Upstream commit f596da3efaf4130ff61cd029558845808df9bf99 ] + +When the blk_classic option is enabled, non-blktrace events must be +filtered out. Otherwise, events of other types are output in the blktrace +classic format, which is unexpected. + +The problem can be triggered in the following ways: + + # echo 1 > /sys/kernel/debug/tracing/options/blk_classic + # echo 1 > /sys/kernel/debug/tracing/events/enable + # echo blk > /sys/kernel/debug/tracing/current_tracer + # cat /sys/kernel/debug/tracing/trace_pipe + +Fixes: c71a89615411 ("blktrace: add ftrace plugin") +Signed-off-by: Yang Jihong +Link: https://lore.kernel.org/r/20221122040410.85113-1-yangjihong1@huawei.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + kernel/trace/blktrace.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c +index eaa98e2b468f..16b0d3fa56e0 100644 +--- a/kernel/trace/blktrace.c ++++ b/kernel/trace/blktrace.c +@@ -1547,7 +1547,8 @@ blk_trace_event_print_binary(struct trace_iterator *iter, int flags, + + static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter) + { +- if (!(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC)) ++ if ((iter->ent->type != TRACE_BLK) || ++ !(blk_tracer_flags.val & TRACE_BLK_OPT_CLASSIC)) + return TRACE_TYPE_UNHANDLED; + + return print_one_line(iter, true); +-- +2.35.1 + diff --git a/queue-5.15/block-bfq-fix-possible-uaf-for-bfqq-bic.patch b/queue-5.15/block-bfq-fix-possible-uaf-for-bfqq-bic.patch new file mode 100644 index 00000000000..1fce6f21960 --- /dev/null +++ b/queue-5.15/block-bfq-fix-possible-uaf-for-bfqq-bic.patch @@ -0,0 +1,125 @@ +From 251cb9b241889fa1ac97b86127cdf8b4119e4782 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Dec 2022 11:04:30 +0800 +Subject: block, bfq: fix possible uaf for 'bfqq->bic' +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yu Kuai + +[ Upstream commit 64dc8c732f5c2b406cc752e6aaa1bd5471159cab ] + +Our test report a uaf for 'bfqq->bic' in 5.10: + +================================================================== +BUG: KASAN: use-after-free in bfq_select_queue+0x378/0xa30 + +CPU: 6 PID: 2318352 Comm: fsstress Kdump: loaded Not tainted 5.10.0-60.18.0.50.h602.kasan.eulerosv2r11.x86_64 #1 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58-20220320_160524-szxrtosci10000 04/01/2014 +Call Trace: + bfq_select_queue+0x378/0xa30 + bfq_dispatch_request+0xe8/0x130 + blk_mq_do_dispatch_sched+0x62/0xb0 + __blk_mq_sched_dispatch_requests+0x215/0x2a0 + blk_mq_sched_dispatch_requests+0x8f/0xd0 + __blk_mq_run_hw_queue+0x98/0x180 + __blk_mq_delay_run_hw_queue+0x22b/0x240 + blk_mq_run_hw_queue+0xe3/0x190 + blk_mq_sched_insert_requests+0x107/0x200 + blk_mq_flush_plug_list+0x26e/0x3c0 + blk_finish_plug+0x63/0x90 + __iomap_dio_rw+0x7b5/0x910 + iomap_dio_rw+0x36/0x80 + ext4_dio_read_iter+0x146/0x190 [ext4] + ext4_file_read_iter+0x1e2/0x230 [ext4] + new_sync_read+0x29f/0x400 + vfs_read+0x24e/0x2d0 + ksys_read+0xd5/0x1b0 + do_syscall_64+0x33/0x40 + entry_SYSCALL_64_after_hwframe+0x61/0xc6 + +Commit 3bc5e683c67d ("bfq: Split shared queues on move between cgroups") +changes that move process to a new cgroup will allocate a new bfqq to +use, however, the old bfqq and new bfqq can point to the same bic: + +1) Initial state, two process with io in the same cgroup. + +Process 1 Process 2 + (BIC1) (BIC2) + | Λ | Λ + | | | | + V | V | + bfqq1 bfqq2 + +2) bfqq1 is merged to bfqq2. + +Process 1 Process 2 + (BIC1) (BIC2) + | | + \-------------\| + V + bfqq1 bfqq2(coop) + +3) Process 1 exit, then issue new io(denoce IOA) from Process 2. + + (BIC2) + | Λ + | | + V | + bfqq2(coop) + +4) Before IOA is completed, move Process 2 to another cgroup and issue io. + +Process 2 + (BIC2) + Λ + |\--------------\ + | V + bfqq2 bfqq3 + +Now that BIC2 points to bfqq3, while bfqq2 and bfqq3 both point to BIC2. +If all the requests are completed, and Process 2 exit, BIC2 will be +freed while there is no guarantee that bfqq2 will be freed before BIC2. + +Fix the problem by clearing bfqq->bic while bfqq is detached from bic. + +Fixes: 3bc5e683c67d ("bfq: Split shared queues on move between cgroups") +Suggested-by: Jan Kara +Signed-off-by: Yu Kuai +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221214030430.3304151-1-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/bfq-iosched.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c +index f21b861a0d66..b8b6e9eae94b 100644 +--- a/block/bfq-iosched.c ++++ b/block/bfq-iosched.c +@@ -386,6 +386,12 @@ static void bfq_put_stable_ref(struct bfq_queue *bfqq); + + void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync) + { ++ struct bfq_queue *old_bfqq = bic->bfqq[is_sync]; ++ ++ /* Clear bic pointer if bfqq is detached from this bic */ ++ if (old_bfqq && old_bfqq->bic == bic) ++ old_bfqq->bic = NULL; ++ + /* + * If bfqq != NULL, then a non-stable queue merge between + * bic->bfqq and bfqq is happening here. This causes troubles +@@ -5245,7 +5251,6 @@ static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync) + unsigned long flags; + + spin_lock_irqsave(&bfqd->lock, flags); +- bfqq->bic = NULL; + bfq_exit_bfqq(bfqd, bfqq); + bic_set_bfqq(bic, NULL, is_sync); + spin_unlock_irqrestore(&bfqd->lock, flags); +-- +2.35.1 + diff --git a/queue-5.15/block-clear-slave_dir-when-dropping-the-main-slave_d.patch b/queue-5.15/block-clear-slave_dir-when-dropping-the-main-slave_d.patch new file mode 100644 index 00000000000..25777d67b6a --- /dev/null +++ b/queue-5.15/block-clear-slave_dir-when-dropping-the-main-slave_d.patch @@ -0,0 +1,48 @@ +From 3b790cd7d9876f3decb9acf520ab16ae66df107e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 22:10:45 +0800 +Subject: block: clear ->slave_dir when dropping the main slave_dir reference + +From: Christoph Hellwig + +[ Upstream commit d90db3b1c8676bc88b4309c5a571333de2263b8e ] + +Zero out the pointer to ->slave_dir so that the holder code doesn't +incorrectly treat the object as alive when add_disk failed or after +del_gendisk was called. + +Fixes: 89f871af1b26 ("dm: delay registering the gendisk") +Reported-by: Yu Kuai +Signed-off-by: Christoph Hellwig +Signed-off-by: Yu Kuai +Reviewed-by: Mike Snitzer +Link: https://lore.kernel.org/r/20221115141054.1051801-2-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/genhd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/block/genhd.c b/block/genhd.c +index 68065189ca17..a1d9e785dcf7 100644 +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -530,6 +530,7 @@ int device_add_disk(struct device *parent, struct gendisk *disk, + rq_qos_exit(disk->queue); + out_put_slave_dir: + kobject_put(disk->slave_dir); ++ disk->slave_dir = NULL; + out_put_holder_dir: + kobject_put(disk->part0->bd_holder_dir); + out_del_integrity: +@@ -624,6 +625,7 @@ void del_gendisk(struct gendisk *disk) + + kobject_put(disk->part0->bd_holder_dir); + kobject_put(disk->slave_dir); ++ disk->slave_dir = NULL; + + part_stat_set_all(disk->part0, 0); + disk->part0->bd_stamp = 0; +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-btintel-fix-missing-free-skb-in-btintel_se.patch b/queue-5.15/bluetooth-btintel-fix-missing-free-skb-in-btintel_se.patch new file mode 100644 index 00000000000..89e2afc4ee8 --- /dev/null +++ b/queue-5.15/bluetooth-btintel-fix-missing-free-skb-in-btintel_se.patch @@ -0,0 +1,50 @@ +From 533cbfc1f0590d2e74b3aa47adbbeefb3ec17eaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 21:53:57 +0800 +Subject: Bluetooth: btintel: Fix missing free skb in btintel_setup_combined() + +From: Wang ShaoBo + +[ Upstream commit cee50ce899de415baf4da3ed38b7d4f13c3170d1 ] + +skb allocated by __hci_cmd_sync would not be used whether in checking +for supported iBT hardware variants or after, we should free it in all +error branches, this patch makes the case read version failed or default +error case free skb before return. + +Fixes: c86c7285bb08 ("Bluetooth: btintel: Fix the legacy bootloader returns tlv based version") +Fixes: 019a1caa7fd2 ("Bluetooth: btintel: Refactoring setup routine for bootloader devices") +Signed-off-by: Wang ShaoBo +Reviewed-by: Tedd Ho-Jeong An +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index de3d851d85e7..d707aa63e944 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2353,7 +2353,7 @@ static int btintel_setup_combined(struct hci_dev *hdev) + */ + err = btintel_read_version(hdev, &ver); + if (err) +- return err; ++ break; + + /* Apply the device specific HCI quirks + * +@@ -2394,7 +2394,8 @@ static int btintel_setup_combined(struct hci_dev *hdev) + default: + bt_dev_err(hdev, "Unsupported Intel hw variant (%u)", + INTEL_HW_VARIANT(ver_tlv.cnvi_bt)); +- return -EINVAL; ++ err = -EINVAL; ++ break; + } + + exit_error: +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-btusb-don-t-call-kfree_skb-under-spin_lock.patch b/queue-5.15/bluetooth-btusb-don-t-call-kfree_skb-under-spin_lock.patch new file mode 100644 index 00000000000..5f4b4818a21 --- /dev/null +++ b/queue-5.15/bluetooth-btusb-don-t-call-kfree_skb-under-spin_lock.patch @@ -0,0 +1,45 @@ +From 7e638f5f37600aa82240a569ba634627c248b9e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 20:59:10 +0800 +Subject: Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit b15a6bd3c80c77faec8317319b97f976b1a08332 ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 803b58367ffb ("Bluetooth: btusb: Implement driver internal packet reassembly") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 69380cb03dd3..9c32263f872b 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -735,13 +735,13 @@ static inline void btusb_free_frags(struct btusb_data *data) + + spin_lock_irqsave(&data->rxlock, flags); + +- kfree_skb(data->evt_skb); ++ dev_kfree_skb_irq(data->evt_skb); + data->evt_skb = NULL; + +- kfree_skb(data->acl_skb); ++ dev_kfree_skb_irq(data->acl_skb); + data->acl_skb = NULL; + +- kfree_skb(data->sco_skb); ++ dev_kfree_skb_irq(data->sco_skb); + data->sco_skb = NULL; + + spin_unlock_irqrestore(&data->rxlock, flags); +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-hci_bcsp-don-t-call-kfree_skb-under-spin_l.patch b/queue-5.15/bluetooth-hci_bcsp-don-t-call-kfree_skb-under-spin_l.patch new file mode 100644 index 00000000000..72a2c75a52f --- /dev/null +++ b/queue-5.15/bluetooth-hci_bcsp-don-t-call-kfree_skb-under-spin_l.patch @@ -0,0 +1,37 @@ +From 0f52291f8a865b6170bdf72b23ea56822fb0d7e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:33 +0800 +Subject: Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 7b503e339c1a80bf0051ec2d19c3bc777014ac61 ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_bcsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c +index cf4a56095817..8055f63603f4 100644 +--- a/drivers/bluetooth/hci_bcsp.c ++++ b/drivers/bluetooth/hci_bcsp.c +@@ -378,7 +378,7 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp) + i++; + + __skb_unlink(skb, &bcsp->unack); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + if (skb_queue_empty(&bcsp->unack)) +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-hci_core-don-t-call-kfree_skb-under-spin_l.patch b/queue-5.15/bluetooth-hci_core-don-t-call-kfree_skb-under-spin_l.patch new file mode 100644 index 00000000000..f8c6f6723e8 --- /dev/null +++ b/queue-5.15/bluetooth-hci_core-don-t-call-kfree_skb-under-spin_l.patch @@ -0,0 +1,37 @@ +From be98f0736182c9dc531e1b28deb89a4114c5cbd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:34 +0800 +Subject: Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 39c1eb6fcbae8ce9bb71b2ac5cb609355a2b181b ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 9238f36a5a50 ("Bluetooth: Add request cmd_complete and cmd_status functions") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index bb84ff5fb98a..a41b4dcf1a7a 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -5101,7 +5101,7 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, + *req_complete_skb = bt_cb(skb)->hci.req_complete_skb; + else + *req_complete = bt_cb(skb)->hci.req_complete; +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + spin_unlock_irqrestore(&hdev->cmd_q.lock, flags); + } +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-hci_h5-don-t-call-kfree_skb-under-spin_loc.patch b/queue-5.15/bluetooth-hci_h5-don-t-call-kfree_skb-under-spin_loc.patch new file mode 100644 index 00000000000..475f8bfda0d --- /dev/null +++ b/queue-5.15/bluetooth-hci_h5-don-t-call-kfree_skb-under-spin_loc.patch @@ -0,0 +1,37 @@ +From 9181974b5c1d6e072b77f681cc7db31c878d12c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:32 +0800 +Subject: Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 383630cc6758d619874c2e8bb2f68a61f3f9ef6e ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 43eb12d78960 ("Bluetooth: Fix/implement Three-wire reliable packet sending") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_h5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index e0ea9d25bb39..1363b21c81b7 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -313,7 +313,7 @@ static void h5_pkt_cull(struct h5 *h5) + break; + + __skb_unlink(skb, &h5->unack); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + } + + if (skb_queue_empty(&h5->unack)) +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-hci_ll-don-t-call-kfree_skb-under-spin_loc.patch b/queue-5.15/bluetooth-hci_ll-don-t-call-kfree_skb-under-spin_loc.patch new file mode 100644 index 00000000000..24c63fa54e1 --- /dev/null +++ b/queue-5.15/bluetooth-hci_ll-don-t-call-kfree_skb-under-spin_loc.patch @@ -0,0 +1,37 @@ +From 73d3baed520a1600861a702be8a04c77f1628255 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:31 +0800 +Subject: Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 8f458f783dfbb19c1f1cb58ed06eeb701f52091b ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 166d2f6a4332 ("[Bluetooth] Add UART driver for Texas Instruments' BRF63xx chips") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ll.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c +index eb1e736efeeb..e4e5b26e2c33 100644 +--- a/drivers/bluetooth/hci_ll.c ++++ b/drivers/bluetooth/hci_ll.c +@@ -345,7 +345,7 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) + default: + BT_ERR("illegal hcill state: %ld (losing packet)", + ll->hcill_state); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + break; + } + +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-hci_qca-don-t-call-kfree_skb-under-spin_lo.patch b/queue-5.15/bluetooth-hci_qca-don-t-call-kfree_skb-under-spin_lo.patch new file mode 100644 index 00000000000..cf60818c425 --- /dev/null +++ b/queue-5.15/bluetooth-hci_qca-don-t-call-kfree_skb-under-spin_lo.patch @@ -0,0 +1,37 @@ +From 895e7a2f6644452f5a737d124b92398ad656a3bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:30 +0800 +Subject: Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit df4cfc91208e0a98f078223793f5871b1a82cc54 ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 0ff252c1976d ("Bluetooth: hciuart: Add support QCA chipset for UART") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_qca.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index ed91af4319b5..5d0428fc854f 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -912,7 +912,7 @@ static int qca_enqueue(struct hci_uart *hu, struct sk_buff *skb) + default: + BT_ERR("Illegal tx state: %d (losing packet)", + qca->tx_ibs_state); +- kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + break; + } + +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-mgmt-fix-error-report-for-add_ext_adv_para.patch b/queue-5.15/bluetooth-mgmt-fix-error-report-for-add_ext_adv_para.patch new file mode 100644 index 00000000000..14b0abd7ee2 --- /dev/null +++ b/queue-5.15/bluetooth-mgmt-fix-error-report-for-add_ext_adv_para.patch @@ -0,0 +1,37 @@ +From 4639b481e9a04c12598cad69439c99c566c48835 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 17:48:56 -0700 +Subject: Bluetooth: MGMT: Fix error report for ADD_EXT_ADV_PARAMS + +From: Inga Stotland + +[ Upstream commit 3b1c7c00b8c22b3cb79532252c59eb0b287bb86d ] + +When validating the parameter length for MGMT_OP_ADD_EXT_ADV_PARAMS +command, use the correct op code in error status report: +was MGMT_OP_ADD_ADVERTISING, changed to MGMT_OP_ADD_EXT_ADV_PARAMS. + +Fixes: 12410572833a2 ("Bluetooth: Break add adv into two mgmt commands") +Signed-off-by: Inga Stotland +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/mgmt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c +index f09f0a78eb7b..04000499f4a2 100644 +--- a/net/bluetooth/mgmt.c ++++ b/net/bluetooth/mgmt.c +@@ -7971,7 +7971,7 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, + * extra parameters we don't know about will be ignored in this request. + */ + if (data_len < MGMT_ADD_EXT_ADV_PARAMS_MIN_SIZE) +- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, ++ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS, + MGMT_STATUS_INVALID_PARAMS); + + flags = __le32_to_cpu(cp->flags); +-- +2.35.1 + diff --git a/queue-5.15/bluetooth-rfcomm-don-t-call-kfree_skb-under-spin_loc.patch b/queue-5.15/bluetooth-rfcomm-don-t-call-kfree_skb-under-spin_loc.patch new file mode 100644 index 00000000000..decd8deb111 --- /dev/null +++ b/queue-5.15/bluetooth-rfcomm-don-t-call-kfree_skb-under-spin_loc.patch @@ -0,0 +1,37 @@ +From 0afa80088b1e1f9c67d9d1d2a796fa41f26e6d03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 10:18:35 +0800 +Subject: Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 0ba18967d4544955b2eff2fbc4f2a8750c4df90a ] + +It is not allowed to call kfree_skb() from hardware interrupt +context or with interrupts being disabled. So replace kfree_skb() +with dev_kfree_skb_irq() under spin_lock_irqsave(). + +Fixes: 81be03e026dc ("Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg") +Signed-off-by: Yang Yingliang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/rfcomm/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c +index 7324764384b6..8d6fce9005bd 100644 +--- a/net/bluetooth/rfcomm/core.c ++++ b/net/bluetooth/rfcomm/core.c +@@ -590,7 +590,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) + + ret = rfcomm_dlc_send_frag(d, frag); + if (ret < 0) { +- kfree_skb(frag); ++ dev_kfree_skb_irq(frag); + goto unlock; + } + +-- +2.35.1 + diff --git a/queue-5.15/bonding-fix-link-recovery-in-mode-2-when-updelay-is-.patch b/queue-5.15/bonding-fix-link-recovery-in-mode-2-when-updelay-is-.patch new file mode 100644 index 00000000000..06221dea90d --- /dev/null +++ b/queue-5.15/bonding-fix-link-recovery-in-mode-2-when-updelay-is-.patch @@ -0,0 +1,49 @@ +From e8ffa109d0fec17672b64f15644c1a150aca6a66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 16:24:29 -0500 +Subject: bonding: fix link recovery in mode 2 when updelay is nonzero + +From: Jonathan Toppins + +[ Upstream commit f8a65ab2f3ff7410921ebbf0dc55453102c33c56 ] + +Before this change when a bond in mode 2 lost link, all of its slaves +lost link, the bonding device would never recover even after the +expiration of updelay. This change removes the updelay when the bond +currently has no usable links. Conforming to bonding.txt section 13.1 +paragraph 4. + +Fixes: 41f891004063 ("bonding: ignore updelay param when there is no active slave") +Signed-off-by: Jonathan Toppins +Acked-by: Jay Vosburgh +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 402dffc508ef..6dca5bfe8247 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2504,7 +2504,16 @@ static int bond_miimon_inspect(struct bonding *bond) + struct slave *slave; + bool ignore_updelay; + +- ignore_updelay = !rcu_dereference(bond->curr_active_slave); ++ if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { ++ ignore_updelay = !rcu_dereference(bond->curr_active_slave); ++ } else { ++ struct bond_up_slave *usable_slaves; ++ ++ usable_slaves = rcu_dereference(bond->usable_slaves); ++ ++ if (usable_slaves && usable_slaves->count == 0) ++ ignore_updelay = true; ++ } + + bond_for_each_slave_rcu(bond, slave, iter) { + bond_propose_link_state(slave, BOND_LINK_NOCHANGE); +-- +2.35.1 + diff --git a/queue-5.15/bonding-uninitialized-variable-in-bond_miimon_inspec.patch b/queue-5.15/bonding-uninitialized-variable-in-bond_miimon_inspec.patch new file mode 100644 index 00000000000..8e4e84eda16 --- /dev/null +++ b/queue-5.15/bonding-uninitialized-variable-in-bond_miimon_inspec.patch @@ -0,0 +1,41 @@ +From 8f2ad94ce2fb3b1ecd28d4f2f76df2d8714f17f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 14:06:14 +0300 +Subject: bonding: uninitialized variable in bond_miimon_inspect() + +From: Dan Carpenter + +[ Upstream commit e5214f363dabca240446272dac54d404501ad5e5 ] + +The "ignore_updelay" variable needs to be initialized to false. + +Fixes: f8a65ab2f3ff ("bonding: fix link recovery in mode 2 when updelay is nonzero") +Signed-off-by: Dan Carpenter +Reviewed-by: Pavan Chebbi +Acked-by: Jay Vosburgh +Link: https://lore.kernel.org/r/Y4SWJlh3ohJ6EPTL@kili +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 6dca5bfe8247..456298919d54 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2499,10 +2499,10 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in + /* called with rcu_read_lock() */ + static int bond_miimon_inspect(struct bonding *bond) + { ++ bool ignore_updelay = false; + int link_state, commit = 0; + struct list_head *iter; + struct slave *slave; +- bool ignore_updelay; + + if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) { + ignore_updelay = !rcu_dereference(bond->curr_active_slave); +-- +2.35.1 + diff --git a/queue-5.15/bpf-check-the-other-end-of-slot_type-for-stack_spill.patch b/queue-5.15/bpf-check-the-other-end-of-slot_type-for-stack_spill.patch new file mode 100644 index 00000000000..ee0eccce3ba --- /dev/null +++ b/queue-5.15/bpf-check-the-other-end-of-slot_type-for-stack_spill.patch @@ -0,0 +1,147 @@ +From b467dbf5840723a9a18e8e47f0bd31a50f2d425b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Sep 2021 17:49:34 -0700 +Subject: bpf: Check the other end of slot_type for STACK_SPILL + +From: Martin KaFai Lau + +[ Upstream commit 27113c59b6d0a587b29ae72d4ff3f832f58b0651 ] + +Every 8 bytes of the stack is tracked by a bpf_stack_state. +Within each bpf_stack_state, there is a 'u8 slot_type[8]' to track +the type of each byte. Verifier tests slot_type[0] == STACK_SPILL +to decide if the spilled reg state is saved. Verifier currently only +saves the reg state if the whole 8 bytes are spilled to the stack, +so checking the slot_type[7] is the same as checking slot_type[0]. + +The later patch will allow verifier to save the bounded scalar +reg also for <8 bytes spill. There is a llvm patch [1] to ensure +the <8 bytes spill will be 8-byte aligned, so checking +slot_type[7] instead of slot_type[0] is required. + +While at it, this patch refactors the slot_type[0] == STACK_SPILL +test into a new function is_spilled_reg() and change the +slot_type[0] check to slot_type[7] check in there also. + +[1] https://reviews.llvm.org/D109073 + +Signed-off-by: Martin KaFai Lau +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20210922004934.624194-1-kafai@fb.com +Stable-dep-of: 529409ea92d5 ("bpf: propagate precision across all frames, not just the last one") +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 98d182dc848a..a0a1061eabb1 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -606,6 +606,14 @@ static const char *kernel_type_name(const struct btf* btf, u32 id) + return btf_name_by_offset(btf, btf_type_by_id(btf, id)->name_off); + } + ++/* The reg state of a pointer or a bounded scalar was saved when ++ * it was spilled to the stack. ++ */ ++static bool is_spilled_reg(const struct bpf_stack_state *stack) ++{ ++ return stack->slot_type[BPF_REG_SIZE - 1] == STACK_SPILL; ++} ++ + static void print_verifier_state(struct bpf_verifier_env *env, + const struct bpf_func_state *state) + { +@@ -709,7 +717,7 @@ static void print_verifier_state(struct bpf_verifier_env *env, + continue; + verbose(env, " fp%d", (-i - 1) * BPF_REG_SIZE); + print_liveness(env, state->stack[i].spilled_ptr.live); +- if (state->stack[i].slot_type[0] == STACK_SPILL) { ++ if (is_spilled_reg(&state->stack[i])) { + reg = &state->stack[i].spilled_ptr; + t = reg->type; + verbose(env, "=%s", reg_type_str(env, t)); +@@ -2351,7 +2359,7 @@ static void mark_all_scalars_precise(struct bpf_verifier_env *env, + reg->precise = true; + } + for (j = 0; j < func->allocated_stack / BPF_REG_SIZE; j++) { +- if (func->stack[j].slot_type[0] != STACK_SPILL) ++ if (!is_spilled_reg(&func->stack[j])) + continue; + reg = &func->stack[j].spilled_ptr; + if (reg->type != SCALAR_VALUE) +@@ -2393,7 +2401,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + } + + while (spi >= 0) { +- if (func->stack[spi].slot_type[0] != STACK_SPILL) { ++ if (!is_spilled_reg(&func->stack[spi])) { + stack_mask = 0; + break; + } +@@ -2492,7 +2500,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + return 0; + } + +- if (func->stack[i].slot_type[0] != STACK_SPILL) { ++ if (!is_spilled_reg(&func->stack[i])) { + stack_mask &= ~(1ull << i); + continue; + } +@@ -2682,7 +2690,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env, + /* regular write of data into stack destroys any spilled ptr */ + state->stack[spi].spilled_ptr.type = NOT_INIT; + /* Mark slots as STACK_MISC if they belonged to spilled ptr. */ +- if (state->stack[spi].slot_type[0] == STACK_SPILL) ++ if (is_spilled_reg(&state->stack[spi])) + for (i = 0; i < BPF_REG_SIZE; i++) + state->stack[spi].slot_type[i] = STACK_MISC; + +@@ -2895,7 +2903,7 @@ static int check_stack_read_fixed_off(struct bpf_verifier_env *env, + stype = reg_state->stack[spi].slot_type; + reg = ®_state->stack[spi].spilled_ptr; + +- if (stype[0] == STACK_SPILL) { ++ if (is_spilled_reg(®_state->stack[spi])) { + if (size != BPF_REG_SIZE) { + if (reg->type != SCALAR_VALUE) { + verbose_linfo(env, env->insn_idx, "; "); +@@ -4534,11 +4542,11 @@ static int check_stack_range_initialized( + goto mark; + } + +- if (state->stack[spi].slot_type[0] == STACK_SPILL && ++ if (is_spilled_reg(&state->stack[spi]) && + state->stack[spi].spilled_ptr.type == PTR_TO_BTF_ID) + goto mark; + +- if (state->stack[spi].slot_type[0] == STACK_SPILL && ++ if (is_spilled_reg(&state->stack[spi]) && + (state->stack[spi].spilled_ptr.type == SCALAR_VALUE || + env->allow_ptr_leaks)) { + if (clobber) { +@@ -10342,9 +10350,9 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old, + * return false to continue verification of this path + */ + return false; +- if (i % BPF_REG_SIZE) ++ if (i % BPF_REG_SIZE != BPF_REG_SIZE - 1) + continue; +- if (old->stack[spi].slot_type[0] != STACK_SPILL) ++ if (!is_spilled_reg(&old->stack[spi])) + continue; + if (!regsafe(env, &old->stack[spi].spilled_ptr, + &cur->stack[spi].spilled_ptr, idmap)) +@@ -10551,7 +10559,7 @@ static int propagate_precision(struct bpf_verifier_env *env, + } + + for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { +- if (state->stack[i].slot_type[0] != STACK_SPILL) ++ if (!is_spilled_reg(&state->stack[i])) + continue; + state_reg = &state->stack[i].spilled_ptr; + if (state_reg->type != SCALAR_VALUE || +-- +2.35.1 + diff --git a/queue-5.15/bpf-do-not-zero-extend-kfunc-return-values.patch b/queue-5.15/bpf-do-not-zero-extend-kfunc-return-values.patch new file mode 100644 index 00000000000..d96d794a569 --- /dev/null +++ b/queue-5.15/bpf-do-not-zero-extend-kfunc-return-values.patch @@ -0,0 +1,106 @@ +From ff1fd5812085ab2d56c3e9a17fc5da73672a1f3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 11:35:40 +0100 +Subject: bpf: Do not zero-extend kfunc return values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Björn Töpel + +[ Upstream commit d35af0a7feb077c43ff0233bba5a8c6e75b73e35 ] + +In BPF all global functions, and BPF helpers return a 64-bit +value. For kfunc calls, this is not the case, and they can return +e.g. 32-bit values. + +The return register R0 for kfuncs calls can therefore be marked as +subreg_def != DEF_NOT_SUBREG. In general, if a register is marked with +subreg_def != DEF_NOT_SUBREG, some archs (where bpf_jit_needs_zext() +returns true) require the verifier to insert explicit zero-extension +instructions. + +For kfuncs calls, however, the caller should do sign/zero extension +for return values. In other words, the compiler is responsible to +insert proper instructions, not the verifier. + +An example, provided by Yonghong Song: + +$ cat t.c +extern unsigned foo(void); +unsigned bar1(void) { + return foo(); +} +unsigned bar2(void) { + if (foo()) return 10; else return 20; +} + +$ clang -target bpf -mcpu=v3 -O2 -c t.c && llvm-objdump -d t.o +t.o: file format elf64-bpf + +Disassembly of section .text: + +0000000000000000 : + 0: 85 10 00 00 ff ff ff ff call -0x1 + 1: 95 00 00 00 00 00 00 00 exit + +0000000000000010 : + 2: 85 10 00 00 ff ff ff ff call -0x1 + 3: bc 01 00 00 00 00 00 00 w1 = w0 + 4: b4 00 00 00 14 00 00 00 w0 = 0x14 + 5: 16 01 01 00 00 00 00 00 if w1 == 0x0 goto +0x1 + 6: b4 00 00 00 0a 00 00 00 w0 = 0xa + +0000000000000038 : + 7: 95 00 00 00 00 00 00 00 exit + +If the return value of 'foo()' is used in the BPF program, the proper +zero-extension will be done. + +Currently, the verifier correctly marks, say, a 32-bit return value as +subreg_def != DEF_NOT_SUBREG, but will fail performing the actual +zero-extension, due to a verifier bug in +opt_subreg_zext_lo32_rnd_hi32(). load_reg is not properly set to R0, +and the following path will be taken: + + if (WARN_ON(load_reg == -1)) { + verbose(env, "verifier bug. zext_dst is set, but no reg is defined\n"); + return -EFAULT; + } + +A longer discussion from v1 can be found in the link below. + +Correct the verifier by avoiding doing explicit zero-extension of R0 +for kfunc calls. Note that R0 will still be marked as a sub-register +for return values smaller than 64-bit. + +Fixes: 83a2881903f3 ("bpf: Account for BPF_FETCH in insn_has_def32()") +Link: https://lore.kernel.org/bpf/20221202103620.1915679-1-bjorn@kernel.org/ +Suggested-by: Yonghong Song +Signed-off-by: Björn Töpel +Acked-by: Yonghong Song +Link: https://lore.kernel.org/r/20221207103540.396496-1-bjorn@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index b1ca4dbdeecf..488225bb42f6 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -12132,6 +12132,10 @@ static int opt_subreg_zext_lo32_rnd_hi32(struct bpf_verifier_env *env, + if (!bpf_jit_needs_zext() && !is_cmpxchg_insn(&insn)) + continue; + ++ /* Zero-extension is done by the caller. */ ++ if (bpf_pseudo_kfunc_call(&insn)) ++ continue; ++ + if (WARN_ON(load_reg == -1)) { + verbose(env, "verifier bug. zext_dst is set, but no reg is defined\n"); + return -EFAULT; +-- +2.35.1 + diff --git a/queue-5.15/bpf-fix-slot-type-check-in-check_stack_write_var_off.patch b/queue-5.15/bpf-fix-slot-type-check-in-check_stack_write_var_off.patch new file mode 100644 index 00000000000..34159bc5d52 --- /dev/null +++ b/queue-5.15/bpf-fix-slot-type-check-in-check_stack_write_var_off.patch @@ -0,0 +1,57 @@ +From 973ad6c3406bbc72d70fd62adf7ed7dbacb47b84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 00:39:53 +0530 +Subject: bpf: Fix slot type check in check_stack_write_var_off + +From: Kumar Kartikeya Dwivedi + +[ Upstream commit f5e477a861e4a20d8a1c5f7a245f3a3c3c376b03 ] + +For the case where allow_ptr_leaks is false, code is checking whether +slot type is STACK_INVALID and STACK_SPILL and rejecting other cases. +This is a consequence of incorrectly checking for register type instead +of the slot type (NOT_INIT and SCALAR_VALUE respectively). Fix the +check. + +Fixes: 01f810ace9ed ("bpf: Allow variable-offset stack access") +Signed-off-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20221103191013.1236066-5-memxor@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index cceb29b0585f..027ead3d0680 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2772,14 +2772,17 @@ static int check_stack_write_var_off(struct bpf_verifier_env *env, + spi = slot / BPF_REG_SIZE; + stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE]; + +- if (!env->allow_ptr_leaks +- && *stype != NOT_INIT +- && *stype != SCALAR_VALUE) { +- /* Reject the write if there's are spilled pointers in +- * range. If we didn't reject here, the ptr status +- * would be erased below (even though not all slots are +- * actually overwritten), possibly opening the door to +- * leaks. ++ if (!env->allow_ptr_leaks && *stype != STACK_MISC && *stype != STACK_ZERO) { ++ /* Reject the write if range we may write to has not ++ * been initialized beforehand. If we didn't reject ++ * here, the ptr status would be erased below (even ++ * though not all slots are actually overwritten), ++ * possibly opening the door to leaks. ++ * ++ * We do however catch STACK_INVALID case below, and ++ * only allow reading possibly uninitialized memory ++ * later for CAP_PERFMON, as the write may not happen to ++ * that slot. + */ + verbose(env, "spilled ptr in range of var-offset stack write; insn %d, ptr off: %d", + insn_idx, i); +-- +2.35.1 + diff --git a/queue-5.15/bpf-make-sure-skb-len-0-when-redirecting-to-a-tunnel.patch b/queue-5.15/bpf-make-sure-skb-len-0-when-redirecting-to-a-tunnel.patch new file mode 100644 index 00000000000..3e085beb98a --- /dev/null +++ b/queue-5.15/bpf-make-sure-skb-len-0-when-redirecting-to-a-tunnel.patch @@ -0,0 +1,73 @@ +From 79361f05f1f1975c0ee39724bcd72fa990f8d88e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 15:55:37 -0700 +Subject: bpf: make sure skb->len != 0 when redirecting to a tunneling device + +From: Stanislav Fomichev + +[ Upstream commit 07ec7b502800ba9f7b8b15cb01dd6556bb41aaca ] + +syzkaller managed to trigger another case where skb->len == 0 +when we enter __dev_queue_xmit: + +WARNING: CPU: 0 PID: 2470 at include/linux/skbuff.h:2576 skb_assert_len include/linux/skbuff.h:2576 [inline] +WARNING: CPU: 0 PID: 2470 at include/linux/skbuff.h:2576 __dev_queue_xmit+0x2069/0x35e0 net/core/dev.c:4295 + +Call Trace: + dev_queue_xmit+0x17/0x20 net/core/dev.c:4406 + __bpf_tx_skb net/core/filter.c:2115 [inline] + __bpf_redirect_no_mac net/core/filter.c:2140 [inline] + __bpf_redirect+0x5fb/0xda0 net/core/filter.c:2163 + ____bpf_clone_redirect net/core/filter.c:2447 [inline] + bpf_clone_redirect+0x247/0x390 net/core/filter.c:2419 + bpf_prog_48159a89cb4a9a16+0x59/0x5e + bpf_dispatcher_nop_func include/linux/bpf.h:897 [inline] + __bpf_prog_run include/linux/filter.h:596 [inline] + bpf_prog_run include/linux/filter.h:603 [inline] + bpf_test_run+0x46c/0x890 net/bpf/test_run.c:402 + bpf_prog_test_run_skb+0xbdc/0x14c0 net/bpf/test_run.c:1170 + bpf_prog_test_run+0x345/0x3c0 kernel/bpf/syscall.c:3648 + __sys_bpf+0x43a/0x6c0 kernel/bpf/syscall.c:5005 + __do_sys_bpf kernel/bpf/syscall.c:5091 [inline] + __se_sys_bpf kernel/bpf/syscall.c:5089 [inline] + __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5089 + do_syscall_64+0x54/0x70 arch/x86/entry/common.c:48 + entry_SYSCALL_64_after_hwframe+0x61/0xc6 + +The reproducer doesn't really reproduce outside of syzkaller +environment, so I'm taking a guess here. It looks like we +do generate correct ETH_HLEN-sized packet, but we redirect +the packet to the tunneling device. Before we do so, we +__skb_pull l2 header and arrive again at skb->len == 0. +Doesn't seem like we can do anything better than having +an explicit check after __skb_pull? + +Cc: Eric Dumazet +Reported-by: syzbot+f635e86ec3fa0a37e019@syzkaller.appspotmail.com +Signed-off-by: Stanislav Fomichev +Link: https://lore.kernel.org/r/20221027225537.353077-1-sdf@google.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/core/filter.c b/net/core/filter.c +index 68b1509e6188..2da05622afbe 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2130,6 +2130,10 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev, + + if (mlen) { + __skb_pull(skb, mlen); ++ if (unlikely(!skb->len)) { ++ kfree_skb(skb); ++ return -ERANGE; ++ } + + /* At ingress, the mac header has already been pulled once. + * At egress, skb_pospull_rcsum has to be done in case that +-- +2.35.1 + diff --git a/queue-5.15/bpf-move-skb-len-0-checks-into-__bpf_redirect.patch b/queue-5.15/bpf-move-skb-len-0-checks-into-__bpf_redirect.patch new file mode 100644 index 00000000000..6734ddfa396 --- /dev/null +++ b/queue-5.15/bpf-move-skb-len-0-checks-into-__bpf_redirect.patch @@ -0,0 +1,66 @@ +From 27f3aa793d3e2ebdc3b30ed1ef09d963ef9206b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 10:03:39 -0800 +Subject: bpf: Move skb->len == 0 checks into __bpf_redirect + +From: Stanislav Fomichev + +[ Upstream commit 114039b342014680911c35bd6b72624180fd669a ] + +To avoid potentially breaking existing users. + +Both mac/no-mac cases have to be amended; mac_header >= network_header +is not enough (verified with a new test, see next patch). + +Fixes: fd1894224407 ("bpf: Don't redirect packets with invalid pkt_len") +Signed-off-by: Stanislav Fomichev +Link: https://lore.kernel.org/r/20221121180340.1983627-1-sdf@google.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + net/bpf/test_run.c | 3 --- + net/core/filter.c | 7 ++++++- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c +index 7583ee98c35b..11d254ce3581 100644 +--- a/net/bpf/test_run.c ++++ b/net/bpf/test_run.c +@@ -470,9 +470,6 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) + { + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; + +- if (!skb->len) +- return -EINVAL; +- + if (!__skb) + return 0; + +diff --git a/net/core/filter.c b/net/core/filter.c +index fb5b9dbf3bc0..68b1509e6188 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2123,6 +2123,11 @@ static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev, + { + unsigned int mlen = skb_network_offset(skb); + ++ if (unlikely(skb->len <= mlen)) { ++ kfree_skb(skb); ++ return -ERANGE; ++ } ++ + if (mlen) { + __skb_pull(skb, mlen); + +@@ -2144,7 +2149,7 @@ static int __bpf_redirect_common(struct sk_buff *skb, struct net_device *dev, + u32 flags) + { + /* Verify that a link layer header is carried */ +- if (unlikely(skb->mac_header >= skb->network_header)) { ++ if (unlikely(skb->mac_header >= skb->network_header || skb->len == 0)) { + kfree_skb(skb); + return -ERANGE; + } +-- +2.35.1 + diff --git a/queue-5.15/bpf-prevent-decl_tag-from-being-referenced-in-func_p.patch b/queue-5.15/bpf-prevent-decl_tag-from-being-referenced-in-func_p.patch new file mode 100644 index 00000000000..c4dfe142065 --- /dev/null +++ b/queue-5.15/bpf-prevent-decl_tag-from-being-referenced-in-func_p.patch @@ -0,0 +1,55 @@ +From 03634d5e68fcbc01d2d8e6e2fdb7435c27e5d146 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:54:22 -0800 +Subject: bpf: Prevent decl_tag from being referenced in func_proto arg + +From: Stanislav Fomichev + +[ Upstream commit f17472d4599697d701aa239b4c475a506bccfd19 ] + +Syzkaller managed to hit another decl_tag issue: + + btf_func_proto_check kernel/bpf/btf.c:4506 [inline] + btf_check_all_types kernel/bpf/btf.c:4734 [inline] + btf_parse_type_sec+0x1175/0x1980 kernel/bpf/btf.c:4763 + btf_parse kernel/bpf/btf.c:5042 [inline] + btf_new_fd+0x65a/0xb00 kernel/bpf/btf.c:6709 + bpf_btf_load+0x6f/0x90 kernel/bpf/syscall.c:4342 + __sys_bpf+0x50a/0x6c0 kernel/bpf/syscall.c:5034 + __do_sys_bpf kernel/bpf/syscall.c:5093 [inline] + __se_sys_bpf kernel/bpf/syscall.c:5091 [inline] + __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5091 + do_syscall_64+0x54/0x70 arch/x86/entry/common.c:48 + +This seems similar to commit ea68376c8bed ("bpf: prevent decl_tag from being +referenced in func_proto") but for the argument. + +Reported-by: syzbot+8dd0551dda6020944c5d@syzkaller.appspotmail.com +Signed-off-by: Stanislav Fomichev +Signed-off-by: Daniel Borkmann +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20221123035422.872531-2-sdf@google.com +Signed-off-by: Sasha Levin +--- + kernel/bpf/btf.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index 7cb13b9f69a6..0c2fa93bd8d2 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -3864,6 +3864,11 @@ static int btf_func_proto_check(struct btf_verifier_env *env, + break; + } + ++ if (btf_type_is_resolve_source_only(arg_type)) { ++ btf_verifier_log_type(env, t, "Invalid arg#%u", i + 1); ++ return -EINVAL; ++ } ++ + if (args[i].name_off && + (!btf_name_offset_valid(btf, args[i].name_off) || + !btf_name_valid_identifier(btf, args[i].name_off))) { +-- +2.35.1 + diff --git a/queue-5.15/bpf-propagate-precision-across-all-frames-not-just-t.patch b/queue-5.15/bpf-propagate-precision-across-all-frames-not-just-t.patch new file mode 100644 index 00000000000..85164eb97e9 --- /dev/null +++ b/queue-5.15/bpf-propagate-precision-across-all-frames-not-just-t.patch @@ -0,0 +1,160 @@ +From 881d06d60abaf63eb57268f024f4799a8abd1b11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 09:36:45 -0700 +Subject: bpf: propagate precision across all frames, not just the last one + +From: Andrii Nakryiko + +[ Upstream commit 529409ea92d590659be487ba0839710329bd8074 ] + +When equivalent completed state is found and it has additional precision +restrictions, BPF verifier propagates precision to +currently-being-verified state chain (i.e., including parent states) so +that if some of the states in the chain are not yet completed, necessary +precision restrictions are enforced. + +Unfortunately, right now this happens only for the last frame (deepest +active subprogram's frame), not all the frames. This can lead to +incorrect matching of states due to missing precision marker. Currently +this doesn't seem possible as BPF verifier forces everything to precise +when validated BPF program has any subprograms. But with the next patch +lifting this restriction, this becomes problematic. + +In fact, without this fix, we'll start getting failure in one of the +existing test_verifier test cases: + + #906/p precise: cross frame pruning FAIL + Unexpected success to load! + verification time 48 usec + stack depth 0+0 + processed 26 insns (limit 1000000) max_states_per_insn 3 total_states 17 peak_states 17 mark_read 8 + +This patch adds precision propagation across all frames. + +Fixes: a3ce685dd01a ("bpf: fix precision tracking") +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/r/20221104163649.121784-3-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 71 ++++++++++++++++++++++++------------------- + 1 file changed, 39 insertions(+), 32 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index a0a1061eabb1..b1ca4dbdeecf 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2369,7 +2369,7 @@ static void mark_all_scalars_precise(struct bpf_verifier_env *env, + } + } + +-static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, ++static int __mark_chain_precision(struct bpf_verifier_env *env, int frame, int regno, + int spi) + { + struct bpf_verifier_state *st = env->cur_state; +@@ -2386,7 +2386,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + if (!env->bpf_capable) + return 0; + +- func = st->frame[st->curframe]; ++ func = st->frame[frame]; + if (regno >= 0) { + reg = &func->regs[regno]; + if (reg->type != SCALAR_VALUE) { +@@ -2467,7 +2467,7 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + break; + + new_marks = false; +- func = st->frame[st->curframe]; ++ func = st->frame[frame]; + bitmap_from_u64(mask, reg_mask); + for_each_set_bit(i, mask, 32) { + reg = &func->regs[i]; +@@ -2533,12 +2533,17 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno, + + static int mark_chain_precision(struct bpf_verifier_env *env, int regno) + { +- return __mark_chain_precision(env, regno, -1); ++ return __mark_chain_precision(env, env->cur_state->curframe, regno, -1); + } + +-static int mark_chain_precision_stack(struct bpf_verifier_env *env, int spi) ++static int mark_chain_precision_frame(struct bpf_verifier_env *env, int frame, int regno) + { +- return __mark_chain_precision(env, -1, spi); ++ return __mark_chain_precision(env, frame, regno, -1); ++} ++ ++static int mark_chain_precision_stack_frame(struct bpf_verifier_env *env, int frame, int spi) ++{ ++ return __mark_chain_precision(env, frame, -1, spi); + } + + static bool is_spillable_regtype(enum bpf_reg_type type) +@@ -10543,34 +10548,36 @@ static int propagate_precision(struct bpf_verifier_env *env, + { + struct bpf_reg_state *state_reg; + struct bpf_func_state *state; +- int i, err = 0; ++ int i, err = 0, fr; + +- state = old->frame[old->curframe]; +- state_reg = state->regs; +- for (i = 0; i < BPF_REG_FP; i++, state_reg++) { +- if (state_reg->type != SCALAR_VALUE || +- !state_reg->precise) +- continue; +- if (env->log.level & BPF_LOG_LEVEL2) +- verbose(env, "propagating r%d\n", i); +- err = mark_chain_precision(env, i); +- if (err < 0) +- return err; +- } ++ for (fr = old->curframe; fr >= 0; fr--) { ++ state = old->frame[fr]; ++ state_reg = state->regs; ++ for (i = 0; i < BPF_REG_FP; i++, state_reg++) { ++ if (state_reg->type != SCALAR_VALUE || ++ !state_reg->precise) ++ continue; ++ if (env->log.level & BPF_LOG_LEVEL2) ++ verbose(env, "frame %d: propagating r%d\n", i, fr); ++ err = mark_chain_precision_frame(env, fr, i); ++ if (err < 0) ++ return err; ++ } + +- for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { +- if (!is_spilled_reg(&state->stack[i])) +- continue; +- state_reg = &state->stack[i].spilled_ptr; +- if (state_reg->type != SCALAR_VALUE || +- !state_reg->precise) +- continue; +- if (env->log.level & BPF_LOG_LEVEL2) +- verbose(env, "propagating fp%d\n", +- (-i - 1) * BPF_REG_SIZE); +- err = mark_chain_precision_stack(env, i); +- if (err < 0) +- return err; ++ for (i = 0; i < state->allocated_stack / BPF_REG_SIZE; i++) { ++ if (!is_spilled_reg(&state->stack[i])) ++ continue; ++ state_reg = &state->stack[i].spilled_ptr; ++ if (state_reg->type != SCALAR_VALUE || ++ !state_reg->precise) ++ continue; ++ if (env->log.level & BPF_LOG_LEVEL2) ++ verbose(env, "frame %d: propagating fp%d\n", ++ (-i - 1) * BPF_REG_SIZE, fr); ++ err = mark_chain_precision_stack_frame(env, fr, i); ++ if (err < 0) ++ return err; ++ } + } + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/bpf-propagate-precision-in-alu-alu64-operations.patch b/queue-5.15/bpf-propagate-precision-in-alu-alu64-operations.patch new file mode 100644 index 00000000000..ca3d5c5cf1e --- /dev/null +++ b/queue-5.15/bpf-propagate-precision-in-alu-alu64-operations.patch @@ -0,0 +1,89 @@ +From b3e891eff3944b5958c8185767286ad9830d2a8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 09:36:44 -0700 +Subject: bpf: propagate precision in ALU/ALU64 operations + +From: Andrii Nakryiko + +[ Upstream commit a3b666bfa9c9edc05bca62a87abafe0936bd7f97 ] + +When processing ALU/ALU64 operations (apart from BPF_MOV, which is +handled correctly already; and BPF_NEG and BPF_END are special and don't +have source register), if destination register is already marked +precise, this causes problem with potentially missing precision tracking +for the source register. E.g., when we have r1 >>= r5 and r1 is marked +precise, but r5 isn't, this will lead to r5 staying as imprecise. This +is due to the precision backtracking logic stopping early when it sees +r1 is already marked precise. If r1 wasn't precise, we'd keep +backtracking and would add r5 to the set of registers that need to be +marked precise. So there is a discrepancy here which can lead to invalid +and incompatible states matched due to lack of precision marking on r5. +If r1 wasn't precise, precision backtracking would correctly mark both +r1 and r5 as precise. + +This is simple to fix, though. During the forward instruction simulation +pass, for arithmetic operations of `scalar = scalar` form (where + is ALU or ALU64 operations), if destination register is already +precise, mark source register as precise. This applies only when both +involved registers are SCALARs. `ptr += scalar` and `scalar += ptr` +cases are already handled correctly. + +This does have (negative) effect on some selftest programs and few +Cilium programs. ~/baseline-tmp-results.csv are veristat results with +this patch, while ~/baseline-results.csv is without it. See post +scriptum for instructions on how to make Cilium programs testable with +veristat. Correctness has a price. + +$ ./veristat -C -e file,prog,insns,states ~/baseline-results.csv ~/baseline-tmp-results.csv | grep -v '+0' +File Program Total insns (A) Total insns (B) Total insns (DIFF) Total states (A) Total states (B) Total states (DIFF) +----------------------- -------------------- --------------- --------------- ------------------ ---------------- ---------------- ------------------- +bpf_cubic.bpf.linked1.o bpf_cubic_cong_avoid 997 1700 +703 (+70.51%) 62 90 +28 (+45.16%) +test_l4lb.bpf.linked1.o balancer_ingress 4559 5469 +910 (+19.96%) 118 126 +8 (+6.78%) +----------------------- -------------------- --------------- --------------- ------------------ ---------------- ---------------- ------------------- + +$ ./veristat -C -e file,prog,verdict,insns,states ~/baseline-results-cilium.csv ~/baseline-tmp-results-cilium.csv | grep -v '+0' +File Program Total insns (A) Total insns (B) Total insns (DIFF) Total states (A) Total states (B) Total states (DIFF) +------------- ------------------------------ --------------- --------------- ------------------ ---------------- ---------------- ------------------- +bpf_host.o tail_nodeport_nat_ingress_ipv6 4448 5261 +813 (+18.28%) 234 247 +13 (+5.56%) +bpf_host.o tail_nodeport_nat_ipv6_egress 3396 3446 +50 (+1.47%) 201 203 +2 (+1.00%) +bpf_lxc.o tail_nodeport_nat_ingress_ipv6 4448 5261 +813 (+18.28%) 234 247 +13 (+5.56%) +bpf_overlay.o tail_nodeport_nat_ingress_ipv6 4448 5261 +813 (+18.28%) 234 247 +13 (+5.56%) +bpf_xdp.o tail_lb_ipv4 71736 73442 +1706 (+2.38%) 4295 4370 +75 (+1.75%) +------------- ------------------------------ --------------- --------------- ------------------ ---------------- ---------------- ------------------- + +P.S. To make Cilium ([0]) programs libbpf-compatible and thus +veristat-loadable, apply changes from topmost commit in [1], which does +minimal changes to Cilium source code, mostly around SEC() annotations +and BPF map definitions. + + [0] https://github.com/cilium/cilium/ + [1] https://github.com/anakryiko/cilium/commits/libbpf-friendliness + +Fixes: b5dc0163d8fd ("bpf: precise scalar_value tracking") +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/r/20221104163649.121784-2-andrii@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 027ead3d0680..98d182dc848a 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -7998,6 +7998,11 @@ static int adjust_reg_min_max_vals(struct bpf_verifier_env *env, + return err; + return adjust_ptr_min_max_vals(env, insn, + dst_reg, src_reg); ++ } else if (dst_reg->precise) { ++ /* if dst_reg is precise, src_reg should be precise as well */ ++ err = mark_chain_precision(env, insn->src_reg); ++ if (err) ++ return err; + } + } else { + /* Pretend the src is a reg with a known value, since we only +-- +2.35.1 + diff --git a/queue-5.15/bpf-sockmap-fix-data-loss-caused-by-using-apply_byte.patch b/queue-5.15/bpf-sockmap-fix-data-loss-caused-by-using-apply_byte.patch new file mode 100644 index 00000000000..64deda4e3a6 --- /dev/null +++ b/queue-5.15/bpf-sockmap-fix-data-loss-caused-by-using-apply_byte.patch @@ -0,0 +1,47 @@ +From 7191f8afdfd1b9fa87912a567481ed446dd780e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 18:40:40 +0800 +Subject: bpf, sockmap: Fix data loss caused by using apply_bytes on ingress + redirect + +From: Pengcheng Yang + +[ Upstream commit 9072931f020bfd907d6d89ee21ff1481cd78b407 ] + +Use apply_bytes on ingress redirect, when apply_bytes is less than +the length of msg data, some data may be skipped and lost in +bpf_tcp_ingress(). + +If there is still data in the scatterlist that has not been consumed, +we cannot move the msg iter. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Pengcheng Yang +Signed-off-by: Daniel Borkmann +Acked-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/1669718441-2654-4-git-send-email-yangpc@wangsu.com +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 2db868ca32af..b4b642e3de78 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -45,8 +45,11 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + tmp->sg.end = i; + if (apply) { + apply_bytes -= size; +- if (!apply_bytes) ++ if (!apply_bytes) { ++ if (sge->length) ++ sk_msg_iter_var_prev(i); + break; ++ } + } + } while (i != msg->sg.end); + +-- +2.35.1 + diff --git a/queue-5.15/bpf-sockmap-fix-missing-bpf_f_ingress-flag-when-usin.patch b/queue-5.15/bpf-sockmap-fix-missing-bpf_f_ingress-flag-when-usin.patch new file mode 100644 index 00000000000..75c2b29251a --- /dev/null +++ b/queue-5.15/bpf-sockmap-fix-missing-bpf_f_ingress-flag-when-usin.patch @@ -0,0 +1,161 @@ +From 1af4f1e2dd81cee3c55edd3f4ded6882b2a65609 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 18:40:39 +0800 +Subject: bpf, sockmap: Fix missing BPF_F_INGRESS flag when using apply_bytes + +From: Pengcheng Yang + +[ Upstream commit a351d6087bf7d3d8440d58d3bf244ec64b89394a ] + +When redirecting, we use sk_msg_to_ingress() to get the BPF_F_INGRESS +flag from the msg->flags. If apply_bytes is used and it is larger than +the current data being processed, sk_psock_msg_verdict() will not be +called when sendmsg() is called again. At this time, the msg->flags is 0, +and we lost the BPF_F_INGRESS flag. + +So we need to save the BPF_F_INGRESS flag in sk_psock and use it when +redirection. + +Fixes: 8934ce2fd081 ("bpf: sockmap redirect ingress support") +Signed-off-by: Pengcheng Yang +Signed-off-by: Daniel Borkmann +Acked-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/1669718441-2654-3-git-send-email-yangpc@wangsu.com +Signed-off-by: Sasha Levin +--- + include/linux/skmsg.h | 1 + + include/net/tcp.h | 4 ++-- + net/core/skmsg.c | 9 ++++++--- + net/ipv4/tcp_bpf.c | 11 ++++++----- + net/tls/tls_sw.c | 6 ++++-- + 5 files changed, 19 insertions(+), 12 deletions(-) + +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index ba015a77238a..6e18ca234f81 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -83,6 +83,7 @@ struct sk_psock { + u32 apply_bytes; + u32 cork_bytes; + u32 eval; ++ bool redir_ingress; /* undefined if sk_redir is null */ + struct sk_msg *cork; + struct sk_psock_progs progs; + #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 81ef95dc27ba..fdac6913b6c8 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -2243,8 +2243,8 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); + void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); + #endif /* CONFIG_BPF_SYSCALL */ + +-int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, u32 bytes, +- int flags); ++int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress, ++ struct sk_msg *msg, u32 bytes, int flags); + #endif /* CONFIG_NET_SOCK_MSG */ + + #if !defined(CONFIG_BPF_SYSCALL) || !defined(CONFIG_NET_SOCK_MSG) +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index f562f7e2bdc7..dc9b93d8f0d3 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -880,13 +880,16 @@ int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock, + ret = sk_psock_map_verd(ret, msg->sk_redir); + psock->apply_bytes = msg->apply_bytes; + if (ret == __SK_REDIRECT) { +- if (psock->sk_redir) ++ if (psock->sk_redir) { + sock_put(psock->sk_redir); +- psock->sk_redir = msg->sk_redir; +- if (!psock->sk_redir) { ++ psock->sk_redir = NULL; ++ } ++ if (!msg->sk_redir) { + ret = __SK_DROP; + goto out; + } ++ psock->redir_ingress = sk_msg_to_ingress(msg); ++ psock->sk_redir = msg->sk_redir; + sock_hold(psock->sk_redir); + } + out: +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index a38db402994d..2db868ca32af 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -131,10 +131,9 @@ static int tcp_bpf_push_locked(struct sock *sk, struct sk_msg *msg, + return ret; + } + +-int tcp_bpf_sendmsg_redir(struct sock *sk, struct sk_msg *msg, +- u32 bytes, int flags) ++int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress, ++ struct sk_msg *msg, u32 bytes, int flags) + { +- bool ingress = sk_msg_to_ingress(msg); + struct sk_psock *psock = sk_psock_get(sk); + int ret; + +@@ -277,7 +276,7 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + struct sk_msg *msg, int *copied, int flags) + { +- bool cork = false, enospc = sk_msg_full(msg); ++ bool cork = false, enospc = sk_msg_full(msg), redir_ingress; + struct sock *sk_redir; + u32 tosend, origsize, sent, delta = 0; + u32 eval; +@@ -323,6 +322,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + sk_msg_apply_bytes(psock, tosend); + break; + case __SK_REDIRECT: ++ redir_ingress = psock->redir_ingress; + sk_redir = psock->sk_redir; + sk_msg_apply_bytes(psock, tosend); + if (!psock->apply_bytes) { +@@ -339,7 +339,8 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + release_sock(sk); + + origsize = msg->sg.size; +- ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags); ++ ret = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress, ++ msg, tosend, flags); + sent = origsize - msg->sg.size; + + if (eval == __SK_REDIRECT) +diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c +index 794ef3b3d7d4..c0fea678abb1 100644 +--- a/net/tls/tls_sw.c ++++ b/net/tls/tls_sw.c +@@ -801,7 +801,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + struct sk_psock *psock; + struct sock *sk_redir; + struct tls_rec *rec; +- bool enospc, policy; ++ bool enospc, policy, redir_ingress; + int err = 0, send; + u32 delta = 0; + +@@ -846,6 +846,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + } + break; + case __SK_REDIRECT: ++ redir_ingress = psock->redir_ingress; + sk_redir = psock->sk_redir; + memcpy(&msg_redir, msg, sizeof(*msg)); + if (msg->apply_bytes < send) +@@ -855,7 +856,8 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk, + sk_msg_return_zero(sk, msg, send); + msg->sg.size -= send; + release_sock(sk); +- err = tcp_bpf_sendmsg_redir(sk_redir, &msg_redir, send, flags); ++ err = tcp_bpf_sendmsg_redir(sk_redir, redir_ingress, ++ &msg_redir, send, flags); + lock_sock(sk); + if (err < 0) { + *copied -= sk_msg_free_nocharge(sk, &msg_redir); +-- +2.35.1 + diff --git a/queue-5.15/bpf-sockmap-fix-race-in-sock_map_free.patch b/queue-5.15/bpf-sockmap-fix-race-in-sock_map_free.patch new file mode 100644 index 00000000000..c86b52b7c07 --- /dev/null +++ b/queue-5.15/bpf-sockmap-fix-race-in-sock_map_free.patch @@ -0,0 +1,87 @@ +From 8df5e3fe51c97696a67c485759b9f6e9a1d5c07c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 11:16:40 +0000 +Subject: bpf, sockmap: fix race in sock_map_free() + +From: Eric Dumazet + +[ Upstream commit 0a182f8d607464911756b4dbef5d6cad8de22469 ] + +sock_map_free() calls release_sock(sk) without owning a reference +on the socket. This can cause use-after-free as syzbot found [1] + +Jakub Sitnicki already took care of a similar issue +in sock_hash_free() in commit 75e68e5bf2c7 ("bpf, sockhash: +Synchronize delete from bucket list on map free") + +[1] +refcount_t: decrement hit 0; leaking memory. +WARNING: CPU: 0 PID: 3785 at lib/refcount.c:31 refcount_warn_saturate+0x17c/0x1a0 lib/refcount.c:31 +Modules linked in: +CPU: 0 PID: 3785 Comm: kworker/u4:6 Not tainted 6.1.0-rc7-syzkaller-00103-gef4d3ea40565 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 +Workqueue: events_unbound bpf_map_free_deferred +RIP: 0010:refcount_warn_saturate+0x17c/0x1a0 lib/refcount.c:31 +Code: 68 8b 31 c0 e8 75 71 15 fd 0f 0b e9 64 ff ff ff e8 d9 6e 4e fd c6 05 62 9c 3d 0a 01 48 c7 c7 80 bb 68 8b 31 c0 e8 54 71 15 fd <0f> 0b e9 43 ff ff ff 89 d9 80 e1 07 80 c1 03 38 c1 0f 8c a2 fe ff +RSP: 0018:ffffc9000456fb60 EFLAGS: 00010246 +RAX: eae59bab72dcd700 RBX: 0000000000000004 RCX: ffff8880207057c0 +RDX: 0000000000000000 RSI: 0000000000000201 RDI: 0000000000000000 +RBP: 0000000000000004 R08: ffffffff816fdabd R09: fffff520008adee5 +R10: fffff520008adee5 R11: 1ffff920008adee4 R12: 0000000000000004 +R13: dffffc0000000000 R14: ffff88807b1c6c00 R15: 1ffff1100f638dcf +FS: 0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000001b30c30000 CR3: 000000000d08e000 CR4: 00000000003506f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + +__refcount_dec include/linux/refcount.h:344 [inline] +refcount_dec include/linux/refcount.h:359 [inline] +__sock_put include/net/sock.h:779 [inline] +tcp_release_cb+0x2d0/0x360 net/ipv4/tcp_output.c:1092 +release_sock+0xaf/0x1c0 net/core/sock.c:3468 +sock_map_free+0x219/0x2c0 net/core/sock_map.c:356 +process_one_work+0x81c/0xd10 kernel/workqueue.c:2289 +worker_thread+0xb14/0x1330 kernel/workqueue.c:2436 +kthread+0x266/0x300 kernel/kthread.c:376 +ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306 + + +Fixes: 7e81a3530206 ("bpf: Sockmap, ensure sock lock held during tear down") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Cc: Jakub Sitnicki +Cc: John Fastabend +Cc: Alexei Starovoitov +Cc: Daniel Borkmann +Cc: Song Liu +Acked-by: John Fastabend +Link: https://lore.kernel.org/r/20221202111640.2745533-1-edumazet@google.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 4f4bc163a223..ae6013a8bce5 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -349,11 +349,13 @@ static void sock_map_free(struct bpf_map *map) + + sk = xchg(psk, NULL); + if (sk) { ++ sock_hold(sk); + lock_sock(sk); + rcu_read_lock(); + sock_map_unref(sk, psk); + rcu_read_unlock(); + release_sock(sk); ++ sock_put(sk); + } + } + +-- +2.35.1 + diff --git a/queue-5.15/bpf-sockmap-fix-repeated-calls-to-sock_put-when-msg-.patch b/queue-5.15/bpf-sockmap-fix-repeated-calls-to-sock_put-when-msg-.patch new file mode 100644 index 00000000000..184fe56bddf --- /dev/null +++ b/queue-5.15/bpf-sockmap-fix-repeated-calls-to-sock_put-when-msg-.patch @@ -0,0 +1,80 @@ +From 2fe0b27c5526fd1db3e36c963aacc250725048f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 18:40:38 +0800 +Subject: bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data + +From: Pengcheng Yang + +[ Upstream commit 7a9841ca025275b5b0edfb0b618934abb6ceec15 ] + +In tcp_bpf_send_verdict() redirection, the eval variable is assigned to +__SK_REDIRECT after the apply_bytes data is sent, if msg has more_data, +sock_put() will be called multiple times. + +We should reset the eval variable to __SK_NONE every time more_data +starts. + +This causes: + +IPv4: Attempt to release TCP socket in state 1 00000000b4c925d7 +------------[ cut here ]------------ +refcount_t: addition on 0; use-after-free. +WARNING: CPU: 5 PID: 4482 at lib/refcount.c:25 refcount_warn_saturate+0x7d/0x110 +Modules linked in: +CPU: 5 PID: 4482 Comm: sockhash_bypass Kdump: loaded Not tainted 6.0.0 #1 +Hardware name: Red Hat KVM, BIOS 1.11.0-2.el7 04/01/2014 +Call Trace: + + __tcp_transmit_skb+0xa1b/0xb90 + ? __alloc_skb+0x8c/0x1a0 + ? __kmalloc_node_track_caller+0x184/0x320 + tcp_write_xmit+0x22a/0x1110 + __tcp_push_pending_frames+0x32/0xf0 + do_tcp_sendpages+0x62d/0x640 + tcp_bpf_push+0xae/0x2c0 + tcp_bpf_sendmsg_redir+0x260/0x410 + ? preempt_count_add+0x70/0xa0 + tcp_bpf_send_verdict+0x386/0x4b0 + tcp_bpf_sendmsg+0x21b/0x3b0 + sock_sendmsg+0x58/0x70 + __sys_sendto+0xfa/0x170 + ? xfd_validate_state+0x1d/0x80 + ? switch_fpu_return+0x59/0xe0 + __x64_sys_sendto+0x24/0x30 + do_syscall_64+0x37/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Fixes: cd9733f5d75c ("tcp_bpf: Fix one concurrency problem in the tcp_bpf_send_verdict function") +Signed-off-by: Pengcheng Yang +Signed-off-by: Daniel Borkmann +Acked-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/1669718441-2654-2-git-send-email-yangpc@wangsu.com +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 5194c6870273..a38db402994d 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -280,7 +280,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + bool cork = false, enospc = sk_msg_full(msg); + struct sock *sk_redir; + u32 tosend, origsize, sent, delta = 0; +- u32 eval = __SK_NONE; ++ u32 eval; + int ret; + + more_data: +@@ -311,6 +311,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, + tosend = msg->sg.size; + if (psock->apply_bytes && psock->apply_bytes < tosend) + tosend = psock->apply_bytes; ++ eval = __SK_NONE; + + switch (psock->eval) { + case __SK_PASS: +-- +2.35.1 + diff --git a/queue-5.15/brcmfmac-return-error-when-getting-invalid-max_flowr.patch b/queue-5.15/brcmfmac-return-error-when-getting-invalid-max_flowr.patch new file mode 100644 index 00000000000..de9ea5ad804 --- /dev/null +++ b/queue-5.15/brcmfmac-return-error-when-getting-invalid-max_flowr.patch @@ -0,0 +1,43 @@ +From 4c516597c0775e330e3822e9dcda1c461d44d159 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 22:10:00 -0500 +Subject: brcmfmac: return error when getting invalid max_flowrings from dongle + +From: Wright Feng + +[ Upstream commit 2aca4f3734bd717e04943ddf340d49ab62299a00 ] + +When firmware hit trap at initialization, host will read abnormal +max_flowrings number from dongle, and it will cause kernel panic when +doing iowrite to initialize dongle ring. +To detect this error at early stage, we directly return error when getting +invalid max_flowrings(>256). + +Signed-off-by: Wright Feng +Signed-off-by: Chi-hsien Lin +Signed-off-by: Ian Lin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220929031001.9962-3-ian.lin@infineon.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 358021a33b8a..f5f5a002fdcf 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -1118,6 +1118,10 @@ static int brcmf_pcie_init_ringbuffers(struct brcmf_pciedev_info *devinfo) + BRCMF_NROF_H2D_COMMON_MSGRINGS; + max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS; + } ++ if (max_flowrings > 256) { ++ brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings); ++ return -EIO; ++ } + + if (devinfo->dma_idx_sz != 0) { + bufsz = (max_submissionrings + max_completionrings) * +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-add-struct-kvaser_usb_busparams.patch b/queue-5.15/can-kvaser_usb-add-struct-kvaser_usb_busparams.patch new file mode 100644 index 00000000000..ca4f0f67b39 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-add-struct-kvaser_usb_busparams.patch @@ -0,0 +1,143 @@ +From fd71baad0c341993f0fae8a39b81ac876818faf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:36 +0200 +Subject: can: kvaser_usb: Add struct kvaser_usb_busparams + +From: Jimmy Assarsson + +[ Upstream commit 00e5786177649c1e3110f9454fdd34e336597265 ] + +Add struct kvaser_usb_busparams containing the busparameters used in +CMD_{SET,GET}_BUSPARAMS* commands. + +Tested-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-11-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 39d3df6b0ea8 ("can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming") +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 8 +++++ + .../net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 32 +++++++------------ + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 18 ++++------- + 3 files changed, 27 insertions(+), 31 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +index 1f4583f1dae2..cb8018723748 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +@@ -76,6 +76,14 @@ struct kvaser_usb_tx_urb_context { + int dlc; + }; + ++struct kvaser_usb_busparams { ++ __le32 bitrate; ++ u8 tseg1; ++ u8 tseg2; ++ u8 sjw; ++ u8 nsamples; ++} __packed; ++ + struct kvaser_usb { + struct usb_device *udev; + struct usb_interface *intf; +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +index b485f0bc2e6b..64b84c8d5dfd 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -196,17 +196,9 @@ struct kvaser_cmd_chip_state_event { + #define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO 0x01 + #define KVASER_USB_HYDRA_BUS_MODE_NONISO 0x02 + struct kvaser_cmd_set_busparams { +- __le32 bitrate; +- u8 tseg1; +- u8 tseg2; +- u8 sjw; +- u8 nsamples; ++ struct kvaser_usb_busparams busparams_arb; + u8 reserved0[4]; +- __le32 bitrate_d; +- u8 tseg1_d; +- u8 tseg2_d; +- u8 sjw_d; +- u8 nsamples_d; ++ struct kvaser_usb_busparams busparams_data; + u8 canfd_mode; + u8 reserved1[7]; + } __packed; +@@ -1542,11 +1534,11 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ; +- cmd->set_busparams_req.bitrate = cpu_to_le32(bt->bitrate); +- cmd->set_busparams_req.sjw = (u8)sjw; +- cmd->set_busparams_req.tseg1 = (u8)tseg1; +- cmd->set_busparams_req.tseg2 = (u8)tseg2; +- cmd->set_busparams_req.nsamples = 1; ++ cmd->set_busparams_req.busparams_arb.bitrate = cpu_to_le32(bt->bitrate); ++ cmd->set_busparams_req.busparams_arb.sjw = (u8)sjw; ++ cmd->set_busparams_req.busparams_arb.tseg1 = (u8)tseg1; ++ cmd->set_busparams_req.busparams_arb.tseg2 = (u8)tseg2; ++ cmd->set_busparams_req.busparams_arb.nsamples = 1; + + kvaser_usb_hydra_set_cmd_dest_he + (cmd, dev->card_data.hydra.channel_to_he[priv->channel]); +@@ -1576,11 +1568,11 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ; +- cmd->set_busparams_req.bitrate_d = cpu_to_le32(dbt->bitrate); +- cmd->set_busparams_req.sjw_d = (u8)sjw; +- cmd->set_busparams_req.tseg1_d = (u8)tseg1; +- cmd->set_busparams_req.tseg2_d = (u8)tseg2; +- cmd->set_busparams_req.nsamples_d = 1; ++ cmd->set_busparams_req.busparams_data.bitrate = cpu_to_le32(dbt->bitrate); ++ cmd->set_busparams_req.busparams_data.sjw = (u8)sjw; ++ cmd->set_busparams_req.busparams_data.tseg1 = (u8)tseg1; ++ cmd->set_busparams_req.busparams_data.tseg2 = (u8)tseg2; ++ cmd->set_busparams_req.busparams_data.nsamples = 1; + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index b44a9ca22136..9818bc6dc8e9 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -164,11 +164,7 @@ struct usbcan_cmd_softinfo { + struct kvaser_cmd_busparams { + u8 tid; + u8 channel; +- __le32 bitrate; +- u8 tseg1; +- u8 tseg2; +- u8 sjw; +- u8 no_samp; ++ struct kvaser_usb_busparams busparams; + } __packed; + + struct kvaser_cmd_tx_can { +@@ -1704,15 +1700,15 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams); + cmd->u.busparams.channel = priv->channel; + cmd->u.busparams.tid = 0xff; +- cmd->u.busparams.bitrate = cpu_to_le32(bt->bitrate); +- cmd->u.busparams.sjw = bt->sjw; +- cmd->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1; +- cmd->u.busparams.tseg2 = bt->phase_seg2; ++ cmd->u.busparams.busparams.bitrate = cpu_to_le32(bt->bitrate); ++ cmd->u.busparams.busparams.sjw = bt->sjw; ++ cmd->u.busparams.busparams.tseg1 = bt->prop_seg + bt->phase_seg1; ++ cmd->u.busparams.busparams.tseg2 = bt->phase_seg2; + + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) +- cmd->u.busparams.no_samp = 3; ++ cmd->u.busparams.busparams.nsamples = 3; + else +- cmd->u.busparams.no_samp = 1; ++ cmd->u.busparams.busparams.nsamples = 1; + + rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); + +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-compare-requested-bittiming-parameter.patch b/queue-5.15/can-kvaser_usb-compare-requested-bittiming-parameter.patch new file mode 100644 index 00000000000..078495937ad --- /dev/null +++ b/queue-5.15/can-kvaser_usb-compare-requested-bittiming-parameter.patch @@ -0,0 +1,598 @@ +From 57aa25201624ddbf6d3a8eb6bce11f1a9baa1680 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:37 +0200 +Subject: can: kvaser_usb: Compare requested bittiming parameters with actual + parameters in do_set_{,data}_bittiming + +From: Jimmy Assarsson + +[ Upstream commit 39d3df6b0ea80f9b515c632ca07b39b1c156edee ] + +The device will respond with a CMD_ERROR_EVENT command, with error_code +KVASER_USB_{LEAF,HYDRA}_ERROR_EVENT_PARAM, if the CMD_SET_BUSPARAMS_REQ +contains invalid bittiming parameters. +However, this command does not contain any channel reference. + +To check if the CMD_SET_BUSPARAMS_REQ was successful, redback and compare +the requested bittiming parameters with the device reported parameters. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Fixes: aec5fb2268b7 ("can: kvaser_usb: Add support for Kvaser USB hydra family") +Tested-by: Anssi Hannula +Co-developed-by: Anssi Hannula +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-12-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 15 +- + .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 96 ++++++++++- + .../net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 150 +++++++++++++++--- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 64 ++++++-- + 4 files changed, 284 insertions(+), 41 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +index cb8018723748..5699531f8787 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +@@ -119,9 +119,12 @@ struct kvaser_usb_net_priv { + struct net_device *netdev; + int channel; + +- struct completion start_comp, stop_comp, flush_comp; ++ struct completion start_comp, stop_comp, flush_comp, ++ get_busparams_comp; + struct usb_anchor tx_submitted; + ++ struct kvaser_usb_busparams busparams_nominal, busparams_data; ++ + spinlock_t tx_contexts_lock; /* lock for active_tx_contexts */ + int active_tx_contexts; + struct kvaser_usb_tx_urb_context tx_contexts[]; +@@ -131,7 +134,9 @@ struct kvaser_usb_net_priv { + * struct kvaser_usb_dev_ops - Device specific functions + * @dev_set_mode: used for can.do_set_mode + * @dev_set_bittiming: used for can.do_set_bittiming ++ * @dev_get_busparams: readback arbitration busparams + * @dev_set_data_bittiming: used for can.do_set_data_bittiming ++ * @dev_get_data_busparams: readback data busparams + * @dev_get_berr_counter: used for can.do_get_berr_counter + * + * @dev_setup_endpoints: setup USB in and out endpoints +@@ -153,8 +158,12 @@ struct kvaser_usb_net_priv { + */ + struct kvaser_usb_dev_ops { + int (*dev_set_mode)(struct net_device *netdev, enum can_mode mode); +- int (*dev_set_bittiming)(struct net_device *netdev); +- int (*dev_set_data_bittiming)(struct net_device *netdev); ++ int (*dev_set_bittiming)(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams); ++ int (*dev_get_busparams)(struct kvaser_usb_net_priv *priv); ++ int (*dev_set_data_bittiming)(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams); ++ int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv); + int (*dev_get_berr_counter)(const struct net_device *netdev, + struct can_berr_counter *bec); + int (*dev_setup_endpoints)(struct kvaser_usb *dev); +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +index 4915d5f180da..09dbc51347d7 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +@@ -443,10 +443,6 @@ static int kvaser_usb_open(struct net_device *netdev) + if (err) + return err; + +- err = kvaser_usb_setup_rx_urbs(dev); +- if (err) +- goto error; +- + err = ops->dev_set_opt_mode(priv); + if (err) + goto error; +@@ -537,6 +533,93 @@ static int kvaser_usb_close(struct net_device *netdev) + return 0; + } + ++static int kvaser_usb_set_bittiming(struct net_device *netdev) ++{ ++ struct kvaser_usb_net_priv *priv = netdev_priv(netdev); ++ struct kvaser_usb *dev = priv->dev; ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; ++ struct can_bittiming *bt = &priv->can.bittiming; ++ ++ struct kvaser_usb_busparams busparams; ++ int tseg1 = bt->prop_seg + bt->phase_seg1; ++ int tseg2 = bt->phase_seg2; ++ int sjw = bt->sjw; ++ int err = -EOPNOTSUPP; ++ ++ busparams.bitrate = cpu_to_le32(bt->bitrate); ++ busparams.sjw = (u8)sjw; ++ busparams.tseg1 = (u8)tseg1; ++ busparams.tseg2 = (u8)tseg2; ++ if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ++ busparams.nsamples = 3; ++ else ++ busparams.nsamples = 1; ++ ++ err = ops->dev_set_bittiming(netdev, &busparams); ++ if (err) ++ return err; ++ ++ err = kvaser_usb_setup_rx_urbs(priv->dev); ++ if (err) ++ return err; ++ ++ err = ops->dev_get_busparams(priv); ++ if (err) { ++ /* Treat EOPNOTSUPP as success */ ++ if (err == -EOPNOTSUPP) ++ err = 0; ++ return err; ++ } ++ ++ if (memcmp(&busparams, &priv->busparams_nominal, ++ sizeof(priv->busparams_nominal)) != 0) ++ err = -EINVAL; ++ ++ return err; ++} ++ ++static int kvaser_usb_set_data_bittiming(struct net_device *netdev) ++{ ++ struct kvaser_usb_net_priv *priv = netdev_priv(netdev); ++ struct kvaser_usb *dev = priv->dev; ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; ++ struct can_bittiming *dbt = &priv->can.data_bittiming; ++ ++ struct kvaser_usb_busparams busparams; ++ int tseg1 = dbt->prop_seg + dbt->phase_seg1; ++ int tseg2 = dbt->phase_seg2; ++ int sjw = dbt->sjw; ++ int err; ++ ++ if (!ops->dev_set_data_bittiming || ++ !ops->dev_get_data_busparams) ++ return -EOPNOTSUPP; ++ ++ busparams.bitrate = cpu_to_le32(dbt->bitrate); ++ busparams.sjw = (u8)sjw; ++ busparams.tseg1 = (u8)tseg1; ++ busparams.tseg2 = (u8)tseg2; ++ busparams.nsamples = 1; ++ ++ err = ops->dev_set_data_bittiming(netdev, &busparams); ++ if (err) ++ return err; ++ ++ err = kvaser_usb_setup_rx_urbs(priv->dev); ++ if (err) ++ return err; ++ ++ err = ops->dev_get_data_busparams(priv); ++ if (err) ++ return err; ++ ++ if (memcmp(&busparams, &priv->busparams_data, ++ sizeof(priv->busparams_data)) != 0) ++ err = -EINVAL; ++ ++ return err; ++} ++ + static void kvaser_usb_write_bulk_callback(struct urb *urb) + { + struct kvaser_usb_tx_urb_context *context = urb->context; +@@ -722,6 +805,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + init_completion(&priv->start_comp); + init_completion(&priv->stop_comp); + init_completion(&priv->flush_comp); ++ init_completion(&priv->get_busparams_comp); + priv->can.ctrlmode_supported = 0; + + priv->dev = dev; +@@ -734,7 +818,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + priv->can.state = CAN_STATE_STOPPED; + priv->can.clock.freq = dev->cfg->clock.freq; + priv->can.bittiming_const = dev->cfg->bittiming_const; +- priv->can.do_set_bittiming = ops->dev_set_bittiming; ++ priv->can.do_set_bittiming = kvaser_usb_set_bittiming; + priv->can.do_set_mode = ops->dev_set_mode; + if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) || + (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP)) +@@ -746,7 +830,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + + if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) { + priv->can.data_bittiming_const = dev->cfg->data_bittiming_const; +- priv->can.do_set_data_bittiming = ops->dev_set_data_bittiming; ++ priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming; + } + + netdev->flags |= IFF_ECHO; +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +index 64b84c8d5dfd..6cc65bf28d03 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -45,6 +45,8 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt; + + /* Minihydra command IDs */ + #define CMD_SET_BUSPARAMS_REQ 16 ++#define CMD_GET_BUSPARAMS_REQ 17 ++#define CMD_GET_BUSPARAMS_RESP 18 + #define CMD_GET_CHIP_STATE_REQ 19 + #define CMD_CHIP_STATE_EVENT 20 + #define CMD_SET_DRIVERMODE_REQ 21 +@@ -196,13 +198,26 @@ struct kvaser_cmd_chip_state_event { + #define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO 0x01 + #define KVASER_USB_HYDRA_BUS_MODE_NONISO 0x02 + struct kvaser_cmd_set_busparams { +- struct kvaser_usb_busparams busparams_arb; ++ struct kvaser_usb_busparams busparams_nominal; + u8 reserved0[4]; + struct kvaser_usb_busparams busparams_data; + u8 canfd_mode; + u8 reserved1[7]; + } __packed; + ++/* Busparam type */ ++#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN 0x00 ++#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD 0x01 ++struct kvaser_cmd_get_busparams_req { ++ u8 type; ++ u8 reserved[27]; ++} __packed; ++ ++struct kvaser_cmd_get_busparams_res { ++ struct kvaser_usb_busparams busparams; ++ u8 reserved[20]; ++} __packed; ++ + /* Ctrl modes */ + #define KVASER_USB_HYDRA_CTRLMODE_NORMAL 0x01 + #define KVASER_USB_HYDRA_CTRLMODE_LISTEN 0x02 +@@ -273,6 +288,8 @@ struct kvaser_cmd { + struct kvaser_cmd_error_event error_event; + + struct kvaser_cmd_set_busparams set_busparams_req; ++ struct kvaser_cmd_get_busparams_req get_busparams_req; ++ struct kvaser_cmd_get_busparams_res get_busparams_res; + + struct kvaser_cmd_chip_state_event chip_state_event; + +@@ -355,6 +372,10 @@ struct kvaser_cmd_ext { + } __packed; + } __packed; + ++struct kvaser_usb_net_hydra_priv { ++ int pending_get_busparams_type; ++}; ++ + static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { + .name = "kvaser_usb_kcan", + .tseg1_min = 1, +@@ -832,6 +853,39 @@ static void kvaser_usb_hydra_flush_queue_reply(const struct kvaser_usb *dev, + complete(&priv->flush_comp); + } + ++static void kvaser_usb_hydra_get_busparams_reply(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ struct kvaser_usb_net_priv *priv; ++ struct kvaser_usb_net_hydra_priv *hydra; ++ ++ priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd); ++ if (!priv) ++ return; ++ ++ hydra = priv->sub_priv; ++ if (!hydra) ++ return; ++ ++ switch (hydra->pending_get_busparams_type) { ++ case KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN: ++ memcpy(&priv->busparams_nominal, &cmd->get_busparams_res.busparams, ++ sizeof(priv->busparams_nominal)); ++ break; ++ case KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD: ++ memcpy(&priv->busparams_data, &cmd->get_busparams_res.busparams, ++ sizeof(priv->busparams_nominal)); ++ break; ++ default: ++ dev_warn(&dev->intf->dev, "Unknown get_busparams_type %d\n", ++ hydra->pending_get_busparams_type); ++ break; ++ } ++ hydra->pending_get_busparams_type = -1; ++ ++ complete(&priv->get_busparams_comp); ++} ++ + static void + kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv, + u8 bus_status, +@@ -1318,6 +1372,10 @@ static void kvaser_usb_hydra_handle_cmd_std(const struct kvaser_usb *dev, + kvaser_usb_hydra_state_event(dev, cmd); + break; + ++ case CMD_GET_BUSPARAMS_RESP: ++ kvaser_usb_hydra_get_busparams_reply(dev, cmd); ++ break; ++ + case CMD_ERROR_EVENT: + kvaser_usb_hydra_error_event(dev, cmd); + break; +@@ -1518,15 +1576,58 @@ static int kvaser_usb_hydra_set_mode(struct net_device *netdev, + return err; + } + +-static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) ++static int kvaser_usb_hydra_get_busparams(struct kvaser_usb_net_priv *priv, ++ int busparams_type) ++{ ++ struct kvaser_usb *dev = priv->dev; ++ struct kvaser_usb_net_hydra_priv *hydra = priv->sub_priv; ++ struct kvaser_cmd *cmd; ++ int err; ++ ++ if (!hydra) ++ return -EINVAL; ++ ++ cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ cmd->header.cmd_no = CMD_GET_BUSPARAMS_REQ; ++ kvaser_usb_hydra_set_cmd_dest_he ++ (cmd, dev->card_data.hydra.channel_to_he[priv->channel]); ++ kvaser_usb_hydra_set_cmd_transid ++ (cmd, kvaser_usb_hydra_get_next_transid(dev)); ++ cmd->get_busparams_req.type = busparams_type; ++ hydra->pending_get_busparams_type = busparams_type; ++ ++ reinit_completion(&priv->get_busparams_comp); ++ ++ err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd)); ++ if (err) ++ return err; ++ ++ if (!wait_for_completion_timeout(&priv->get_busparams_comp, ++ msecs_to_jiffies(KVASER_USB_TIMEOUT))) ++ return -ETIMEDOUT; ++ ++ return err; ++} ++ ++static int kvaser_usb_hydra_get_nominal_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN); ++} ++ ++static int kvaser_usb_hydra_get_data_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD); ++} ++ ++static int kvaser_usb_hydra_set_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_cmd *cmd; + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *bt = &priv->can.bittiming; + struct kvaser_usb *dev = priv->dev; +- int tseg1 = bt->prop_seg + bt->phase_seg1; +- int tseg2 = bt->phase_seg2; +- int sjw = bt->sjw; + int err; + + cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL); +@@ -1534,11 +1635,8 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ; +- cmd->set_busparams_req.busparams_arb.bitrate = cpu_to_le32(bt->bitrate); +- cmd->set_busparams_req.busparams_arb.sjw = (u8)sjw; +- cmd->set_busparams_req.busparams_arb.tseg1 = (u8)tseg1; +- cmd->set_busparams_req.busparams_arb.tseg2 = (u8)tseg2; +- cmd->set_busparams_req.busparams_arb.nsamples = 1; ++ memcpy(&cmd->set_busparams_req.busparams_nominal, busparams, ++ sizeof(cmd->set_busparams_req.busparams_nominal)); + + kvaser_usb_hydra_set_cmd_dest_he + (cmd, dev->card_data.hydra.channel_to_he[priv->channel]); +@@ -1552,15 +1650,12 @@ static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev) + return err; + } + +-static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) ++static int kvaser_usb_hydra_set_data_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_cmd *cmd; + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *dbt = &priv->can.data_bittiming; + struct kvaser_usb *dev = priv->dev; +- int tseg1 = dbt->prop_seg + dbt->phase_seg1; +- int tseg2 = dbt->phase_seg2; +- int sjw = dbt->sjw; + int err; + + cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL); +@@ -1568,11 +1663,8 @@ static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev) + return -ENOMEM; + + cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ; +- cmd->set_busparams_req.busparams_data.bitrate = cpu_to_le32(dbt->bitrate); +- cmd->set_busparams_req.busparams_data.sjw = (u8)sjw; +- cmd->set_busparams_req.busparams_data.tseg1 = (u8)tseg1; +- cmd->set_busparams_req.busparams_data.tseg2 = (u8)tseg2; +- cmd->set_busparams_req.busparams_data.nsamples = 1; ++ memcpy(&cmd->set_busparams_req.busparams_data, busparams, ++ sizeof(cmd->set_busparams_req.busparams_data)); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { + if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) +@@ -1679,6 +1771,19 @@ static int kvaser_usb_hydra_init_card(struct kvaser_usb *dev) + return 0; + } + ++static int kvaser_usb_hydra_init_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_hydra_priv *hydra; ++ ++ hydra = devm_kzalloc(&priv->dev->intf->dev, sizeof(*hydra), GFP_KERNEL); ++ if (!hydra) ++ return -ENOMEM; ++ ++ priv->sub_priv = hydra; ++ ++ return 0; ++} ++ + static int kvaser_usb_hydra_get_software_info(struct kvaser_usb *dev) + { + struct kvaser_cmd cmd; +@@ -2023,10 +2128,13 @@ kvaser_usb_hydra_frame_to_cmd(const struct kvaser_usb_net_priv *priv, + const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = { + .dev_set_mode = kvaser_usb_hydra_set_mode, + .dev_set_bittiming = kvaser_usb_hydra_set_bittiming, ++ .dev_get_busparams = kvaser_usb_hydra_get_nominal_busparams, + .dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming, ++ .dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams, + .dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter, + .dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints, + .dev_init_card = kvaser_usb_hydra_init_card, ++ .dev_init_channel = kvaser_usb_hydra_init_channel, + .dev_get_software_info = kvaser_usb_hydra_get_software_info, + .dev_get_software_details = kvaser_usb_hydra_get_software_details, + .dev_get_card_info = kvaser_usb_hydra_get_card_info, +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 9818bc6dc8e9..ad3103391c79 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -57,6 +57,8 @@ + #define CMD_RX_EXT_MESSAGE 14 + #define CMD_TX_EXT_MESSAGE 15 + #define CMD_SET_BUS_PARAMS 16 ++#define CMD_GET_BUS_PARAMS 17 ++#define CMD_GET_BUS_PARAMS_REPLY 18 + #define CMD_GET_CHIP_STATE 19 + #define CMD_CHIP_STATE_EVENT 20 + #define CMD_SET_CTRL_MODE 21 +@@ -376,6 +378,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), + [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), ++ [CMD_GET_BUS_PARAMS_REPLY] = kvaser_fsize(u.busparams), + [CMD_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, +@@ -1468,6 +1471,25 @@ static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, + complete(&priv->stop_comp); + } + ++static void kvaser_usb_leaf_get_busparams_reply(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ struct kvaser_usb_net_priv *priv; ++ u8 channel = cmd->u.busparams.channel; ++ ++ if (channel >= dev->nchannels) { ++ dev_err(&dev->intf->dev, ++ "Invalid channel number (%d)\n", channel); ++ return; ++ } ++ ++ priv = dev->nets[channel]; ++ memcpy(&priv->busparams_nominal, &cmd->u.busparams.busparams, ++ sizeof(priv->busparams_nominal)); ++ ++ complete(&priv->get_busparams_comp); ++} ++ + static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -1510,6 +1532,10 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, + kvaser_usb_leaf_error_event(dev, cmd); + break; + ++ case CMD_GET_BUS_PARAMS_REPLY: ++ kvaser_usb_leaf_get_busparams_reply(dev, cmd); ++ break; ++ + /* Ignored commands */ + case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: + if (dev->driver_info->family != KVASER_USBCAN) +@@ -1684,10 +1710,10 @@ static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv) + cancel_delayed_work_sync(&leaf->chip_state_req_work); + } + +-static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) ++static int kvaser_usb_leaf_set_bittiming(const struct net_device *netdev, ++ const struct kvaser_usb_busparams *busparams) + { + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +- struct can_bittiming *bt = &priv->can.bittiming; + struct kvaser_usb *dev = priv->dev; + struct kvaser_cmd *cmd; + int rc; +@@ -1700,15 +1726,8 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams); + cmd->u.busparams.channel = priv->channel; + cmd->u.busparams.tid = 0xff; +- cmd->u.busparams.busparams.bitrate = cpu_to_le32(bt->bitrate); +- cmd->u.busparams.busparams.sjw = bt->sjw; +- cmd->u.busparams.busparams.tseg1 = bt->prop_seg + bt->phase_seg1; +- cmd->u.busparams.busparams.tseg2 = bt->phase_seg2; +- +- if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) +- cmd->u.busparams.busparams.nsamples = 3; +- else +- cmd->u.busparams.busparams.nsamples = 1; ++ memcpy(&cmd->u.busparams.busparams, busparams, ++ sizeof(cmd->u.busparams.busparams)); + + rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); + +@@ -1716,6 +1735,27 @@ static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + return rc; + } + ++static int kvaser_usb_leaf_get_busparams(struct kvaser_usb_net_priv *priv) ++{ ++ int err; ++ ++ if (priv->dev->driver_info->family == KVASER_USBCAN) ++ return -EOPNOTSUPP; ++ ++ reinit_completion(&priv->get_busparams_comp); ++ ++ err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_GET_BUS_PARAMS, ++ priv->channel); ++ if (err) ++ return err; ++ ++ if (!wait_for_completion_timeout(&priv->get_busparams_comp, ++ msecs_to_jiffies(KVASER_USB_TIMEOUT))) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ + static int kvaser_usb_leaf_set_mode(struct net_device *netdev, + enum can_mode mode) + { +@@ -1777,7 +1817,9 @@ static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev) + const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_set_mode = kvaser_usb_leaf_set_mode, + .dev_set_bittiming = kvaser_usb_leaf_set_bittiming, ++ .dev_get_busparams = kvaser_usb_leaf_get_busparams, + .dev_set_data_bittiming = NULL, ++ .dev_get_data_busparams = NULL, + .dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter, + .dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints, + .dev_init_card = kvaser_usb_leaf_init_card, +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-do-not-increase-tx-statistics-when-se.patch b/queue-5.15/can-kvaser_usb-do-not-increase-tx-statistics-when-se.patch new file mode 100644 index 00000000000..37f6b549092 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-do-not-increase-tx-statistics-when-se.patch @@ -0,0 +1,76 @@ +From f6598cad4578324280585a6a31a55c0671fbb818 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Dec 2021 21:15:28 +0900 +Subject: can: kvaser_usb: do not increase tx statistics when sending error + message frames + +From: Vincent Mailhol + +[ Upstream commit 0b0ce2c67795672115ac6ca28351a78799cd114b ] + +The CAN error message frames (i.e. error skb) are an interface +specific to socket CAN. The payload of the CAN error message frames +does not correspond to any actual data sent on the wire. Only an error +flag and a delimiter are transmitted when an error occurs (c.f. ISO +11898-1 section 10.4.4.2 "Error flag"). + +For this reason, it makes no sense to increment the tx_packets and +tx_bytes fields of struct net_device_stats when sending an error +message frame because no actual payload will be transmitted on the +wire. + +N.B. Sending error message frames is a very specific feature which, at +the moment, is only supported by the Kvaser Hydra hardware. Please +refer to [1] for more details on the topic. + +[1] https://lore.kernel.org/linux-can/CAMZ6RqK0rTNg3u3mBpZOoY51jLZ-et-J01tY6-+mWsM4meVw-A@mail.gmail.com/t/#u + +Link: https://lore.kernel.org/all/20211207121531.42941-3-mailhol.vincent@wanadoo.fr +Co-developed-by: Jimmy Assarsson +Signed-off-by: Jimmy Assarsson +Signed-off-by: Vincent Mailhol +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 35364f5b41a4 ("can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device") +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +index 3ff2cd9828d2..215f2b48db24 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -295,6 +295,7 @@ struct kvaser_cmd { + #define KVASER_USB_HYDRA_CF_FLAG_OVERRUN BIT(1) + #define KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME BIT(4) + #define KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID BIT(5) ++#define KVASER_USB_HYDRA_CF_FLAG_TX_ACK BIT(6) + /* CAN frame flags. Used in ext_rx_can and ext_tx_can */ + #define KVASER_USB_HYDRA_CF_FLAG_OSM_NACK BIT(12) + #define KVASER_USB_HYDRA_CF_FLAG_ABL BIT(13) +@@ -1125,6 +1126,7 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev, + struct kvaser_usb_net_priv *priv; + unsigned long irq_flags; + bool one_shot_fail = false; ++ bool is_err_frame = false; + u16 transid = kvaser_usb_hydra_get_cmd_transid(cmd); + + priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd); +@@ -1143,10 +1145,13 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev, + kvaser_usb_hydra_one_shot_fail(priv, cmd_ext); + one_shot_fail = true; + } ++ ++ is_err_frame = flags & KVASER_USB_HYDRA_CF_FLAG_TX_ACK && ++ flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME; + } + + context = &priv->tx_contexts[transid % dev->max_tx_urbs]; +- if (!one_shot_fail) { ++ if (!one_shot_fail && !is_err_frame) { + struct net_device_stats *stats = &priv->netdev->stats; + + stats->tx_packets++; +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-get-capabilities-from.patch b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-get-capabilities-from.patch new file mode 100644 index 00000000000..e3631c2614d --- /dev/null +++ b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-get-capabilities-from.patch @@ -0,0 +1,231 @@ +From b647a2bf6680bdfd182b6a983d2217718afd6770 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:28 +0200 +Subject: can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device + +From: Jimmy Assarsson + +[ Upstream commit 35364f5b41a4917fe94a3f393d149b63ec583297 ] + +Use the CMD_GET_CAPABILITIES_REQ command to query the device for certain +capabilities. We are only interested in LISTENONLY mode and wither the +device reports CAN error counters. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Reported-by: Anssi Hannula +Tested-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-3-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 144 +++++++++++++++++- + 1 file changed, 143 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 7a71097281c2..6c7ee1f0a9d9 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -73,6 +73,8 @@ + #define CMD_TX_ACKNOWLEDGE 50 + #define CMD_CAN_ERROR_EVENT 51 + #define CMD_FLUSH_QUEUE_REPLY 68 ++#define CMD_GET_CAPABILITIES_REQ 95 ++#define CMD_GET_CAPABILITIES_RESP 96 + + #define CMD_LEAF_LOG_MESSAGE 106 + +@@ -82,6 +84,8 @@ + #define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) + #define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) + ++#define KVASER_USB_LEAF_SWOPTION_EXT_CAP BIT(12) ++ + /* error factors */ + #define M16C_EF_ACKE BIT(0) + #define M16C_EF_CRCE BIT(1) +@@ -277,6 +281,28 @@ struct leaf_cmd_log_message { + u8 data[8]; + } __packed; + ++/* Sub commands for cap_req and cap_res */ ++#define KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE 0x02 ++#define KVASER_USB_LEAF_CAP_CMD_ERR_REPORT 0x05 ++struct kvaser_cmd_cap_req { ++ __le16 padding0; ++ __le16 cap_cmd; ++ __le16 padding1; ++ __le16 channel; ++} __packed; ++ ++/* Status codes for cap_res */ ++#define KVASER_USB_LEAF_CAP_STAT_OK 0x00 ++#define KVASER_USB_LEAF_CAP_STAT_NOT_IMPL 0x01 ++#define KVASER_USB_LEAF_CAP_STAT_UNAVAIL 0x02 ++struct kvaser_cmd_cap_res { ++ __le16 padding; ++ __le16 cap_cmd; ++ __le16 status; ++ __le32 mask; ++ __le32 value; ++} __packed; ++ + struct kvaser_cmd { + u8 len; + u8 id; +@@ -294,6 +320,8 @@ struct kvaser_cmd { + struct leaf_cmd_chip_state_event chip_state_event; + struct leaf_cmd_error_event error_event; + struct leaf_cmd_log_message log_message; ++ struct kvaser_cmd_cap_req cap_req; ++ struct kvaser_cmd_cap_res cap_res; + } __packed leaf; + + union { +@@ -323,6 +351,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), ++ [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, + }; +@@ -607,6 +636,9 @@ static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, + dev->fw_version = le32_to_cpu(softinfo->fw_version); + dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); + ++ if (sw_options & KVASER_USB_LEAF_SWOPTION_EXT_CAP) ++ dev->card_data.capabilities |= KVASER_USB_CAP_EXT_CAP; ++ + if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) { + /* Firmware expects bittiming parameters calculated for 16MHz + * clock, regardless of the actual clock +@@ -694,6 +726,116 @@ static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) + return 0; + } + ++static int kvaser_usb_leaf_get_single_capability(struct kvaser_usb *dev, ++ u16 cap_cmd_req, u16 *status) ++{ ++ struct kvaser_usb_dev_card_data *card_data = &dev->card_data; ++ struct kvaser_cmd *cmd; ++ u32 value = 0; ++ u32 mask = 0; ++ u16 cap_cmd_res; ++ int err; ++ int i; ++ ++ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); ++ if (!cmd) ++ return -ENOMEM; ++ ++ cmd->id = CMD_GET_CAPABILITIES_REQ; ++ cmd->u.leaf.cap_req.cap_cmd = cpu_to_le16(cap_cmd_req); ++ cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_cap_req); ++ ++ err = kvaser_usb_send_cmd(dev, cmd, cmd->len); ++ if (err) ++ goto end; ++ ++ err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_CAPABILITIES_RESP, cmd); ++ if (err) ++ goto end; ++ ++ *status = le16_to_cpu(cmd->u.leaf.cap_res.status); ++ ++ if (*status != KVASER_USB_LEAF_CAP_STAT_OK) ++ goto end; ++ ++ cap_cmd_res = le16_to_cpu(cmd->u.leaf.cap_res.cap_cmd); ++ switch (cap_cmd_res) { ++ case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE: ++ case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT: ++ value = le32_to_cpu(cmd->u.leaf.cap_res.value); ++ mask = le32_to_cpu(cmd->u.leaf.cap_res.mask); ++ break; ++ default: ++ dev_warn(&dev->intf->dev, "Unknown capability command %u\n", ++ cap_cmd_res); ++ break; ++ } ++ ++ for (i = 0; i < dev->nchannels; i++) { ++ if (BIT(i) & (value & mask)) { ++ switch (cap_cmd_res) { ++ case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE: ++ card_data->ctrlmode_supported |= ++ CAN_CTRLMODE_LISTENONLY; ++ break; ++ case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT: ++ card_data->capabilities |= ++ KVASER_USB_CAP_BERR_CAP; ++ break; ++ } ++ } ++ } ++ ++end: ++ kfree(cmd); ++ ++ return err; ++} ++ ++static int kvaser_usb_leaf_get_capabilities_leaf(struct kvaser_usb *dev) ++{ ++ int err; ++ u16 status; ++ ++ if (!(dev->card_data.capabilities & KVASER_USB_CAP_EXT_CAP)) { ++ dev_info(&dev->intf->dev, ++ "No extended capability support. Upgrade device firmware.\n"); ++ return 0; ++ } ++ ++ err = kvaser_usb_leaf_get_single_capability(dev, ++ KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE, ++ &status); ++ if (err) ++ return err; ++ if (status) ++ dev_info(&dev->intf->dev, ++ "KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE failed %u\n", ++ status); ++ ++ err = kvaser_usb_leaf_get_single_capability(dev, ++ KVASER_USB_LEAF_CAP_CMD_ERR_REPORT, ++ &status); ++ if (err) ++ return err; ++ if (status) ++ dev_info(&dev->intf->dev, ++ "KVASER_USB_LEAF_CAP_CMD_ERR_REPORT failed %u\n", ++ status); ++ ++ return 0; ++} ++ ++static int kvaser_usb_leaf_get_capabilities(struct kvaser_usb *dev) ++{ ++ int err = 0; ++ ++ if (dev->driver_info->family == KVASER_LEAF) ++ err = kvaser_usb_leaf_get_capabilities_leaf(dev); ++ ++ return err; ++} ++ + static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -1490,7 +1632,7 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_get_software_info = kvaser_usb_leaf_get_software_info, + .dev_get_software_details = NULL, + .dev_get_card_info = kvaser_usb_leaf_get_card_info, +- .dev_get_capabilities = NULL, ++ .dev_get_capabilities = kvaser_usb_leaf_get_capabilities, + .dev_set_opt_mode = kvaser_usb_leaf_set_opt_mode, + .dev_start_chip = kvaser_usb_leaf_start_chip, + .dev_stop_chip = kvaser_usb_leaf_stop_chip, +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-handle-cmd_error_even.patch b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-handle-cmd_error_even.patch new file mode 100644 index 00000000000..29fe2e9f3a2 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-handle-cmd_error_even.patch @@ -0,0 +1,186 @@ +From 6e1cf10b670d834f11f022bd1493d9c98b187761 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:30 +0200 +Subject: can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT + +From: Jimmy Assarsson + +[ Upstream commit b24cb2d169e0c9dce664a959e1f2aa9781285dc9 ] + +The device will send an error event command, to indicate certain errors. +This indicates a misbehaving driver, and should never occur. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Tested-by: Anssi Hannula +Co-developed-by: Anssi Hannula +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-5-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 99 +++++++++++++++++++ + 1 file changed, 99 insertions(+) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index d6553d9ee958..a59cb4ea5456 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -69,6 +69,7 @@ + #define CMD_GET_CARD_INFO_REPLY 35 + #define CMD_GET_SOFTWARE_INFO 38 + #define CMD_GET_SOFTWARE_INFO_REPLY 39 ++#define CMD_ERROR_EVENT 45 + #define CMD_FLUSH_QUEUE 48 + #define CMD_TX_ACKNOWLEDGE 50 + #define CMD_CAN_ERROR_EVENT 51 +@@ -257,6 +258,28 @@ struct usbcan_cmd_can_error_event { + __le16 time; + } __packed; + ++/* CMD_ERROR_EVENT error codes */ ++#define KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL 0x8 ++#define KVASER_USB_LEAF_ERROR_EVENT_PARAM 0x9 ++ ++struct leaf_cmd_error_event { ++ u8 tid; ++ u8 error_code; ++ __le16 timestamp[3]; ++ __le16 padding; ++ __le16 info1; ++ __le16 info2; ++} __packed; ++ ++struct usbcan_cmd_error_event { ++ u8 tid; ++ u8 error_code; ++ __le16 info1; ++ __le16 info2; ++ __le16 timestamp; ++ __le16 padding; ++} __packed; ++ + struct kvaser_cmd_ctrl_mode { + u8 tid; + u8 channel; +@@ -320,6 +343,7 @@ struct kvaser_cmd { + struct leaf_cmd_chip_state_event chip_state_event; + struct leaf_cmd_can_error_event can_error_event; + struct leaf_cmd_log_message log_message; ++ struct leaf_cmd_error_event error_event; + struct kvaser_cmd_cap_req cap_req; + struct kvaser_cmd_cap_res cap_res; + } __packed leaf; +@@ -329,6 +353,7 @@ struct kvaser_cmd { + struct usbcan_cmd_rx_can rx_can; + struct usbcan_cmd_chip_state_event chip_state_event; + struct usbcan_cmd_can_error_event can_error_event; ++ struct usbcan_cmd_error_event error_event; + } __packed usbcan; + + struct kvaser_cmd_tx_can tx_can; +@@ -352,6 +377,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), + [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), ++ [CMD_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, + }; +@@ -366,6 +392,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), + [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event), ++ [CMD_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), + /* ignored events: */ + [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, + }; +@@ -1308,6 +1335,74 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, + netif_rx(skb); + } + ++static void kvaser_usb_leaf_error_event_parameter(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ u16 info1 = 0; ++ ++ switch (dev->driver_info->family) { ++ case KVASER_LEAF: ++ info1 = le16_to_cpu(cmd->u.leaf.error_event.info1); ++ break; ++ case KVASER_USBCAN: ++ info1 = le16_to_cpu(cmd->u.usbcan.error_event.info1); ++ break; ++ } ++ ++ /* info1 will contain the offending cmd_no */ ++ switch (info1) { ++ case CMD_SET_CTRL_MODE: ++ dev_warn(&dev->intf->dev, ++ "CMD_SET_CTRL_MODE error in parameter\n"); ++ break; ++ ++ case CMD_SET_BUS_PARAMS: ++ dev_warn(&dev->intf->dev, ++ "CMD_SET_BUS_PARAMS error in parameter\n"); ++ break; ++ ++ default: ++ dev_warn(&dev->intf->dev, ++ "Unhandled parameter error event cmd_no (%u)\n", ++ info1); ++ break; ++ } ++} ++ ++static void kvaser_usb_leaf_error_event(const struct kvaser_usb *dev, ++ const struct kvaser_cmd *cmd) ++{ ++ u8 error_code = 0; ++ ++ switch (dev->driver_info->family) { ++ case KVASER_LEAF: ++ error_code = cmd->u.leaf.error_event.error_code; ++ break; ++ case KVASER_USBCAN: ++ error_code = cmd->u.usbcan.error_event.error_code; ++ break; ++ } ++ ++ switch (error_code) { ++ case KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL: ++ /* Received additional CAN message, when firmware TX queue is ++ * already full. Something is wrong with the driver. ++ * This should never happen! ++ */ ++ dev_err(&dev->intf->dev, ++ "Received error event TX_QUEUE_FULL\n"); ++ break; ++ case KVASER_USB_LEAF_ERROR_EVENT_PARAM: ++ kvaser_usb_leaf_error_event_parameter(dev, cmd); ++ break; ++ ++ default: ++ dev_warn(&dev->intf->dev, ++ "Unhandled error event (%d)\n", error_code); ++ break; ++ } ++} ++ + static void kvaser_usb_leaf_start_chip_reply(const struct kvaser_usb *dev, + const struct kvaser_cmd *cmd) + { +@@ -1386,6 +1481,10 @@ static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, + kvaser_usb_leaf_tx_acknowledge(dev, cmd); + break; + ++ case CMD_ERROR_EVENT: ++ kvaser_usb_leaf_error_event(dev, cmd); ++ break; ++ + /* Ignored commands */ + case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: + if (dev->driver_info->family != KVASER_USBCAN) +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-rename-leaf-usbcan-_c.patch b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-rename-leaf-usbcan-_c.patch new file mode 100644 index 00000000000..83d45393a66 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-kvaser_usb_leaf-rename-leaf-usbcan-_c.patch @@ -0,0 +1,136 @@ +From b74bc37696cdeb8bb1d273a1b3fceb48a2d02260 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:29 +0200 +Subject: can: kvaser_usb: kvaser_usb_leaf: Rename + {leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event + +From: Jimmy Assarsson + +[ Upstream commit 7ea56128dbf904a3359bcf9289cccdfa3c85c7e8 ] + +Prepare for handling CMD_ERROR_EVENT. Rename struct +{leaf,usbcan}_cmd_error_event to {leaf,usbcan}_cmd_can_error_event. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Reported-by: Anssi Hannula +Tested-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-4-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 38 +++++++++---------- + 1 file changed, 19 insertions(+), 19 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 6c7ee1f0a9d9..d6553d9ee958 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -233,7 +233,7 @@ struct kvaser_cmd_tx_acknowledge_header { + u8 tid; + } __packed; + +-struct leaf_cmd_error_event { ++struct leaf_cmd_can_error_event { + u8 tid; + u8 flags; + __le16 time[3]; +@@ -245,7 +245,7 @@ struct leaf_cmd_error_event { + u8 error_factor; + } __packed; + +-struct usbcan_cmd_error_event { ++struct usbcan_cmd_can_error_event { + u8 tid; + u8 padding; + u8 tx_errors_count_ch0; +@@ -318,7 +318,7 @@ struct kvaser_cmd { + struct leaf_cmd_softinfo softinfo; + struct leaf_cmd_rx_can rx_can; + struct leaf_cmd_chip_state_event chip_state_event; +- struct leaf_cmd_error_event error_event; ++ struct leaf_cmd_can_error_event can_error_event; + struct leaf_cmd_log_message log_message; + struct kvaser_cmd_cap_req cap_req; + struct kvaser_cmd_cap_res cap_res; +@@ -328,7 +328,7 @@ struct kvaser_cmd { + struct usbcan_cmd_softinfo softinfo; + struct usbcan_cmd_rx_can rx_can; + struct usbcan_cmd_chip_state_event chip_state_event; +- struct usbcan_cmd_error_event error_event; ++ struct usbcan_cmd_can_error_event can_error_event; + } __packed usbcan; + + struct kvaser_cmd_tx_can tx_can; +@@ -350,7 +350,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.leaf.rx_can), + [CMD_LEAF_LOG_MESSAGE] = kvaser_fsize(u.leaf.log_message), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.leaf.chip_state_event), +- [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.error_event), ++ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.leaf.can_error_event), + [CMD_GET_CAPABILITIES_RESP] = kvaser_fsize(u.leaf.cap_res), + /* ignored events: */ + [CMD_FLUSH_QUEUE_REPLY] = CMD_SIZE_ANY, +@@ -365,7 +365,7 @@ static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { + [CMD_RX_STD_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_RX_EXT_MESSAGE] = kvaser_fsize(u.usbcan.rx_can), + [CMD_CHIP_STATE_EVENT] = kvaser_fsize(u.usbcan.chip_state_event), +- [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.error_event), ++ [CMD_CAN_ERROR_EVENT] = kvaser_fsize(u.usbcan.can_error_event), + /* ignored events: */ + [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, + }; +@@ -1137,11 +1137,11 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, + + case CMD_CAN_ERROR_EVENT: + es.channel = 0; +- es.status = cmd->u.usbcan.error_event.status_ch0; +- es.txerr = cmd->u.usbcan.error_event.tx_errors_count_ch0; +- es.rxerr = cmd->u.usbcan.error_event.rx_errors_count_ch0; ++ es.status = cmd->u.usbcan.can_error_event.status_ch0; ++ es.txerr = cmd->u.usbcan.can_error_event.tx_errors_count_ch0; ++ es.rxerr = cmd->u.usbcan.can_error_event.rx_errors_count_ch0; + es.usbcan.other_ch_status = +- cmd->u.usbcan.error_event.status_ch1; ++ cmd->u.usbcan.can_error_event.status_ch1; + kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); + + /* The USBCAN firmware supports up to 2 channels. +@@ -1149,13 +1149,13 @@ static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, + */ + if (dev->nchannels == MAX_USBCAN_NET_DEVICES) { + es.channel = 1; +- es.status = cmd->u.usbcan.error_event.status_ch1; ++ es.status = cmd->u.usbcan.can_error_event.status_ch1; + es.txerr = +- cmd->u.usbcan.error_event.tx_errors_count_ch1; ++ cmd->u.usbcan.can_error_event.tx_errors_count_ch1; + es.rxerr = +- cmd->u.usbcan.error_event.rx_errors_count_ch1; ++ cmd->u.usbcan.can_error_event.rx_errors_count_ch1; + es.usbcan.other_ch_status = +- cmd->u.usbcan.error_event.status_ch0; ++ cmd->u.usbcan.can_error_event.status_ch0; + kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); + } + break; +@@ -1172,11 +1172,11 @@ static void kvaser_usb_leaf_leaf_rx_error(const struct kvaser_usb *dev, + + switch (cmd->id) { + case CMD_CAN_ERROR_EVENT: +- es.channel = cmd->u.leaf.error_event.channel; +- es.status = cmd->u.leaf.error_event.status; +- es.txerr = cmd->u.leaf.error_event.tx_errors_count; +- es.rxerr = cmd->u.leaf.error_event.rx_errors_count; +- es.leaf.error_factor = cmd->u.leaf.error_event.error_factor; ++ es.channel = cmd->u.leaf.can_error_event.channel; ++ es.status = cmd->u.leaf.can_error_event.status; ++ es.txerr = cmd->u.leaf.can_error_event.tx_errors_count; ++ es.rxerr = cmd->u.leaf.can_error_event.rx_errors_count; ++ es.leaf.error_factor = cmd->u.leaf.can_error_event.error_factor; + break; + case CMD_LEAF_LOG_MESSAGE: + es.channel = cmd->u.leaf.log_message.channel; +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb-make-use-of-units.h-in-assignment-of-.patch b/queue-5.15/can-kvaser_usb-make-use-of-units.h-in-assignment-of-.patch new file mode 100644 index 00000000000..cad51120621 --- /dev/null +++ b/queue-5.15/can-kvaser_usb-make-use-of-units.h-in-assignment-of-.patch @@ -0,0 +1,112 @@ +From 58d98c5ebef30cf9c510da37d4d7e22ed78d8877 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Dec 2021 12:56:05 +0100 +Subject: can: kvaser_usb: make use of units.h in assignment of frequency + +From: Jimmy Assarsson + +[ Upstream commit b8f91799687eeb6ffe73b66420db46d8c0292295 ] + +Use the MEGA define plus the comment /* Hz */ when assigning +frequencies. + +Link: https://lore.kernel.org/all/20211210075803.343841-1-mkl@pengutronix.de +Signed-off-by: Jimmy Assarsson +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 8d21f5927ae6 ("can: kvaser_usb_leaf: Fix improved state not being reported") +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 7 ++++--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 9 +++++---- + 2 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +index 215f2b48db24..b485f0bc2e6b 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -2049,7 +2050,7 @@ const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_kcan = { + .clock = { +- .freq = 80000000, ++ .freq = 80 * MEGA /* Hz */, + }, + .timestamp_freq = 80, + .bittiming_const = &kvaser_usb_hydra_kcan_bittiming_c, +@@ -2058,7 +2059,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_kcan = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = { + .clock = { +- .freq = 24000000, ++ .freq = 24 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, +@@ -2066,7 +2067,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_flexc = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_hydra_dev_cfg_rt = { + .clock = { +- .freq = 80000000, ++ .freq = 80 * MEGA /* Hz */, + }, + .timestamp_freq = 24, + .bittiming_const = &kvaser_usb_hydra_rt_bittiming_c, +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index a653318f583a..6d64d566873d 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -446,7 +447,7 @@ static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = { + .clock = { +- .freq = 8000000, ++ .freq = 8 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const, +@@ -454,7 +455,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = { + .clock = { +- .freq = 16000000, ++ .freq = 16 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const, +@@ -470,7 +471,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = { + .clock = { +- .freq = 24000000, ++ .freq = 24 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, +@@ -478,7 +479,7 @@ static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = { + + static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = { + .clock = { +- .freq = 32000000, ++ .freq = 32 * MEGA /* Hz */, + }, + .timestamp_freq = 1, + .bittiming_const = &kvaser_usb_flexc_bittiming_const, +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb_leaf-fix-bogus-restart-events.patch b/queue-5.15/can-kvaser_usb_leaf-fix-bogus-restart-events.patch new file mode 100644 index 00000000000..1cb76e1acec --- /dev/null +++ b/queue-5.15/can-kvaser_usb_leaf-fix-bogus-restart-events.patch @@ -0,0 +1,66 @@ +From 8ddf81fd9638c9be9d0eb116c0536feb432ee108 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:35 +0200 +Subject: can: kvaser_usb_leaf: Fix bogus restart events + +From: Anssi Hannula + +[ Upstream commit 90904d326269a38fe5dd895fb2db7c03199654c4 ] + +When auto-restart is enabled, the kvaser_usb_leaf driver considers +transition from any state >= CAN_STATE_BUS_OFF as a bus-off recovery +event (restart). + +However, these events may occur at interface startup time before +kvaser_usb_open() has set the state to CAN_STATE_ERROR_ACTIVE, causing +restarts counter to increase and CAN_ERR_RESTARTED to be sent despite no +actual restart having occurred. + +Fix that by making the auto-restart condition checks more strict so that +they only trigger when the interface was actually in the BUS_OFF state. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Tested-by: Jimmy Assarsson +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-10-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 5888b2fb5eb3..b44a9ca22136 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -900,7 +900,7 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev, + context = &priv->tx_contexts[tid % dev->max_tx_urbs]; + + /* Sometimes the state change doesn't come after a bus-off event */ +- if (priv->can.restart_ms && priv->can.state >= CAN_STATE_BUS_OFF) { ++ if (priv->can.restart_ms && priv->can.state == CAN_STATE_BUS_OFF) { + struct sk_buff *skb; + struct can_frame *cf; + +@@ -1003,7 +1003,7 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + } + + if (priv->can.restart_ms && +- cur_state >= CAN_STATE_BUS_OFF && ++ cur_state == CAN_STATE_BUS_OFF && + new_state < CAN_STATE_BUS_OFF) + priv->can.can_stats.restarts++; + +@@ -1093,7 +1093,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + } + + if (priv->can.restart_ms && +- old_state >= CAN_STATE_BUS_OFF && ++ old_state == CAN_STATE_BUS_OFF && + new_state < CAN_STATE_BUS_OFF) { + cf->can_id |= CAN_ERR_RESTARTED; + netif_carrier_on(priv->netdev); +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb_leaf-fix-improved-state-not-being-rep.patch b/queue-5.15/can-kvaser_usb_leaf-fix-improved-state-not-being-rep.patch new file mode 100644 index 00000000000..f4bf3c72c8a --- /dev/null +++ b/queue-5.15/can-kvaser_usb_leaf-fix-improved-state-not-being-rep.patch @@ -0,0 +1,259 @@ +From bf133da19e0e50d5cf542d166b8c0baaa40dc021 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:32 +0200 +Subject: can: kvaser_usb_leaf: Fix improved state not being reported + +From: Anssi Hannula + +[ Upstream commit 8d21f5927ae604881f98587fabf6753f88730968 ] + +The tested 0bfd:0017 Kvaser Memorator Professional HS/HS FW 2.0.50 and +0bfd:0124 Kvaser Mini PCI Express 2xHS FW 4.18.778 do not seem to send +any unsolicited events when error counters decrease or when the device +transitions from ERROR_PASSIVE to ERROR_ACTIVE (or WARNING). + +This causes the interface to e.g. indefinitely stay in the ERROR_PASSIVE +state. + +Fix that by asking for chip state (inc. counters) event every 0.5 secs +when error counters are non-zero. + +Since there are non-error-counter devices, also always poll in +ERROR_PASSIVE even if the counters show zero. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Tested-by: Jimmy Assarsson +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-7-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 7 +++ + .../net/can/usb/kvaser_usb/kvaser_usb_core.c | 19 +++++- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 58 +++++++++++++++++++ + 3 files changed, 81 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +index 62958f04a2f2..1f4583f1dae2 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +@@ -104,6 +104,9 @@ struct kvaser_usb_net_priv { + struct can_priv can; + struct can_berr_counter bec; + ++ /* subdriver-specific data */ ++ void *sub_priv; ++ + struct kvaser_usb *dev; + struct net_device *netdev; + int channel; +@@ -125,6 +128,8 @@ struct kvaser_usb_net_priv { + * + * @dev_setup_endpoints: setup USB in and out endpoints + * @dev_init_card: initialize card ++ * @dev_init_channel: initialize channel ++ * @dev_remove_channel: uninitialize channel + * @dev_get_software_info: get software info + * @dev_get_software_details: get software details + * @dev_get_card_info: get card info +@@ -146,6 +151,8 @@ struct kvaser_usb_dev_ops { + struct can_berr_counter *bec); + int (*dev_setup_endpoints)(struct kvaser_usb *dev); + int (*dev_init_card)(struct kvaser_usb *dev); ++ int (*dev_init_channel)(struct kvaser_usb_net_priv *priv); ++ void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv); + int (*dev_get_software_info)(struct kvaser_usb *dev); + int (*dev_get_software_details)(struct kvaser_usb *dev); + int (*dev_get_card_info)(struct kvaser_usb *dev); +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +index bdcaccf8e2b2..4915d5f180da 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +@@ -672,6 +672,7 @@ static const struct net_device_ops kvaser_usb_netdev_ops = { + + static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) + { ++ const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops; + int i; + + for (i = 0; i < dev->nchannels; i++) { +@@ -687,6 +688,9 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev) + if (!dev->nets[i]) + continue; + ++ if (ops->dev_remove_channel) ++ ops->dev_remove_channel(dev->nets[i]); ++ + free_candev(dev->nets[i]->netdev); + } + } +@@ -754,17 +758,26 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) + + dev->nets[channel] = priv; + ++ if (ops->dev_init_channel) { ++ err = ops->dev_init_channel(priv); ++ if (err) ++ goto err; ++ } ++ + err = register_candev(netdev); + if (err) { + dev_err(&dev->intf->dev, "Failed to register CAN device\n"); +- free_candev(netdev); +- dev->nets[channel] = NULL; +- return err; ++ goto err; + } + + netdev_dbg(netdev, "device registered\n"); + + return 0; ++ ++err: ++ free_candev(netdev); ++ dev->nets[channel] = NULL; ++ return err; + } + + static int kvaser_usb_probe(struct usb_interface *intf, +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index 6d64d566873d..b5d06c6b79ae 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -56,6 +57,7 @@ + #define CMD_RX_EXT_MESSAGE 14 + #define CMD_TX_EXT_MESSAGE 15 + #define CMD_SET_BUS_PARAMS 16 ++#define CMD_GET_CHIP_STATE 19 + #define CMD_CHIP_STATE_EVENT 20 + #define CMD_SET_CTRL_MODE 21 + #define CMD_RESET_CHIP 24 +@@ -421,6 +423,12 @@ struct kvaser_usb_err_summary { + }; + }; + ++struct kvaser_usb_net_leaf_priv { ++ struct kvaser_usb_net_priv *net; ++ ++ struct delayed_work chip_state_req_work; ++}; ++ + static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = { + .name = "kvaser_usb_ucii", + .tseg1_min = 4, +@@ -948,6 +956,16 @@ static int kvaser_usb_leaf_simple_cmd_async(struct kvaser_usb_net_priv *priv, + return err; + } + ++static void kvaser_usb_leaf_chip_state_req_work(struct work_struct *work) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf = ++ container_of(work, struct kvaser_usb_net_leaf_priv, ++ chip_state_req_work.work); ++ struct kvaser_usb_net_priv *priv = leaf->net; ++ ++ kvaser_usb_leaf_simple_cmd_async(priv, CMD_GET_CHIP_STATE); ++} ++ + static void + kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + const struct kvaser_usb_err_summary *es, +@@ -1019,6 +1037,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + struct sk_buff *skb; + struct net_device_stats *stats; + struct kvaser_usb_net_priv *priv; ++ struct kvaser_usb_net_leaf_priv *leaf; + enum can_state old_state, new_state; + + if (es->channel >= dev->nchannels) { +@@ -1028,6 +1047,7 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + } + + priv = dev->nets[es->channel]; ++ leaf = priv->sub_priv; + stats = &priv->netdev->stats; + + /* Update all of the CAN interface's state and error counters before +@@ -1044,6 +1064,14 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf); + new_state = priv->can.state; + ++ /* If there are errors, request status updates periodically as we do ++ * not get automatic notifications of improved state. ++ */ ++ if (new_state < CAN_STATE_BUS_OFF && ++ (es->rxerr || es->txerr || new_state == CAN_STATE_ERROR_PASSIVE)) ++ schedule_delayed_work(&leaf->chip_state_req_work, ++ msecs_to_jiffies(500)); ++ + skb = alloc_can_err_skb(priv->netdev, &cf); + if (!skb) { + stats->rx_dropped++; +@@ -1578,10 +1606,13 @@ static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv) + + static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv) + { ++ struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; + int err; + + reinit_completion(&priv->stop_comp); + ++ cancel_delayed_work(&leaf->chip_state_req_work); ++ + err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, + priv->channel); + if (err) +@@ -1628,6 +1659,31 @@ static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) + return 0; + } + ++static int kvaser_usb_leaf_init_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf; ++ ++ leaf = devm_kzalloc(&priv->dev->intf->dev, sizeof(*leaf), GFP_KERNEL); ++ if (!leaf) ++ return -ENOMEM; ++ ++ leaf->net = priv; ++ INIT_DELAYED_WORK(&leaf->chip_state_req_work, ++ kvaser_usb_leaf_chip_state_req_work); ++ ++ priv->sub_priv = leaf; ++ ++ return 0; ++} ++ ++static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv) ++{ ++ struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv; ++ ++ if (leaf) ++ cancel_delayed_work_sync(&leaf->chip_state_req_work); ++} ++ + static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) + { + struct kvaser_usb_net_priv *priv = netdev_priv(netdev); +@@ -1725,6 +1781,8 @@ const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { + .dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter, + .dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints, + .dev_init_card = kvaser_usb_leaf_init_card, ++ .dev_init_channel = kvaser_usb_leaf_init_channel, ++ .dev_remove_channel = kvaser_usb_leaf_remove_channel, + .dev_get_software_info = kvaser_usb_leaf_get_software_info, + .dev_get_software_details = NULL, + .dev_get_card_info = kvaser_usb_leaf_get_card_info, +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb_leaf-fix-wrong-can-state-after-stoppi.patch b/queue-5.15/can-kvaser_usb_leaf-fix-wrong-can-state-after-stoppi.patch new file mode 100644 index 00000000000..02df1d92024 --- /dev/null +++ b/queue-5.15/can-kvaser_usb_leaf-fix-wrong-can-state-after-stoppi.patch @@ -0,0 +1,45 @@ +From de8aace147c542b94c935ec1ecf38701b8959bcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:33 +0200 +Subject: can: kvaser_usb_leaf: Fix wrong CAN state after stopping + +From: Anssi Hannula + +[ Upstream commit a11249acf802341294557895d8e5f6aef080253f ] + +0bfd:0124 Kvaser Mini PCI Express 2xHS FW 4.18.778 sends a +CMD_CHIP_STATE_EVENT indicating bus-off after stopping the device, +causing a stopped device to appear as CAN_STATE_BUS_OFF instead of +CAN_STATE_STOPPED. + +Fix that by not handling error events on stopped devices. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Tested-by: Jimmy Assarsson +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-8-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index b5d06c6b79ae..5888b2fb5eb3 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -1050,6 +1050,10 @@ static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, + leaf = priv->sub_priv; + stats = &priv->netdev->stats; + ++ /* Ignore e.g. state change to bus-off reported just after stopping */ ++ if (!netif_running(priv->netdev)) ++ return; ++ + /* Update all of the CAN interface's state and error counters before + * trying any memory allocation that can actually fail with -ENOMEM. + * +-- +2.35.1 + diff --git a/queue-5.15/can-kvaser_usb_leaf-set-warning-state-even-without-b.patch b/queue-5.15/can-kvaser_usb_leaf-set-warning-state-even-without-b.patch new file mode 100644 index 00000000000..7a1b66d5526 --- /dev/null +++ b/queue-5.15/can-kvaser_usb_leaf-set-warning-state-even-without-b.patch @@ -0,0 +1,76 @@ +From 4ab8696aa1b139a9994abd1761f9c65a962bf536 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 20:52:31 +0200 +Subject: can: kvaser_usb_leaf: Set Warning state even without bus errors + +From: Anssi Hannula + +[ Upstream commit df1b7af2761b935f63b4a53e789d41ed859edf61 ] + +kvaser_usb_leaf_rx_error_update_can_state() sets error state according +to error counters when the hardware does not indicate a specific state +directly. + +However, this is currently gated behind a check for +M16C_STATE_BUS_ERROR which does not always seem to be set when error +counters are increasing, and may not be set when error counters are +decreasing. + +This causes the CAN_STATE_ERROR_WARNING state to not be set in some +cases even when appropriate. + +Change the code to set error state from counters even without +M16C_STATE_BUS_ERROR. + +The Error-Passive case seems superfluous as it is already set via +M16C_STATE_BUS_PASSIVE flag above, but it is kept for now. + +Tested with 0bfd:0124 Kvaser Mini PCI Express 2xHS FW 4.18.778. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Tested-by: Jimmy Assarsson +Signed-off-by: Anssi Hannula +Signed-off-by: Jimmy Assarsson +Link: https://lore.kernel.org/all/20221010185237.319219-6-extja@kvaser.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + .../net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 20 ++++++++----------- + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +index a59cb4ea5456..a653318f583a 100644 +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -965,20 +965,16 @@ kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, + new_state = CAN_STATE_BUS_OFF; + } else if (es->status & M16C_STATE_BUS_PASSIVE) { + new_state = CAN_STATE_ERROR_PASSIVE; +- } else if (es->status & M16C_STATE_BUS_ERROR) { ++ } else if ((es->status & M16C_STATE_BUS_ERROR) && ++ cur_state >= CAN_STATE_BUS_OFF) { + /* Guard against spurious error events after a busoff */ +- if (cur_state < CAN_STATE_BUS_OFF) { +- if (es->txerr >= 128 || es->rxerr >= 128) +- new_state = CAN_STATE_ERROR_PASSIVE; +- else if (es->txerr >= 96 || es->rxerr >= 96) +- new_state = CAN_STATE_ERROR_WARNING; +- else if (cur_state > CAN_STATE_ERROR_ACTIVE) +- new_state = CAN_STATE_ERROR_ACTIVE; +- } +- } +- +- if (!es->status) ++ } else if (es->txerr >= 128 || es->rxerr >= 128) { ++ new_state = CAN_STATE_ERROR_PASSIVE; ++ } else if (es->txerr >= 96 || es->rxerr >= 96) { ++ new_state = CAN_STATE_ERROR_WARNING; ++ } else { + new_state = CAN_STATE_ERROR_ACTIVE; ++ } + + if (new_state != cur_state) { + tx_state = (es->txerr >= es->rxerr) ? new_state : 0; +-- +2.35.1 + diff --git a/queue-5.15/can-m_can-call-the-ram-init-directly-from-m_can_chip.patch b/queue-5.15/can-m_can-call-the-ram-init-directly-from-m_can_chip.patch new file mode 100644 index 00000000000..02357387945 --- /dev/null +++ b/queue-5.15/can-m_can-call-the-ram-init-directly-from-m_can_chip.patch @@ -0,0 +1,141 @@ +From 0e8c980e278c296eff2a5e4839da537ef9cf0b29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 15:36:31 +0530 +Subject: can: m_can: Call the RAM init directly from m_can_chip_config + +From: Vivek Yadav + +[ Upstream commit eaacfeaca7ad0804b9a6eff7afeba93a87db7638 ] + +When we try to access the mcan message ram addresses during the probe, +hclk is gated by any other drivers or disabled, because of that probe +gets failed. + +Move the mram init functionality to mcan chip config called by +m_can_start from mcan open function, by that time clocks are +enabled. + +Suggested-by: Marc Kleine-Budde +Signed-off-by: Vivek Yadav +Link: https://lore.kernel.org/all/20221207100632.96200-2-vivek.2311@samsung.com +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 67727a17a6b3 ("can: tcan4x5x: Fix use of register error status mask") +Signed-off-by: Sasha Levin +--- + drivers/net/can/m_can/m_can.c | 32 +++++++++++++++++++++----- + drivers/net/can/m_can/m_can_platform.c | 4 ---- + drivers/net/can/m_can/tcan4x5x-core.c | 5 ---- + 3 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c +index 46ab6155795c..e027229c1955 100644 +--- a/drivers/net/can/m_can/m_can.c ++++ b/drivers/net/can/m_can/m_can.c +@@ -1248,10 +1248,17 @@ static int m_can_set_bittiming(struct net_device *dev) + * - setup bittiming + * - configure timestamp generation + */ +-static void m_can_chip_config(struct net_device *dev) ++static int m_can_chip_config(struct net_device *dev) + { + struct m_can_classdev *cdev = netdev_priv(dev); + u32 cccr, test; ++ int err; ++ ++ err = m_can_init_ram(cdev); ++ if (err) { ++ dev_err(cdev->dev, "Message RAM configuration failed\n"); ++ return err; ++ } + + m_can_config_endisable(cdev, true); + +@@ -1375,18 +1382,25 @@ static void m_can_chip_config(struct net_device *dev) + + if (cdev->ops->init) + cdev->ops->init(cdev); ++ ++ return 0; + } + +-static void m_can_start(struct net_device *dev) ++static int m_can_start(struct net_device *dev) + { + struct m_can_classdev *cdev = netdev_priv(dev); ++ int ret; + + /* basic m_can configuration */ +- m_can_chip_config(dev); ++ ret = m_can_chip_config(dev); ++ if (ret) ++ return ret; + + cdev->can.state = CAN_STATE_ERROR_ACTIVE; + + m_can_enable_all_interrupts(cdev); ++ ++ return 0; + } + + static int m_can_set_mode(struct net_device *dev, enum can_mode mode) +@@ -1824,7 +1838,9 @@ static int m_can_open(struct net_device *dev) + } + + /* start the m_can controller */ +- m_can_start(dev); ++ err = m_can_start(dev); ++ if (err) ++ goto exit_irq_fail; + + can_led_event(dev, CAN_LED_EVENT_OPEN); + +@@ -2082,9 +2098,13 @@ int m_can_class_resume(struct device *dev) + ret = m_can_clk_start(cdev); + if (ret) + return ret; ++ ret = m_can_start(ndev); ++ if (ret) { ++ m_can_clk_stop(cdev); ++ ++ return ret; ++ } + +- m_can_init_ram(cdev); +- m_can_start(ndev); + netif_device_attach(ndev); + netif_start_queue(ndev); + } +diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c +index eee47bad0592..de6d8e01bf2e 100644 +--- a/drivers/net/can/m_can/m_can_platform.c ++++ b/drivers/net/can/m_can/m_can_platform.c +@@ -140,10 +140,6 @@ static int m_can_plat_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, mcan_class); + +- ret = m_can_init_ram(mcan_class); +- if (ret) +- goto probe_fail; +- + pm_runtime_enable(mcan_class->dev); + ret = m_can_class_register(mcan_class); + if (ret) +diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c +index 9b735eccec8a..a0eee69e52ea 100644 +--- a/drivers/net/can/m_can/tcan4x5x-core.c ++++ b/drivers/net/can/m_can/tcan4x5x-core.c +@@ -229,11 +229,6 @@ static int tcan4x5x_init(struct m_can_classdev *cdev) + if (ret) + return ret; + +- /* Zero out the MCAN buffers */ +- ret = m_can_init_ram(cdev); +- if (ret) +- return ret; +- + ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, + TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/can-tcan4x5x-fix-use-of-register-error-status-mask.patch b/queue-5.15/can-tcan4x5x-fix-use-of-register-error-status-mask.patch new file mode 100644 index 00000000000..74dd5f97f71 --- /dev/null +++ b/queue-5.15/can-tcan4x5x-fix-use-of-register-error-status-mask.patch @@ -0,0 +1,68 @@ +From fbdb736bde807d920f5f50161042ecdbafddb244 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 12:57:26 +0100 +Subject: can: tcan4x5x: Fix use of register error status mask + +From: Markus Schneider-Pargmann + +[ Upstream commit 67727a17a6b375d68fe569b77e6516b034b834c0 ] + +TCAN4X5X_ERROR_STATUS is not a status register that needs clearing +during interrupt handling. Instead this is a masking register that masks +error interrupts. Writing TCAN4X5X_CLEAR_ALL_INT to this register +effectively masks everything. + +Rename the register and mask all error interrupts only once by writing +to the register in tcan4x5x_init. + +Fixes: 5443c226ba91 ("can: tcan4x5x: Add tcan4x5x driver to the kernel") +Signed-off-by: Markus Schneider-Pargmann +Link: https://lore.kernel.org/all/20221206115728.1056014-10-msp@baylibre.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/m_can/tcan4x5x-core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c +index a0eee69e52ea..c83b347be1cf 100644 +--- a/drivers/net/can/m_can/tcan4x5x-core.c ++++ b/drivers/net/can/m_can/tcan4x5x-core.c +@@ -10,7 +10,7 @@ + #define TCAN4X5X_DEV_ID1 0x04 + #define TCAN4X5X_REV 0x08 + #define TCAN4X5X_STATUS 0x0C +-#define TCAN4X5X_ERROR_STATUS 0x10 ++#define TCAN4X5X_ERROR_STATUS_MASK 0x10 + #define TCAN4X5X_CONTROL 0x14 + + #define TCAN4X5X_CONFIG 0x800 +@@ -204,12 +204,7 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) + if (ret) + return ret; + +- ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, +- TCAN4X5X_CLEAR_ALL_INT); +- if (ret) +- return ret; +- +- return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS, ++ return tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, + TCAN4X5X_CLEAR_ALL_INT); + } + +@@ -229,6 +224,11 @@ static int tcan4x5x_init(struct m_can_classdev *cdev) + if (ret) + return ret; + ++ ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_ERROR_STATUS_MASK, ++ TCAN4X5X_CLEAR_ALL_INT); ++ if (ret) ++ return ret; ++ + ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG, + TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/can-tcan4x5x-remove-invalid-write-in-clear_interrupt.patch b/queue-5.15/can-tcan4x5x-remove-invalid-write-in-clear_interrupt.patch new file mode 100644 index 00000000000..bff9e3194f6 --- /dev/null +++ b/queue-5.15/can-tcan4x5x-remove-invalid-write-in-clear_interrupt.patch @@ -0,0 +1,44 @@ +From 54aae6d8d09bf918385b87a229fd903c89403fd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 12:57:25 +0100 +Subject: can: tcan4x5x: Remove invalid write in clear_interrupts + +From: Markus Schneider-Pargmann + +[ Upstream commit 40c9e4f676abbe194541d88e796341c92d5a13c0 ] + +Register 0x824 TCAN4X5X_MCAN_INT_REG is a read-only register. Any writes +to this register do not have any effect. + +Remove this write. The m_can driver aldready clears the interrupts in +m_can_isr() by writing to M_CAN_IR which is translated to register +0x1050 which is a writable version of this register. + +Fixes: 5443c226ba91 ("can: tcan4x5x: Add tcan4x5x driver to the kernel") +Signed-off-by: Markus Schneider-Pargmann +Link: https://lore.kernel.org/all/20221206115728.1056014-9-msp@baylibre.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/m_can/tcan4x5x-core.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c +index 04687b15b250..9b735eccec8a 100644 +--- a/drivers/net/can/m_can/tcan4x5x-core.c ++++ b/drivers/net/can/m_can/tcan4x5x-core.c +@@ -204,11 +204,6 @@ static int tcan4x5x_clear_interrupts(struct m_can_classdev *cdev) + if (ret) + return ret; + +- ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG, +- TCAN4X5X_ENABLE_MCAN_INT); +- if (ret) +- return ret; +- + ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS, + TCAN4X5X_CLEAR_ALL_INT); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/chardev-fix-error-handling-in-cdev_device_add.patch b/queue-5.15/chardev-fix-error-handling-in-cdev_device_add.patch new file mode 100644 index 00000000000..53436be7c0e --- /dev/null +++ b/queue-5.15/chardev-fix-error-handling-in-cdev_device_add.patch @@ -0,0 +1,54 @@ +From 034d0b410718cff9c151e07557b5a062791ce7f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 11:02:37 +0800 +Subject: chardev: fix error handling in cdev_device_add() + +From: Yang Yingliang + +[ Upstream commit 11fa7fefe3d8fac7da56bc9aa3dd5fb3081ca797 ] + +While doing fault injection test, I got the following report: + +------------[ cut here ]------------ +kobject: '(null)' (0000000039956980): is not initialized, yet kobject_put() is being called. +WARNING: CPU: 3 PID: 6306 at kobject_put+0x23d/0x4e0 +CPU: 3 PID: 6306 Comm: 283 Tainted: G W 6.1.0-rc2-00005-g307c1086d7c9 #1253 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 +RIP: 0010:kobject_put+0x23d/0x4e0 +Call Trace: + + cdev_device_add+0x15e/0x1b0 + __iio_device_register+0x13b4/0x1af0 [industrialio] + __devm_iio_device_register+0x22/0x90 [industrialio] + max517_probe+0x3d8/0x6b4 [max517] + i2c_device_probe+0xa81/0xc00 + +When device_add() is injected fault and returns error, if dev->devt is not set, +cdev_add() is not called, cdev_del() is not needed. Fix this by checking dev->devt +in error path. + +Fixes: 233ed09d7fda ("chardev: add helper function to register char devs with a struct device") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221202030237.520280-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + fs/char_dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/char_dev.c b/fs/char_dev.c +index ba0ded7842a7..3f667292608c 100644 +--- a/fs/char_dev.c ++++ b/fs/char_dev.c +@@ -547,7 +547,7 @@ int cdev_device_add(struct cdev *cdev, struct device *dev) + } + + rc = device_add(dev); +- if (rc) ++ if (rc && dev->devt) + cdev_del(cdev); + + return rc; +-- +2.35.1 + diff --git a/queue-5.15/class-fix-possible-memory-leak-in-__class_register.patch b/queue-5.15/class-fix-possible-memory-leak-in-__class_register.patch new file mode 100644 index 00000000000..7393f2696d4 --- /dev/null +++ b/queue-5.15/class-fix-possible-memory-leak-in-__class_register.patch @@ -0,0 +1,71 @@ +From ff633398f2cc400be16db16ff1795bc95c102f90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 16:28:03 +0800 +Subject: class: fix possible memory leak in __class_register() + +From: Yang Yingliang + +[ Upstream commit 8c3e8a6bdb5253b97ad532570f8b5db5f7a06407 ] + +If class_add_groups() returns error, the 'cp->subsys' need be +unregister, and the 'cp' need be freed. + +We can not call kset_unregister() here, because the 'cls' will +be freed in callback function class_release() and it's also +freed in caller's error path, it will cause double free. + +So fix this by calling kobject_del() and kfree_const(name) to +cleanup kobject. Besides, call kfree() to free the 'cp'. + +Fault injection test can trigger this: + +unreferenced object 0xffff888102fa8190 (size 8): + comm "modprobe", pid 502, jiffies 4294906074 (age 49.296s) + hex dump (first 8 bytes): + 70 6b 74 63 64 76 64 00 pktcdvd. + backtrace: + [<00000000e7c7703d>] __kmalloc_track_caller+0x1ae/0x320 + [<000000005e4d70bc>] kstrdup+0x3a/0x70 + [<00000000c2e5e85a>] kstrdup_const+0x68/0x80 + [<000000000049a8c7>] kvasprintf_const+0x10b/0x190 + [<0000000029123163>] kobject_set_name_vargs+0x56/0x150 + [<00000000747219c9>] kobject_set_name+0xab/0xe0 + [<0000000005f1ea4e>] __class_register+0x15c/0x49a + +unreferenced object 0xffff888037274000 (size 1024): + comm "modprobe", pid 502, jiffies 4294906074 (age 49.296s) + hex dump (first 32 bytes): + 00 40 27 37 80 88 ff ff 00 40 27 37 80 88 ff ff .@'7.....@'7.... + 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... + backtrace: + [<00000000151f9600>] kmem_cache_alloc_trace+0x17c/0x2f0 + [<00000000ecf3dd95>] __class_register+0x86/0x49a + +Fixes: ced6473e7486 ("driver core: class: add class_groups support") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221026082803.3458760-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/base/class.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/base/class.c b/drivers/base/class.c +index 7476f393df97..0e44a68e90a0 100644 +--- a/drivers/base/class.c ++++ b/drivers/base/class.c +@@ -192,6 +192,11 @@ int __class_register(struct class *cls, struct lock_class_key *key) + } + error = class_add_groups(class_get(cls), cls->class_groups); + class_put(cls); ++ if (error) { ++ kobject_del(&cp->subsys.kobj); ++ kfree_const(cp->subsys.kobj.name); ++ kfree(cp); ++ } + return error; + } + EXPORT_SYMBOL_GPL(__class_register); +-- +2.35.1 + diff --git a/queue-5.15/clk-imx-replace-osc_hdmi-with-dummy.patch b/queue-5.15/clk-imx-replace-osc_hdmi-with-dummy.patch new file mode 100644 index 00000000000..a2f6b611b71 --- /dev/null +++ b/queue-5.15/clk-imx-replace-osc_hdmi-with-dummy.patch @@ -0,0 +1,70 @@ +From 6ed1561571c54eed0a0793362c0fbcb56f37747d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 12:36:34 +0100 +Subject: clk: imx: replace osc_hdmi with dummy + +From: Dario Binacchi + +[ Upstream commit e7fa365ff66f16772dc06b480cd78f858d10856b ] + +There is no occurrence of the hdmi oscillator in the reference manual +(document IMX8MNRM Rev 2, 07/2022). Further, if we consider the indexes +76-81 and 134 of the "Clock Root" table of chapter 5 of the RM, there is +no entry for the source select bits 101b, which is the setting referenced +by "osc_hdmi". +Fix by renaming "osc_hdmi" with "dummy", a clock which has already been +used for missing source select bits. + +Tested on the BSH SystemMaster (SMM) S2 board. + +Fixes: 96d6392b54dbb ("clk: imx: Add support for i.MX8MN clock driver") +Signed-off-by: Dario Binacchi +Acked-by: Marco Felsch +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20221117113637.1978703-3-dario.binacchi@amarulasolutions.com +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mn.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index 4f5f368ef25b..dfba853335fd 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -108,27 +108,27 @@ static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out + "sys_pll3_out", "clk_ext4", }; + + static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext3", "clk_ext4", }; + + static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", +- "video_pll1_out", "sys_pll1_133m", "osc_hdmi", ++ "video_pll1_out", "sys_pll1_133m", "dummy", + "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", +-- +2.35.1 + diff --git a/queue-5.15/clk-imx8mn-fix-imx8mn_enet_phy_sels-clocks-list.patch b/queue-5.15/clk-imx8mn-fix-imx8mn_enet_phy_sels-clocks-list.patch new file mode 100644 index 00000000000..020dedd4c95 --- /dev/null +++ b/queue-5.15/clk-imx8mn-fix-imx8mn_enet_phy_sels-clocks-list.patch @@ -0,0 +1,56 @@ +From 855d1815d0ded63e5cf460a82722c135cb86fc6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 12:36:37 +0100 +Subject: clk: imx8mn: fix imx8mn_enet_phy_sels clocks list + +From: Dario Binacchi + +[ Upstream commit 2626cf67f20b28446dfc3a5b9493dd535cdb747b ] + +According to the "Clock Root" table of the reference manual (document +IMX8MNRM Rev 2, 07/2022): + + Clock Root offset Source Select (CCM_TARGET_ROOTn[MUX]) + ... ... ... + ENET_PHY_REF_CLK_ROOT 0xAA80 000 - 24M_REF_CLK + 001 - SYSTEM_PLL2_DIV20 + 010 - SYSTEM_PLL2_DIV8 + 011 - SYSTEM_PLL2_DIV5 + 100 - SYSTEM_PLL2_DIV2 + 101 - AUDIO_PLL1_CLK + 110 - VIDEO_PLL_CLK + 111 - AUDIO_PLL2_CLK + ... ... ... + +while the imx8mn_enet_phy_sels list didn't contained audio_pll1_out for +source select bits 101b. + +Fixes: 96d6392b54dbb ("clk: imx: Add support for i.MX8MN clock driver") +Signed-off-by: Dario Binacchi +Acked-by: Marco Felsch +Reviewed-by: Abel Vesa +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20221117113637.1978703-6-dario.binacchi@amarulasolutions.com +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mn.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index 4016fb124932..52903146fdba 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -140,8 +140,8 @@ static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m" + "clk_ext4", "video_pll1_out", }; + + static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", +- "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out", +- "audio_pll2_out", }; ++ "sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out", ++ "video_pll_out", "audio_pll2_out", }; + + static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", + "sys_pll1_400m", "audio_pll2_out", "sys_pll3_out", +-- +2.35.1 + diff --git a/queue-5.15/clk-imx8mn-fix-imx8mn_sai2_sels-clocks-list.patch b/queue-5.15/clk-imx8mn-fix-imx8mn_sai2_sels-clocks-list.patch new file mode 100644 index 00000000000..22a591bb189 --- /dev/null +++ b/queue-5.15/clk-imx8mn-fix-imx8mn_sai2_sels-clocks-list.patch @@ -0,0 +1,53 @@ +From bd665b452036e9887e1bf57dd01e84997a2494cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 12:36:36 +0100 +Subject: clk: imx8mn: fix imx8mn_sai2_sels clocks list + +From: Dario Binacchi + +[ Upstream commit 34d996747a74e3a86990f9f9c48de09159d78edb ] + +According to the "Clock Root" table of the reference manual (document +IMX8MNRM Rev 2, 07/2022): + + Clock Root offset Source Select (CCM_TARGET_ROOTn[MUX]) + ... ... ... + SAI2_CLK_ROOT 0xA600 000 - 24M_REF_CLK + 001 - AUDIO_PLL1_CLK + 010 - AUDIO_PLL2_CLK + 011 - VIDEO_PLL_CLK + 100 - SYSTEM_PLL1_DIV6 + 110 - EXT_CLK_2 + 111 - EXT_CLK_3 + ... ... ... + +while the imx8mn_sai2_sels list contained clk_ext3 and clk_ext4 for +source select bits 110b and 111b. + +Fixes: 96d6392b54dbb ("clk: imx: Add support for i.MX8MN clock driver") +Signed-off-by: Dario Binacchi +Acked-by: Marco Felsch +Reviewed-by: Abel Vesa +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20221117113637.1978703-5-dario.binacchi@amarulasolutions.com +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mn.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index dfba853335fd..4016fb124932 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -109,7 +109,7 @@ static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out + + static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "dummy", +- "clk_ext3", "clk_ext4", }; ++ "clk_ext2", "clk_ext3", }; + + static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", + "video_pll1_out", "sys_pll1_133m", "dummy", +-- +2.35.1 + diff --git a/queue-5.15/clk-imx8mn-rename-vpu_pll-to-m7_alt_pll.patch b/queue-5.15/clk-imx8mn-rename-vpu_pll-to-m7_alt_pll.patch new file mode 100644 index 00000000000..eda8d263fef --- /dev/null +++ b/queue-5.15/clk-imx8mn-rename-vpu_pll-to-m7_alt_pll.patch @@ -0,0 +1,170 @@ +From 7872c72782cbb887181b567573efe565a45d6b3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 12:36:33 +0100 +Subject: clk: imx8mn: rename vpu_pll to m7_alt_pll + +From: Dario Binacchi + +[ Upstream commit a429c60baefd95ab43a2ce7f25d5b2d7a2e431df ] + +The IMX8MN platform does not have any video processing unit (VPU), and +indeed in the reference manual (document IMX8MNRM Rev 2, 07/2022) there +is no occurrence of its pll. From an analysis of the code and the RM +itself, I think vpu pll is used instead of m7 alternate pll, probably +for copy and paste of code taken from modules of similar architectures. + +As an example for all, if we consider the second row of the "Clock Root" +table of chapter 5 (Clocks and Power Management) of the RM: + + Clock Root offset Source Select (CCM_TARGET_ROOTn[MUX]) + ... ... ... + ARM_M7_CLK_ROOT 0x8080 000 - 24M_REF_CLK + 001 - SYSTEM_PLL2_DIV5 + 010 - SYSTEM_PLL2_DIV4 + 011 - M7_ALT_PLL_CLK + 100 - SYSTEM_PLL1_CLK + 101 - AUDIO_PLL1_CLK + 110 - VIDEO_PLL_CLK + 111 - SYSTEM_PLL3_CLK + ... ... ... + +but in the source code, the imx8mn_m7_sels clocks list contains vpu_pll +for the source select bits 011b. + +So, let's rename "vpu_pll" to "m7_alt_pll" to be consistent with the RM. + +The IMX8MN_VPU_* constants have not been removed to ensure backward +compatibility of the patch. + +No functional changes intended. + +Fixes: 96d6392b54dbb ("clk: imx: Add support for i.MX8MN clock driver") +Signed-off-by: Dario Binacchi +Acked-by: Marco Felsch +Reviewed-by: Abel Vesa +Signed-off-by: Abel Vesa +Link: https://lore.kernel.org/r/20221117113637.1978703-2-dario.binacchi@amarulasolutions.com +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-imx8mn.c | 16 ++++++++-------- + include/dt-bindings/clock/imx8mn-clock.h | 12 ++++++++---- + 2 files changed, 16 insertions(+), 12 deletions(-) + +diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c +index 021355a24708..4f5f368ef25b 100644 +--- a/drivers/clk/imx/clk-imx8mn.c ++++ b/drivers/clk/imx/clk-imx8mn.c +@@ -30,7 +30,7 @@ static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ + static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", }; + static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", }; + static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", }; +-static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", }; ++static const char * const m7_alt_pll_bypass_sels[] = {"m7_alt_pll", "m7_alt_pll_ref_sel", }; + static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", }; + static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", }; + +@@ -40,7 +40,7 @@ static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl + + static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", }; + +-static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "vpu_pll_out", ++static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "m7_alt_pll_out", + "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", }; + + static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", +@@ -228,10 +228,10 @@ static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys + "sys_pll1_80m", "video_pll1_out", }; + + static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", +- "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out", ++ "m7_alt_pll_out", "sys_pll2_125m", "sys_pll3_out", + "sys_pll1_80m", "sys_pll2_166m", }; + +-static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out", ++static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "m7_alt_pll_out", + "sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m", + "sys_pll2_500m", "sys_pll1_100m", }; + +@@ -328,7 +328,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + hws[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); +- hws[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); ++ hws[IMX8MN_M7_ALT_PLL_REF_SEL] = imx_clk_hw_mux("m7_alt_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + +@@ -337,7 +337,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + hws[IMX8MN_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx_1443x_pll); + hws[IMX8MN_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll); + hws[IMX8MN_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll); +- hws[IMX8MN_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll); ++ hws[IMX8MN_M7_ALT_PLL] = imx_clk_hw_pll14xx("m7_alt_pll", "m7_alt_pll_ref_sel", base + 0x74, &imx_1416x_pll); + hws[IMX8MN_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll); + hws[IMX8MN_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000); + hws[IMX8MN_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000); +@@ -349,7 +349,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + hws[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT); +- hws[IMX8MN_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT); ++ hws[IMX8MN_M7_ALT_PLL_BYPASS] = imx_clk_hw_mux_flags("m7_alt_pll_bypass", base + 0x74, 28, 1, m7_alt_pll_bypass_sels, ARRAY_SIZE(m7_alt_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT); + +@@ -359,7 +359,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) + hws[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13); + hws[IMX8MN_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13); + hws[IMX8MN_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11); +- hws[IMX8MN_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11); ++ hws[IMX8MN_M7_ALT_PLL_OUT] = imx_clk_hw_gate("m7_alt_pll_out", "m7_alt_pll_bypass", base + 0x74, 11); + hws[IMX8MN_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11); + hws[IMX8MN_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11); + +diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h +index 01e8bab1d767..1aa462e5cafd 100644 +--- a/include/dt-bindings/clock/imx8mn-clock.h ++++ b/include/dt-bindings/clock/imx8mn-clock.h +@@ -19,7 +19,8 @@ + #define IMX8MN_VIDEO_PLL1_REF_SEL 10 + #define IMX8MN_DRAM_PLL_REF_SEL 11 + #define IMX8MN_GPU_PLL_REF_SEL 12 +-#define IMX8MN_VPU_PLL_REF_SEL 13 ++#define IMX8MN_M7_ALT_PLL_REF_SEL 13 ++#define IMX8MN_VPU_PLL_REF_SEL IMX8MN_M7_ALT_PLL_REF_SEL + #define IMX8MN_ARM_PLL_REF_SEL 14 + #define IMX8MN_SYS_PLL1_REF_SEL 15 + #define IMX8MN_SYS_PLL2_REF_SEL 16 +@@ -29,7 +30,8 @@ + #define IMX8MN_VIDEO_PLL1 20 + #define IMX8MN_DRAM_PLL 21 + #define IMX8MN_GPU_PLL 22 +-#define IMX8MN_VPU_PLL 23 ++#define IMX8MN_M7_ALT_PLL 23 ++#define IMX8MN_VPU_PLL IMX8MN_M7_ALT_PLL + #define IMX8MN_ARM_PLL 24 + #define IMX8MN_SYS_PLL1 25 + #define IMX8MN_SYS_PLL2 26 +@@ -39,7 +41,8 @@ + #define IMX8MN_VIDEO_PLL1_BYPASS 30 + #define IMX8MN_DRAM_PLL_BYPASS 31 + #define IMX8MN_GPU_PLL_BYPASS 32 +-#define IMX8MN_VPU_PLL_BYPASS 33 ++#define IMX8MN_M7_ALT_PLL_BYPASS 33 ++#define IMX8MN_VPU_PLL_BYPASS IMX8MN_M7_ALT_PLL_BYPASS + #define IMX8MN_ARM_PLL_BYPASS 34 + #define IMX8MN_SYS_PLL1_BYPASS 35 + #define IMX8MN_SYS_PLL2_BYPASS 36 +@@ -49,7 +52,8 @@ + #define IMX8MN_VIDEO_PLL1_OUT 40 + #define IMX8MN_DRAM_PLL_OUT 41 + #define IMX8MN_GPU_PLL_OUT 42 +-#define IMX8MN_VPU_PLL_OUT 43 ++#define IMX8MN_M7_ALT_PLL_OUT 43 ++#define IMX8MN_VPU_PLL_OUT IMX8MN_M7_ALT_PLL_OUT + #define IMX8MN_ARM_PLL_OUT 44 + #define IMX8MN_SYS_PLL1_OUT 45 + #define IMX8MN_SYS_PLL2_OUT 46 +-- +2.35.1 + diff --git a/queue-5.15/clk-qcom-clk-krait-fix-wrong-div2-functions.patch b/queue-5.15/clk-qcom-clk-krait-fix-wrong-div2-functions.patch new file mode 100644 index 00000000000..62038e59c85 --- /dev/null +++ b/queue-5.15/clk-qcom-clk-krait-fix-wrong-div2-functions.patch @@ -0,0 +1,40 @@ +From 634d5543c1f0d7d28aa87bf639b7efc07853fa64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 22:56:25 +0100 +Subject: clk: qcom: clk-krait: fix wrong div2 functions + +From: Christian Marangi + +[ Upstream commit d676d3a3717cf726d3affedbe5ba98fc4ccad7b3 ] + +Currently div2 value is applied to the wrong bits. This is caused by a +bug in the code where the shift is done only for lpl, for anything +else the mask is not shifted to the correct bits. + +Fix this by correctly shift if lpl is not supported. + +Fixes: 4d7dc77babfe ("clk: qcom: Add support for Krait clocks") +Signed-off-by: Christian Marangi +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221108215625.30186-1-ansuelsmth@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/clk-krait.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c +index 90046428693c..e74fc81a14d0 100644 +--- a/drivers/clk/qcom/clk-krait.c ++++ b/drivers/clk/qcom/clk-krait.c +@@ -98,6 +98,8 @@ static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate, + + if (d->lpl) + mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift; ++ else ++ mask <<= d->shift; + + spin_lock_irqsave(&krait_clock_reg_lock, flags); + val = krait_get_l2_indirect_reg(d->offset); +-- +2.35.1 + diff --git a/queue-5.15/clk-qcom-gcc-sm8250-use-retention-mode-for-usb-gdscs.patch b/queue-5.15/clk-qcom-gcc-sm8250-use-retention-mode-for-usb-gdscs.patch new file mode 100644 index 00000000000..e8b9b2eb195 --- /dev/null +++ b/queue-5.15/clk-qcom-gcc-sm8250-use-retention-mode-for-usb-gdscs.patch @@ -0,0 +1,48 @@ +From 9f96cf66c2cfece60f94c68b4ed958874625f9d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 14:43:20 +0530 +Subject: clk: qcom: gcc-sm8250: Use retention mode for USB GDSCs + +From: Manivannan Sadhasivam + +[ Upstream commit ac1c5a03d3772b1db25e8092f771aa33f6ae2f7e ] + +USB controllers on SM8250 doesn't work after coming back from suspend. +This can be fixed by keeping the USB GDSCs in retention mode so that +hardware can keep them ON and put into rentention mode once the parent +domain goes to a low power state. + +Fixes: 3e5770921a88 ("clk: qcom: gcc: Add global clock controller driver for SM8250") +Signed-off-by: Manivannan Sadhasivam +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221102091320.66007-1-manivannan.sadhasivam@linaro.org +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-sm8250.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c +index 9755ef4888c1..a0ba37656b07 100644 +--- a/drivers/clk/qcom/gcc-sm8250.c ++++ b/drivers/clk/qcom/gcc-sm8250.c +@@ -3267,7 +3267,7 @@ static struct gdsc usb30_prim_gdsc = { + .pd = { + .name = "usb30_prim_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + }; + + static struct gdsc usb30_sec_gdsc = { +@@ -3275,7 +3275,7 @@ static struct gdsc usb30_sec_gdsc = { + .pd = { + .name = "usb30_sec_gdsc", + }, +- .pwrsts = PWRSTS_OFF_ON, ++ .pwrsts = PWRSTS_RET_ON, + }; + + static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = { +-- +2.35.1 + diff --git a/queue-5.15/clk-qcom-lpass-sc7180-fix-pm_runtime-usage.patch b/queue-5.15/clk-qcom-lpass-sc7180-fix-pm_runtime-usage.patch new file mode 100644 index 00000000000..4b0d8f0c054 --- /dev/null +++ b/queue-5.15/clk-qcom-lpass-sc7180-fix-pm_runtime-usage.patch @@ -0,0 +1,135 @@ +From 1ec4d9a7559f494d6e7cc5986ab15bf9875c1948 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 06:56:29 -0700 +Subject: clk: qcom: lpass-sc7180: Fix pm_runtime usage + +From: Douglas Anderson + +[ Upstream commit ff1ccf59eaffd192efe21f7de9fb0c130faf1b1b ] + +The sc7180 lpass clock controller's pm_runtime usage wasn't broken +quite as spectacularly as the sc7280's pm_runtime usage, but it was +still broken. Putting some printouts in at boot showed me this (with +serial console enabled, which makes the prints slow and thus changes +timing): + [ 3.109951] DOUG: my_pm_clk_resume, usage=1 + [ 3.114767] DOUG: my_pm_clk_resume, usage=1 + [ 3.664443] DOUG: my_pm_clk_suspend, usage=0 + [ 3.897566] DOUG: my_pm_clk_suspend, usage=0 + [ 3.910137] DOUG: my_pm_clk_resume, usage=1 + [ 3.923217] DOUG: my_pm_clk_resume, usage=0 + [ 4.440116] DOUG: my_pm_clk_suspend, usage=-1 + [ 4.444982] DOUG: my_pm_clk_suspend, usage=0 + [ 14.170501] DOUG: my_pm_clk_resume, usage=1 + [ 14.176245] DOUG: my_pm_clk_resume, usage=0 + +...or this w/out serial console: + [ 0.556139] DOUG: my_pm_clk_resume, usage=1 + [ 0.556279] DOUG: my_pm_clk_resume, usage=1 + [ 1.058422] DOUG: my_pm_clk_suspend, usage=-1 + [ 1.058464] DOUG: my_pm_clk_suspend, usage=0 + [ 1.186250] DOUG: my_pm_clk_resume, usage=1 + [ 1.186292] DOUG: my_pm_clk_resume, usage=0 + [ 1.731536] DOUG: my_pm_clk_suspend, usage=-1 + [ 1.731557] DOUG: my_pm_clk_suspend, usage=0 + [ 10.288910] DOUG: my_pm_clk_resume, usage=1 + [ 10.289496] DOUG: my_pm_clk_resume, usage=0 + +It seems to be doing roughly the right sequence of calls, but just +like with sc7280 this is more by luck than anything. Having a usage of +-1 is just not OK. + +Let's fix this like we did with sc7280. + +Signed-off-by: Douglas Anderson +Fixes: ce8c195e652f ("clk: qcom: lpasscc: Introduce pm autosuspend for SC7180") +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221104064055.2.I49b25b9bda9430fc7ea21e5a708ca5a0aced2798@changeid +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/lpasscorecc-sc7180.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c +index ac09b7b840ab..a5731994cbed 100644 +--- a/drivers/clk/qcom/lpasscorecc-sc7180.c ++++ b/drivers/clk/qcom/lpasscorecc-sc7180.c +@@ -356,7 +356,7 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = { + .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs), + }; + +-static int lpass_create_pm_clks(struct platform_device *pdev) ++static int lpass_setup_runtime_pm(struct platform_device *pdev) + { + int ret; + +@@ -375,7 +375,7 @@ static int lpass_create_pm_clks(struct platform_device *pdev) + if (ret < 0) + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + +- return ret; ++ return pm_runtime_resume_and_get(&pdev->dev); + } + + static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) +@@ -384,7 +384,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + struct regmap *regmap; + int ret; + +- ret = lpass_create_pm_clks(pdev); ++ ret = lpass_setup_runtime_pm(pdev); + if (ret) + return ret; + +@@ -392,12 +392,14 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + desc = &lpass_audio_hm_sc7180_desc; + ret = qcom_cc_probe_by_index(pdev, 1, desc); + if (ret) +- return ret; ++ goto exit; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc"; + regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc); +- if (IS_ERR(regmap)) +- return PTR_ERR(regmap); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ goto exit; ++ } + + /* + * Keep the CLK always-ON +@@ -415,6 +417,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) + ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); + + pm_runtime_mark_last_busy(&pdev->dev); ++exit: + pm_runtime_put_autosuspend(&pdev->dev); + + return ret; +@@ -425,14 +428,19 @@ static int lpass_hm_core_probe(struct platform_device *pdev) + const struct qcom_cc_desc *desc; + int ret; + +- ret = lpass_create_pm_clks(pdev); ++ ret = lpass_setup_runtime_pm(pdev); + if (ret) + return ret; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core"; + desc = &lpass_core_hm_sc7180_desc; + +- return qcom_cc_probe_by_index(pdev, 0, desc); ++ ret = qcom_cc_probe_by_index(pdev, 0, desc); ++ ++ pm_runtime_mark_last_busy(&pdev->dev); ++ pm_runtime_put_autosuspend(&pdev->dev); ++ ++ return ret; + } + + static const struct of_device_id lpass_hm_sc7180_match_table[] = { +-- +2.35.1 + diff --git a/queue-5.15/clk-renesas-r9a06g032-repair-grave-increment-error.patch b/queue-5.15/clk-renesas-r9a06g032-repair-grave-increment-error.patch new file mode 100644 index 00000000000..0c8ac91bf70 --- /dev/null +++ b/queue-5.15/clk-renesas-r9a06g032-repair-grave-increment-error.patch @@ -0,0 +1,47 @@ +From 73a5a286428055643541395cbe47d9da2721f148 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 13:38:34 +0200 +Subject: clk: renesas: r9a06g032: Repair grave increment error + +From: Marek Vasut + +[ Upstream commit 02693e11611e082e3c4d8653e8af028e43d31164 ] + +If condition (clkspec.np != pd->dev.of_node) is true, then the driver +ends up in an endless loop, forever, locking up the machine. + +Fixes: aad03a66f902 ("clk: renesas: r9a06g032: Add clock domain support") +Reviewed-by: Ralph Siemsen +Signed-off-by: Marek Vasut +Reviewed-by: Gareth Williams +Link: https://lore.kernel.org/r/20221028113834.7496-1-marex@denx.de +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + drivers/clk/renesas/r9a06g032-clocks.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c +index abc0891fd96d..3e43ae8480dd 100644 +--- a/drivers/clk/renesas/r9a06g032-clocks.c ++++ b/drivers/clk/renesas/r9a06g032-clocks.c +@@ -386,7 +386,7 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd, + int error; + int index; + +- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, ++ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++, + &clkspec)) { + if (clkspec.np != pd->dev.of_node) + continue; +@@ -399,7 +399,6 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd, + if (error) + return error; + } +- i++; + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/clk-rockchip-fix-memory-leak-in-rockchip_clk_registe.patch b/queue-5.15/clk-rockchip-fix-memory-leak-in-rockchip_clk_registe.patch new file mode 100644 index 00000000000..1ba2fb9001e --- /dev/null +++ b/queue-5.15/clk-rockchip-fix-memory-leak-in-rockchip_clk_registe.patch @@ -0,0 +1,37 @@ +From a7c45d16d6507b063c0d32c42a37df547998455d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 17:12:01 +0800 +Subject: clk: rockchip: Fix memory leak in rockchip_clk_register_pll() + +From: Xiu Jianfeng + +[ Upstream commit 739a6a6bbdb793bd57938cb24aa5a6df89983546 ] + +If clk_register() fails, @pll->rate_table may have allocated memory by +kmemdup(), so it needs to be freed, otherwise will cause memory leak +issue, this patch fixes it. + +Fixes: 90c590254051 ("clk: rockchip: add clock type for pll clocks and pll used on rk3066") +Signed-off-by: Xiu Jianfeng +Link: https://lore.kernel.org/r/20221123091201.199819-1-xiujianfeng@huawei.com +Signed-off-by: Heiko Stuebner +Signed-off-by: Sasha Levin +--- + drivers/clk/rockchip/clk-pll.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c +index f7827b3b7fc1..6e5e502be44a 100644 +--- a/drivers/clk/rockchip/clk-pll.c ++++ b/drivers/clk/rockchip/clk-pll.c +@@ -981,6 +981,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx, + return mux_clk; + + err_pll: ++ kfree(pll->rate_table); + clk_unregister(mux_clk); + mux_clk = pll_clk; + err_mux: +-- +2.35.1 + diff --git a/queue-5.15/clk-samsung-fix-memory-leak-in-_samsung_clk_register.patch b/queue-5.15/clk-samsung-fix-memory-leak-in-_samsung_clk_register.patch new file mode 100644 index 00000000000..17e8ff569d7 --- /dev/null +++ b/queue-5.15/clk-samsung-fix-memory-leak-in-_samsung_clk_register.patch @@ -0,0 +1,38 @@ +From 6b315d82301a573905d890d8027ce757414f07d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 11:20:15 +0800 +Subject: clk: samsung: Fix memory leak in _samsung_clk_register_pll() + +From: Xiu Jianfeng + +[ Upstream commit 5174e5b0d1b669a489524192b6adcbb3c54ebc72 ] + +If clk_register() fails, @pll->rate_table may have allocated memory by +kmemdup(), so it needs to be freed, otherwise will cause memory leak +issue, this patch fixes it. + +Fixes: 3ff6e0d8d64d ("clk: samsung: Add support to register rate_table for samsung plls") +Signed-off-by: Xiu Jianfeng +Link: https://lore.kernel.org/r/20221123032015.63980-1-xiujianfeng@huawei.com +Reviewed-by: Alim Akhtar +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/samsung/clk-pll.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c +index 5873a9354b50..4909e940f0ab 100644 +--- a/drivers/clk/samsung/clk-pll.c ++++ b/drivers/clk/samsung/clk-pll.c +@@ -1385,6 +1385,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, + if (ret) { + pr_err("%s: failed to register pll clock %s : %d\n", + __func__, pll_clk->name, ret); ++ kfree(pll->rate_table); + kfree(pll); + return; + } +-- +2.35.1 + diff --git a/queue-5.15/clk-socfpga-fix-memory-leak-in-socfpga_gate_init.patch b/queue-5.15/clk-socfpga-fix-memory-leak-in-socfpga_gate_init.patch new file mode 100644 index 00000000000..eb800f91999 --- /dev/null +++ b/queue-5.15/clk-socfpga-fix-memory-leak-in-socfpga_gate_init.patch @@ -0,0 +1,48 @@ +From a09756def0fce67554a016c11a76f60f9702e2fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 11:16:22 +0800 +Subject: clk: socfpga: Fix memory leak in socfpga_gate_init() + +From: Xiu Jianfeng + +[ Upstream commit 0b8ba891ad4d1ef6bfa4c72efc83f9f9f855f68b ] + +Free @socfpga_clk and @ops on the error path to avoid memory leak issue. + +Fixes: a30a67be7b6e ("clk: socfpga: Don't have get_parent for single parent ops") +Signed-off-by: Xiu Jianfeng +Link: https://lore.kernel.org/r/20221123031622.63171-1-xiujianfeng@huawei.com +Acked-by: Dinh Nguyen +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/socfpga/clk-gate.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c +index 1ec9678d8cd3..ee2a2d284113 100644 +--- a/drivers/clk/socfpga/clk-gate.c ++++ b/drivers/clk/socfpga/clk-gate.c +@@ -188,8 +188,10 @@ void __init socfpga_gate_init(struct device_node *node) + return; + + ops = kmemdup(&gateclk_ops, sizeof(gateclk_ops), GFP_KERNEL); +- if (WARN_ON(!ops)) ++ if (WARN_ON(!ops)) { ++ kfree(socfpga_clk); + return; ++ } + + rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); + if (rc) +@@ -243,6 +245,7 @@ void __init socfpga_gate_init(struct device_node *node) + + err = clk_hw_register(NULL, hw_clk); + if (err) { ++ kfree(ops); + kfree(socfpga_clk); + return; + } +-- +2.35.1 + diff --git a/queue-5.15/clk-st-fix-memory-leak-in-st_of_quadfs_setup.patch b/queue-5.15/clk-st-fix-memory-leak-in-st_of_quadfs_setup.patch new file mode 100644 index 00000000000..b7d0eb388f9 --- /dev/null +++ b/queue-5.15/clk-st-fix-memory-leak-in-st_of_quadfs_setup.patch @@ -0,0 +1,41 @@ +From 6ce3213ea37727ba91da5579611f7b5fa5f8b16b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 21:36:14 +0800 +Subject: clk: st: Fix memory leak in st_of_quadfs_setup() + +From: Xiu Jianfeng + +[ Upstream commit cfd3ffb36f0d566846163118651d868e607300ba ] + +If st_clk_register_quadfs_pll() fails, @lock should be freed before goto +@err_exit, otherwise will cause meory leak issue, fix it. + +Signed-off-by: Xiu Jianfeng +Link: https://lore.kernel.org/r/20221122133614.184910-1-xiujianfeng@huawei.com +Reviewed-by: Patrice Chotard +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/st/clkgen-fsyn.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c +index 164285d6be97..ba18e58f0aae 100644 +--- a/drivers/clk/st/clkgen-fsyn.c ++++ b/drivers/clk/st/clkgen-fsyn.c +@@ -1008,9 +1008,10 @@ static void __init st_of_quadfs_setup(struct device_node *np, + + clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data, + reg, lock); +- if (IS_ERR(clk)) ++ if (IS_ERR(clk)) { ++ kfree(lock); + goto err_exit; +- else ++ } else + pr_debug("%s: parent %s rate %u\n", + __clk_get_name(clk), + __clk_get_name(clk_get_parent(clk)), +-- +2.35.1 + diff --git a/queue-5.15/clocksource-drivers-sh_cmt-access-registers-accordin.patch b/queue-5.15/clocksource-drivers-sh_cmt-access-registers-accordin.patch new file mode 100644 index 00000000000..9dad69932f3 --- /dev/null +++ b/queue-5.15/clocksource-drivers-sh_cmt-access-registers-accordin.patch @@ -0,0 +1,195 @@ +From 44f26e5a4dae991c30b038ecf425fa6222a9ebd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 22:06:09 +0100 +Subject: clocksource/drivers/sh_cmt: Access registers according to spec + +From: Wolfram Sang + +[ Upstream commit 3f44f7156f59cae06e9160eafb5d8b2dfd09e639 ] + +Documentation for most CMTs say that it takes two input clocks before +changes propagate to the timer. This is especially relevant when the timer +is stopped to change further settings. + +Implement the delays according to the spec. To avoid unnecessary delays in +atomic mode, also check if the to-be-written value actually differs. + +CMCNT is a bit special because testing showed that it requires 3 cycles to +propagate, which affects all CMTs. Also, the WRFLAG needs to be checked +before writing. This fixes "cannot clear CMCNT" messages which occur often +on R-Car Gen4 SoCs, but only very rarely on older SoCs for some reason. + +Fixes: 81b3b2711072 ("clocksource: sh_cmt: Add support for multiple channels per device") +Signed-off-by: Wolfram Sang +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20221130210609.7718-1-wsa+renesas@sang-engineering.com +Signed-off-by: Sasha Levin +--- + drivers/clocksource/sh_cmt.c | 88 ++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 33 deletions(-) + +diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c +index dd0956ad969c..d35548aa026f 100644 +--- a/drivers/clocksource/sh_cmt.c ++++ b/drivers/clocksource/sh_cmt.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -116,6 +117,7 @@ struct sh_cmt_device { + void __iomem *mapbase; + struct clk *clk; + unsigned long rate; ++ unsigned int reg_delay; + + raw_spinlock_t lock; /* Protect the shared start/stop register */ + +@@ -247,10 +249,17 @@ static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch) + + static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value) + { +- if (ch->iostart) +- ch->cmt->info->write_control(ch->iostart, 0, value); +- else +- ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); ++ u32 old_value = sh_cmt_read_cmstr(ch); ++ ++ if (value != old_value) { ++ if (ch->iostart) { ++ ch->cmt->info->write_control(ch->iostart, 0, value); ++ udelay(ch->cmt->reg_delay); ++ } else { ++ ch->cmt->info->write_control(ch->cmt->mapbase, 0, value); ++ udelay(ch->cmt->reg_delay); ++ } ++ } + } + + static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) +@@ -260,7 +269,12 @@ static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch) + + static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value) + { +- ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); ++ u32 old_value = sh_cmt_read_cmcsr(ch); ++ ++ if (value != old_value) { ++ ch->cmt->info->write_control(ch->ioctrl, CMCSR, value); ++ udelay(ch->cmt->reg_delay); ++ } + } + + static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) +@@ -268,14 +282,33 @@ static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch) + return ch->cmt->info->read_count(ch->ioctrl, CMCNT); + } + +-static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) ++static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value) + { ++ /* Tests showed that we need to wait 3 clocks here */ ++ unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2); ++ u32 reg; ++ ++ if (ch->cmt->info->model > SH_CMT_16BIT) { ++ int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg, ++ !(reg & SH_CMT32_CMCSR_WRFLG), ++ 1, cmcnt_delay, false, ch); ++ if (ret < 0) ++ return ret; ++ } ++ + ch->cmt->info->write_count(ch->ioctrl, CMCNT, value); ++ udelay(cmcnt_delay); ++ return 0; + } + + static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value) + { +- ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); ++ u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR); ++ ++ if (value != old_value) { ++ ch->cmt->info->write_count(ch->ioctrl, CMCOR, value); ++ udelay(ch->cmt->reg_delay); ++ } + } + + static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped) +@@ -319,7 +352,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start) + + static int sh_cmt_enable(struct sh_cmt_channel *ch) + { +- int k, ret; ++ int ret; + + dev_pm_syscore_device(&ch->cmt->pdev->dev, true); + +@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch) + } + + sh_cmt_write_cmcor(ch, 0xffffffff); +- sh_cmt_write_cmcnt(ch, 0); +- +- /* +- * According to the sh73a0 user's manual, as CMCNT can be operated +- * only by the RCLK (Pseudo 32 kHz), there's one restriction on +- * modifying CMCNT register; two RCLK cycles are necessary before +- * this register is either read or any modification of the value +- * it holds is reflected in the LSI's actual operation. +- * +- * While at it, we're supposed to clear out the CMCNT as of this +- * moment, so make sure it's processed properly here. This will +- * take RCLKx2 at maximum. +- */ +- for (k = 0; k < 100; k++) { +- if (!sh_cmt_read_cmcnt(ch)) +- break; +- udelay(1); +- } ++ ret = sh_cmt_write_cmcnt(ch, 0); + +- if (sh_cmt_read_cmcnt(ch)) { ++ if (ret || sh_cmt_read_cmcnt(ch)) { + dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n", + ch->index); + ret = -ETIMEDOUT; +@@ -987,8 +1003,8 @@ MODULE_DEVICE_TABLE(of, sh_cmt_of_table); + + static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) + { +- unsigned int mask; +- unsigned int i; ++ unsigned int mask, i; ++ unsigned long rate; + int ret; + + cmt->pdev = pdev; +@@ -1024,10 +1040,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev) + if (ret < 0) + goto err_clk_unprepare; + +- if (cmt->info->width == 16) +- cmt->rate = clk_get_rate(cmt->clk) / 512; +- else +- cmt->rate = clk_get_rate(cmt->clk) / 8; ++ rate = clk_get_rate(cmt->clk); ++ if (!rate) { ++ ret = -EINVAL; ++ goto err_clk_disable; ++ } ++ ++ /* We shall wait 2 input clks after register writes */ ++ if (cmt->info->model >= SH_CMT_48BIT) ++ cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate); ++ cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8); + + /* Map the memory resource(s). */ + ret = sh_cmt_map_memory(cmt); +-- +2.35.1 + diff --git a/queue-5.15/clocksource-drivers-timer-ti-dm-fix-missing-clk_disa.patch b/queue-5.15/clocksource-drivers-timer-ti-dm-fix-missing-clk_disa.patch new file mode 100644 index 00000000000..4ee3d86bea3 --- /dev/null +++ b/queue-5.15/clocksource-drivers-timer-ti-dm-fix-missing-clk_disa.patch @@ -0,0 +1,43 @@ +From 8f605a055fac4d3bfc574fb900f5d143ca49daf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Oct 2022 19:44:27 +0800 +Subject: clocksource/drivers/timer-ti-dm: Fix missing clk_disable_unprepare in + dmtimer_systimer_init_clock() + +From: Yang Yingliang + +[ Upstream commit 180d35a7c05d520314a590c99ad8643d0213f28b ] + +If clk_get_rate() fails which is called after clk_prepare_enable(), +clk_disable_unprepare() need be called in error path to disable the +clock in dmtimer_systimer_init_clock(). + +Fixes: 52762fbd1c47 ("clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support") +Signed-off-by: Yang Yingliang +Reviewed-by: Tony Lindgren +Link: https://lore.kernel.org/r/20221029114427.946520-1-yangyingliang@huawei.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/clocksource/timer-ti-dm-systimer.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c +index 2737407ff069..632523c1232f 100644 +--- a/drivers/clocksource/timer-ti-dm-systimer.c ++++ b/drivers/clocksource/timer-ti-dm-systimer.c +@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t, + return error; + + r = clk_get_rate(clock); +- if (!r) ++ if (!r) { ++ clk_disable_unprepare(clock); + return -ENODEV; ++ } + + if (is_ick) + t->ick = clock; +-- +2.35.1 + diff --git a/queue-5.15/configfs-fix-possible-memory-leak-in-configfs_create.patch b/queue-5.15/configfs-fix-possible-memory-leak-in-configfs_create.patch new file mode 100644 index 00000000000..b2e7a259903 --- /dev/null +++ b/queue-5.15/configfs-fix-possible-memory-leak-in-configfs_create.patch @@ -0,0 +1,102 @@ +From 978981d677f24e0527c45e4583a9e4cbdbc012dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 09:42:30 +0800 +Subject: configfs: fix possible memory leak in configfs_create_dir() + +From: Chen Zhongjin + +[ Upstream commit c65234b283a65cfbfc94619655e820a5e55199eb ] + +kmemleak reported memory leaks in configfs_create_dir(): + +unreferenced object 0xffff888009f6af00 (size 192): + comm "modprobe", pid 3777, jiffies 4295537735 (age 233.784s) + backtrace: + kmem_cache_alloc (mm/slub.c:3250 mm/slub.c:3256 mm/slub.c:3263 mm/slub.c:3273) + new_fragment (./include/linux/slab.h:600 fs/configfs/dir.c:163) + configfs_register_subsystem (fs/configfs/dir.c:1857) + basic_write (drivers/hwtracing/stm/p_basic.c:14) stm_p_basic + do_one_initcall (init/main.c:1296) + do_init_module (kernel/module/main.c:2455) + ... + +unreferenced object 0xffff888003ba7180 (size 96): + comm "modprobe", pid 3777, jiffies 4295537735 (age 233.784s) + backtrace: + kmem_cache_alloc (mm/slub.c:3250 mm/slub.c:3256 mm/slub.c:3263 mm/slub.c:3273) + configfs_new_dirent (./include/linux/slab.h:723 fs/configfs/dir.c:194) + configfs_make_dirent (fs/configfs/dir.c:248) + configfs_create_dir (fs/configfs/dir.c:296) + configfs_attach_group.isra.28 (fs/configfs/dir.c:816 fs/configfs/dir.c:852) + configfs_register_subsystem (fs/configfs/dir.c:1881) + basic_write (drivers/hwtracing/stm/p_basic.c:14) stm_p_basic + do_one_initcall (init/main.c:1296) + do_init_module (kernel/module/main.c:2455) + ... + +This is because the refcount is not correct in configfs_make_dirent(). +For normal stage, the refcount is changing as: + +configfs_register_subsystem() + configfs_create_dir() + configfs_make_dirent() + configfs_new_dirent() # set s_count = 1 + dentry->d_fsdata = configfs_get(sd); # s_count = 2 +... +configfs_unregister_subsystem() + configfs_remove_dir() + remove_dir() + configfs_remove_dirent() # s_count = 1 + dput() ... + *dentry_unlink_inode()* + configfs_d_iput() # s_count = 0, release + +However, if we failed in configfs_create(): + +configfs_register_subsystem() + configfs_create_dir() + configfs_make_dirent() # s_count = 2 + ... + configfs_create() # fail + ->out_remove: + configfs_remove_dirent(dentry) + configfs_put(sd) # s_count = 1 + return PTR_ERR(inode); + +There is no inode in the error path, so the configfs_d_iput() is lost +and makes sd and fragment memory leaked. + +To fix this, when we failed in configfs_create(), manually call +configfs_put(sd) to keep the refcount correct. + +Fixes: 7063fbf22611 ("[PATCH] configfs: User-driven configuration filesystem") +Signed-off-by: Chen Zhongjin +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + fs/configfs/dir.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c +index d1f9d2632202..ec6519e1ca3b 100644 +--- a/fs/configfs/dir.c ++++ b/fs/configfs/dir.c +@@ -316,6 +316,7 @@ static int configfs_create_dir(struct config_item *item, struct dentry *dentry, + return 0; + + out_remove: ++ configfs_put(dentry->d_fsdata); + configfs_remove_dirent(dentry); + return PTR_ERR(inode); + } +@@ -382,6 +383,7 @@ int configfs_create_link(struct configfs_dirent *target, struct dentry *parent, + return 0; + + out_remove: ++ configfs_put(dentry->d_fsdata); + configfs_remove_dirent(dentry); + return PTR_ERR(inode); + } +-- +2.35.1 + diff --git a/queue-5.15/coresight-trbe-remove-cpuhp-instance-node-before-rem.patch b/queue-5.15/coresight-trbe-remove-cpuhp-instance-node-before-rem.patch new file mode 100644 index 00000000000..e0dc463ac28 --- /dev/null +++ b/queue-5.15/coresight-trbe-remove-cpuhp-instance-node-before-rem.patch @@ -0,0 +1,61 @@ +From a37b44803bb94302a2b67f3a18efc4d55cc8f61a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 17:03:55 +0800 +Subject: coresight: trbe: remove cpuhp instance node before remove cpuhp state + +From: Yang Shen + +[ Upstream commit 20ee8c223f792947378196307d8e707c9cdc2d61 ] + +cpuhp_state_add_instance() and cpuhp_state_remove_instance() should +be used in pairs. Or there will lead to the warn on +cpuhp_remove_multi_state() since the cpuhp_step list is not empty. + +The following is the error log with 'rmmod coresight-trbe': +Error: Removing state 215 which has instances left. +Call trace: + __cpuhp_remove_state_cpuslocked+0x144/0x160 + __cpuhp_remove_state+0xac/0x100 + arm_trbe_device_remove+0x2c/0x60 [coresight_trbe] + platform_remove+0x34/0x70 + device_remove+0x54/0x90 + device_release_driver_internal+0x1e4/0x250 + driver_detach+0x5c/0xb0 + bus_remove_driver+0x64/0xc0 + driver_unregister+0x3c/0x70 + platform_driver_unregister+0x20/0x30 + arm_trbe_exit+0x1c/0x658 [coresight_trbe] + __arm64_sys_delete_module+0x1ac/0x24c + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0x58/0x1a0 + do_el0_svc+0x38/0xd0 + el0_svc+0x2c/0xc0 + el0t_64_sync_handler+0x1ac/0x1b0 + el0t_64_sync+0x19c/0x1a0 + ---[ end trace 0000000000000000 ]--- + +Fixes: 3fbf7f011f24 ("coresight: sink: Add TRBE driver") +Reviewed-by: Anshuman Khandual +Signed-off-by: Yang Shen +Signed-off-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20221122090355.23533-1-shenyang39@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/hwtracing/coresight/coresight-trbe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c +index 7dddb85b9059..fac63d092c7b 100644 +--- a/drivers/hwtracing/coresight/coresight-trbe.c ++++ b/drivers/hwtracing/coresight/coresight-trbe.c +@@ -1030,6 +1030,7 @@ static int arm_trbe_probe_cpuhp(struct trbe_drvdata *drvdata) + + static void arm_trbe_remove_cpuhp(struct trbe_drvdata *drvdata) + { ++ cpuhp_state_remove_instance(drvdata->trbe_online, &drvdata->hotplug_node); + cpuhp_remove_multi_state(drvdata->trbe_online); + } + +-- +2.35.1 + diff --git a/queue-5.15/counter-stm32-lptimer-cnt-fix-the-check-on-arr-and-c.patch b/queue-5.15/counter-stm32-lptimer-cnt-fix-the-check-on-arr-and-c.patch new file mode 100644 index 00000000000..06edfeefd75 --- /dev/null +++ b/queue-5.15/counter-stm32-lptimer-cnt-fix-the-check-on-arr-and-c.patch @@ -0,0 +1,42 @@ +From 1da1d993b4cf79cfe7f42fba96ffb4b0827bea4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 14:36:09 +0100 +Subject: counter: stm32-lptimer-cnt: fix the check on arr and cmp registers + update + +From: Fabrice Gasnier + +[ Upstream commit fd5ac974fc25feed084c2d1599d0dddb4e0556bc ] + +The ARR (auto reload register) and CMP (compare) registers are +successively written. The status bits to check the update of these +registers are polled together with regmap_read_poll_timeout(). +The condition to end the loop may become true, even if one of the register +isn't correctly updated. +So ensure both status bits are set before clearing them. + +Fixes: d8958824cf07 ("iio: counter: Add support for STM32 LPTimer") +Signed-off-by: Fabrice Gasnier +Link: https://lore.kernel.org/r/20221123133609.465614-1-fabrice.gasnier@foss.st.com/ +Signed-off-by: William Breathitt Gray +Signed-off-by: Sasha Levin +--- + drivers/counter/stm32-lptimer-cnt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c +index 13656957c45f..fa7f86cf0ea3 100644 +--- a/drivers/counter/stm32-lptimer-cnt.c ++++ b/drivers/counter/stm32-lptimer-cnt.c +@@ -69,7 +69,7 @@ static int stm32_lptim_set_enable_state(struct stm32_lptim_cnt *priv, + + /* ensure CMP & ARR registers are properly written */ + ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val, +- (val & STM32_LPTIM_CMPOK_ARROK), ++ (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK, + 100, 1000); + if (ret) + return ret; +-- +2.35.1 + diff --git a/queue-5.15/cpu-hotplug-do-not-bail-out-in-dying-starting-sectio.patch b/queue-5.15/cpu-hotplug-do-not-bail-out-in-dying-starting-sectio.patch new file mode 100644 index 00000000000..fa001d01fe6 --- /dev/null +++ b/queue-5.15/cpu-hotplug-do-not-bail-out-in-dying-starting-sectio.patch @@ -0,0 +1,141 @@ +From 49e28a0bf40f9fb765e9aa97068e4f4775735e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 11:12:59 +0100 +Subject: cpu/hotplug: Do not bail-out in DYING/STARTING sections + +From: Vincent Donnefort + +[ Upstream commit 6f855b39e4602b6b42a8e5cbcfefb8a1b8b5f0be ] + +The DYING/STARTING callbacks are not expected to fail. However, as reported +by Derek, buggy drivers such as tboot are still free to return errors +within those sections, which halts the hot(un)plug and leaves the CPU in an +unrecoverable state. + +As there is no rollback possible, only log the failures and proceed with +the following steps. + +This restores the hotplug behaviour prior to commit 453e41085183 +("cpu/hotplug: Add cpuhp_invoke_callback_range()") + +Fixes: 453e41085183 ("cpu/hotplug: Add cpuhp_invoke_callback_range()") +Reported-by: Derek Dolney +Signed-off-by: Vincent Donnefort +Signed-off-by: Thomas Gleixner +Tested-by: Derek Dolney +Reviewed-by: Valentin Schneider +Link: https://bugzilla.kernel.org/show_bug.cgi?id=215867 +Link: https://lore.kernel.org/r/20220927101259.1149636-1-vdonnefort@google.com +Signed-off-by: Sasha Levin +--- + kernel/cpu.c | 56 +++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 40 insertions(+), 16 deletions(-) + +diff --git a/kernel/cpu.c b/kernel/cpu.c +index e08d207011dd..393114c10c28 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -662,21 +662,51 @@ static bool cpuhp_next_state(bool bringup, + return true; + } + +-static int cpuhp_invoke_callback_range(bool bringup, +- unsigned int cpu, +- struct cpuhp_cpu_state *st, +- enum cpuhp_state target) ++static int __cpuhp_invoke_callback_range(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target, ++ bool nofail) + { + enum cpuhp_state state; +- int err = 0; ++ int ret = 0; + + while (cpuhp_next_state(bringup, &state, st, target)) { ++ int err; ++ + err = cpuhp_invoke_callback(cpu, state, bringup, NULL, NULL); +- if (err) ++ if (!err) ++ continue; ++ ++ if (nofail) { ++ pr_warn("CPU %u %s state %s (%d) failed (%d)\n", ++ cpu, bringup ? "UP" : "DOWN", ++ cpuhp_get_step(st->state)->name, ++ st->state, err); ++ ret = -1; ++ } else { ++ ret = err; + break; ++ } + } + +- return err; ++ return ret; ++} ++ ++static inline int cpuhp_invoke_callback_range(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target) ++{ ++ return __cpuhp_invoke_callback_range(bringup, cpu, st, target, false); ++} ++ ++static inline void cpuhp_invoke_callback_range_nofail(bool bringup, ++ unsigned int cpu, ++ struct cpuhp_cpu_state *st, ++ enum cpuhp_state target) ++{ ++ __cpuhp_invoke_callback_range(bringup, cpu, st, target, true); + } + + static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st) +@@ -994,7 +1024,6 @@ static int take_cpu_down(void *_param) + struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state); + enum cpuhp_state target = max((int)st->target, CPUHP_AP_OFFLINE); + int err, cpu = smp_processor_id(); +- int ret; + + /* Ensure this CPU doesn't handle any more interrupts. */ + err = __cpu_disable(); +@@ -1007,13 +1036,10 @@ static int take_cpu_down(void *_param) + */ + WARN_ON(st->state != (CPUHP_TEARDOWN_CPU - 1)); + +- /* Invoke the former CPU_DYING callbacks */ +- ret = cpuhp_invoke_callback_range(false, cpu, st, target); +- + /* +- * DYING must not fail! ++ * Invoke the former CPU_DYING callbacks. DYING must not fail! + */ +- WARN_ON_ONCE(ret); ++ cpuhp_invoke_callback_range_nofail(false, cpu, st, target); + + /* Give up timekeeping duties */ + tick_handover_do_timer(); +@@ -1285,16 +1311,14 @@ void notify_cpu_starting(unsigned int cpu) + { + struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); + enum cpuhp_state target = min((int)st->target, CPUHP_AP_ONLINE); +- int ret; + + rcu_cpu_starting(cpu); /* Enables RCU usage on this CPU. */ + cpumask_set_cpu(cpu, &cpus_booted_once_mask); +- ret = cpuhp_invoke_callback_range(true, cpu, st, target); + + /* + * STARTING must not fail! + */ +- WARN_ON_ONCE(ret); ++ cpuhp_invoke_callback_range_nofail(true, cpu, st, target); + } + + /* +-- +2.35.1 + diff --git a/queue-5.15/cpu-hotplug-make-target_store-a-nop-when-target-stat.patch b/queue-5.15/cpu-hotplug-make-target_store-a-nop-when-target-stat.patch new file mode 100644 index 00000000000..646f162bc97 --- /dev/null +++ b/queue-5.15/cpu-hotplug-make-target_store-a-nop-when-target-stat.patch @@ -0,0 +1,60 @@ +From 4fa46d903d9907d69fca9942cc034c866cb3beb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 11:23:28 -0500 +Subject: cpu/hotplug: Make target_store() a nop when target == state + +From: Phil Auld + +[ Upstream commit 64ea6e44f85b9b75925ebe1ba0e6e8430cc4e06f ] + +Writing the current state back in hotplug/target calls cpu_down() +which will set cpu dying even when it isn't and then nothing will +ever clear it. A stress test that reads values and writes them back +for all cpu device files in sysfs will trigger the BUG() in +select_fallback_rq once all cpus are marked as dying. + +kernel/cpu.c::target_store() + ... + if (st->state < target) + ret = cpu_up(dev->id, target); + else + ret = cpu_down(dev->id, target); + +cpu_down() -> cpu_set_state() + bool bringup = st->state < target; + ... + if (cpu_dying(cpu) != !bringup) + set_cpu_dying(cpu, !bringup); + +Fix this by letting state==target fall through in the target_store() +conditional. Also make sure st->target == target in that case. + +Fixes: 757c989b9994 ("cpu/hotplug: Make target state writeable") +Signed-off-by: Phil Auld +Signed-off-by: Thomas Gleixner +Reviewed-by: Valentin Schneider +Link: https://lore.kernel.org/r/20221117162329.3164999-2-pauld@redhat.com +Signed-off-by: Sasha Levin +--- + kernel/cpu.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/kernel/cpu.c b/kernel/cpu.c +index da871eb07566..e08d207011dd 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -2315,8 +2315,10 @@ static ssize_t target_store(struct device *dev, struct device_attribute *attr, + + if (st->state < target) + ret = cpu_up(dev->id, target); +- else ++ else if (st->state > target) + ret = cpu_down(dev->id, target); ++ else if (WARN_ON(st->target != target)) ++ st->target = target; + out: + unlock_device_hotplug(); + return ret ? ret : count; +-- +2.35.1 + diff --git a/queue-5.15/cpufreq-amd_freq_sensitivity-add-missing-pci_dev_put.patch b/queue-5.15/cpufreq-amd_freq_sensitivity-add-missing-pci_dev_put.patch new file mode 100644 index 00000000000..2029f86daf3 --- /dev/null +++ b/queue-5.15/cpufreq-amd_freq_sensitivity-add-missing-pci_dev_put.patch @@ -0,0 +1,37 @@ +From 31c3ecde573af21e051141879ea0c06e65bab66e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 19:33:39 +0800 +Subject: cpufreq: amd_freq_sensitivity: Add missing pci_dev_put() + +From: Xiongfeng Wang + +[ Upstream commit 91fda1f88c0968f1491ab150bb01690525af150a ] + +pci_get_device() will increase the reference count for the returned +pci_dev. We need to use pci_dev_put() to decrease the reference count +after using pci_get_device(). Let's add it. + +Fixes: 59a3b3a8db16 ("cpufreq: AMD: Ignore the check for ProcFeedback in ST/CZ") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd_freq_sensitivity.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c +index d0b10baf039a..151771129c7b 100644 +--- a/drivers/cpufreq/amd_freq_sensitivity.c ++++ b/drivers/cpufreq/amd_freq_sensitivity.c +@@ -124,6 +124,8 @@ static int __init amd_freq_sensitivity_init(void) + if (!pcidev) { + if (!boot_cpu_has(X86_FEATURE_PROC_FEEDBACK)) + return -ENODEV; ++ } else { ++ pci_dev_put(pcidev); + } + + if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val)) +-- +2.35.1 + diff --git a/queue-5.15/cpufreq-qcom-hw-fix-memory-leak-in-qcom_cpufreq_hw_r.patch b/queue-5.15/cpufreq-qcom-hw-fix-memory-leak-in-qcom_cpufreq_hw_r.patch new file mode 100644 index 00000000000..dc3792f4c89 --- /dev/null +++ b/queue-5.15/cpufreq-qcom-hw-fix-memory-leak-in-qcom_cpufreq_hw_r.patch @@ -0,0 +1,36 @@ +From 3f4173c7d8122c63c72f353e40e5b7f5790f1eca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 15:23:02 +0800 +Subject: cpufreq: qcom-hw: Fix memory leak in qcom_cpufreq_hw_read_lut() + +From: Chen Hui + +[ Upstream commit 9901c21bcaf2f01fe5078f750d624f4ddfa8f81b ] + +If "cpu_dev" fails to get opp table in qcom_cpufreq_hw_read_lut(), +the program will return, resulting in "table" resource is not released. + +Fixes: 51c843cf77bb ("cpufreq: qcom: Update the bandwidth levels on frequency change") +Signed-off-by: Chen Hui +Reviewed-by: Sibi Sankar +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/qcom-cpufreq-hw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c +index bb2f59fd0de4..bbcba2c38e85 100644 +--- a/drivers/cpufreq/qcom-cpufreq-hw.c ++++ b/drivers/cpufreq/qcom-cpufreq-hw.c +@@ -177,6 +177,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, + } + } else if (ret != -ENODEV) { + dev_err(cpu_dev, "Invalid opp table in device tree\n"); ++ kfree(table); + return ret; + } else { + policy->fast_switch_possible = true; +-- +2.35.1 + diff --git a/queue-5.15/cpuidle-dt-return-the-correct-numbers-of-parsed-idle.patch b/queue-5.15/cpuidle-dt-return-the-correct-numbers-of-parsed-idle.patch new file mode 100644 index 00000000000..22578b7782c --- /dev/null +++ b/queue-5.15/cpuidle-dt-return-the-correct-numbers-of-parsed-idle.patch @@ -0,0 +1,44 @@ +From a344a07f554246c7b4ca7f5f33c2f83a80deae87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 17:10:12 +0200 +Subject: cpuidle: dt: Return the correct numbers of parsed idle states + +From: Ulf Hansson + +[ Upstream commit ee3c2c8ad6ba6785f14a60e4081d7c82e88162a2 ] + +While we correctly skips to initialize an idle state from a disabled idle +state node in DT, the returned value from dt_init_idle_driver() don't get +adjusted accordingly. Instead the number of found idle state nodes are +returned, while the callers are expecting the number of successfully +initialized idle states from DT. + +This leads to cpuidle drivers unnecessarily continues to initialize their +idle state specific data. Moreover, in the case when all idle states have +been disabled in DT, we would end up registering a cpuidle driver, rather +than relying on the default arch specific idle call. + +Fixes: 9f14da345599 ("drivers: cpuidle: implement DT based idle states infrastructure") +Signed-off-by: Ulf Hansson +Reviewed-by: Sudeep Holla +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpuidle/dt_idle_states.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c +index 252f2a9686a6..448bc796b0b4 100644 +--- a/drivers/cpuidle/dt_idle_states.c ++++ b/drivers/cpuidle/dt_idle_states.c +@@ -223,6 +223,6 @@ int dt_init_idle_driver(struct cpuidle_driver *drv, + * also be 0 on platforms with missing DT idle states or legacy DT + * configuration predating the DT idle states bindings. + */ +- return i; ++ return state_idx - start_idx; + } + EXPORT_SYMBOL_GPL(dt_init_idle_driver); +-- +2.35.1 + diff --git a/queue-5.15/crypto-amlogic-remove-kcalloc-without-check.patch b/queue-5.15/crypto-amlogic-remove-kcalloc-without-check.patch new file mode 100644 index 00000000000..6c161fad271 --- /dev/null +++ b/queue-5.15/crypto-amlogic-remove-kcalloc-without-check.patch @@ -0,0 +1,53 @@ +From 2f40863c59b551152126ed7ccd76f4a54f52e4af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 22:56:19 +0100 +Subject: crypto: amlogic - Remove kcalloc without check + +From: Christophe JAILLET + +[ Upstream commit 3d780c8a9850ad60dee47a8d971ba7888f3d1bd3 ] + +There is no real point in allocating dedicated memory for the irqs array. +MAXFLOW is only 2, so it is easier to allocated the needed space +directly within the 'meson_dev' structure. + +This saves some memory allocation and avoids an indirection when using the +irqs array. + +Fixes: 48fe583fe541 ("crypto: amlogic - Add crypto accelerator...") +Signed-off-by: Christophe JAILLET +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/amlogic/amlogic-gxl-core.c | 1 - + drivers/crypto/amlogic/amlogic-gxl.h | 2 +- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c +index 6e7ae896717c..937187027ad5 100644 +--- a/drivers/crypto/amlogic/amlogic-gxl-core.c ++++ b/drivers/crypto/amlogic/amlogic-gxl-core.c +@@ -237,7 +237,6 @@ static int meson_crypto_probe(struct platform_device *pdev) + return err; + } + +- mc->irqs = devm_kcalloc(mc->dev, MAXFLOW, sizeof(int), GFP_KERNEL); + for (i = 0; i < MAXFLOW; i++) { + mc->irqs[i] = platform_get_irq(pdev, i); + if (mc->irqs[i] < 0) +diff --git a/drivers/crypto/amlogic/amlogic-gxl.h b/drivers/crypto/amlogic/amlogic-gxl.h +index dc0f142324a3..8c0746a1d6d4 100644 +--- a/drivers/crypto/amlogic/amlogic-gxl.h ++++ b/drivers/crypto/amlogic/amlogic-gxl.h +@@ -95,7 +95,7 @@ struct meson_dev { + struct device *dev; + struct meson_flow *chanlist; + atomic_t flow; +- int *irqs; ++ int irqs[MAXFLOW]; + #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG + struct dentry *dbgfs_dir; + #endif +-- +2.35.1 + diff --git a/queue-5.15/crypto-ccree-make-cc_debugfs_global_fini-available-f.patch b/queue-5.15/crypto-ccree-make-cc_debugfs_global_fini-available-f.patch new file mode 100644 index 00000000000..b2461ce7c7d --- /dev/null +++ b/queue-5.15/crypto-ccree-make-cc_debugfs_global_fini-available-f.patch @@ -0,0 +1,46 @@ +From 980e50459c9df8d5a7468633cdfd5c7055b44e6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 18:22:36 +0100 +Subject: crypto: ccree - Make cc_debugfs_global_fini() available for module + init function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 8e96729fc26c8967db45a3fb7a60387619f77a22 ] + +ccree_init() calls cc_debugfs_global_fini(), the former is an init +function and the latter an exit function though. + +A modular build emits: + + WARNING: modpost: drivers/crypto/ccree/ccree.o: section mismatch in reference: init_module (section: .init.text) -> cc_debugfs_global_fini (section: .exit.text) + +(with CONFIG_DEBUG_SECTION_MISMATCH=y). + +Fixes: 4f1c596df706 ("crypto: ccree - Remove debugfs when platform_driver_register failed") +Signed-off-by: Uwe Kleine-König +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccree/cc_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/ccree/cc_debugfs.c b/drivers/crypto/ccree/cc_debugfs.c +index 7083767602fc..8f008f024f8f 100644 +--- a/drivers/crypto/ccree/cc_debugfs.c ++++ b/drivers/crypto/ccree/cc_debugfs.c +@@ -55,7 +55,7 @@ void __init cc_debugfs_global_init(void) + cc_debugfs_dir = debugfs_create_dir("ccree", NULL); + } + +-void __exit cc_debugfs_global_fini(void) ++void cc_debugfs_global_fini(void) + { + debugfs_remove(cc_debugfs_dir); + } +-- +2.35.1 + diff --git a/queue-5.15/crypto-ccree-remove-debugfs-when-platform_driver_reg.patch b/queue-5.15/crypto-ccree-remove-debugfs-when-platform_driver_reg.patch new file mode 100644 index 00000000000..7af86108e3d --- /dev/null +++ b/queue-5.15/crypto-ccree-remove-debugfs-when-platform_driver_reg.patch @@ -0,0 +1,49 @@ +From 8b63dbf3a964877080e3a8a9dedf4fe285f2af24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 16:29:12 +0800 +Subject: crypto: ccree - Remove debugfs when platform_driver_register failed + +From: Gaosheng Cui + +[ Upstream commit 4f1c596df706c9aca662b6c214fad84047ae2a97 ] + +When platform_driver_register failed, we need to remove debugfs, +which will caused a resource leak, fix it. + +Failed logs as follows: +[ 32.606488] debugfs: Directory 'ccree' with parent '/' already present! + +Fixes: 4c3f97276e15 ("crypto: ccree - introduce CryptoCell driver") +Signed-off-by: Gaosheng Cui +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccree/cc_driver.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c +index 790fa9058a36..41f0a404bdf9 100644 +--- a/drivers/crypto/ccree/cc_driver.c ++++ b/drivers/crypto/ccree/cc_driver.c +@@ -656,9 +656,17 @@ static struct platform_driver ccree_driver = { + + static int __init ccree_init(void) + { ++ int rc; ++ + cc_debugfs_global_init(); + +- return platform_driver_register(&ccree_driver); ++ rc = platform_driver_register(&ccree_driver); ++ if (rc) { ++ cc_debugfs_global_fini(); ++ return rc; ++ } ++ ++ return 0; + } + module_init(ccree_init); + +-- +2.35.1 + diff --git a/queue-5.15/crypto-cryptd-use-request-context-instead-of-stack-f.patch b/queue-5.15/crypto-cryptd-use-request-context-instead-of-stack-f.patch new file mode 100644 index 00000000000..0deaab108b5 --- /dev/null +++ b/queue-5.15/crypto-cryptd-use-request-context-instead-of-stack-f.patch @@ -0,0 +1,128 @@ +From efc2e01eb391b2face4fa511bc3e95aaf370e006 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 17:59:17 +0800 +Subject: crypto: cryptd - Use request context instead of stack for sub-request + +From: Herbert Xu + +[ Upstream commit 3a58c231172537f7b0e19d93ed33decd04f80eab ] + +cryptd is buggy as it tries to use sync_skcipher without going +through the proper sync_skcipher interface. In fact it doesn't +even need sync_skcipher since it's already a proper skcipher and +can easily access the request context instead of using something +off the stack. + +Fixes: 36b3875a97b8 ("crypto: cryptd - Remove VLA usage of skcipher") +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/cryptd.c | 36 +++++++++++++++++++----------------- + 1 file changed, 19 insertions(+), 17 deletions(-) + +diff --git a/crypto/cryptd.c b/crypto/cryptd.c +index 668095eca0fa..ca3a40fc7da9 100644 +--- a/crypto/cryptd.c ++++ b/crypto/cryptd.c +@@ -68,11 +68,12 @@ struct aead_instance_ctx { + + struct cryptd_skcipher_ctx { + refcount_t refcnt; +- struct crypto_sync_skcipher *child; ++ struct crypto_skcipher *child; + }; + + struct cryptd_skcipher_request_ctx { + crypto_completion_t complete; ++ struct skcipher_request req; + }; + + struct cryptd_hash_ctx { +@@ -227,13 +228,13 @@ static int cryptd_skcipher_setkey(struct crypto_skcipher *parent, + const u8 *key, unsigned int keylen) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent); +- struct crypto_sync_skcipher *child = ctx->child; ++ struct crypto_skcipher *child = ctx->child; + +- crypto_sync_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); +- crypto_sync_skcipher_set_flags(child, +- crypto_skcipher_get_flags(parent) & +- CRYPTO_TFM_REQ_MASK); +- return crypto_sync_skcipher_setkey(child, key, keylen); ++ crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); ++ crypto_skcipher_set_flags(child, ++ crypto_skcipher_get_flags(parent) & ++ CRYPTO_TFM_REQ_MASK); ++ return crypto_skcipher_setkey(child, key, keylen); + } + + static void cryptd_skcipher_complete(struct skcipher_request *req, int err) +@@ -258,13 +259,13 @@ static void cryptd_skcipher_encrypt(struct crypto_async_request *base, + struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct crypto_sync_skcipher *child = ctx->child; +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); ++ struct skcipher_request *subreq = &rctx->req; ++ struct crypto_skcipher *child = ctx->child; + + if (unlikely(err == -EINPROGRESS)) + goto out; + +- skcipher_request_set_sync_tfm(subreq, child); ++ skcipher_request_set_tfm(subreq, child); + skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, +@@ -286,13 +287,13 @@ static void cryptd_skcipher_decrypt(struct crypto_async_request *base, + struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct crypto_sync_skcipher *child = ctx->child; +- SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); ++ struct skcipher_request *subreq = &rctx->req; ++ struct crypto_skcipher *child = ctx->child; + + if (unlikely(err == -EINPROGRESS)) + goto out; + +- skcipher_request_set_sync_tfm(subreq, child); ++ skcipher_request_set_tfm(subreq, child); + skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, +@@ -343,9 +344,10 @@ static int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm) + if (IS_ERR(cipher)) + return PTR_ERR(cipher); + +- ctx->child = (struct crypto_sync_skcipher *)cipher; ++ ctx->child = cipher; + crypto_skcipher_set_reqsize( +- tfm, sizeof(struct cryptd_skcipher_request_ctx)); ++ tfm, sizeof(struct cryptd_skcipher_request_ctx) + ++ crypto_skcipher_reqsize(cipher)); + return 0; + } + +@@ -353,7 +355,7 @@ static void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); + +- crypto_free_sync_skcipher(ctx->child); ++ crypto_free_skcipher(ctx->child); + } + + static void cryptd_skcipher_free(struct skcipher_instance *inst) +@@ -931,7 +933,7 @@ struct crypto_skcipher *cryptd_skcipher_child(struct cryptd_skcipher *tfm) + { + struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base); + +- return &ctx->child->base; ++ return ctx->child; + } + EXPORT_SYMBOL_GPL(cryptd_skcipher_child); + +-- +2.35.1 + diff --git a/queue-5.15/crypto-hisilicon-hpre-fix-resource-leak-in-remove-pr.patch b/queue-5.15/crypto-hisilicon-hpre-fix-resource-leak-in-remove-pr.patch new file mode 100644 index 00000000000..e28bbf831c0 --- /dev/null +++ b/queue-5.15/crypto-hisilicon-hpre-fix-resource-leak-in-remove-pr.patch @@ -0,0 +1,49 @@ +From abba7c274c1ba5f6a52182bacdd66bf96e9dfcd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 15:38:31 +0800 +Subject: crypto: hisilicon/hpre - fix resource leak in remove process + +From: Zhiqi Song + +[ Upstream commit 45e6319bd5f2154d8b8c9f1eaa4ac030ba0d330c ] + +In hpre_remove(), when the disable operation of qm sriov failed, +the following logic should continue to be executed to release the +remaining resources that have been allocated, instead of returning +directly, otherwise there will be resource leakage. + +Signed-off-by: Zhiqi Song +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/hpre/hpre_main.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c +index 65a641396c07..edc61e4105f3 100644 +--- a/drivers/crypto/hisilicon/hpre/hpre_main.c ++++ b/drivers/crypto/hisilicon/hpre/hpre_main.c +@@ -1143,18 +1143,12 @@ static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id) + static void hpre_remove(struct pci_dev *pdev) + { + struct hisi_qm *qm = pci_get_drvdata(pdev); +- int ret; + + hisi_qm_pm_uninit(qm); + hisi_qm_wait_task_finish(qm, &hpre_devices); + hisi_qm_alg_unregister(qm, &hpre_devices); +- if (qm->fun_type == QM_HW_PF && qm->vfs_num) { +- ret = hisi_qm_sriov_disable(pdev, true); +- if (ret) { +- pci_err(pdev, "Disable SRIOV fail!\n"); +- return; +- } +- } ++ if (qm->fun_type == QM_HW_PF && qm->vfs_num) ++ hisi_qm_sriov_disable(pdev, true); + + hpre_debugfs_exit(qm); + hisi_qm_stop(qm, QM_NORMAL); +-- +2.35.1 + diff --git a/queue-5.15/crypto-hisilicon-qm-add-missing-pci_dev_put-in-q_num.patch b/queue-5.15/crypto-hisilicon-qm-add-missing-pci_dev_put-in-q_num.patch new file mode 100644 index 00000000000..2b51e422cb2 --- /dev/null +++ b/queue-5.15/crypto-hisilicon-qm-add-missing-pci_dev_put-in-q_num.patch @@ -0,0 +1,55 @@ +From 4141b4486c5d575c17c61b4e0a2d599939e6394f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 18:00:36 +0800 +Subject: crypto: hisilicon/qm - add missing pci_dev_put() in q_num_set() + +From: Xiongfeng Wang + +[ Upstream commit cc7710d0d4ebc6998f04035cde4f32c5ddbe9d7f ] + +pci_get_device() will increase the reference count for the returned +pci_dev. We need to use pci_dev_put() to decrease the reference count +before q_num_set() returns. + +Fixes: c8b4b477079d ("crypto: hisilicon - add HiSilicon HPRE accelerator") +Signed-off-by: Xiongfeng Wang +Reviewed-by: Weili Qian +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/qm.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h +index 3068093229a5..bbb35de994eb 100644 +--- a/drivers/crypto/hisilicon/qm.h ++++ b/drivers/crypto/hisilicon/qm.h +@@ -318,14 +318,14 @@ struct hisi_qp { + static inline int q_num_set(const char *val, const struct kernel_param *kp, + unsigned int device) + { +- struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, +- device, NULL); ++ struct pci_dev *pdev; + u32 n, q_num; + int ret; + + if (!val) + return -EINVAL; + ++ pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, device, NULL); + if (!pdev) { + q_num = min_t(u32, QM_QNUM_V1, QM_QNUM_V2); + pr_info("No device found currently, suppose queue number is %u\n", +@@ -335,6 +335,8 @@ static inline int q_num_set(const char *val, const struct kernel_param *kp, + q_num = QM_QNUM_V1; + else + q_num = QM_QNUM_V2; ++ ++ pci_dev_put(pdev); + } + + ret = kstrtou32(val, 10, &n); +-- +2.35.1 + diff --git a/queue-5.15/crypto-hisilicon-qm-fix-missing-destroy-qp_idr.patch b/queue-5.15/crypto-hisilicon-qm-fix-missing-destroy-qp_idr.patch new file mode 100644 index 00000000000..0da8dba1e69 --- /dev/null +++ b/queue-5.15/crypto-hisilicon-qm-fix-missing-destroy-qp_idr.patch @@ -0,0 +1,48 @@ +From e53943ac6cf85edccc04b3e078cbd0e6fce5e3ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Aug 2022 18:34:52 +0800 +Subject: crypto: hisilicon/qm - fix missing destroy qp_idr + +From: Weili Qian + +[ Upstream commit 116be08f6e4e385733d42360a33c3d883d2dd702 ] + +In the function hisi_qm_memory_init(), if resource alloc fails after +idr_init, the initialized qp_idr needs to be destroyed. + +Signed-off-by: Weili Qian +Signed-off-by: Yang Shen +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/qm.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index b8900a5dbf6e..fd89918abd19 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -5727,8 +5727,8 @@ static int hisi_qm_memory_init(struct hisi_qm *qm) + GFP_ATOMIC); + dev_dbg(dev, "allocate qm dma buf size=%zx)\n", qm->qdma.size); + if (!qm->qdma.va) { +- ret = -ENOMEM; +- goto err_alloc_qdma; ++ ret = -ENOMEM; ++ goto err_destroy_idr; + } + + QM_INIT_BUF(qm, eqe, QM_EQ_DEPTH); +@@ -5744,7 +5744,8 @@ static int hisi_qm_memory_init(struct hisi_qm *qm) + + err_alloc_qp_array: + dma_free_coherent(dev, qm->qdma.size, qm->qdma.va, qm->qdma.dma); +-err_alloc_qdma: ++err_destroy_idr: ++ idr_destroy(&qm->qp_idr); + kfree(qm->factor); + + return ret; +-- +2.35.1 + diff --git a/queue-5.15/crypto-img-hash-fix-variable-dereferenced-before-che.patch b/queue-5.15/crypto-img-hash-fix-variable-dereferenced-before-che.patch new file mode 100644 index 00000000000..c97aa71741f --- /dev/null +++ b/queue-5.15/crypto-img-hash-fix-variable-dereferenced-before-che.patch @@ -0,0 +1,52 @@ +From 4a7364d5f38a899763f3fffad61147633e1f5423 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 14:25:26 +0800 +Subject: crypto: img-hash - Fix variable dereferenced before check 'hdev->req' + +From: Gaosheng Cui + +[ Upstream commit 04ba54e5af8f8f0137b08cb51a0b3a2e1ea46c94 ] + +Smatch report warning as follows: + +drivers/crypto/img-hash.c:366 img_hash_dma_task() warn: variable +dereferenced before check 'hdev->req' + +Variable dereferenced should be done after check 'hdev->req', +fix it. + +Fixes: d358f1abbf71 ("crypto: img-hash - Add Imagination Technologies hw hash accelerator") +Fixes: 10badea259fa ("crypto: img-hash - Fix null pointer exception") +Signed-off-by: Gaosheng Cui +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/img-hash.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c +index aa4c7b2af3e2..34b41cbcfa8d 100644 +--- a/drivers/crypto/img-hash.c ++++ b/drivers/crypto/img-hash.c +@@ -358,12 +358,16 @@ static int img_hash_dma_init(struct img_hash_dev *hdev) + static void img_hash_dma_task(unsigned long d) + { + struct img_hash_dev *hdev = (struct img_hash_dev *)d; +- struct img_hash_request_ctx *ctx = ahash_request_ctx(hdev->req); ++ struct img_hash_request_ctx *ctx; + u8 *addr; + size_t nbytes, bleft, wsend, len, tbc; + struct scatterlist tsg; + +- if (!hdev->req || !ctx->sg) ++ if (!hdev->req) ++ return; ++ ++ ctx = ahash_request_ctx(hdev->req); ++ if (!ctx->sg) + return; + + addr = sg_virt(ctx->sg); +-- +2.35.1 + diff --git a/queue-5.15/crypto-nitrox-avoid-double-free-on-error-path-in-nit.patch b/queue-5.15/crypto-nitrox-avoid-double-free-on-error-path-in-nit.patch new file mode 100644 index 00000000000..f5ba3f5bb6e --- /dev/null +++ b/queue-5.15/crypto-nitrox-avoid-double-free-on-error-path-in-nit.patch @@ -0,0 +1,43 @@ +From 1b032c515526f284ab249a3876f37015650a52e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 13:25:05 +0300 +Subject: crypto: nitrox - avoid double free on error path in + nitrox_sriov_init() + +From: Natalia Petrova + +[ Upstream commit 094528b6a5a755b1195a01e10b13597d67d1a0e6 ] + +If alloc_workqueue() fails in nitrox_mbox_init() it deallocates +ndev->iov.vfdev and returns error code, but then nitrox_sriov_init() +calls nitrox_sriov_cleanup() where ndev->iov.vfdev is deallocated +again. + +Fix this by nulling ndev->iov.vfdev after the first deallocation. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 9e5de3e06e54 ("crypto: cavium/nitrox - Add mailbox...") +Signed-off-by: Natalia Petrova +Signed-off-by: Alexey Khoroshilov +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/cavium/nitrox/nitrox_mbx.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/crypto/cavium/nitrox/nitrox_mbx.c b/drivers/crypto/cavium/nitrox/nitrox_mbx.c +index 2e9c0d214363..199fcec9b8d0 100644 +--- a/drivers/crypto/cavium/nitrox/nitrox_mbx.c ++++ b/drivers/crypto/cavium/nitrox/nitrox_mbx.c +@@ -191,6 +191,7 @@ int nitrox_mbox_init(struct nitrox_device *ndev) + ndev->iov.pf2vf_wq = alloc_workqueue("nitrox_pf2vf", 0, 0); + if (!ndev->iov.pf2vf_wq) { + kfree(ndev->iov.vfdev); ++ ndev->iov.vfdev = NULL; + return -ENOMEM; + } + /* enable pf2vf mailbox interrupts */ +-- +2.35.1 + diff --git a/queue-5.15/crypto-omap-sham-use-pm_runtime_resume_and_get-in-om.patch b/queue-5.15/crypto-omap-sham-use-pm_runtime_resume_and_get-in-om.patch new file mode 100644 index 00000000000..c8352ce60d8 --- /dev/null +++ b/queue-5.15/crypto-omap-sham-use-pm_runtime_resume_and_get-in-om.patch @@ -0,0 +1,41 @@ +From ffced4815d873931690a41403f70912ad15dabfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 14:49:40 +0800 +Subject: crypto: omap-sham - Use pm_runtime_resume_and_get() in + omap_sham_probe() + +From: Shang XiaoJing + +[ Upstream commit 7bcceb4c9896b1b672b636ae70fe75110d6bf1ad ] + +omap_sham_probe() calls pm_runtime_get_sync() and calls +pm_runtime_put_sync() latter to put usage_counter. However, +pm_runtime_get_sync() will increment usage_counter even it failed. Fix +it by replacing it with pm_runtime_resume_and_get() to keep usage +counter balanced. + +Fixes: b359f034c8bf ("crypto: omap-sham - Convert to use pm_runtime API") +Signed-off-by: Shang XiaoJing +Acked-by: Mark Greer +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/omap-sham.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c +index f6bf53c00b61..4ec6949a7ca9 100644 +--- a/drivers/crypto/omap-sham.c ++++ b/drivers/crypto/omap-sham.c +@@ -2114,7 +2114,7 @@ static int omap_sham_probe(struct platform_device *pdev) + + pm_runtime_enable(dev); + +- err = pm_runtime_get_sync(dev); ++ err = pm_runtime_resume_and_get(dev); + if (err < 0) { + dev_err(dev, "failed to get sync: %d\n", err); + goto err_pm; +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-add-fallback-for-ahash.patch b/queue-5.15/crypto-rockchip-add-fallback-for-ahash.patch new file mode 100644 index 00000000000..56cd8d21850 --- /dev/null +++ b/queue-5.15/crypto-rockchip-add-fallback-for-ahash.patch @@ -0,0 +1,86 @@ +From 6c26d1946e374ace48071bbe5dbfe47ea40df6a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:45 +0000 +Subject: crypto: rockchip - add fallback for ahash + +From: Corentin Labbe + +[ Upstream commit 816600485cb597b3ff7d6806a95a78512839f775 ] + +Adds a fallback for all case hardware cannot handle. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/rockchip/rk3288_crypto_ahash.c | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +index 49017d1fb510..16009bb0bf16 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +@@ -16,6 +16,40 @@ + * so we put the fixed hash out when met zero message. + */ + ++static bool rk_ahash_need_fallback(struct ahash_request *req) ++{ ++ struct scatterlist *sg; ++ ++ sg = req->src; ++ while (sg) { ++ if (!IS_ALIGNED(sg->offset, sizeof(u32))) { ++ return true; ++ } ++ if (sg->length % 4) { ++ return true; ++ } ++ sg = sg_next(sg); ++ } ++ return false; ++} ++ ++static int rk_ahash_digest_fb(struct ahash_request *areq) ++{ ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm); ++ ++ ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); ++ rctx->fallback_req.base.flags = areq->base.flags & ++ CRYPTO_TFM_REQ_MAY_SLEEP; ++ ++ rctx->fallback_req.nbytes = areq->nbytes; ++ rctx->fallback_req.src = areq->src; ++ rctx->fallback_req.result = areq->result; ++ ++ return crypto_ahash_digest(&rctx->fallback_req); ++} ++ + static int zero_message_process(struct ahash_request *req) + { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); +@@ -167,6 +201,9 @@ static int rk_ahash_digest(struct ahash_request *req) + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(req->base.tfm); + struct rk_crypto_info *dev = tctx->dev; + ++ if (rk_ahash_need_fallback(req)) ++ return rk_ahash_digest_fb(req); ++ + if (!req->nbytes) + return zero_message_process(req); + else +@@ -309,6 +346,7 @@ static void rk_cra_hash_exit(struct crypto_tfm *tfm) + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); + + free_page((unsigned long)tctx->dev->addr_vir); ++ crypto_free_ahash(tctx->fallback_tfm); + } + + struct rk_crypto_tmp rk_ahash_sha1 = { +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-add-fallback-for-cipher.patch b/queue-5.15/crypto-rockchip-add-fallback-for-cipher.patch new file mode 100644 index 00000000000..b447de9c15d --- /dev/null +++ b/queue-5.15/crypto-rockchip-add-fallback-for-cipher.patch @@ -0,0 +1,259 @@ +From dc4c04ab1e169e15d5980f9040e3e13dae134cbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:44 +0000 +Subject: crypto: rockchip - add fallback for cipher + +From: Corentin Labbe + +[ Upstream commit 68ef8af09a1a912a5ed2cfaa4cca7606f52cef90 ] + +The hardware does not handle 0 size length request, let's add a +fallback. +Furthermore fallback will be used for all unaligned case the hardware +cannot handle. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/Kconfig | 4 + + drivers/crypto/rockchip/rk3288_crypto.h | 2 + + .../crypto/rockchip/rk3288_crypto_skcipher.c | 97 ++++++++++++++++--- + 3 files changed, 90 insertions(+), 13 deletions(-) + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 51690e73153a..9432375988fe 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -772,6 +772,10 @@ config CRYPTO_DEV_IMGTEC_HASH + config CRYPTO_DEV_ROCKCHIP + tristate "Rockchip's Cryptographic Engine driver" + depends on OF && ARCH_ROCKCHIP ++ depends on PM ++ select CRYPTO_ECB ++ select CRYPTO_CBC ++ select CRYPTO_DES + select CRYPTO_AES + select CRYPTO_LIB_DES + select CRYPTO_MD5 +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index 3e60e3dca1b5..dfff0e2a83e4 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -246,10 +246,12 @@ struct rk_cipher_ctx { + struct rk_crypto_info *dev; + unsigned int keylen; + u8 iv[AES_BLOCK_SIZE]; ++ struct crypto_skcipher *fallback_tfm; + }; + + struct rk_cipher_rctx { + u32 mode; ++ struct skcipher_request fallback_req; // keep at the end + }; + + enum alg_type { +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index bbd0bf52bf07..eac5bba66e25 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -13,6 +13,63 @@ + + #define RK_CRYPTO_DEC BIT(0) + ++static int rk_cipher_need_fallback(struct skcipher_request *req) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ unsigned int bs = crypto_skcipher_blocksize(tfm); ++ struct scatterlist *sgs, *sgd; ++ unsigned int stodo, dtodo, len; ++ ++ if (!req->cryptlen) ++ return true; ++ ++ len = req->cryptlen; ++ sgs = req->src; ++ sgd = req->dst; ++ while (sgs && sgd) { ++ if (!IS_ALIGNED(sgs->offset, sizeof(u32))) { ++ return true; ++ } ++ if (!IS_ALIGNED(sgd->offset, sizeof(u32))) { ++ return true; ++ } ++ stodo = min(len, sgs->length); ++ if (stodo % bs) { ++ return true; ++ } ++ dtodo = min(len, sgd->length); ++ if (dtodo % bs) { ++ return true; ++ } ++ if (stodo != dtodo) { ++ return true; ++ } ++ len -= stodo; ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ } ++ return false; ++} ++ ++static int rk_cipher_fallback(struct skcipher_request *areq) ++{ ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); ++ struct rk_cipher_ctx *op = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ int err; ++ ++ skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); ++ skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, ++ areq->base.complete, areq->base.data); ++ skcipher_request_set_crypt(&rctx->fallback_req, areq->src, areq->dst, ++ areq->cryptlen, areq->iv); ++ if (rctx->mode & RK_CRYPTO_DEC) ++ err = crypto_skcipher_decrypt(&rctx->fallback_req); ++ else ++ err = crypto_skcipher_encrypt(&rctx->fallback_req); ++ return err; ++} ++ + static void rk_crypto_complete(struct crypto_async_request *base, int err) + { + if (base->complete) +@@ -22,10 +79,10 @@ static void rk_crypto_complete(struct crypto_async_request *base, int err) + static int rk_handle_req(struct rk_crypto_info *dev, + struct skcipher_request *req) + { +- if (!IS_ALIGNED(req->cryptlen, dev->align_size)) +- return -EINVAL; +- else +- return dev->enqueue(dev, &req->base); ++ if (rk_cipher_need_fallback(req)) ++ return rk_cipher_fallback(req); ++ ++ return dev->enqueue(dev, &req->base); + } + + static int rk_aes_setkey(struct crypto_skcipher *cipher, +@@ -39,7 +96,8 @@ static int rk_aes_setkey(struct crypto_skcipher *cipher, + return -EINVAL; + ctx->keylen = keylen; + memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, key, keylen); +- return 0; ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_des_setkey(struct crypto_skcipher *cipher, +@@ -54,7 +112,8 @@ static int rk_des_setkey(struct crypto_skcipher *cipher, + + ctx->keylen = keylen; + memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); +- return 0; ++ ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_tdes_setkey(struct crypto_skcipher *cipher, +@@ -69,7 +128,7 @@ static int rk_tdes_setkey(struct crypto_skcipher *cipher, + + ctx->keylen = keylen; + memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); +- return 0; ++ return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + + static int rk_aes_ecb_encrypt(struct skcipher_request *req) +@@ -394,6 +453,7 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + { + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); ++ const char *name = crypto_tfm_alg_name(&tfm->base); + struct rk_crypto_tmp *algt; + + algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); +@@ -407,6 +467,16 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + if (!ctx->dev->addr_vir) + return -ENOMEM; + ++ ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); ++ if (IS_ERR(ctx->fallback_tfm)) { ++ dev_err(ctx->dev->dev, "ERROR: Cannot allocate fallback for %s %ld\n", ++ name, PTR_ERR(ctx->fallback_tfm)); ++ return PTR_ERR(ctx->fallback_tfm); ++ } ++ ++ tfm->reqsize = sizeof(struct rk_cipher_rctx) + ++ crypto_skcipher_reqsize(ctx->fallback_tfm); ++ + return 0; + } + +@@ -415,6 +485,7 @@ static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + + free_page((unsigned long)ctx->dev->addr_vir); ++ crypto_free_skcipher(ctx->fallback_tfm); + } + + struct rk_crypto_tmp rk_ecb_aes_alg = { +@@ -423,7 +494,7 @@ struct rk_crypto_tmp rk_ecb_aes_alg = { + .base.cra_name = "ecb(aes)", + .base.cra_driver_name = "ecb-aes-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x0f, +@@ -445,7 +516,7 @@ struct rk_crypto_tmp rk_cbc_aes_alg = { + .base.cra_name = "cbc(aes)", + .base.cra_driver_name = "cbc-aes-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x0f, +@@ -468,7 +539,7 @@ struct rk_crypto_tmp rk_ecb_des_alg = { + .base.cra_name = "ecb(des)", + .base.cra_driver_name = "ecb-des-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -490,7 +561,7 @@ struct rk_crypto_tmp rk_cbc_des_alg = { + .base.cra_name = "cbc(des)", + .base.cra_driver_name = "cbc-des-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -513,7 +584,7 @@ struct rk_crypto_tmp rk_ecb_des3_ede_alg = { + .base.cra_name = "ecb(des3_ede)", + .base.cra_driver_name = "ecb-des3-ede-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +@@ -535,7 +606,7 @@ struct rk_crypto_tmp rk_cbc_des3_ede_alg = { + .base.cra_name = "cbc(des3_ede)", + .base.cra_driver_name = "cbc-des3-ede-rk", + .base.cra_priority = 300, +- .base.cra_flags = CRYPTO_ALG_ASYNC, ++ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct rk_cipher_ctx), + .base.cra_alignmask = 0x07, +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-better-handle-cipher-key.patch b/queue-5.15/crypto-rockchip-better-handle-cipher-key.patch new file mode 100644 index 00000000000..7f8f89d12f4 --- /dev/null +++ b/queue-5.15/crypto-rockchip-better-handle-cipher-key.patch @@ -0,0 +1,94 @@ +From 438319ffe8f9be0e77417c22c7ae59acf77bce2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:46 +0000 +Subject: crypto: rockchip - better handle cipher key + +From: Corentin Labbe + +[ Upstream commit d6b23ccef82816050c2fd458c9dabfa0e0af09b9 ] + +The key should not be set in hardware too much in advance, this will +fail it 2 TFM with different keys generate alternative requests. +The key should be stored and used just before doing cipher operations. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/rockchip/rk3288_crypto.h | 1 + + drivers/crypto/rockchip/rk3288_crypto_skcipher.c | 10 +++++++--- + 2 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index dfff0e2a83e4..665cc0bb2264 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -245,6 +245,7 @@ struct rk_ahash_rctx { + struct rk_cipher_ctx { + struct rk_crypto_info *dev; + unsigned int keylen; ++ u8 key[AES_MAX_KEY_SIZE]; + u8 iv[AES_BLOCK_SIZE]; + struct crypto_skcipher *fallback_tfm; + }; +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index eac5bba66e25..1ef94f8db2c5 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -95,7 +95,7 @@ static int rk_aes_setkey(struct crypto_skcipher *cipher, + keylen != AES_KEYSIZE_256) + return -EINVAL; + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, key, keylen); ++ memcpy(ctx->key, key, keylen); + + return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } +@@ -111,7 +111,7 @@ static int rk_des_setkey(struct crypto_skcipher *cipher, + return err; + + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); ++ memcpy(ctx->key, key, keylen); + + return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } +@@ -127,7 +127,8 @@ static int rk_tdes_setkey(struct crypto_skcipher *cipher, + return err; + + ctx->keylen = keylen; +- memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, key, keylen); ++ memcpy(ctx->key, key, keylen); ++ + return crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + } + +@@ -283,6 +284,7 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + RK_CRYPTO_TDES_BYTESWAP_IV; + CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode); + memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, req->iv, ivsize); ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen); + conf_reg = RK_CRYPTO_DESSEL; + } else { + rctx->mode |= RK_CRYPTO_AES_FIFO_MODE | +@@ -295,6 +297,7 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + rctx->mode |= RK_CRYPTO_AES_256BIT_key; + CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode); + memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, req->iv, ivsize); ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen); + } + conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO | + RK_CRYPTO_BYTESWAP_BRFIFO; +@@ -484,6 +487,7 @@ static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) + { + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + ++ memzero_explicit(ctx->key, ctx->keylen); + free_page((unsigned long)ctx->dev->addr_vir); + crypto_free_skcipher(ctx->fallback_tfm); + } +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-do-not-do-custom-power-management.patch b/queue-5.15/crypto-rockchip-do-not-do-custom-power-management.patch new file mode 100644 index 00000000000..9c8aebf6e6a --- /dev/null +++ b/queue-5.15/crypto-rockchip-do-not-do-custom-power-management.patch @@ -0,0 +1,111 @@ +From b949583c74dc1004a427fd6293fb084479c17a48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:41 +0000 +Subject: crypto: rockchip - do not do custom power management + +From: Corentin Labbe + +[ Upstream commit c50ef1411c8cbad0c7db100c477126076b6e3348 ] + +The clock enable/disable at tfm init/exit is fragile, +if 2 tfm are init in the same time and one is removed just after, +it will leave the hardware uncloked even if a user remains. + +Instead simply enable clocks at probe time. +We will do PM later. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/rockchip/rk3288_crypto.c | 4 ++-- + drivers/crypto/rockchip/rk3288_crypto.h | 2 -- + drivers/crypto/rockchip/rk3288_crypto_ahash.c | 3 +-- + drivers/crypto/rockchip/rk3288_crypto_skcipher.c | 5 +++-- + 4 files changed, 6 insertions(+), 8 deletions(-) + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c +index 35d73061d156..5f8444b9633a 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.c ++++ b/drivers/crypto/rockchip/rk3288_crypto.c +@@ -395,8 +395,7 @@ static int rk_crypto_probe(struct platform_device *pdev) + rk_crypto_done_task_cb, (unsigned long)crypto_info); + crypto_init_queue(&crypto_info->queue, 50); + +- crypto_info->enable_clk = rk_crypto_enable_clk; +- crypto_info->disable_clk = rk_crypto_disable_clk; ++ rk_crypto_enable_clk(crypto_info); + crypto_info->load_data = rk_load_data; + crypto_info->unload_data = rk_unload_data; + crypto_info->enqueue = rk_crypto_enqueue; +@@ -423,6 +422,7 @@ static int rk_crypto_remove(struct platform_device *pdev) + struct rk_crypto_info *crypto_tmp = platform_get_drvdata(pdev); + + rk_crypto_unregister(); ++ rk_crypto_disable_clk(crypto_tmp); + tasklet_kill(&crypto_tmp->done_task); + tasklet_kill(&crypto_tmp->queue_task); + return 0; +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index 97278c2574ff..2fa7131e4060 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -220,8 +220,6 @@ struct rk_crypto_info { + int (*start)(struct rk_crypto_info *dev); + int (*update)(struct rk_crypto_info *dev); + void (*complete)(struct crypto_async_request *base, int err); +- int (*enable_clk)(struct rk_crypto_info *dev); +- void (*disable_clk)(struct rk_crypto_info *dev); + int (*load_data)(struct rk_crypto_info *dev, + struct scatterlist *sg_src, + struct scatterlist *sg_dst); +diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +index ed03058497bc..49017d1fb510 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +@@ -301,7 +301,7 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + sizeof(struct rk_ahash_rctx) + + crypto_ahash_reqsize(tctx->fallback_tfm)); + +- return tctx->dev->enable_clk(tctx->dev); ++ return 0; + } + + static void rk_cra_hash_exit(struct crypto_tfm *tfm) +@@ -309,7 +309,6 @@ static void rk_cra_hash_exit(struct crypto_tfm *tfm) + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); + + free_page((unsigned long)tctx->dev->addr_vir); +- return tctx->dev->disable_clk(tctx->dev); + } + + struct rk_crypto_tmp rk_ahash_sha1 = { +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index 5bbf0d2722e1..8c44a19eab75 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -388,8 +388,10 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + ctx->dev->update = rk_ablk_rx; + ctx->dev->complete = rk_crypto_complete; + ctx->dev->addr_vir = (char *)__get_free_page(GFP_KERNEL); ++ if (!ctx->dev->addr_vir) ++ return -ENOMEM; + +- return ctx->dev->addr_vir ? ctx->dev->enable_clk(ctx->dev) : -ENOMEM; ++ return 0; + } + + static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) +@@ -397,7 +399,6 @@ static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + + free_page((unsigned long)ctx->dev->addr_vir); +- ctx->dev->disable_clk(ctx->dev); + } + + struct rk_crypto_tmp rk_ecb_aes_alg = { +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-do-not-store-mode-globally.patch b/queue-5.15/crypto-rockchip-do-not-store-mode-globally.patch new file mode 100644 index 00000000000..98b986c6076 --- /dev/null +++ b/queue-5.15/crypto-rockchip-do-not-store-mode-globally.patch @@ -0,0 +1,275 @@ +From 947d4409d09c74a3dcc378c98a9ad93c07c6865a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:43 +0000 +Subject: crypto: rockchip - do not store mode globally + +From: Corentin Labbe + +[ Upstream commit 87e356c4966444866186f68f05832fdcc0f351a3 ] + +Storing the mode globally does not work if 2 requests are handled in the +same time. +We should store it in a request context. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/rockchip/rk3288_crypto.h | 5 +- + .../crypto/rockchip/rk3288_crypto_skcipher.c | 58 ++++++++++++------- + 2 files changed, 41 insertions(+), 22 deletions(-) + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index 2fa7131e4060..3e60e3dca1b5 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -245,10 +245,13 @@ struct rk_ahash_rctx { + struct rk_cipher_ctx { + struct rk_crypto_info *dev; + unsigned int keylen; +- u32 mode; + u8 iv[AES_BLOCK_SIZE]; + }; + ++struct rk_cipher_rctx { ++ u32 mode; ++}; ++ + enum alg_type { + ALG_TYPE_HASH, + ALG_TYPE_CIPHER, +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index 8c44a19eab75..bbd0bf52bf07 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -76,9 +76,10 @@ static int rk_aes_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_ECB_MODE; ++ rctx->mode = RK_CRYPTO_AES_ECB_MODE; + return rk_handle_req(dev, req); + } + +@@ -86,9 +87,10 @@ static int rk_aes_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -96,9 +98,10 @@ static int rk_aes_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_CBC_MODE; ++ rctx->mode = RK_CRYPTO_AES_CBC_MODE; + return rk_handle_req(dev, req); + } + +@@ -106,9 +109,10 @@ static int rk_aes_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -116,9 +120,10 @@ static int rk_des_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = 0; ++ rctx->mode = 0; + return rk_handle_req(dev, req); + } + +@@ -126,9 +131,10 @@ static int rk_des_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -136,9 +142,10 @@ static int rk_des_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC; ++ rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC; + return rk_handle_req(dev, req); + } + +@@ -146,9 +153,10 @@ static int rk_des_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -156,9 +164,10 @@ static int rk_des3_ede_ecb_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT; ++ rctx->mode = RK_CRYPTO_TDES_SELECT; + return rk_handle_req(dev, req); + } + +@@ -166,9 +175,10 @@ static int rk_des3_ede_ecb_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC; ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } + +@@ -176,9 +186,10 @@ static int rk_des3_ede_cbc_encrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC; ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC; + return rk_handle_req(dev, req); + } + +@@ -186,9 +197,10 @@ static int rk_des3_ede_cbc_decrypt(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_crypto_info *dev = ctx->dev; + +- ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC | ++ rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC | + RK_CRYPTO_DEC; + return rk_handle_req(dev, req); + } +@@ -199,6 +211,7 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + skcipher_request_cast(dev->async_req); + struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher); + u32 ivsize, block, conf_reg = 0; + +@@ -206,22 +219,22 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + ivsize = crypto_skcipher_ivsize(cipher); + + if (block == DES_BLOCK_SIZE) { +- ctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | ++ rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | + RK_CRYPTO_TDES_BYTESWAP_KEY | + RK_CRYPTO_TDES_BYTESWAP_IV; +- CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, ctx->mode); ++ CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode); + memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, req->iv, ivsize); + conf_reg = RK_CRYPTO_DESSEL; + } else { +- ctx->mode |= RK_CRYPTO_AES_FIFO_MODE | ++ rctx->mode |= RK_CRYPTO_AES_FIFO_MODE | + RK_CRYPTO_AES_KEY_CHANGE | + RK_CRYPTO_AES_BYTESWAP_KEY | + RK_CRYPTO_AES_BYTESWAP_IV; + if (ctx->keylen == AES_KEYSIZE_192) +- ctx->mode |= RK_CRYPTO_AES_192BIT_key; ++ rctx->mode |= RK_CRYPTO_AES_192BIT_key; + else if (ctx->keylen == AES_KEYSIZE_256) +- ctx->mode |= RK_CRYPTO_AES_256BIT_key; +- CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, ctx->mode); ++ rctx->mode |= RK_CRYPTO_AES_256BIT_key; ++ CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode); + memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, req->iv, ivsize); + } + conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO | +@@ -246,6 +259,7 @@ static int rk_set_data_start(struct rk_crypto_info *dev) + struct skcipher_request *req = + skcipher_request_cast(dev->async_req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + u32 ivsize = crypto_skcipher_ivsize(tfm); + u8 *src_last_blk = page_address(sg_page(dev->sg_src)) + +@@ -254,7 +268,7 @@ static int rk_set_data_start(struct rk_crypto_info *dev) + /* Store the iv that need to be updated in chain mode. + * And update the IV buffer to contain the next IV for decryption mode. + */ +- if (ctx->mode & RK_CRYPTO_DEC) { ++ if (rctx->mode & RK_CRYPTO_DEC) { + memcpy(ctx->iv, src_last_blk, ivsize); + sg_pcopy_to_buffer(dev->first, dev->src_nents, req->iv, + ivsize, dev->total - ivsize); +@@ -294,11 +308,12 @@ static void rk_iv_copyback(struct rk_crypto_info *dev) + struct skcipher_request *req = + skcipher_request_cast(dev->async_req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + u32 ivsize = crypto_skcipher_ivsize(tfm); + + /* Update the IV buffer to contain the next IV for encryption mode. */ +- if (!(ctx->mode & RK_CRYPTO_DEC)) { ++ if (!(rctx->mode & RK_CRYPTO_DEC)) { + if (dev->aligned) { + memcpy(req->iv, sg_virt(dev->sg_dst) + + dev->sg_dst->length - ivsize, ivsize); +@@ -314,11 +329,12 @@ static void rk_update_iv(struct rk_crypto_info *dev) + struct skcipher_request *req = + skcipher_request_cast(dev->async_req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + u32 ivsize = crypto_skcipher_ivsize(tfm); + u8 *new_iv = NULL; + +- if (ctx->mode & RK_CRYPTO_DEC) { ++ if (rctx->mode & RK_CRYPTO_DEC) { + new_iv = ctx->iv; + } else { + new_iv = page_address(sg_page(dev->sg_dst)) + +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-remove-non-aligned-handling.patch b/queue-5.15/crypto-rockchip-remove-non-aligned-handling.patch new file mode 100644 index 00000000000..687f94b3512 --- /dev/null +++ b/queue-5.15/crypto-rockchip-remove-non-aligned-handling.patch @@ -0,0 +1,280 @@ +From effb7b39f18be22d04633caf400705074ece15ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:47 +0000 +Subject: crypto: rockchip - remove non-aligned handling + +From: Corentin Labbe + +[ Upstream commit bb3c7b73363c9a149b12b74c44ae94b73a8fddf8 ] + +Now driver have fallback for un-aligned cases, remove all code handling +those cases. + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/rockchip/rk3288_crypto.c | 69 +++++-------------- + drivers/crypto/rockchip/rk3288_crypto.h | 4 -- + drivers/crypto/rockchip/rk3288_crypto_ahash.c | 22 ++---- + .../crypto/rockchip/rk3288_crypto_skcipher.c | 39 +++-------- + 4 files changed, 31 insertions(+), 103 deletions(-) + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c +index 5f8444b9633a..31453257ab11 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.c ++++ b/drivers/crypto/rockchip/rk3288_crypto.c +@@ -88,63 +88,26 @@ static int rk_load_data(struct rk_crypto_info *dev, + { + unsigned int count; + +- dev->aligned = dev->aligned ? +- check_alignment(sg_src, sg_dst, dev->align_size) : +- dev->aligned; +- if (dev->aligned) { +- count = min(dev->left_bytes, sg_src->length); +- dev->left_bytes -= count; +- +- if (!dma_map_sg(dev->dev, sg_src, 1, DMA_TO_DEVICE)) { +- dev_err(dev->dev, "[%s:%d] dma_map_sg(src) error\n", ++ count = min(dev->left_bytes, sg_src->length); ++ dev->left_bytes -= count; ++ ++ if (!dma_map_sg(dev->dev, sg_src, 1, DMA_TO_DEVICE)) { ++ dev_err(dev->dev, "[%s:%d] dma_map_sg(src) error\n", + __func__, __LINE__); +- return -EINVAL; +- } +- dev->addr_in = sg_dma_address(sg_src); ++ return -EINVAL; ++ } ++ dev->addr_in = sg_dma_address(sg_src); + +- if (sg_dst) { +- if (!dma_map_sg(dev->dev, sg_dst, 1, DMA_FROM_DEVICE)) { +- dev_err(dev->dev, ++ if (sg_dst) { ++ if (!dma_map_sg(dev->dev, sg_dst, 1, DMA_FROM_DEVICE)) { ++ dev_err(dev->dev, + "[%s:%d] dma_map_sg(dst) error\n", + __func__, __LINE__); +- dma_unmap_sg(dev->dev, sg_src, 1, +- DMA_TO_DEVICE); +- return -EINVAL; +- } +- dev->addr_out = sg_dma_address(sg_dst); +- } +- } else { +- count = (dev->left_bytes > PAGE_SIZE) ? +- PAGE_SIZE : dev->left_bytes; +- +- if (!sg_pcopy_to_buffer(dev->first, dev->src_nents, +- dev->addr_vir, count, +- dev->total - dev->left_bytes)) { +- dev_err(dev->dev, "[%s:%d] pcopy err\n", +- __func__, __LINE__); ++ dma_unmap_sg(dev->dev, sg_src, 1, ++ DMA_TO_DEVICE); + return -EINVAL; + } +- dev->left_bytes -= count; +- sg_init_one(&dev->sg_tmp, dev->addr_vir, count); +- if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1, DMA_TO_DEVICE)) { +- dev_err(dev->dev, "[%s:%d] dma_map_sg(sg_tmp) error\n", +- __func__, __LINE__); +- return -ENOMEM; +- } +- dev->addr_in = sg_dma_address(&dev->sg_tmp); +- +- if (sg_dst) { +- if (!dma_map_sg(dev->dev, &dev->sg_tmp, 1, +- DMA_FROM_DEVICE)) { +- dev_err(dev->dev, +- "[%s:%d] dma_map_sg(sg_tmp) error\n", +- __func__, __LINE__); +- dma_unmap_sg(dev->dev, &dev->sg_tmp, 1, +- DMA_TO_DEVICE); +- return -ENOMEM; +- } +- dev->addr_out = sg_dma_address(&dev->sg_tmp); +- } ++ dev->addr_out = sg_dma_address(sg_dst); + } + dev->count = count; + return 0; +@@ -154,11 +117,11 @@ static void rk_unload_data(struct rk_crypto_info *dev) + { + struct scatterlist *sg_in, *sg_out; + +- sg_in = dev->aligned ? dev->sg_src : &dev->sg_tmp; ++ sg_in = dev->sg_src; + dma_unmap_sg(dev->dev, sg_in, 1, DMA_TO_DEVICE); + + if (dev->sg_dst) { +- sg_out = dev->aligned ? dev->sg_dst : &dev->sg_tmp; ++ sg_out = dev->sg_dst; + dma_unmap_sg(dev->dev, sg_out, 1, DMA_FROM_DEVICE); + } + } +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index 665cc0bb2264..df4db59fa13e 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -204,12 +204,8 @@ struct rk_crypto_info { + /* the public variable */ + struct scatterlist *sg_src; + struct scatterlist *sg_dst; +- struct scatterlist sg_tmp; + struct scatterlist *first; + unsigned int left_bytes; +- void *addr_vir; +- int aligned; +- int align_size; + size_t src_nents; + size_t dst_nents; + unsigned int total; +diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +index 16009bb0bf16..c762e462eb57 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +@@ -236,8 +236,6 @@ static int rk_ahash_start(struct rk_crypto_info *dev) + + dev->total = req->nbytes; + dev->left_bytes = req->nbytes; +- dev->aligned = 0; +- dev->align_size = 4; + dev->sg_dst = NULL; + dev->sg_src = req->src; + dev->first = req->src; +@@ -272,15 +270,13 @@ static int rk_ahash_crypto_rx(struct rk_crypto_info *dev) + + dev->unload_data(dev); + if (dev->left_bytes) { +- if (dev->aligned) { +- if (sg_is_last(dev->sg_src)) { +- dev_warn(dev->dev, "[%s:%d], Lack of data\n", +- __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; +- } +- dev->sg_src = sg_next(dev->sg_src); ++ if (sg_is_last(dev->sg_src)) { ++ dev_warn(dev->dev, "[%s:%d], Lack of data\n", ++ __func__, __LINE__); ++ err = -ENOMEM; ++ goto out_rx; + } ++ dev->sg_src = sg_next(dev->sg_src); + err = rk_ahash_set_data_start(dev); + } else { + /* +@@ -318,11 +314,6 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + + tctx->dev = algt->dev; +- tctx->dev->addr_vir = (void *)__get_free_page(GFP_KERNEL); +- if (!tctx->dev->addr_vir) { +- dev_err(tctx->dev->dev, "failed to kmalloc for addr_vir\n"); +- return -ENOMEM; +- } + tctx->dev->start = rk_ahash_start; + tctx->dev->update = rk_ahash_crypto_rx; + tctx->dev->complete = rk_ahash_crypto_complete; +@@ -345,7 +336,6 @@ static void rk_cra_hash_exit(struct crypto_tfm *tfm) + { + struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); + +- free_page((unsigned long)tctx->dev->addr_vir); + crypto_free_ahash(tctx->fallback_tfm); + } + +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index 1ef94f8db2c5..d067b7f09165 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -356,7 +356,6 @@ static int rk_ablk_start(struct rk_crypto_info *dev) + dev->src_nents = sg_nents(req->src); + dev->sg_dst = req->dst; + dev->dst_nents = sg_nents(req->dst); +- dev->aligned = 1; + + spin_lock_irqsave(&dev->lock, flags); + rk_ablk_hw_init(dev); +@@ -376,13 +375,9 @@ static void rk_iv_copyback(struct rk_crypto_info *dev) + + /* Update the IV buffer to contain the next IV for encryption mode. */ + if (!(rctx->mode & RK_CRYPTO_DEC)) { +- if (dev->aligned) { +- memcpy(req->iv, sg_virt(dev->sg_dst) + +- dev->sg_dst->length - ivsize, ivsize); +- } else { +- memcpy(req->iv, dev->addr_vir + +- dev->count - ivsize, ivsize); +- } ++ memcpy(req->iv, ++ sg_virt(dev->sg_dst) + dev->sg_dst->length - ivsize, ++ ivsize); + } + } + +@@ -420,27 +415,16 @@ static int rk_ablk_rx(struct rk_crypto_info *dev) + skcipher_request_cast(dev->async_req); + + dev->unload_data(dev); +- if (!dev->aligned) { +- if (!sg_pcopy_from_buffer(req->dst, dev->dst_nents, +- dev->addr_vir, dev->count, +- dev->total - dev->left_bytes - +- dev->count)) { +- err = -EINVAL; +- goto out_rx; +- } +- } + if (dev->left_bytes) { + rk_update_iv(dev); +- if (dev->aligned) { +- if (sg_is_last(dev->sg_src)) { +- dev_err(dev->dev, "[%s:%d] Lack of data\n", ++ if (sg_is_last(dev->sg_src)) { ++ dev_err(dev->dev, "[%s:%d] Lack of data\n", + __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; +- } +- dev->sg_src = sg_next(dev->sg_src); +- dev->sg_dst = sg_next(dev->sg_dst); ++ err = -ENOMEM; ++ goto out_rx; + } ++ dev->sg_src = sg_next(dev->sg_src); ++ dev->sg_dst = sg_next(dev->sg_dst); + err = rk_set_data_start(dev); + } else { + rk_iv_copyback(dev); +@@ -462,13 +446,9 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + + ctx->dev = algt->dev; +- ctx->dev->align_size = crypto_tfm_alg_alignmask(crypto_skcipher_tfm(tfm)) + 1; + ctx->dev->start = rk_ablk_start; + ctx->dev->update = rk_ablk_rx; + ctx->dev->complete = rk_crypto_complete; +- ctx->dev->addr_vir = (char *)__get_free_page(GFP_KERNEL); +- if (!ctx->dev->addr_vir) +- return -ENOMEM; + + ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(ctx->fallback_tfm)) { +@@ -488,7 +468,6 @@ static void rk_ablk_exit_tfm(struct crypto_skcipher *tfm) + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); + + memzero_explicit(ctx->key, ctx->keylen); +- free_page((unsigned long)ctx->dev->addr_vir); + crypto_free_skcipher(ctx->fallback_tfm); + } + +-- +2.35.1 + diff --git a/queue-5.15/crypto-rockchip-rework-by-using-crypto_engine.patch b/queue-5.15/crypto-rockchip-rework-by-using-crypto_engine.patch new file mode 100644 index 00000000000..66212650481 --- /dev/null +++ b/queue-5.15/crypto-rockchip-rework-by-using-crypto_engine.patch @@ -0,0 +1,902 @@ +From fea6eaf235b7b719e5708fd95cd9baa501c2df08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 07:54:48 +0000 +Subject: crypto: rockchip - rework by using crypto_engine + +From: Corentin Labbe + +[ Upstream commit 57d67c6e8219b2a034c16d6149e30fb40fd39935 ] + +Instead of doing manual queue management, let's use the crypto/engine +for that. +In the same time, rework the requests handling to be easier to +understand (and fix all bugs related to them). + +Fixes: ce0183cb6464b ("crypto: rockchip - switch to skcipher API") +Reviewed-by: John Keeping +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/Kconfig | 1 + + drivers/crypto/rockchip/rk3288_crypto.c | 152 +---------- + drivers/crypto/rockchip/rk3288_crypto.h | 39 +-- + drivers/crypto/rockchip/rk3288_crypto_ahash.c | 144 +++++----- + .../crypto/rockchip/rk3288_crypto_skcipher.c | 250 +++++++++--------- + 5 files changed, 221 insertions(+), 365 deletions(-) + +diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig +index 9432375988fe..b46343b5c26b 100644 +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -777,6 +777,7 @@ config CRYPTO_DEV_ROCKCHIP + select CRYPTO_CBC + select CRYPTO_DES + select CRYPTO_AES ++ select CRYPTO_ENGINE + select CRYPTO_LIB_DES + select CRYPTO_MD5 + select CRYPTO_SHA1 +diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c +index 31453257ab11..14a0aef18ab1 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.c ++++ b/drivers/crypto/rockchip/rk3288_crypto.c +@@ -65,149 +65,24 @@ static void rk_crypto_disable_clk(struct rk_crypto_info *dev) + clk_disable_unprepare(dev->sclk); + } + +-static int check_alignment(struct scatterlist *sg_src, +- struct scatterlist *sg_dst, +- int align_mask) +-{ +- int in, out, align; +- +- in = IS_ALIGNED((uint32_t)sg_src->offset, 4) && +- IS_ALIGNED((uint32_t)sg_src->length, align_mask); +- if (!sg_dst) +- return in; +- out = IS_ALIGNED((uint32_t)sg_dst->offset, 4) && +- IS_ALIGNED((uint32_t)sg_dst->length, align_mask); +- align = in && out; +- +- return (align && (sg_src->length == sg_dst->length)); +-} +- +-static int rk_load_data(struct rk_crypto_info *dev, +- struct scatterlist *sg_src, +- struct scatterlist *sg_dst) +-{ +- unsigned int count; +- +- count = min(dev->left_bytes, sg_src->length); +- dev->left_bytes -= count; +- +- if (!dma_map_sg(dev->dev, sg_src, 1, DMA_TO_DEVICE)) { +- dev_err(dev->dev, "[%s:%d] dma_map_sg(src) error\n", +- __func__, __LINE__); +- return -EINVAL; +- } +- dev->addr_in = sg_dma_address(sg_src); +- +- if (sg_dst) { +- if (!dma_map_sg(dev->dev, sg_dst, 1, DMA_FROM_DEVICE)) { +- dev_err(dev->dev, +- "[%s:%d] dma_map_sg(dst) error\n", +- __func__, __LINE__); +- dma_unmap_sg(dev->dev, sg_src, 1, +- DMA_TO_DEVICE); +- return -EINVAL; +- } +- dev->addr_out = sg_dma_address(sg_dst); +- } +- dev->count = count; +- return 0; +-} +- +-static void rk_unload_data(struct rk_crypto_info *dev) +-{ +- struct scatterlist *sg_in, *sg_out; +- +- sg_in = dev->sg_src; +- dma_unmap_sg(dev->dev, sg_in, 1, DMA_TO_DEVICE); +- +- if (dev->sg_dst) { +- sg_out = dev->sg_dst; +- dma_unmap_sg(dev->dev, sg_out, 1, DMA_FROM_DEVICE); +- } +-} +- + static irqreturn_t rk_crypto_irq_handle(int irq, void *dev_id) + { + struct rk_crypto_info *dev = platform_get_drvdata(dev_id); + u32 interrupt_status; + +- spin_lock(&dev->lock); + interrupt_status = CRYPTO_READ(dev, RK_CRYPTO_INTSTS); + CRYPTO_WRITE(dev, RK_CRYPTO_INTSTS, interrupt_status); + ++ dev->status = 1; + if (interrupt_status & 0x0a) { + dev_warn(dev->dev, "DMA Error\n"); +- dev->err = -EFAULT; ++ dev->status = 0; + } +- tasklet_schedule(&dev->done_task); ++ complete(&dev->complete); + +- spin_unlock(&dev->lock); + return IRQ_HANDLED; + } + +-static int rk_crypto_enqueue(struct rk_crypto_info *dev, +- struct crypto_async_request *async_req) +-{ +- unsigned long flags; +- int ret; +- +- spin_lock_irqsave(&dev->lock, flags); +- ret = crypto_enqueue_request(&dev->queue, async_req); +- if (dev->busy) { +- spin_unlock_irqrestore(&dev->lock, flags); +- return ret; +- } +- dev->busy = true; +- spin_unlock_irqrestore(&dev->lock, flags); +- tasklet_schedule(&dev->queue_task); +- +- return ret; +-} +- +-static void rk_crypto_queue_task_cb(unsigned long data) +-{ +- struct rk_crypto_info *dev = (struct rk_crypto_info *)data; +- struct crypto_async_request *async_req, *backlog; +- unsigned long flags; +- int err = 0; +- +- dev->err = 0; +- spin_lock_irqsave(&dev->lock, flags); +- backlog = crypto_get_backlog(&dev->queue); +- async_req = crypto_dequeue_request(&dev->queue); +- +- if (!async_req) { +- dev->busy = false; +- spin_unlock_irqrestore(&dev->lock, flags); +- return; +- } +- spin_unlock_irqrestore(&dev->lock, flags); +- +- if (backlog) { +- backlog->complete(backlog, -EINPROGRESS); +- backlog = NULL; +- } +- +- dev->async_req = async_req; +- err = dev->start(dev); +- if (err) +- dev->complete(dev->async_req, err); +-} +- +-static void rk_crypto_done_task_cb(unsigned long data) +-{ +- struct rk_crypto_info *dev = (struct rk_crypto_info *)data; +- +- if (dev->err) { +- dev->complete(dev->async_req, dev->err); +- return; +- } +- +- dev->err = dev->update(dev); +- if (dev->err) +- dev->complete(dev->async_req, dev->err); +-} +- + static struct rk_crypto_tmp *rk_cipher_algs[] = { + &rk_ecb_aes_alg, + &rk_cbc_aes_alg, +@@ -300,8 +175,6 @@ static int rk_crypto_probe(struct platform_device *pdev) + if (err) + goto err_crypto; + +- spin_lock_init(&crypto_info->lock); +- + crypto_info->reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(crypto_info->reg)) { + err = PTR_ERR(crypto_info->reg); +@@ -352,17 +225,11 @@ static int rk_crypto_probe(struct platform_device *pdev) + crypto_info->dev = &pdev->dev; + platform_set_drvdata(pdev, crypto_info); + +- tasklet_init(&crypto_info->queue_task, +- rk_crypto_queue_task_cb, (unsigned long)crypto_info); +- tasklet_init(&crypto_info->done_task, +- rk_crypto_done_task_cb, (unsigned long)crypto_info); +- crypto_init_queue(&crypto_info->queue, 50); ++ crypto_info->engine = crypto_engine_alloc_init(&pdev->dev, true); ++ crypto_engine_start(crypto_info->engine); ++ init_completion(&crypto_info->complete); + + rk_crypto_enable_clk(crypto_info); +- crypto_info->load_data = rk_load_data; +- crypto_info->unload_data = rk_unload_data; +- crypto_info->enqueue = rk_crypto_enqueue; +- crypto_info->busy = false; + + err = rk_crypto_register(crypto_info); + if (err) { +@@ -374,9 +241,9 @@ static int rk_crypto_probe(struct platform_device *pdev) + return 0; + + err_register_alg: +- tasklet_kill(&crypto_info->queue_task); +- tasklet_kill(&crypto_info->done_task); ++ crypto_engine_exit(crypto_info->engine); + err_crypto: ++ dev_err(dev, "Crypto Accelerator not successfully registered\n"); + return err; + } + +@@ -386,8 +253,7 @@ static int rk_crypto_remove(struct platform_device *pdev) + + rk_crypto_unregister(); + rk_crypto_disable_clk(crypto_tmp); +- tasklet_kill(&crypto_tmp->done_task); +- tasklet_kill(&crypto_tmp->queue_task); ++ crypto_engine_exit(crypto_tmp->engine); + return 0; + } + +diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h +index df4db59fa13e..045e811b4af8 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto.h ++++ b/drivers/crypto/rockchip/rk3288_crypto.h +@@ -5,9 +5,11 @@ + #include + #include + #include ++#include + #include + #include + #include ++#include + #include + #include + +@@ -193,39 +195,15 @@ struct rk_crypto_info { + struct reset_control *rst; + void __iomem *reg; + int irq; +- struct crypto_queue queue; +- struct tasklet_struct queue_task; +- struct tasklet_struct done_task; +- struct crypto_async_request *async_req; +- int err; +- /* device lock */ +- spinlock_t lock; +- +- /* the public variable */ +- struct scatterlist *sg_src; +- struct scatterlist *sg_dst; +- struct scatterlist *first; +- unsigned int left_bytes; +- size_t src_nents; +- size_t dst_nents; +- unsigned int total; +- unsigned int count; +- dma_addr_t addr_in; +- dma_addr_t addr_out; +- bool busy; +- int (*start)(struct rk_crypto_info *dev); +- int (*update)(struct rk_crypto_info *dev); +- void (*complete)(struct crypto_async_request *base, int err); +- int (*load_data)(struct rk_crypto_info *dev, +- struct scatterlist *sg_src, +- struct scatterlist *sg_dst); +- void (*unload_data)(struct rk_crypto_info *dev); +- int (*enqueue)(struct rk_crypto_info *dev, +- struct crypto_async_request *async_req); ++ ++ struct crypto_engine *engine; ++ struct completion complete; ++ int status; + }; + + /* the private variable of hash */ + struct rk_ahash_ctx { ++ struct crypto_engine_ctx enginectx; + struct rk_crypto_info *dev; + /* for fallback */ + struct crypto_ahash *fallback_tfm; +@@ -235,10 +213,12 @@ struct rk_ahash_ctx { + struct rk_ahash_rctx { + struct ahash_request fallback_req; + u32 mode; ++ int nrsg; + }; + + /* the private variable of cipher */ + struct rk_cipher_ctx { ++ struct crypto_engine_ctx enginectx; + struct rk_crypto_info *dev; + unsigned int keylen; + u8 key[AES_MAX_KEY_SIZE]; +@@ -247,6 +227,7 @@ struct rk_cipher_ctx { + }; + + struct rk_cipher_rctx { ++ u8 backup_iv[AES_BLOCK_SIZE]; + u32 mode; + struct skcipher_request fallback_req; // keep at the end + }; +diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +index c762e462eb57..edd40e16a3f0 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c +@@ -9,6 +9,7 @@ + * Some ideas are from marvell/cesa.c and s5p-sss.c driver. + */ + #include ++#include + #include "rk3288_crypto.h" + + /* +@@ -72,16 +73,12 @@ static int zero_message_process(struct ahash_request *req) + return 0; + } + +-static void rk_ahash_crypto_complete(struct crypto_async_request *base, int err) ++static void rk_ahash_reg_init(struct ahash_request *req) + { +- if (base->complete) +- base->complete(base, err); +-} +- +-static void rk_ahash_reg_init(struct rk_crypto_info *dev) +-{ +- struct ahash_request *req = ahash_request_cast(dev->async_req); + struct rk_ahash_rctx *rctx = ahash_request_ctx(req); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ struct rk_crypto_info *dev = tctx->dev; + int reg_status; + + reg_status = CRYPTO_READ(dev, RK_CRYPTO_CTRL) | +@@ -108,7 +105,7 @@ static void rk_ahash_reg_init(struct rk_crypto_info *dev) + RK_CRYPTO_BYTESWAP_BRFIFO | + RK_CRYPTO_BYTESWAP_BTFIFO); + +- CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, dev->total); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HASH_MSG_LEN, req->nbytes); + } + + static int rk_ahash_init(struct ahash_request *req) +@@ -206,44 +203,59 @@ static int rk_ahash_digest(struct ahash_request *req) + + if (!req->nbytes) + return zero_message_process(req); +- else +- return dev->enqueue(dev, &req->base); ++ ++ return crypto_transfer_hash_request_to_engine(dev->engine, req); + } + +-static void crypto_ahash_dma_start(struct rk_crypto_info *dev) ++static void crypto_ahash_dma_start(struct rk_crypto_info *dev, struct scatterlist *sg) + { +- CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, dev->addr_in); +- CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, (dev->count + 3) / 4); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAS, sg_dma_address(sg)); ++ CRYPTO_WRITE(dev, RK_CRYPTO_HRDMAL, sg_dma_len(sg) / 4); + CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_HASH_START | + (RK_CRYPTO_HASH_START << 16)); + } + +-static int rk_ahash_set_data_start(struct rk_crypto_info *dev) ++static int rk_hash_prepare(struct crypto_engine *engine, void *breq) ++{ ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ int ret; ++ ++ ret = dma_map_sg(tctx->dev->dev, areq->src, sg_nents(areq->src), DMA_TO_DEVICE); ++ if (ret <= 0) ++ return -EINVAL; ++ ++ rctx->nrsg = ret; ++ ++ return 0; ++} ++ ++static int rk_hash_unprepare(struct crypto_engine *engine, void *breq) + { +- int err; ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); + +- err = dev->load_data(dev, dev->sg_src, NULL); +- if (!err) +- crypto_ahash_dma_start(dev); +- return err; ++ dma_unmap_sg(tctx->dev->dev, areq->src, rctx->nrsg, DMA_TO_DEVICE); ++ return 0; + } + +-static int rk_ahash_start(struct rk_crypto_info *dev) ++static int rk_hash_run(struct crypto_engine *engine, void *breq) + { +- struct ahash_request *req = ahash_request_cast(dev->async_req); +- struct crypto_ahash *tfm; +- struct rk_ahash_rctx *rctx; +- +- dev->total = req->nbytes; +- dev->left_bytes = req->nbytes; +- dev->sg_dst = NULL; +- dev->sg_src = req->src; +- dev->first = req->src; +- dev->src_nents = sg_nents(req->src); +- rctx = ahash_request_ctx(req); ++ struct ahash_request *areq = container_of(breq, struct ahash_request, base); ++ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); ++ struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); ++ struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); ++ struct scatterlist *sg = areq->src; ++ int err = 0; ++ int i; ++ u32 v; ++ + rctx->mode = 0; + +- tfm = crypto_ahash_reqtfm(req); + switch (crypto_ahash_digestsize(tfm)) { + case SHA1_DIGEST_SIZE: + rctx->mode = RK_CRYPTO_HASH_SHA1; +@@ -255,30 +267,26 @@ static int rk_ahash_start(struct rk_crypto_info *dev) + rctx->mode = RK_CRYPTO_HASH_MD5; + break; + default: +- return -EINVAL; ++ err = -EINVAL; ++ goto theend; + } + +- rk_ahash_reg_init(dev); +- return rk_ahash_set_data_start(dev); +-} ++ rk_ahash_reg_init(areq); + +-static int rk_ahash_crypto_rx(struct rk_crypto_info *dev) +-{ +- int err = 0; +- struct ahash_request *req = ahash_request_cast(dev->async_req); +- struct crypto_ahash *tfm; +- +- dev->unload_data(dev); +- if (dev->left_bytes) { +- if (sg_is_last(dev->sg_src)) { +- dev_warn(dev->dev, "[%s:%d], Lack of data\n", +- __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; ++ while (sg) { ++ reinit_completion(&tctx->dev->complete); ++ tctx->dev->status = 0; ++ crypto_ahash_dma_start(tctx->dev, sg); ++ wait_for_completion_interruptible_timeout(&tctx->dev->complete, ++ msecs_to_jiffies(2000)); ++ if (!tctx->dev->status) { ++ dev_err(tctx->dev->dev, "DMA timeout\n"); ++ err = -EFAULT; ++ goto theend; + } +- dev->sg_src = sg_next(dev->sg_src); +- err = rk_ahash_set_data_start(dev); +- } else { ++ sg = sg_next(sg); ++ } ++ + /* + * it will take some time to process date after last dma + * transmission. +@@ -289,18 +297,20 @@ static int rk_ahash_crypto_rx(struct rk_crypto_info *dev) + * efficiency, and make it response quickly when dma + * complete. + */ +- while (!CRYPTO_READ(dev, RK_CRYPTO_HASH_STS)) +- udelay(10); +- +- tfm = crypto_ahash_reqtfm(req); +- memcpy_fromio(req->result, dev->reg + RK_CRYPTO_HASH_DOUT_0, +- crypto_ahash_digestsize(tfm)); +- dev->complete(dev->async_req, 0); +- tasklet_schedule(&dev->queue_task); ++ while (!CRYPTO_READ(tctx->dev, RK_CRYPTO_HASH_STS)) ++ udelay(10); ++ ++ for (i = 0; i < crypto_ahash_digestsize(tfm) / 4; i++) { ++ v = readl(tctx->dev->reg + RK_CRYPTO_HASH_DOUT_0 + i * 4); ++ put_unaligned_le32(v, areq->result + i * 4); + } + +-out_rx: +- return err; ++theend: ++ local_bh_disable(); ++ crypto_finalize_hash_request(engine, breq, err); ++ local_bh_enable(); ++ ++ return 0; + } + + static int rk_cra_hash_init(struct crypto_tfm *tfm) +@@ -314,9 +324,6 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + + tctx->dev = algt->dev; +- tctx->dev->start = rk_ahash_start; +- tctx->dev->update = rk_ahash_crypto_rx; +- tctx->dev->complete = rk_ahash_crypto_complete; + + /* for fallback */ + tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0, +@@ -325,10 +332,15 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) + dev_err(tctx->dev->dev, "Could not load fallback driver.\n"); + return PTR_ERR(tctx->fallback_tfm); + } ++ + crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + sizeof(struct rk_ahash_rctx) + + crypto_ahash_reqsize(tctx->fallback_tfm)); + ++ tctx->enginectx.op.do_one_request = rk_hash_run; ++ tctx->enginectx.op.prepare_request = rk_hash_prepare; ++ tctx->enginectx.op.unprepare_request = rk_hash_unprepare; ++ + return 0; + } + +diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +index d067b7f09165..67a7e05d5ae3 100644 +--- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c ++++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +@@ -9,6 +9,7 @@ + * Some ideas are from marvell-cesa.c and s5p-sss.c driver. + */ + #include ++#include + #include "rk3288_crypto.h" + + #define RK_CRYPTO_DEC BIT(0) +@@ -70,19 +71,15 @@ static int rk_cipher_fallback(struct skcipher_request *areq) + return err; + } + +-static void rk_crypto_complete(struct crypto_async_request *base, int err) +-{ +- if (base->complete) +- base->complete(base, err); +-} +- + static int rk_handle_req(struct rk_crypto_info *dev, + struct skcipher_request *req) + { ++ struct crypto_engine *engine = dev->engine; ++ + if (rk_cipher_need_fallback(req)) + return rk_cipher_fallback(req); + +- return dev->enqueue(dev, &req->base); ++ return crypto_transfer_skcipher_request_to_engine(engine, req); + } + + static int rk_aes_setkey(struct crypto_skcipher *cipher, +@@ -265,25 +262,21 @@ static int rk_des3_ede_cbc_decrypt(struct skcipher_request *req) + return rk_handle_req(dev, req); + } + +-static void rk_ablk_hw_init(struct rk_crypto_info *dev) ++static void rk_ablk_hw_init(struct rk_crypto_info *dev, struct skcipher_request *req) + { +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); + struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req); + struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher); + struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher); +- u32 ivsize, block, conf_reg = 0; ++ u32 block, conf_reg = 0; + + block = crypto_tfm_alg_blocksize(tfm); +- ivsize = crypto_skcipher_ivsize(cipher); + + if (block == DES_BLOCK_SIZE) { + rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE | + RK_CRYPTO_TDES_BYTESWAP_KEY | + RK_CRYPTO_TDES_BYTESWAP_IV; + CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode); +- memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, req->iv, ivsize); + memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_KEY1_0, ctx->key, ctx->keylen); + conf_reg = RK_CRYPTO_DESSEL; + } else { +@@ -296,7 +289,6 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + else if (ctx->keylen == AES_KEYSIZE_256) + rctx->mode |= RK_CRYPTO_AES_256BIT_key; + CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode); +- memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, req->iv, ivsize); + memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_KEY_0, ctx->key, ctx->keylen); + } + conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO | +@@ -306,133 +298,138 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev) + RK_CRYPTO_BCDMA_ERR_ENA | RK_CRYPTO_BCDMA_DONE_ENA); + } + +-static void crypto_dma_start(struct rk_crypto_info *dev) ++static void crypto_dma_start(struct rk_crypto_info *dev, ++ struct scatterlist *sgs, ++ struct scatterlist *sgd, unsigned int todo) + { +- CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, dev->addr_in); +- CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, dev->count / 4); +- CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, dev->addr_out); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAS, sg_dma_address(sgs)); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BRDMAL, todo); ++ CRYPTO_WRITE(dev, RK_CRYPTO_BTDMAS, sg_dma_address(sgd)); + CRYPTO_WRITE(dev, RK_CRYPTO_CTRL, RK_CRYPTO_BLOCK_START | + _SBF(RK_CRYPTO_BLOCK_START, 16)); + } + +-static int rk_set_data_start(struct rk_crypto_info *dev) ++static int rk_cipher_run(struct crypto_engine *engine, void *async_req) + { +- int err; +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); ++ struct skcipher_request *areq = container_of(async_req, struct skcipher_request, base); ++ struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); + struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); +- u8 *src_last_blk = page_address(sg_page(dev->sg_src)) + +- dev->sg_src->offset + dev->sg_src->length - ivsize; +- +- /* Store the iv that need to be updated in chain mode. +- * And update the IV buffer to contain the next IV for decryption mode. +- */ +- if (rctx->mode & RK_CRYPTO_DEC) { +- memcpy(ctx->iv, src_last_blk, ivsize); +- sg_pcopy_to_buffer(dev->first, dev->src_nents, req->iv, +- ivsize, dev->total - ivsize); +- } +- +- err = dev->load_data(dev, dev->sg_src, dev->sg_dst); +- if (!err) +- crypto_dma_start(dev); +- return err; +-} +- +-static int rk_ablk_start(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- unsigned long flags; ++ struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq); ++ struct scatterlist *sgs, *sgd; + int err = 0; ++ int ivsize = crypto_skcipher_ivsize(tfm); ++ int offset; ++ u8 iv[AES_BLOCK_SIZE]; ++ u8 biv[AES_BLOCK_SIZE]; ++ u8 *ivtouse = areq->iv; ++ unsigned int len = areq->cryptlen; ++ unsigned int todo; ++ ++ ivsize = crypto_skcipher_ivsize(tfm); ++ if (areq->iv && crypto_skcipher_ivsize(tfm) > 0) { ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ offset = areq->cryptlen - ivsize; ++ scatterwalk_map_and_copy(rctx->backup_iv, areq->src, ++ offset, ivsize, 0); ++ } ++ } + +- dev->left_bytes = req->cryptlen; +- dev->total = req->cryptlen; +- dev->sg_src = req->src; +- dev->first = req->src; +- dev->src_nents = sg_nents(req->src); +- dev->sg_dst = req->dst; +- dev->dst_nents = sg_nents(req->dst); +- +- spin_lock_irqsave(&dev->lock, flags); +- rk_ablk_hw_init(dev); +- err = rk_set_data_start(dev); +- spin_unlock_irqrestore(&dev->lock, flags); +- return err; +-} +- +-static void rk_iv_copyback(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); +- struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); ++ sgs = areq->src; ++ sgd = areq->dst; + +- /* Update the IV buffer to contain the next IV for encryption mode. */ +- if (!(rctx->mode & RK_CRYPTO_DEC)) { +- memcpy(req->iv, +- sg_virt(dev->sg_dst) + dev->sg_dst->length - ivsize, +- ivsize); ++ while (sgs && sgd && len) { ++ if (!sgs->length) { ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); ++ continue; ++ } ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ /* we backup last block of source to be used as IV at next step */ ++ offset = sgs->length - ivsize; ++ scatterwalk_map_and_copy(biv, sgs, offset, ivsize, 0); ++ } ++ if (sgs == sgd) { ++ err = dma_map_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_iv; ++ } ++ } else { ++ err = dma_map_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_iv; ++ } ++ err = dma_map_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); ++ if (err <= 0) { ++ err = -EINVAL; ++ goto theend_sgs; ++ } ++ } ++ err = 0; ++ rk_ablk_hw_init(ctx->dev, areq); ++ if (ivsize) { ++ if (ivsize == DES_BLOCK_SIZE) ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_TDES_IV_0, ivtouse, ivsize); ++ else ++ memcpy_toio(ctx->dev->reg + RK_CRYPTO_AES_IV_0, ivtouse, ivsize); ++ } ++ reinit_completion(&ctx->dev->complete); ++ ctx->dev->status = 0; ++ ++ todo = min(sg_dma_len(sgs), len); ++ len -= todo; ++ crypto_dma_start(ctx->dev, sgs, sgd, todo / 4); ++ wait_for_completion_interruptible_timeout(&ctx->dev->complete, ++ msecs_to_jiffies(2000)); ++ if (!ctx->dev->status) { ++ dev_err(ctx->dev->dev, "DMA timeout\n"); ++ err = -EFAULT; ++ goto theend; ++ } ++ if (sgs == sgd) { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); ++ } else { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ dma_unmap_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); ++ } ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ memcpy(iv, biv, ivsize); ++ ivtouse = iv; ++ } else { ++ offset = sgd->length - ivsize; ++ scatterwalk_map_and_copy(iv, sgd, offset, ivsize, 0); ++ ivtouse = iv; ++ } ++ sgs = sg_next(sgs); ++ sgd = sg_next(sgd); + } +-} +- +-static void rk_update_iv(struct rk_crypto_info *dev) +-{ +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); +- struct rk_cipher_rctx *rctx = skcipher_request_ctx(req); +- struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); +- u32 ivsize = crypto_skcipher_ivsize(tfm); +- u8 *new_iv = NULL; + +- if (rctx->mode & RK_CRYPTO_DEC) { +- new_iv = ctx->iv; +- } else { +- new_iv = page_address(sg_page(dev->sg_dst)) + +- dev->sg_dst->offset + dev->sg_dst->length - ivsize; ++ if (areq->iv && ivsize > 0) { ++ offset = areq->cryptlen - ivsize; ++ if (rctx->mode & RK_CRYPTO_DEC) { ++ memcpy(areq->iv, rctx->backup_iv, ivsize); ++ memzero_explicit(rctx->backup_iv, ivsize); ++ } else { ++ scatterwalk_map_and_copy(areq->iv, areq->dst, offset, ++ ivsize, 0); ++ } + } + +- if (ivsize == DES_BLOCK_SIZE) +- memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, new_iv, ivsize); +- else if (ivsize == AES_BLOCK_SIZE) +- memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, new_iv, ivsize); +-} ++theend: ++ local_bh_disable(); ++ crypto_finalize_skcipher_request(engine, areq, err); ++ local_bh_enable(); ++ return 0; + +-/* return: +- * true some err was occurred +- * fault no err, continue +- */ +-static int rk_ablk_rx(struct rk_crypto_info *dev) +-{ +- int err = 0; +- struct skcipher_request *req = +- skcipher_request_cast(dev->async_req); +- +- dev->unload_data(dev); +- if (dev->left_bytes) { +- rk_update_iv(dev); +- if (sg_is_last(dev->sg_src)) { +- dev_err(dev->dev, "[%s:%d] Lack of data\n", +- __func__, __LINE__); +- err = -ENOMEM; +- goto out_rx; +- } +- dev->sg_src = sg_next(dev->sg_src); +- dev->sg_dst = sg_next(dev->sg_dst); +- err = rk_set_data_start(dev); ++theend_sgs: ++ if (sgs == sgd) { ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_BIDIRECTIONAL); + } else { +- rk_iv_copyback(dev); +- /* here show the calculation is over without any err */ +- dev->complete(dev->async_req, 0); +- tasklet_schedule(&dev->queue_task); ++ dma_unmap_sg(ctx->dev->dev, sgs, 1, DMA_TO_DEVICE); ++ dma_unmap_sg(ctx->dev->dev, sgd, 1, DMA_FROM_DEVICE); + } +-out_rx: ++theend_iv: + return err; + } + +@@ -446,9 +443,6 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + + ctx->dev = algt->dev; +- ctx->dev->start = rk_ablk_start; +- ctx->dev->update = rk_ablk_rx; +- ctx->dev->complete = rk_crypto_complete; + + ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(ctx->fallback_tfm)) { +@@ -460,6 +454,8 @@ static int rk_ablk_init_tfm(struct crypto_skcipher *tfm) + tfm->reqsize = sizeof(struct rk_cipher_rctx) + + crypto_skcipher_reqsize(ctx->fallback_tfm); + ++ ctx->enginectx.op.do_one_request = rk_cipher_run; ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/crypto-sun8i-ss-use-dma_addr-instead-u32.patch b/queue-5.15/crypto-sun8i-ss-use-dma_addr-instead-u32.patch new file mode 100644 index 00000000000..a0ed79d0022 --- /dev/null +++ b/queue-5.15/crypto-sun8i-ss-use-dma_addr-instead-u32.patch @@ -0,0 +1,36 @@ +From fa43a344af5b1fa2f9e51f385adf901d284cf39d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 08:55:55 +0000 +Subject: crypto: sun8i-ss - use dma_addr instead u32 + +From: Corentin Labbe + +[ Upstream commit 839b8ae2fc10f205317bcc32c9de18456756e1f5 ] + +The DMA address need to be stored in a dma_addr_t + +Fixes: 359e893e8af4 ("crypto: sun8i-ss - rework handling of IV") +Reported-by: Dan Carpenter +Signed-off-by: Corentin Labbe +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +index 3c46ad8c3a1c..005eefecfdf5 100644 +--- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c ++++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +@@ -105,7 +105,7 @@ static int sun8i_ss_setup_ivs(struct skcipher_request *areq) + unsigned int ivsize = crypto_skcipher_ivsize(tfm); + struct sun8i_ss_flow *sf = &ss->flows[rctx->flow]; + int i = 0; +- u32 a; ++ dma_addr_t a; + int err; + + rctx->ivlen = ivsize; +-- +2.35.1 + diff --git a/queue-5.15/crypto-tcrypt-fix-multibuffer-skcipher-speed-test-me.patch b/queue-5.15/crypto-tcrypt-fix-multibuffer-skcipher-speed-test-me.patch new file mode 100644 index 00000000000..8ac5a96a65e --- /dev/null +++ b/queue-5.15/crypto-tcrypt-fix-multibuffer-skcipher-speed-test-me.patch @@ -0,0 +1,45 @@ +From 848d627f47e73b3343125122ad49d3ec8217b75d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 17:24:11 +0800 +Subject: crypto: tcrypt - Fix multibuffer skcipher speed test mem leak + +From: Zhang Yiqun + +[ Upstream commit 1aa33fc8d4032227253ceb736f47c52b859d9683 ] + +In the past, the data for mb-skcipher test has been allocated +twice, that means the first allcated memory area is without +free, which may cause a potential memory leakage. So this +patch is to remove one allocation to fix this error. + +Fixes: e161c5930c15 ("crypto: tcrypt - add multibuf skcipher...") +Signed-off-by: Zhang Yiqun +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/tcrypt.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c +index 3362897bf61b..4ada7e749390 100644 +--- a/crypto/tcrypt.c ++++ b/crypto/tcrypt.c +@@ -1295,15 +1295,6 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, + goto out_free_tfm; + } + +- +- for (i = 0; i < num_mb; ++i) +- if (testmgr_alloc_buf(data[i].xbuf)) { +- while (i--) +- testmgr_free_buf(data[i].xbuf); +- goto out_free_tfm; +- } +- +- + for (i = 0; i < num_mb; ++i) { + data[i].req = skcipher_request_alloc(tfm, GFP_KERNEL); + if (!data[i].req) { +-- +2.35.1 + diff --git a/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_guest_init_af.patch b/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_guest_init_af.patch new file mode 100644 index 00000000000..9e06b9a0af7 --- /dev/null +++ b/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_guest_init_af.patch @@ -0,0 +1,99 @@ +From 1a3007a985f9af7e2f83bc9fe787f65169f3c93d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 22:54:39 +0800 +Subject: cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter() + +From: Yang Yingliang + +[ Upstream commit 61c80d1c3833e196256fb060382db94f24d3d9a7 ] + +If device_register() fails in cxl_register_afu|adapter(), the device +is not added, device_unregister() can not be called in the error path, +otherwise it will cause a null-ptr-deref because of removing not added +device. + +As comment of device_register() says, it should use put_device() to give +up the reference in the error path. So split device_unregister() into +device_del() and put_device(), then goes to put dev when register fails. + +Fixes: 14baf4d9c739 ("cxl: Add guest-specific code") +Signed-off-by: Yang Yingliang +Acked-by: Andrew Donnellan +Acked-by: Frederic Barrat +Link: https://lore.kernel.org/r/20221111145440.2426970-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/cxl/guest.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c +index 186308f1f8eb..6334376826a9 100644 +--- a/drivers/misc/cxl/guest.c ++++ b/drivers/misc/cxl/guest.c +@@ -959,10 +959,10 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + * if it returns an error! + */ + if ((rc = cxl_register_afu(afu))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_afu_add(afu))) +- goto err_put1; ++ goto err_del_dev; + + /* + * pHyp doesn't expose the programming models supported by the +@@ -978,7 +978,7 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + afu->modes_supported = CXL_MODE_DIRECTED; + + if ((rc = cxl_afu_select_best_mode(afu))) +- goto err_put2; ++ goto err_remove_sysfs; + + adapter->afu[afu->slice] = afu; + +@@ -998,10 +998,12 @@ int cxl_guest_init_afu(struct cxl *adapter, int slice, struct device_node *afu_n + + return 0; + +-err_put2: ++err_remove_sysfs: + cxl_sysfs_afu_remove(afu); +-err_put1: +- device_unregister(&afu->dev); ++err_del_dev: ++ device_del(&afu->dev); ++err_put_dev: ++ put_device(&afu->dev); + free = false; + guest_release_serr_irq(afu); + err2: +@@ -1135,18 +1137,20 @@ struct cxl *cxl_guest_init_adapter(struct device_node *np, struct platform_devic + * even if it returns an error! + */ + if ((rc = cxl_register_adapter(adapter))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_adapter_add(adapter))) +- goto err_put1; ++ goto err_del_dev; + + /* release the context lock as the adapter is configured */ + cxl_adapter_context_unlock(adapter); + + return adapter; + +-err_put1: +- device_unregister(&adapter->dev); ++err_del_dev: ++ device_del(&adapter->dev); ++err_put_dev: ++ put_device(&adapter->dev); + free = false; + cxl_guest_remove_chardev(adapter); + err1: +-- +2.35.1 + diff --git a/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_pci_init_afu-.patch b/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_pci_init_afu-.patch new file mode 100644 index 00000000000..8f3769c2f7b --- /dev/null +++ b/queue-5.15/cxl-fix-possible-null-ptr-deref-in-cxl_pci_init_afu-.patch @@ -0,0 +1,94 @@ +From b844c922970b8b889d24676d061de9396d65ede2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 22:54:40 +0800 +Subject: cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter() + +From: Yang Yingliang + +[ Upstream commit 02cd3032b154fa02fdf90e7467abaeed889330b2 ] + +If device_register() fails in cxl_pci_afu|adapter(), the device +is not added, device_unregister() can not be called in the error +path, otherwise it will cause a null-ptr-deref because of removing +not added device. + +As comment of device_register() says, it should use put_device() to give +up the reference in the error path. So split device_unregister() into +device_del() and put_device(), then goes to put dev when register fails. + +Fixes: f204e0b8cedd ("cxl: Driver code for powernv PCIe based cards for userspace access") +Signed-off-by: Yang Yingliang +Acked-by: Frederic Barrat +Acked-by: Andrew Donnellan +Link: https://lore.kernel.org/r/20221111145440.2426970-2-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/cxl/pci.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c +index 2ba899f5659f..0ac3f4cb88ac 100644 +--- a/drivers/misc/cxl/pci.c ++++ b/drivers/misc/cxl/pci.c +@@ -1164,10 +1164,10 @@ static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) + * if it returns an error! + */ + if ((rc = cxl_register_afu(afu))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_afu_add(afu))) +- goto err_put1; ++ goto err_del_dev; + + adapter->afu[afu->slice] = afu; + +@@ -1176,10 +1176,12 @@ static int pci_init_afu(struct cxl *adapter, int slice, struct pci_dev *dev) + + return 0; + +-err_put1: ++err_del_dev: ++ device_del(&afu->dev); ++err_put_dev: + pci_deconfigure_afu(afu); + cxl_debugfs_afu_remove(afu); +- device_unregister(&afu->dev); ++ put_device(&afu->dev); + return rc; + + err_free_native: +@@ -1667,23 +1669,25 @@ static struct cxl *cxl_pci_init_adapter(struct pci_dev *dev) + * even if it returns an error! + */ + if ((rc = cxl_register_adapter(adapter))) +- goto err_put1; ++ goto err_put_dev; + + if ((rc = cxl_sysfs_adapter_add(adapter))) +- goto err_put1; ++ goto err_del_dev; + + /* Release the context lock as adapter is configured */ + cxl_adapter_context_unlock(adapter); + + return adapter; + +-err_put1: ++err_del_dev: ++ device_del(&adapter->dev); ++err_put_dev: + /* This should mirror cxl_remove_adapter, except without the + * sysfs parts + */ + cxl_debugfs_adapter_remove(adapter); + cxl_deconfigure_adapter(adapter); +- device_unregister(&adapter->dev); ++ put_device(&adapter->dev); + return ERR_PTR(rc); + + err_release: +-- +2.35.1 + diff --git a/queue-5.15/cxl-fix-refcount-leak-in-cxl_calc_capp_routing.patch b/queue-5.15/cxl-fix-refcount-leak-in-cxl_calc_capp_routing.patch new file mode 100644 index 00000000000..a9f2683af2b --- /dev/null +++ b/queue-5.15/cxl-fix-refcount-leak-in-cxl_calc_capp_routing.patch @@ -0,0 +1,41 @@ +From 8d42020ca440de10f92e9c65e903ad41a0cb41a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jun 2022 10:00:38 +0400 +Subject: cxl: Fix refcount leak in cxl_calc_capp_routing + +From: Miaoqian Lin + +[ Upstream commit 1d09697ff22908ae487fc8c4fbde1811732be523 ] + +of_get_next_parent() returns a node pointer with refcount incremented, +we should use of_node_put() on it when not need anymore. +This function only calls of_node_put() in normal path, +missing it in the error path. +Add missing of_node_put() to avoid refcount leak. + +Fixes: f24be42aab37 ("cxl: Add psl9 specific code") +Signed-off-by: Miaoqian Lin +Acked-by: Andrew Donnellan +Acked-by: Frederic Barrat +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220605060038.62217-1-linmq006@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/misc/cxl/pci.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c +index 0ac3f4cb88ac..d183836d80e3 100644 +--- a/drivers/misc/cxl/pci.c ++++ b/drivers/misc/cxl/pci.c +@@ -387,6 +387,7 @@ int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid, + rc = get_phb_index(np, phb_index); + if (rc) { + pr_err("cxl: invalid phb index\n"); ++ of_node_put(np); + return rc; + } + +-- +2.35.1 + diff --git a/queue-5.15/debugfs-fix-error-when-writing-negative-value-to-ato.patch b/queue-5.15/debugfs-fix-error-when-writing-negative-value-to-ato.patch new file mode 100644 index 00000000000..f07d15a168f --- /dev/null +++ b/queue-5.15/debugfs-fix-error-when-writing-negative-value-to-ato.patch @@ -0,0 +1,198 @@ +From 71e0adc4f50bdf1870ea4fff41d6a668640f36ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 02:24:18 +0900 +Subject: debugfs: fix error when writing negative value to atomic_t debugfs + file + +From: Akinobu Mita + +[ Upstream commit d472cf797c4e268613dbce5ec9b95d0bcae19ecb ] + +The simple attribute files do not accept a negative value since the commit +488dac0c9237 ("libfs: fix error cast of negative value in +simple_attr_write()"), so we have to use a 64-bit value to write a +negative value for a debugfs file created by debugfs_create_atomic_t(). + +This restores the previous behaviour by introducing +DEFINE_DEBUGFS_ATTRIBUTE_SIGNED for a signed value. + +Link: https://lkml.kernel.org/r/20220919172418.45257-4-akinobu.mita@gmail.com +Fixes: 488dac0c9237 ("libfs: fix error cast of negative value in simple_attr_write()") +Signed-off-by: Akinobu Mita +Reported-by: Zhao Gongyi +Reviewed-by: David Hildenbrand +Reviewed-by: Greg Kroah-Hartman +Cc: Alexander Viro +Cc: Jonathan Corbet +Cc: Oscar Salvador +Cc: Rafael J. Wysocki +Cc: Shuah Khan +Cc: Wei Yongjun +Cc: Yicong Yang +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + .../fault-injection/fault-injection.rst | 10 +++---- + fs/debugfs/file.c | 28 +++++++++++++++---- + include/linux/debugfs.h | 19 +++++++++++-- + 3 files changed, 43 insertions(+), 14 deletions(-) + +diff --git a/Documentation/fault-injection/fault-injection.rst b/Documentation/fault-injection/fault-injection.rst +index 4a25c5eb6f07..8c47847755a6 100644 +--- a/Documentation/fault-injection/fault-injection.rst ++++ b/Documentation/fault-injection/fault-injection.rst +@@ -83,9 +83,7 @@ configuration of fault-injection capabilities. + - /sys/kernel/debug/fail*/times: + + specifies how many times failures may happen at most. A value of -1 +- means "no limit". Note, though, that this file only accepts unsigned +- values. So, if you want to specify -1, you better use 'printf' instead +- of 'echo', e.g.: $ printf %#x -1 > times ++ means "no limit". + + - /sys/kernel/debug/fail*/space: + +@@ -277,7 +275,7 @@ Application Examples + echo Y > /sys/kernel/debug/$FAILTYPE/task-filter + echo 10 > /sys/kernel/debug/$FAILTYPE/probability + echo 100 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 2 > /sys/kernel/debug/$FAILTYPE/verbose + echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait +@@ -331,7 +329,7 @@ Application Examples + echo N > /sys/kernel/debug/$FAILTYPE/task-filter + echo 10 > /sys/kernel/debug/$FAILTYPE/probability + echo 100 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 2 > /sys/kernel/debug/$FAILTYPE/verbose + echo 1 > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait +@@ -362,7 +360,7 @@ Application Examples + echo N > /sys/kernel/debug/$FAILTYPE/task-filter + echo 100 > /sys/kernel/debug/$FAILTYPE/probability + echo 0 > /sys/kernel/debug/$FAILTYPE/interval +- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times ++ echo -1 > /sys/kernel/debug/$FAILTYPE/times + echo 0 > /sys/kernel/debug/$FAILTYPE/space + echo 1 > /sys/kernel/debug/$FAILTYPE/verbose + +diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c +index 950c63fa4d0b..38930d9b0bb7 100644 +--- a/fs/debugfs/file.c ++++ b/fs/debugfs/file.c +@@ -378,8 +378,8 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf, + } + EXPORT_SYMBOL_GPL(debugfs_attr_read); + +-ssize_t debugfs_attr_write(struct file *file, const char __user *buf, +- size_t len, loff_t *ppos) ++static ssize_t debugfs_attr_write_xsigned(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos, bool is_signed) + { + struct dentry *dentry = F_DENTRY(file); + ssize_t ret; +@@ -387,12 +387,28 @@ ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + ret = debugfs_file_get(dentry); + if (unlikely(ret)) + return ret; +- ret = simple_attr_write(file, buf, len, ppos); ++ if (is_signed) ++ ret = simple_attr_write_signed(file, buf, len, ppos); ++ else ++ ret = simple_attr_write(file, buf, len, ppos); + debugfs_file_put(dentry); + return ret; + } ++ ++ssize_t debugfs_attr_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return debugfs_attr_write_xsigned(file, buf, len, ppos, false); ++} + EXPORT_SYMBOL_GPL(debugfs_attr_write); + ++ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return debugfs_attr_write_xsigned(file, buf, len, ppos, true); ++} ++EXPORT_SYMBOL_GPL(debugfs_attr_write_signed); ++ + static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode, + struct dentry *parent, void *value, + const struct file_operations *fops, +@@ -738,11 +754,11 @@ static int debugfs_atomic_t_get(void *data, u64 *val) + *val = atomic_read((atomic_t *)data); + return 0; + } +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t, debugfs_atomic_t_get, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t, debugfs_atomic_t_get, + debugfs_atomic_t_set, "%lld\n"); +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_ro, debugfs_atomic_t_get, NULL, + "%lld\n"); +-DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, ++DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(fops_atomic_t_wo, NULL, debugfs_atomic_t_set, + "%lld\n"); + + /** +diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h +index f60674692d36..ea2d919fd9c7 100644 +--- a/include/linux/debugfs.h ++++ b/include/linux/debugfs.h +@@ -45,7 +45,7 @@ struct debugfs_u32_array { + + extern struct dentry *arch_debugfs_dir; + +-#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++#define DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed) \ + static int __fops ## _open(struct inode *inode, struct file *file) \ + { \ + __simple_attr_check_format(__fmt, 0ull); \ +@@ -56,10 +56,16 @@ static const struct file_operations __fops = { \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = debugfs_attr_read, \ +- .write = debugfs_attr_write, \ ++ .write = (__is_signed) ? debugfs_attr_write_signed : debugfs_attr_write, \ + .llseek = no_llseek, \ + } + ++#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++ DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false) ++ ++#define DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ ++ DEFINE_DEBUGFS_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true) ++ + typedef struct vfsmount *(*debugfs_automount_t)(struct dentry *, void *); + + #if defined(CONFIG_DEBUG_FS) +@@ -102,6 +108,8 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); + ssize_t debugfs_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos); ++ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos); + + struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, const char *new_name); +@@ -254,6 +262,13 @@ static inline ssize_t debugfs_attr_write(struct file *file, + return -ENODEV; + } + ++static inline ssize_t debugfs_attr_write_signed(struct file *file, ++ const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return -ENODEV; ++} ++ + static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, + struct dentry *new_dir, char *new_name) + { +-- +2.35.1 + diff --git a/queue-5.15/dmaengine-idxd-fix-crc_val-field-for-completion-reco.patch b/queue-5.15/dmaengine-idxd-fix-crc_val-field-for-completion-reco.patch new file mode 100644 index 00000000000..c5c6bd935e3 --- /dev/null +++ b/queue-5.15/dmaengine-idxd-fix-crc_val-field-for-completion-reco.patch @@ -0,0 +1,38 @@ +From 1b3b9745579f8e00b3f94f7e19203d570048f1f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 17:27:15 -0800 +Subject: dmaengine: idxd: Fix crc_val field for completion record + +From: Fenghua Yu + +[ Upstream commit dc901d98b1fe6e52ab81cd3e0879379168e06daa ] + +The crc_val in the completion record should be 64 bits and not 32 bits. + +Fixes: 4ac823e9cd85 ("dmaengine: idxd: fix delta_rec and crc size field for completion record") +Reported-by: Nirav N Shah +Signed-off-by: Fenghua Yu +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20221111012715.2031481-1-fenghua.yu@intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + include/uapi/linux/idxd.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h +index c750eac09fc9..f7c01709cb0f 100644 +--- a/include/uapi/linux/idxd.h ++++ b/include/uapi/linux/idxd.h +@@ -272,7 +272,7 @@ struct dsa_completion_record { + }; + + uint32_t delta_rec_size; +- uint32_t crc_val; ++ uint64_t crc_val; + + /* DIF check & strip */ + struct { +-- +2.35.1 + diff --git a/queue-5.15/drbd-destroy-workqueue-when-drbd-device-was-freed.patch b/queue-5.15/drbd-destroy-workqueue-when-drbd-device-was-freed.patch new file mode 100644 index 00000000000..47728714f7e --- /dev/null +++ b/queue-5.15/drbd-destroy-workqueue-when-drbd-device-was-freed.patch @@ -0,0 +1,56 @@ +From 4c27feea436b35e089f82017a957c5f93cdc81db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 09:58:17 +0800 +Subject: drbd: destroy workqueue when drbd device was freed + +From: Wang ShaoBo + +[ Upstream commit 8692814b77ca4228a99da8a005de0acf40af6132 ] + +A submitter workqueue is dynamically allocated by init_submitter() +called by drbd_create_device(), we should destroy it when this +device is not needed or destroyed. + +Fixes: 113fef9e20e0 ("drbd: prepare to queue write requests on a submit worker") +Signed-off-by: Wang ShaoBo +Link: https://lore.kernel.org/r/20221124015817.2729789-3-bobo.shaobowang@huawei.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/drbd/drbd_main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c +index be819f80884f..eaf20a332401 100644 +--- a/drivers/block/drbd/drbd_main.c ++++ b/drivers/block/drbd/drbd_main.c +@@ -2244,6 +2244,8 @@ void drbd_destroy_device(struct kref *kref) + kref_put(&peer_device->connection->kref, drbd_destroy_connection); + kfree(peer_device); + } ++ if (device->submit.wq) ++ destroy_workqueue(device->submit.wq); + kfree(device); + kref_put(&resource->kref, drbd_destroy_resource); + } +@@ -2797,7 +2799,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig + + err = add_disk(disk); + if (err) +- goto out_idr_remove_from_resource; ++ goto out_destroy_workqueue; + + /* inherit the connection state */ + device->state.conn = first_connection(resource)->cstate; +@@ -2811,6 +2813,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig + drbd_debugfs_device_add(device); + return NO_ERROR; + ++out_destroy_workqueue: ++ destroy_workqueue(device->submit.wq); + out_idr_remove_from_resource: + for_each_connection_safe(connection, n, resource) { + peer_device = idr_remove(&connection->peer_devices, vnr); +-- +2.35.1 + diff --git a/queue-5.15/drbd-remove-call-to-memset-before-free-device-resour.patch b/queue-5.15/drbd-remove-call-to-memset-before-free-device-resour.patch new file mode 100644 index 00000000000..dc8f3a4653f --- /dev/null +++ b/queue-5.15/drbd-remove-call-to-memset-before-free-device-resour.patch @@ -0,0 +1,53 @@ +From 115d5909432aa926d8994cd09e701c5e04b6e756 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 09:58:16 +0800 +Subject: drbd: remove call to memset before free device/resource/connection + +From: Wang ShaoBo + +[ Upstream commit 6e7b854e4c1b02dba00760dfa79d8dbf6cce561e ] + +This revert c2258ffc56f2 ("drbd: poison free'd device, resource and +connection structs"), add memset is odd here for debugging, there are +some methods to accurately show what happened, such as kdump. + +Signed-off-by: Wang ShaoBo +Link: https://lore.kernel.org/r/20221124015817.2729789-2-bobo.shaobowang@huawei.com +Signed-off-by: Jens Axboe +Stable-dep-of: 8692814b77ca ("drbd: destroy workqueue when drbd device was freed") +Signed-off-by: Sasha Levin +--- + drivers/block/drbd/drbd_main.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c +index f4e38c208b9f..be819f80884f 100644 +--- a/drivers/block/drbd/drbd_main.c ++++ b/drivers/block/drbd/drbd_main.c +@@ -2244,7 +2244,6 @@ void drbd_destroy_device(struct kref *kref) + kref_put(&peer_device->connection->kref, drbd_destroy_connection); + kfree(peer_device); + } +- memset(device, 0xfd, sizeof(*device)); + kfree(device); + kref_put(&resource->kref, drbd_destroy_resource); + } +@@ -2336,7 +2335,6 @@ void drbd_destroy_resource(struct kref *kref) + idr_destroy(&resource->devices); + free_cpumask_var(resource->cpu_mask); + kfree(resource->name); +- memset(resource, 0xf2, sizeof(*resource)); + kfree(resource); + } + +@@ -2677,7 +2675,6 @@ void drbd_destroy_connection(struct kref *kref) + drbd_free_socket(&connection->data); + kfree(connection->int_dig_in); + kfree(connection->int_dig_vv); +- memset(connection, 0xfc, sizeof(*connection)); + kfree(connection); + kref_put(&resource->kref, drbd_destroy_resource); + } +-- +2.35.1 + diff --git a/queue-5.15/drivers-dio-fix-possible-memory-leak-in-dio_init.patch b/queue-5.15/drivers-dio-fix-possible-memory-leak-in-dio_init.patch new file mode 100644 index 00000000000..75ba91efc4c --- /dev/null +++ b/queue-5.15/drivers-dio-fix-possible-memory-leak-in-dio_init.patch @@ -0,0 +1,60 @@ +From ac64c0b9713decd7458f24eefa98128a3a5f68ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 14:40:36 +0800 +Subject: drivers: dio: fix possible memory leak in dio_init() + +From: Yang Yingliang + +[ Upstream commit e63e99397b2613d50a5f4f02ed07307e67a190f1 ] + +If device_register() returns error, the 'dev' and name needs be +freed. Add a release function, and then call put_device() in the +error path, so the name is freed in kobject_cleanup() and to the +'dev' is freed in release function. + +Fixes: 2e4c77bea3d8 ("m68k: dio - Kill warn_unused_result warnings") +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221109064036.1835346-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/dio/dio.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c +index 4c06c93c93d3..c7f7134adc21 100644 +--- a/drivers/dio/dio.c ++++ b/drivers/dio/dio.c +@@ -110,6 +110,12 @@ static char dio_no_name[] = { 0 }; + + #endif /* CONFIG_DIO_CONSTANTS */ + ++static void dio_dev_release(struct device *dev) ++{ ++ struct dio_dev *ddev = container_of(dev, typeof(struct dio_dev), dev); ++ kfree(ddev); ++} ++ + int __init dio_find(int deviceid) + { + /* Called to find a DIO device before the full bus scan has run. +@@ -224,6 +230,7 @@ static int __init dio_init(void) + dev->bus = &dio_bus; + dev->dev.parent = &dio_bus.dev; + dev->dev.bus = &dio_bus_type; ++ dev->dev.release = dio_dev_release; + dev->scode = scode; + dev->resource.start = pa; + dev->resource.end = pa + DIO_SIZE(scode, va); +@@ -251,6 +258,7 @@ static int __init dio_init(void) + if (error) { + pr_err("DIO: Error registering device %s\n", + dev->name); ++ put_device(&dev->dev); + continue; + } + error = dio_create_sysfs_dev_files(dev); +-- +2.35.1 + diff --git a/queue-5.15/drivers-mcb-fix-resource-leak-in-mcb_probe.patch b/queue-5.15/drivers-mcb-fix-resource-leak-in-mcb_probe.patch new file mode 100644 index 00000000000..930a757b6a7 --- /dev/null +++ b/queue-5.15/drivers-mcb-fix-resource-leak-in-mcb_probe.patch @@ -0,0 +1,41 @@ +From c60b47aa7f6f2458aa01064ec1e5be03f9743cd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 01:38:49 -0800 +Subject: drivers: mcb: fix resource leak in mcb_probe() + +From: Zhengchao Shao + +[ Upstream commit d7237462561fcd224fa687c56ccb68629f50fc0d ] + +When probe hook function failed in mcb_probe(), it doesn't put the device. +Compiled test only. + +Fixes: 7bc364097a89 ("mcb: Acquire reference to device in probe") +Signed-off-by: Zhengchao Shao +Signed-off-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/9f87de36bfb85158b506cb78c6fc9db3f6a3bad1.1669624063.git.johannes.thumshirn@wdc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/mcb/mcb-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c +index cf128b3471d7..0530db548231 100644 +--- a/drivers/mcb/mcb-core.c ++++ b/drivers/mcb/mcb-core.c +@@ -71,8 +71,10 @@ static int mcb_probe(struct device *dev) + + get_device(dev); + ret = mdrv->probe(mdev, found_id); +- if (ret) ++ if (ret) { + module_put(carrier_mod); ++ put_device(dev); ++ } + + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/drivers-md-md-bitmap-check-the-return-value-of-md_bi.patch b/queue-5.15/drivers-md-md-bitmap-check-the-return-value-of-md_bi.patch new file mode 100644 index 00000000000..e7f1813c2ec --- /dev/null +++ b/queue-5.15/drivers-md-md-bitmap-check-the-return-value-of-md_bi.patch @@ -0,0 +1,65 @@ +From 370f79221d0cb9eb762c8fff0d5975d6ba7c1ed7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 16:33:05 -0700 +Subject: drivers/md/md-bitmap: check the return value of + md_bitmap_get_counter() + +From: Li Zhong + +[ Upstream commit 3bd548e5b819b8c0f2c9085de775c5c7bff9052f ] + +Check the return value of md_bitmap_get_counter() in case it returns +NULL pointer, which will result in a null pointer dereference. + +v2: update the check to include other dereference + +Signed-off-by: Li Zhong +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/md-bitmap.c | 27 +++++++++++++++------------ + 1 file changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c +index 8cc11b1987ec..650bfccd066f 100644 +--- a/drivers/md/md-bitmap.c ++++ b/drivers/md/md-bitmap.c +@@ -2196,20 +2196,23 @@ int md_bitmap_resize(struct bitmap *bitmap, sector_t blocks, + + if (set) { + bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1); +- if (*bmc_new == 0) { +- /* need to set on-disk bits too. */ +- sector_t end = block + new_blocks; +- sector_t start = block >> chunkshift; +- start <<= chunkshift; +- while (start < end) { +- md_bitmap_file_set_bit(bitmap, block); +- start += 1 << chunkshift; ++ if (bmc_new) { ++ if (*bmc_new == 0) { ++ /* need to set on-disk bits too. */ ++ sector_t end = block + new_blocks; ++ sector_t start = block >> chunkshift; ++ ++ start <<= chunkshift; ++ while (start < end) { ++ md_bitmap_file_set_bit(bitmap, block); ++ start += 1 << chunkshift; ++ } ++ *bmc_new = 2; ++ md_bitmap_count_page(&bitmap->counts, block, 1); ++ md_bitmap_set_pending(&bitmap->counts, block); + } +- *bmc_new = 2; +- md_bitmap_count_page(&bitmap->counts, block, 1); +- md_bitmap_set_pending(&bitmap->counts, block); ++ *bmc_new |= NEEDED_MASK; + } +- *bmc_new |= NEEDED_MASK; + if (new_blocks < old_blocks) + old_blocks = new_blocks; + } +-- +2.35.1 + diff --git a/queue-5.15/drivers-net-qlcnic-fix-potential-memory-leak-in-qlcn.patch b/queue-5.15/drivers-net-qlcnic-fix-potential-memory-leak-in-qlcn.patch new file mode 100644 index 00000000000..5a927708276 --- /dev/null +++ b/queue-5.15/drivers-net-qlcnic-fix-potential-memory-leak-in-qlcn.patch @@ -0,0 +1,38 @@ +From db18301c2fb195f16f5e87f2a994e104a17b6afd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 08:54:10 +0000 +Subject: drivers: net: qlcnic: Fix potential memory leak in + qlcnic_sriov_init() + +From: Yuan Can + +[ Upstream commit 01de1123322e4fe1bbd0fcdf0982511b55519c03 ] + +If vp alloc failed in qlcnic_sriov_init(), all previously allocated vp +needs to be freed. + +Fixes: f197a7aa6288 ("qlcnic: VF-PF communication channel implementation") +Signed-off-by: Yuan Can +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +index 42a44c97572a..df9b84f6600f 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +@@ -221,6 +221,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs) + return 0; + + qlcnic_destroy_async_wq: ++ while (i--) ++ kfree(sriov->vf_info[i].vp); + destroy_workqueue(bc->bc_async_wq); + + qlcnic_destroy_trans_wq: +-- +2.35.1 + diff --git a/queue-5.15/drivers-soc-ti-knav_qmss_queue-mark-knav_acc_firmwar.patch b/queue-5.15/drivers-soc-ti-knav_qmss_queue-mark-knav_acc_firmwar.patch new file mode 100644 index 00000000000..73ad8961fac --- /dev/null +++ b/queue-5.15/drivers-soc-ti-knav_qmss_queue-mark-knav_acc_firmwar.patch @@ -0,0 +1,42 @@ +From b8b2d706c4b6843c83cb547ef8207b8effc37902 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Oct 2022 23:32:12 +0800 +Subject: drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static + +From: Chen Jiahao + +[ Upstream commit adf85adc2a7199b41e7a4da083bd17274a3d6969 ] + +There is a sparse warning shown below: + +drivers/soc/ti/knav_qmss_queue.c:70:12: warning: symbol +'knav_acc_firmwares' was not declared. Should it be static? + +Since 'knav_acc_firmwares' is only called within knav_qmss_queue.c, +mark it as static to fix the warning. + +Fixes: 96ee19becc3b ("soc: ti: add firmware file name as part of the driver") +Signed-off-by: Chen Jiahao +Signed-off-by: Nishanth Menon +Link: https://lore.kernel.org/r/20221019153212.72350-1-chenjiahao16@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/knav_qmss_queue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c +index 2ac3856b8d42..920eca809084 100644 +--- a/drivers/soc/ti/knav_qmss_queue.c ++++ b/drivers/soc/ti/knav_qmss_queue.c +@@ -67,7 +67,7 @@ static DEFINE_MUTEX(knav_dev_lock); + * Newest followed by older ones. Search is done from start of the array + * until a firmware file is found. + */ +-const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; ++static const char * const knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; + + static bool device_ready; + bool knav_qmss_device_ready(void) +-- +2.35.1 + diff --git a/queue-5.15/drm-amd-display-fix-array-index-out-of-bound-error-i.patch b/queue-5.15/drm-amd-display-fix-array-index-out-of-bound-error-i.patch new file mode 100644 index 00000000000..db5af285eed --- /dev/null +++ b/queue-5.15/drm-amd-display-fix-array-index-out-of-bound-error-i.patch @@ -0,0 +1,68 @@ +From 9c1176f935ba56bc215c00fdc6c869d1552631be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 15:35:53 -0400 +Subject: drm/amd/display: fix array index out of bound error in bios parser + +From: Aurabindo Pillai + +[ Upstream commit 4fc1ba4aa589ca267468ad23fedef37562227d32 ] + +[Why&How] +Firmware headers dictate that gpio_pin array only has a size of 8. The +count returned from vbios however is greater than 8. + +Fix this by not using array indexing but incrementing the pointer since +gpio_pin definition in atomfirmware.h is hardcoded to size 8 + +Reviewed-by: Martin Leung +Acked-by: Tom Chung +Signed-off-by: Aurabindo Pillai +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../gpu/drm/amd/display/dc/bios/bios_parser2.c | 16 +++++++--------- + 1 file changed, 7 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +index 6dbde74c1e06..1d86fd5610c0 100644 +--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c ++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +@@ -352,6 +352,7 @@ static enum bp_result get_gpio_i2c_info( + uint32_t count = 0; + unsigned int table_index = 0; + bool find_valid = false; ++ struct atom_gpio_pin_assignment *pin; + + if (!info) + return BP_RESULT_BADINPUT; +@@ -379,20 +380,17 @@ static enum bp_result get_gpio_i2c_info( + - sizeof(struct atom_common_table_header)) + / sizeof(struct atom_gpio_pin_assignment); + ++ pin = (struct atom_gpio_pin_assignment *) header->gpio_pin; ++ + for (table_index = 0; table_index < count; table_index++) { +- if (((record->i2c_id & I2C_HW_CAP) == ( +- header->gpio_pin[table_index].gpio_id & +- I2C_HW_CAP)) && +- ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == +- (header->gpio_pin[table_index].gpio_id & +- I2C_HW_ENGINE_ID_MASK)) && +- ((record->i2c_id & I2C_HW_LANE_MUX) == +- (header->gpio_pin[table_index].gpio_id & +- I2C_HW_LANE_MUX))) { ++ if (((record->i2c_id & I2C_HW_CAP) == (pin->gpio_id & I2C_HW_CAP)) && ++ ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) && ++ ((record->i2c_id & I2C_HW_LANE_MUX) == (pin->gpio_id & I2C_HW_LANE_MUX))) { + /* still valid */ + find_valid = true; + break; + } ++ pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment)); + } + + /* If we don't find the entry that we are looking for then +-- +2.35.1 + diff --git a/queue-5.15/drm-amd-display-prevent-memory-leak.patch b/queue-5.15/drm-amd-display-prevent-memory-leak.patch new file mode 100644 index 00000000000..f187f7f2f25 --- /dev/null +++ b/queue-5.15/drm-amd-display-prevent-memory-leak.patch @@ -0,0 +1,73 @@ +From ae62fd81018cad9ea2a57d69a5e6ffb6393cb7a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 17:54:05 +0800 +Subject: drm/amd/display: prevent memory leak + +From: gehao + +[ Upstream commit d232afb1f3417ae8194ccf19ad3a8360e70e104e ] + +In dce6(0,1,4)_create_resource_pool and dce80_create_resource_pool +the allocated memory should be released if construct pool fails. + +Reviewed-by: Rodrigo Siqueira +Signed-off-by: gehao +Signed-off-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c | 3 +++ + drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +index dcfa0a3efa00..bf72d3f60d7f 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c +@@ -1127,6 +1127,7 @@ struct resource_pool *dce60_create_resource_pool( + if (dce60_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1324,6 +1325,7 @@ struct resource_pool *dce61_create_resource_pool( + if (dce61_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1517,6 +1519,7 @@ struct resource_pool *dce64_create_resource_pool( + if (dce64_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +index 725d92e40cd3..52d1f9746e8c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +@@ -1138,6 +1138,7 @@ struct resource_pool *dce80_create_resource_pool( + if (dce80_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +@@ -1337,6 +1338,7 @@ struct resource_pool *dce81_create_resource_pool( + if (dce81_construct(num_virtual_links, dc, pool)) + return &pool->base; + ++ kfree(pool); + BREAK_TO_DEBUGGER(); + return NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/drm-amd-display-use-the-largest-vready_offset-in-pip.patch b/queue-5.15/drm-amd-display-use-the-largest-vready_offset-in-pip.patch new file mode 100644 index 00000000000..7437ed453a5 --- /dev/null +++ b/queue-5.15/drm-amd-display-use-the-largest-vready_offset-in-pip.patch @@ -0,0 +1,141 @@ +From bf69de63f84aee8b374ac58d0570db534de9869a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 17:43:13 -0500 +Subject: drm/amd/display: Use the largest vready_offset in pipe group + +From: Wesley Chalmers + +[ Upstream commit 5842abd985b792a3b13a89b6dae4869b56656c92 ] + +[WHY] +Corruption can occur in LB if vready_offset is not large enough. +DML calculates vready_offset for each pipe, but we currently select the +top pipe's vready_offset, which is not necessarily enough for all pipes +in the group. + +[HOW] +Wherever program_global_sync is currently called, iterate through the +entire pipe group and find the highest vready_offset. + +Reviewed-by: Dillon Varone +Acked-by: Jasdeep Dhillon +Signed-off-by: Wesley Chalmers +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 30 +++++++++++++++++-- + .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 29 ++++++++++++++++-- + 2 files changed, 55 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index 91ab4dbbe1a6..c655d03ef754 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -804,6 +804,32 @@ static void false_optc_underflow_wa( + tg->funcs->clear_optc_underflow(tg); + } + ++static int calculate_vready_offset_for_group(struct pipe_ctx *pipe) ++{ ++ struct pipe_ctx *other_pipe; ++ int vready_offset = pipe->pipe_dlg_param.vready_offset; ++ ++ /* Always use the largest vready_offset of all connected pipes */ ++ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ ++ return vready_offset; ++} ++ + enum dc_status dcn10_enable_stream_timing( + struct pipe_ctx *pipe_ctx, + struct dc_state *context, +@@ -838,7 +864,7 @@ enum dc_status dcn10_enable_stream_timing( + pipe_ctx->stream_res.tg->funcs->program_timing( + pipe_ctx->stream_res.tg, + &stream->timing, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width, +@@ -2776,7 +2802,7 @@ void dcn10_program_pipe( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +index 58eea3aa3bfc..bf2a8f53694b 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +@@ -1564,6 +1564,31 @@ static void dcn20_update_dchubp_dpp( + hubp->funcs->set_blank(hubp, false); + } + ++static int calculate_vready_offset_for_group(struct pipe_ctx *pipe) ++{ ++ struct pipe_ctx *other_pipe; ++ int vready_offset = pipe->pipe_dlg_param.vready_offset; ++ ++ /* Always use the largest vready_offset of all connected pipes */ ++ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) { ++ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset) ++ vready_offset = other_pipe->pipe_dlg_param.vready_offset; ++ } ++ ++ return vready_offset; ++} + + static void dcn20_program_pipe( + struct dc *dc, +@@ -1582,7 +1607,7 @@ static void dcn20_program_pipe( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); +@@ -1875,7 +1900,7 @@ bool dcn20_update_bandwidth( + + pipe_ctx->stream_res.tg->funcs->program_global_sync( + pipe_ctx->stream_res.tg, +- pipe_ctx->pipe_dlg_param.vready_offset, ++ calculate_vready_offset_for_group(pipe_ctx), + pipe_ctx->pipe_dlg_param.vstartup_start, + pipe_ctx->pipe_dlg_param.vupdate_offset, + pipe_ctx->pipe_dlg_param.vupdate_width); +-- +2.35.1 + diff --git a/queue-5.15/drm-amd-pm-smu11-baco-is-supported-when-it-s-in-baco.patch b/queue-5.15/drm-amd-pm-smu11-baco-is-supported-when-it-s-in-baco.patch new file mode 100644 index 00000000000..b9afcec58cf --- /dev/null +++ b/queue-5.15/drm-amd-pm-smu11-baco-is-supported-when-it-s-in-baco.patch @@ -0,0 +1,43 @@ +From 2d8fe4b4f85bb2a4bf9121477af2d93876c36390 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 17:33:24 +0800 +Subject: drm/amd/pm/smu11: BACO is supported when it's in BACO state + +From: Guchun Chen + +[ Upstream commit 6dca7efe6e522bf213c7dab691fa580d82f48f74 ] + +Return true early if ASIC is in BACO state already, no need +to talk to SMU. It can fix the issue that driver was not +calling BACO exit at all in runtime pm resume, and a timing +issue leading to a PCI AER error happened eventually. + +Fixes: 8795e182b02d ("PCI/portdrv: Don't disable AER reporting in get_port_device_capability()") +Suggested-by: Lijo Lazar +Signed-off-by: Guchun Chen +Reviewed-by: Lijo Lazar +Reviewed-by: Evan Quan +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +index 614c3d049514..83fa3d20a1d5 100644 +--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c ++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +@@ -1595,6 +1595,10 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu) + if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) + return false; + ++ /* return true if ASIC is in BACO state already */ ++ if (smu_v11_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) ++ return true; ++ + /* Arcturus does not support this bit mask */ + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && + !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) +-- +2.35.1 + diff --git a/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak-in-amdgpu_at.patch b/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak-in-amdgpu_at.patch new file mode 100644 index 00000000000..762411dde1f --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak-in-amdgpu_at.patch @@ -0,0 +1,40 @@ +From 0cdaa0ca235d19dfdd7e3af7178cc7aff6c72add Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:30:43 +0800 +Subject: drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios() + +From: Xiongfeng Wang + +[ Upstream commit ca54639c7752edf1304d92ff4d0c049d4efc9ba0 ] + +As comment of pci_get_class() says, it returns a pci_device with its +refcount increased and decreased the refcount for the input parameter +@from if it is not NULL. + +If we break the loop in amdgpu_atrm_get_bios() with 'pdev' not NULL, we +need to call pci_dev_put() to decrease the refcount. Add the missing +pci_dev_put() to avoid refcount leak. + +Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +index 27b19503773b..71354f505b84 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +@@ -317,6 +317,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) + + if (!found) + return false; ++ pci_dev_put(pdev); + + adev->bios = kmalloc(size, GFP_KERNEL); + if (!adev->bios) { +-- +2.35.1 + diff --git a/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak.patch b/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak.patch new file mode 100644 index 00000000000..05338949333 --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-pci-device-refcount-leak.patch @@ -0,0 +1,58 @@ +From c9d457b554b5c93d1b811ccc63a928aea163fc83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 23:00:03 +0800 +Subject: drm/amdgpu: fix pci device refcount leak + +From: Yang Yingliang + +[ Upstream commit b85e285e3d6352b02947fc1b72303673dfacb0aa ] + +As comment of pci_get_domain_bus_and_slot() says, it returns +a pci device with refcount increment, when finish using it, +the caller must decrement the reference count by calling +pci_dev_put(). + +So before returning from amdgpu_device_resume|suspend_display_audio(), +pci_dev_put() is called to avoid refcount leak. + +Fixes: 3f12acc8d6d4 ("drm/amdgpu: put the audio codec into suspend state before gpu reset V3") +Reviewed-by: Evan Quan +Signed-off-by: Yang Yingliang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +index 36cc89f56cea..0d998bc830c2 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +@@ -4902,6 +4902,8 @@ static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) + pm_runtime_enable(&(p->dev)); + pm_runtime_resume(&(p->dev)); + } ++ ++ pci_dev_put(p); + } + + static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) +@@ -4940,6 +4942,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) + + if (expires < ktime_get_mono_fast_ns()) { + dev_warn(adev->dev, "failed to suspend display audio\n"); ++ pci_dev_put(p); + /* TODO: abort the succeeding gpu reset? */ + return -ETIMEDOUT; + } +@@ -4947,6 +4950,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev) + + pm_runtime_disable(&(p->dev)); + ++ pci_dev_put(p); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-odn_edit_.patch b/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-odn_edit_.patch new file mode 100644 index 00000000000..c4425145292 --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-odn_edit_.patch @@ -0,0 +1,78 @@ +From af01a774f80da95d9da33b7191716d88341faa40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 08:25:40 -0700 +Subject: drm/amdgpu: Fix type of second parameter in odn_edit_dpm_table() + callback + +From: Nathan Chancellor + +[ Upstream commit e4d0ef752081e7aa6ffb7ccac11c499c732a2e05 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/gpu/drm/amd/amdgpu/../pm/swsmu/amdgpu_smu.c:3008:29: error: incompatible function pointer types initializing 'int (*)(void *, uint32_t, long *, uint32_t)' (aka 'int (*)(void *, unsigned int, long *, unsigned int)') with an expression of type 'int (void *, enum PP_OD_DPM_TABLE_COMMAND, long *, uint32_t)' (aka 'int (void *, enum PP_OD_DPM_TABLE_COMMAND, long *, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] + .odn_edit_dpm_table = smu_od_edit_dpm_table, + ^~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + +There are only two implementations of ->odn_edit_dpm_table() in 'struct +amd_pm_funcs': smu_od_edit_dpm_table() and pp_odn_edit_dpm_table(). One +has a second parameter type of 'enum PP_OD_DPM_TABLE_COMMAND' and the +other uses 'u32'. Ultimately, smu_od_edit_dpm_table() calls +->od_edit_dpm_table() from 'struct pptable_funcs' and +pp_odn_edit_dpm_table() calls ->odn_edit_dpm_table() from 'struct +pp_hwmgr_func', which both have a second parameter type of 'enum +PP_OD_DPM_TABLE_COMMAND'. + +Update the type parameter in both the prototype in 'struct amd_pm_funcs' +and pp_odn_edit_dpm_table() to 'enum PP_OD_DPM_TABLE_COMMAND', which +cleans up the warning. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reported-by: Sami Tolvanen +Reviewed-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/include/kgd_pp_interface.h | 3 ++- + drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +index bac15c466733..6e27c8b16391 100644 +--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h ++++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h +@@ -341,7 +341,8 @@ struct amd_pm_funcs { + int (*get_power_profile_mode)(void *handle, char *buf); + int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); +- int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); ++ int (*odn_edit_dpm_table)(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size); + int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state); + int (*smu_i2c_bus_access)(void *handle, bool acquire); + int (*gfx_state_change_set)(void *handle, uint32_t state); +diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +index 321215003643..0f5930e797bd 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +@@ -924,7 +924,8 @@ static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, u + return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size); + } + +-static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) ++static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type, ++ long *input, uint32_t size) + { + struct pp_hwmgr *hwmgr = handle; + +-- +2.35.1 + diff --git a/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-trans_msg.patch b/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-trans_msg.patch new file mode 100644 index 00000000000..891c29e5f95 --- /dev/null +++ b/queue-5.15/drm-amdgpu-fix-type-of-second-parameter-in-trans_msg.patch @@ -0,0 +1,66 @@ +From d8a8b84e2c9fd923aa58feb3ce585d14b1c99df7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 08:25:39 -0700 +Subject: drm/amdgpu: Fix type of second parameter in trans_msg() callback + +From: Nathan Chancellor + +[ Upstream commit f0d0f1087333714ee683cc134a95afe331d7ddd9 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c:412:15: error: incompatible function pointer types initializing 'void (*)(struct amdgpu_device *, u32, u32, u32, u32)' (aka 'void (*)(struct amdgpu_device *, unsigned int, unsigned int, unsigned int, unsigned int)') with an expression of type 'void (struct amdgpu_device *, enum idh_request, u32, u32, u32)' (aka 'void (struct amdgpu_device *, enum idh_request, unsigned int, unsigned int, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] + .trans_msg = xgpu_ai_mailbox_trans_msg, + ^~~~~~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + + drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c:435:15: error: incompatible function pointer types initializing 'void (*)(struct amdgpu_device *, u32, u32, u32, u32)' (aka 'void (*)(struct amdgpu_device *, unsigned int, unsigned int, unsigned int, unsigned int)') with an expression of type 'void (struct amdgpu_device *, enum idh_request, u32, u32, u32)' (aka 'void (struct amdgpu_device *, enum idh_request, unsigned int, unsigned int, unsigned int)') [-Werror,-Wincompatible-function-pointer-types-strict] + .trans_msg = xgpu_nv_mailbox_trans_msg, + ^~~~~~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + +The type of the second parameter in the prototype should be 'enum +idh_request' instead of 'u32'. Update it to clear up the warnings. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reported-by: Sami Tolvanen +Reviewed-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +index ce31d4fdee93..4af3610f4a82 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +@@ -62,6 +62,8 @@ struct amdgpu_vf_error_buffer { + uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; + }; + ++enum idh_request; ++ + /** + * struct amdgpu_virt_ops - amdgpu device virt operations + */ +@@ -71,7 +73,8 @@ struct amdgpu_virt_ops { + int (*req_init_data)(struct amdgpu_device *adev); + int (*reset_gpu)(struct amdgpu_device *adev); + int (*wait_reset)(struct amdgpu_device *adev); +- void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); ++ void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req, ++ u32 data1, u32 data2, u32 data3); + }; + + /* +-- +2.35.1 + diff --git a/queue-5.15/drm-amdgpu-powerplay-psm-fix-memory-leak-in-power-st.patch b/queue-5.15/drm-amdgpu-powerplay-psm-fix-memory-leak-in-power-st.patch new file mode 100644 index 00000000000..98401658753 --- /dev/null +++ b/queue-5.15/drm-amdgpu-powerplay-psm-fix-memory-leak-in-power-st.patch @@ -0,0 +1,41 @@ +From 5242f1e3d9d0420ba60051d68c7b4eec07c7e794 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 21:53:57 -0300 +Subject: drm/amdgpu/powerplay/psm: Fix memory leak in power state init + +From: Rafael Mendonca + +[ Upstream commit 8f8033d5663b18e6efb33feb61f2287a04605ab5 ] + +Commit 902bc65de0b3 ("drm/amdgpu/powerplay/psm: return an error in power +state init") made the power state init function return early in case of +failure to get an entry from the powerplay table, but it missed to clean up +the allocated memory for the current power state before returning. + +Fixes: 902bc65de0b3 ("drm/amdgpu/powerplay/psm: return an error in power state init") +Reviewed-by: Evan Quan +Signed-off-by: Rafael Mendonca +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +index 67d7da0b6fed..1d829402cd2e 100644 +--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c ++++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c +@@ -75,8 +75,10 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr) + for (i = 0; i < table_entries; i++) { + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + if (result) { ++ kfree(hwmgr->current_ps); + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); ++ hwmgr->current_ps = NULL; + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + return -EINVAL; +-- +2.35.1 + diff --git a/queue-5.15/drm-amdkfd-fix-memory-leakage.patch b/queue-5.15/drm-amdkfd-fix-memory-leakage.patch new file mode 100644 index 00000000000..ebbfad4e247 --- /dev/null +++ b/queue-5.15/drm-amdkfd-fix-memory-leakage.patch @@ -0,0 +1,38 @@ +From 4a4192ef2f489c210e543a452800d2275527b59b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 23:02:54 -0500 +Subject: drm/amdkfd: Fix memory leakage + +From: Konstantin Meskhidze + +[ Upstream commit 75818afff631e1ea785a82c3e8bb82eb0dee539c ] + +This patch fixes potential memory leakage and seg fault +in _gpuvm_import_dmabuf() function + +Fixes: d4ec4bdc0bd5 ("drm/amdkfd: Allow access for mmapping KFD BOs") +Signed-off-by: Konstantin Meskhidze +Signed-off-by: Felix Kuehling +Reviewed-by: Felix Kuehling +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 477ab3551177..34303dd3ada9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1910,7 +1910,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, + + ret = drm_vma_node_allow(&obj->vma_node, drm_priv); + if (ret) { +- kfree(mem); ++ kfree(*mem); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/drm-bridge-adv7533-remove-dynamic-lane-switching-fro.patch b/queue-5.15/drm-bridge-adv7533-remove-dynamic-lane-switching-fro.patch new file mode 100644 index 00000000000..3e02d22f270 --- /dev/null +++ b/queue-5.15/drm-bridge-adv7533-remove-dynamic-lane-switching-fro.patch @@ -0,0 +1,228 @@ +From db085935b097ee64e4facafed5df6b741a48e2ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Oct 2022 14:10:49 -0700 +Subject: drm/bridge: adv7533: remove dynamic lane switching from adv7533 + bridge + +From: Abhinav Kumar + +[ Upstream commit 9a0cdcd6649b76f0b7ceec0e55b0a718321e34d3 ] + +adv7533 bridge tries to dynamically switch lanes based on the +mode by detaching and attaching the mipi dsi device. + +This approach is incorrect because this method of dynamic switch of +detaching and attaching the mipi dsi device also results in removing +and adding the component which is not necessary. + +This approach is also prone to deadlocks. So for example, on the +db410c whenever this path is executed with lockdep enabled, +this results in a deadlock due to below ordering of locks. + +-> #1 (crtc_ww_class_acquire){+.+.}-{0:0}: + lock_acquire+0x6c/0x90 + drm_modeset_acquire_init+0xf4/0x150 + drmm_mode_config_init+0x220/0x770 + msm_drm_bind+0x13c/0x654 + try_to_bring_up_aggregate_device+0x164/0x1d0 + __component_add+0xa8/0x174 + component_add+0x18/0x2c + dsi_dev_attach+0x24/0x30 + dsi_host_attach+0x98/0x14c + devm_mipi_dsi_attach+0x38/0xb0 + adv7533_attach_dsi+0x8c/0x110 + adv7511_probe+0x5a0/0x930 + i2c_device_probe+0x30c/0x350 + really_probe.part.0+0x9c/0x2b0 + __driver_probe_device+0x98/0x144 + driver_probe_device+0xac/0x14c + __device_attach_driver+0xbc/0x124 + bus_for_each_drv+0x78/0xd0 + __device_attach+0xa8/0x1c0 + device_initial_probe+0x18/0x24 + bus_probe_device+0xa0/0xac + deferred_probe_work_func+0x90/0xd0 + process_one_work+0x28c/0x6b0 + worker_thread+0x240/0x444 + kthread+0x110/0x114 + ret_from_fork+0x10/0x20 + +-> #0 (component_mutex){+.+.}-{3:3}: + __lock_acquire+0x1280/0x20ac + lock_acquire.part.0+0xe0/0x230 + lock_acquire+0x6c/0x90 + __mutex_lock+0x84/0x400 + mutex_lock_nested+0x3c/0x70 + component_del+0x34/0x170 + dsi_dev_detach+0x24/0x30 + dsi_host_detach+0x20/0x64 + mipi_dsi_detach+0x2c/0x40 + adv7533_mode_set+0x64/0x90 + adv7511_bridge_mode_set+0x210/0x214 + drm_bridge_chain_mode_set+0x5c/0x84 + crtc_set_mode+0x18c/0x1dc + drm_atomic_helper_commit_modeset_disables+0x40/0x50 + msm_atomic_commit_tail+0x1d0/0x6e0 + commit_tail+0xa4/0x180 + drm_atomic_helper_commit+0x178/0x3b0 + drm_atomic_commit+0xa4/0xe0 + drm_client_modeset_commit_atomic+0x228/0x284 + drm_client_modeset_commit_locked+0x64/0x1d0 + drm_client_modeset_commit+0x34/0x60 + drm_fb_helper_lastclose+0x74/0xcc + drm_lastclose+0x3c/0x80 + drm_release+0xfc/0x114 + __fput+0x70/0x224 + ____fput+0x14/0x20 + task_work_run+0x88/0x1a0 + do_exit+0x350/0xa50 + do_group_exit+0x38/0xa4 + __wake_up_parent+0x0/0x34 + invoke_syscall+0x48/0x114 + el0_svc_common.constprop.0+0x60/0x11c + do_el0_svc+0x30/0xc0 + el0_svc+0x58/0x100 + el0t_64_sync_handler+0x1b0/0x1bc + el0t_64_sync+0x18c/0x190 + +Due to above reasons, remove the dynamic lane switching +code from adv7533 bridge chip and filter out the modes +which would need different number of lanes as compared +to the initialization time using the mode_valid callback. + +This can be potentially re-introduced by using the pre_enable() +callback but this needs to be evaluated first whether such an +approach will work so this will be done with a separate change. + +changes since RFC: + - Fix commit text and add TODO comment + +changes in v2: + - Fix checkpatch formatting errors + +Fixes: 62b2f026cd8e ("drm/bridge: adv7533: Change number of DSI lanes dynamically") +Closes: https://gitlab.freedesktop.org/drm/msm/-/issues/16 +Suggested-by: Dmitry Baryshkov +Signed-off-by: Abhinav Kumar +Reviewed-by: Robert Foss +Link: https://lore.kernel.org/r/1661797363-7564-1-git-send-email-quic_abhinavk@quicinc.com +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/1665522649-3423-1-git-send-email-quic_abhinavk@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/adv7511/adv7511.h | 3 ++- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 18 ++++++++++---- + drivers/gpu/drm/bridge/adv7511/adv7533.c | 25 ++++++++++---------- + 3 files changed, 29 insertions(+), 17 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h +index aeeb09a27202..fdd8e3d3232e 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h +@@ -395,7 +395,8 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) + + void adv7533_dsi_power_on(struct adv7511 *adv); + void adv7533_dsi_power_off(struct adv7511 *adv); +-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode); ++enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv, ++ const struct drm_display_mode *mode); + int adv7533_patch_registers(struct adv7511 *adv); + int adv7533_patch_cec_registers(struct adv7511 *adv); + int adv7533_attach_dsi(struct adv7511 *adv); +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 3dc551d223d6..44762116aac9 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -697,7 +697,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector) + } + + static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511, +- struct drm_display_mode *mode) ++ const struct drm_display_mode *mode) + { + if (mode->clock > 165000) + return MODE_CLOCK_HIGH; +@@ -791,9 +791,6 @@ static void adv7511_mode_set(struct adv7511 *adv7511, + regmap_update_bits(adv7511->regmap, 0x17, + 0x60, (vsync_polarity << 6) | (hsync_polarity << 5)); + +- if (adv7511->type == ADV7533 || adv7511->type == ADV7535) +- adv7533_mode_set(adv7511, adj_mode); +- + drm_mode_copy(&adv7511->curr_mode, adj_mode); + + /* +@@ -913,6 +910,18 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge, + adv7511_mode_set(adv, mode, adj_mode); + } + ++static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ struct adv7511 *adv = bridge_to_adv7511(bridge); ++ ++ if (adv->type == ADV7533 || adv->type == ADV7535) ++ return adv7533_mode_valid(adv, mode); ++ else ++ return adv7511_mode_valid(adv, mode); ++} ++ + static int adv7511_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) + { +@@ -963,6 +972,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = { + .enable = adv7511_bridge_enable, + .disable = adv7511_bridge_disable, + .mode_set = adv7511_bridge_mode_set, ++ .mode_valid = adv7511_bridge_mode_valid, + .attach = adv7511_bridge_attach, + .detect = adv7511_bridge_detect, + .get_edid = adv7511_bridge_get_edid, +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c +index 59d718bde8c4..7eda12f338a1 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c +@@ -100,26 +100,27 @@ void adv7533_dsi_power_off(struct adv7511 *adv) + regmap_write(adv->regmap_cec, 0x27, 0x0b); + } + +-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode) ++enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv, ++ const struct drm_display_mode *mode) + { ++ int lanes; + struct mipi_dsi_device *dsi = adv->dsi; +- int lanes, ret; +- +- if (adv->num_dsi_lanes != 4) +- return; + + if (mode->clock > 80000) + lanes = 4; + else + lanes = 3; + +- if (lanes != dsi->lanes) { +- mipi_dsi_detach(dsi); +- dsi->lanes = lanes; +- ret = mipi_dsi_attach(dsi); +- if (ret) +- dev_err(&dsi->dev, "failed to change host lanes\n"); +- } ++ /* ++ * TODO: add support for dynamic switching of lanes ++ * by using the bridge pre_enable() op . Till then filter ++ * out the modes which shall need different number of lanes ++ * than what was configured in the device tree. ++ */ ++ if (lanes != dsi->lanes) ++ return MODE_BAD; ++ ++ return MODE_OK; + } + + int adv7533_patch_registers(struct adv7511 *adv) +-- +2.35.1 + diff --git a/queue-5.15/drm-etnaviv-add-missing-quirks-for-gc300.patch b/queue-5.15/drm-etnaviv-add-missing-quirks-for-gc300.patch new file mode 100644 index 00000000000..91c978f41da --- /dev/null +++ b/queue-5.15/drm-etnaviv-add-missing-quirks-for-gc300.patch @@ -0,0 +1,53 @@ +From fc1edd1755b9b1d40c6baa92e7a975dc9214725b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Sep 2022 13:29:38 -0700 +Subject: drm/etnaviv: add missing quirks for GC300 + +From: Doug Brown + +[ Upstream commit cc7d3fb446a91f24978a6aa59cbb578f92e22242 ] + +The GC300's features register doesn't specify that a 2D pipe is +available, and like the GC600, its idle register reports zero bits where +modules aren't present. + +Signed-off-by: Doug Brown +Reviewed-by: Christian Gmeiner +Signed-off-by: Lucas Stach +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +index cc5b07f86346..e8ff70be449a 100644 +--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c ++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +@@ -416,6 +416,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) + if (gpu->identity.model == chipModel_GC700) + gpu->identity.features &= ~chipFeatures_FAST_CLEAR; + ++ /* These models/revisions don't have the 2D pipe bit */ ++ if ((gpu->identity.model == chipModel_GC500 && ++ gpu->identity.revision <= 2) || ++ gpu->identity.model == chipModel_GC300) ++ gpu->identity.features |= chipFeatures_PIPE_2D; ++ + if ((gpu->identity.model == chipModel_GC500 && + gpu->identity.revision < 2) || + (gpu->identity.model == chipModel_GC300 && +@@ -449,8 +455,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) + gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5); + } + +- /* GC600 idle register reports zero bits where modules aren't present */ +- if (gpu->identity.model == chipModel_GC600) ++ /* GC600/300 idle register reports zero bits where modules aren't present */ ++ if (gpu->identity.model == chipModel_GC600 || ++ gpu->identity.model == chipModel_GC300) + gpu->idle_mask = VIVS_HI_IDLE_STATE_TX | + VIVS_HI_IDLE_STATE_RA | + VIVS_HI_IDLE_STATE_SE | +-- +2.35.1 + diff --git a/queue-5.15/drm-fourcc-add-packed-10bit-yuv-4-2-0-format.patch b/queue-5.15/drm-fourcc-add-packed-10bit-yuv-4-2-0-format.patch new file mode 100644 index 00000000000..eac1b35fd16 --- /dev/null +++ b/queue-5.15/drm-fourcc-add-packed-10bit-yuv-4-2-0-format.patch @@ -0,0 +1,71 @@ +From 85367eee9b0b4ce4b57b36eea26c0a14ac42ace9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Dec 2021 10:17:37 +0100 +Subject: drm/fourcc: Add packed 10bit YUV 4:2:0 format + +From: Dave Stevenson + +[ Upstream commit 006ea1b5822f9019bd722ffc6242bc0880879e3d ] + +Adds a format that is 3 10bit YUV 4:2:0 samples packed into +a 32bit word (with 2 spare bits). + +Supported on Broadcom BCM2711 chips. + +Signed-off-by: Dave Stevenson +Signed-off-by: Maxime Ripard +Acked-by: Thomas Zimmermann +Link: https://lore.kernel.org/r/20211215091739.135042-2-maxime@cerno.tech +Stable-dep-of: b230555f3257 ("drm/fourcc: Fix vsub/hsub for Q410 and Q401") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_fourcc.c | 3 +++ + include/uapi/drm/drm_fourcc.h | 11 +++++++++++ + 2 files changed, 14 insertions(+) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index eda832f9200d..aa747111476f 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -266,6 +266,9 @@ const struct drm_format_info *__drm_format_info(u32 format) + .num_planes = 3, .char_per_block = { 2, 2, 2 }, + .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, + .vsub = 0, .is_yuv = true }, ++ { .format = DRM_FORMAT_P030, .depth = 0, .num_planes = 2, ++ .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 }, ++ .hsub = 2, .vsub = 2, .is_yuv = true}, + }; + + unsigned int i; +diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h +index 808c73c52820..a50e4646bd6d 100644 +--- a/include/uapi/drm/drm_fourcc.h ++++ b/include/uapi/drm/drm_fourcc.h +@@ -308,6 +308,13 @@ extern "C" { + */ + #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6') /* 2x2 subsampled Cr:Cb plane 16 bits per channel */ + ++/* 2 plane YCbCr420. ++ * 3 10 bit components and 2 padding bits packed into 4 bytes. ++ * index 0 = Y plane, [31:0] x:Y2:Y1:Y0 2:10:10:10 little endian ++ * index 1 = Cr:Cb plane, [63:0] x:Cr2:Cb2:Cr1:x:Cb1:Cr0:Cb0 [2:10:10:10:2:10:10:10] little endian ++ */ ++#define DRM_FORMAT_P030 fourcc_code('P', '0', '3', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel packed */ ++ + /* 3 plane non-subsampled (444) YCbCr + * 16 bits per component, but only 10 bits are used and 6 bits are padded + * index 0: Y plane, [15:0] Y:x [10:6] little endian +@@ -842,6 +849,10 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier) + * and UV. Some SAND-using hardware stores UV in a separate tiled + * image from Y to reduce the column height, which is not supported + * with these modifiers. ++ * ++ * The DRM_FORMAT_MOD_BROADCOM_SAND128_COL_HEIGHT modifier is also ++ * supported for DRM_FORMAT_P030 where the columns remain as 128 bytes ++ * wide, but as this is a 10 bpp format that translates to 96 pixels. + */ + + #define DRM_FORMAT_MOD_BROADCOM_SAND32_COL_HEIGHT(v) \ +-- +2.35.1 + diff --git a/queue-5.15/drm-fourcc-fix-vsub-hsub-for-q410-and-q401.patch b/queue-5.15/drm-fourcc-fix-vsub-hsub-for-q410-and-q401.patch new file mode 100644 index 00000000000..8deea7ebfc5 --- /dev/null +++ b/queue-5.15/drm-fourcc-fix-vsub-hsub-for-q410-and-q401.patch @@ -0,0 +1,48 @@ +From 0fd040721c84762be883e3334610e9d72903e1c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 15:43:06 +0100 +Subject: drm/fourcc: Fix vsub/hsub for Q410 and Q401 + +From: Brian Starkey + +[ Upstream commit b230555f3257f197dd98641ef6ebaf778b52dd51 ] + +These formats are not subsampled, but that means hsub and vsub should be +1, not 0. + +Fixes: 94b292b27734 ("drm: drm_fourcc: add NV15, Q410, Q401 YUV formats") +Reported-by: George Kennedy +Reported-by: butt3rflyh4ck +Signed-off-by: Brian Starkey +Reviewed-by: Liviu Dudau +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20220913144306.17279-1-brian.starkey@arm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_fourcc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c +index aa747111476f..32ee023aed26 100644 +--- a/drivers/gpu/drm/drm_fourcc.c ++++ b/drivers/gpu/drm/drm_fourcc.c +@@ -260,12 +260,12 @@ const struct drm_format_info *__drm_format_info(u32 format) + .vsub = 2, .is_yuv = true }, + { .format = DRM_FORMAT_Q410, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, +- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +- .vsub = 0, .is_yuv = true }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_Q401, .depth = 0, + .num_planes = 3, .char_per_block = { 2, 2, 2 }, +- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0, +- .vsub = 0, .is_yuv = true }, ++ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1, ++ .vsub = 1, .is_yuv = true }, + { .format = DRM_FORMAT_P030, .depth = 0, .num_planes = 2, + .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 }, + .hsub = 2, .vsub = 2, .is_yuv = true}, +-- +2.35.1 + diff --git a/queue-5.15/drm-fsl-dcu-fix-return-type-of-fsl_dcu_drm_connector.patch b/queue-5.15/drm-fsl-dcu-fix-return-type-of-fsl_dcu_drm_connector.patch new file mode 100644 index 00000000000..f824e3b97bb --- /dev/null +++ b/queue-5.15/drm-fsl-dcu-fix-return-type-of-fsl_dcu_drm_connector.patch @@ -0,0 +1,57 @@ +From b94a54b6071ccf136ad56e7616ba3a68cfcf130e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 08:42:15 -0700 +Subject: drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid() + +From: Nathan Chancellor + +[ Upstream commit 96d845a67b7e406cfed7880a724c8ca6121e022e ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c:74:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_connector *, struct drm_display_mode *)' with an expression of type 'int (struct drm_connector *, struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .mode_valid = fsl_dcu_drm_connector_mode_valid, + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + +->mode_valid() in 'struct drm_connector_helper_funcs' expects a return +type of 'enum drm_mode_status', not 'int'. Adjust the return type of +fsl_dcu_drm_connector_mode_valid() to match the prototype's to resolve +the warning and CFI failure. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reported-by: Sami Tolvanen +Signed-off-by: Nathan Chancellor +Reviewed-by: Kees Cook +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20221102154215.78059-1-nathan@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +index 4d4a715b429d..2c2b92324a2e 100644 +--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c ++++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +@@ -60,8 +60,9 @@ static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector) + return drm_panel_get_modes(fsl_connector->panel, connector); + } + +-static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + if (mode->hdisplay & 0xf) + return MODE_ERROR; +-- +2.35.1 + diff --git a/queue-5.15/drm-mediatek-fix-return-type-of-mtk_hdmi_bridge_mode.patch b/queue-5.15/drm-mediatek-fix-return-type-of-mtk_hdmi_bridge_mode.patch new file mode 100644 index 00000000000..e50f05154f4 --- /dev/null +++ b/queue-5.15/drm-mediatek-fix-return-type-of-mtk_hdmi_bridge_mode.patch @@ -0,0 +1,59 @@ +From d3e3175a6dc7bfcd81aa7852152be99db6d6eb3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 08:47:12 -0700 +Subject: drm/mediatek: Fix return type of mtk_hdmi_bridge_mode_valid() + +From: Nathan Chancellor + +[ Upstream commit 890d637523eec9d730e3885532fa1228ba678880 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/gpu/drm/mediatek/mtk_hdmi.c:1407:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_bridge *, const struct drm_display_info *, const struct drm_display_mode *)' with an expression of type 'int (struct drm_bridge *, const struct drm_display_info *, const struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .mode_valid = mtk_hdmi_bridge_mode_valid, + ^~~~~~~~~~~~~~~~~~~~~~~~~~ + 1 error generated. + +->mode_valid() in 'struct drm_bridge_funcs' expects a return type of +'enum drm_mode_status', not 'int'. Adjust the return type of +mtk_hdmi_bridge_mode_valid() to match the prototype's to resolve the +warning and CFI failure. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reported-by: Sami Tolvanen +Signed-off-by: Nathan Chancellor +Reviewed-by: Kees Cook +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_hdmi.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c +index 3196189429bc..7613b0fa2be6 100644 +--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c ++++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c +@@ -1203,9 +1203,10 @@ static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi) + return mtk_hdmi_update_plugged_status(hdmi); + } + +-static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, +- const struct drm_display_info *info, +- const struct drm_display_mode *mode) ++static enum drm_mode_status ++mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) + { + struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge); + struct drm_bridge *next_bridge; +-- +2.35.1 + diff --git a/queue-5.15/drm-mediatek-modify-dpi-power-on-off-sequence.patch b/queue-5.15/drm-mediatek-modify-dpi-power-on-off-sequence.patch new file mode 100644 index 00000000000..a61e6ea879b --- /dev/null +++ b/queue-5.15/drm-mediatek-modify-dpi-power-on-off-sequence.patch @@ -0,0 +1,66 @@ +From 7aaa6db1eedad3ead5fc7f58cb28d80a78d4c9fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 18:00:59 +0800 +Subject: drm/mediatek: Modify dpi power on/off sequence. + +From: Xinlei Lee + +[ Upstream commit ff446c0f6290185cefafe3b376bb86063a3a9f6a ] + +Modify dpi power on/off sequence so that the first gpio operation will +take effect. + +Fixes: 6bd4763fd532 ("drm/mediatek: set dpi pin mode to gpio low to avoid leakage current") +Signed-off-by: Xinlei Lee +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/mediatek/mtk_dpi.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c +index 41c783349321..94c6bd3b0082 100644 +--- a/drivers/gpu/drm/mediatek/mtk_dpi.c ++++ b/drivers/gpu/drm/mediatek/mtk_dpi.c +@@ -387,9 +387,6 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi) + if (--dpi->refcount != 0) + return; + +- if (dpi->pinctrl && dpi->pins_gpio) +- pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); +- + mtk_dpi_disable(dpi); + clk_disable_unprepare(dpi->pixel_clk); + clk_disable_unprepare(dpi->engine_clk); +@@ -414,9 +411,6 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi) + goto err_pixel; + } + +- if (dpi->pinctrl && dpi->pins_dpi) +- pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); +- + return 0; + + err_pixel: +@@ -630,12 +624,18 @@ static void mtk_dpi_bridge_disable(struct drm_bridge *bridge) + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + + mtk_dpi_power_off(dpi); ++ ++ if (dpi->pinctrl && dpi->pins_gpio) ++ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); + } + + static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) + { + struct mtk_dpi *dpi = bridge_to_dpi(bridge); + ++ if (dpi->pinctrl && dpi->pins_dpi) ++ pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); ++ + mtk_dpi_power_on(dpi); + mtk_dpi_set_display_mode(dpi, &dpi->mode); + mtk_dpi_enable(dpi); +-- +2.35.1 + diff --git a/queue-5.15/drm-msm-a6xx-fix-speed-bin-detection-vs-probe-defer.patch b/queue-5.15/drm-msm-a6xx-fix-speed-bin-detection-vs-probe-defer.patch new file mode 100644 index 00000000000..77c1c1cec29 --- /dev/null +++ b/queue-5.15/drm-msm-a6xx-fix-speed-bin-detection-vs-probe-defer.patch @@ -0,0 +1,73 @@ +From 8513f7d125658bc95881967dc41338646d170e51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 07:46:34 -0800 +Subject: drm/msm/a6xx: Fix speed-bin detection vs probe-defer + +From: Rob Clark + +[ Upstream commit f6d1918794ef92b4e26b80c3d40365347b76b1fd ] + +If we get an error (other than -ENOENT) we need to propagate that up the +stack. Otherwise if the nvmem driver hasn't probed yet, we'll end up +end up claiming that we support all the OPPs which is not likely to be +true (and on some generations impossible to be true, ie. if there are +conflicting OPPs). + +v2: Update commit msg, gc unused label, etc +v3: Add previously missing \n's + +Fixes: fe7952c629da ("drm/msm: Add speed-bin support to a618 gpu") +Signed-off-by: Rob Clark +Reviewed-by: Douglas Anderson +Reviewed-by: Akhil P Oommen +Patchwork: https://patchwork.freedesktop.org/patch/511690/ +Link: https://lore.kernel.org/r/20221115154637.1613968-1-robdclark@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +index c0dec5b919d4..2d07c02c59f1 100644 +--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c ++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +@@ -1746,7 +1746,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) + + if (val == UINT_MAX) { + DRM_DEV_ERROR(dev, +- "missing support for speed-bin: %u. Some OPPs may not be supported by hardware", ++ "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n", + fuse); + return UINT_MAX; + } +@@ -1756,7 +1756,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse) + + static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) + { +- u32 supp_hw = UINT_MAX; ++ u32 supp_hw; + u32 speedbin; + int ret; + +@@ -1768,15 +1768,13 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev) + if (ret == -ENOENT) { + return 0; + } else if (ret) { +- DRM_DEV_ERROR(dev, +- "failed to read speed-bin (%d). Some OPPs may not be supported by hardware", +- ret); +- goto done; ++ dev_err_probe(dev, ret, ++ "failed to read speed-bin. Some OPPs may not be supported by hardware\n"); ++ return ret; + } + + supp_hw = fuse_to_supp_hw(dev, rev, speedbin); + +-done: + ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1); + if (ret) + return ret; +-- +2.35.1 + diff --git a/queue-5.15/drm-msm-hdmi-drop-unused-gpio-support.patch b/queue-5.15/drm-msm-hdmi-drop-unused-gpio-support.patch new file mode 100644 index 00000000000..e2074d9a392 --- /dev/null +++ b/queue-5.15/drm-msm-hdmi-drop-unused-gpio-support.patch @@ -0,0 +1,278 @@ +From 10a9deda384cccb29c8532416ca40dbd51ee5b4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jun 2022 15:23:42 +0300 +Subject: drm/msm/hdmi: drop unused GPIO support + +From: Dmitry Baryshkov + +[ Upstream commit 68e674b13b17ed41aac2763d12ece6deaae8df58 ] + +The HDMI driver has code to configure extra GPIOs, which predates +pinctrl support. Nowadays all platforms should use pinctrl instead. +Neither of upstreamed Qualcomm platforms uses these properties, so it's +safe to drop them. + +Reported-by: kernel test robot +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Stephen Boyd +Patchwork: https://patchwork.freedesktop.org/patch/488858/ +Link: https://lore.kernel.org/r/20220609122350.3157529-7-dmitry.baryshkov@linaro.org +Signed-off-by: Dmitry Baryshkov +Stable-dep-of: b964444b2b64 ("drm/msm/hdmi: use devres helper for runtime PM management") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/hdmi/hdmi.c | 66 +++++++---------------------- + drivers/gpu/drm/msm/hdmi/hdmi.h | 13 +----- + drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 62 ++------------------------- + 3 files changed, 21 insertions(+), 120 deletions(-) + +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index f6b09e8eca67..efb14043a6ec 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -247,6 +247,20 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) + hdmi->pwr_clks[i] = clk; + } + ++ hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); ++ /* This will catch e.g. -EPROBE_DEFER */ ++ if (IS_ERR(hdmi->hpd_gpiod)) { ++ ret = PTR_ERR(hdmi->hpd_gpiod); ++ DRM_DEV_ERROR(&pdev->dev, "failed to get hpd gpio: (%d)\n", ret); ++ goto fail; ++ } ++ ++ if (!hdmi->hpd_gpiod) ++ DBG("failed to get HPD gpio"); ++ ++ if (hdmi->hpd_gpiod) ++ gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD"); ++ + pm_runtime_enable(&pdev->dev); + + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); +@@ -429,20 +443,6 @@ static struct hdmi_platform_config hdmi_tx_8996_config = { + .hpd_freq = hpd_clk_freq_8x74, + }; + +-static const struct { +- const char *name; +- const bool output; +- const int value; +- const char *label; +-} msm_hdmi_gpio_pdata[] = { +- { "qcom,hdmi-tx-ddc-clk", true, 1, "HDMI_DDC_CLK" }, +- { "qcom,hdmi-tx-ddc-data", true, 1, "HDMI_DDC_DATA" }, +- { "qcom,hdmi-tx-hpd", false, 1, "HDMI_HPD" }, +- { "qcom,hdmi-tx-mux-en", true, 1, "HDMI_MUX_EN" }, +- { "qcom,hdmi-tx-mux-sel", true, 0, "HDMI_MUX_SEL" }, +- { "qcom,hdmi-tx-mux-lpm", true, 1, "HDMI_MUX_LPM" }, +-}; +- + /* + * HDMI audio codec callbacks + */ +@@ -555,7 +555,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) + struct hdmi_platform_config *hdmi_cfg; + struct hdmi *hdmi; + struct device_node *of_node = dev->of_node; +- int i, err; ++ int err; + + hdmi_cfg = (struct hdmi_platform_config *) + of_device_get_match_data(dev); +@@ -567,42 +567,6 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data) + hdmi_cfg->mmio_name = "core_physical"; + hdmi_cfg->qfprom_mmio_name = "qfprom_physical"; + +- for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { +- const char *name = msm_hdmi_gpio_pdata[i].name; +- struct gpio_desc *gpiod; +- +- /* +- * We are fetching the GPIO lines "as is" since the connector +- * code is enabling and disabling the lines. Until that point +- * the power-on default value will be kept. +- */ +- gpiod = devm_gpiod_get_optional(dev, name, GPIOD_ASIS); +- /* This will catch e.g. -PROBE_DEFER */ +- if (IS_ERR(gpiod)) +- return PTR_ERR(gpiod); +- if (!gpiod) { +- /* Try a second time, stripping down the name */ +- char name3[32]; +- +- /* +- * Try again after stripping out the "qcom,hdmi-tx" +- * prefix. This is mainly to match "hpd-gpios" used +- * in the upstream bindings. +- */ +- if (sscanf(name, "qcom,hdmi-tx-%s", name3)) +- gpiod = devm_gpiod_get_optional(dev, name3, GPIOD_ASIS); +- if (IS_ERR(gpiod)) +- return PTR_ERR(gpiod); +- if (!gpiod) +- DBG("failed to get gpio: %s", name); +- } +- hdmi_cfg->gpios[i].gpiod = gpiod; +- if (gpiod) +- gpiod_set_consumer_name(gpiod, msm_hdmi_gpio_pdata[i].label); +- hdmi_cfg->gpios[i].output = msm_hdmi_gpio_pdata[i].output; +- hdmi_cfg->gpios[i].value = msm_hdmi_gpio_pdata[i].value; +- } +- + dev->platform_data = hdmi_cfg; + + hdmi = msm_hdmi_init(to_platform_device(dev)); +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h +index 8d2706bec3b9..20f554312b17 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.h ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.h +@@ -19,17 +19,9 @@ + #include "msm_drv.h" + #include "hdmi.xml.h" + +-#define HDMI_MAX_NUM_GPIO 6 +- + struct hdmi_phy; + struct hdmi_platform_config; + +-struct hdmi_gpio_data { +- struct gpio_desc *gpiod; +- bool output; +- int value; +-}; +- + struct hdmi_audio { + bool enabled; + struct hdmi_audio_infoframe infoframe; +@@ -61,6 +53,8 @@ struct hdmi { + struct clk **hpd_clks; + struct clk **pwr_clks; + ++ struct gpio_desc *hpd_gpiod; ++ + struct hdmi_phy *phy; + struct device *phy_dev; + +@@ -109,9 +103,6 @@ struct hdmi_platform_config { + /* clks that need to be on for screen pwr (ie pixel clk): */ + const char **pwr_clk_names; + int pwr_clk_cnt; +- +- /* gpio's: */ +- struct hdmi_gpio_data gpios[HDMI_MAX_NUM_GPIO]; + }; + + struct hdmi_bridge { +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +index c3a236bb952c..52ebe562ca9b 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +@@ -60,48 +60,6 @@ static void msm_hdmi_phy_reset(struct hdmi *hdmi) + } + } + +-static int gpio_config(struct hdmi *hdmi, bool on) +-{ +- const struct hdmi_platform_config *config = hdmi->config; +- int i; +- +- if (on) { +- for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { +- struct hdmi_gpio_data gpio = config->gpios[i]; +- +- if (gpio.gpiod) { +- if (gpio.output) { +- gpiod_direction_output(gpio.gpiod, +- gpio.value); +- } else { +- gpiod_direction_input(gpio.gpiod); +- gpiod_set_value_cansleep(gpio.gpiod, +- gpio.value); +- } +- } +- } +- +- DBG("gpio on"); +- } else { +- for (i = 0; i < HDMI_MAX_NUM_GPIO; i++) { +- struct hdmi_gpio_data gpio = config->gpios[i]; +- +- if (!gpio.gpiod) +- continue; +- +- if (gpio.output) { +- int value = gpio.value ? 0 : 1; +- +- gpiod_set_value_cansleep(gpio.gpiod, value); +- } +- } +- +- DBG("gpio off"); +- } +- +- return 0; +-} +- + static void enable_hpd_clocks(struct hdmi *hdmi, bool enable) + { + const struct hdmi_platform_config *config = hdmi->config; +@@ -157,11 +115,8 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) + goto fail; + } + +- ret = gpio_config(hdmi, true); +- if (ret) { +- DRM_DEV_ERROR(dev, "failed to configure GPIOs: %d\n", ret); +- goto fail; +- } ++ if (hdmi->hpd_gpiod) ++ gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); + + pm_runtime_get_sync(dev); + enable_hpd_clocks(hdmi, true); +@@ -210,10 +165,6 @@ void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge) + enable_hpd_clocks(hdmi, false); + pm_runtime_put_autosuspend(dev); + +- ret = gpio_config(hdmi, false); +- if (ret) +- dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret); +- + ret = pinctrl_pm_select_sleep_state(dev); + if (ret) + dev_warn(dev, "pinctrl state chg failed: %d\n", ret); +@@ -275,10 +226,7 @@ static enum drm_connector_status detect_reg(struct hdmi *hdmi) + #define HPD_GPIO_INDEX 2 + static enum drm_connector_status detect_gpio(struct hdmi *hdmi) + { +- const struct hdmi_platform_config *config = hdmi->config; +- struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX]; +- +- return gpiod_get_value(hpd_gpio.gpiod) ? ++ return gpiod_get_value(hdmi->hpd_gpiod) ? + connector_status_connected : + connector_status_disconnected; + } +@@ -288,8 +236,6 @@ enum drm_connector_status msm_hdmi_bridge_detect( + { + struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = hdmi_bridge->hdmi; +- const struct hdmi_platform_config *config = hdmi->config; +- struct hdmi_gpio_data hpd_gpio = config->gpios[HPD_GPIO_INDEX]; + enum drm_connector_status stat_gpio, stat_reg; + int retry = 20; + +@@ -297,7 +243,7 @@ enum drm_connector_status msm_hdmi_bridge_detect( + * some platforms may not have hpd gpio. Rely only on the status + * provided by REG_HDMI_HPD_INT_STATUS in this case. + */ +- if (!hpd_gpio.gpiod) ++ if (!hdmi->hpd_gpiod) + return detect_reg(hdmi); + + do { +-- +2.35.1 + diff --git a/queue-5.15/drm-msm-hdmi-use-devres-helper-for-runtime-pm-manage.patch b/queue-5.15/drm-msm-hdmi-use-devres-helper-for-runtime-pm-manage.patch new file mode 100644 index 00000000000..6167b047b40 --- /dev/null +++ b/queue-5.15/drm-msm-hdmi-use-devres-helper-for-runtime-pm-manage.patch @@ -0,0 +1,39 @@ +From 53b8b775369ff9d6fdd5e86675b369490010a7e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 12:39:23 +0300 +Subject: drm/msm/hdmi: use devres helper for runtime PM management + +From: Dmitry Baryshkov + +[ Upstream commit b964444b2b64ce182495731d830499d1c588ccf6 ] + +Use devm_pm_runtime_enable() to enable runtime PM. This way its effect +will be reverted on device unbind/destruction. + +Fixes: 6ed9ed484d04 ("drm/msm/hdmi: Set up runtime PM for HDMI") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Abhinav Kumar +Patchwork: https://patchwork.freedesktop.org/patch/499647/ +Link: https://lore.kernel.org/r/20220826093927.851597-2-dmitry.baryshkov@linaro.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/hdmi/hdmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c +index efb14043a6ec..e1a9b52d0a29 100644 +--- a/drivers/gpu/drm/msm/hdmi/hdmi.c ++++ b/drivers/gpu/drm/msm/hdmi/hdmi.c +@@ -261,7 +261,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) + if (hdmi->hpd_gpiod) + gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD"); + +- pm_runtime_enable(&pdev->dev); ++ devm_pm_runtime_enable(&pdev->dev); + + hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0); + +-- +2.35.1 + diff --git a/queue-5.15/drm-msm-use-drm_mode_copy.patch b/queue-5.15/drm-msm-use-drm_mode_copy.patch new file mode 100644 index 00000000000..cf23dcc0856 --- /dev/null +++ b/queue-5.15/drm-msm-use-drm_mode_copy.patch @@ -0,0 +1,99 @@ +From 6932f31c437cacde936aa431892d45e780b449ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 21:25:42 +0200 +Subject: drm/msm: Use drm_mode_copy() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +[ Upstream commit b2a1c5ca50db22b3677676dd5bad5f6092429acf ] + +struct drm_display_mode embeds a list head, so overwriting +the full struct with another one will corrupt the list +(if the destination mode is on a list). Use drm_mode_copy() +instead which explicitly preserves the list head of +the destination mode. + +Even if we know the destination mode is not on any list +using drm_mode_copy() seems decent as it sets a good +example. Bad examples of not using it might eventually +get copied into code where preserving the list head +actually matters. + +Obviously one case not covered here is when the mode +itself is embedded in a larger structure and the whole +structure is copied. But if we are careful when copying +into modes embedded in structures I think we can be a +little more reassured that bogus list heads haven't been +propagated in. + +@is_mode_copy@ +@@ +drm_mode_copy(...) +{ +... +} + +@depends on !is_mode_copy@ +struct drm_display_mode *mode; +expression E, S; +@@ +( +- *mode = E ++ drm_mode_copy(mode, &E) +| +- memcpy(mode, E, S) ++ drm_mode_copy(mode, E) +) + +@depends on !is_mode_copy@ +struct drm_display_mode mode; +expression E; +@@ +( +- mode = E ++ drm_mode_copy(&mode, &E) +| +- memcpy(&mode, E, S) ++ drm_mode_copy(&mode, E) +) + +@@ +struct drm_display_mode *mode; +@@ +- &*mode ++ mode + +Cc: Rob Clark +Cc: Sean Paul +Cc: Abhinav Kumar +Cc: linux-arm-msm@vger.kernel.org +Cc: freedreno@lists.freedesktop.org +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Abhinav Kumar +Reviewed-by: Daniel Vetter +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20221107192545.9896-5-ville.syrjala@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dp/dp_display.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c +index d13fd39f05de..15e38ad7aefb 100644 +--- a/drivers/gpu/drm/msm/dp/dp_display.c ++++ b/drivers/gpu/drm/msm/dp/dp_display.c +@@ -840,7 +840,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display, + + dp = container_of(dp_display, struct dp_display_private, dp_display); + +- dp->panel->dp_mode.drm_mode = mode->drm_mode; ++ drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode); + dp->panel->dp_mode.bpp = mode->bpp; + dp->panel->dp_mode.capabilities = mode->capabilities; + dp_panel_init_panel_info(dp->panel); +-- +2.35.1 + diff --git a/queue-5.15/drm-panel-panel-sitronix-st7701-remove-panel-on-dsi-.patch b/queue-5.15/drm-panel-panel-sitronix-st7701-remove-panel-on-dsi-.patch new file mode 100644 index 00000000000..e93d0043127 --- /dev/null +++ b/queue-5.15/drm-panel-panel-sitronix-st7701-remove-panel-on-dsi-.patch @@ -0,0 +1,45 @@ +From fdc64515a84305f54788e03a6529a17e006364fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 15 Oct 2022 01:11:06 +0200 +Subject: drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure + +From: Marek Vasut + +[ Upstream commit c62102165dd79284d42383d2f7ed17301bd8e629 ] + +In case mipi_dsi_attach() fails, call drm_panel_remove() to +avoid memory leak. + +Fixes: 849b2e3ff969 ("drm/panel: Add Sitronix ST7701 panel driver") +Signed-off-by: Marek Vasut +Signed-off-by: Linus Walleij +Link: https://patchwork.freedesktop.org/patch/msgid/20221014231106.468063-1-marex@denx.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-sitronix-st7701.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c +index 320a2a8fd459..098955526b68 100644 +--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c ++++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c +@@ -384,7 +384,15 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi) + st7701->dsi = dsi; + st7701->desc = desc; + +- return mipi_dsi_attach(dsi); ++ ret = mipi_dsi_attach(dsi); ++ if (ret) ++ goto err_attach; ++ ++ return 0; ++ ++err_attach: ++ drm_panel_remove(&st7701->panel); ++ return ret; + } + + static int st7701_dsi_remove(struct mipi_dsi_device *dsi) +-- +2.35.1 + diff --git a/queue-5.15/drm-radeon-add-the-missed-acpi_put_table-to-fix-memo.patch b/queue-5.15/drm-radeon-add-the-missed-acpi_put_table-to-fix-memo.patch new file mode 100644 index 00000000000..8b72327887a --- /dev/null +++ b/queue-5.15/drm-radeon-add-the-missed-acpi_put_table-to-fix-memo.patch @@ -0,0 +1,86 @@ +From 526242bf08d23175e20bb0e41f2fb38e2f971676 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 17:50:02 +0800 +Subject: drm/radeon: Add the missed acpi_put_table() to fix memory leak + +From: Hanjun Guo + +[ Upstream commit 10276a20be1115e1f76c189330da2992df980eee ] + +When the radeon driver reads the bios information from ACPI +table in radeon_acpi_vfct_bios(), it misses to call acpi_put_table() +to release the ACPI memory after the init, so add acpi_put_table() +properly to fix the memory leak. + +v2: fix text formatting (Alex) + +Fixes: 268ba0a99f89 ("drm/radeon: implement ACPI VFCT vbios fetch (v3)") +Signed-off-by: Hanjun Guo +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/radeon/radeon_bios.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 33121655d50b..1d99c9a2b56e 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -612,13 +612,14 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + unsigned offset; ++ bool r = false; + + if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr))) + return false; + tbl_size = hdr->length; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); +- return false; ++ goto out; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; +@@ -631,13 +632,13 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + offset += sizeof(VFCT_IMAGE_HEADER); + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image header truncated\n"); +- return false; ++ goto out; + } + + offset += vhdr->ImageLength; + if (offset > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); +- return false; ++ goto out; + } + + if (vhdr->ImageLength && +@@ -649,15 +650,18 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) + rdev->bios = kmemdup(&vbios->VbiosContent, + vhdr->ImageLength, + GFP_KERNEL); ++ if (rdev->bios) ++ r = true; + +- if (!rdev->bios) +- return false; +- return true; ++ goto out; + } + } + + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); +- return false; ++ ++out: ++ acpi_put_table(hdr); ++ return r; + } + #else + static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +-- +2.35.1 + diff --git a/queue-5.15/drm-radeon-fix-pci-device-refcount-leak-in-radeon_at.patch b/queue-5.15/drm-radeon-fix-pci-device-refcount-leak-in-radeon_at.patch new file mode 100644 index 00000000000..84cdc254fde --- /dev/null +++ b/queue-5.15/drm-radeon-fix-pci-device-refcount-leak-in-radeon_at.patch @@ -0,0 +1,41 @@ +From 84b6530b012bb2faa7e7c56b34cdb7570a9dbc61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:30:42 +0800 +Subject: drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios() + +From: Xiongfeng Wang + +[ Upstream commit 725a521a18734f65de05b8d353b5bd0d3ca4c37a ] + +As comment of pci_get_class() says, it returns a pci_device with its +refcount increased and decreased the refcount for the input parameter +@from if it is not NULL. + +If we break the loop in radeon_atrm_get_bios() with 'pdev' not NULL, we +need to call pci_dev_put() to decrease the refcount. Add the missing +pci_dev_put() to avoid refcount leak. + +Fixes: d8ade3526b2a ("drm/radeon: handle non-VGA class pci devices with ATRM") +Fixes: c61e2775873f ("drm/radeon: split ATRM support out from the ATPX handler (v3)") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/radeon/radeon_bios.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c +index 1d99c9a2b56e..63bdc9f6fc24 100644 +--- a/drivers/gpu/drm/radeon/radeon_bios.c ++++ b/drivers/gpu/drm/radeon/radeon_bios.c +@@ -227,6 +227,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) + + if (!found) + return false; ++ pci_dev_put(pdev); + + rdev->bios = kmalloc(size, GFP_KERNEL); + if (!rdev->bios) { +-- +2.35.1 + diff --git a/queue-5.15/drm-rockchip-lvds-fix-pm-usage-counter-unbalance-in-.patch b/queue-5.15/drm-rockchip-lvds-fix-pm-usage-counter-unbalance-in-.patch new file mode 100644 index 00000000000..14eecc25407 --- /dev/null +++ b/queue-5.15/drm-rockchip-lvds-fix-pm-usage-counter-unbalance-in-.patch @@ -0,0 +1,63 @@ +From 52c8b71e31d8803e50129bb0c5a23d553f97833c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 21:21:07 +0800 +Subject: drm/rockchip: lvds: fix PM usage counter unbalance in poweron + +From: Zhang Qilong + +[ Upstream commit 4dba27f1a14592ac4cf71c3bc1cc1fd05dea8015 ] + +pm_runtime_get_sync will increment pm usage counter even it failed. +Forgetting to putting operation will result in reference leak here. +We fix it by replacing it with the newest pm_runtime_resume_and_get +to keep usage counter balanced. + +Fixes: 34cc0aa25456 ("drm/rockchip: Add support for Rockchip Soc LVDS") +Fixes: cca1705c3d89 ("drm/rockchip: lvds: Add PX30 support") +Signed-off-by: Zhang Qilong +Signed-off-by: Heiko Stuebner +Link: https://patchwork.freedesktop.org/patch/msgid/20220922132107.105419-3-zhangqilong3@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/rockchip_lvds.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c +index 551653940e39..2550429df49f 100644 +--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c ++++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c +@@ -145,7 +145,7 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds) + DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret); + return ret; + } +- ret = pm_runtime_get_sync(lvds->dev); ++ ret = pm_runtime_resume_and_get(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + clk_disable(lvds->pclk); +@@ -329,16 +329,20 @@ static int px30_lvds_poweron(struct rockchip_lvds *lvds) + { + int ret; + +- ret = pm_runtime_get_sync(lvds->dev); ++ ret = pm_runtime_resume_and_get(lvds->dev); + if (ret < 0) { + DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); + return ret; + } + + /* Enable LVDS mode */ +- return regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1, ++ ret = regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1, + PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1), + PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1)); ++ if (ret) ++ pm_runtime_put(lvds->dev); ++ ++ return ret; + } + + static void px30_lvds_poweroff(struct rockchip_lvds *lvds) +-- +2.35.1 + diff --git a/queue-5.15/drm-rockchip-use-drm_mode_copy.patch b/queue-5.15/drm-rockchip-use-drm_mode_copy.patch new file mode 100644 index 00000000000..3bb87c54349 --- /dev/null +++ b/queue-5.15/drm-rockchip-use-drm_mode_copy.patch @@ -0,0 +1,124 @@ +From 18975a88c1441137bf61797107408081b0c29a2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 21:25:44 +0200 +Subject: drm/rockchip: Use drm_mode_copy() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +[ Upstream commit 2bfaa28000d2830d3209161a4541cce0660e1b84 ] + +struct drm_display_mode embeds a list head, so overwriting +the full struct with another one will corrupt the list +(if the destination mode is on a list). Use drm_mode_copy() +instead which explicitly preserves the list head of +the destination mode. + +Even if we know the destination mode is not on any list +using drm_mode_copy() seems decent as it sets a good +example. Bad examples of not using it might eventually +get copied into code where preserving the list head +actually matters. + +Obviously one case not covered here is when the mode +itself is embedded in a larger structure and the whole +structure is copied. But if we are careful when copying +into modes embedded in structures I think we can be a +little more reassured that bogus list heads haven't been +propagated in. + +@is_mode_copy@ +@@ +drm_mode_copy(...) +{ +... +} + +@depends on !is_mode_copy@ +struct drm_display_mode *mode; +expression E, S; +@@ +( +- *mode = E ++ drm_mode_copy(mode, &E) +| +- memcpy(mode, E, S) ++ drm_mode_copy(mode, E) +) + +@depends on !is_mode_copy@ +struct drm_display_mode mode; +expression E; +@@ +( +- mode = E ++ drm_mode_copy(&mode, &E) +| +- memcpy(&mode, E, S) ++ drm_mode_copy(&mode, E) +) + +@@ +struct drm_display_mode *mode; +@@ +- &*mode ++ mode + +Signed-off-by: Ville Syrjälä +Cc: Sandy Huang +Cc: "Heiko Stübner" +Cc: linux-arm-kernel@lists.infradead.org +Cc: linux-rockchip@lists.infradead.org +Link: https://patchwork.freedesktop.org/patch/msgid/20221107192545.9896-7-ville.syrjala@linux.intel.com +Reviewed-by: Daniel Vetter +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rockchip/cdn-dp-core.c | 2 +- + drivers/gpu/drm/rockchip/inno_hdmi.c | 2 +- + drivers/gpu/drm/rockchip/rk3066_hdmi.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c +index 6b5d0722afa6..20e63cadec8c 100644 +--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c ++++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c +@@ -565,7 +565,7 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder, + video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + +- memcpy(&dp->mode, adjusted, sizeof(*mode)); ++ drm_mode_copy(&dp->mode, adjusted); + } + + static bool cdn_dp_check_link_status(struct cdn_dp_device *dp) +diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c +index 7afdc54eb3ec..78120da5e63a 100644 +--- a/drivers/gpu/drm/rockchip/inno_hdmi.c ++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c +@@ -488,7 +488,7 @@ static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder, + inno_hdmi_setup(hdmi, adj_mode); + + /* Store the display mode for plugin/DPMS poweron events */ +- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode)); ++ drm_mode_copy(&hdmi->previous_mode, adj_mode); + } + + static void inno_hdmi_encoder_enable(struct drm_encoder *encoder) +diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c +index 1c546c3a8998..17e7c40a9e7b 100644 +--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c ++++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c +@@ -383,7 +383,7 @@ rk3066_hdmi_encoder_mode_set(struct drm_encoder *encoder, + struct rk3066_hdmi *hdmi = to_rk3066_hdmi(encoder); + + /* Store the display mode for plugin/DPMS poweron events. */ +- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode)); ++ drm_mode_copy(&hdmi->previous_mode, adj_mode); + } + + static void rk3066_hdmi_encoder_enable(struct drm_encoder *encoder) +-- +2.35.1 + diff --git a/queue-5.15/drm-sti-fix-return-type-of-sti_-dvo-hda-hdmi-_connec.patch b/queue-5.15/drm-sti-fix-return-type-of-sti_-dvo-hda-hdmi-_connec.patch new file mode 100644 index 00000000000..a3c3e45dfeb --- /dev/null +++ b/queue-5.15/drm-sti-fix-return-type-of-sti_-dvo-hda-hdmi-_connec.patch @@ -0,0 +1,95 @@ +From c1af7392105d464f30a85e87d1fdadaa2308e5e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 08:56:23 -0700 +Subject: drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid() + +From: Nathan Chancellor + +[ Upstream commit 0ad811cc08a937d875cbad0149c1bab17f84ba05 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/gpu/drm/sti/sti_hda.c:637:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_connector *, struct drm_display_mode *)' with an expression of type 'int (struct drm_connector *, struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .mode_valid = sti_hda_connector_mode_valid, + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + drivers/gpu/drm/sti/sti_dvo.c:376:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_connector *, struct drm_display_mode *)' with an expression of type 'int (struct drm_connector *, struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .mode_valid = sti_dvo_connector_mode_valid, + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ + drivers/gpu/drm/sti/sti_hdmi.c:1035:16: error: incompatible function pointer types initializing 'enum drm_mode_status (*)(struct drm_connector *, struct drm_display_mode *)' with an expression of type 'int (struct drm_connector *, struct drm_display_mode *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .mode_valid = sti_hdmi_connector_mode_valid, + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +->mode_valid() in 'struct drm_connector_helper_funcs' expects a return +type of 'enum drm_mode_status', not 'int'. Adjust the return type of +sti_{dvo,hda,hdmi}_connector_mode_valid() to match the prototype's to +resolve the warning and CFI failure. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Signed-off-by: Nathan Chancellor +Reviewed-by: Kees Cook +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20221102155623.3042869-1-nathan@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/sti/sti_dvo.c | 5 +++-- + drivers/gpu/drm/sti/sti_hda.c | 5 +++-- + drivers/gpu/drm/sti/sti_hdmi.c | 5 +++-- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c +index f3a5616b7daf..577c477b5f46 100644 +--- a/drivers/gpu/drm/sti/sti_dvo.c ++++ b/drivers/gpu/drm/sti/sti_dvo.c +@@ -346,8 +346,9 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector) + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_dvo_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_dvo_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c +index c9e6db15ab66..aa54a6400ab8 100644 +--- a/drivers/gpu/drm/sti/sti_hda.c ++++ b/drivers/gpu/drm/sti/sti_hda.c +@@ -600,8 +600,9 @@ static int sti_hda_connector_get_modes(struct drm_connector *connector) + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_hda_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_hda_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c +index bb2a2868de2d..36bea1551ef8 100644 +--- a/drivers/gpu/drm/sti/sti_hdmi.c ++++ b/drivers/gpu/drm/sti/sti_hdmi.c +@@ -1003,8 +1003,9 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector) + + #define CLK_TOLERANCE_HZ 50 + +-static int sti_hdmi_connector_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status ++sti_hdmi_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + int target = mode->clock * 1000; + int target_min = target - CLK_TOLERANCE_HZ; +-- +2.35.1 + diff --git a/queue-5.15/drm-sti-use-drm_mode_copy.patch b/queue-5.15/drm-sti-use-drm_mode_copy.patch new file mode 100644 index 00000000000..30728ab4e54 --- /dev/null +++ b/queue-5.15/drm-sti-use-drm_mode_copy.patch @@ -0,0 +1,121 @@ +From 187522b55d0ff560573ca8162adec20990266d23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 21:25:45 +0200 +Subject: drm/sti: Use drm_mode_copy() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ville Syrjälä + +[ Upstream commit 442cf8e22ba25a77cb9092d78733fdbac9844e50 ] + +struct drm_display_mode embeds a list head, so overwriting +the full struct with another one will corrupt the list +(if the destination mode is on a list). Use drm_mode_copy() +instead which explicitly preserves the list head of +the destination mode. + +Even if we know the destination mode is not on any list +using drm_mode_copy() seems decent as it sets a good +example. Bad examples of not using it might eventually +get copied into code where preserving the list head +actually matters. + +Obviously one case not covered here is when the mode +itself is embedded in a larger structure and the whole +structure is copied. But if we are careful when copying +into modes embedded in structures I think we can be a +little more reassured that bogus list heads haven't been +propagated in. + +@is_mode_copy@ +@@ +drm_mode_copy(...) +{ +... +} + +@depends on !is_mode_copy@ +struct drm_display_mode *mode; +expression E, S; +@@ +( +- *mode = E ++ drm_mode_copy(mode, &E) +| +- memcpy(mode, E, S) ++ drm_mode_copy(mode, E) +) + +@depends on !is_mode_copy@ +struct drm_display_mode mode; +expression E; +@@ +( +- mode = E ++ drm_mode_copy(&mode, &E) +| +- memcpy(&mode, E, S) ++ drm_mode_copy(&mode, E) +) + +@@ +struct drm_display_mode *mode; +@@ +- &*mode ++ mode + +Cc: Alain Volmat +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20221107192545.9896-8-ville.syrjala@linux.intel.com +Reviewed-by: Daniel Vetter +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/sti/sti_dvo.c | 2 +- + drivers/gpu/drm/sti/sti_hda.c | 2 +- + drivers/gpu/drm/sti/sti_hdmi.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c +index b6ee8a82e656..f3a5616b7daf 100644 +--- a/drivers/gpu/drm/sti/sti_dvo.c ++++ b/drivers/gpu/drm/sti/sti_dvo.c +@@ -288,7 +288,7 @@ static void sti_dvo_set_mode(struct drm_bridge *bridge, + + DRM_DEBUG_DRIVER("\n"); + +- memcpy(&dvo->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&dvo->mode, mode); + + /* According to the path used (main or aux), the dvo clocks should + * have a different parent clock. */ +diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c +index 03f3377f918c..c9e6db15ab66 100644 +--- a/drivers/gpu/drm/sti/sti_hda.c ++++ b/drivers/gpu/drm/sti/sti_hda.c +@@ -523,7 +523,7 @@ static void sti_hda_set_mode(struct drm_bridge *bridge, + + DRM_DEBUG_DRIVER("\n"); + +- memcpy(&hda->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&hda->mode, mode); + + if (!hda_get_mode_idx(hda->mode, &mode_idx)) { + DRM_ERROR("Undefined mode\n"); +diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c +index f3ace11209dd..bb2a2868de2d 100644 +--- a/drivers/gpu/drm/sti/sti_hdmi.c ++++ b/drivers/gpu/drm/sti/sti_hdmi.c +@@ -940,7 +940,7 @@ static void sti_hdmi_set_mode(struct drm_bridge *bridge, + DRM_DEBUG_DRIVER("\n"); + + /* Copy the drm display mode in the connector local structure */ +- memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode)); ++ drm_mode_copy(&hdmi->mode, mode); + + /* Update clock framerate according to the selected mode */ + ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000); +-- +2.35.1 + diff --git a/queue-5.15/drm-tegra-add-missing-clk_disable_unprepare-in-tegra.patch b/queue-5.15/drm-tegra-add-missing-clk_disable_unprepare-in-tegra.patch new file mode 100644 index 00000000000..47393972d3a --- /dev/null +++ b/queue-5.15/drm-tegra-add-missing-clk_disable_unprepare-in-tegra.patch @@ -0,0 +1,39 @@ +From 4f3b1d6da69b2be892f3b93f6ddf09e716395cfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 08:50:50 +0000 +Subject: drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe() + +From: Zhang Zekun + +[ Upstream commit 7ad4384d53c67672a8720cdc2ef638d7d1710ab8 ] + +Add the missing clk_disable_unprepare() before return from +tegra_dc_probe() in the error handling path. + +Fixes: f68ba6912bd2 ("drm/tegra: dc: Link DC1 to DC0 on Tegra20") +Signed-off-by: Zhang Zekun +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tegra/dc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c +index a29d64f87563..abb409b08bc6 100644 +--- a/drivers/gpu/drm/tegra/dc.c ++++ b/drivers/gpu/drm/tegra/dc.c +@@ -3022,8 +3022,10 @@ static int tegra_dc_probe(struct platform_device *pdev) + usleep_range(2000, 4000); + + err = reset_control_assert(dc->rst); +- if (err < 0) ++ if (err < 0) { ++ clk_disable_unprepare(dc->clk); + return err; ++ } + + usleep_range(2000, 4000); + +-- +2.35.1 + diff --git a/queue-5.15/dt-bindings-imx6q-pcie-fix-clock-names-for-imx6sx-an.patch b/queue-5.15/dt-bindings-imx6q-pcie-fix-clock-names-for-imx6sx-an.patch new file mode 100644 index 00000000000..536d5c322db --- /dev/null +++ b/queue-5.15/dt-bindings-imx6q-pcie-fix-clock-names-for-imx6sx-an.patch @@ -0,0 +1,102 @@ +From c2be41c286de41c56b6f1f88a1da8a49a73a35e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 22:12:42 +0300 +Subject: dt-bindings: imx6q-pcie: Fix clock names for imx6sx and imx8mq + +From: Serge Semin + +[ Upstream commit b8a83e600bdde93e7da41ea3204b2b3832a3c99b ] + +Originally as it was defined the legacy bindings the pcie_inbound_axi and +pcie_aux clock names were supposed to be used in the fsl,imx6sx-pcie and +fsl,imx8mq-pcie devices respectively. But the bindings conversion has been +incorrectly so now the fourth clock name is defined as "pcie_inbound_axi +for imx6sx-pcie, pcie_aux for imx8mq-pcie", which is completely wrong. +Let's fix that by conditionally apply the clock-names constraints based on +the compatible string content. + +Link: https://lore.kernel.org/r/20221113191301.5526-2-Sergey.Semin@baikalelectronics.ru +Fixes: 751ca492f131 ("dt-bindings: PCI: imx6: convert the imx pcie controller to dtschema") +Signed-off-by: Serge Semin +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Alexander Stein +Signed-off-by: Sasha Levin +--- + .../bindings/pci/fsl,imx6q-pcie.yaml | 46 +++++++++++++++++-- + 1 file changed, 42 insertions(+), 4 deletions(-) + +diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml +index acea1cd444fd..9b0548264a39 100644 +--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml +@@ -14,9 +14,6 @@ description: |+ + This PCIe host controller is based on the Synopsys DesignWare PCIe IP + and thus inherits all the common properties defined in snps,dw-pcie.yaml. + +-allOf: +- - $ref: /schemas/pci/snps,dw-pcie.yaml# +- + properties: + compatible: + enum: +@@ -59,7 +56,7 @@ properties: + - const: pcie + - const: pcie_bus + - const: pcie_phy +- - const: pcie_inbound_axi for imx6sx-pcie, pcie_aux for imx8mq-pcie ++ - enum: [ pcie_inbound_axi, pcie_aux ] + + num-lanes: + const: 1 +@@ -166,6 +163,47 @@ required: + - clocks + - clock-names + ++allOf: ++ - $ref: /schemas/pci/snps,dw-pcie.yaml# ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: fsl,imx6sx-pcie ++ then: ++ properties: ++ clock-names: ++ items: ++ - {} ++ - {} ++ - {} ++ - const: pcie_inbound_axi ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: fsl,imx8mq-pcie ++ then: ++ properties: ++ clock-names: ++ items: ++ - {} ++ - {} ++ - {} ++ - const: pcie_aux ++ - if: ++ properties: ++ compatible: ++ not: ++ contains: ++ enum: ++ - fsl,imx6sx-pcie ++ - fsl,imx8mq-pcie ++ then: ++ properties: ++ clock-names: ++ maxItems: 3 ++ + unevaluatedProperties: false + + examples: +-- +2.35.1 + diff --git a/queue-5.15/dt-bindings-visconti-pcie-fix-interrupts-array-max-c.patch b/queue-5.15/dt-bindings-visconti-pcie-fix-interrupts-array-max-c.patch new file mode 100644 index 00000000000..0a94d05b1d4 --- /dev/null +++ b/queue-5.15/dt-bindings-visconti-pcie-fix-interrupts-array-max-c.patch @@ -0,0 +1,55 @@ +From ad02df73ced680026c77b73d0a69c9075715dd9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 22:12:43 +0300 +Subject: dt-bindings: visconti-pcie: Fix interrupts array max constraints + +From: Serge Semin + +[ Upstream commit 4cf4b9b70ab2785461190c08a3542d2d74c28b46 ] + +In accordance with the way the device DT-node is actually defined in +arch/arm64/boot/dts/toshiba/tmpv7708.dtsi and the way the device is probed +by the DW PCIe driver there are two IRQs it actually has. It's MSI IRQ the +DT-bindings lack. Let's extend the interrupts property constraints then +and fix the schema example so one would be acceptable by the actual device +DT-bindings. + +Link: https://lore.kernel.org/r/20221113191301.5526-3-Sergey.Semin@baikalelectronics.ru +Fixes: 17c1b16340f0 ("dt-bindings: pci: Add DT binding for Toshiba Visconti PCIe controller") +Signed-off-by: Serge Semin +Signed-off-by: Lorenzo Pieralisi +Acked-by: Rob Herring +Acked-by: Nobuhiro Iwamatsu +Signed-off-by: Sasha Levin +--- + .../devicetree/bindings/pci/toshiba,visconti-pcie.yaml | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml +index 30b6396d83c8..aea0e2bcdd77 100644 +--- a/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml ++++ b/Documentation/devicetree/bindings/pci/toshiba,visconti-pcie.yaml +@@ -36,7 +36,7 @@ properties: + - const: mpu + + interrupts: +- maxItems: 1 ++ maxItems: 2 + + clocks: + items: +@@ -94,8 +94,9 @@ examples: + #interrupt-cells = <1>; + ranges = <0x81000000 0 0x40000000 0 0x40000000 0 0x00010000>, + <0x82000000 0 0x50000000 0 0x50000000 0 0x20000000>; +- interrupts = ; +- interrupt-names = "intr"; ++ interrupts = , ++ ; ++ interrupt-names = "msi", "intr"; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = + <0 0 0 1 &gic GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH +-- +2.35.1 + diff --git a/queue-5.15/edac-i10nm-fix-refcount-leak-in-pci_get_dev_wrapper.patch b/queue-5.15/edac-i10nm-fix-refcount-leak-in-pci_get_dev_wrapper.patch new file mode 100644 index 00000000000..14eb151b63e --- /dev/null +++ b/queue-5.15/edac-i10nm-fix-refcount-leak-in-pci_get_dev_wrapper.patch @@ -0,0 +1,44 @@ +From 10bb6192d3d0e1533aa0362de3edb96462469bf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 14:55:12 +0800 +Subject: EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper() + +From: Yang Yingliang + +[ Upstream commit 9c8921555907f4d723f01ed2d859b66f2d14f08e ] + +As the comment of pci_get_domain_bus_and_slot() says, it returns +a PCI device with refcount incremented, so it doesn't need to +call an extra pci_dev_get() in pci_get_dev_wrapper(), and the PCI +device needs to be put in the error path. + +Fixes: d4dc89d069aa ("EDAC, i10nm: Add a driver for Intel 10nm server processors") +Signed-off-by: Yang Yingliang +Reviewed-by: Qiuxu Zhuo +Signed-off-by: Tony Luck +Link: https://lore.kernel.org/r/20221128065512.3572550-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/edac/i10nm_base.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c +index 6cf50ee0b77c..e0af60833d28 100644 +--- a/drivers/edac/i10nm_base.c ++++ b/drivers/edac/i10nm_base.c +@@ -198,11 +198,10 @@ static struct pci_dev *pci_get_dev_wrapper(int dom, unsigned int bus, + if (unlikely(pci_enable_device(pdev) < 0)) { + edac_dbg(2, "Failed to enable device %02x:%02x.%x\n", + bus, dev, fun); ++ pci_dev_put(pdev); + return NULL; + } + +- pci_dev_get(pdev); +- + return pdev; + } + +-- +2.35.1 + diff --git a/queue-5.15/ethernet-s2io-don-t-call-dev_kfree_skb-under-spin_lo.patch b/queue-5.15/ethernet-s2io-don-t-call-dev_kfree_skb-under-spin_lo.patch new file mode 100644 index 00000000000..8e53544ad77 --- /dev/null +++ b/queue-5.15/ethernet-s2io-don-t-call-dev_kfree_skb-under-spin_lo.patch @@ -0,0 +1,45 @@ +From 7dd8a8ec11d645500e99bbed7ae9398f629c55ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 20:01:21 +0800 +Subject: ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 6cee96e09df54ae17784c0f38a49e0ed8229b825 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In this case, dev_kfree_skb() is called in free_tx_buffers() to drop +the SKBs in tx buffers, when the card is down, so replace it with +dev_kfree_skb_irq() here. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/neterion/s2io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c +index f4703f53bcdc..65ccdbe665e5 100644 +--- a/drivers/net/ethernet/neterion/s2io.c ++++ b/drivers/net/ethernet/neterion/s2io.c +@@ -2386,7 +2386,7 @@ static void free_tx_buffers(struct s2io_nic *nic) + skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); + if (skb) { + swstats->mem_freed += skb->truesize; +- dev_kfree_skb(skb); ++ dev_kfree_skb_irq(skb); + cnt++; + } + } +-- +2.35.1 + diff --git a/queue-5.15/ethtool-avoiding-integer-overflow-in-ethtool_phys_id.patch b/queue-5.15/ethtool-avoiding-integer-overflow-in-ethtool_phys_id.patch new file mode 100644 index 00000000000..2be5ac6d0a9 --- /dev/null +++ b/queue-5.15/ethtool-avoiding-integer-overflow-in-ethtool_phys_id.patch @@ -0,0 +1,43 @@ +From 3ff2c7bd9a27fbab14e5d434d419e0a51303c88c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 15:29:01 +0300 +Subject: ethtool: avoiding integer overflow in ethtool_phys_id() + +From: Maxim Korotkov + +[ Upstream commit 64a8f8f7127da228d59a39e2c5e75f86590f90b4 ] + +The value of an arithmetic expression "n * id.data" is subject +to possible overflow due to a failure to cast operands to a larger data +type before performing arithmetic. Used macro for multiplication instead +operator for avoiding overflow. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Signed-off-by: Maxim Korotkov +Reviewed-by: Alexander Lobakin +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20221122122901.22294-1-korotkov.maxim.s@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ethtool/ioctl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c +index e4983f473a3c..6991d77dcb2e 100644 +--- a/net/ethtool/ioctl.c ++++ b/net/ethtool/ioctl.c +@@ -1988,7 +1988,8 @@ static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) + } else { + /* Driver expects to be called at twice the frequency in rc */ + int n = rc * 2, interval = HZ / n; +- u64 count = n * id.data, i = 0; ++ u64 count = mul_u32_u32(n, id.data); ++ u64 i = 0; + + do { + rtnl_lock(); +-- +2.35.1 + diff --git a/queue-5.15/eventfd-change-int-to-__u64-in-eventfd_signal-ifndef.patch b/queue-5.15/eventfd-change-int-to-__u64-in-eventfd_signal-ifndef.patch new file mode 100644 index 00000000000..9c65bd2ebf4 --- /dev/null +++ b/queue-5.15/eventfd-change-int-to-__u64-in-eventfd_signal-ifndef.patch @@ -0,0 +1,41 @@ +From 7f24effd743ec08ceb3e777be4431783076b9f25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 22:01:54 +0800 +Subject: eventfd: change int to __u64 in eventfd_signal() ifndef + CONFIG_EVENTFD + +From: Zhang Qilong + +[ Upstream commit fd4e60bf0ef8eb9edcfa12dda39e8b6ee9060492 ] + +Commit ee62c6b2dc93 ("eventfd: change int to __u64 in eventfd_signal()") +forgot to change int to __u64 in the CONFIG_EVENTFD=n stub function. + +Link: https://lkml.kernel.org/r/20221124140154.104680-1-zhangqilong3@huawei.com +Fixes: ee62c6b2dc93 ("eventfd: change int to __u64 in eventfd_signal()") +Signed-off-by: Zhang Qilong +Cc: Dylan Yudaken +Cc: Jens Axboe +Cc: Sha Zhengju +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + include/linux/eventfd.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h +index 30eb30d6909b..3cd202d3eefb 100644 +--- a/include/linux/eventfd.h ++++ b/include/linux/eventfd.h +@@ -61,7 +61,7 @@ static inline struct eventfd_ctx *eventfd_ctx_fdget(int fd) + return ERR_PTR(-ENOSYS); + } + +-static inline int eventfd_signal(struct eventfd_ctx *ctx, int n) ++static inline int eventfd_signal(struct eventfd_ctx *ctx, __u64 n) + { + return -ENOSYS; + } +-- +2.35.1 + diff --git a/queue-5.15/extcon-usbc-tusb320-add-support-for-mode-setting-and.patch b/queue-5.15/extcon-usbc-tusb320-add-support-for-mode-setting-and.patch new file mode 100644 index 00000000000..64585c392fd --- /dev/null +++ b/queue-5.15/extcon-usbc-tusb320-add-support-for-mode-setting-and.patch @@ -0,0 +1,145 @@ +From ad6d3b13f9ba2a0db61575ee1518046f863595dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Sep 2021 05:45:39 +0000 +Subject: extcon: usbc-tusb320: Add support for mode setting and reset + +From: Yassine Oudjana + +[ Upstream commit 70c55d6be634e5f9894169340f3fe5c73f53ac2d ] + +Reset the chip and set its mode to default (maintain mode set by PORT pin) +during probe to make sure it comes up in the default state. + +Signed-off-by: Yassine Oudjana +Signed-off-by: Chanwoo Choi +Stable-dep-of: 581c848b610d ("extcon: usbc-tusb320: Update state on probe even if no IRQ pending") +Signed-off-by: Sasha Levin +--- + drivers/extcon/extcon-usbc-tusb320.c | 85 ++++++++++++++++++++++++++-- + 1 file changed, 81 insertions(+), 4 deletions(-) + +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index 805af73b4152..1ed1dfe54206 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -19,15 +19,32 @@ + #define TUSB320_REG9_ATTACHED_STATE_MASK 0x3 + #define TUSB320_REG9_CABLE_DIRECTION BIT(5) + #define TUSB320_REG9_INTERRUPT_STATUS BIT(4) +-#define TUSB320_ATTACHED_STATE_NONE 0x0 +-#define TUSB320_ATTACHED_STATE_DFP 0x1 +-#define TUSB320_ATTACHED_STATE_UFP 0x2 +-#define TUSB320_ATTACHED_STATE_ACC 0x3 ++ ++#define TUSB320_REGA 0xa ++#define TUSB320_REGA_I2C_SOFT_RESET BIT(3) ++#define TUSB320_REGA_MODE_SELECT_SHIFT 4 ++#define TUSB320_REGA_MODE_SELECT_MASK 0x3 ++ ++enum tusb320_attached_state { ++ TUSB320_ATTACHED_STATE_NONE, ++ TUSB320_ATTACHED_STATE_DFP, ++ TUSB320_ATTACHED_STATE_UFP, ++ TUSB320_ATTACHED_STATE_ACC, ++}; ++ ++enum tusb320_mode { ++ TUSB320_MODE_PORT, ++ TUSB320_MODE_UFP, ++ TUSB320_MODE_DFP, ++ TUSB320_MODE_DRP, ++}; + + struct tusb320_priv { + struct device *dev; + struct regmap *regmap; + struct extcon_dev *edev; ++ ++ enum tusb320_attached_state state; + }; + + static const char * const tusb_attached_states[] = { +@@ -62,6 +79,53 @@ static int tusb320_check_signature(struct tusb320_priv *priv) + return 0; + } + ++static int tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode) ++{ ++ int ret; ++ ++ /* Mode cannot be changed while cable is attached */ ++ if (priv->state != TUSB320_ATTACHED_STATE_NONE) ++ return -EBUSY; ++ ++ /* Write mode */ ++ ret = regmap_write_bits(priv->regmap, TUSB320_REGA, ++ TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT, ++ mode << TUSB320_REGA_MODE_SELECT_SHIFT); ++ if (ret) { ++ dev_err(priv->dev, "failed to write mode: %d\n", ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int tusb320_reset(struct tusb320_priv *priv) ++{ ++ int ret; ++ ++ /* Set mode to default (follow PORT pin) */ ++ ret = tusb320_set_mode(priv, TUSB320_MODE_PORT); ++ if (ret && ret != -EBUSY) { ++ dev_err(priv->dev, ++ "failed to set mode to PORT: %d\n", ret); ++ return ret; ++ } ++ ++ /* Perform soft reset */ ++ ret = regmap_write_bits(priv->regmap, TUSB320_REGA, ++ TUSB320_REGA_I2C_SOFT_RESET, 1); ++ if (ret) { ++ dev_err(priv->dev, ++ "failed to write soft reset bit: %d\n", ret); ++ return ret; ++ } ++ ++ /* Wait for chip to go through reset */ ++ msleep(95); ++ ++ return 0; ++} ++ + static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + { + struct tusb320_priv *priv = dev_id; +@@ -96,6 +160,8 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + extcon_sync(priv->edev, EXTCON_USB); + extcon_sync(priv->edev, EXTCON_USB_HOST); + ++ priv->state = state; ++ + regmap_write(priv->regmap, TUSB320_REG9, reg); + + return IRQ_HANDLED; +@@ -145,6 +211,17 @@ static int tusb320_extcon_probe(struct i2c_client *client, + /* update initial state */ + tusb320_irq_handler(client->irq, priv); + ++ /* Reset chip to its default state */ ++ ret = tusb320_reset(priv); ++ if (ret) ++ dev_warn(priv->dev, "failed to reset chip: %d\n", ret); ++ else ++ /* ++ * State and polarity might change after a reset, so update ++ * them again and make sure the interrupt status bit is cleared. ++ */ ++ tusb320_irq_handler(client->irq, priv); ++ + ret = devm_request_threaded_irq(priv->dev, client->irq, NULL, + tusb320_irq_handler, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, +-- +2.35.1 + diff --git a/queue-5.15/extcon-usbc-tusb320-add-support-for-tusb320l.patch b/queue-5.15/extcon-usbc-tusb320-add-support-for-tusb320l.patch new file mode 100644 index 00000000000..f8c7ebf44fe --- /dev/null +++ b/queue-5.15/extcon-usbc-tusb320-add-support-for-tusb320l.patch @@ -0,0 +1,185 @@ +From 574ee93a0177aba851a3687df48748db3ef86d95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 25 Sep 2021 05:45:54 +0000 +Subject: extcon: usbc-tusb320: Add support for TUSB320L + +From: Yassine Oudjana + +[ Upstream commit ce0320bd3872038569be360870e2d5251b975692 ] + +TUSB320L is a newer chip with additional features, and it has additional steps +in its mode changing sequence: + - Disable CC state machine, + - Write to mode register, + - Wait for 5 ms, + - Re-enable CC state machine. +It also has an additional register that a revision number can be read from. + +Add support for the mode changing sequence, and read the revision number during +probe and print it as info. + +Signed-off-by: Yassine Oudjana +Signed-off-by: Chanwoo Choi +Stable-dep-of: 581c848b610d ("extcon: usbc-tusb320: Update state on probe even if no IRQ pending") +Signed-off-by: Sasha Levin +--- + drivers/extcon/extcon-usbc-tusb320.c | 82 +++++++++++++++++++++++++++- + 1 file changed, 79 insertions(+), 3 deletions(-) + +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index 1ed1dfe54206..6ba3d89b106d 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -21,10 +21,13 @@ + #define TUSB320_REG9_INTERRUPT_STATUS BIT(4) + + #define TUSB320_REGA 0xa ++#define TUSB320L_REGA_DISABLE_TERM BIT(0) + #define TUSB320_REGA_I2C_SOFT_RESET BIT(3) + #define TUSB320_REGA_MODE_SELECT_SHIFT 4 + #define TUSB320_REGA_MODE_SELECT_MASK 0x3 + ++#define TUSB320L_REGA0_REVISION 0xa0 ++ + enum tusb320_attached_state { + TUSB320_ATTACHED_STATE_NONE, + TUSB320_ATTACHED_STATE_DFP, +@@ -39,11 +42,18 @@ enum tusb320_mode { + TUSB320_MODE_DRP, + }; + ++struct tusb320_priv; ++ ++struct tusb320_ops { ++ int (*set_mode)(struct tusb320_priv *priv, enum tusb320_mode mode); ++ int (*get_revision)(struct tusb320_priv *priv, unsigned int *revision); ++}; ++ + struct tusb320_priv { + struct device *dev; + struct regmap *regmap; + struct extcon_dev *edev; +- ++ struct tusb320_ops *ops; + enum tusb320_attached_state state; + }; + +@@ -99,12 +109,46 @@ static int tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode) + return 0; + } + ++static int tusb320l_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode) ++{ ++ int ret; ++ ++ /* Disable CC state machine */ ++ ret = regmap_write_bits(priv->regmap, TUSB320_REGA, ++ TUSB320L_REGA_DISABLE_TERM, 1); ++ if (ret) { ++ dev_err(priv->dev, ++ "failed to disable CC state machine: %d\n", ret); ++ return ret; ++ } ++ ++ /* Write mode */ ++ ret = regmap_write_bits(priv->regmap, TUSB320_REGA, ++ TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT, ++ mode << TUSB320_REGA_MODE_SELECT_SHIFT); ++ if (ret) { ++ dev_err(priv->dev, "failed to write mode: %d\n", ret); ++ goto err; ++ } ++ ++ msleep(5); ++err: ++ /* Re-enable CC state machine */ ++ ret = regmap_write_bits(priv->regmap, TUSB320_REGA, ++ TUSB320L_REGA_DISABLE_TERM, 0); ++ if (ret) ++ dev_err(priv->dev, ++ "failed to re-enable CC state machine: %d\n", ret); ++ ++ return ret; ++} ++ + static int tusb320_reset(struct tusb320_priv *priv) + { + int ret; + + /* Set mode to default (follow PORT pin) */ +- ret = tusb320_set_mode(priv, TUSB320_MODE_PORT); ++ ret = priv->ops->set_mode(priv, TUSB320_MODE_PORT); + if (ret && ret != -EBUSY) { + dev_err(priv->dev, + "failed to set mode to PORT: %d\n", ret); +@@ -126,6 +170,20 @@ static int tusb320_reset(struct tusb320_priv *priv) + return 0; + } + ++static int tusb320l_get_revision(struct tusb320_priv *priv, unsigned int *revision) ++{ ++ return regmap_read(priv->regmap, TUSB320L_REGA0_REVISION, revision); ++} ++ ++static struct tusb320_ops tusb320_ops = { ++ .set_mode = tusb320_set_mode, ++}; ++ ++static struct tusb320_ops tusb320l_ops = { ++ .set_mode = tusb320l_set_mode, ++ .get_revision = tusb320l_get_revision, ++}; ++ + static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + { + struct tusb320_priv *priv = dev_id; +@@ -176,6 +234,8 @@ static int tusb320_extcon_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { + struct tusb320_priv *priv; ++ const void *match_data; ++ unsigned int revision; + int ret; + + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); +@@ -191,12 +251,27 @@ static int tusb320_extcon_probe(struct i2c_client *client, + if (ret) + return ret; + ++ match_data = device_get_match_data(&client->dev); ++ if (!match_data) ++ return -EINVAL; ++ ++ priv->ops = (struct tusb320_ops*)match_data; ++ + priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable); + if (IS_ERR(priv->edev)) { + dev_err(priv->dev, "failed to allocate extcon device\n"); + return PTR_ERR(priv->edev); + } + ++ if (priv->ops->get_revision) { ++ ret = priv->ops->get_revision(priv, &revision); ++ if (ret) ++ dev_warn(priv->dev, ++ "failed to read revision register: %d\n", ret); ++ else ++ dev_info(priv->dev, "chip revision %d\n", revision); ++ } ++ + ret = devm_extcon_dev_register(priv->dev, priv->edev); + if (ret < 0) { + dev_err(priv->dev, "failed to register extcon device\n"); +@@ -231,7 +306,8 @@ static int tusb320_extcon_probe(struct i2c_client *client, + } + + static const struct of_device_id tusb320_extcon_dt_match[] = { +- { .compatible = "ti,tusb320", }, ++ { .compatible = "ti,tusb320", .data = &tusb320_ops, }, ++ { .compatible = "ti,tusb320l", .data = &tusb320l_ops, }, + { } + }; + MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); +-- +2.35.1 + diff --git a/queue-5.15/extcon-usbc-tusb320-add-usb-type-c-support.patch b/queue-5.15/extcon-usbc-tusb320-add-usb-type-c-support.patch new file mode 100644 index 00000000000..78c382da524 --- /dev/null +++ b/queue-5.15/extcon-usbc-tusb320-add-usb-type-c-support.patch @@ -0,0 +1,267 @@ +From 8291def16d7ca41439139cddd3ecfe552be18d71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Jul 2022 20:05:00 +0200 +Subject: extcon: usbc-tusb320: Add USB TYPE-C support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Vasut + +[ Upstream commit bf7571c00dca0a9c5af3f5125ef5a89a40b13cd5 ] + +The TI TUSB320 seems like a better fit for USB TYPE-C subsystem, +which can expose details collected by the TUSB320 in a far more +precise way than extcon. Since there are existing users in the +kernel and in DT which depend on the extcon interface, keep it +for now. + +Add TYPE-C interface and expose the supported supply current, +direction and connector polarity via the TYPE-C interface. + +Signed-off-by: Marek Vasut +Acked-by: Heikki Krogerus +Reviewed-by: Alvin Å ipraga +Signed-off-by: Chanwoo Choi +Stable-dep-of: 581c848b610d ("extcon: usbc-tusb320: Update state on probe even if no IRQ pending") +Signed-off-by: Sasha Levin +--- + drivers/extcon/Kconfig | 2 +- + drivers/extcon/extcon-usbc-tusb320.c | 159 +++++++++++++++++++++++++++ + 2 files changed, 160 insertions(+), 1 deletion(-) + +diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig +index c69d40ae5619..7684b3afa630 100644 +--- a/drivers/extcon/Kconfig ++++ b/drivers/extcon/Kconfig +@@ -180,7 +180,7 @@ config EXTCON_USBC_CROS_EC + + config EXTCON_USBC_TUSB320 + tristate "TI TUSB320 USB-C extcon support" +- depends on I2C ++ depends on I2C && TYPEC + select REGMAP_I2C + help + Say Y here to enable support for USB Type C cable detection extcon +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index aced4bbb455d..edb8c3f997c9 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -6,6 +6,7 @@ + * Author: Michael Auchter + */ + ++#include + #include + #include + #include +@@ -13,6 +14,24 @@ + #include + #include + #include ++#include ++ ++#define TUSB320_REG8 0x8 ++#define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6) ++#define TUSB320_REG8_CURRENT_MODE_ADVERTISE_USB 0x0 ++#define TUSB320_REG8_CURRENT_MODE_ADVERTISE_15A 0x1 ++#define TUSB320_REG8_CURRENT_MODE_ADVERTISE_30A 0x2 ++#define TUSB320_REG8_CURRENT_MODE_DETECT GENMASK(5, 4) ++#define TUSB320_REG8_CURRENT_MODE_DETECT_DEF 0x0 ++#define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1 ++#define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2 ++#define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3 ++#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 2) ++#define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0 ++#define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4 ++#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC 0x5 ++#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6 ++#define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0) + + #define TUSB320_REG9 0x9 + #define TUSB320_REG9_ATTACHED_STATE_SHIFT 6 +@@ -55,6 +74,10 @@ struct tusb320_priv { + struct extcon_dev *edev; + struct tusb320_ops *ops; + enum tusb320_attached_state state; ++ struct typec_port *port; ++ struct typec_capability cap; ++ enum typec_port_type port_type; ++ enum typec_pwr_opmode pwr_opmode; + }; + + static const char * const tusb_attached_states[] = { +@@ -184,6 +207,44 @@ static struct tusb320_ops tusb320l_ops = { + .get_revision = tusb320l_get_revision, + }; + ++static int tusb320_set_adv_pwr_mode(struct tusb320_priv *priv) ++{ ++ u8 mode; ++ ++ if (priv->pwr_opmode == TYPEC_PWR_MODE_USB) ++ mode = TUSB320_REG8_CURRENT_MODE_ADVERTISE_USB; ++ else if (priv->pwr_opmode == TYPEC_PWR_MODE_1_5A) ++ mode = TUSB320_REG8_CURRENT_MODE_ADVERTISE_15A; ++ else if (priv->pwr_opmode == TYPEC_PWR_MODE_3_0A) ++ mode = TUSB320_REG8_CURRENT_MODE_ADVERTISE_30A; ++ else /* No other mode is supported. */ ++ return -EINVAL; ++ ++ return regmap_write_bits(priv->regmap, TUSB320_REG8, ++ TUSB320_REG8_CURRENT_MODE_ADVERTISE, ++ FIELD_PREP(TUSB320_REG8_CURRENT_MODE_ADVERTISE, ++ mode)); ++} ++ ++static int tusb320_port_type_set(struct typec_port *port, ++ enum typec_port_type type) ++{ ++ struct tusb320_priv *priv = typec_get_drvdata(port); ++ ++ if (type == TYPEC_PORT_SRC) ++ return priv->ops->set_mode(priv, TUSB320_MODE_DFP); ++ else if (type == TYPEC_PORT_SNK) ++ return priv->ops->set_mode(priv, TUSB320_MODE_UFP); ++ else if (type == TYPEC_PORT_DRP) ++ return priv->ops->set_mode(priv, TUSB320_MODE_DRP); ++ else ++ return priv->ops->set_mode(priv, TUSB320_MODE_PORT); ++} ++ ++static const struct typec_operations tusb320_typec_ops = { ++ .port_type_set = tusb320_port_type_set, ++}; ++ + static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg) + { + int state, polarity; +@@ -211,6 +272,47 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg) + priv->state = state; + } + ++static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9) ++{ ++ struct typec_port *port = priv->port; ++ struct device *dev = priv->dev; ++ u8 mode, role, state; ++ int ret, reg8; ++ bool ori; ++ ++ ori = reg9 & TUSB320_REG9_CABLE_DIRECTION; ++ typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE : ++ TYPEC_ORIENTATION_NORMAL); ++ ++ state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & ++ TUSB320_REG9_ATTACHED_STATE_MASK; ++ if (state == TUSB320_ATTACHED_STATE_DFP) ++ role = TYPEC_SOURCE; ++ else ++ role = TYPEC_SINK; ++ ++ typec_set_vconn_role(port, role); ++ typec_set_pwr_role(port, role); ++ typec_set_data_role(port, role == TYPEC_SOURCE ? ++ TYPEC_HOST : TYPEC_DEVICE); ++ ++ ret = regmap_read(priv->regmap, TUSB320_REG8, ®8); ++ if (ret) { ++ dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret); ++ return; ++ } ++ ++ mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8); ++ if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF) ++ typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB); ++ else if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_MED) ++ typec_set_pwr_opmode(port, TYPEC_PWR_MODE_1_5A); ++ else if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_HI) ++ typec_set_pwr_opmode(port, TYPEC_PWR_MODE_3_0A); ++ else /* Charge through accessory */ ++ typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB); ++} ++ + static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + { + struct tusb320_priv *priv = dev_id; +@@ -225,6 +327,7 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + return IRQ_NONE; + + tusb320_extcon_irq_handler(priv, reg); ++ tusb320_typec_irq_handler(priv, reg); + + regmap_write(priv->regmap, TUSB320_REG9, reg); + +@@ -260,6 +363,58 @@ static int tusb320_extcon_probe(struct tusb320_priv *priv) + return 0; + } + ++static int tusb320_typec_probe(struct i2c_client *client, ++ struct tusb320_priv *priv) ++{ ++ struct fwnode_handle *connector; ++ const char *cap_str; ++ int ret; ++ ++ /* The Type-C connector is optional, for backward compatibility. */ ++ connector = device_get_named_child_node(&client->dev, "connector"); ++ if (!connector) ++ return 0; ++ ++ /* Type-C connector found. */ ++ ret = typec_get_fw_cap(&priv->cap, connector); ++ if (ret) ++ return ret; ++ ++ priv->port_type = priv->cap.type; ++ ++ /* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */ ++ ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str); ++ if (ret) ++ return ret; ++ ++ ret = typec_find_pwr_opmode(cap_str); ++ if (ret < 0) ++ return ret; ++ if (ret == TYPEC_PWR_MODE_PD) ++ return -EINVAL; ++ ++ priv->pwr_opmode = ret; ++ ++ /* Initialize the hardware with the devicetree settings. */ ++ ret = tusb320_set_adv_pwr_mode(priv); ++ if (ret) ++ return ret; ++ ++ priv->cap.revision = USB_TYPEC_REV_1_1; ++ priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO; ++ priv->cap.accessory[1] = TYPEC_ACCESSORY_DEBUG; ++ priv->cap.orientation_aware = true; ++ priv->cap.driver_data = priv; ++ priv->cap.ops = &tusb320_typec_ops; ++ priv->cap.fwnode = connector; ++ ++ priv->port = typec_register_port(&client->dev, &priv->cap); ++ if (IS_ERR(priv->port)) ++ return PTR_ERR(priv->port); ++ ++ return 0; ++} ++ + static int tusb320_probe(struct i2c_client *client, + const struct i2c_device_id *id) + { +@@ -300,6 +455,10 @@ static int tusb320_probe(struct i2c_client *client, + if (ret) + return ret; + ++ ret = tusb320_typec_probe(client, priv); ++ if (ret) ++ return ret; ++ + /* update initial state */ + tusb320_irq_handler(client->irq, priv); + +-- +2.35.1 + diff --git a/queue-5.15/extcon-usbc-tusb320-factor-out-extcon-into-dedicated.patch b/queue-5.15/extcon-usbc-tusb320-factor-out-extcon-into-dedicated.patch new file mode 100644 index 00000000000..75bb0acaab3 --- /dev/null +++ b/queue-5.15/extcon-usbc-tusb320-factor-out-extcon-into-dedicated.patch @@ -0,0 +1,147 @@ +From 6e43dfed23f3218693173e6d2b3b180ec99641bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Jul 2022 20:04:59 +0200 +Subject: extcon: usbc-tusb320: Factor out extcon into dedicated functions + +From: Marek Vasut + +[ Upstream commit 9483811a126a319ecac749f1b767ea5faecc7aed ] + +Move extcon code into separate functions in preparation for addition of +USB TYPE-C support. No functional change. + +Signed-off-by: Marek Vasut +Signed-off-by: Chanwoo Choi +Stable-dep-of: 581c848b610d ("extcon: usbc-tusb320: Update state on probe even if no IRQ pending") +Signed-off-by: Sasha Levin +--- + drivers/extcon/extcon-usbc-tusb320.c | 75 +++++++++++++++++----------- + 1 file changed, 46 insertions(+), 29 deletions(-) + +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index 6ba3d89b106d..aced4bbb455d 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -184,19 +184,9 @@ static struct tusb320_ops tusb320l_ops = { + .get_revision = tusb320l_get_revision, + }; + +-static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg) + { +- struct tusb320_priv *priv = dev_id; + int state, polarity; +- unsigned reg; +- +- if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { +- dev_err(priv->dev, "error during i2c read!\n"); +- return IRQ_NONE; +- } +- +- if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) +- return IRQ_NONE; + + state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) & + TUSB320_REG9_ATTACHED_STATE_MASK; +@@ -219,6 +209,22 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + extcon_sync(priv->edev, EXTCON_USB_HOST); + + priv->state = state; ++} ++ ++static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++{ ++ struct tusb320_priv *priv = dev_id; ++ unsigned int reg; ++ ++ if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { ++ dev_err(priv->dev, "error during i2c read!\n"); ++ return IRQ_NONE; ++ } ++ ++ if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) ++ return IRQ_NONE; ++ ++ tusb320_extcon_irq_handler(priv, reg); + + regmap_write(priv->regmap, TUSB320_REG9, reg); + +@@ -230,8 +236,32 @@ static const struct regmap_config tusb320_regmap_config = { + .val_bits = 8, + }; + +-static int tusb320_extcon_probe(struct i2c_client *client, +- const struct i2c_device_id *id) ++static int tusb320_extcon_probe(struct tusb320_priv *priv) ++{ ++ int ret; ++ ++ priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable); ++ if (IS_ERR(priv->edev)) { ++ dev_err(priv->dev, "failed to allocate extcon device\n"); ++ return PTR_ERR(priv->edev); ++ } ++ ++ ret = devm_extcon_dev_register(priv->dev, priv->edev); ++ if (ret < 0) { ++ dev_err(priv->dev, "failed to register extcon device\n"); ++ return ret; ++ } ++ ++ extcon_set_property_capability(priv->edev, EXTCON_USB, ++ EXTCON_PROP_USB_TYPEC_POLARITY); ++ extcon_set_property_capability(priv->edev, EXTCON_USB_HOST, ++ EXTCON_PROP_USB_TYPEC_POLARITY); ++ ++ return 0; ++} ++ ++static int tusb320_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) + { + struct tusb320_priv *priv; + const void *match_data; +@@ -257,12 +287,6 @@ static int tusb320_extcon_probe(struct i2c_client *client, + + priv->ops = (struct tusb320_ops*)match_data; + +- priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable); +- if (IS_ERR(priv->edev)) { +- dev_err(priv->dev, "failed to allocate extcon device\n"); +- return PTR_ERR(priv->edev); +- } +- + if (priv->ops->get_revision) { + ret = priv->ops->get_revision(priv, &revision); + if (ret) +@@ -272,16 +296,9 @@ static int tusb320_extcon_probe(struct i2c_client *client, + dev_info(priv->dev, "chip revision %d\n", revision); + } + +- ret = devm_extcon_dev_register(priv->dev, priv->edev); +- if (ret < 0) { +- dev_err(priv->dev, "failed to register extcon device\n"); ++ ret = tusb320_extcon_probe(priv); ++ if (ret) + return ret; +- } +- +- extcon_set_property_capability(priv->edev, EXTCON_USB, +- EXTCON_PROP_USB_TYPEC_POLARITY); +- extcon_set_property_capability(priv->edev, EXTCON_USB_HOST, +- EXTCON_PROP_USB_TYPEC_POLARITY); + + /* update initial state */ + tusb320_irq_handler(client->irq, priv); +@@ -313,7 +330,7 @@ static const struct of_device_id tusb320_extcon_dt_match[] = { + MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match); + + static struct i2c_driver tusb320_extcon_driver = { +- .probe = tusb320_extcon_probe, ++ .probe = tusb320_probe, + .driver = { + .name = "extcon-tusb320", + .of_match_table = tusb320_extcon_dt_match, +-- +2.35.1 + diff --git a/queue-5.15/extcon-usbc-tusb320-update-state-on-probe-even-if-no.patch b/queue-5.15/extcon-usbc-tusb320-update-state-on-probe-even-if-no.patch new file mode 100644 index 00000000000..3fcff1a4744 --- /dev/null +++ b/queue-5.15/extcon-usbc-tusb320-update-state-on-probe-even-if-no.patch @@ -0,0 +1,104 @@ +From 48ad5508e724c7600aec65651f05dd4fe80633bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 15:15:09 +0100 +Subject: extcon: usbc-tusb320: Update state on probe even if no IRQ pending +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Vasut + +[ Upstream commit 581c848b610dbf3fe1ed4d85fd53d0743c61faba ] + +Currently this driver triggers extcon and typec state update in its +probe function, to read out current state reported by the chip and +report the correct state to upper layers. This synchronization is +performed correctly, but only in case the chip indicates a pending +interrupt in reg09 register. + +This fails to cover the situation where all interrupts reported by +the chip were already handled by Linux before reboot, then the system +rebooted, and then Linux starts again. In this case, the TUSB320 no +longer reports any interrupts in reg09, and the state update does not +perform any update as it depends on that interrupt indication. + +Fix this by turning tusb320_irq_handler() into a thin wrapper around +tusb320_state_update_handler(), where the later now contains the bulk +of the code of tusb320_irq_handler(), but adds new function parameter +"force_update". The "force_update" parameter can be used by the probe +function to assure that the state synchronization is always performed, +independent of the interrupt indicated in reg09. The interrupt handler +tusb320_irq_handler() callback uses force_update=false to avoid state +updates on potential spurious interrupts and retain current behavior. + +Fixes: 06bc4ca115cdd ("extcon: Add driver for TI TUSB320") +Signed-off-by: Marek Vasut +Reviewed-by: Alvin Å ipraga +Acked-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20221120141509.81012-1-marex@denx.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/extcon/extcon-usbc-tusb320.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c +index edb8c3f997c9..b0f6e16ab0a9 100644 +--- a/drivers/extcon/extcon-usbc-tusb320.c ++++ b/drivers/extcon/extcon-usbc-tusb320.c +@@ -313,9 +313,9 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9) + typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB); + } + +-static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++static irqreturn_t tusb320_state_update_handler(struct tusb320_priv *priv, ++ bool force_update) + { +- struct tusb320_priv *priv = dev_id; + unsigned int reg; + + if (regmap_read(priv->regmap, TUSB320_REG9, ®)) { +@@ -323,7 +323,7 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + return IRQ_NONE; + } + +- if (!(reg & TUSB320_REG9_INTERRUPT_STATUS)) ++ if (!force_update && !(reg & TUSB320_REG9_INTERRUPT_STATUS)) + return IRQ_NONE; + + tusb320_extcon_irq_handler(priv, reg); +@@ -334,6 +334,13 @@ static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) + return IRQ_HANDLED; + } + ++static irqreturn_t tusb320_irq_handler(int irq, void *dev_id) ++{ ++ struct tusb320_priv *priv = dev_id; ++ ++ return tusb320_state_update_handler(priv, false); ++} ++ + static const struct regmap_config tusb320_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -460,7 +467,7 @@ static int tusb320_probe(struct i2c_client *client, + return ret; + + /* update initial state */ +- tusb320_irq_handler(client->irq, priv); ++ tusb320_state_update_handler(priv, true); + + /* Reset chip to its default state */ + ret = tusb320_reset(priv); +@@ -471,7 +478,7 @@ static int tusb320_probe(struct i2c_client *client, + * State and polarity might change after a reset, so update + * them again and make sure the interrupt status bit is cleared. + */ +- tusb320_irq_handler(client->irq, priv); ++ tusb320_state_update_handler(priv, true); + + ret = devm_request_threaded_irq(priv->dev, client->irq, NULL, + tusb320_irq_handler, +-- +2.35.1 + diff --git a/queue-5.15/f2fs-avoid-victim-selection-from-previous-victim-sec.patch b/queue-5.15/f2fs-avoid-victim-selection-from-previous-victim-sec.patch new file mode 100644 index 00000000000..13b2ccaaf0b --- /dev/null +++ b/queue-5.15/f2fs-avoid-victim-selection-from-previous-victim-sec.patch @@ -0,0 +1,48 @@ +From e9371b7854aad25ab220ee311eef3938ea3f1186 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 18:03:20 +0900 +Subject: f2fs: avoid victim selection from previous victim section + +From: Yonggil Song + +[ Upstream commit e219aecfd4b766c4e878a3769057e9809f7fcadc ] + +When f2fs chooses GC victim in large section & LFS mode, +next_victim_seg[gc_type] is referenced first. After segment is freed, +next_victim_seg[gc_type] has the next segment number. +However, next_victim_seg[gc_type] still has the last segment number +even after the last segment of section is freed. In this case, when f2fs +chooses a victim for the next GC round, the last segment of previous victim +section is chosen as a victim. + +Initialize next_victim_seg[gc_type] to NULL_SEGNO for the last segment in +large section. + +Fixes: e3080b0120a1 ("f2fs: support subsectional garbage collection") +Signed-off-by: Yonggil Song +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/gc.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index 4cbaa6ab083f..7863f8fd3b95 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -1673,8 +1673,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, + get_valid_blocks(sbi, segno, false) == 0) + seg_freed++; + +- if (__is_large_section(sbi) && segno + 1 < end_segno) +- sbi->next_victim_seg[gc_type] = segno + 1; ++ if (__is_large_section(sbi)) ++ sbi->next_victim_seg[gc_type] = ++ (segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO; + skip: + f2fs_put_page(sum_page, 0); + } +-- +2.35.1 + diff --git a/queue-5.15/f2fs-fix-normal-discard-process.patch b/queue-5.15/f2fs-fix-normal-discard-process.patch new file mode 100644 index 00000000000..22e1b8a1f8e --- /dev/null +++ b/queue-5.15/f2fs-fix-normal-discard-process.patch @@ -0,0 +1,43 @@ +From fcf7888192cdbb2ab1c5de403adcffa17c2ed62c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 17:40:36 +0800 +Subject: f2fs: fix normal discard process + +From: Dongdong Zhang + +[ Upstream commit b5f1a218ae5e4339130d6e733f0e63d623e09a2c ] + +In the DPOLICY_BG mode, there is a conflict between +the two conditions "i + 1 < dpolicy->granularity" and +"i < DEFAULT_DISCARD_GRANULARITY". If i = 15, the first +condition is false, it will enter the second condition +and dispatch all small granularity discards in function + __issue_discard_cmd_orderly. The restrictive effect +of the first condition to small discards will be +invalidated. These two conditions should align. + +Fixes: 20ee4382322c ("f2fs: issue small discard by LBA order") +Signed-off-by: Dongdong Zhang +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 28939e3573ea..194c0811fbdf 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -1551,7 +1551,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi, + if (i + 1 < dpolicy->granularity) + break; + +- if (i < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered) ++ if (i + 1 < DEFAULT_DISCARD_GRANULARITY && dpolicy->ordered) + return __issue_discard_cmd_orderly(sbi, dpolicy); + + pend_list = &dcc->pend_list[i]; +-- +2.35.1 + diff --git a/queue-5.15/f2fs-fix-the-race-condition-of-resize-flag-between-r.patch b/queue-5.15/f2fs-fix-the-race-condition-of-resize-flag-between-r.patch new file mode 100644 index 00000000000..57139c958af --- /dev/null +++ b/queue-5.15/f2fs-fix-the-race-condition-of-resize-flag-between-r.patch @@ -0,0 +1,74 @@ +From 54b7534194fb953130faff104e5a015ad3ecc342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 10:45:32 +0800 +Subject: f2fs: Fix the race condition of resize flag between resizefs + +From: Zhang Qilong + +[ Upstream commit 28fc4e9077ce59ab28c89c20dc6be5154473218f ] + +Because the set/clear SBI_IS_RESIZEFS flag not between any locks, +In the following case: + thread1 thread2 + ->ioctl(resizefs) + ->set RESIZEFS flag ->ioctl(resizefs) + ... ->set RESIZEFS flag + ->clear RESIZEFS flag + ->resizefs stream + # No RESIZEFS flag in the stream + +Also before freeze_super, the resizefs not started, we should not set +the SBI_IS_RESIZEFS flag. + +So move the set/clear SBI_IS_RESIZEFS flag between the cp_mutex and +gc_lock. + +Fixes: b4b10061ef98 ("f2fs: refactor resize_fs to avoid meta updates in progress") +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Zhang Qilong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/gc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c +index e75a276f5b9c..4cbaa6ab083f 100644 +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -2051,8 +2051,6 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) + if (err) + return err; + +- set_sbi_flag(sbi, SBI_IS_RESIZEFS); +- + freeze_super(sbi->sb); + down_write(&sbi->gc_lock); + down_write(&sbi->cp_global_sem); +@@ -2068,6 +2066,7 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) + if (err) + goto out_err; + ++ set_sbi_flag(sbi, SBI_IS_RESIZEFS); + err = free_segment_range(sbi, secs, false); + if (err) + goto recover_out; +@@ -2091,6 +2090,7 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) + f2fs_commit_super(sbi, false); + } + recover_out: ++ clear_sbi_flag(sbi, SBI_IS_RESIZEFS); + if (err) { + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_err(sbi, "resize_fs failed, should run fsck to repair!"); +@@ -2103,6 +2103,5 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count) + up_write(&sbi->cp_global_sem); + up_write(&sbi->gc_lock); + thaw_super(sbi->sb); +- clear_sbi_flag(sbi, SBI_IS_RESIZEFS); + return err; + } +-- +2.35.1 + diff --git a/queue-5.15/f2fs-fix-to-destroy-sbi-post_read_wq-in-error-path-o.patch b/queue-5.15/f2fs-fix-to-destroy-sbi-post_read_wq-in-error-path-o.patch new file mode 100644 index 00000000000..4e489b2e96a --- /dev/null +++ b/queue-5.15/f2fs-fix-to-destroy-sbi-post_read_wq-in-error-path-o.patch @@ -0,0 +1,39 @@ +From 7939abeb2fc45a15fed371f207445b9fea64bd16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 17:30:26 +0800 +Subject: f2fs: fix to destroy sbi->post_read_wq in error path of + f2fs_fill_super() + +From: Chao Yu + +[ Upstream commit 7b02b2201893a71b881026cf574902019ab00db5 ] + +In error path of f2fs_fill_super(), this patch fixes to call +f2fs_destroy_post_read_wq() once if we fail in f2fs_start_ckpt_thread(). + +Fixes: 261eeb9c1585 ("f2fs: introduce checkpoint_merge mount option") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c +index a0d1ef73b83e..f4e8de1f4789 100644 +--- a/fs/f2fs/super.c ++++ b/fs/f2fs/super.c +@@ -4428,9 +4428,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) + f2fs_destroy_node_manager(sbi); + free_sm: + f2fs_destroy_segment_manager(sbi); +- f2fs_destroy_post_read_wq(sbi); + stop_ckpt_thread: + f2fs_stop_ckpt_thread(sbi); ++ f2fs_destroy_post_read_wq(sbi); + free_devices: + destroy_device_list(sbi); + kvfree(sbi->ckpt); +-- +2.35.1 + diff --git a/queue-5.15/f2fs-fix-to-invalidate-dcc-f2fs_issue_discard-in-err.patch b/queue-5.15/f2fs-fix-to-invalidate-dcc-f2fs_issue_discard-in-err.patch new file mode 100644 index 00000000000..522fd7edddc --- /dev/null +++ b/queue-5.15/f2fs-fix-to-invalidate-dcc-f2fs_issue_discard-in-err.patch @@ -0,0 +1,70 @@ +From 941cb02e94e488b756179422a1b8f9e95ce4c606 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 10:34:22 +0800 +Subject: f2fs: fix to invalidate dcc->f2fs_issue_discard in error path + +From: Chao Yu + +[ Upstream commit 91586ce0d39a05f88795aa8814fb99b1387236b3 ] + +Syzbot reports a NULL pointer dereference issue as below: + + __refcount_add include/linux/refcount.h:193 [inline] + __refcount_inc include/linux/refcount.h:250 [inline] + refcount_inc include/linux/refcount.h:267 [inline] + get_task_struct include/linux/sched/task.h:110 [inline] + kthread_stop+0x34/0x1c0 kernel/kthread.c:703 + f2fs_stop_discard_thread+0x3c/0x5c fs/f2fs/segment.c:1638 + kill_f2fs_super+0x5c/0x194 fs/f2fs/super.c:4522 + deactivate_locked_super+0x70/0xe8 fs/super.c:332 + deactivate_super+0xd0/0xd4 fs/super.c:363 + cleanup_mnt+0x1f8/0x234 fs/namespace.c:1186 + __cleanup_mnt+0x20/0x30 fs/namespace.c:1193 + task_work_run+0xc4/0x14c kernel/task_work.c:177 + exit_task_work include/linux/task_work.h:38 [inline] + do_exit+0x26c/0xbe0 kernel/exit.c:795 + do_group_exit+0x60/0xe8 kernel/exit.c:925 + __do_sys_exit_group kernel/exit.c:936 [inline] + __se_sys_exit_group kernel/exit.c:934 [inline] + __wake_up_parent+0x0/0x40 kernel/exit.c:934 + __invoke_syscall arch/arm64/kernel/syscall.c:38 [inline] + invoke_syscall arch/arm64/kernel/syscall.c:52 [inline] + el0_svc_common+0x138/0x220 arch/arm64/kernel/syscall.c:142 + do_el0_svc+0x48/0x164 arch/arm64/kernel/syscall.c:206 + el0_svc+0x58/0x150 arch/arm64/kernel/entry-common.c:636 + el0t_64_sync_handler+0x84/0xf0 arch/arm64/kernel/entry-common.c:654 + el0t_64_sync+0x18c/0x190 arch/arm64/kernel/entry.S:581 + +The root cause of this issue is in error path of f2fs_start_discard_thread(), +it missed to invalidate dcc->f2fs_issue_discard, later kthread_stop() may +access invalid pointer. + +Fixes: 4d67490498ac ("f2fs: Don't create discard thread when device doesn't support realtime discard") +Reported-by: syzbot+035a381ea1afb63f098d@syzkaller.appspotmail.com +Reported-by: syzbot+729c925c2d9fc495ddee@syzkaller.appspotmail.com +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/segment.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index af810b2d5d90..28939e3573ea 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -2129,8 +2129,10 @@ int f2fs_start_discard_thread(struct f2fs_sb_info *sbi) + + dcc->f2fs_issue_discard = kthread_run(issue_discard_thread, sbi, + "f2fs_discard-%u:%u", MAJOR(dev), MINOR(dev)); +- if (IS_ERR(dcc->f2fs_issue_discard)) ++ if (IS_ERR(dcc->f2fs_issue_discard)) { + err = PTR_ERR(dcc->f2fs_issue_discard); ++ dcc->f2fs_issue_discard = NULL; ++ } + + return err; + } +-- +2.35.1 + diff --git a/queue-5.15/fbdev-ep93xx-fb-add-missing-clk_disable_unprepare-in.patch b/queue-5.15/fbdev-ep93xx-fb-add-missing-clk_disable_unprepare-in.patch new file mode 100644 index 00000000000..b9d4cfc945c --- /dev/null +++ b/queue-5.15/fbdev-ep93xx-fb-add-missing-clk_disable_unprepare-in.patch @@ -0,0 +1,44 @@ +From 4ad254b85e2ddc20710d921eb6e44227355c2931 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 17:29:43 +0800 +Subject: fbdev: ep93xx-fb: Add missing clk_disable_unprepare in + ep93xxfb_probe() + +From: Gaosheng Cui + +[ Upstream commit c84bf485a5aaf9aa0764a58832b7ef4375c29f03 ] + +The clk_disable_unprepare() should be called in the error handling +of register_framebuffer(), fix it. + +Fixes: 0937a7b3625d ("video: ep93xx: Prepare clock before using it") +Signed-off-by: Gaosheng Cui +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/ep93xx-fb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c +index 2398b3d48fed..305f1587bd89 100644 +--- a/drivers/video/fbdev/ep93xx-fb.c ++++ b/drivers/video/fbdev/ep93xx-fb.c +@@ -552,12 +552,14 @@ static int ep93xxfb_probe(struct platform_device *pdev) + + err = register_framebuffer(info); + if (err) +- goto failed_check; ++ goto failed_framebuffer; + + dev_info(info->dev, "registered. Mode = %dx%d-%d\n", + info->var.xres, info->var.yres, info->var.bits_per_pixel); + return 0; + ++failed_framebuffer: ++ clk_disable_unprepare(fbi->clk); + failed_check: + if (fbi->mach_info->teardown) + fbi->mach_info->teardown(pdev); +-- +2.35.1 + diff --git a/queue-5.15/fbdev-geode-don-t-build-on-uml.patch b/queue-5.15/fbdev-geode-don-t-build-on-uml.patch new file mode 100644 index 00000000000..3b8b64d2664 --- /dev/null +++ b/queue-5.15/fbdev-geode-don-t-build-on-uml.patch @@ -0,0 +1,70 @@ +From f9d70ba4229351d6ea5f8704f4941df428e8a037 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 13:55:44 -0800 +Subject: fbdev: geode: don't build on UML +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Randy Dunlap + +[ Upstream commit 71c53e19226b0166ba387d3c590d0509f541a0a1 ] + +The geode fbdev driver uses struct cpuinfo fields that are not present +on ARCH=um, so don't allow this driver to be built on UML. + +Prevents these build errors: + +In file included from ../arch/x86/include/asm/olpc.h:7:0, + from ../drivers/mfd/cs5535-mfd.c:17: +../arch/x86/include/asm/geode.h: In function ‘is_geode_gx’: +../arch/x86/include/asm/geode.h:16:24: error: ‘struct cpuinfo_um’ has no member named ‘x86_vendor’ + return ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC) && +../arch/x86/include/asm/geode.h:16:39: error: ‘X86_VENDOR_NSC’ undeclared (first use in this function); did you mean ‘X86_VENDOR_ANY’? + return ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC) && +../arch/x86/include/asm/geode.h:17:17: error: ‘struct cpuinfo_um’ has no member named ‘x86’ + (boot_cpu_data.x86 == 5) && +../arch/x86/include/asm/geode.h:18:17: error: ‘struct cpuinfo_um’ has no member named ‘x86_model’ + (boot_cpu_data.x86_model == 5)); +../arch/x86/include/asm/geode.h: In function ‘is_geode_lx’: +../arch/x86/include/asm/geode.h:23:24: error: ‘struct cpuinfo_um’ has no member named ‘x86_vendor’ + return ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && +../arch/x86/include/asm/geode.h:23:39: error: ‘X86_VENDOR_AMD’ undeclared (first use in this function); did you mean ‘X86_VENDOR_ANY’? + return ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && +../arch/x86/include/asm/geode.h:24:17: error: ‘struct cpuinfo_um’ has no member named ‘x86’ + (boot_cpu_data.x86 == 5) && +../arch/x86/include/asm/geode.h:25:17: error: ‘struct cpuinfo_um’ has no member named ‘x86_model’ + (boot_cpu_data.x86_model == 10)); + +Fixes: 68f5d3f3b654 ("um: add PCI over virtio emulation driver") +Signed-off-by: Randy Dunlap +Cc: Johannes Berg +Cc: Richard Weinberger +Cc: linux-um@lists.infradead.org +Cc: Daniel Vetter +Cc: Helge Deller +Cc: linux-fbdev@vger.kernel.org +Cc: dri-devel@lists.freedesktop.org +Cc: Andres Salomon +Cc: linux-geode@lists.infradead.org +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/geode/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/video/fbdev/geode/Kconfig b/drivers/video/fbdev/geode/Kconfig +index ac9c860592aa..85bc14b6faf6 100644 +--- a/drivers/video/fbdev/geode/Kconfig ++++ b/drivers/video/fbdev/geode/Kconfig +@@ -5,6 +5,7 @@ + config FB_GEODE + bool "AMD Geode family framebuffer support" + depends on FB && PCI && (X86_32 || (X86 && COMPILE_TEST)) ++ depends on !UML + help + Say 'Y' here to allow you to select framebuffer drivers for + the AMD Geode family of processors. +-- +2.35.1 + diff --git a/queue-5.15/fbdev-pm2fb-fix-missing-pci_disable_device.patch b/queue-5.15/fbdev-pm2fb-fix-missing-pci_disable_device.patch new file mode 100644 index 00000000000..610b859755d --- /dev/null +++ b/queue-5.15/fbdev-pm2fb-fix-missing-pci_disable_device.patch @@ -0,0 +1,56 @@ +From 4a5c96eed84665c0c723ce09ee792c28526abf4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 17:55:10 +0800 +Subject: fbdev: pm2fb: fix missing pci_disable_device() + +From: Yang Yingliang + +[ Upstream commit ed359a464846b48f76ea6cc5cd8257e545ac97f4 ] + +Add missing pci_disable_device() in error path of probe() and remove() path. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/pm2fb.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c +index cbcf112c88d3..e8690f7aea05 100644 +--- a/drivers/video/fbdev/pm2fb.c ++++ b/drivers/video/fbdev/pm2fb.c +@@ -1530,8 +1530,10 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + + info = framebuffer_alloc(sizeof(struct pm2fb_par), &pdev->dev); +- if (!info) +- return -ENOMEM; ++ if (!info) { ++ err = -ENOMEM; ++ goto err_exit_disable; ++ } + default_par = info->par; + + switch (pdev->device) { +@@ -1712,6 +1714,8 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + release_mem_region(pm2fb_fix.mmio_start, pm2fb_fix.mmio_len); + err_exit_neither: + framebuffer_release(info); ++ err_exit_disable: ++ pci_disable_device(pdev); + return retval; + } + +@@ -1738,6 +1742,7 @@ static void pm2fb_remove(struct pci_dev *pdev) + fb_dealloc_cmap(&info->cmap); + kfree(info->pixmap.addr); + framebuffer_release(info); ++ pci_disable_device(pdev); + } + + static const struct pci_device_id pm2fb_id_table[] = { +-- +2.35.1 + diff --git a/queue-5.15/fbdev-ssd1307fb-drop-optional-dependency.patch b/queue-5.15/fbdev-ssd1307fb-drop-optional-dependency.patch new file mode 100644 index 00000000000..ec266083c3a --- /dev/null +++ b/queue-5.15/fbdev-ssd1307fb-drop-optional-dependency.patch @@ -0,0 +1,38 @@ +From ab437d92178b706c352956f13e85dd9158b4c662 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 17:09:46 +0200 +Subject: fbdev: ssd1307fb: Drop optional dependency + +From: Andy Shevchenko + +[ Upstream commit 025e3b507a3a8e1ee96a3112bb67495c77d6cdb6 ] + +Only a single out of three devices need a PWM, so from driver it's +optional. Moreover it's a single driver in the entire kernel that +currently selects PWM. Unfortunately this selection is a root cause +of the circular dependencies when we want to enable optional PWM +for some other drivers that select GPIOLIB. + +Fixes: a2ed00da5047 ("drivers/video: add support for the Solomon SSD1307 OLED Controller") +Signed-off-by: Andy Shevchenko +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig +index 6ed5e608dd04..5050a9f8e879 100644 +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -2218,7 +2218,6 @@ config FB_SSD1307 + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_DEFERRED_IO +- select PWM + select FB_BACKLIGHT + help + This driver implements support for the Solomon SSD1307 +-- +2.35.1 + diff --git a/queue-5.15/fbdev-uvesafb-don-t-build-on-uml.patch b/queue-5.15/fbdev-uvesafb-don-t-build-on-uml.patch new file mode 100644 index 00000000000..7dfbd8b284f --- /dev/null +++ b/queue-5.15/fbdev-uvesafb-don-t-build-on-uml.patch @@ -0,0 +1,54 @@ +From dd99e719ee3eaec7d8b4730bc93b50468e109de9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 13:55:59 -0800 +Subject: fbdev: uvesafb: don't build on UML +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Randy Dunlap + +[ Upstream commit 35b4f4d4a725cf8f8c10649163cd12aed509b953 ] + +The uvesafb fbdev driver uses memory management information that is not +available on ARCH=um, so don't allow this driver to be built on UML. + +Prevents these build errors: + +../drivers/video/fbdev/uvesafb.c: In function ‘uvesafb_vbe_init’: +../drivers/video/fbdev/uvesafb.c:807:21: error: ‘__supported_pte_mask’ undeclared (first use in this function) + 807 | if (__supported_pte_mask & _PAGE_NX) { +../drivers/video/fbdev/uvesafb.c:807:44: error: ‘_PAGE_NX’ undeclared (first use in this function) + 807 | if (__supported_pte_mask & _PAGE_NX) { + +Fixes: 68f5d3f3b654 ("um: add PCI over virtio emulation driver") +Signed-off-by: Randy Dunlap +Cc: Johannes Berg +Cc: Richard Weinberger +Cc: linux-um@lists.infradead.org +Cc: Daniel Vetter +Cc: Helge Deller +Cc: linux-fbdev@vger.kernel.org +Cc: dri-devel@lists.freedesktop.org +Cc: Michal Januszewski +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig +index 5050a9f8e879..26531aa19428 100644 +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -606,6 +606,7 @@ config FB_TGA + config FB_UVESA + tristate "Userspace VESA VGA graphics support" + depends on FB && CONNECTOR ++ depends on !UML + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT +-- +2.35.1 + diff --git a/queue-5.15/fbdev-uvesafb-fixes-an-error-handling-path-in-uvesaf.patch b/queue-5.15/fbdev-uvesafb-fixes-an-error-handling-path-in-uvesaf.patch new file mode 100644 index 00000000000..9eaec21345f --- /dev/null +++ b/queue-5.15/fbdev-uvesafb-fixes-an-error-handling-path-in-uvesaf.patch @@ -0,0 +1,39 @@ +From 548297f9e1d78bcebb09952f5180854db21a6b0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Dec 2022 12:35:22 +0100 +Subject: fbdev: uvesafb: Fixes an error handling path in uvesafb_probe() + +From: Christophe JAILLET + +[ Upstream commit a94371040712031ba129c7e9d8ff04a06a2f8207 ] + +If an error occurs after a successful uvesafb_init_mtrr() call, it must be +undone by a corresponding arch_phys_wc_del() call, as already done in the +remove function. + +This has been added in the remove function in commit 63e28a7a5ffc +("uvesafb: Clean up MTRR code") + +Fixes: 8bdb3a2d7df4 ("uvesafb: the driver core") +Signed-off-by: Christophe JAILLET +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/uvesafb.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c +index 4df6772802d7..1f3b7e013568 100644 +--- a/drivers/video/fbdev/uvesafb.c ++++ b/drivers/video/fbdev/uvesafb.c +@@ -1758,6 +1758,7 @@ static int uvesafb_probe(struct platform_device *dev) + out_unmap: + iounmap(info->screen_base); + out_mem: ++ arch_phys_wc_del(par->mtrr_handle); + release_mem_region(info->fix.smem_start, info->fix.smem_len); + out_reg: + release_region(0x3c0, 32); +-- +2.35.1 + diff --git a/queue-5.15/fbdev-vermilion-decrease-reference-count-in-error-pa.patch b/queue-5.15/fbdev-vermilion-decrease-reference-count-in-error-pa.patch new file mode 100644 index 00000000000..fa5e23de9c6 --- /dev/null +++ b/queue-5.15/fbdev-vermilion-decrease-reference-count-in-error-pa.patch @@ -0,0 +1,40 @@ +From 42b4dd9f13812898d300c31b012a0e7a5b15044c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 16:56:54 +0800 +Subject: fbdev: vermilion: decrease reference count in error path + +From: Xiongfeng Wang + +[ Upstream commit 001f2cdb952a9566c77fb4b5470cc361db5601bb ] + +pci_get_device() will increase the reference count for the returned +pci_dev. For the error path, we need to use pci_dev_put() to decrease +the reference count. + +Fixes: dbe7e429fedb ("vmlfb: framebuffer driver for Intel Vermilion Range") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/vermilion/vermilion.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c +index ff61605b8764..a543643ce014 100644 +--- a/drivers/video/fbdev/vermilion/vermilion.c ++++ b/drivers/video/fbdev/vermilion/vermilion.c +@@ -277,8 +277,10 @@ static int vmlfb_get_gpu(struct vml_par *par) + + mutex_unlock(&vml_mutex); + +- if (pci_enable_device(par->gpu) < 0) ++ if (pci_enable_device(par->gpu) < 0) { ++ pci_dev_put(par->gpu); + return -ENODEV; ++ } + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/fbdev-via-fix-error-in-via_core_init.patch b/queue-5.15/fbdev-via-fix-error-in-via_core_init.patch new file mode 100644 index 00000000000..4044230f35e --- /dev/null +++ b/queue-5.15/fbdev-via-fix-error-in-via_core_init.patch @@ -0,0 +1,47 @@ +From f3fc6266fe1f3cea1934191e3ecd281e68e19631 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 09:08:52 +0800 +Subject: fbdev: via: Fix error in via_core_init() + +From: Shang XiaoJing + +[ Upstream commit 5886b130de953cfb8826f7771ec8640a79934a7f ] + +via_core_init() won't exit the driver when pci_register_driver() failed. +Exit the viafb-i2c and the viafb-gpio in failed path to prevent error. + +VIA Graphics Integration Chipset framebuffer 2.4 initializing +Error: Driver 'viafb-i2c' is already registered, aborting... +Error: Driver 'viafb-gpio' is already registered, aborting... + +Fixes: 7582eb9be85f ("viafb: Turn GPIO and i2c into proper platform devices") +Signed-off-by: Shang XiaoJing +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + drivers/video/fbdev/via/via-core.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c +index 89d75079b730..0363b478fa3e 100644 +--- a/drivers/video/fbdev/via/via-core.c ++++ b/drivers/video/fbdev/via/via-core.c +@@ -725,7 +725,14 @@ static int __init via_core_init(void) + return ret; + viafb_i2c_init(); + viafb_gpio_init(); +- return pci_register_driver(&via_driver); ++ ret = pci_register_driver(&via_driver); ++ if (ret) { ++ viafb_gpio_exit(); ++ viafb_i2c_exit(); ++ return ret; ++ } ++ ++ return 0; + } + + static void __exit via_core_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/firmware-raspberrypi-fix-possible-memory-leak-in-rpi.patch b/queue-5.15/firmware-raspberrypi-fix-possible-memory-leak-in-rpi.patch new file mode 100644 index 00000000000..63851b02da8 --- /dev/null +++ b/queue-5.15/firmware-raspberrypi-fix-possible-memory-leak-in-rpi.patch @@ -0,0 +1,39 @@ +From 6696165c7e441f92da0c971f49f0d2b815fc551a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:06:36 +0800 +Subject: firmware: raspberrypi: fix possible memory leak in + rpi_firmware_probe() + +From: Yang Yingliang + +[ Upstream commit 7b51161696e803fd5f9ad55b20a64c2df313f95c ] + +In rpi_firmware_probe(), if mbox_request_channel() fails, the 'fw' will +not be freed through rpi_firmware_delete(), fix this leak by calling +kfree() in the error path. + +Fixes: 1e7c57355a3b ("firmware: raspberrypi: Keep count of all consumers") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221117070636.3849773-1-yangyingliang@huawei.com +Acked-by: Joel Savitz +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/firmware/raspberrypi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c +index 4b8978b254f9..dba315f675bc 100644 +--- a/drivers/firmware/raspberrypi.c ++++ b/drivers/firmware/raspberrypi.c +@@ -272,6 +272,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) + int ret = PTR_ERR(fw->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get mbox channel: %d\n", ret); ++ kfree(fw); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/fs-don-t-audit-the-capability-check-in-simple_xattr_.patch b/queue-5.15/fs-don-t-audit-the-capability-check-in-simple_xattr_.patch new file mode 100644 index 00000000000..a3d120d3698 --- /dev/null +++ b/queue-5.15/fs-don-t-audit-the-capability-check-in-simple_xattr_.patch @@ -0,0 +1,54 @@ +From 7bb2acb2e8a2ef5ea718aa053dcc3e3d2c6958b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 16:12:05 +0100 +Subject: fs: don't audit the capability check in simple_xattr_list() + +From: Ondrej Mosnacek + +[ Upstream commit e7eda157c4071cd1e69f4b1687b0fbe1ae5e6f46 ] + +The check being unconditional may lead to unwanted denials reported by +LSMs when a process has the capability granted by DAC, but denied by an +LSM. In the case of SELinux such denials are a problem, since they can't +be effectively filtered out via the policy and when not silenced, they +produce noise that may hide a true problem or an attack. + +Checking for the capability only if any trusted xattr is actually +present wouldn't really address the issue, since calling listxattr(2) on +such node on its own doesn't indicate an explicit attempt to see the +trusted xattrs. Additionally, it could potentially leak the presence of +trusted xattrs to an unprivileged user if they can check for the denials +(e.g. through dmesg). + +Therefore, it's best (and simplest) to keep the check unconditional and +instead use ns_capable_noaudit() that will silence any associated LSM +denials. + +Fixes: 38f38657444d ("xattr: extract simple_xattr code from tmpfs") +Reported-by: Martin Pitt +Suggested-by: Christian Brauner (Microsoft) +Signed-off-by: Ondrej Mosnacek +Reviewed-by: Christian Brauner (Microsoft) +Reviewed-by: Paul Moore +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Sasha Levin +--- + fs/xattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/xattr.c b/fs/xattr.c +index 7117cb253864..4c82f271f4aa 100644 +--- a/fs/xattr.c ++++ b/fs/xattr.c +@@ -1119,7 +1119,7 @@ static int xattr_list_one(char **buffer, ssize_t *remaining_size, + ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, + char *buffer, size_t size) + { +- bool trusted = capable(CAP_SYS_ADMIN); ++ bool trusted = ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN); + struct simple_xattr *xattr; + ssize_t remaining_size = size; + int err = 0; +-- +2.35.1 + diff --git a/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dballocag.patch b/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dballocag.patch new file mode 100644 index 00000000000..4530e437071 --- /dev/null +++ b/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dballocag.patch @@ -0,0 +1,90 @@ +From e97024877eed767c8ee49389bc759a80f438e880 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 08:48:07 -0500 +Subject: fs: jfs: fix shift-out-of-bounds in dbAllocAG + +From: Dongliang Mu + +[ Upstream commit 898f706695682b9954f280d95e49fa86ffa55d08 ] + +Syzbot found a crash : UBSAN: shift-out-of-bounds in dbAllocAG. The +underlying bug is the missing check of bmp->db_agl2size. The field can +be greater than 64 and trigger the shift-out-of-bounds. + +Fix this bug by adding a check of bmp->db_agl2size in dbMount since this +field is used in many following functions. The upper bound for this +field is L2MAXL2SIZE - L2MAXAG, thanks for the help of Dave Kleikamp. +Note that, for maintenance, I reorganized error handling code of dbMount. + +Reported-by: syzbot+15342c1aa6a00fb7a438@syzkaller.appspotmail.com +Signed-off-by: Dongliang Mu +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_dmap.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index e75f31b81d63..44600cd7614a 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -155,7 +155,7 @@ int dbMount(struct inode *ipbmap) + struct bmap *bmp; + struct dbmap_disk *dbmp_le; + struct metapage *mp; +- int i; ++ int i, err; + + /* + * allocate/initialize the in-memory bmap descriptor +@@ -170,8 +170,8 @@ int dbMount(struct inode *ipbmap) + BMAPBLKNO << JFS_SBI(ipbmap->i_sb)->l2nbperpage, + PSIZE, 0); + if (mp == NULL) { +- kfree(bmp); +- return -EIO; ++ err = -EIO; ++ goto err_kfree_bmp; + } + + /* copy the on-disk bmap descriptor to its in-memory version. */ +@@ -181,9 +181,8 @@ int dbMount(struct inode *ipbmap) + bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage); + bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag); + if (!bmp->db_numag) { +- release_metapage(mp); +- kfree(bmp); +- return -EINVAL; ++ err = -EINVAL; ++ goto err_release_metapage; + } + + bmp->db_maxlevel = le32_to_cpu(dbmp_le->dn_maxlevel); +@@ -194,6 +193,11 @@ int dbMount(struct inode *ipbmap) + bmp->db_agwidth = le32_to_cpu(dbmp_le->dn_agwidth); + bmp->db_agstart = le32_to_cpu(dbmp_le->dn_agstart); + bmp->db_agl2size = le32_to_cpu(dbmp_le->dn_agl2size); ++ if (bmp->db_agl2size > L2MAXL2SIZE - L2MAXAG) { ++ err = -EINVAL; ++ goto err_release_metapage; ++ } ++ + for (i = 0; i < MAXAG; i++) + bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]); + bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize); +@@ -214,6 +218,12 @@ int dbMount(struct inode *ipbmap) + BMAP_LOCK_INIT(bmp); + + return (0); ++ ++err_release_metapage: ++ release_metapage(mp); ++err_kfree_bmp: ++ kfree(bmp); ++ return err; + } + + +-- +2.35.1 + diff --git a/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch b/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch new file mode 100644 index 00000000000..dc22dd5384d --- /dev/null +++ b/queue-5.15/fs-jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch @@ -0,0 +1,39 @@ +From c716349016b6190495949115438c4d130ed175bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 23:20:45 +0800 +Subject: fs: jfs: fix shift-out-of-bounds in dbDiscardAG + +From: Hoi Pok Wu + +[ Upstream commit 25e70c6162f207828dd405b432d8f2a98dbf7082 ] + +This should be applied to most URSAN bugs found recently by syzbot, +by guarding the dbMount. As syzbot feeding rubbish into the bmap +descriptor. + +Signed-off-by: Hoi Pok Wu +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/jfs_dmap.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c +index 44600cd7614a..f401bc05d5ff 100644 +--- a/fs/jfs/jfs_dmap.c ++++ b/fs/jfs/jfs_dmap.c +@@ -198,6 +198,11 @@ int dbMount(struct inode *ipbmap) + goto err_release_metapage; + } + ++ if (((bmp->db_mapsize - 1) >> bmp->db_agl2size) > MAXAG) { ++ err = -EINVAL; ++ goto err_release_metapage; ++ } ++ + for (i = 0; i < MAXAG; i++) + bmp->db_agfree[i] = le64_to_cpu(dbmp_le->dn_agfree[i]); + bmp->db_agsize = le64_to_cpu(dbmp_le->dn_agsize); +-- +2.35.1 + diff --git a/queue-5.15/fs-ntfs3-avoid-ubsan-error-on-true_sectors_per_clst.patch b/queue-5.15/fs-ntfs3-avoid-ubsan-error-on-true_sectors_per_clst.patch new file mode 100644 index 00000000000..ec6222763ec --- /dev/null +++ b/queue-5.15/fs-ntfs3-avoid-ubsan-error-on-true_sectors_per_clst.patch @@ -0,0 +1,44 @@ +From 6139c395189723d4dbcae0e43d1e18b5ff90132c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 23:46:25 +0900 +Subject: fs/ntfs3: Avoid UBSAN error on true_sectors_per_clst() + +From: Shigeru Yoshida + +[ Upstream commit caad9dd8792a2622737b7273cb34835fd9536cd2 ] + +syzbot reported UBSAN error as below: + +[ 76.901829][ T6677] ================================================================================ +[ 76.903908][ T6677] UBSAN: shift-out-of-bounds in fs/ntfs3/super.c:675:13 +[ 76.905363][ T6677] shift exponent -247 is negative + +This patch avoid this error. + +Link: https://syzkaller.appspot.com/bug?id=b0299c09a14aababf0f1c862dd4ebc8ab9eb0179 +Fixes: a3b774342fa7 (fs/ntfs3: validate BOOT sectors_per_clusters) +Cc: Author: Randy Dunlap +Reported-by: syzbot+35b87c668935bb55e666@syzkaller.appspotmail.com +Signed-off-by: Shigeru Yoshida +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c +index f3b88c7e35f7..39b09f32f4db 100644 +--- a/fs/ntfs3/super.c ++++ b/fs/ntfs3/super.c +@@ -672,7 +672,7 @@ static u32 true_sectors_per_clst(const struct NTFS_BOOT *boot) + if (boot->sectors_per_clusters <= 0x80) + return boot->sectors_per_clusters; + if (boot->sectors_per_clusters >= 0xf4) /* limit shift to 2MB max */ +- return 1U << (0 - boot->sectors_per_clusters); ++ return 1U << -(s8)boot->sectors_per_clusters; + return -EINVAL; + } + +-- +2.35.1 + diff --git a/queue-5.15/fs-ntfs3-fix-slab-out-of-bounds-read-in-ntfs_trim_fs.patch b/queue-5.15/fs-ntfs3-fix-slab-out-of-bounds-read-in-ntfs_trim_fs.patch new file mode 100644 index 00000000000..4a7b102f4b8 --- /dev/null +++ b/queue-5.15/fs-ntfs3-fix-slab-out-of-bounds-read-in-ntfs_trim_fs.patch @@ -0,0 +1,42 @@ +From 2ba0ac03f215b55ee446e7b2666f58988a1b86fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 12:30:24 +0530 +Subject: fs/ntfs3: Fix slab-out-of-bounds read in ntfs_trim_fs + +From: Abdun Nihaal + +[ Upstream commit 557d19675a470bb0a98beccec38c5dc3735c20fa ] + +Syzbot reports an out of bound access in ntfs_trim_fs. +The cause of this is using a loop termination condition that compares +window index (iw) with wnd->nbits instead of wnd->nwnd, due to which the +index used for wnd->free_bits exceeds the size of the array allocated. + +Fix the loop condition. + +Fixes: 3f3b442b5ad2 ("fs/ntfs3: Add bitmap") +Link: https://syzkaller.appspot.com/bug?extid=b892240eac461e488d51 +Reported-by: syzbot+b892240eac461e488d51@syzkaller.appspotmail.com +Signed-off-by: Abdun Nihaal +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/bitmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/bitmap.c b/fs/ntfs3/bitmap.c +index aa184407520f..7f2055b7427a 100644 +--- a/fs/ntfs3/bitmap.c ++++ b/fs/ntfs3/bitmap.c +@@ -1432,7 +1432,7 @@ int ntfs_trim_fs(struct ntfs_sb_info *sbi, struct fstrim_range *range) + + down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS); + +- for (; iw < wnd->nbits; iw++, wbit = 0) { ++ for (; iw < wnd->nwnd; iw++, wbit = 0) { + CLST lcn_wnd = iw * wbits; + struct buffer_head *bh; + +-- +2.35.1 + diff --git a/queue-5.15/fs-ntfs3-harden-against-integer-overflows.patch b/queue-5.15/fs-ntfs3-harden-against-integer-overflows.patch new file mode 100644 index 00000000000..4fb9b9da2e6 --- /dev/null +++ b/queue-5.15/fs-ntfs3-harden-against-integer-overflows.patch @@ -0,0 +1,36 @@ +From 0c67f573ab125d9935691706320f6d9edd1c7058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 18:08:51 +0300 +Subject: fs/ntfs3: Harden against integer overflows + +From: Dan Carpenter + +[ Upstream commit e001e60869390686809663c02bceb1d3922548fb ] + +Smatch complains that the "add_bytes" is not to be trusted. Use +size_add() to prevent an integer overflow. + +Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") +Signed-off-by: Dan Carpenter +Signed-off-by: Konstantin Komarov +Signed-off-by: Sasha Levin +--- + fs/ntfs3/xattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index eb799a5cdfad..8847db015908 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -107,7 +107,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, + return -EFBIG; + + /* Allocate memory for packed Ea. */ +- ea_p = kmalloc(size + add_bytes, GFP_NOFS); ++ ea_p = kmalloc(size_add(size, add_bytes), GFP_NOFS); + if (!ea_p) + return -ENOMEM; + +-- +2.35.1 + diff --git a/queue-5.15/fs-sysv-fix-sysv_nblocks-returns-wrong-value.patch b/queue-5.15/fs-sysv-fix-sysv_nblocks-returns-wrong-value.patch new file mode 100644 index 00000000000..e3f2d52b1cf --- /dev/null +++ b/queue-5.15/fs-sysv-fix-sysv_nblocks-returns-wrong-value.patch @@ -0,0 +1,42 @@ +From 7add5b6c22ddf4bf7f961101eb736d8aefda8683 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 18:04:48 +0800 +Subject: fs: sysv: Fix sysv_nblocks() returns wrong value + +From: Chen Zhongjin + +[ Upstream commit e0c49bd2b4d3cd1751491eb2d940bce968ac65e9 ] + +sysv_nblocks() returns 'blocks' rather than 'res', which only counting +the number of triple-indirect blocks and causing sysv_getattr() gets a +wrong result. + +[AV: this is actually a sysv counterpart of minixfs fix - +0fcd426de9d0 "[PATCH] minix block usage counting fix" in +historical tree; mea culpa, should've thought to check +fs/sysv back then...] + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Chen Zhongjin +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + fs/sysv/itree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c +index 749385015a8d..5a59d56a2038 100644 +--- a/fs/sysv/itree.c ++++ b/fs/sysv/itree.c +@@ -438,7 +438,7 @@ static unsigned sysv_nblocks(struct super_block *s, loff_t size) + res += blocks; + direct = 1; + } +- return blocks; ++ return res; + } + + int sysv_getattr(struct user_namespace *mnt_userns, const struct path *path, +-- +2.35.1 + diff --git a/queue-5.15/futex-move-to-kernel-futex.patch b/queue-5.15/futex-move-to-kernel-futex.patch new file mode 100644 index 00000000000..5b34e26d76b --- /dev/null +++ b/queue-5.15/futex-move-to-kernel-futex.patch @@ -0,0 +1,85 @@ +From ffdccac0032fcf020622ffd41dabf484fc9853b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Sep 2021 14:10:50 -0300 +Subject: futex: Move to kernel/futex/ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Peter Zijlstra + +[ Upstream commit 77e52ae35463521041906c510fe580d15663bb93 ] + +In preparation for splitup.. + +Signed-off-by: Peter Zijlstra (Intel) +Suggested-by: Thomas Gleixner +Signed-off-by: André Almeida +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: André Almeida +Link: https://lore.kernel.org/r/20210923171111.300673-2-andrealmeid@collabora.com +Stable-dep-of: 90d758896787 ("futex: Resend potentially swallowed owner death notification") +Signed-off-by: Sasha Levin +--- + MAINTAINERS | 2 +- + kernel/Makefile | 2 +- + kernel/futex/Makefile | 3 +++ + kernel/{futex.c => futex/core.c} | 2 +- + 4 files changed, 6 insertions(+), 3 deletions(-) + create mode 100644 kernel/futex/Makefile + rename kernel/{futex.c => futex/core.c} (99%) + +diff --git a/MAINTAINERS b/MAINTAINERS +index 1cf05aee91af..4f50a453e18a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -7746,7 +7746,7 @@ F: Documentation/locking/*futex* + F: include/asm-generic/futex.h + F: include/linux/futex.h + F: include/uapi/linux/futex.h +-F: kernel/futex.c ++F: kernel/futex/* + F: tools/perf/bench/futex* + F: tools/testing/selftests/futex/ + +diff --git a/kernel/Makefile b/kernel/Makefile +index 0e119c52a2cd..599cb926449a 100644 +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -59,7 +59,7 @@ obj-$(CONFIG_FREEZER) += freezer.o + obj-$(CONFIG_PROFILING) += profile.o + obj-$(CONFIG_STACKTRACE) += stacktrace.o + obj-y += time/ +-obj-$(CONFIG_FUTEX) += futex.o ++obj-$(CONFIG_FUTEX) += futex/ + obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o + obj-$(CONFIG_SMP) += smp.o + ifneq ($(CONFIG_SMP),y) +diff --git a/kernel/futex/Makefile b/kernel/futex/Makefile +new file mode 100644 +index 000000000000..b89ba3fba343 +--- /dev/null ++++ b/kernel/futex/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-y += core.o +diff --git a/kernel/futex.c b/kernel/futex/core.c +similarity index 99% +rename from kernel/futex.c +rename to kernel/futex/core.c +index c15ad276fd15..f9bc9aa0ce1e 100644 +--- a/kernel/futex.c ++++ b/kernel/futex/core.c +@@ -42,7 +42,7 @@ + + #include + +-#include "locking/rtmutex_common.h" ++#include "../locking/rtmutex_common.h" + + /* + * READ this before attempting to hack on futexes! +-- +2.35.1 + diff --git a/queue-5.15/futex-resend-potentially-swallowed-owner-death-notif.patch b/queue-5.15/futex-resend-potentially-swallowed-owner-death-notif.patch new file mode 100644 index 00000000000..22ad12872f1 --- /dev/null +++ b/queue-5.15/futex-resend-potentially-swallowed-owner-death-notif.patch @@ -0,0 +1,104 @@ +From 9f4489eaf8585a81e27d13103e8d894b5aab769e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 00:54:39 +0300 +Subject: futex: Resend potentially swallowed owner death notification + +From: Alexey Izbyshev + +[ Upstream commit 90d758896787048fa3d4209309d4800f3920e66f ] + +Commit ca16d5bee598 ("futex: Prevent robust futex exit race") addressed +two cases when tasks waiting on a robust non-PI futex remained blocked +despite the futex not being owned anymore: + +* if the owner died after writing zero to the futex word, but before + waking up a waiter + +* if a task waiting on the futex was woken up, but died before updating + the futex word (effectively swallowing the notification without acting + on it) + +In the second case, the task could be woken up either by the previous +owner (after the futex word was reset to zero) or by the kernel (after +the OWNER_DIED bit was set and the TID part of the futex word was reset +to zero) if the previous owner died without the resetting the futex. + +Because the referenced commit wakes up a potential waiter only if the +whole futex word is zero, the latter subcase remains unaddressed. + +Fix this by looking only at the TID part of the futex when deciding +whether a wake up is needed. + +Fixes: ca16d5bee598 ("futex: Prevent robust futex exit race") +Signed-off-by: Alexey Izbyshev +Signed-off-by: Thomas Gleixner +Acked-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20221111215439.248185-1-izbyshev@ispras.ru +Signed-off-by: Sasha Levin +--- + kernel/futex/core.c | 26 +++++++++++++++++--------- + 1 file changed, 17 insertions(+), 9 deletions(-) + +diff --git a/kernel/futex/core.c b/kernel/futex/core.c +index f9bc9aa0ce1e..764e73622b38 100644 +--- a/kernel/futex/core.c ++++ b/kernel/futex/core.c +@@ -3632,6 +3632,7 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + bool pi, bool pending_op) + { + u32 uval, nval, mval; ++ pid_t owner; + int err; + + /* Futex address must be 32bit aligned */ +@@ -3653,6 +3654,10 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * 2. A woken up waiter is killed before it can acquire the + * futex in user space. + * ++ * In the second case, the wake up notification could be generated ++ * by the unlock path in user space after setting the futex value ++ * to zero or by the kernel after setting the OWNER_DIED bit below. ++ * + * In both cases the TID validation below prevents a wakeup of + * potential waiters which can cause these waiters to block + * forever. +@@ -3661,24 +3666,27 @@ static int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, + * + * 1) task->robust_list->list_op_pending != NULL + * @pending_op == true +- * 2) User space futex value == 0 ++ * 2) The owner part of user space futex value == 0 + * 3) Regular futex: @pi == false + * + * If these conditions are met, it is safe to attempt waking up a + * potential waiter without touching the user space futex value and +- * trying to set the OWNER_DIED bit. The user space futex value is +- * uncontended and the rest of the user space mutex state is +- * consistent, so a woken waiter will just take over the +- * uncontended futex. Setting the OWNER_DIED bit would create +- * inconsistent state and malfunction of the user space owner died +- * handling. ++ * trying to set the OWNER_DIED bit. If the futex value is zero, ++ * the rest of the user space mutex state is consistent, so a woken ++ * waiter will just take over the uncontended futex. Setting the ++ * OWNER_DIED bit would create inconsistent state and malfunction ++ * of the user space owner died handling. Otherwise, the OWNER_DIED ++ * bit is already set, and the woken waiter is expected to deal with ++ * this. + */ +- if (pending_op && !pi && !uval) { ++ owner = uval & FUTEX_TID_MASK; ++ ++ if (pending_op && !pi && !owner) { + futex_wake(uaddr, 1, 1, FUTEX_BITSET_MATCH_ANY); + return 0; + } + +- if ((uval & FUTEX_TID_MASK) != task_pid_vnr(curr)) ++ if (owner != task_pid_vnr(curr)) + return 0; + + /* +-- +2.35.1 + diff --git a/queue-5.15/genirq-irqdesc-don-t-try-to-remove-non-existing-sysf.patch b/queue-5.15/genirq-irqdesc-don-t-try-to-remove-non-existing-sysf.patch new file mode 100644 index 00000000000..ff852b70a16 --- /dev/null +++ b/queue-5.15/genirq-irqdesc-don-t-try-to-remove-non-existing-sysf.patch @@ -0,0 +1,115 @@ +From 6d9f33e47dbd5c540a155e1e3c6037ace15aafe8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 23:16:12 +0800 +Subject: genirq/irqdesc: Don't try to remove non-existing sysfs files + +From: Yang Yingliang + +[ Upstream commit 9049e1ca41983ab773d7ea244bee86d7835ec9f5 ] + +Fault injection tests trigger warnings like this: + + kernfs: can not remove 'chip_name', no directory + WARNING: CPU: 0 PID: 253 at fs/kernfs/dir.c:1616 kernfs_remove_by_name_ns+0xce/0xe0 + RIP: 0010:kernfs_remove_by_name_ns+0xce/0xe0 + Call Trace: + + remove_files.isra.1+0x3f/0xb0 + sysfs_remove_group+0x68/0xe0 + sysfs_remove_groups+0x41/0x70 + __kobject_del+0x45/0xc0 + kobject_del+0x29/0x40 + free_desc+0x42/0x70 + irq_free_descs+0x5e/0x90 + +The reason is that the interrupt descriptor sysfs handling does not roll +back on a failing kobject_add() during allocation. If the descriptor is +freed later on, kobject_del() is invoked with a not added kobject resulting +in the above warnings. + +A proper rollback in case of a kobject_add() failure would be the straight +forward solution. But this is not possible due to the way how interrupt +descriptor sysfs handling works. + +Interrupt descriptors are allocated before sysfs becomes available. So the +sysfs files for the early allocated descriptors are added later in the boot +process. At this point there can be nothing useful done about a failing +kobject_add(). For consistency the interrupt descriptor allocation always +treats kobject_add() failures as non-critical and just emits a warning. + +To solve this problem, keep track in the interrupt descriptor whether +kobject_add() was successful or not and make the invocation of +kobject_del() conditional on that. + +[ tglx: Massage changelog, comments and use a state bit. ] + +Fixes: ecb3f394c5db ("genirq: Expose interrupt information through sysfs") +Signed-off-by: Yang Yingliang +Signed-off-by: Thomas Gleixner +Reviewed-by: Greg Kroah-Hartman +Link: https://lore.kernel.org/r/20221128151612.1786122-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + kernel/irq/internals.h | 2 ++ + kernel/irq/irqdesc.c | 15 +++++++++------ + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h +index e58342ace11f..f1d83a8b4417 100644 +--- a/kernel/irq/internals.h ++++ b/kernel/irq/internals.h +@@ -52,6 +52,7 @@ enum { + * IRQS_PENDING - irq is pending and replayed later + * IRQS_SUSPENDED - irq is suspended + * IRQS_NMI - irq line is used to deliver NMIs ++ * IRQS_SYSFS - descriptor has been added to sysfs + */ + enum { + IRQS_AUTODETECT = 0x00000001, +@@ -64,6 +65,7 @@ enum { + IRQS_SUSPENDED = 0x00000800, + IRQS_TIMINGS = 0x00001000, + IRQS_NMI = 0x00002000, ++ IRQS_SYSFS = 0x00004000, + }; + + #include "debug.h" +diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c +index 21b3ac2a29d2..7a45fd593245 100644 +--- a/kernel/irq/irqdesc.c ++++ b/kernel/irq/irqdesc.c +@@ -288,22 +288,25 @@ static void irq_sysfs_add(int irq, struct irq_desc *desc) + if (irq_kobj_base) { + /* + * Continue even in case of failure as this is nothing +- * crucial. ++ * crucial and failures in the late irq_sysfs_init() ++ * cannot be rolled back. + */ + if (kobject_add(&desc->kobj, irq_kobj_base, "%d", irq)) + pr_warn("Failed to add kobject for irq %d\n", irq); ++ else ++ desc->istate |= IRQS_SYSFS; + } + } + + static void irq_sysfs_del(struct irq_desc *desc) + { + /* +- * If irq_sysfs_init() has not yet been invoked (early boot), then +- * irq_kobj_base is NULL and the descriptor was never added. +- * kobject_del() complains about a object with no parent, so make +- * it conditional. ++ * Only invoke kobject_del() when kobject_add() was successfully ++ * invoked for the descriptor. This covers both early boot, where ++ * sysfs is not initialized yet, and the case of a failed ++ * kobject_add() invocation. + */ +- if (irq_kobj_base) ++ if (desc->istate & IRQS_SYSFS) + kobject_del(&desc->kobj); + } + +-- +2.35.1 + diff --git a/queue-5.15/gpiolib-cdev-fix-null-pointer-dereferences.patch b/queue-5.15/gpiolib-cdev-fix-null-pointer-dereferences.patch new file mode 100644 index 00000000000..c3c67b0ba01 --- /dev/null +++ b/queue-5.15/gpiolib-cdev-fix-null-pointer-dereferences.patch @@ -0,0 +1,134 @@ +From 12c823a71adff1bb45ff4e1615762413309ef743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 13:39:02 +0100 +Subject: gpiolib: cdev: fix NULL-pointer dereferences + +From: Bartosz Golaszewski + +[ Upstream commit 533aae7c94dbc2b14301cfd68ae7e0e90f0c8438 ] + +There are several places where we can crash the kernel by requesting +lines, unbinding the GPIO device, then calling any of the system calls +relevant to the GPIO character device's annonymous file descriptors: +ioctl(), read(), poll(). + +While I observed it with the GPIO simulator, it will also happen for any +of the GPIO devices that can be hot-unplugged - for instance any HID GPIO +expander (e.g. CP2112). + +This affects both v1 and v2 uAPI. + +This fixes it partially by checking if gdev->chip is not NULL but it +doesn't entirely remedy the situation as we still have a race condition +in which another thread can remove the device after the check. + +Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") +Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL") +Fixes: aad955842d1c ("gpiolib: cdev: support GPIO_V2_GET_LINEINFO_IOCTL and GPIO_V2_GET_LINEINFO_WATCH_IOCTL") +Fixes: a54756cb24ea ("gpiolib: cdev: support GPIO_V2_LINE_SET_CONFIG_IOCTL") +Fixes: 7b8e00d98168 ("gpiolib: cdev: support GPIO_V2_LINE_SET_VALUES_IOCTL") +Signed-off-by: Bartosz Golaszewski +Reviewed-by: Andy Shevchenko +Reviewed-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib-cdev.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c +index a20396a6448b..64e37618216f 100644 +--- a/drivers/gpio/gpiolib-cdev.c ++++ b/drivers/gpio/gpiolib-cdev.c +@@ -200,6 +200,9 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + unsigned int i; + int ret; + ++ if (!lh->gdev->chip) ++ return -ENODEV; ++ + switch (cmd) { + case GPIOHANDLE_GET_LINE_VALUES_IOCTL: + /* NOTE: It's okay to read values of output lines */ +@@ -1188,6 +1191,9 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, + struct linereq *lr = file->private_data; + void __user *ip = (void __user *)arg; + ++ if (!lr->gdev->chip) ++ return -ENODEV; ++ + switch (cmd) { + case GPIO_V2_LINE_GET_VALUES_IOCTL: + return linereq_get_values(lr, ip); +@@ -1214,6 +1220,9 @@ static __poll_t linereq_poll(struct file *file, + struct linereq *lr = file->private_data; + __poll_t events = 0; + ++ if (!lr->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &lr->wait, wait); + + if (!kfifo_is_empty_spinlocked_noirqsave(&lr->events, +@@ -1233,6 +1242,9 @@ static ssize_t linereq_read(struct file *file, + ssize_t bytes_read = 0; + int ret; + ++ if (!lr->gdev->chip) ++ return -ENODEV; ++ + if (count < sizeof(le)) + return -EINVAL; + +@@ -1498,6 +1510,9 @@ static __poll_t lineevent_poll(struct file *file, + struct lineevent_state *le = file->private_data; + __poll_t events = 0; + ++ if (!le->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &le->wait, wait); + + if (!kfifo_is_empty_spinlocked_noirqsave(&le->events, &le->wait.lock)) +@@ -1522,6 +1537,9 @@ static ssize_t lineevent_read(struct file *file, + ssize_t ge_size; + int ret; + ++ if (!le->gdev->chip) ++ return -ENODEV; ++ + /* + * When compatible system call is being used the struct gpioevent_data, + * in case of at least ia32, has different size due to the alignment +@@ -1603,6 +1621,9 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd, + void __user *ip = (void __user *)arg; + struct gpiohandle_data ghd; + ++ if (!le->gdev->chip) ++ return -ENODEV; ++ + /* + * We can get the value for an event line but not set it, + * because it is input by definition. +@@ -2187,6 +2208,9 @@ static __poll_t lineinfo_watch_poll(struct file *file, + struct gpio_chardev_data *cdev = file->private_data; + __poll_t events = 0; + ++ if (!cdev->gdev->chip) ++ return EPOLLHUP | EPOLLERR; ++ + poll_wait(file, &cdev->wait, pollt); + + if (!kfifo_is_empty_spinlocked_noirqsave(&cdev->events, +@@ -2205,6 +2229,9 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, + int ret; + size_t event_size; + ++ if (!cdev->gdev->chip) ++ return -ENODEV; ++ + #ifndef CONFIG_GPIO_CDEV_V1 + event_size = sizeof(struct gpio_v2_line_info_changed); + if (count < event_size) +-- +2.35.1 + diff --git a/queue-5.15/gpiolib-get-rid-of-redundant-else.patch b/queue-5.15/gpiolib-get-rid-of-redundant-else.patch new file mode 100644 index 00000000000..6ab284022fd --- /dev/null +++ b/queue-5.15/gpiolib-get-rid-of-redundant-else.patch @@ -0,0 +1,191 @@ +From 24f01e1c9911dde8957f1374ef989096a87d1f70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Mar 2022 18:06:20 +0300 +Subject: gpiolib: Get rid of redundant 'else' + +From: Andy Shevchenko + +[ Upstream commit 1cef8b5019769d46725932eeace7a383bca97905 ] + +In the snippets like the following + + if (...) + return / goto / break / continue ...; + else + ... + +the 'else' is redundant. Get rid of it. In case of IOCTLs use +switch-case pattern that seems the usual in such cases. + +While at it, clarify necessity of else in gpiod_direction_output() +by attaching else if to the closing curly brace on a previous line. + +Signed-off-by: Andy Shevchenko +Signed-off-by: Bartosz Golaszewski +Stable-dep-of: 533aae7c94db ("gpiolib: cdev: fix NULL-pointer dereferences") +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib-cdev.c | 66 ++++++++++++++++++++----------------- + drivers/gpio/gpiolib.c | 12 +++---- + 2 files changed, 40 insertions(+), 38 deletions(-) + +diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c +index 937e7a8dd8a9..a20396a6448b 100644 +--- a/drivers/gpio/gpiolib-cdev.c ++++ b/drivers/gpio/gpiolib-cdev.c +@@ -197,16 +197,15 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + void __user *ip = (void __user *)arg; + struct gpiohandle_data ghd; + DECLARE_BITMAP(vals, GPIOHANDLES_MAX); +- int i; ++ unsigned int i; ++ int ret; + +- if (cmd == GPIOHANDLE_GET_LINE_VALUES_IOCTL) { +- /* NOTE: It's ok to read values of output lines. */ +- int ret = gpiod_get_array_value_complex(false, +- true, +- lh->num_descs, +- lh->descs, +- NULL, +- vals); ++ switch (cmd) { ++ case GPIOHANDLE_GET_LINE_VALUES_IOCTL: ++ /* NOTE: It's okay to read values of output lines */ ++ ret = gpiod_get_array_value_complex(false, true, ++ lh->num_descs, lh->descs, ++ NULL, vals); + if (ret) + return ret; + +@@ -218,7 +217,7 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + return -EFAULT; + + return 0; +- } else if (cmd == GPIOHANDLE_SET_LINE_VALUES_IOCTL) { ++ case GPIOHANDLE_SET_LINE_VALUES_IOCTL: + /* + * All line descriptors were created at once with the same + * flags so just check if the first one is really output. +@@ -240,10 +239,11 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + lh->descs, + NULL, + vals); +- } else if (cmd == GPIOHANDLE_SET_CONFIG_IOCTL) { ++ case GPIOHANDLE_SET_CONFIG_IOCTL: + return linehandle_set_config(lh, ip); ++ default: ++ return -EINVAL; + } +- return -EINVAL; + } + + #ifdef CONFIG_COMPAT +@@ -1188,14 +1188,16 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, + struct linereq *lr = file->private_data; + void __user *ip = (void __user *)arg; + +- if (cmd == GPIO_V2_LINE_GET_VALUES_IOCTL) ++ switch (cmd) { ++ case GPIO_V2_LINE_GET_VALUES_IOCTL: + return linereq_get_values(lr, ip); +- else if (cmd == GPIO_V2_LINE_SET_VALUES_IOCTL) ++ case GPIO_V2_LINE_SET_VALUES_IOCTL: + return linereq_set_values(lr, ip); +- else if (cmd == GPIO_V2_LINE_SET_CONFIG_IOCTL) ++ case GPIO_V2_LINE_SET_CONFIG_IOCTL: + return linereq_set_config(lr, ip); +- +- return -EINVAL; ++ default: ++ return -EINVAL; ++ } + } + + #ifdef CONFIG_COMPAT +@@ -2114,28 +2116,30 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return -ENODEV; + + /* Fill in the struct and pass to userspace */ +- if (cmd == GPIO_GET_CHIPINFO_IOCTL) { ++ switch (cmd) { ++ case GPIO_GET_CHIPINFO_IOCTL: + return chipinfo_get(cdev, ip); + #ifdef CONFIG_GPIO_CDEV_V1 +- } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { ++ case GPIO_GET_LINEHANDLE_IOCTL: + return linehandle_create(gdev, ip); +- } else if (cmd == GPIO_GET_LINEEVENT_IOCTL) { ++ case GPIO_GET_LINEEVENT_IOCTL: + return lineevent_create(gdev, ip); +- } else if (cmd == GPIO_GET_LINEINFO_IOCTL || +- cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) { +- return lineinfo_get_v1(cdev, ip, +- cmd == GPIO_GET_LINEINFO_WATCH_IOCTL); ++ case GPIO_GET_LINEINFO_IOCTL: ++ return lineinfo_get_v1(cdev, ip, false); ++ case GPIO_GET_LINEINFO_WATCH_IOCTL: ++ return lineinfo_get_v1(cdev, ip, true); + #endif /* CONFIG_GPIO_CDEV_V1 */ +- } else if (cmd == GPIO_V2_GET_LINEINFO_IOCTL || +- cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL) { +- return lineinfo_get(cdev, ip, +- cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL); +- } else if (cmd == GPIO_V2_GET_LINE_IOCTL) { ++ case GPIO_V2_GET_LINEINFO_IOCTL: ++ return lineinfo_get(cdev, ip, false); ++ case GPIO_V2_GET_LINEINFO_WATCH_IOCTL: ++ return lineinfo_get(cdev, ip, true); ++ case GPIO_V2_GET_LINE_IOCTL: + return linereq_create(gdev, ip); +- } else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) { ++ case GPIO_GET_LINEINFO_UNWATCH_IOCTL: + return lineinfo_unwatch(cdev, ip); ++ default: ++ return -EINVAL; + } +- return -EINVAL; + } + + #ifdef CONFIG_COMPAT +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 67bc96403a4e..fdca300f6003 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -189,9 +189,8 @@ static int gpiochip_find_base(int ngpio) + /* found a free space? */ + if (gdev->base + gdev->ngpio <= base) + break; +- else +- /* nope, check the space right before the chip */ +- base = gdev->base - ngpio; ++ /* nope, check the space right before the chip */ ++ base = gdev->base - ngpio; + } + + if (gpio_is_valid(base)) { +@@ -2410,8 +2409,7 @@ int gpiod_direction_output(struct gpio_desc *desc, int value) + ret = gpiod_direction_input(desc); + goto set_output_flag; + } +- } +- else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { ++ } else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) { + ret = gpio_set_config(desc, PIN_CONFIG_DRIVE_OPEN_SOURCE); + if (!ret) + goto set_output_value; +@@ -2568,9 +2566,9 @@ static int gpiod_get_raw_value_commit(const struct gpio_desc *desc) + static int gpio_chip_get_multiple(struct gpio_chip *gc, + unsigned long *mask, unsigned long *bits) + { +- if (gc->get_multiple) { ++ if (gc->get_multiple) + return gc->get_multiple(gc, mask, bits); +- } else if (gc->get) { ++ if (gc->get) { + int i, value; + + for_each_set_bit(i, mask, gc->ngpio) { +-- +2.35.1 + diff --git a/queue-5.15/gpiolib-make-struct-comments-into-real-kernel-docs.patch b/queue-5.15/gpiolib-make-struct-comments-into-real-kernel-docs.patch new file mode 100644 index 00000000000..2052afedd3f --- /dev/null +++ b/queue-5.15/gpiolib-make-struct-comments-into-real-kernel-docs.patch @@ -0,0 +1,144 @@ +From 1e345004ab3ce71750b31dab25dad81010a2fabc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Feb 2022 11:48:31 +0100 +Subject: gpiolib: make struct comments into real kernel docs + +From: Bartosz Golaszewski + +[ Upstream commit 4398693a9e24bcab0b99ea219073917991d0792b ] + +We have several comments that start with '/**' but don't conform to the +kernel doc standard. Add proper detailed descriptions for the affected +definitions and move the docs from the forward declarations to the +struct definitions where applicable. + +Reported-by: Randy Dunlap +Signed-off-by: Bartosz Golaszewski +Reviewed-by: Andy Shevchenko +Tested-by: Randy Dunlap +Stable-dep-of: bdbbae241a04 ("gpiolib: protect the GPIO device against being dropped while in use by user-space") +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib.h | 34 ++++++++++++++++++++++++++++++++++ + include/linux/gpio/consumer.h | 35 ++++++++++++++++------------------- + 2 files changed, 50 insertions(+), 19 deletions(-) + +diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h +index c31f4626915d..d77be9d1da80 100644 +--- a/drivers/gpio/gpiolib.h ++++ b/drivers/gpio/gpiolib.h +@@ -37,6 +37,9 @@ + * or name of the IP component in a System on Chip. + * @data: per-instance data assigned by the driver + * @list: links gpio_device:s together for traversal ++ * @notifier: used to notify subscribers about lines being requested, released ++ * or reconfigured ++ * @pin_ranges: range of pins served by the GPIO driver + * + * This state container holds most of the runtime variable data + * for a GPIO device and can hold references and live on after the +@@ -72,6 +75,20 @@ struct gpio_device { + /* gpio suffixes used for ACPI and device tree lookup */ + static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" }; + ++/** ++ * struct gpio_array - Opaque descriptor for a structure of GPIO array attributes ++ * ++ * @desc: Array of pointers to the GPIO descriptors ++ * @size: Number of elements in desc ++ * @chip: Parent GPIO chip ++ * @get_mask: Get mask used in fastpath ++ * @set_mask: Set mask used in fastpath ++ * @invert_mask: Invert mask used in fastpath ++ * ++ * This structure is attached to struct gpiod_descs obtained from ++ * gpiod_get_array() and can be passed back to get/set array functions in order ++ * to activate fast processing path if applicable. ++ */ + struct gpio_array { + struct gpio_desc **desc; + unsigned int size; +@@ -96,6 +113,23 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, + extern spinlock_t gpio_lock; + extern struct list_head gpio_devices; + ++ ++/** ++ * struct gpio_desc - Opaque descriptor for a GPIO ++ * ++ * @gdev: Pointer to the parent GPIO device ++ * @flags: Binary descriptor flags ++ * @label: Name of the consumer ++ * @name: Line name ++ * @hog: Pointer to the device node that hogs this line (if any) ++ * @debounce_period_us: Debounce period in microseconds ++ * ++ * These are obtained using gpiod_get() and are preferable to the old ++ * integer-based handles. ++ * ++ * Contrary to integers, a pointer to a &struct gpio_desc is guaranteed to be ++ * valid until the GPIO is released. ++ */ + struct gpio_desc { + struct gpio_device *gdev; + unsigned long flags; +diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h +index 97a28ad3393b..369902d52f9c 100644 +--- a/include/linux/gpio/consumer.h ++++ b/include/linux/gpio/consumer.h +@@ -8,27 +8,16 @@ + #include + + struct device; +- +-/** +- * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are +- * preferable to the old integer-based handles. +- * +- * Contrary to integers, a pointer to a gpio_desc is guaranteed to be valid +- * until the GPIO is released. +- */ + struct gpio_desc; +- +-/** +- * Opaque descriptor for a structure of GPIO array attributes. This structure +- * is attached to struct gpiod_descs obtained from gpiod_get_array() and can be +- * passed back to get/set array functions in order to activate fast processing +- * path if applicable. +- */ + struct gpio_array; + + /** +- * Struct containing an array of descriptors that can be obtained using +- * gpiod_get_array(). ++ * struct gpio_descs - Struct containing an array of descriptors that can be ++ * obtained using gpiod_get_array() ++ * ++ * @info: Pointer to the opaque gpio_array structure ++ * @ndescs: Number of held descriptors ++ * @desc: Array of pointers to GPIO descriptors + */ + struct gpio_descs { + struct gpio_array *info; +@@ -43,8 +32,16 @@ struct gpio_descs { + #define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4) + + /** +- * Optional flags that can be passed to one of gpiod_* to configure direction +- * and output value. These values cannot be OR'd. ++ * enum gpiod_flags - Optional flags that can be passed to one of gpiod_* to ++ * configure direction and output value. These values ++ * cannot be OR'd. ++ * ++ * @GPIOD_ASIS: Don't change anything ++ * @GPIOD_IN: Set lines to input mode ++ * @GPIOD_OUT_LOW: Set lines to output and drive them low ++ * @GPIOD_OUT_HIGH: Set lines to output and drive them high ++ * @GPIOD_OUT_LOW_OPEN_DRAIN: Set lines to open-drain output and drive them low ++ * @GPIOD_OUT_HIGH_OPEN_DRAIN: Set lines to open-drain output and drive them high + */ + enum gpiod_flags { + GPIOD_ASIS = 0, +-- +2.35.1 + diff --git a/queue-5.15/gpiolib-protect-the-gpio-device-against-being-droppe.patch b/queue-5.15/gpiolib-protect-the-gpio-device-against-being-droppe.patch new file mode 100644 index 00000000000..5478c3d2e0d --- /dev/null +++ b/queue-5.15/gpiolib-protect-the-gpio-device-against-being-droppe.patch @@ -0,0 +1,423 @@ +From 7ed90486321ca29ae3955a7934d8f223defe5b10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 13:39:03 +0100 +Subject: gpiolib: protect the GPIO device against being dropped while in use + by user-space + +From: Bartosz Golaszewski + +[ Upstream commit bdbbae241a04f387ba910b8609f95fad5f1470c7 ] + +While any of the GPIO cdev syscalls is in progress, the kernel can call +gpiochip_remove() (for instance, when a USB GPIO expander is disconnected) +which will set gdev->chip to NULL after which any subsequent access will +cause a crash. + +To avoid that: use an RW-semaphore in which the syscalls take it for +reading (so that we don't needlessly prohibit the user-space from calling +syscalls simultaneously) while gpiochip_remove() takes it for writing so +that it can only happen once all syscalls return. + +Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") +Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL") +Fixes: aad955842d1c ("gpiolib: cdev: support GPIO_V2_GET_LINEINFO_IOCTL and GPIO_V2_GET_LINEINFO_WATCH_IOCTL") +Fixes: a54756cb24ea ("gpiolib: cdev: support GPIO_V2_LINE_SET_CONFIG_IOCTL") +Fixes: 7b8e00d98168 ("gpiolib: cdev: support GPIO_V2_LINE_SET_VALUES_IOCTL") +Signed-off-by: Bartosz Golaszewski +[Nick: fixed a build failure with CDEV_V1 disabled] +Co-authored-by: Nick Hainke +Reviewed-by: Kent Gibson +Reviewed-by: Andy Shevchenko +Reviewed-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpiolib-cdev.c | 177 +++++++++++++++++++++++++++++++----- + drivers/gpio/gpiolib.c | 4 + + drivers/gpio/gpiolib.h | 5 + + 3 files changed, 161 insertions(+), 25 deletions(-) + +diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c +index 64e37618216f..2a2e0691462b 100644 +--- a/drivers/gpio/gpiolib-cdev.c ++++ b/drivers/gpio/gpiolib-cdev.c +@@ -54,6 +54,50 @@ static_assert(IS_ALIGNED(sizeof(struct gpio_v2_line_values), 8)); + * interface to gpiolib GPIOs via ioctl()s. + */ + ++typedef __poll_t (*poll_fn)(struct file *, struct poll_table_struct *); ++typedef long (*ioctl_fn)(struct file *, unsigned int, unsigned long); ++typedef ssize_t (*read_fn)(struct file *, char __user *, ++ size_t count, loff_t *); ++ ++static __poll_t call_poll_locked(struct file *file, ++ struct poll_table_struct *wait, ++ struct gpio_device *gdev, poll_fn func) ++{ ++ __poll_t ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, wait); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ ++static long call_ioctl_locked(struct file *file, unsigned int cmd, ++ unsigned long arg, struct gpio_device *gdev, ++ ioctl_fn func) ++{ ++ long ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, cmd, arg); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ ++static ssize_t call_read_locked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps, ++ struct gpio_device *gdev, read_fn func) ++{ ++ ssize_t ret; ++ ++ down_read(&gdev->sem); ++ ret = func(file, buf, count, f_ps); ++ up_read(&gdev->sem); ++ ++ return ret; ++} ++ + /* + * GPIO line handle management + */ +@@ -190,8 +234,8 @@ static long linehandle_set_config(struct linehandle_state *lh, + return 0; + } + +-static long linehandle_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long linehandle_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct linehandle_state *lh = file->private_data; + void __user *ip = (void __user *)arg; +@@ -249,6 +293,15 @@ static long linehandle_ioctl(struct file *file, unsigned int cmd, + } + } + ++static long linehandle_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct linehandle_state *lh = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, lh->gdev, ++ linehandle_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long linehandle_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -1185,8 +1238,8 @@ static long linereq_set_config(struct linereq *lr, void __user *ip) + return ret; + } + +-static long linereq_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long linereq_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct linereq *lr = file->private_data; + void __user *ip = (void __user *)arg; +@@ -1206,6 +1259,15 @@ static long linereq_ioctl(struct file *file, unsigned int cmd, + } + } + ++static long linereq_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, lr->gdev, ++ linereq_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long linereq_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -1214,8 +1276,8 @@ static long linereq_ioctl_compat(struct file *file, unsigned int cmd, + } + #endif + +-static __poll_t linereq_poll(struct file *file, +- struct poll_table_struct *wait) ++static __poll_t linereq_poll_unlocked(struct file *file, ++ struct poll_table_struct *wait) + { + struct linereq *lr = file->private_data; + __poll_t events = 0; +@@ -1232,10 +1294,16 @@ static __poll_t linereq_poll(struct file *file, + return events; + } + +-static ssize_t linereq_read(struct file *file, +- char __user *buf, +- size_t count, +- loff_t *f_ps) ++static __poll_t linereq_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_poll_locked(file, wait, lr->gdev, linereq_poll_unlocked); ++} ++ ++static ssize_t linereq_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) + { + struct linereq *lr = file->private_data; + struct gpio_v2_line_event le; +@@ -1289,6 +1357,15 @@ static ssize_t linereq_read(struct file *file, + return bytes_read; + } + ++static ssize_t linereq_read(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) ++{ ++ struct linereq *lr = file->private_data; ++ ++ return call_read_locked(file, buf, count, f_ps, lr->gdev, ++ linereq_read_unlocked); ++} ++ + static void linereq_free(struct linereq *lr) + { + unsigned int i; +@@ -1504,8 +1581,8 @@ struct lineevent_state { + (GPIOEVENT_REQUEST_RISING_EDGE | \ + GPIOEVENT_REQUEST_FALLING_EDGE) + +-static __poll_t lineevent_poll(struct file *file, +- struct poll_table_struct *wait) ++static __poll_t lineevent_poll_unlocked(struct file *file, ++ struct poll_table_struct *wait) + { + struct lineevent_state *le = file->private_data; + __poll_t events = 0; +@@ -1521,15 +1598,21 @@ static __poll_t lineevent_poll(struct file *file, + return events; + } + ++static __poll_t lineevent_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); ++} ++ + struct compat_gpioeevent_data { + compat_u64 timestamp; + u32 id; + }; + +-static ssize_t lineevent_read(struct file *file, +- char __user *buf, +- size_t count, +- loff_t *f_ps) ++static ssize_t lineevent_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) + { + struct lineevent_state *le = file->private_data; + struct gpioevent_data ge; +@@ -1597,6 +1680,15 @@ static ssize_t lineevent_read(struct file *file, + return bytes_read; + } + ++static ssize_t lineevent_read(struct file *file, char __user *buf, ++ size_t count, loff_t *f_ps) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_read_locked(file, buf, count, f_ps, le->gdev, ++ lineevent_read_unlocked); ++} ++ + static void lineevent_free(struct lineevent_state *le) + { + if (le->irq) +@@ -1614,8 +1706,8 @@ static int lineevent_release(struct inode *inode, struct file *file) + return 0; + } + +-static long lineevent_ioctl(struct file *file, unsigned int cmd, +- unsigned long arg) ++static long lineevent_ioctl_unlocked(struct file *file, unsigned int cmd, ++ unsigned long arg) + { + struct lineevent_state *le = file->private_data; + void __user *ip = (void __user *)arg; +@@ -1646,6 +1738,15 @@ static long lineevent_ioctl(struct file *file, unsigned int cmd, + return -EINVAL; + } + ++static long lineevent_ioctl(struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct lineevent_state *le = file->private_data; ++ ++ return call_ioctl_locked(file, cmd, arg, le->gdev, ++ lineevent_ioctl_unlocked); ++} ++ + #ifdef CONFIG_COMPAT + static long lineevent_ioctl_compat(struct file *file, unsigned int cmd, + unsigned long arg) +@@ -2202,8 +2303,8 @@ static int lineinfo_changed_notify(struct notifier_block *nb, + return NOTIFY_OK; + } + +-static __poll_t lineinfo_watch_poll(struct file *file, +- struct poll_table_struct *pollt) ++static __poll_t lineinfo_watch_poll_unlocked(struct file *file, ++ struct poll_table_struct *pollt) + { + struct gpio_chardev_data *cdev = file->private_data; + __poll_t events = 0; +@@ -2220,8 +2321,17 @@ static __poll_t lineinfo_watch_poll(struct file *file, + return events; + } + +-static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, +- size_t count, loff_t *off) ++static __poll_t lineinfo_watch_poll(struct file *file, ++ struct poll_table_struct *pollt) ++{ ++ struct gpio_chardev_data *cdev = file->private_data; ++ ++ return call_poll_locked(file, pollt, cdev->gdev, ++ lineinfo_watch_poll_unlocked); ++} ++ ++static ssize_t lineinfo_watch_read_unlocked(struct file *file, char __user *buf, ++ size_t count, loff_t *off) + { + struct gpio_chardev_data *cdev = file->private_data; + struct gpio_v2_line_info_changed event; +@@ -2299,6 +2409,15 @@ static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, + return bytes_read; + } + ++static ssize_t lineinfo_watch_read(struct file *file, char __user *buf, ++ size_t count, loff_t *off) ++{ ++ struct gpio_chardev_data *cdev = file->private_data; ++ ++ return call_read_locked(file, buf, count, off, cdev->gdev, ++ lineinfo_watch_read_unlocked); ++} ++ + /** + * gpio_chrdev_open() - open the chardev for ioctl operations + * @inode: inode for this chardev +@@ -2312,13 +2431,17 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) + struct gpio_chardev_data *cdev; + int ret = -ENOMEM; + ++ down_read(&gdev->sem); ++ + /* Fail on open if the backing gpiochip is gone */ +- if (!gdev->chip) +- return -ENODEV; ++ if (!gdev->chip) { ++ ret = -ENODEV; ++ goto out_unlock; ++ } + + cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); + if (!cdev) +- return -ENOMEM; ++ goto out_unlock; + + cdev->watched_lines = bitmap_zalloc(gdev->chip->ngpio, GFP_KERNEL); + if (!cdev->watched_lines) +@@ -2341,6 +2464,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) + if (ret) + goto out_unregister_notifier; + ++ up_read(&gdev->sem); ++ + return ret; + + out_unregister_notifier: +@@ -2350,6 +2475,8 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) + bitmap_free(cdev->watched_lines); + out_free_cdev: + kfree(cdev); ++out_unlock: ++ up_read(&gdev->sem); + return ret; + } + +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index fdca300f6003..8c041a8dd9d8 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -727,6 +727,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, + spin_unlock_irqrestore(&gpio_lock, flags); + + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->notifier); ++ init_rwsem(&gdev->sem); + + #ifdef CONFIG_PINCTRL + INIT_LIST_HEAD(&gdev->pin_ranges); +@@ -865,6 +866,8 @@ void gpiochip_remove(struct gpio_chip *gc) + unsigned long flags; + unsigned int i; + ++ down_write(&gdev->sem); ++ + /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ + gpiochip_sysfs_unregister(gdev); + gpiochip_free_hogs(gc); +@@ -899,6 +902,7 @@ void gpiochip_remove(struct gpio_chip *gc) + * gone. + */ + gcdev_unregister(gdev); ++ up_write(&gdev->sem); + put_device(&gdev->dev); + } + EXPORT_SYMBOL_GPL(gpiochip_remove); +diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h +index d77be9d1da80..73b732a1d9c9 100644 +--- a/drivers/gpio/gpiolib.h ++++ b/drivers/gpio/gpiolib.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #define GPIOCHIP_NAME "gpiochip" + +@@ -39,6 +40,9 @@ + * @list: links gpio_device:s together for traversal + * @notifier: used to notify subscribers about lines being requested, released + * or reconfigured ++ * @sem: protects the structure from a NULL-pointer dereference of @chip by ++ * user-space operations when the device gets unregistered during ++ * a hot-unplug event + * @pin_ranges: range of pins served by the GPIO driver + * + * This state container holds most of the runtime variable data +@@ -60,6 +64,7 @@ struct gpio_device { + void *data; + struct list_head list; + struct blocking_notifier_head notifier; ++ struct rw_semaphore sem; + + #ifdef CONFIG_PINCTRL + /* +-- +2.35.1 + diff --git a/queue-5.15/hamradio-baycom_epp-fix-return-type-of-baycom_send_p.patch b/queue-5.15/hamradio-baycom_epp-fix-return-type-of-baycom_send_p.patch new file mode 100644 index 00000000000..74fa294d26d --- /dev/null +++ b/queue-5.15/hamradio-baycom_epp-fix-return-type-of-baycom_send_p.patch @@ -0,0 +1,52 @@ +From 3b7ae21fac9fc60ca16d730d52b655f3b04f93bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 09:06:10 -0700 +Subject: hamradio: baycom_epp: Fix return type of baycom_send_packet() + +From: Nathan Chancellor + +[ Upstream commit c5733e5b15d91ab679646ec3149e192996a27d5d ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/net/hamradio/baycom_epp.c:1119:25: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = baycom_send_packet, + ^~~~~~~~~~~~~~~~~~ + 1 error generated. + +->ndo_start_xmit() in 'struct net_device_ops' expects a return type of +'netdev_tx_t', not 'int'. Adjust the return type of baycom_send_packet() +to match the prototype's to resolve the warning and CFI failure. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Signed-off-by: Nathan Chancellor +Reviewed-by: Kees Cook +Link: https://lore.kernel.org/r/20221102160610.1186145-1-nathan@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/hamradio/baycom_epp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c +index 6b6f28d5b8d5..f9d03f7b9101 100644 +--- a/drivers/net/hamradio/baycom_epp.c ++++ b/drivers/net/hamradio/baycom_epp.c +@@ -758,7 +758,7 @@ static void epp_bh(struct work_struct *work) + * ===================== network driver interface ========================= + */ + +-static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t baycom_send_packet(struct sk_buff *skb, struct net_device *dev) + { + struct baycom_state *bc = netdev_priv(dev); + +-- +2.35.1 + diff --git a/queue-5.15/hamradio-don-t-call-dev_kfree_skb-under-spin_lock_ir.patch b/queue-5.15/hamradio-don-t-call-dev_kfree_skb-under-spin_lock_ir.patch new file mode 100644 index 00000000000..7faf9cd228b --- /dev/null +++ b/queue-5.15/hamradio-don-t-call-dev_kfree_skb-under-spin_lock_ir.patch @@ -0,0 +1,62 @@ +From 6ac90072bd014896cb3b344251796571ceae239e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 22:21:46 +0800 +Subject: hamradio: don't call dev_kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 3727f742915f04f6fc550b80cf406999bd4e90d0 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In scc_discard_buffers(), dev_kfree_skb() is called to discard the SKBs, +so replace it with dev_kfree_skb_irq(). + +In scc_net_tx(), dev_kfree_skb() is called to drop the SKB that exceed +queue length, so replace it with dev_kfree_skb_irq(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/hamradio/scc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c +index e0bb131a33d7..39db3cae4dd1 100644 +--- a/drivers/net/hamradio/scc.c ++++ b/drivers/net/hamradio/scc.c +@@ -301,12 +301,12 @@ static inline void scc_discard_buffers(struct scc_channel *scc) + spin_lock_irqsave(&scc->lock, flags); + if (scc->tx_buff != NULL) + { +- dev_kfree_skb(scc->tx_buff); ++ dev_kfree_skb_irq(scc->tx_buff); + scc->tx_buff = NULL; + } + + while (!skb_queue_empty(&scc->tx_queue)) +- dev_kfree_skb(skb_dequeue(&scc->tx_queue)); ++ dev_kfree_skb_irq(skb_dequeue(&scc->tx_queue)); + + spin_unlock_irqrestore(&scc->lock, flags); + } +@@ -1668,7 +1668,7 @@ static netdev_tx_t scc_net_tx(struct sk_buff *skb, struct net_device *dev) + if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) { + struct sk_buff *skb_del; + skb_del = skb_dequeue(&scc->tx_queue); +- dev_kfree_skb(skb_del); ++ dev_kfree_skb_irq(skb_del); + } + skb_queue_tail(&scc->tx_queue, skb); + netif_trans_update(dev); +-- +2.35.1 + diff --git a/queue-5.15/hfs-fix-oob-read-in-__hfs_brec_find.patch b/queue-5.15/hfs-fix-oob-read-in-__hfs_brec_find.patch new file mode 100644 index 00000000000..3f29d42f5e2 --- /dev/null +++ b/queue-5.15/hfs-fix-oob-read-in-__hfs_brec_find.patch @@ -0,0 +1,81 @@ +From 34d8979e15c87da6d2fb9cc014850ce2d6a44b47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 06:59:59 +0000 +Subject: hfs: fix OOB Read in __hfs_brec_find + +From: ZhangPeng + +[ Upstream commit 8d824e69d9f3fa3121b2dda25053bae71e2460d2 ] + +Syzbot reported a OOB read bug: + +================================================================== +BUG: KASAN: slab-out-of-bounds in hfs_strcmp+0x117/0x190 +fs/hfs/string.c:84 +Read of size 1 at addr ffff88807eb62c4e by task kworker/u4:1/11 +CPU: 1 PID: 11 Comm: kworker/u4:1 Not tainted +6.1.0-rc6-syzkaller-00308-g644e9524388a #0 +Workqueue: writeback wb_workfn (flush-7:0) +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106 + print_address_description+0x74/0x340 mm/kasan/report.c:284 + print_report+0x107/0x1f0 mm/kasan/report.c:395 + kasan_report+0xcd/0x100 mm/kasan/report.c:495 + hfs_strcmp+0x117/0x190 fs/hfs/string.c:84 + __hfs_brec_find+0x213/0x5c0 fs/hfs/bfind.c:75 + hfs_brec_find+0x276/0x520 fs/hfs/bfind.c:138 + hfs_write_inode+0x34c/0xb40 fs/hfs/inode.c:462 + write_inode fs/fs-writeback.c:1440 [inline] + +If the input inode of hfs_write_inode() is incorrect: +struct inode + struct hfs_inode_info + struct hfs_cat_key + struct hfs_name + u8 len # len is greater than HFS_NAMELEN(31) which is the +maximum length of an HFS filename + +OOB read occurred: +hfs_write_inode() + hfs_brec_find() + __hfs_brec_find() + hfs_cat_keycmp() + hfs_strcmp() # OOB read occurred due to len is too large + +Fix this by adding a Check on len in hfs_write_inode() before calling +hfs_brec_find(). + +Link: https://lkml.kernel.org/r/20221130065959.2168236-1-zhangpeng362@huawei.com +Signed-off-by: ZhangPeng +Reported-by: +Cc: Damien Le Moal +Cc: Ira Weiny +Cc: Jeff Layton +Cc: Kefeng Wang +Cc: Matthew Wilcox +Cc: Nanyong Sun +Cc: Viacheslav Dubeyko +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/hfs/inode.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c +index 4a95a92546a0..a58a5b733224 100644 +--- a/fs/hfs/inode.c ++++ b/fs/hfs/inode.c +@@ -456,6 +456,8 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + /* panic? */ + return -EIO; + ++ if (HFS_I(main_inode)->cat_key.CName.len > HFS_NAMELEN) ++ return -EIO; + fd.search_key->cat = HFS_I(main_inode)->cat_key; + if (hfs_brec_find(&fd)) + /* panic? */ +-- +2.35.1 + diff --git a/queue-5.15/hfs-fix-oob-write-in-hfs_asc2mac.patch b/queue-5.15/hfs-fix-oob-write-in-hfs_asc2mac.patch new file mode 100644 index 00000000000..f34946d60b3 --- /dev/null +++ b/queue-5.15/hfs-fix-oob-write-in-hfs_asc2mac.patch @@ -0,0 +1,66 @@ +From ce3fac9114b7536c6f83d56348fca95b7772d585 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 03:00:38 +0000 +Subject: hfs: Fix OOB Write in hfs_asc2mac + +From: ZhangPeng + +[ Upstream commit c53ed55cb275344086e32a7080a6b19cb183650b ] + +Syzbot reported a OOB Write bug: + +loop0: detected capacity change from 0 to 64 +================================================================== +BUG: KASAN: slab-out-of-bounds in hfs_asc2mac+0x467/0x9a0 +fs/hfs/trans.c:133 +Write of size 1 at addr ffff88801848314e by task syz-executor391/3632 + +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106 + print_address_description+0x74/0x340 mm/kasan/report.c:284 + print_report+0x107/0x1f0 mm/kasan/report.c:395 + kasan_report+0xcd/0x100 mm/kasan/report.c:495 + hfs_asc2mac+0x467/0x9a0 fs/hfs/trans.c:133 + hfs_cat_build_key+0x92/0x170 fs/hfs/catalog.c:28 + hfs_lookup+0x1ab/0x2c0 fs/hfs/dir.c:31 + lookup_open fs/namei.c:3391 [inline] + open_last_lookups fs/namei.c:3481 [inline] + path_openat+0x10e6/0x2df0 fs/namei.c:3710 + do_filp_open+0x264/0x4f0 fs/namei.c:3740 + +If in->len is much larger than HFS_NAMELEN(31) which is the maximum +length of an HFS filename, a OOB write could occur in hfs_asc2mac(). In +that case, when the dst reaches the boundary, the srclen is still +greater than 0, which causes a OOB write. +Fix this by adding a check on dstlen in while() before writing to dst +address. + +Link: https://lkml.kernel.org/r/20221202030038.1391945-1-zhangpeng362@huawei.com +Fixes: 328b92278650 ("[PATCH] hfs: NLS support") +Signed-off-by: ZhangPeng +Reviewed-by: Viacheslav Dubeyko +Reported-by: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/hfs/trans.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c +index 39f5e343bf4d..fdb0edb8a607 100644 +--- a/fs/hfs/trans.c ++++ b/fs/hfs/trans.c +@@ -109,7 +109,7 @@ void hfs_asc2mac(struct super_block *sb, struct hfs_name *out, const struct qstr + if (nls_io) { + wchar_t ch; + +- while (srclen > 0) { ++ while (srclen > 0 && dstlen > 0) { + size = nls_io->char2uni(src, srclen, &ch); + if (size < 0) { + ch = '?'; +-- +2.35.1 + diff --git a/queue-5.15/hid-amd_sfh-add-missing-check-for-dma_alloc_coherent.patch b/queue-5.15/hid-amd_sfh-add-missing-check-for-dma_alloc_coherent.patch new file mode 100644 index 00000000000..f8cdd8afbf3 --- /dev/null +++ b/queue-5.15/hid-amd_sfh-add-missing-check-for-dma_alloc_coherent.patch @@ -0,0 +1,40 @@ +From 52c7c5db559e1cf3308b525042ad9cac6ddb4266 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Dec 2022 10:49:21 +0800 +Subject: HID: amd_sfh: Add missing check for dma_alloc_coherent + +From: Jiasheng Jiang + +[ Upstream commit 53ffa6a9f83b2170c60591da1ead8791d5a42e81 ] + +Add check for the return value of the dma_alloc_coherent since +it may return NULL pointer if allocation fails. + +Fixes: 4b2c53d93a4b ("SFH:Transport Driver to add support of AMD Sensor Fusion Hub (SFH)") +Signed-off-by: Jiasheng Jiang +Acked-by: Basavaraj Natikar +Signed-off-by: Benjamin Tissoires +Link: https://lore.kernel.org/r/20221220024921.21992-1-jiasheng@iscas.ac.cn +Signed-off-by: Sasha Levin +--- + drivers/hid/amd-sfh-hid/amd_sfh_client.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +index ab149b80f86c..911a23a9bcd1 100644 +--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c ++++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c +@@ -166,6 +166,10 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) + in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8, + &cl_data->sensor_dma_addr[i], + GFP_KERNEL); ++ if (!in_data->sensor_virt_addr[i]) { ++ rc = -ENOMEM; ++ goto cleanup; ++ } + cl_data->sensor_sts[i] = SENSOR_DISABLED; + cl_data->sensor_requested_cnt[i] = 0; + cl_data->cur_hid_dev = i; +-- +2.35.1 + diff --git a/queue-5.15/hid-hid-sensor-custom-set-fixed-size-for-custom-attr.patch b/queue-5.15/hid-hid-sensor-custom-set-fixed-size-for-custom-attr.patch new file mode 100644 index 00000000000..b4b26f4bc43 --- /dev/null +++ b/queue-5.15/hid-hid-sensor-custom-set-fixed-size-for-custom-attr.patch @@ -0,0 +1,48 @@ +From 6176142c1219f3124937656a8e369c4dcbf56855 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 13:13:26 +0100 +Subject: HID: hid-sensor-custom: set fixed size for custom attributes + +From: Marcus Folkesson + +[ Upstream commit 9d013910df22de91333a0acc81d1dbb115bd76f6 ] + +This is no bugfix (so no Fixes: tag is necessary) as it is +taken care of in hid_sensor_custom_add_attributes(). + +The motivation for this patch is that: +hid_sensor_custom_field.attr_name and +hid_sensor_custom_field.attrs +has the size of HID_CUSTOM_TOTAL_ATTRS and used in same context. + +We compare against HID_CUSTOM_TOTAL_ATTRS when +looping through hid_custom_attrs. + +We will silent the smatch error: +hid_sensor_custom_add_attributes() error: buffer overflow +'hid_custom_attrs' 8 <= 10 + +Signed-off-by: Marcus Folkesson +Acked-by: Jonathan Cameron +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-sensor-custom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c +index 32c2306e240d..602465ad2745 100644 +--- a/drivers/hid/hid-sensor-custom.c ++++ b/drivers/hid/hid-sensor-custom.c +@@ -62,7 +62,7 @@ struct hid_sensor_sample { + u32 raw_len; + } __packed; + +-static struct attribute hid_custom_attrs[] = { ++static struct attribute hid_custom_attrs[HID_CUSTOM_TOTAL_ATTRS] = { + {.name = "name", .mode = S_IRUGO}, + {.name = "units", .mode = S_IRUGO}, + {.name = "unit-expo", .mode = S_IRUGO}, +-- +2.35.1 + diff --git a/queue-5.15/hsi-omap_ssi_core-fix-error-handling-in-ssi_init.patch b/queue-5.15/hsi-omap_ssi_core-fix-error-handling-in-ssi_init.patch new file mode 100644 index 00000000000..7ff2b3cbe0f --- /dev/null +++ b/queue-5.15/hsi-omap_ssi_core-fix-error-handling-in-ssi_init.patch @@ -0,0 +1,45 @@ +From cb4dab9f870f2fb5d330c6d6af4eb5a4c1f6b513 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 11:33:32 +0000 +Subject: HSI: omap_ssi_core: Fix error handling in ssi_init() + +From: Yuan Can + +[ Upstream commit 3ffa9f713c39a213a08d9ff13ab983a8aa5d8b5d ] + +The ssi_init() returns the platform_driver_register() directly without +checking its return value, if platform_driver_register() failed, the +ssi_pdriver is not unregistered. +Fix by unregister ssi_pdriver when the last platform_driver_register() +failed. + +Fixes: 0fae198988b8 ("HSI: omap_ssi: built omap_ssi and omap_ssi_port into one module") +Signed-off-by: Yuan Can +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/controllers/omap_ssi_core.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c +index 052cf3e92dd6..26f2c3c01297 100644 +--- a/drivers/hsi/controllers/omap_ssi_core.c ++++ b/drivers/hsi/controllers/omap_ssi_core.c +@@ -631,7 +631,13 @@ static int __init ssi_init(void) { + if (ret) + return ret; + +- return platform_driver_register(&ssi_port_pdriver); ++ ret = platform_driver_register(&ssi_port_pdriver); ++ if (ret) { ++ platform_driver_unregister(&ssi_pdriver); ++ return ret; ++ } ++ ++ return 0; + } + module_init(ssi_init); + +-- +2.35.1 + diff --git a/queue-5.15/hsi-omap_ssi_core-fix-possible-memory-leak-in-ssi_pr.patch b/queue-5.15/hsi-omap_ssi_core-fix-possible-memory-leak-in-ssi_pr.patch new file mode 100644 index 00000000000..a6567733811 --- /dev/null +++ b/queue-5.15/hsi-omap_ssi_core-fix-possible-memory-leak-in-ssi_pr.patch @@ -0,0 +1,41 @@ +From 04cabb09694ed93119db3053ef6ac17394f259b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 15:43:37 +0800 +Subject: HSI: omap_ssi_core: fix possible memory leak in ssi_probe() + +From: Yang Yingliang + +[ Upstream commit 1aff514e1d2bd47854dbbdf867970b9d463d4c57 ] + +If ssi_add_controller() returns error, it should call hsi_put_controller() +to give up the reference that was set in hsi_alloc_controller(), so that +it can call hsi_controller_release() to free controller and ports that +allocated in hsi_alloc_controller(). + +Fixes: b209e047bc74 ("HSI: Introduce OMAP SSI driver") +Signed-off-by: Yang Yingliang +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/controllers/omap_ssi_core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c +index b23a576ed88a..052cf3e92dd6 100644 +--- a/drivers/hsi/controllers/omap_ssi_core.c ++++ b/drivers/hsi/controllers/omap_ssi_core.c +@@ -502,8 +502,10 @@ static int ssi_probe(struct platform_device *pd) + platform_set_drvdata(pd, ssi); + + err = ssi_add_controller(ssi, pd); +- if (err < 0) ++ if (err < 0) { ++ hsi_put_controller(ssi); + goto out1; ++ } + + pm_runtime_enable(&pd->dev); + +-- +2.35.1 + diff --git a/queue-5.15/hsi-omap_ssi_core-fix-unbalanced-pm_runtime_disable.patch b/queue-5.15/hsi-omap_ssi_core-fix-unbalanced-pm_runtime_disable.patch new file mode 100644 index 00000000000..a23184c018d --- /dev/null +++ b/queue-5.15/hsi-omap_ssi_core-fix-unbalanced-pm_runtime_disable.patch @@ -0,0 +1,38 @@ +From 43a0faa9f67f4d483c9a4a28504dcd01765dd391 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 11:41:18 +0800 +Subject: HSI: omap_ssi_core: fix unbalanced pm_runtime_disable() + +From: Yang Yingliang + +[ Upstream commit f5181c35ed7ba0ceb6e42872aad1334d994b0175 ] + +In error label 'out1' path in ssi_probe(), the pm_runtime_enable() +has not been called yet, so pm_runtime_disable() is not needed. + +Fixes: b209e047bc74 ("HSI: Introduce OMAP SSI driver") +Signed-off-by: Yang Yingliang +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/controllers/omap_ssi_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c +index eb9820158318..b23a576ed88a 100644 +--- a/drivers/hsi/controllers/omap_ssi_core.c ++++ b/drivers/hsi/controllers/omap_ssi_core.c +@@ -536,9 +536,9 @@ static int ssi_probe(struct platform_device *pd) + device_for_each_child(&pd->dev, NULL, ssi_remove_ports); + out2: + ssi_remove_controller(ssi); ++ pm_runtime_disable(&pd->dev); + out1: + platform_set_drvdata(pd, NULL); +- pm_runtime_disable(&pd->dev); + + return err; + } +-- +2.35.1 + diff --git a/queue-5.15/hsr-add-a-rcu-read-lock-to-hsr_forward_skb.patch b/queue-5.15/hsr-add-a-rcu-read-lock-to-hsr_forward_skb.patch new file mode 100644 index 00000000000..d87906f5eb7 --- /dev/null +++ b/queue-5.15/hsr-add-a-rcu-read-lock-to-hsr_forward_skb.patch @@ -0,0 +1,55 @@ +From e421b8f74dc7c681bdebc8d6798d5ddaf0e77253 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:09 +0100 +Subject: hsr: Add a rcu-read lock to hsr_forward_skb(). + +From: Sebastian Andrzej Siewior + +[ Upstream commit 5aa2820177af650293b2f9f1873c1f6f8e4ad7a4 ] + +hsr_forward_skb() a skb and keeps information in an on-stack +hsr_frame_info. hsr_get_node() assigns hsr_frame_info::node_src which is +from a RCU list. This pointer is used later in hsr_forward_do(). +I don't see a reason why this pointer can't vanish midway since there is +no guarantee that hsr_forward_skb() is invoked from an RCU read section. + +Use rcu_read_lock() to protect hsr_frame_info::node_src from its +assignment until it is no longer used. + +Fixes: f266a683a4804 ("net/hsr: Better frame dispatch") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_forward.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index 07892c4b6d0c..daf6abbadeb9 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -572,11 +572,13 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) + { + struct hsr_frame_info frame; + ++ rcu_read_lock(); + if (fill_frame_info(&frame, skb, port) < 0) + goto out_drop; + + hsr_register_frame_in(frame.node_src, port, frame.sequence_nr); + hsr_forward_do(&frame); ++ rcu_read_unlock(); + /* Gets called for ingress frames as well as egress from master port. + * So check and increment stats for master port only here. + */ +@@ -591,6 +593,7 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) + return; + + out_drop: ++ rcu_read_unlock(); + port->dev->stats.tx_dropped++; + kfree_skb(skb); + } +-- +2.35.1 + diff --git a/queue-5.15/hsr-avoid-double-remove-of-a-node.patch b/queue-5.15/hsr-avoid-double-remove-of-a-node.patch new file mode 100644 index 00000000000..290d57d0589 --- /dev/null +++ b/queue-5.15/hsr-avoid-double-remove-of-a-node.patch @@ -0,0 +1,85 @@ +From fa101dddfc35763673f1e188761776c0dc7a751b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:10 +0100 +Subject: hsr: Avoid double remove of a node. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 0c74d9f79ec4299365bbe803baa736ae0068179e ] + +Due to the hashed-MAC optimisation one problem become visible: +hsr_handle_sup_frame() walks over the list of available nodes and merges +two node entries into one if based on the information in the supervision +both MAC addresses belong to one node. The list-walk happens on a RCU +protected list and delete operation happens under a lock. + +If the supervision arrives on both slave interfaces at the same time +then this delete operation can occur simultaneously on two CPUs. The +result is the first-CPU deletes the from the list and the second CPUs +BUGs while attempting to dereference a poisoned list-entry. This happens +more likely with the optimisation because a new node for the mac_B entry +is created once a packet has been received and removed (merged) once the +supervision frame has been received. + +Avoid removing/ cleaning up a hsr_node twice by adding a `removed' field +which is set to true after the removal and checked before the removal. + +Fixes: f266a683a4804 ("net/hsr: Better frame dispatch") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_framereg.c | 16 +++++++++++----- + net/hsr/hsr_framereg.h | 1 + + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index e31949479305..440788e5b3e2 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -326,9 +326,12 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + node_real->addr_B_port = port_rcv->type; + + spin_lock_bh(&hsr->list_lock); +- list_del_rcu(&node_curr->mac_list); ++ if (!node_curr->removed) { ++ list_del_rcu(&node_curr->mac_list); ++ node_curr->removed = true; ++ kfree_rcu(node_curr, rcu_head); ++ } + spin_unlock_bh(&hsr->list_lock); +- kfree_rcu(node_curr, rcu_head); + + done: + /* PRP uses v0 header */ +@@ -502,9 +505,12 @@ void hsr_prune_nodes(struct timer_list *t) + if (time_is_before_jiffies(timestamp + + msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { + hsr_nl_nodedown(hsr, node->macaddress_A); +- list_del_rcu(&node->mac_list); +- /* Note that we need to free this entry later: */ +- kfree_rcu(node, rcu_head); ++ if (!node->removed) { ++ list_del_rcu(&node->mac_list); ++ node->removed = true; ++ /* Note that we need to free this entry later: */ ++ kfree_rcu(node, rcu_head); ++ } + } + } + spin_unlock_bh(&hsr->list_lock); +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index d9628e7a5f05..f9c83dc02ca5 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -80,6 +80,7 @@ struct hsr_node { + bool san_a; + bool san_b; + u16 seq_out[HSR_PT_PORTS]; ++ bool removed; + struct rcu_head rcu_head; + }; + +-- +2.35.1 + diff --git a/queue-5.15/hsr-disable-netpoll.patch b/queue-5.15/hsr-disable-netpoll.patch new file mode 100644 index 00000000000..762bb76c319 --- /dev/null +++ b/queue-5.15/hsr-disable-netpoll.patch @@ -0,0 +1,133 @@ +From 9df5854d67e5f8c98a75470cba35f0a6cc040869 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:11 +0100 +Subject: hsr: Disable netpoll. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Sebastian Andrzej Siewior + +[ Upstream commit d5c7652eb16fa203d82546e0285136d7b321ffa9 ] + +The hsr device is a software device. Its +net_device_ops::ndo_start_xmit() routine will process the packet and +then pass the resulting skb to dev_queue_xmit(). +During processing, hsr acquires a lock with spin_lock_bh() +(hsr_add_node()) which needs to be promoted to the _irq() suffix in +order to avoid a potential deadlock. +Then there are the warnings in dev_queue_xmit() (due to +local_bh_disable() with disabled interrupts) left. + +Instead trying to address those (there is qdisc and…) for netpoll sake, +just disable netpoll on hsr. + +Disable netpoll on hsr and replace the _irqsave() locking with _bh(). + +Fixes: f421436a591d3 ("net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 14 ++++++-------- + net/hsr/hsr_forward.c | 5 ++--- + 2 files changed, 8 insertions(+), 11 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index a1045c3d71b4..c44c6747a0bf 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -278,7 +278,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + __u8 type = HSR_TLV_LIFE_CHECK; + struct hsr_sup_payload *hsr_sp; + struct hsr_sup_tag *hsr_stag; +- unsigned long irqflags; + struct sk_buff *skb; + + *interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); +@@ -299,7 +298,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + set_hsr_stag_HSR_ver(hsr_stag, hsr->prot_version); + + /* From HSRv1 on we have separate supervision sequence numbers. */ +- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); ++ spin_lock_bh(&hsr->seqnr_lock); + if (hsr->prot_version > 0) { + hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); + hsr->sup_sequence_nr++; +@@ -307,7 +306,7 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + hsr_stag->sequence_nr = htons(hsr->sequence_nr); + hsr->sequence_nr++; + } +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); ++ spin_unlock_bh(&hsr->seqnr_lock); + + hsr_stag->HSR_TLV_type = type; + /* TODO: Why 12 in HSRv0? */ +@@ -332,7 +331,6 @@ static void send_prp_supervision_frame(struct hsr_port *master, + struct hsr_priv *hsr = master->hsr; + struct hsr_sup_payload *hsr_sp; + struct hsr_sup_tag *hsr_stag; +- unsigned long irqflags; + struct sk_buff *skb; + + skb = hsr_init_skb(master); +@@ -347,7 +345,7 @@ static void send_prp_supervision_frame(struct hsr_port *master, + set_hsr_stag_HSR_ver(hsr_stag, (hsr->prot_version ? 1 : 0)); + + /* From HSRv1 on we have separate supervision sequence numbers. */ +- spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); ++ spin_lock_bh(&hsr->seqnr_lock); + hsr_stag->sequence_nr = htons(hsr->sup_sequence_nr); + hsr->sup_sequence_nr++; + hsr_stag->HSR_TLV_type = PRP_TLV_LIFE_CHECK_DD; +@@ -358,11 +356,11 @@ static void send_prp_supervision_frame(struct hsr_port *master, + ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); + + if (skb_put_padto(skb, ETH_ZLEN)) { +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); ++ spin_unlock_bh(&hsr->seqnr_lock); + return; + } + +- spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); ++ spin_unlock_bh(&hsr->seqnr_lock); + + hsr_forward_skb(skb, master); + } +@@ -444,7 +442,7 @@ void hsr_dev_setup(struct net_device *dev) + dev->header_ops = &hsr_header_ops; + dev->netdev_ops = &hsr_device_ops; + SET_NETDEV_DEVTYPE(dev, &hsr_type); +- dev->priv_flags |= IFF_NO_QUEUE; ++ dev->priv_flags |= IFF_NO_QUEUE | IFF_DISABLE_NETPOLL; + + dev->needs_free_netdev = true; + +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index daf6abbadeb9..c8bcbd990f59 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -458,7 +458,6 @@ static void handle_std_frame(struct sk_buff *skb, + { + struct hsr_port *port = frame->port_rcv; + struct hsr_priv *hsr = port->hsr; +- unsigned long irqflags; + + frame->skb_hsr = NULL; + frame->skb_prp = NULL; +@@ -468,10 +467,10 @@ static void handle_std_frame(struct sk_buff *skb, + frame->is_from_san = true; + } else { + /* Sequence nr for the master node */ +- spin_lock_irqsave(&hsr->seqnr_lock, irqflags); ++ spin_lock_bh(&hsr->seqnr_lock); + frame->sequence_nr = hsr->sequence_nr; + hsr->sequence_nr++; +- spin_unlock_irqrestore(&hsr->seqnr_lock, irqflags); ++ spin_unlock_bh(&hsr->seqnr_lock); + } + } + +-- +2.35.1 + diff --git a/queue-5.15/hsr-synchronize-sending-frames-to-have-always-increm.patch b/queue-5.15/hsr-synchronize-sending-frames-to-have-always-increm.patch new file mode 100644 index 00000000000..fb777b917e0 --- /dev/null +++ b/queue-5.15/hsr-synchronize-sending-frames-to-have-always-increm.patch @@ -0,0 +1,137 @@ +From 3210c8ab971a8e78a2891025a18eca2895cb893a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:12 +0100 +Subject: hsr: Synchronize sending frames to have always incremented outgoing + seq nr. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 06afd2c31d338fa762548580c1bf088703dd1e03 ] + +Sending frames via the hsr (master) device requires a sequence number +which is tracked in hsr_priv::sequence_nr and protected by +hsr_priv::seqnr_lock. Each time a new frame is sent, it will obtain a +new id and then send it via the slave devices. +Each time a packet is sent (via hsr_forward_do()) the sequence number is +checked via hsr_register_frame_out() to ensure that a frame is not +handled twice. This make sense for the receiving side to ensure that the +frame is not injected into the stack twice after it has been received +from both slave ports. + +There is no locking to cover the sending path which means the following +scenario is possible: + + CPU0 CPU1 + hsr_dev_xmit(skb1) hsr_dev_xmit(skb2) + fill_frame_info() fill_frame_info() + hsr_fill_frame_info() hsr_fill_frame_info() + handle_std_frame() handle_std_frame() + skb1's sequence_nr = 1 + skb2's sequence_nr = 2 + hsr_forward_do() hsr_forward_do() + + hsr_register_frame_out(, 2) // okay, send) + + hsr_register_frame_out(, 1) // stop, lower seq duplicate + +Both skbs (or their struct hsr_frame_info) received an unique id. +However since skb2 was sent before skb1, the higher sequence number was +recorded in hsr_register_frame_out() and the late arriving skb1 was +dropped and never sent. + +This scenario has been observed in a three node HSR setup, with node1 + +node2 having ping and iperf running in parallel. From time to time ping +reported a missing packet. Based on tracing that missing ping packet did +not leave the system. + +It might be possible (didn't check) to drop the sequence number check on +the sending side. But if the higher sequence number leaves on wire +before the lower does and the destination receives them in that order +and it will drop the packet with the lower sequence number and never +inject into the stack. +Therefore it seems the only way is to lock the whole path from obtaining +the sequence number and sending via dev_queue_xmit() and assuming the +packets leave on wire in the same order (and don't get reordered by the +NIC). + +Cover the whole path for the master interface from obtaining the ID +until after it has been forwarded via hsr_forward_skb() to ensure the +skbs are sent to the NIC in the order of the assigned sequence numbers. + +Fixes: f421436a591d3 ("net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_device.c | 12 +++++++----- + net/hsr/hsr_forward.c | 3 +-- + 2 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c +index c44c6747a0bf..7ce40b49c956 100644 +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -219,7 +219,9 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) + skb->dev = master->dev; + skb_reset_mac_header(skb); + skb_reset_mac_len(skb); ++ spin_lock_bh(&hsr->seqnr_lock); + hsr_forward_skb(skb, master); ++ spin_unlock_bh(&hsr->seqnr_lock); + } else { + atomic_long_inc(&dev->tx_dropped); + dev_kfree_skb_any(skb); +@@ -306,7 +308,6 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + hsr_stag->sequence_nr = htons(hsr->sequence_nr); + hsr->sequence_nr++; + } +- spin_unlock_bh(&hsr->seqnr_lock); + + hsr_stag->HSR_TLV_type = type; + /* TODO: Why 12 in HSRv0? */ +@@ -317,11 +318,13 @@ static void send_hsr_supervision_frame(struct hsr_port *master, + hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); + ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); + +- if (skb_put_padto(skb, ETH_ZLEN)) ++ if (skb_put_padto(skb, ETH_ZLEN)) { ++ spin_unlock_bh(&hsr->seqnr_lock); + return; ++ } + + hsr_forward_skb(skb, master); +- ++ spin_unlock_bh(&hsr->seqnr_lock); + return; + } + +@@ -360,9 +363,8 @@ static void send_prp_supervision_frame(struct hsr_port *master, + return; + } + +- spin_unlock_bh(&hsr->seqnr_lock); +- + hsr_forward_skb(skb, master); ++ spin_unlock_bh(&hsr->seqnr_lock); + } + + /* Announce (supervision frame) timer function +diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c +index c8bcbd990f59..35382ed686d1 100644 +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -467,10 +467,9 @@ static void handle_std_frame(struct sk_buff *skb, + frame->is_from_san = true; + } else { + /* Sequence nr for the master node */ +- spin_lock_bh(&hsr->seqnr_lock); ++ lockdep_assert_held(&hsr->seqnr_lock); + frame->sequence_nr = hsr->sequence_nr; + hsr->sequence_nr++; +- spin_unlock_bh(&hsr->seqnr_lock); + } + } + +-- +2.35.1 + diff --git a/queue-5.15/hsr-synchronize-sequence-number-updates.patch b/queue-5.15/hsr-synchronize-sequence-number-updates.patch new file mode 100644 index 00000000000..9c859da7545 --- /dev/null +++ b/queue-5.15/hsr-synchronize-sequence-number-updates.patch @@ -0,0 +1,101 @@ +From c202050a456a70d021d7fc9b15a94daf84e17162 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 17:48:13 +0100 +Subject: hsr: Synchronize sequence number updates. + +From: Sebastian Andrzej Siewior + +[ Upstream commit 5c7aa13210c3abdd34fd421f62347665ec6eb551 ] + +hsr_register_frame_out() compares new sequence_nr vs the old one +recorded in hsr_node::seq_out and if the new sequence_nr is higher then +it will be written to hsr_node::seq_out as the new value. + +This operation isn't locked so it is possible that two frames with the +same sequence number arrive (via the two slave devices) and are fed to +hsr_register_frame_out() at the same time. Both will pass the check and +update the sequence counter later to the same value. As a result the +content of the same packet is fed into the stack twice. + +This was noticed by running ping and observing DUP being reported from +time to time. + +Instead of using the hsr_priv::seqnr_lock for the whole receive path (as +it is for sending in the master node) add an additional lock that is only +used for sequence number checks and updates. + +Add a per-node lock that is used during sequence number reads and +updates. + +Fixes: f421436a591d3 ("net/hsr: Add support for the High-availability Seamless Redundancy protocol (HSRv0)") +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_framereg.c | 9 ++++++++- + net/hsr/hsr_framereg.h | 2 ++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c +index 440788e5b3e2..414bf4d3d3c9 100644 +--- a/net/hsr/hsr_framereg.c ++++ b/net/hsr/hsr_framereg.c +@@ -159,6 +159,7 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr, + return NULL; + + ether_addr_copy(new_node->macaddress_A, addr); ++ spin_lock_init(&new_node->seq_out_lock); + + /* We are only interested in time diffs here, so use current jiffies + * as initialization. (0 could trigger an spurious ring error warning). +@@ -313,6 +314,7 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + goto done; + + ether_addr_copy(node_real->macaddress_B, ethhdr->h_source); ++ spin_lock_bh(&node_real->seq_out_lock); + for (i = 0; i < HSR_PT_PORTS; i++) { + if (!node_curr->time_in_stale[i] && + time_after(node_curr->time_in[i], node_real->time_in[i])) { +@@ -323,6 +325,7 @@ void hsr_handle_sup_frame(struct hsr_frame_info *frame) + if (seq_nr_after(node_curr->seq_out[i], node_real->seq_out[i])) + node_real->seq_out[i] = node_curr->seq_out[i]; + } ++ spin_unlock_bh(&node_real->seq_out_lock); + node_real->addr_B_port = port_rcv->type; + + spin_lock_bh(&hsr->list_lock); +@@ -419,13 +422,17 @@ void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, + int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, + u16 sequence_nr) + { ++ spin_lock_bh(&node->seq_out_lock); + if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type]) && + time_is_after_jiffies(node->time_out[port->type] + +- msecs_to_jiffies(HSR_ENTRY_FORGET_TIME))) ++ msecs_to_jiffies(HSR_ENTRY_FORGET_TIME))) { ++ spin_unlock_bh(&node->seq_out_lock); + return 1; ++ } + + node->time_out[port->type] = jiffies; + node->seq_out[port->type] = sequence_nr; ++ spin_unlock_bh(&node->seq_out_lock); + return 0; + } + +diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h +index f9c83dc02ca5..48990166e4c4 100644 +--- a/net/hsr/hsr_framereg.h ++++ b/net/hsr/hsr_framereg.h +@@ -69,6 +69,8 @@ void prp_update_san_info(struct hsr_node *node, bool is_sup); + + struct hsr_node { + struct list_head mac_list; ++ /* Protect R/W access to seq_out */ ++ spinlock_t seq_out_lock; + unsigned char macaddress_A[ETH_ALEN]; + unsigned char macaddress_B[ETH_ALEN]; + /* Local slave through which AddrB frames are received from this node */ +-- +2.35.1 + diff --git a/queue-5.15/hugetlbfs-fix-null-ptr-deref-in-hugetlbfs_parse_para.patch b/queue-5.15/hugetlbfs-fix-null-ptr-deref-in-hugetlbfs_parse_para.patch new file mode 100644 index 00000000000..8708d2156ff --- /dev/null +++ b/queue-5.15/hugetlbfs-fix-null-ptr-deref-in-hugetlbfs_parse_para.patch @@ -0,0 +1,96 @@ +From 19ad01066d5864865bad8646ba1140e19e37c66a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 07:16:08 +0800 +Subject: hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param() + +From: Hawkins Jiawei + +[ Upstream commit 26215b7ee923b9251f7bb12c4e5f09dc465d35f2 ] + +Syzkaller reports a null-ptr-deref bug as follows: +====================================================== +KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] +RIP: 0010:hugetlbfs_parse_param+0x1dd/0x8e0 fs/hugetlbfs/inode.c:1380 +[...] +Call Trace: + + vfs_parse_fs_param fs/fs_context.c:148 [inline] + vfs_parse_fs_param+0x1f9/0x3c0 fs/fs_context.c:129 + vfs_parse_fs_string+0xdb/0x170 fs/fs_context.c:191 + generic_parse_monolithic+0x16f/0x1f0 fs/fs_context.c:231 + do_new_mount fs/namespace.c:3036 [inline] + path_mount+0x12de/0x1e20 fs/namespace.c:3370 + do_mount fs/namespace.c:3383 [inline] + __do_sys_mount fs/namespace.c:3591 [inline] + __se_sys_mount fs/namespace.c:3568 [inline] + __x64_sys_mount+0x27f/0x300 fs/namespace.c:3568 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + [...] + +====================================================== + +According to commit "vfs: parse: deal with zero length string value", +kernel will set the param->string to null pointer in vfs_parse_fs_string() +if fs string has zero length. + +Yet the problem is that, hugetlbfs_parse_param() will dereference the +param->string, without checking whether it is a null pointer. To be more +specific, if hugetlbfs_parse_param() parses an illegal mount parameter, +such as "size=,", kernel will constructs struct fs_parameter with null +pointer in vfs_parse_fs_string(), then passes this struct fs_parameter to +hugetlbfs_parse_param(), which triggers the above null-ptr-deref bug. + +This patch solves it by adding sanity check on param->string +in hugetlbfs_parse_param(). + +Link: https://lkml.kernel.org/r/20221020231609.4810-1-yin31149@gmail.com +Reported-by: syzbot+a3e6acd85ded5c16a709@syzkaller.appspotmail.com +Tested-by: syzbot+a3e6acd85ded5c16a709@syzkaller.appspotmail.com + Link: https://lore.kernel.org/all/0000000000005ad00405eb7148c6@google.com/ +Signed-off-by: Hawkins Jiawei +Reviewed-by: Mike Kravetz +Cc: Hawkins Jiawei +Cc: Muchun Song +Cc: Ian Kent +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/hugetlbfs/inode.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index be8deec29ebe..352230a011e0 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -1250,7 +1250,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_size: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->max_size_opt = memparse(param->string, &rest); + ctx->max_val_type = SIZE_STD; +@@ -1260,7 +1260,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_nr_inodes: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->nr_inodes = memparse(param->string, &rest); + return 0; +@@ -1276,7 +1276,7 @@ static int hugetlbfs_parse_param(struct fs_context *fc, struct fs_parameter *par + + case Opt_min_size: + /* memparse() will accept a K/M/G without a digit */ +- if (!isdigit(param->string[0])) ++ if (!param->string || !isdigit(param->string[0])) + goto bad_val; + ctx->min_size_opt = memparse(param->string, &rest); + ctx->min_val_type = SIZE_STD; +-- +2.35.1 + diff --git a/queue-5.15/hwmon-jc42-convert-register-access-and-caching-to-re.patch b/queue-5.15/hwmon-jc42-convert-register-access-and-caching-to-re.patch new file mode 100644 index 00000000000..392c32380b0 --- /dev/null +++ b/queue-5.15/hwmon-jc42-convert-register-access-and-caching-to-re.patch @@ -0,0 +1,421 @@ +From 1fcb0476a67414b7452a255290c5fdbe4dccd3ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Oct 2022 23:31:56 +0200 +Subject: hwmon: (jc42) Convert register access and caching to regmap/regcache + +From: Martin Blumenstingl + +[ Upstream commit 8f2fa4726faf01094d7a5be7bd0c120c565f54d9 ] + +Switch the jc42 driver to use an I2C regmap to access the registers. +Also move over to regmap's built-in caching instead of adding a +custom caching implementation. This works for JC42_REG_TEMP_UPPER, +JC42_REG_TEMP_LOWER and JC42_REG_TEMP_CRITICAL as these values never +change except when explicitly written. The cache For JC42_REG_TEMP is +dropped (regmap can't cache it because it's volatile, meaning it can +change at any time) as well for simplicity and consistency with other +drivers. + +Signed-off-by: Martin Blumenstingl +Link: https://lore.kernel.org/r/20221023213157.11078-2-martin.blumenstingl@googlemail.com +Signed-off-by: Guenter Roeck +Stable-dep-of: 084ed144c448 ("hwmon: (jc42) Restore the min/max/critical temperatures on resume") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/Kconfig | 1 + + drivers/hwmon/jc42.c | 233 ++++++++++++++++++++++++------------------ + 2 files changed, 132 insertions(+), 102 deletions(-) + +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 51f1caa10d11..17ba1d9ff075 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -776,6 +776,7 @@ config SENSORS_IT87 + config SENSORS_JC42 + tristate "JEDEC JC42.4 compliant memory module temperature sensors" + depends on I2C ++ select REGMAP_I2C + help + If you say yes here, you get support for JEDEC JC42.4 compliant + temperature sensors, which are used on many DDR3 memory modules for +diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c +index 4a03d010ec5a..9a2a062eb7b8 100644 +--- a/drivers/hwmon/jc42.c ++++ b/drivers/hwmon/jc42.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + /* Addresses to scan */ + static const unsigned short normal_i2c[] = { +@@ -189,31 +190,14 @@ static struct jc42_chips jc42_chips[] = { + { STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK }, + }; + +-enum temp_index { +- t_input = 0, +- t_crit, +- t_min, +- t_max, +- t_num_temp +-}; +- +-static const u8 temp_regs[t_num_temp] = { +- [t_input] = JC42_REG_TEMP, +- [t_crit] = JC42_REG_TEMP_CRITICAL, +- [t_min] = JC42_REG_TEMP_LOWER, +- [t_max] = JC42_REG_TEMP_UPPER, +-}; +- + /* Each client has this additional data */ + struct jc42_data { +- struct i2c_client *client; + struct mutex update_lock; /* protect register access */ ++ struct regmap *regmap; + bool extended; /* true if extended range supported */ + bool valid; +- unsigned long last_updated; /* In jiffies */ + u16 orig_config; /* original configuration */ + u16 config; /* current configuration */ +- u16 temp[t_num_temp];/* Temperatures */ + }; + + #define JC42_TEMP_MIN_EXTENDED (-40000) +@@ -238,85 +222,102 @@ static int jc42_temp_from_reg(s16 reg) + return reg * 125 / 2; + } + +-static struct jc42_data *jc42_update_device(struct device *dev) +-{ +- struct jc42_data *data = dev_get_drvdata(dev); +- struct i2c_client *client = data->client; +- struct jc42_data *ret = data; +- int i, val; +- +- mutex_lock(&data->update_lock); +- +- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { +- for (i = 0; i < t_num_temp; i++) { +- val = i2c_smbus_read_word_swapped(client, temp_regs[i]); +- if (val < 0) { +- ret = ERR_PTR(val); +- goto abort; +- } +- data->temp[i] = val; +- } +- data->last_updated = jiffies; +- data->valid = true; +- } +-abort: +- mutex_unlock(&data->update_lock); +- return ret; +-} +- + static int jc42_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) + { +- struct jc42_data *data = jc42_update_device(dev); +- int temp, hyst; ++ struct jc42_data *data = dev_get_drvdata(dev); ++ unsigned int regval; ++ int ret, temp, hyst; + +- if (IS_ERR(data)) +- return PTR_ERR(data); ++ mutex_lock(&data->update_lock); + + switch (attr) { + case hwmon_temp_input: +- *val = jc42_temp_from_reg(data->temp[t_input]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_min: +- *val = jc42_temp_from_reg(data->temp[t_min]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_LOWER, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_max: +- *val = jc42_temp_from_reg(data->temp[t_max]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_crit: +- *val = jc42_temp_from_reg(data->temp[t_crit]); +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ break; ++ ++ *val = jc42_temp_from_reg(regval); ++ break; + case hwmon_temp_max_hyst: +- temp = jc42_temp_from_reg(data->temp[t_max]); ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, ®val); ++ if (ret) ++ break; ++ ++ temp = jc42_temp_from_reg(regval); + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; + *val = temp - hyst; +- return 0; ++ break; + case hwmon_temp_crit_hyst: +- temp = jc42_temp_from_reg(data->temp[t_crit]); ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ break; ++ ++ temp = jc42_temp_from_reg(regval); + hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK) + >> JC42_CFG_HYST_SHIFT]; + *val = temp - hyst; +- return 0; ++ break; + case hwmon_temp_min_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_MIN_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_MIN_BIT) & 1; ++ break; + case hwmon_temp_max_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_MAX_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_MAX_BIT) & 1; ++ break; + case hwmon_temp_crit_alarm: +- *val = (data->temp[t_input] >> JC42_ALARM_CRIT_BIT) & 1; +- return 0; ++ ret = regmap_read(data->regmap, JC42_REG_TEMP, ®val); ++ if (ret) ++ break; ++ ++ *val = (regval >> JC42_ALARM_CRIT_BIT) & 1; ++ break; + default: +- return -EOPNOTSUPP; ++ ret = -EOPNOTSUPP; ++ break; + } ++ ++ mutex_unlock(&data->update_lock); ++ ++ return ret; + } + + static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) + { + struct jc42_data *data = dev_get_drvdata(dev); +- struct i2c_client *client = data->client; ++ unsigned int regval; + int diff, hyst; + int ret; + +@@ -324,21 +325,23 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + + switch (attr) { + case hwmon_temp_min: +- data->temp[t_min] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_min], +- data->temp[t_min]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_LOWER, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_max: +- data->temp[t_max] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_max], +- data->temp[t_max]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_UPPER, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_crit: +- data->temp[t_crit] = jc42_temp_to_reg(val, data->extended); +- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_crit], +- data->temp[t_crit]); ++ ret = regmap_write(data->regmap, JC42_REG_TEMP_CRITICAL, ++ jc42_temp_to_reg(val, data->extended)); + break; + case hwmon_temp_crit_hyst: ++ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL, ++ ®val); ++ if (ret) ++ return ret; ++ + /* + * JC42.4 compliant chips only support four hysteresis values. + * Pick best choice and go from there. +@@ -346,7 +349,7 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + val = clamp_val(val, (data->extended ? JC42_TEMP_MIN_EXTENDED + : JC42_TEMP_MIN) - 6000, + JC42_TEMP_MAX); +- diff = jc42_temp_from_reg(data->temp[t_crit]) - val; ++ diff = jc42_temp_from_reg(regval) - val; + hyst = 0; + if (diff > 0) { + if (diff < 2250) +@@ -358,9 +361,8 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type, + } + data->config = (data->config & ~JC42_CFG_HYST_MASK) | + (hyst << JC42_CFG_HYST_SHIFT); +- ret = i2c_smbus_write_word_swapped(data->client, +- JC42_REG_CONFIG, +- data->config); ++ ret = regmap_write(data->regmap, JC42_REG_CONFIG, ++ data->config); + break; + default: + ret = -EOPNOTSUPP; +@@ -458,51 +460,80 @@ static const struct hwmon_chip_info jc42_chip_info = { + .info = jc42_info, + }; + ++static bool jc42_readable_reg(struct device *dev, unsigned int reg) ++{ ++ return (reg >= JC42_REG_CAP && reg <= JC42_REG_DEVICEID) || ++ reg == JC42_REG_SMBUS; ++} ++ ++static bool jc42_writable_reg(struct device *dev, unsigned int reg) ++{ ++ return (reg >= JC42_REG_CONFIG && reg <= JC42_REG_TEMP_CRITICAL) || ++ reg == JC42_REG_SMBUS; ++} ++ ++static bool jc42_volatile_reg(struct device *dev, unsigned int reg) ++{ ++ return reg == JC42_REG_CONFIG || reg == JC42_REG_TEMP; ++} ++ ++static const struct regmap_config jc42_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 16, ++ .val_format_endian = REGMAP_ENDIAN_BIG, ++ .max_register = JC42_REG_SMBUS, ++ .writeable_reg = jc42_writable_reg, ++ .readable_reg = jc42_readable_reg, ++ .volatile_reg = jc42_volatile_reg, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static int jc42_probe(struct i2c_client *client) + { + struct device *dev = &client->dev; + struct device *hwmon_dev; ++ unsigned int config, cap; + struct jc42_data *data; +- int config, cap; ++ int ret; + + data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + +- data->client = client; ++ data->regmap = devm_regmap_init_i2c(client, &jc42_regmap_config); ++ if (IS_ERR(data->regmap)) ++ return PTR_ERR(data->regmap); ++ + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + +- cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP); +- if (cap < 0) +- return cap; ++ ret = regmap_read(data->regmap, JC42_REG_CAP, &cap); ++ if (ret) ++ return ret; + + data->extended = !!(cap & JC42_CAP_RANGE); + + if (device_property_read_bool(dev, "smbus-timeout-disable")) { +- int smbus; +- + /* + * Not all chips support this register, but from a + * quick read of various datasheets no chip appears + * incompatible with the below attempt to disable + * the timeout. And the whole thing is opt-in... + */ +- smbus = i2c_smbus_read_word_swapped(client, JC42_REG_SMBUS); +- if (smbus < 0) +- return smbus; +- i2c_smbus_write_word_swapped(client, JC42_REG_SMBUS, +- smbus | SMBUS_STMOUT); ++ ret = regmap_set_bits(data->regmap, JC42_REG_SMBUS, ++ SMBUS_STMOUT); ++ if (ret) ++ return ret; + } + +- config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG); +- if (config < 0) +- return config; ++ ret = regmap_read(data->regmap, JC42_REG_CONFIG, &config); ++ if (ret) ++ return ret; + + data->orig_config = config; + if (config & JC42_CFG_SHUTDOWN) { + config &= ~JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, config); + } + data->config = config; + +@@ -523,7 +554,7 @@ static int jc42_remove(struct i2c_client *client) + + config = (data->orig_config & ~JC42_CFG_HYST_MASK) + | (data->config & JC42_CFG_HYST_MASK); +- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, config); + } + return 0; + } +@@ -535,8 +566,7 @@ static int jc42_suspend(struct device *dev) + struct jc42_data *data = dev_get_drvdata(dev); + + data->config |= JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, +- data->config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, data->config); + return 0; + } + +@@ -545,8 +575,7 @@ static int jc42_resume(struct device *dev) + struct jc42_data *data = dev_get_drvdata(dev); + + data->config &= ~JC42_CFG_SHUTDOWN; +- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG, +- data->config); ++ regmap_write(data->regmap, JC42_REG_CONFIG, data->config); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/hwmon-jc42-restore-the-min-max-critical-temperatures.patch b/queue-5.15/hwmon-jc42-restore-the-min-max-critical-temperatures.patch new file mode 100644 index 00000000000..cc88cbcaeee --- /dev/null +++ b/queue-5.15/hwmon-jc42-restore-the-min-max-critical-temperatures.patch @@ -0,0 +1,86 @@ +From b4e155244fabc183848ae2fb4e70d17daef47e3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Oct 2022 23:31:57 +0200 +Subject: hwmon: (jc42) Restore the min/max/critical temperatures on resume +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin Blumenstingl + +[ Upstream commit 084ed144c448fd5bc8ed5a58247153fbbfd115c3 ] + +The JC42 compatible thermal sensor on Kingston KSM32ES8/16ME DIMMs +(using Micron E-Die) is an ST Microelectronics STTS2004 (manufacturer +0x104a, device 0x2201). It does not keep the previously programmed +minimum, maximum and critical temperatures after system suspend and +resume (which is a shutdown / startup cycle for the JC42 temperature +sensor). This results in an alarm on system resume because the hardware +default for these values is 0°C (so any environment temperature greater +than 0°C will trigger the alarm). + +Example before system suspend: + jc42-i2c-0-1a + Adapter: SMBus PIIX4 adapter port 0 at 0b00 + temp1: +34.8°C (low = +0.0°C) + (high = +85.0°C, hyst = +85.0°C) + (crit = +95.0°C, hyst = +95.0°C) + +Example after system resume (without this change): + jc42-i2c-0-1a + Adapter: SMBus PIIX4 adapter port 0 at 0b00 + temp1: +34.8°C (low = +0.0°C) ALARM (HIGH, CRIT) + (high = +0.0°C, hyst = +0.0°C) + (crit = +0.0°C, hyst = +0.0°C) + +Apply the cached values from the JC42_REG_TEMP_UPPER, +JC42_REG_TEMP_LOWER, JC42_REG_TEMP_CRITICAL and JC42_REG_SMBUS (where +the SMBUS register is not related to this issue but a side-effect of +using regcache_sync() during system resume with the previously +cached/programmed values. This fixes the alarm due to the hardware +defaults of 0°C because the previously applied limits (set by userspace) +are re-applied on system resume. + +Fixes: 175c490c9e7f ("hwmon: (jc42) Add support for STTS2004 and AT30TSE004") +Reviewed-by: Guenter Roeck +Signed-off-by: Martin Blumenstingl +Link: https://lore.kernel.org/r/20221023213157.11078-3-martin.blumenstingl@googlemail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/jc42.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c +index 9a2a062eb7b8..5240bfdfcf2e 100644 +--- a/drivers/hwmon/jc42.c ++++ b/drivers/hwmon/jc42.c +@@ -567,6 +567,10 @@ static int jc42_suspend(struct device *dev) + + data->config |= JC42_CFG_SHUTDOWN; + regmap_write(data->regmap, JC42_REG_CONFIG, data->config); ++ ++ regcache_cache_only(data->regmap, true); ++ regcache_mark_dirty(data->regmap); ++ + return 0; + } + +@@ -574,9 +578,13 @@ static int jc42_resume(struct device *dev) + { + struct jc42_data *data = dev_get_drvdata(dev); + ++ regcache_cache_only(data->regmap, false); ++ + data->config &= ~JC42_CFG_SHUTDOWN; + regmap_write(data->regmap, JC42_REG_CONFIG, data->config); +- return 0; ++ ++ /* Restore cached register values to hardware */ ++ return regcache_sync(data->regmap); + } + + static const struct dev_pm_ops jc42_dev_pm_ops = { +-- +2.35.1 + diff --git a/queue-5.15/hwrng-amd-fix-pci-device-refcount-leak.patch b/queue-5.15/hwrng-amd-fix-pci-device-refcount-leak.patch new file mode 100644 index 00000000000..e8a2176715f --- /dev/null +++ b/queue-5.15/hwrng-amd-fix-pci-device-refcount-leak.patch @@ -0,0 +1,76 @@ +From e27f14641d1b40a2d9b3eb297638428e4d6ff217 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 21:22:33 +0800 +Subject: hwrng: amd - Fix PCI device refcount leak + +From: Xiongfeng Wang + +[ Upstream commit ecadb5b0111ea19fc7c240bb25d424a94471eb7d ] + +for_each_pci_dev() is implemented by pci_get_device(). The comment of +pci_get_device() says that it will increase the reference count for the +returned pci_dev and also decrease the reference count for the input +pci_dev @from if it is not NULL. + +If we break for_each_pci_dev() loop with pdev not NULL, we need to call +pci_dev_put() to decrease the reference count. Add the missing +pci_dev_put() for the normal and error path. + +Fixes: 96d63c0297cc ("[PATCH] Add AMD HW RNG driver") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/char/hw_random/amd-rng.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c +index c22d4184bb61..0555e3838bce 100644 +--- a/drivers/char/hw_random/amd-rng.c ++++ b/drivers/char/hw_random/amd-rng.c +@@ -143,15 +143,19 @@ static int __init amd_rng_mod_init(void) + found: + err = pci_read_config_dword(pdev, 0x58, &pmbase); + if (err) +- return err; ++ goto put_dev; + + pmbase &= 0x0000FF00; +- if (pmbase == 0) +- return -EIO; ++ if (pmbase == 0) { ++ err = -EIO; ++ goto put_dev; ++ } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; ++ if (!priv) { ++ err = -ENOMEM; ++ goto put_dev; ++ } + + if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) { + dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n", +@@ -185,6 +189,8 @@ static int __init amd_rng_mod_init(void) + release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE); + out: + kfree(priv); ++put_dev: ++ pci_dev_put(pdev); + return err; + } + +@@ -200,6 +206,8 @@ static void __exit amd_rng_mod_exit(void) + + release_region(priv->pmbase + PMBASE_OFFSET, PMBASE_SIZE); + ++ pci_dev_put(priv->pcidev); ++ + kfree(priv); + } + +-- +2.35.1 + diff --git a/queue-5.15/hwrng-geode-fix-pci-device-refcount-leak.patch b/queue-5.15/hwrng-geode-fix-pci-device-refcount-leak.patch new file mode 100644 index 00000000000..c03265396e5 --- /dev/null +++ b/queue-5.15/hwrng-geode-fix-pci-device-refcount-leak.patch @@ -0,0 +1,115 @@ +From d74b77335070b931bceb3a0298db0ed972ee22ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 21:22:34 +0800 +Subject: hwrng: geode - Fix PCI device refcount leak + +From: Xiongfeng Wang + +[ Upstream commit 9f6ec8dc574efb7f4f3d7ee9cd59ae307e78f445 ] + +for_each_pci_dev() is implemented by pci_get_device(). The comment of +pci_get_device() says that it will increase the reference count for the +returned pci_dev and also decrease the reference count for the input +pci_dev @from if it is not NULL. + +If we break for_each_pci_dev() loop with pdev not NULL, we need to call +pci_dev_put() to decrease the reference count. We add a new struct +'amd_geode_priv' to record pointer of the pci_dev and membase, and then +add missing pci_dev_put() for the normal and error path. + +Fixes: ef5d862734b8 ("[PATCH] Add Geode HW RNG driver") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/char/hw_random/geode-rng.c | 36 +++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 8 deletions(-) + +diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c +index 138ce434f86b..12fbe8091831 100644 +--- a/drivers/char/hw_random/geode-rng.c ++++ b/drivers/char/hw_random/geode-rng.c +@@ -51,6 +51,10 @@ static const struct pci_device_id pci_tbl[] = { + }; + MODULE_DEVICE_TABLE(pci, pci_tbl); + ++struct amd_geode_priv { ++ struct pci_dev *pcidev; ++ void __iomem *membase; ++}; + + static int geode_rng_data_read(struct hwrng *rng, u32 *data) + { +@@ -90,6 +94,7 @@ static int __init geode_rng_init(void) + const struct pci_device_id *ent; + void __iomem *mem; + unsigned long rng_base; ++ struct amd_geode_priv *priv; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); +@@ -97,17 +102,26 @@ static int __init geode_rng_init(void) + goto found; + } + /* Device not found. */ +- goto out; ++ return err; + + found: ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ err = -ENOMEM; ++ goto put_dev; ++ } ++ + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) +- goto out; ++ goto free_priv; + err = -ENOMEM; + mem = ioremap(rng_base, 0x58); + if (!mem) +- goto out; +- geode_rng.priv = (unsigned long)mem; ++ goto free_priv; ++ ++ geode_rng.priv = (unsigned long)priv; ++ priv->membase = mem; ++ priv->pcidev = pdev; + + pr_info("AMD Geode RNG detected\n"); + err = hwrng_register(&geode_rng); +@@ -116,20 +130,26 @@ static int __init geode_rng_init(void) + err); + goto err_unmap; + } +-out: + return err; + + err_unmap: + iounmap(mem); +- goto out; ++free_priv: ++ kfree(priv); ++put_dev: ++ pci_dev_put(pdev); ++ return err; + } + + static void __exit geode_rng_exit(void) + { +- void __iomem *mem = (void __iomem *)geode_rng.priv; ++ struct amd_geode_priv *priv; + ++ priv = (struct amd_geode_priv *)geode_rng.priv; + hwrng_unregister(&geode_rng); +- iounmap(mem); ++ iounmap(priv->membase); ++ pci_dev_put(priv->pcidev); ++ kfree(priv); + } + + module_init(geode_rng_init); +-- +2.35.1 + diff --git a/queue-5.15/i2c-ismt-fix-an-out-of-bounds-bug-in-ismt_access.patch b/queue-5.15/i2c-ismt-fix-an-out-of-bounds-bug-in-ismt_access.patch new file mode 100644 index 00000000000..5efe1d1c7a9 --- /dev/null +++ b/queue-5.15/i2c-ismt-fix-an-out-of-bounds-bug-in-ismt_access.patch @@ -0,0 +1,54 @@ +From 5fb6b5e0971129c3ac3094b71d01a8e1547588ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 19:02:16 +0800 +Subject: i2c: ismt: Fix an out-of-bounds bug in ismt_access() + +From: Zheyu Ma + +[ Upstream commit 39244cc754829bf707dccd12e2ce37510f5b1f8d ] + +When the driver does not check the data from the user, the variable +'data->block[0]' may be very large to cause an out-of-bounds bug. + +The following log can reveal it: + +[ 33.995542] i2c i2c-1: ioctl, cmd=0x720, arg=0x7ffcb3dc3a20 +[ 33.995978] ismt_smbus 0000:00:05.0: I2C_SMBUS_BLOCK_DATA: WRITE +[ 33.996475] ================================================================== +[ 33.996995] BUG: KASAN: out-of-bounds in ismt_access.cold+0x374/0x214b +[ 33.997473] Read of size 18446744073709551615 at addr ffff88810efcfdb1 by task ismt_poc/485 +[ 33.999450] Call Trace: +[ 34.001849] memcpy+0x20/0x60 +[ 34.002077] ismt_access.cold+0x374/0x214b +[ 34.003382] __i2c_smbus_xfer+0x44f/0xfb0 +[ 34.004007] i2c_smbus_xfer+0x10a/0x390 +[ 34.004291] i2cdev_ioctl_smbus+0x2c8/0x710 +[ 34.005196] i2cdev_ioctl+0x5ec/0x74c + +Fix this bug by checking the size of 'data->block[0]' first. + +Fixes: 13f35ac14cd0 ("i2c: Adding support for Intel iSMT SMBus 2.0 host controller") +Signed-off-by: Zheyu Ma +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-ismt.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c +index 483428c5e30b..10cdd501d4c5 100644 +--- a/drivers/i2c/busses/i2c-ismt.c ++++ b/drivers/i2c/busses/i2c-ismt.c +@@ -509,6 +509,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, + if (read_write == I2C_SMBUS_WRITE) { + /* Block Write */ + dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA: WRITE\n"); ++ if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) ++ return -EINVAL; ++ + dma_size = data->block[0] + 1; + dma_direction = DMA_TO_DEVICE; + desc->wr_len_cmd = dma_size; +-- +2.35.1 + diff --git a/queue-5.15/i2c-mux-reg-check-return-value-after-calling-platfor.patch b/queue-5.15/i2c-mux-reg-check-return-value-after-calling-platfor.patch new file mode 100644 index 00000000000..2b5a9cc0599 --- /dev/null +++ b/queue-5.15/i2c-mux-reg-check-return-value-after-calling-platfor.patch @@ -0,0 +1,46 @@ +From 9cbbc81e7e691c4fad58a65354066b6af6abf0d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Oct 2022 17:38:25 +0800 +Subject: i2c: mux: reg: check return value after calling + platform_get_resource() + +From: Yang Yingliang + +[ Upstream commit 2d47b79d2bd39cc6369eccf94a06568d84c906ae ] + +It will cause null-ptr-deref in resource_size(), if platform_get_resource() +returns NULL, move calling resource_size() after devm_ioremap_resource() that +will check 'res' to avoid null-ptr-deref. +And use devm_platform_get_and_ioremap_resource() to simplify code. + +Fixes: b3fdd32799d8 ("i2c: mux: Add register-based mux i2c-mux-reg") +Signed-off-by: Yang Yingliang +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/muxes/i2c-mux-reg.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c +index 0e0679f65cf7..30a6de1694e0 100644 +--- a/drivers/i2c/muxes/i2c-mux-reg.c ++++ b/drivers/i2c/muxes/i2c-mux-reg.c +@@ -183,13 +183,12 @@ static int i2c_mux_reg_probe(struct platform_device *pdev) + if (!mux->data.reg) { + dev_info(&pdev->dev, + "Register not set, using platform resource\n"); +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- mux->data.reg_size = resource_size(res); +- mux->data.reg = devm_ioremap_resource(&pdev->dev, res); ++ mux->data.reg = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(mux->data.reg)) { + ret = PTR_ERR(mux->data.reg); + goto err_put_parent; + } ++ mux->data.reg_size = resource_size(res); + } + + if (mux->data.reg_size != 4 && mux->data.reg_size != 2 && +-- +2.35.1 + diff --git a/queue-5.15/i2c-pxa-pci-fix-missing-pci_disable_device-on-error-.patch b/queue-5.15/i2c-pxa-pci-fix-missing-pci_disable_device-on-error-.patch new file mode 100644 index 00000000000..6350c9fa8d9 --- /dev/null +++ b/queue-5.15/i2c-pxa-pci-fix-missing-pci_disable_device-on-error-.patch @@ -0,0 +1,58 @@ +From df6fad822cfda06efff1878ee1b5b6ffbcdd43e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 17:25:40 +0800 +Subject: i2c: pxa-pci: fix missing pci_disable_device() on error in + ce4100_i2c_probe + +From: Hui Tang + +[ Upstream commit d78a167332e1ca8113268ed922c1212fd71b73ad ] + +Using pcim_enable_device() to avoid missing pci_disable_device(). + +Fixes: 7e94dd154e93 ("i2c-pxa2xx: Add PCI support for PXA I2C controller") +Signed-off-by: Hui Tang +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-pxa-pci.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c +index f614cade432b..30e38bc8b6db 100644 +--- a/drivers/i2c/busses/i2c-pxa-pci.c ++++ b/drivers/i2c/busses/i2c-pxa-pci.c +@@ -105,7 +105,7 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + int i; + struct ce4100_devices *sds; + +- ret = pci_enable_device_mem(dev); ++ ret = pcim_enable_device(dev); + if (ret) + return ret; + +@@ -114,10 +114,8 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + return -EINVAL; + } + sds = kzalloc(sizeof(*sds), GFP_KERNEL); +- if (!sds) { +- ret = -ENOMEM; +- goto err_mem; +- } ++ if (!sds) ++ return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { + sds->pdev[i] = add_i2c_device(dev, i); +@@ -133,8 +131,6 @@ static int ce4100_i2c_probe(struct pci_dev *dev, + + err_dev_add: + kfree(sds); +-err_mem: +- pci_disable_device(dev); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/i40e-fix-the-inability-to-attach-xdp-program-on-down.patch b/queue-5.15/i40e-fix-the-inability-to-attach-xdp-program-on-down.patch new file mode 100644 index 00000000000..992e793f431 --- /dev/null +++ b/queue-5.15/i40e-fix-the-inability-to-attach-xdp-program-on-down.patch @@ -0,0 +1,102 @@ +From da705309f8e05c636d52f1f14aef7c36af37771e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 10:54:11 -0800 +Subject: i40e: Fix the inability to attach XDP program on downed interface + +From: Bartosz Staszewski + +[ Upstream commit 0c87b545a2ed5cd8a6318011f1c92b188c2d74bc ] + +Whenever trying to load XDP prog on downed interface, function i40e_xdp +was passing vsi->rx_buf_len field to i40e_xdp_setup() which was equal 0. +i40e_open() calls i40e_vsi_configure_rx() which configures that field, +but that only happens when interface is up. When it is down, i40e_open() +is not being called, thus vsi->rx_buf_len is not set. + +Solution for this is calculate buffer length in newly created +function - i40e_calculate_vsi_rx_buf_len() that return actual buffer +length. Buffer length is being calculated based on the same rules +applied previously in i40e_vsi_configure_rx() function. + +Fixes: 613142b0bb88 ("i40e: Log error for oversized MTU on device") +Fixes: 0c8493d90b6b ("i40e: add XDP support for pass and drop actions") +Signed-off-by: Bartosz Staszewski +Signed-off-by: Mateusz Palczewski +Tested-by: Shwetha Nagaraju +Reviewed-by: Maciej Fijalkowski +Signed-off-by: Tony Nguyen +Reviewed-by: Saeed Mahameed +Link: https://lore.kernel.org/r/20221209185411.2519898-1-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 36 ++++++++++++++------- + 1 file changed, 24 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index ed2c961902b6..c013d86559af 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -3548,6 +3548,24 @@ static int i40e_vsi_configure_tx(struct i40e_vsi *vsi) + return err; + } + ++/** ++ * i40e_calculate_vsi_rx_buf_len - Calculates buffer length ++ * ++ * @vsi: VSI to calculate rx_buf_len from ++ */ ++static u16 i40e_calculate_vsi_rx_buf_len(struct i40e_vsi *vsi) ++{ ++ if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX)) ++ return I40E_RXBUFFER_2048; ++ ++#if (PAGE_SIZE < 8192) ++ if (!I40E_2K_TOO_SMALL_WITH_PADDING && vsi->netdev->mtu <= ETH_DATA_LEN) ++ return I40E_RXBUFFER_1536 - NET_IP_ALIGN; ++#endif ++ ++ return PAGE_SIZE < 8192 ? I40E_RXBUFFER_3072 : I40E_RXBUFFER_2048; ++} ++ + /** + * i40e_vsi_configure_rx - Configure the VSI for Rx + * @vsi: the VSI being configured +@@ -3559,20 +3577,14 @@ static int i40e_vsi_configure_rx(struct i40e_vsi *vsi) + int err = 0; + u16 i; + +- if (!vsi->netdev || (vsi->back->flags & I40E_FLAG_LEGACY_RX)) { +- vsi->max_frame = I40E_MAX_RXBUFFER; +- vsi->rx_buf_len = I40E_RXBUFFER_2048; ++ vsi->max_frame = I40E_MAX_RXBUFFER; ++ vsi->rx_buf_len = i40e_calculate_vsi_rx_buf_len(vsi); ++ + #if (PAGE_SIZE < 8192) +- } else if (!I40E_2K_TOO_SMALL_WITH_PADDING && +- (vsi->netdev->mtu <= ETH_DATA_LEN)) { ++ if (vsi->netdev && !I40E_2K_TOO_SMALL_WITH_PADDING && ++ vsi->netdev->mtu <= ETH_DATA_LEN) + vsi->max_frame = I40E_RXBUFFER_1536 - NET_IP_ALIGN; +- vsi->rx_buf_len = I40E_RXBUFFER_1536 - NET_IP_ALIGN; + #endif +- } else { +- vsi->max_frame = I40E_MAX_RXBUFFER; +- vsi->rx_buf_len = (PAGE_SIZE < 8192) ? I40E_RXBUFFER_3072 : +- I40E_RXBUFFER_2048; +- } + + /* set up individual rings */ + for (i = 0; i < vsi->num_queue_pairs && !err; i++) +@@ -13147,7 +13159,7 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi, struct bpf_prog *prog, + int i; + + /* Don't allow frames that span over multiple buffers */ +- if (frame_size > vsi->rx_buf_len) { ++ if (frame_size > i40e_calculate_vsi_rx_buf_len(vsi)) { + NL_SET_ERR_MSG_MOD(extack, "MTU too large to enable XDP"); + return -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.15/ib-ipoib-fix-queue-count-inconsistency-for-pkey-chil.patch b/queue-5.15/ib-ipoib-fix-queue-count-inconsistency-for-pkey-chil.patch new file mode 100644 index 00000000000..3d06aa97529 --- /dev/null +++ b/queue-5.15/ib-ipoib-fix-queue-count-inconsistency-for-pkey-chil.patch @@ -0,0 +1,61 @@ +From d4645619baf1967fb3e7c1c3b1887bf96dfe1b9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 09:52:54 +0200 +Subject: IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces + +From: Dragos Tatulea + +[ Upstream commit dbc94a0fb81771a38733c0e8f2ea8c4fa6934dc1 ] + +There are 2 ways to create IPoIB PKEY child interfaces: +1) Writing a PKEY to /sys/class/net//create_child. +2) Using netlink with iproute. + +While with sysfs the child interface has the same number of tx and +rx queues as the parent, with netlink there will always be 1 tx +and 1 rx queue for the child interface. That's because the +get_num_tx/rx_queues() netlink ops are missing and the default value +of 1 is taken for the number of queues (in rtnl_create_link()). + +This change adds the get_num_tx/rx_queues() ops which allows for +interfaces with multiple queues to be created over netlink. This +constant only represents the max number of tx and rx queues on that +net device. + +Fixes: 9baa0b036410 ("IB/ipoib: Add rtnl_link_ops support") +Signed-off-by: Dragos Tatulea +Link: https://lore.kernel.org/r/f4a42c8aa43c02d5ae5559a60c3e5e0f18c82531.1670485816.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/ipoib/ipoib_netlink.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +index 5b05cf3837da..28e9b70844e4 100644 +--- a/drivers/infiniband/ulp/ipoib/ipoib_netlink.c ++++ b/drivers/infiniband/ulp/ipoib/ipoib_netlink.c +@@ -42,6 +42,11 @@ static const struct nla_policy ipoib_policy[IFLA_IPOIB_MAX + 1] = { + [IFLA_IPOIB_UMCAST] = { .type = NLA_U16 }, + }; + ++static unsigned int ipoib_get_max_num_queues(void) ++{ ++ return min_t(unsigned int, num_possible_cpus(), 128); ++} ++ + static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev) + { + struct ipoib_dev_priv *priv = ipoib_priv(dev); +@@ -173,6 +178,8 @@ static struct rtnl_link_ops ipoib_link_ops __read_mostly = { + .changelink = ipoib_changelink, + .get_size = ipoib_get_size, + .fill_info = ipoib_fill_info, ++ .get_num_rx_queues = ipoib_get_max_num_queues, ++ .get_num_tx_queues = ipoib_get_max_num_queues, + }; + + struct rtnl_link_ops *ipoib_get_link_ops(void) +-- +2.35.1 + diff --git a/queue-5.15/ib-mad-don-t-call-to-function-that-might-sleep-while.patch b/queue-5.15/ib-mad-don-t-call-to-function-that-might-sleep-while.patch new file mode 100644 index 00000000000..1732d5605e2 --- /dev/null +++ b/queue-5.15/ib-mad-don-t-call-to-function-that-might-sleep-while.patch @@ -0,0 +1,147 @@ +From 6573bd1f34464a686cd794d00a6eace53750c560 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 11:57:17 +0200 +Subject: IB/mad: Don't call to function that might sleep while in atomic + context + +From: Leonid Ravich + +[ Upstream commit 5c20311d76cbaeb7ed2ecf9c8b8322f8fc4a7ae3 ] + +Tracepoints are not allowed to sleep, as such the following splat is +generated due to call to ib_query_pkey() in atomic context. + +WARNING: CPU: 0 PID: 1888000 at kernel/trace/ring_buffer.c:2492 rb_commit+0xc1/0x220 +CPU: 0 PID: 1888000 Comm: kworker/u9:0 Kdump: loaded Tainted: G OE --------- - - 4.18.0-305.3.1.el8.x86_64 #1 + Hardware name: Red Hat KVM, BIOS 1.13.0-2.module_el8.3.0+555+a55c8938 04/01/2014 + Workqueue: ib-comp-unb-wq ib_cq_poll_work [ib_core] + RIP: 0010:rb_commit+0xc1/0x220 + RSP: 0000:ffffa8ac80f9bca0 EFLAGS: 00010202 + RAX: ffff8951c7c01300 RBX: ffff8951c7c14a00 RCX: 0000000000000246 + RDX: ffff8951c707c000 RSI: ffff8951c707c57c RDI: ffff8951c7c14a00 + RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 + R10: ffff8951c7c01300 R11: 0000000000000001 R12: 0000000000000246 + R13: 0000000000000000 R14: ffffffff964c70c0 R15: 0000000000000000 + FS: 0000000000000000(0000) GS:ffff8951fbc00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f20e8f39010 CR3: 000000002ca10005 CR4: 0000000000170ef0 + Call Trace: + ring_buffer_unlock_commit+0x1d/0xa0 + trace_buffer_unlock_commit_regs+0x3b/0x1b0 + trace_event_buffer_commit+0x67/0x1d0 + trace_event_raw_event_ib_mad_recv_done_handler+0x11c/0x160 [ib_core] + ib_mad_recv_done+0x48b/0xc10 [ib_core] + ? trace_event_raw_event_cq_poll+0x6f/0xb0 [ib_core] + __ib_process_cq+0x91/0x1c0 [ib_core] + ib_cq_poll_work+0x26/0x80 [ib_core] + process_one_work+0x1a7/0x360 + ? create_worker+0x1a0/0x1a0 + worker_thread+0x30/0x390 + ? create_worker+0x1a0/0x1a0 + kthread+0x116/0x130 + ? kthread_flush_work_fn+0x10/0x10 + ret_from_fork+0x35/0x40 + ---[ end trace 78ba8509d3830a16 ]--- + +Fixes: 821bf1de45a1 ("IB/MAD: Add recv path trace point") +Signed-off-by: Leonid Ravich +Link: https://lore.kernel.org/r/Y2t5feomyznrVj7V@leonid-Inspiron-3421 +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/mad.c | 5 ----- + include/trace/events/ib_mad.h | 13 ++++--------- + 2 files changed, 4 insertions(+), 14 deletions(-) + +diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c +index 1893aa613ad7..674344eb8e2f 100644 +--- a/drivers/infiniband/core/mad.c ++++ b/drivers/infiniband/core/mad.c +@@ -59,9 +59,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + struct ib_mad_qp_info *qp_info, + struct trace_event_raw_ib_mad_send_template *entry) + { +- u16 pkey; +- struct ib_device *dev = qp_info->port_priv->device; +- u32 pnum = qp_info->port_priv->port_num; + struct ib_ud_wr *wr = &mad_send_wr->send_wr; + struct rdma_ah_attr attr = {}; + +@@ -69,8 +66,6 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr, + + /* These are common */ + entry->sl = attr.sl; +- ib_query_pkey(dev, pnum, wr->pkey_index, &pkey); +- entry->pkey = pkey; + entry->rqpn = wr->remote_qpn; + entry->rqkey = wr->remote_qkey; + entry->dlid = rdma_ah_get_dlid(&attr); +diff --git a/include/trace/events/ib_mad.h b/include/trace/events/ib_mad.h +index 59363a083ecb..d92691c78cff 100644 +--- a/include/trace/events/ib_mad.h ++++ b/include/trace/events/ib_mad.h +@@ -49,7 +49,6 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + __field(int, retries_left) + __field(int, max_retries) + __field(int, retry) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -89,7 +88,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \ + "method 0x%x status 0x%x class_specific 0x%x tid 0x%llx " \ + "attr_id 0x%x attr_mod 0x%x => dlid 0x%08x sl %d "\ +- "pkey 0x%x rpqn 0x%x rqpkey 0x%x", ++ "rpqn 0x%x rqpkey 0x%x", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->agent_priv, be64_to_cpu(__entry->wrtid), + __entry->retries_left, __entry->max_retries, +@@ -100,7 +99,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- be32_to_cpu(__entry->dlid), __entry->sl, __entry->pkey, ++ be32_to_cpu(__entry->dlid), __entry->sl, + __entry->rqpn, __entry->rqkey + ) + ); +@@ -204,7 +203,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __field(u16, wc_status) + __field(u32, slid) + __field(u32, dev_index) +- __field(u16, pkey) + ), + + TP_fast_assign( +@@ -224,9 +222,6 @@ TRACE_EVENT(ib_mad_recv_done_handler, + __entry->slid = wc->slid; + __entry->src_qp = wc->src_qp; + __entry->sl = wc->sl; +- ib_query_pkey(qp_info->port_priv->device, +- qp_info->port_priv->port_num, +- wc->pkey_index, &__entry->pkey); + __entry->wc_status = wc->status; + ), + +@@ -234,7 +229,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + "base_ver 0x%02x class 0x%02x class_ver 0x%02x " \ + "method 0x%02x status 0x%04x class_specific 0x%04x " \ + "tid 0x%016llx attr_id 0x%04x attr_mod 0x%08x " \ +- "slid 0x%08x src QP%d, sl %d pkey 0x%04x", ++ "slid 0x%08x src QP%d, sl %d", + __entry->dev_index, __entry->port_num, __entry->qp_num, + __entry->wc_status, + __entry->length, +@@ -244,7 +239,7 @@ TRACE_EVENT(ib_mad_recv_done_handler, + be16_to_cpu(__entry->class_specific), + be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id), + be32_to_cpu(__entry->attr_mod), +- __entry->slid, __entry->src_qp, __entry->sl, __entry->pkey ++ __entry->slid, __entry->src_qp, __entry->sl + ) + ); + +-- +2.35.1 + diff --git a/queue-5.15/igb-do-not-free-q_vector-unless-new-one-was-allocate.patch b/queue-5.15/igb-do-not-free-q_vector-unless-new-one-was-allocate.patch new file mode 100644 index 00000000000..056ab28d627 --- /dev/null +++ b/queue-5.15/igb-do-not-free-q_vector-unless-new-one-was-allocate.patch @@ -0,0 +1,53 @@ +From 6b17ce03ca631082982f23aee6633b596b8e42e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 02:25:24 -0700 +Subject: igb: Do not free q_vector unless new one was allocated + +From: Kees Cook + +[ Upstream commit 0668716506ca66f90d395f36ccdaebc3e0e84801 ] + +Avoid potential use-after-free condition under memory pressure. If the +kzalloc() fails, q_vector will be freed but left in the original +adapter->q_vector[v_idx] array position. + +Cc: Jesse Brandeburg +Cc: Tony Nguyen +Cc: "David S. Miller" +Cc: Eric Dumazet +Cc: Jakub Kicinski +Cc: Paolo Abeni +Cc: intel-wired-lan@lists.osuosl.org +Cc: netdev@vger.kernel.org +Signed-off-by: Kees Cook +Reviewed-by: Michael J. Ruhl +Reviewed-by: Jacob Keller +Tested-by: Gurucharan (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igb/igb_main.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c +index 70667b46858a..b246ff8b7c20 100644 +--- a/drivers/net/ethernet/intel/igb/igb_main.c ++++ b/drivers/net/ethernet/intel/igb/igb_main.c +@@ -1204,8 +1204,12 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter, + if (!q_vector) { + q_vector = kzalloc(size, GFP_KERNEL); + } else if (size > ksize(q_vector)) { +- kfree_rcu(q_vector, rcu); +- q_vector = kzalloc(size, GFP_KERNEL); ++ struct igb_q_vector *new_q_vector; ++ ++ new_q_vector = kzalloc(size, GFP_KERNEL); ++ if (new_q_vector) ++ kfree_rcu(q_vector, rcu); ++ q_vector = new_q_vector; + } else { + memset(q_vector, 0, size); + } +-- +2.35.1 + diff --git a/queue-5.15/igc-add-checking-for-basetime-less-than-zero.patch b/queue-5.15/igc-add-checking-for-basetime-less-than-zero.patch new file mode 100644 index 00000000000..4a744e1db43 --- /dev/null +++ b/queue-5.15/igc-add-checking-for-basetime-less-than-zero.patch @@ -0,0 +1,39 @@ +From c41705af15901f69bb787d2fbcc18178cb29c3c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:19 +0800 +Subject: igc: Add checking for basetime less than zero + +From: Muhammad Husaini Zulkifli + +[ Upstream commit 3b61764fb49a6e147ac90d71dccdddc9d5508ba1 ] + +Using the tc qdisc command, the user can set basetime to any value. +Checking should be done on the driver's side to prevent registering +basetime values that are less than zero. + +Fixes: ec50a9d437f0 ("igc: Add support for taprio offloading") +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index af55e2f62e47..26dd710fba8f 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -5984,6 +5984,9 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + if (!qopt->enable) + return igc_tsn_clear_schedule(adapter); + ++ if (qopt->base_time < 0) ++ return -ERANGE; ++ + if (adapter->base_time) + return -EALREADY; + +-- +2.35.1 + diff --git a/queue-5.15/igc-allow-basetime-0-enrollment-for-qbv.patch b/queue-5.15/igc-allow-basetime-0-enrollment-for-qbv.patch new file mode 100644 index 00000000000..faf0d203cff --- /dev/null +++ b/queue-5.15/igc-allow-basetime-0-enrollment-for-qbv.patch @@ -0,0 +1,65 @@ +From d9c1c9cdaaadfea017dc0c28ccd3b199c82af112 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:20 +0800 +Subject: igc: allow BaseTime 0 enrollment for Qbv + +From: Tan Tee Min + +[ Upstream commit e17090eb24944fbbe1f24d9f336d7bad4fbe47e8 ] + +Introduce qbv_enable flag in igc_adapter struct to store the Qbv on/off. +So this allow the BaseTime to enroll with zero value. + +Fixes: 61572d5f8f91 ("igc: Simplify TSN flags handling") +Signed-off-by: Muhammad Husaini Zulkifli +Signed-off-by: Tan Tee Min +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc.h | 1 + + drivers/net/ethernet/intel/igc/igc_main.c | 2 ++ + drivers/net/ethernet/intel/igc/igc_tsn.c | 2 +- + 3 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h +index b69373d67e2d..66678cd72a6c 100644 +--- a/drivers/net/ethernet/intel/igc/igc.h ++++ b/drivers/net/ethernet/intel/igc/igc.h +@@ -184,6 +184,7 @@ struct igc_adapter { + + ktime_t base_time; + ktime_t cycle_time; ++ bool qbv_enable; + + /* OS defined structs */ + struct pci_dev *pdev; +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 26dd710fba8f..f06b67ae3602 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -5981,6 +5981,8 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + u32 start_time = 0, end_time = 0; + size_t n; + ++ adapter->qbv_enable = qopt->enable; ++ + if (!qopt->enable) + return igc_tsn_clear_schedule(adapter); + +diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c +index 4a019954cadb..356c7455c5ce 100644 +--- a/drivers/net/ethernet/intel/igc/igc_tsn.c ++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c +@@ -36,7 +36,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter) + { + unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED; + +- if (adapter->base_time) ++ if (adapter->qbv_enable) + new_flags |= IGC_FLAG_TSN_QBV_ENABLED; + + if (is_any_launchtime(adapter)) +-- +2.35.1 + diff --git a/queue-5.15/igc-enhance-qbv-scheduling-by-using-first-flag-bit.patch b/queue-5.15/igc-enhance-qbv-scheduling-by-using-first-flag-bit.patch new file mode 100644 index 00000000000..e1e9977c603 --- /dev/null +++ b/queue-5.15/igc-enhance-qbv-scheduling-by-using-first-flag-bit.patch @@ -0,0 +1,431 @@ +From 01cbd264ed2bba979a71bdcb21a2aaac8545841f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:17 +0800 +Subject: igc: Enhance Qbv scheduling by using first flag bit + +From: Vinicius Costa Gomes + +[ Upstream commit db0b124f02ba68de6517ac303d431af220ccfe9f ] + +The I225 hardware has a limitation that packets can only be scheduled +in the [0, cycle-time] interval. So, scheduling a packet to the start +of the next cycle doesn't usually work. + +To overcome this, we use the Transmit Descriptor first flag to indicates +that a packet should be the first packet (from a queue) in a cycle +according to the section 7.5.2.9.3.4 The First Packet on Each QBV Cycle +in Intel Discrete I225/6 User Manual. + +But this only works if there was any packet from that queue during the +current cycle, to avoid this issue, we issue an empty packet if that's +not the case. Also require one more descriptor to be available, to take +into account the empty packet that might be issued. + +Test Setup: + +Talker: Use l2_tai to generate the launchtime into packet load. + +Listener: Use timedump.c to compute the delta between packet arrival +and LaunchTime packet payload. + +Test Result: + +Before: + +1666000610127300000,1666000610127300096,96,621273 +1666000610127400000,1666000610127400192,192,621274 +1666000610127500000,1666000610127500032,32,621275 +1666000610127600000,1666000610127600128,128,621276 +1666000610127700000,1666000610127700224,224,621277 +1666000610127800000,1666000610127800064,64,621278 +1666000610127900000,1666000610127900160,160,621279 +1666000610128000000,1666000610128000000,0,621280 +1666000610128100000,1666000610128100096,96,621281 +1666000610128200000,1666000610128200192,192,621282 +1666000610128300000,1666000610128300032,32,621283 +1666000610128400000,1666000610128301056,-98944,621284 +1666000610128500000,1666000610128302080,-197920,621285 +1666000610128600000,1666000610128302848,-297152,621286 +1666000610128700000,1666000610128303872,-396128,621287 +1666000610128800000,1666000610128304896,-495104,621288 +1666000610128900000,1666000610128305664,-594336,621289 +1666000610129000000,1666000610128306688,-693312,621290 +1666000610129100000,1666000610128307712,-792288,621291 +1666000610129200000,1666000610128308480,-891520,621292 +1666000610129300000,1666000610128309504,-990496,621293 +1666000610129400000,1666000610128310528,-1089472,621294 +1666000610129500000,1666000610128311296,-1188704,621295 +1666000610129600000,1666000610128312320,-1287680,621296 +1666000610129700000,1666000610128313344,-1386656,621297 +1666000610129800000,1666000610128314112,-1485888,621298 +1666000610129900000,1666000610128315136,-1584864,621299 +1666000610130000000,1666000610128316160,-1683840,621300 +1666000610130100000,1666000610128316928,-1783072,621301 +1666000610130200000,1666000610128317952,-1882048,621302 +1666000610130300000,1666000610128318976,-1981024,621303 +1666000610130400000,1666000610128319744,-2080256,621304 +1666000610130500000,1666000610128320768,-2179232,621305 +1666000610130600000,1666000610128321792,-2278208,621306 +1666000610130700000,1666000610128322816,-2377184,621307 +1666000610130800000,1666000610128323584,-2476416,621308 +1666000610130900000,1666000610128324608,-2575392,621309 +1666000610131000000,1666000610128325632,-2674368,621310 +1666000610131100000,1666000610128326400,-2773600,621311 +1666000610131200000,1666000610128327424,-2872576,621312 +1666000610131300000,1666000610128328448,-2971552,621313 +1666000610131400000,1666000610128329216,-3070784,621314 +1666000610131500000,1666000610131500032,32,621315 +1666000610131600000,1666000610131600128,128,621316 +1666000610131700000,1666000610131700224,224,621317 + +After: + +1666073510646200000,1666073510646200064,64,2676462 +1666073510646300000,1666073510646300160,160,2676463 +1666073510646400000,1666073510646400256,256,2676464 +1666073510646500000,1666073510646500096,96,2676465 +1666073510646600000,1666073510646600192,192,2676466 +1666073510646700000,1666073510646700032,32,2676467 +1666073510646800000,1666073510646800128,128,2676468 +1666073510646900000,1666073510646900224,224,2676469 +1666073510647000000,1666073510647000064,64,2676470 +1666073510647100000,1666073510647100160,160,2676471 +1666073510647200000,1666073510647200256,256,2676472 +1666073510647300000,1666073510647300096,96,2676473 +1666073510647400000,1666073510647400192,192,2676474 +1666073510647500000,1666073510647500032,32,2676475 +1666073510647600000,1666073510647600128,128,2676476 +1666073510647700000,1666073510647700224,224,2676477 +1666073510647800000,1666073510647800064,64,2676478 +1666073510647900000,1666073510647900160,160,2676479 +1666073510648000000,1666073510648000000,0,2676480 +1666073510648100000,1666073510648100096,96,2676481 +1666073510648200000,1666073510648200192,192,2676482 +1666073510648300000,1666073510648300032,32,2676483 +1666073510648400000,1666073510648400128,128,2676484 +1666073510648500000,1666073510648500224,224,2676485 +1666073510648600000,1666073510648600064,64,2676486 +1666073510648700000,1666073510648700160,160,2676487 +1666073510648800000,1666073510648800000,0,2676488 +1666073510648900000,1666073510648900096,96,2676489 +1666073510649000000,1666073510649000192,192,2676490 +1666073510649100000,1666073510649100032,32,2676491 +1666073510649200000,1666073510649200128,128,2676492 +1666073510649300000,1666073510649300224,224,2676493 +1666073510649400000,1666073510649400064,64,2676494 +1666073510649500000,1666073510649500160,160,2676495 +1666073510649600000,1666073510649600000,0,2676496 +1666073510649700000,1666073510649700096,96,2676497 +1666073510649800000,1666073510649800192,192,2676498 +1666073510649900000,1666073510649900032,32,2676499 +1666073510650000000,1666073510650000128,128,2676500 + +Fixes: 82faa9b79950 ("igc: Add support for ETF offloading") +Signed-off-by: Vinicius Costa Gomes +Co-developed-by: Aravindhan Gunasekaran +Signed-off-by: Aravindhan Gunasekaran +Co-developed-by: Muhammad Husaini Zulkifli +Signed-off-by: Muhammad Husaini Zulkifli +Signed-off-by: Malli C +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc.h | 2 + + drivers/net/ethernet/intel/igc/igc_defines.h | 2 + + drivers/net/ethernet/intel/igc/igc_main.c | 176 ++++++++++++++++--- + 3 files changed, 151 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h +index 3e386c38d016..b69373d67e2d 100644 +--- a/drivers/net/ethernet/intel/igc/igc.h ++++ b/drivers/net/ethernet/intel/igc/igc.h +@@ -94,6 +94,8 @@ struct igc_ring { + u8 queue_index; /* logical index of the ring*/ + u8 reg_idx; /* physical index of the ring */ + bool launchtime_enable; /* true if LaunchTime is enabled */ ++ ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */ ++ ktime_t last_ff_cycle; /* Last cycle with an active first flag */ + + u32 start_time; + u32 end_time; +diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h +index a4bbee748798..f171bc99e58c 100644 +--- a/drivers/net/ethernet/intel/igc/igc_defines.h ++++ b/drivers/net/ethernet/intel/igc/igc_defines.h +@@ -324,6 +324,8 @@ + #define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ + #define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + ++#define IGC_ADVTXD_TSN_CNTX_FIRST 0x00000080 ++ + /* Transmit Control */ + #define IGC_TCTL_EN 0x00000002 /* enable Tx */ + #define IGC_TCTL_PSP 0x00000008 /* pad short packets */ +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 2a84f57ea68b..af55e2f62e47 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -999,25 +999,118 @@ static int igc_write_mc_addr_list(struct net_device *netdev) + return netdev_mc_count(netdev); + } + +-static __le32 igc_tx_launchtime(struct igc_adapter *adapter, ktime_t txtime) ++static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime, ++ bool *first_flag, bool *insert_empty) + { ++ struct igc_adapter *adapter = netdev_priv(ring->netdev); + ktime_t cycle_time = adapter->cycle_time; + ktime_t base_time = adapter->base_time; ++ ktime_t now = ktime_get_clocktai(); ++ ktime_t baset_est, end_of_cycle; + u32 launchtime; ++ s64 n; + +- /* FIXME: when using ETF together with taprio, we may have a +- * case where 'delta' is larger than the cycle_time, this may +- * cause problems if we don't read the current value of +- * IGC_BASET, as the value writen into the launchtime +- * descriptor field may be misinterpreted. ++ n = div64_s64(ktime_sub_ns(now, base_time), cycle_time); ++ ++ baset_est = ktime_add_ns(base_time, cycle_time * (n)); ++ end_of_cycle = ktime_add_ns(baset_est, cycle_time); ++ ++ if (ktime_compare(txtime, end_of_cycle) >= 0) { ++ if (baset_est != ring->last_ff_cycle) { ++ *first_flag = true; ++ ring->last_ff_cycle = baset_est; ++ ++ if (ktime_compare(txtime, ring->last_tx_cycle) > 0) ++ *insert_empty = true; ++ } ++ } ++ ++ /* Introducing a window at end of cycle on which packets ++ * potentially not honor launchtime. Window of 5us chosen ++ * considering software update the tail pointer and packets ++ * are dma'ed to packet buffer. + */ +- div_s64_rem(ktime_sub_ns(txtime, base_time), cycle_time, &launchtime); ++ if ((ktime_sub_ns(end_of_cycle, now) < 5 * NSEC_PER_USEC)) ++ netdev_warn(ring->netdev, "Packet with txtime=%llu may not be honoured\n", ++ txtime); ++ ++ ring->last_tx_cycle = end_of_cycle; ++ ++ launchtime = ktime_sub_ns(txtime, baset_est); ++ if (launchtime > 0) ++ div_s64_rem(launchtime, cycle_time, &launchtime); ++ else ++ launchtime = 0; + + return cpu_to_le32(launchtime); + } + ++static int igc_init_empty_frame(struct igc_ring *ring, ++ struct igc_tx_buffer *buffer, ++ struct sk_buff *skb) ++{ ++ unsigned int size; ++ dma_addr_t dma; ++ ++ size = skb_headlen(skb); ++ ++ dma = dma_map_single(ring->dev, skb->data, size, DMA_TO_DEVICE); ++ if (dma_mapping_error(ring->dev, dma)) { ++ netdev_err_once(ring->netdev, "Failed to map DMA for TX\n"); ++ return -ENOMEM; ++ } ++ ++ buffer->skb = skb; ++ buffer->protocol = 0; ++ buffer->bytecount = skb->len; ++ buffer->gso_segs = 1; ++ buffer->time_stamp = jiffies; ++ dma_unmap_len_set(buffer, len, skb->len); ++ dma_unmap_addr_set(buffer, dma, dma); ++ ++ return 0; ++} ++ ++static int igc_init_tx_empty_descriptor(struct igc_ring *ring, ++ struct sk_buff *skb, ++ struct igc_tx_buffer *first) ++{ ++ union igc_adv_tx_desc *desc; ++ u32 cmd_type, olinfo_status; ++ int err; ++ ++ if (!igc_desc_unused(ring)) ++ return -EBUSY; ++ ++ err = igc_init_empty_frame(ring, first, skb); ++ if (err) ++ return err; ++ ++ cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT | ++ IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD | ++ first->bytecount; ++ olinfo_status = first->bytecount << IGC_ADVTXD_PAYLEN_SHIFT; ++ ++ desc = IGC_TX_DESC(ring, ring->next_to_use); ++ desc->read.cmd_type_len = cpu_to_le32(cmd_type); ++ desc->read.olinfo_status = cpu_to_le32(olinfo_status); ++ desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(first, dma)); ++ ++ netdev_tx_sent_queue(txring_txq(ring), skb->len); ++ ++ first->next_to_watch = desc; ++ ++ ring->next_to_use++; ++ if (ring->next_to_use == ring->count) ++ ring->next_to_use = 0; ++ ++ return 0; ++} ++ ++#define IGC_EMPTY_FRAME_SIZE 60 ++ + static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, +- struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag, + u32 vlan_macip_lens, u32 type_tucmd, + u32 mss_l4len_idx) + { +@@ -1036,26 +1129,17 @@ static void igc_tx_ctxtdesc(struct igc_ring *tx_ring, + if (test_bit(IGC_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) + mss_l4len_idx |= tx_ring->reg_idx << 4; + ++ if (first_flag) ++ mss_l4len_idx |= IGC_ADVTXD_TSN_CNTX_FIRST; ++ + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); +- +- /* We assume there is always a valid Tx time available. Invalid times +- * should have been handled by the upper layers. +- */ +- if (tx_ring->launchtime_enable) { +- struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); +- ktime_t txtime = first->skb->tstamp; +- +- skb_txtime_consumed(first->skb); +- context_desc->launch_time = igc_tx_launchtime(adapter, +- txtime); +- } else { +- context_desc->launch_time = 0; +- } ++ context_desc->launch_time = launch_time; + } + +-static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first) ++static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag) + { + struct sk_buff *skb = first->skb; + u32 vlan_macip_lens = 0; +@@ -1095,7 +1179,8 @@ static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first) + vlan_macip_lens |= skb_network_offset(skb) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + +- igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, type_tucmd, 0); ++ igc_tx_ctxtdesc(tx_ring, launch_time, first_flag, ++ vlan_macip_lens, type_tucmd, 0); + } + + static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) +@@ -1319,6 +1404,7 @@ static int igc_tx_map(struct igc_ring *tx_ring, + + static int igc_tso(struct igc_ring *tx_ring, + struct igc_tx_buffer *first, ++ __le32 launch_time, bool first_flag, + u8 *hdr_len) + { + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; +@@ -1405,8 +1491,8 @@ static int igc_tso(struct igc_ring *tx_ring, + vlan_macip_lens |= (ip.hdr - skb->data) << IGC_ADVTXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & IGC_TX_FLAGS_VLAN_MASK; + +- igc_tx_ctxtdesc(tx_ring, first, vlan_macip_lens, +- type_tucmd, mss_l4len_idx); ++ igc_tx_ctxtdesc(tx_ring, launch_time, first_flag, ++ vlan_macip_lens, type_tucmd, mss_l4len_idx); + + return 1; + } +@@ -1414,11 +1500,14 @@ static int igc_tso(struct igc_ring *tx_ring, + static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + struct igc_ring *tx_ring) + { ++ bool first_flag = false, insert_empty = false; + u16 count = TXD_USE_COUNT(skb_headlen(skb)); + __be16 protocol = vlan_get_protocol(skb); + struct igc_tx_buffer *first; ++ __le32 launch_time = 0; + u32 tx_flags = 0; + unsigned short f; ++ ktime_t txtime; + u8 hdr_len = 0; + int tso = 0; + +@@ -1432,11 +1521,40 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + count += TXD_USE_COUNT(skb_frag_size( + &skb_shinfo(skb)->frags[f])); + +- if (igc_maybe_stop_tx(tx_ring, count + 3)) { ++ if (igc_maybe_stop_tx(tx_ring, count + 5)) { + /* this is a hard error */ + return NETDEV_TX_BUSY; + } + ++ if (!tx_ring->launchtime_enable) ++ goto done; ++ ++ txtime = skb->tstamp; ++ skb->tstamp = ktime_set(0, 0); ++ launch_time = igc_tx_launchtime(tx_ring, txtime, &first_flag, &insert_empty); ++ ++ if (insert_empty) { ++ struct igc_tx_buffer *empty_info; ++ struct sk_buff *empty; ++ void *data; ++ ++ empty_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; ++ empty = alloc_skb(IGC_EMPTY_FRAME_SIZE, GFP_ATOMIC); ++ if (!empty) ++ goto done; ++ ++ data = skb_put(empty, IGC_EMPTY_FRAME_SIZE); ++ memset(data, 0, IGC_EMPTY_FRAME_SIZE); ++ ++ igc_tx_ctxtdesc(tx_ring, 0, false, 0, 0, 0); ++ ++ if (igc_init_tx_empty_descriptor(tx_ring, ++ empty, ++ empty_info) < 0) ++ dev_kfree_skb_any(empty); ++ } ++ ++done: + /* record the location of the first descriptor for this packet */ + first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; + first->type = IGC_TX_BUFFER_TYPE_SKB; +@@ -1473,11 +1591,11 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, + first->tx_flags = tx_flags; + first->protocol = protocol; + +- tso = igc_tso(tx_ring, first, &hdr_len); ++ tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); + if (tso < 0) + goto out_drop; + else if (!tso) +- igc_tx_csum(tx_ring, first); ++ igc_tx_csum(tx_ring, first, launch_time, first_flag); + + igc_tx_map(tx_ring, first, hdr_len); + +-- +2.35.1 + diff --git a/queue-5.15/igc-lift-taprio-schedule-restriction.patch b/queue-5.15/igc-lift-taprio-schedule-restriction.patch new file mode 100644 index 00000000000..7c1498f6f55 --- /dev/null +++ b/queue-5.15/igc-lift-taprio-schedule-restriction.patch @@ -0,0 +1,101 @@ +From cdb7f04810518220b2a5bff8c6c00f5cf918f06f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jun 2022 11:27:47 +0200 +Subject: igc: Lift TAPRIO schedule restriction + +From: Kurt Kanzenbach + +[ Upstream commit a5fd39464a4081ce11c801d7e20c4551ba7cb983 ] + +Add support for Qbv schedules where one queue stays open +in consecutive entries. Currently that's not supported. + +Example schedule: + +|tc qdisc replace dev ${INTERFACE} handle 100 parent root taprio num_tc 3 \ +| map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \ +| queues 1@0 1@1 2@2 \ +| base-time ${BASETIME} \ +| sched-entry S 0x01 300000 \ # Stream High/Low +| sched-entry S 0x06 500000 \ # Management and Best Effort +| sched-entry S 0x04 200000 \ # Best Effort +| flags 0x02 + +Signed-off-by: Kurt Kanzenbach +Reviewed-by: Vinicius Costa Gomes +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Stable-dep-of: 72abeedd8398 ("igc: Set Qbv start_time and end_time to end_time if not being configured in GCL") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index df78aa4fb44b..791f59d09d28 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -5919,9 +5919,10 @@ static bool validate_schedule(struct igc_adapter *adapter, + return false; + + for (n = 0; n < qopt->num_entries; n++) { +- const struct tc_taprio_sched_entry *e; ++ const struct tc_taprio_sched_entry *e, *prev; + int i; + ++ prev = n ? &qopt->entries[n - 1] : NULL; + e = &qopt->entries[n]; + + /* i225 only supports "global" frame preemption +@@ -5934,7 +5935,12 @@ static bool validate_schedule(struct igc_adapter *adapter, + if (e->gate_mask & BIT(i)) + queue_uses[i]++; + +- if (queue_uses[i] > 1) ++ /* There are limitations: A single queue cannot be ++ * opened and closed multiple times per cycle unless the ++ * gate stays open. Check for it. ++ */ ++ if (queue_uses[i] > 1 && ++ !(prev->gate_mask & BIT(i))) + return false; + } + } +@@ -5978,6 +5984,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) + static int igc_save_qbv_schedule(struct igc_adapter *adapter, + struct tc_taprio_qopt_offload *qopt) + { ++ bool queue_configured[IGC_MAX_TX_QUEUES] = { }; + u32 start_time = 0, end_time = 0; + size_t n; + +@@ -5998,9 +6005,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + adapter->cycle_time = qopt->cycle_time; + adapter->base_time = qopt->base_time; + +- /* FIXME: be a little smarter about cases when the gate for a +- * queue stays open for more than one entry. +- */ + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; + int i; +@@ -6028,8 +6032,15 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + if (!(e->gate_mask & BIT(i))) + continue; + +- ring->start_time = start_time; ++ /* Check whether a queue stays open for more than one ++ * entry. If so, keep the start and advance the end ++ * time. ++ */ ++ if (!queue_configured[i]) ++ ring->start_time = start_time; + ring->end_time = end_time; ++ ++ queue_configured[i] = true; + } + + start_time += e->interval; +-- +2.35.1 + diff --git a/queue-5.15/igc-recalculate-qbv-end_time-by-considering-cycle-ti.patch b/queue-5.15/igc-recalculate-qbv-end_time-by-considering-cycle-ti.patch new file mode 100644 index 00000000000..f19b005e59b --- /dev/null +++ b/queue-5.15/igc-recalculate-qbv-end_time-by-considering-cycle-ti.patch @@ -0,0 +1,57 @@ +From b82411280b20780ef1ffb60395f1045884e62718 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:21 +0800 +Subject: igc: recalculate Qbv end_time by considering cycle time + +From: Tan Tee Min + +[ Upstream commit 6d05251d537a4d3835959a8cdd8cbbbdcdc0c904 ] + +Qbv users can specify a cycle time that is not equal to the total GCL +intervals. Hence, recalculation is necessary here to exclude the time +interval that exceeds the cycle time. As those GCL which exceeds the +cycle time will be truncated. + +According to IEEE Std. 802.1Q-2018 section 8.6.9.2, once the end of +the list is reached, it will switch to the END_OF_CYCLE state and +leave the gates in the same state until the next cycle is started. + +Fixes: ec50a9d437f0 ("igc: Add support for taprio offloading") +Signed-off-by: Tan Tee Min +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index f06b67ae3602..df78aa4fb44b 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -6007,6 +6007,21 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + + end_time += e->interval; + ++ /* If any of the conditions below are true, we need to manually ++ * control the end time of the cycle. ++ * 1. Qbv users can specify a cycle time that is not equal ++ * to the total GCL intervals. Hence, recalculation is ++ * necessary here to exclude the time interval that ++ * exceeds the cycle time. ++ * 2. According to IEEE Std. 802.1Q-2018 section 8.6.9.2, ++ * once the end of the list is reached, it will switch ++ * to the END_OF_CYCLE state and leave the gates in the ++ * same state until the next cycle is started. ++ */ ++ if (end_time > adapter->cycle_time || ++ n + 1 == qopt->num_entries) ++ end_time = adapter->cycle_time; ++ + for (i = 0; i < adapter->num_tx_queues; i++) { + struct igc_ring *ring = adapter->tx_ring[i]; + +-- +2.35.1 + diff --git a/queue-5.15/igc-set-qbv-start_time-and-end_time-to-end_time-if-n.patch b/queue-5.15/igc-set-qbv-start_time-and-end_time-to-end_time-if-n.patch new file mode 100644 index 00000000000..656e3ddfb7a --- /dev/null +++ b/queue-5.15/igc-set-qbv-start_time-and-end_time-to-end_time-if-n.patch @@ -0,0 +1,70 @@ +From 6b6875402710d6a51d14dbb9860badbdebe045ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:22 +0800 +Subject: igc: Set Qbv start_time and end_time to end_time if not being + configured in GCL + +From: Tan Tee Min + +[ Upstream commit 72abeedd83982c1bc6023f631e412db78374d9b4 ] + +The default setting of end_time minus start_time is whole 1 second. +Thus, if it's not being configured in any GCL entry then it will be +staying at original 1 second. + +This patch is changing the start_time and end_time to be end_time as +if setting zero will be having weird HW behavior where the gate will +not be fully closed. + +Fixes: ec50a9d437f0 ("igc: Add support for taprio offloading") +Signed-off-by: Tan Tee Min +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_main.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c +index 791f59d09d28..3726c8413c74 100644 +--- a/drivers/net/ethernet/intel/igc/igc_main.c ++++ b/drivers/net/ethernet/intel/igc/igc_main.c +@@ -5987,6 +5987,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + bool queue_configured[IGC_MAX_TX_QUEUES] = { }; + u32 start_time = 0, end_time = 0; + size_t n; ++ int i; + + adapter->qbv_enable = qopt->enable; + +@@ -6007,7 +6008,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + + for (n = 0; n < qopt->num_entries; n++) { + struct tc_taprio_sched_entry *e = &qopt->entries[n]; +- int i; + + end_time += e->interval; + +@@ -6046,6 +6046,18 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, + start_time += e->interval; + } + ++ /* Check whether a queue gets configured. ++ * If not, set the start and end time to be end time. ++ */ ++ for (i = 0; i < adapter->num_tx_queues; i++) { ++ if (!queue_configured[i]) { ++ struct igc_ring *ring = adapter->tx_ring[i]; ++ ++ ring->start_time = end_time; ++ ring->end_time = end_time; ++ } ++ } ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/igc-use-strict-cycles-for-qbv-scheduling.patch b/queue-5.15/igc-use-strict-cycles-for-qbv-scheduling.patch new file mode 100644 index 00000000000..2eee7a542e9 --- /dev/null +++ b/queue-5.15/igc-use-strict-cycles-for-qbv-scheduling.patch @@ -0,0 +1,52 @@ +From 8363e2f8ad05961a683770e161780bda0a0aecfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 12:15:18 +0800 +Subject: igc: Use strict cycles for Qbv scheduling + +From: Vinicius Costa Gomes + +[ Upstream commit d8f45be01dd9381065a3778a579385249ed011dc ] + +Configuring strict cycle mode in the controller forces more well +behaved transmissions when taprio is offloaded. + +When set this strict_cycle and strict_end, transmission is not +enabled if the whole packet cannot be completed before end of +the Qbv cycle. + +Fixes: 82faa9b79950 ("igc: Add support for ETF offloading") +Signed-off-by: Vinicius Costa Gomes +Signed-off-by: Aravindhan Gunasekaran +Signed-off-by: Muhammad Husaini Zulkifli +Tested-by: Naama Meir +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/igc/igc_tsn.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c +index 0fce22de2ab8..4a019954cadb 100644 +--- a/drivers/net/ethernet/intel/igc/igc_tsn.c ++++ b/drivers/net/ethernet/intel/igc/igc_tsn.c +@@ -110,15 +110,8 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter) + wr32(IGC_STQT(i), ring->start_time); + wr32(IGC_ENDQT(i), ring->end_time); + +- if (adapter->base_time) { +- /* If we have a base_time we are in "taprio" +- * mode and we need to be strict about the +- * cycles: only transmit a packet if it can be +- * completed during that cycle. +- */ +- txqctl |= IGC_TXQCTL_STRICT_CYCLE | +- IGC_TXQCTL_STRICT_END; +- } ++ txqctl |= IGC_TXQCTL_STRICT_CYCLE | ++ IGC_TXQCTL_STRICT_END; + + if (ring->launchtime_enable) + txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT; +-- +2.35.1 + diff --git a/queue-5.15/iio-adis-add-__adis_enable_irq-implementation.patch b/queue-5.15/iio-adis-add-__adis_enable_irq-implementation.patch new file mode 100644 index 00000000000..f1b179580ef --- /dev/null +++ b/queue-5.15/iio-adis-add-__adis_enable_irq-implementation.patch @@ -0,0 +1,139 @@ +From 44ff8bf1390a7d8184673e96ec0c6e6fe4092c1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 10:27:49 +0200 +Subject: iio: adis: add '__adis_enable_irq()' implementation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ramona Bolboaca + +[ Upstream commit 99c05e4283a19a02a256f14100ca4ec3b2da3f62 ] + +Add '__adis_enable_irq()' implementation which is the unlocked +version of 'adis_enable_irq()'. +Call '__adis_enable_irq()' instead of 'adis_enable_irq()' from +'__adis_intial_startup()' to keep the expected unlocked functionality. + +This fix is needed to remove a deadlock for all devices which are +using 'adis_initial_startup()'. The deadlock occurs because the +same mutex is acquired twice, without releasing it. +The mutex is acquired once inside 'adis_initial_startup()', before +calling '__adis_initial_startup()', and once inside +'adis_enable_irq()', which is called by '__adis_initial_startup()'. +The deadlock is removed by calling '__adis_enable_irq()', instead of +'adis_enable_irq()' from within '__adis_initial_startup()'. + +Fixes: b600bd7eb3335 ("iio: adis: do not disabe IRQs in 'adis_init()'") +Signed-off-by: Ramona Bolboaca +Reviewed-by: Nuno Sá +Link: https://lore.kernel.org/r/20221122082757.449452-2-ramona.bolboaca@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/adis.c | 28 ++++++++++------------------ + include/linux/iio/imu/adis.h | 13 ++++++++++++- + 2 files changed, 22 insertions(+), 19 deletions(-) + +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index f7fcfd04f659..bc40240b29e2 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -270,23 +270,19 @@ EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB); + #endif + + /** +- * adis_enable_irq() - Enable or disable data ready IRQ ++ * __adis_enable_irq() - Enable or disable data ready IRQ (unlocked) + * @adis: The adis device + * @enable: Whether to enable the IRQ + * + * Returns 0 on success, negative error code otherwise + */ +-int adis_enable_irq(struct adis *adis, bool enable) ++int __adis_enable_irq(struct adis *adis, bool enable) + { +- int ret = 0; ++ int ret; + u16 msc; + +- mutex_lock(&adis->state_lock); +- +- if (adis->data->enable_irq) { +- ret = adis->data->enable_irq(adis, enable); +- goto out_unlock; +- } ++ if (adis->data->enable_irq) ++ return adis->data->enable_irq(adis, enable); + + if (adis->data->unmasked_drdy) { + if (enable) +@@ -294,12 +290,12 @@ int adis_enable_irq(struct adis *adis, bool enable) + else + disable_irq(adis->spi->irq); + +- goto out_unlock; ++ return 0; + } + + ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); + if (ret) +- goto out_unlock; ++ return ret; + + msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; + msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; +@@ -308,13 +304,9 @@ int adis_enable_irq(struct adis *adis, bool enable) + else + msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; + +- ret = __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); +- +-out_unlock: +- mutex_unlock(&adis->state_lock); +- return ret; ++ return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); + } +-EXPORT_SYMBOL_NS(adis_enable_irq, IIO_ADISLIB); ++EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB); + + /** + * __adis_check_status() - Check the device for error conditions (unlocked) +@@ -445,7 +437,7 @@ int __adis_initial_startup(struct adis *adis) + * with 'IRQF_NO_AUTOEN' anyways. + */ + if (!adis->data->unmasked_drdy) +- adis_enable_irq(adis, false); ++ __adis_enable_irq(adis, false); + + if (!adis->data->prod_id_reg) + return 0; +diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h +index 6193f9a6fbc2..8210a9e68215 100644 +--- a/include/linux/iio/imu/adis.h ++++ b/include/linux/iio/imu/adis.h +@@ -406,9 +406,20 @@ static inline int adis_update_bits_base(struct adis *adis, unsigned int reg, + __adis_update_bits_base(adis, reg, mask, val, 2)); \ + }) + +-int adis_enable_irq(struct adis *adis, bool enable); + int __adis_check_status(struct adis *adis); + int __adis_initial_startup(struct adis *adis); ++int __adis_enable_irq(struct adis *adis, bool enable); ++ ++static inline int adis_enable_irq(struct adis *adis, bool enable) ++{ ++ int ret; ++ ++ mutex_lock(&adis->state_lock); ++ ret = __adis_enable_irq(adis, enable); ++ mutex_unlock(&adis->state_lock); ++ ++ return ret; ++} + + static inline int adis_check_status(struct adis *adis) + { +-- +2.35.1 + diff --git a/queue-5.15/iio-adis-handle-devices-that-cannot-unmask-the-drdy-.patch b/queue-5.15/iio-adis-handle-devices-that-cannot-unmask-the-drdy-.patch new file mode 100644 index 00000000000..286b74091b8 --- /dev/null +++ b/queue-5.15/iio-adis-handle-devices-that-cannot-unmask-the-drdy-.patch @@ -0,0 +1,105 @@ +From 6dd6393e890f074e86e2f03c648d9b5fcdf7906f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Sep 2021 16:14:20 +0200 +Subject: iio: adis: handle devices that cannot unmask the drdy pin +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nuno Sá + +[ Upstream commit 31fa357ac809affd9f9a7d0b5d1991951e16beec ] + +Some devices can't mask/unmask the data ready pin and in those cases +each driver was just calling '{dis}enable_irq()' to control the trigger +state. This change, moves that handling into the library by introducing +a new boolean in the data structure that tells the library that the +device cannot unmask the pin. + +On top of controlling the trigger state, we can also use this flag to +automatically request the IRQ with 'IRQF_NO_AUTOEN' in case it is set. +So far, all users of the library want to start operation with IRQs/DRDY +pin disabled so it should be fairly safe to do this inside the library. + +Signed-off-by: Nuno Sá +Link: https://lore.kernel.org/r/20210903141423.517028-3-nuno.sa@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 99c05e4283a1 ("iio: adis: add '__adis_enable_irq()' implementation") +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/adis.c | 15 ++++++++++++++- + drivers/iio/imu/adis_trigger.c | 4 ++++ + include/linux/iio/imu/adis.h | 2 ++ + 3 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index d4e692b187cd..cb0d66bf6561 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -286,6 +286,13 @@ int adis_enable_irq(struct adis *adis, bool enable) + if (adis->data->enable_irq) { + ret = adis->data->enable_irq(adis, enable); + goto out_unlock; ++ } else if (adis->data->unmasked_drdy) { ++ if (enable) ++ enable_irq(adis->spi->irq); ++ else ++ disable_irq(adis->spi->irq); ++ ++ goto out_unlock; + } + + ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); +@@ -430,7 +437,13 @@ int __adis_initial_startup(struct adis *adis) + if (ret) + return ret; + +- adis_enable_irq(adis, false); ++ /* ++ * don't bother calling this if we can't unmask the IRQ as in this case ++ * the IRQ is most likely not yet requested and we will request it ++ * with 'IRQF_NO_AUTOEN' anyways. ++ */ ++ if (!adis->data->unmasked_drdy) ++ adis_enable_irq(adis, false); + + if (!adis->data->prod_id_reg) + return 0; +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index 48eedc29b28a..c461bd1e8e69 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -30,6 +30,10 @@ static const struct iio_trigger_ops adis_trigger_ops = { + static int adis_validate_irq_flag(struct adis *adis) + { + unsigned long direction = adis->irq_flag & IRQF_TRIGGER_MASK; ++ ++ /* We cannot mask the interrupt so ensure it's not enabled at request */ ++ if (adis->data->unmasked_drdy) ++ adis->irq_flag |= IRQF_NO_AUTOEN; + /* + * Typically this devices have data ready either on the rising edge or + * on the falling edge of the data ready pin. This checks enforces that +diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h +index cf49997d5903..7c02f5292eea 100644 +--- a/include/linux/iio/imu/adis.h ++++ b/include/linux/iio/imu/adis.h +@@ -49,6 +49,7 @@ struct adis_timeout { + * @status_error_mask: Bitmask of errors supported by the device + * @timeouts: Chip specific delays + * @enable_irq: Hook for ADIS devices that have a special IRQ enable/disable ++ * @unmasked_drdy: True for devices that cannot mask/unmask the data ready pin + * @has_paging: True if ADIS device has paged registers + * @burst_reg_cmd: Register command that triggers burst + * @burst_len: Burst size in the SPI RX buffer. If @burst_max_len is defined, +@@ -78,6 +79,7 @@ struct adis_data { + unsigned int status_error_mask; + + int (*enable_irq)(struct adis *adis, bool enable); ++ bool unmasked_drdy; + + bool has_paging; + +-- +2.35.1 + diff --git a/queue-5.15/iio-adis-stylistic-changes.patch b/queue-5.15/iio-adis-stylistic-changes.patch new file mode 100644 index 00000000000..cc514a39511 --- /dev/null +++ b/queue-5.15/iio-adis-stylistic-changes.patch @@ -0,0 +1,434 @@ +From 6333d9c049ccb2354b8302734a46c8ff3a162c09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Jan 2022 14:09:05 +0100 +Subject: iio: adis: stylistic changes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nuno Sá + +[ Upstream commit c39010ea6ba13bdf0003bd353e1d4c663aaac0a8 ] + +Minor stylistic changes to address checkptach complains when called with +'--strict'. + +Signed-off-by: Nuno Sá +Link: https://lore.kernel.org/r/20220122130905.99-3-nuno.sa@analog.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 99c05e4283a1 ("iio: adis: add '__adis_enable_irq()' implementation") +Signed-off-by: Sasha Levin +--- + drivers/iio/imu/adis.c | 47 +++++++++++++++++---------------- + drivers/iio/imu/adis_buffer.c | 6 ++--- + drivers/iio/imu/adis_trigger.c | 3 +-- + include/linux/iio/imu/adis.h | 48 ++++++++++++++++++---------------- + 4 files changed, 54 insertions(+), 50 deletions(-) + +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index cb0d66bf6561..638957001653 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -30,8 +30,8 @@ + * @value: The value to write to device (up to 4 bytes) + * @size: The size of the @value (in bytes) + */ +-int __adis_write_reg(struct adis *adis, unsigned int reg, +- unsigned int value, unsigned int size) ++int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, ++ unsigned int size) + { + unsigned int page = reg / ADIS_PAGE_SIZE; + int ret, i; +@@ -114,7 +114,7 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, + ret = spi_sync(adis->spi, &msg); + if (ret) { + dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n", +- reg, ret); ++ reg, ret); + } else { + adis->current_page = page; + } +@@ -130,8 +130,8 @@ EXPORT_SYMBOL_GPL(__adis_write_reg); + * @val: The value read back from the device + * @size: The size of the @val buffer + */ +-int __adis_read_reg(struct adis *adis, unsigned int reg, +- unsigned int *val, unsigned int size) ++int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, ++ unsigned int size) + { + unsigned int page = reg / ADIS_PAGE_SIZE; + struct spi_message msg; +@@ -201,12 +201,12 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, + ret = spi_sync(adis->spi, &msg); + if (ret) { + dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", +- reg, ret); ++ reg, ret); + return ret; +- } else { +- adis->current_page = page; + } + ++ adis->current_page = page; ++ + switch (size) { + case 4: + *val = get_unaligned_be32(adis->rx); +@@ -247,13 +247,13 @@ EXPORT_SYMBOL_GPL(__adis_update_bits_base); + + #ifdef CONFIG_DEBUG_FS + +-int adis_debugfs_reg_access(struct iio_dev *indio_dev, +- unsigned int reg, unsigned int writeval, unsigned int *readval) ++int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg, ++ unsigned int writeval, unsigned int *readval) + { + struct adis *adis = iio_device_get_drvdata(indio_dev); + + if (readval) { +- uint16_t val16; ++ u16 val16; + int ret; + + ret = adis_read_reg_16(adis, reg, &val16); +@@ -261,9 +261,9 @@ int adis_debugfs_reg_access(struct iio_dev *indio_dev, + *readval = val16; + + return ret; +- } else { +- return adis_write_reg_16(adis, reg, writeval); + } ++ ++ return adis_write_reg_16(adis, reg, writeval); + } + EXPORT_SYMBOL(adis_debugfs_reg_access); + +@@ -279,14 +279,16 @@ EXPORT_SYMBOL(adis_debugfs_reg_access); + int adis_enable_irq(struct adis *adis, bool enable) + { + int ret = 0; +- uint16_t msc; ++ u16 msc; + + mutex_lock(&adis->state_lock); + + if (adis->data->enable_irq) { + ret = adis->data->enable_irq(adis, enable); + goto out_unlock; +- } else if (adis->data->unmasked_drdy) { ++ } ++ ++ if (adis->data->unmasked_drdy) { + if (enable) + enable_irq(adis->spi->irq); + else +@@ -322,7 +324,7 @@ EXPORT_SYMBOL(adis_enable_irq); + */ + int __adis_check_status(struct adis *adis) + { +- uint16_t status; ++ u16 status; + int ret; + int i; + +@@ -358,7 +360,7 @@ int __adis_reset(struct adis *adis) + const struct adis_timeout *timeouts = adis->data->timeouts; + + ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, +- ADIS_GLOB_CMD_SW_RESET); ++ ADIS_GLOB_CMD_SW_RESET); + if (ret) { + dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); + return ret; +@@ -414,7 +416,7 @@ int __adis_initial_startup(struct adis *adis) + { + const struct adis_timeout *timeouts = adis->data->timeouts; + struct gpio_desc *gpio; +- uint16_t prod_id; ++ u16 prod_id; + int ret; + + /* check if the device has rst pin low */ +@@ -423,7 +425,7 @@ int __adis_initial_startup(struct adis *adis) + return PTR_ERR(gpio); + + if (gpio) { +- msleep(10); ++ usleep_range(10, 12); + /* bring device out of reset */ + gpiod_set_value_cansleep(gpio, 0); + msleep(timeouts->reset_ms); +@@ -477,7 +479,8 @@ EXPORT_SYMBOL_GPL(__adis_initial_startup); + * a error bit in the channels raw value set error_mask to 0. + */ + int adis_single_conversion(struct iio_dev *indio_dev, +- const struct iio_chan_spec *chan, unsigned int error_mask, int *val) ++ const struct iio_chan_spec *chan, ++ unsigned int error_mask, int *val) + { + struct adis *adis = iio_device_get_drvdata(indio_dev); + unsigned int uval; +@@ -486,7 +489,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, + mutex_lock(&adis->state_lock); + + ret = __adis_read_reg(adis, chan->address, &uval, +- chan->scan_type.storagebits / 8); ++ chan->scan_type.storagebits / 8); + if (ret) + goto err_unlock; + +@@ -521,7 +524,7 @@ EXPORT_SYMBOL_GPL(adis_single_conversion); + * called. + */ + int adis_init(struct adis *adis, struct iio_dev *indio_dev, +- struct spi_device *spi, const struct adis_data *data) ++ struct spi_device *spi, const struct adis_data *data) + { + if (!data || !data->timeouts) { + dev_err(&spi->dev, "No config data or timeouts not defined!\n"); +diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c +index 351c303c8a8c..d3527cf5ed37 100644 +--- a/drivers/iio/imu/adis_buffer.c ++++ b/drivers/iio/imu/adis_buffer.c +@@ -20,7 +20,7 @@ + #include + + static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, +- const unsigned long *scan_mask) ++ const unsigned long *scan_mask) + { + struct adis *adis = iio_device_get_drvdata(indio_dev); + unsigned int burst_length, burst_max_length; +@@ -67,7 +67,7 @@ static int adis_update_scan_mode_burst(struct iio_dev *indio_dev, + } + + int adis_update_scan_mode(struct iio_dev *indio_dev, +- const unsigned long *scan_mask) ++ const unsigned long *scan_mask) + { + struct adis *adis = iio_device_get_drvdata(indio_dev); + const struct iio_chan_spec *chan; +@@ -158,7 +158,7 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) + } + + iio_push_to_buffers_with_timestamp(indio_dev, adis->buffer, +- pf->timestamp); ++ pf->timestamp); + + irq_done: + iio_trigger_notify_done(indio_dev->trig); +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index c461bd1e8e69..0e7fb00ba241 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -15,8 +15,7 @@ + #include + #include + +-static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig, +- bool state) ++static int adis_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) + { + struct adis *adis = iio_trigger_get_drvdata(trig); + +diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h +index 7c02f5292eea..6193f9a6fbc2 100644 +--- a/include/linux/iio/imu/adis.h ++++ b/include/linux/iio/imu/adis.h +@@ -32,6 +32,7 @@ struct adis_timeout { + u16 sw_reset_ms; + u16 self_test_ms; + }; ++ + /** + * struct adis_data - ADIS chip variant specific data + * @read_delay: SPI delay for read operations in us +@@ -45,7 +46,7 @@ struct adis_timeout { + * @self_test_mask: Bitmask of supported self-test operations + * @self_test_reg: Register address to request self test command + * @self_test_no_autoclear: True if device's self-test needs clear of ctrl reg +- * @status_error_msgs: Array of error messgaes ++ * @status_error_msgs: Array of error messages + * @status_error_mask: Bitmask of errors supported by the device + * @timeouts: Chip specific delays + * @enable_irq: Hook for ADIS devices that have a special IRQ enable/disable +@@ -130,12 +131,12 @@ struct adis { + unsigned long irq_flag; + void *buffer; + +- uint8_t tx[10] ____cacheline_aligned; +- uint8_t rx[4]; ++ u8 tx[10] ____cacheline_aligned; ++ u8 rx[4]; + }; + + int adis_init(struct adis *adis, struct iio_dev *indio_dev, +- struct spi_device *spi, const struct adis_data *data); ++ struct spi_device *spi, const struct adis_data *data); + int __adis_reset(struct adis *adis); + + /** +@@ -156,9 +157,9 @@ static inline int adis_reset(struct adis *adis) + } + + int __adis_write_reg(struct adis *adis, unsigned int reg, +- unsigned int val, unsigned int size); ++ unsigned int val, unsigned int size); + int __adis_read_reg(struct adis *adis, unsigned int reg, +- unsigned int *val, unsigned int size); ++ unsigned int *val, unsigned int size); + + /** + * __adis_write_reg_8() - Write single byte to a register (unlocked) +@@ -167,7 +168,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, + * @value: The value to write + */ + static inline int __adis_write_reg_8(struct adis *adis, unsigned int reg, +- uint8_t val) ++ u8 val) + { + return __adis_write_reg(adis, reg, val, 1); + } +@@ -179,7 +180,7 @@ static inline int __adis_write_reg_8(struct adis *adis, unsigned int reg, + * @value: Value to be written + */ + static inline int __adis_write_reg_16(struct adis *adis, unsigned int reg, +- uint16_t val) ++ u16 val) + { + return __adis_write_reg(adis, reg, val, 2); + } +@@ -191,7 +192,7 @@ static inline int __adis_write_reg_16(struct adis *adis, unsigned int reg, + * @value: Value to be written + */ + static inline int __adis_write_reg_32(struct adis *adis, unsigned int reg, +- uint32_t val) ++ u32 val) + { + return __adis_write_reg(adis, reg, val, 4); + } +@@ -203,7 +204,7 @@ static inline int __adis_write_reg_32(struct adis *adis, unsigned int reg, + * @val: The value read back from the device + */ + static inline int __adis_read_reg_16(struct adis *adis, unsigned int reg, +- uint16_t *val) ++ u16 *val) + { + unsigned int tmp; + int ret; +@@ -222,7 +223,7 @@ static inline int __adis_read_reg_16(struct adis *adis, unsigned int reg, + * @val: The value read back from the device + */ + static inline int __adis_read_reg_32(struct adis *adis, unsigned int reg, +- uint32_t *val) ++ u32 *val) + { + unsigned int tmp; + int ret; +@@ -242,7 +243,7 @@ static inline int __adis_read_reg_32(struct adis *adis, unsigned int reg, + * @size: The size of the @value (in bytes) + */ + static inline int adis_write_reg(struct adis *adis, unsigned int reg, +- unsigned int val, unsigned int size) ++ unsigned int val, unsigned int size) + { + int ret; + +@@ -261,7 +262,7 @@ static inline int adis_write_reg(struct adis *adis, unsigned int reg, + * @size: The size of the @val buffer + */ + static int adis_read_reg(struct adis *adis, unsigned int reg, +- unsigned int *val, unsigned int size) ++ unsigned int *val, unsigned int size) + { + int ret; + +@@ -279,7 +280,7 @@ static int adis_read_reg(struct adis *adis, unsigned int reg, + * @value: The value to write + */ + static inline int adis_write_reg_8(struct adis *adis, unsigned int reg, +- uint8_t val) ++ u8 val) + { + return adis_write_reg(adis, reg, val, 1); + } +@@ -291,7 +292,7 @@ static inline int adis_write_reg_8(struct adis *adis, unsigned int reg, + * @value: Value to be written + */ + static inline int adis_write_reg_16(struct adis *adis, unsigned int reg, +- uint16_t val) ++ u16 val) + { + return adis_write_reg(adis, reg, val, 2); + } +@@ -303,7 +304,7 @@ static inline int adis_write_reg_16(struct adis *adis, unsigned int reg, + * @value: Value to be written + */ + static inline int adis_write_reg_32(struct adis *adis, unsigned int reg, +- uint32_t val) ++ u32 val) + { + return adis_write_reg(adis, reg, val, 4); + } +@@ -315,7 +316,7 @@ static inline int adis_write_reg_32(struct adis *adis, unsigned int reg, + * @val: The value read back from the device + */ + static inline int adis_read_reg_16(struct adis *adis, unsigned int reg, +- uint16_t *val) ++ u16 *val) + { + unsigned int tmp; + int ret; +@@ -334,7 +335,7 @@ static inline int adis_read_reg_16(struct adis *adis, unsigned int reg, + * @val: The value read back from the device + */ + static inline int adis_read_reg_32(struct adis *adis, unsigned int reg, +- uint32_t *val) ++ u32 *val) + { + unsigned int tmp; + int ret; +@@ -443,8 +444,8 @@ static inline void adis_dev_unlock(struct adis *adis) + } + + int adis_single_conversion(struct iio_dev *indio_dev, +- const struct iio_chan_spec *chan, unsigned int error_mask, +- int *val); ++ const struct iio_chan_spec *chan, ++ unsigned int error_mask, int *val); + + #define ADIS_VOLTAGE_CHAN(addr, si, chan, name, info_all, bits) { \ + .type = IIO_VOLTAGE, \ +@@ -493,7 +494,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, + .modified = 1, \ + .channel2 = IIO_MOD_ ## mod, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ +- info_sep, \ ++ (info_sep), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = info_all, \ + .address = (addr), \ +@@ -527,7 +528,7 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, + int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev); + + int adis_update_scan_mode(struct iio_dev *indio_dev, +- const unsigned long *scan_mask); ++ const unsigned long *scan_mask); + + #else /* CONFIG_IIO_BUFFER */ + +@@ -551,7 +552,8 @@ static inline int devm_adis_probe_trigger(struct adis *adis, + #ifdef CONFIG_DEBUG_FS + + int adis_debugfs_reg_access(struct iio_dev *indio_dev, +- unsigned int reg, unsigned int writeval, unsigned int *readval); ++ unsigned int reg, unsigned int writeval, ++ unsigned int *readval); + + #else + +-- +2.35.1 + diff --git a/queue-5.15/iio-imu-adis-move-exports-into-iio_adislib-namespace.patch b/queue-5.15/iio-imu-adis-move-exports-into-iio_adislib-namespace.patch new file mode 100644 index 00000000000..84dc0a59003 --- /dev/null +++ b/queue-5.15/iio-imu-adis-move-exports-into-iio_adislib-namespace.patch @@ -0,0 +1,254 @@ +From d08fd9df8a02b6b4110f9be35a39c264b6d19c57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 30 Jan 2022 20:56:53 +0000 +Subject: iio:imu:adis: Move exports into IIO_ADISLIB namespace + +From: Jonathan Cameron + +[ Upstream commit 6c9304d6af122f9afea41885ad82ed627e9442a8 ] + +In order to avoid unneessary pollution of the global symbol namespace +move the common/library functions into a specific namespace and import +that into the various specific device drivers that use them. + +Signed-off-by: Jonathan Cameron +Cc: Lars-Peter Clausen +Cc: Song Bao Hua (Barry Song) +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20220130205701.334592-9-jic23@kernel.org +Stable-dep-of: 99c05e4283a1 ("iio: adis: add '__adis_enable_irq()' implementation") +Signed-off-by: Sasha Levin +--- + drivers/iio/accel/adis16201.c | 1 + + drivers/iio/accel/adis16209.c | 1 + + drivers/iio/gyro/adis16136.c | 1 + + drivers/iio/gyro/adis16260.c | 1 + + drivers/iio/imu/adis.c | 20 ++++++++++---------- + drivers/iio/imu/adis16400.c | 1 + + drivers/iio/imu/adis16460.c | 1 + + drivers/iio/imu/adis16475.c | 1 + + drivers/iio/imu/adis16480.c | 1 + + drivers/iio/imu/adis_buffer.c | 4 ++-- + drivers/iio/imu/adis_trigger.c | 2 +- + drivers/staging/iio/accel/adis16203.c | 1 + + drivers/staging/iio/accel/adis16240.c | 1 + + 13 files changed, 23 insertions(+), 13 deletions(-) + +diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c +index 7a434e2884d4..dfb8e2e5bdf5 100644 +--- a/drivers/iio/accel/adis16201.c ++++ b/drivers/iio/accel/adis16201.c +@@ -300,3 +300,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); + MODULE_DESCRIPTION("Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer"); + MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("spi:adis16201"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c +index ac08e866d612..5a9c6e2296f1 100644 +--- a/drivers/iio/accel/adis16209.c ++++ b/drivers/iio/accel/adis16209.c +@@ -310,3 +310,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); + MODULE_DESCRIPTION("Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer"); + MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("spi:adis16209"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c +index 36879f01e28c..71295709f2b9 100644 +--- a/drivers/iio/gyro/adis16136.c ++++ b/drivers/iio/gyro/adis16136.c +@@ -591,3 +591,4 @@ module_spi_driver(adis16136_driver); + MODULE_AUTHOR("Lars-Peter Clausen "); + MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c +index 66b6b7bd5e1b..eaf57bd339ed 100644 +--- a/drivers/iio/gyro/adis16260.c ++++ b/drivers/iio/gyro/adis16260.c +@@ -433,3 +433,4 @@ module_spi_driver(adis16260_driver); + MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); + MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor"); + MODULE_LICENSE("GPL v2"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c +index 638957001653..f7fcfd04f659 100644 +--- a/drivers/iio/imu/adis.c ++++ b/drivers/iio/imu/adis.c +@@ -121,7 +121,7 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value, + + return ret; + } +-EXPORT_SYMBOL_GPL(__adis_write_reg); ++EXPORT_SYMBOL_NS_GPL(__adis_write_reg, IIO_ADISLIB); + + /** + * __adis_read_reg() - read N bytes from register (unlocked version) +@@ -218,7 +218,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, + + return ret; + } +-EXPORT_SYMBOL_GPL(__adis_read_reg); ++EXPORT_SYMBOL_NS_GPL(__adis_read_reg, IIO_ADISLIB); + /** + * __adis_update_bits_base() - ADIS Update bits function - Unlocked version + * @adis: The adis device +@@ -243,7 +243,7 @@ int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, + + return __adis_write_reg(adis, reg, __val, size); + } +-EXPORT_SYMBOL_GPL(__adis_update_bits_base); ++EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB); + + #ifdef CONFIG_DEBUG_FS + +@@ -265,7 +265,7 @@ int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg, + + return adis_write_reg_16(adis, reg, writeval); + } +-EXPORT_SYMBOL(adis_debugfs_reg_access); ++EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB); + + #endif + +@@ -314,7 +314,7 @@ int adis_enable_irq(struct adis *adis, bool enable) + mutex_unlock(&adis->state_lock); + return ret; + } +-EXPORT_SYMBOL(adis_enable_irq); ++EXPORT_SYMBOL_NS(adis_enable_irq, IIO_ADISLIB); + + /** + * __adis_check_status() - Check the device for error conditions (unlocked) +@@ -346,7 +346,7 @@ int __adis_check_status(struct adis *adis) + + return -EIO; + } +-EXPORT_SYMBOL_GPL(__adis_check_status); ++EXPORT_SYMBOL_NS_GPL(__adis_check_status, IIO_ADISLIB); + + /** + * __adis_reset() - Reset the device (unlocked version) +@@ -370,7 +370,7 @@ int __adis_reset(struct adis *adis) + + return 0; + } +-EXPORT_SYMBOL_GPL(__adis_reset); ++EXPORT_SYMBOL_NS_GPL(__adis_reset, IIO_ADIS_LIB); + + static int adis_self_test(struct adis *adis) + { +@@ -461,7 +461,7 @@ int __adis_initial_startup(struct adis *adis) + + return 0; + } +-EXPORT_SYMBOL_GPL(__adis_initial_startup); ++EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, IIO_ADISLIB); + + /** + * adis_single_conversion() - Performs a single sample conversion +@@ -509,7 +509,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, + mutex_unlock(&adis->state_lock); + return ret; + } +-EXPORT_SYMBOL_GPL(adis_single_conversion); ++EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB); + + /** + * adis_init() - Initialize adis device structure +@@ -546,7 +546,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, + + return 0; + } +-EXPORT_SYMBOL_GPL(adis_init); ++EXPORT_SYMBOL_NS_GPL(adis_init, IIO_ADISLIB); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Lars-Peter Clausen "); +diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c +index b12917a7cb60..9bcd9a9261b9 100644 +--- a/drivers/iio/imu/adis16400.c ++++ b/drivers/iio/imu/adis16400.c +@@ -1230,3 +1230,4 @@ module_spi_driver(adis16400_driver); + MODULE_AUTHOR("Manuel Stahl "); + MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c +index a6f9fba3e03f..40fc0e582a9f 100644 +--- a/drivers/iio/imu/adis16460.c ++++ b/drivers/iio/imu/adis16460.c +@@ -444,3 +444,4 @@ module_spi_driver(adis16460_driver); + MODULE_AUTHOR("Dragos Bogdan "); + MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver"); + MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c +index 287fff39a927..9d28534db3b0 100644 +--- a/drivers/iio/imu/adis16475.c ++++ b/drivers/iio/imu/adis16475.c +@@ -1382,3 +1382,4 @@ module_spi_driver(adis16475_driver); + MODULE_AUTHOR("Nuno Sa "); + MODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver"); + MODULE_LICENSE("GPL"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c +index f9b4540db1f4..44bbe3d19907 100644 +--- a/drivers/iio/imu/adis16480.c ++++ b/drivers/iio/imu/adis16480.c +@@ -1538,3 +1538,4 @@ module_spi_driver(adis16480_driver); + MODULE_AUTHOR("Lars-Peter Clausen "); + MODULE_DESCRIPTION("Analog Devices ADIS16480 IMU driver"); + MODULE_LICENSE("GPL v2"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c +index d3527cf5ed37..928933027ae3 100644 +--- a/drivers/iio/imu/adis_buffer.c ++++ b/drivers/iio/imu/adis_buffer.c +@@ -124,7 +124,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev, + + return 0; + } +-EXPORT_SYMBOL_GPL(adis_update_scan_mode); ++EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode, IIO_ADISLIB); + + static irqreturn_t adis_trigger_handler(int irq, void *p) + { +@@ -212,5 +212,5 @@ devm_adis_setup_buffer_and_trigger(struct adis *adis, struct iio_dev *indio_dev, + return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup, + adis); + } +-EXPORT_SYMBOL_GPL(devm_adis_setup_buffer_and_trigger); ++EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger, IIO_ADISLIB); + +diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c +index 0e7fb00ba241..f890bf842db8 100644 +--- a/drivers/iio/imu/adis_trigger.c ++++ b/drivers/iio/imu/adis_trigger.c +@@ -87,5 +87,5 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev) + + return devm_iio_trigger_register(&adis->spi->dev, adis->trig); + } +-EXPORT_SYMBOL_GPL(devm_adis_probe_trigger); ++EXPORT_SYMBOL_NS_GPL(devm_adis_probe_trigger, IIO_ADISLIB); + +diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c +index 1d3026dae827..62d5397ff1f9 100644 +--- a/drivers/staging/iio/accel/adis16203.c ++++ b/drivers/staging/iio/accel/adis16203.c +@@ -312,3 +312,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); + MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"); + MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("spi:adis16203"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c +index 2a8aa83b8d9e..bca857eef92e 100644 +--- a/drivers/staging/iio/accel/adis16240.c ++++ b/drivers/staging/iio/accel/adis16240.c +@@ -440,3 +440,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); + MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder"); + MODULE_LICENSE("GPL v2"); + MODULE_ALIAS("spi:adis16240"); ++MODULE_IMPORT_NS(IIO_ADISLIB); +-- +2.35.1 + diff --git a/queue-5.15/iio-temperature-ltc2983-make-bulk-write-buffer-dma-s.patch b/queue-5.15/iio-temperature-ltc2983-make-bulk-write-buffer-dma-s.patch new file mode 100644 index 00000000000..022807da6d8 --- /dev/null +++ b/queue-5.15/iio-temperature-ltc2983-make-bulk-write-buffer-dma-s.patch @@ -0,0 +1,61 @@ +From 16d03892d157b7be9edc29c8b19c6863c70766a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 15:00:29 +0200 +Subject: iio: temperature: ltc2983: make bulk write buffer DMA-safe + +From: Cosmin Tanislav + +[ Upstream commit 5e0176213949724fbe9a8e4a39817edce337b8a0 ] + +regmap_bulk_write() does not guarantee implicit DMA-safety, +even though the current implementation duplicates the given +buffer. Do not rely on it. + +Fixes: f110f3188e56 ("iio: temperature: Add support for LTC2983") +Signed-off-by: Cosmin Tanislav +Link: https://lore.kernel.org/r/20221103130041.2153295-2-demonsingur@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/temperature/ltc2983.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/iio/temperature/ltc2983.c b/drivers/iio/temperature/ltc2983.c +index 8306daa77908..b2ae2d2c7eef 100644 +--- a/drivers/iio/temperature/ltc2983.c ++++ b/drivers/iio/temperature/ltc2983.c +@@ -205,6 +205,7 @@ struct ltc2983_data { + * Holds the converted temperature + */ + __be32 temp ____cacheline_aligned; ++ __be32 chan_val; + }; + + struct ltc2983_sensor { +@@ -309,19 +310,18 @@ static int __ltc2983_fault_handler(const struct ltc2983_data *st, + return 0; + } + +-static int __ltc2983_chan_assign_common(const struct ltc2983_data *st, ++static int __ltc2983_chan_assign_common(struct ltc2983_data *st, + const struct ltc2983_sensor *sensor, + u32 chan_val) + { + u32 reg = LTC2983_CHAN_START_ADDR(sensor->chan); +- __be32 __chan_val; + + chan_val |= LTC2983_CHAN_TYPE(sensor->type); + dev_dbg(&st->spi->dev, "Assign reg:0x%04X, val:0x%08X\n", reg, + chan_val); +- __chan_val = cpu_to_be32(chan_val); +- return regmap_bulk_write(st->regmap, reg, &__chan_val, +- sizeof(__chan_val)); ++ st->chan_val = cpu_to_be32(chan_val); ++ return regmap_bulk_write(st->regmap, reg, &st->chan_val, ++ sizeof(st->chan_val)); + } + + static int __ltc2983_chan_custom_sensor_assign(struct ltc2983_data *st, +-- +2.35.1 + diff --git a/queue-5.15/ima-fix-misuse-of-dereference-of-pointer-in-template.patch b/queue-5.15/ima-fix-misuse-of-dereference-of-pointer-in-template.patch new file mode 100644 index 00000000000..c9f448f13f2 --- /dev/null +++ b/queue-5.15/ima-fix-misuse-of-dereference-of-pointer-in-template.patch @@ -0,0 +1,47 @@ +From 078a60017211ac1780977f47357e540a2d5fda4d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 17:27:19 +0800 +Subject: ima: Fix misuse of dereference of pointer in + template_desc_init_fields() + +From: Xiu Jianfeng + +[ Upstream commit 25369175ce84813dd99d6604e710dc2491f68523 ] + +The input parameter @fields is type of struct ima_template_field ***, so +when allocates array memory for @fields, the size of element should be +sizeof(**field) instead of sizeof(*field). + +Actually the original code would not cause any runtime error, but it's +better to make it logically right. + +Fixes: adf53a778a0a ("ima: new templates management mechanism") +Signed-off-by: Xiu Jianfeng +Reviewed-by: Roberto Sassu +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_template.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c +index db1ad6d7a57f..f84a0598e4f6 100644 +--- a/security/integrity/ima/ima_template.c ++++ b/security/integrity/ima/ima_template.c +@@ -241,11 +241,11 @@ int template_desc_init_fields(const char *template_fmt, + } + + if (fields && num_fields) { +- *fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL); ++ *fields = kmalloc_array(i, sizeof(**fields), GFP_KERNEL); + if (*fields == NULL) + return -ENOMEM; + +- memcpy(*fields, found_fields, i * sizeof(*fields)); ++ memcpy(*fields, found_fields, i * sizeof(**fields)); + *num_fields = i; + } + +-- +2.35.1 + diff --git a/queue-5.15/ima-handle-estale-returned-by-ima_filter_rule_match.patch b/queue-5.15/ima-handle-estale-returned-by-ima_filter_rule_match.patch new file mode 100644 index 00000000000..63c6bbf933d --- /dev/null +++ b/queue-5.15/ima-handle-estale-returned-by-ima_filter_rule_match.patch @@ -0,0 +1,114 @@ +From 17bb1d8647c0120d6f55adaa0472481780f5a7ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 20:58:04 +0800 +Subject: ima: Handle -ESTALE returned by ima_filter_rule_match() + +From: GUO Zihua + +[ Upstream commit c7423dbdbc9ecef7fff5239d144cad4b9887f4de ] + +IMA relies on the blocking LSM policy notifier callback to update the +LSM based IMA policy rules. + +When SELinux update its policies, IMA would be notified and starts +updating all its lsm rules one-by-one. During this time, -ESTALE would +be returned by ima_filter_rule_match() if it is called with a LSM rule +that has not yet been updated. In ima_match_rules(), -ESTALE is not +handled, and the LSM rule is considered a match, causing extra files +to be measured by IMA. + +Fix it by re-initializing a temporary rule if -ESTALE is returned by +ima_filter_rule_match(). The origin rule in the rule list would be +updated by the LSM policy notifier callback. + +Fixes: b16942455193 ("ima: use the lsm policy update notifier") +Signed-off-by: GUO Zihua +Reviewed-by: Roberto Sassu +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_policy.c | 41 ++++++++++++++++++++++------- + 1 file changed, 32 insertions(+), 9 deletions(-) + +diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c +index 748b97a2582a..844d69f6ac00 100644 +--- a/security/integrity/ima/ima_policy.c ++++ b/security/integrity/ima/ima_policy.c +@@ -542,6 +542,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + const char *func_data) + { + int i; ++ bool result = false; ++ struct ima_rule_entry *lsm_rule = rule; ++ bool rule_reinitialized = false; + + if ((rule->flags & IMA_FUNC) && + (rule->func != func && func != POST_SETATTR)) +@@ -590,35 +593,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule, + int rc = 0; + u32 osid; + +- if (!rule->lsm[i].rule) { +- if (!rule->lsm[i].args_p) ++ if (!lsm_rule->lsm[i].rule) { ++ if (!lsm_rule->lsm[i].args_p) + continue; + else + return false; + } ++ ++retry: + switch (i) { + case LSM_OBJ_USER: + case LSM_OBJ_ROLE: + case LSM_OBJ_TYPE: + security_inode_getsecid(inode, &osid); +- rc = ima_filter_rule_match(osid, rule->lsm[i].type, ++ rc = ima_filter_rule_match(osid, lsm_rule->lsm[i].type, + Audit_equal, +- rule->lsm[i].rule); ++ lsm_rule->lsm[i].rule); + break; + case LSM_SUBJ_USER: + case LSM_SUBJ_ROLE: + case LSM_SUBJ_TYPE: +- rc = ima_filter_rule_match(secid, rule->lsm[i].type, ++ rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type, + Audit_equal, +- rule->lsm[i].rule); ++ lsm_rule->lsm[i].rule); + break; + default: + break; + } +- if (!rc) +- return false; ++ ++ if (rc == -ESTALE && !rule_reinitialized) { ++ lsm_rule = ima_lsm_copy_rule(rule); ++ if (lsm_rule) { ++ rule_reinitialized = true; ++ goto retry; ++ } ++ } ++ if (!rc) { ++ result = false; ++ goto out; ++ } + } +- return true; ++ result = true; ++ ++out: ++ if (rule_reinitialized) { ++ for (i = 0; i < MAX_LSM_RULES; i++) ++ ima_filter_rule_free(lsm_rule->lsm[i].rule); ++ kfree(lsm_rule); ++ } ++ return result; + } + + /* +-- +2.35.1 + diff --git a/queue-5.15/include-uapi-linux-swab-fix-potentially-missing-__al.patch b/queue-5.15/include-uapi-linux-swab-fix-potentially-missing-__al.patch new file mode 100644 index 00000000000..52dc7030398 --- /dev/null +++ b/queue-5.15/include-uapi-linux-swab-fix-potentially-missing-__al.patch @@ -0,0 +1,64 @@ +From 959a49df456465530f477bb6ec4aeb3f49aedc71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 14:52:56 -0700 +Subject: include/uapi/linux/swab: Fix potentially missing __always_inline +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Matt Redfearn + +[ Upstream commit defbab270d45e32b068e7e73c3567232d745c60f ] + +Commit bc27fb68aaad ("include/uapi/linux/byteorder, swab: force inlining +of some byteswap operations") added __always_inline to swab functions +and commit 283d75737837 ("uapi/linux/stddef.h: Provide __always_inline to +userspace headers") added a definition of __always_inline for use in +exported headers when the kernel's compiler.h is not available. + +However, since swab.h does not include stddef.h, if the header soup does +not indirectly include it, the definition of __always_inline is missing, +resulting in a compilation failure, which was observed compiling the +perf tool using exported headers containing this commit: + +In file included from /usr/include/linux/byteorder/little_endian.h:12:0, + from /usr/include/asm/byteorder.h:14, + from tools/include/uapi/linux/perf_event.h:20, + from perf.h:8, + from builtin-bench.c:18: +/usr/include/linux/swab.h:160:8: error: unknown type name `__always_inline' + static __always_inline __u16 __swab16p(const __u16 *p) + +Fix this by replacing the inclusion of linux/compiler.h with +linux/stddef.h to ensure that we pick up that definition if required, +without relying on it's indirect inclusion. compiler.h is then included +indirectly, via stddef.h. + +Fixes: 283d75737837 ("uapi/linux/stddef.h: Provide __always_inline to userspace headers") +Signed-off-by: Matt Redfearn +Signed-off-by: Florian Fainelli +Signed-off-by: Arnd Bergmann +Tested-by: Nathan Chancellor +Reviewed-by: Petr Vaněk +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + include/uapi/linux/swab.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h +index 7272f85d6d6a..3736f2fe1541 100644 +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -3,7 +3,7 @@ + #define _UAPI_LINUX_SWAB_H + + #include +-#include ++#include + #include + #include + +-- +2.35.1 + diff --git a/queue-5.15/inet-add-read_once-sk-sk_bound_dev_if-in-inet_csk_bi.patch b/queue-5.15/inet-add-read_once-sk-sk_bound_dev_if-in-inet_csk_bi.patch new file mode 100644 index 00000000000..dda3b4fd1d1 --- /dev/null +++ b/queue-5.15/inet-add-read_once-sk-sk_bound_dev_if-in-inet_csk_bi.patch @@ -0,0 +1,45 @@ +From 7cb5d273e2bbc9f2349ca44bb32c7abe76033a98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 May 2022 11:55:46 -0700 +Subject: inet: add READ_ONCE(sk->sk_bound_dev_if) in inet_csk_bind_conflict() + +From: Eric Dumazet + +[ Upstream commit d2c135619cb89d1d5693df81ab408c5e8e97e898 ] + +inet_csk_bind_conflict() can access sk->sk_bound_dev_if for +unlocked sockets. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/inet_connection_sock.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index a53f9bf7886f..8039097546de 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -155,10 +155,14 @@ static int inet_csk_bind_conflict(const struct sock *sk, + */ + + sk_for_each_bound(sk2, &tb->owners) { +- if (sk != sk2 && +- (!sk->sk_bound_dev_if || +- !sk2->sk_bound_dev_if || +- sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { ++ int bound_dev_if2; ++ ++ if (sk == sk2) ++ continue; ++ bound_dev_if2 = READ_ONCE(sk2->sk_bound_dev_if); ++ if ((!sk->sk_bound_dev_if || ++ !bound_dev_if2 || ++ sk->sk_bound_dev_if == bound_dev_if2)) { + if (reuse && sk2->sk_reuse && + sk2->sk_state != TCP_LISTEN) { + if ((!relax || +-- +2.35.1 + diff --git a/queue-5.15/input-elants_i2c-properly-handle-the-reset-gpio-when.patch b/queue-5.15/input-elants_i2c-properly-handle-the-reset-gpio-when.patch new file mode 100644 index 00000000000..ed94d113a2a --- /dev/null +++ b/queue-5.15/input-elants_i2c-properly-handle-the-reset-gpio-when.patch @@ -0,0 +1,90 @@ +From ca1684499b2ed2a9561c9251d82d273ffb5d4fb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 21:49:19 -0800 +Subject: Input: elants_i2c - properly handle the reset GPIO when power is off + +From: Douglas Anderson + +[ Upstream commit a85fbd6498441694475716a4d5c65f9d3e073faf ] + +As can be seen in elants_i2c_power_off(), we want the reset GPIO +asserted when power is off. The reset GPIO is active low so we need +the reset line logic low when power is off to avoid leakage. + +We have a problem, though, at probe time. At probe time we haven't +powered the regulators on yet but we have: + + devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW); + +While that _looks_ right, it turns out that it's not. The +GPIOD_OUT_LOW doesn't mean to init the GPIO to low. It means init the +GPIO to "not asserted". Since this is an active low GPIO that inits it +to be high. + +Let's fix this to properly init the GPIO. Now after both probe and +power off the state of the GPIO is consistent (it's "asserted" or +level low). + +Once we fix this, we can see that at power on time we no longer to +assert the reset GPIO as the first thing. The reset GPIO is _always_ +asserted before powering on. Let's fix powering on to account for +this. + +Fixes: afe10358e47a ("Input: elants_i2c - wire up regulator support") +Signed-off-by: Douglas Anderson +Link: https://lore.kernel.org/r/20221117123805.1.I9959ac561dd6e1e8e1ce7085e4de6167b27c574f@changeid +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/touchscreen/elants_i2c.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c +index b9e2219efbb8..6858a3e20a0c 100644 +--- a/drivers/input/touchscreen/elants_i2c.c ++++ b/drivers/input/touchscreen/elants_i2c.c +@@ -1329,14 +1329,12 @@ static int elants_i2c_power_on(struct elants_data *ts) + if (IS_ERR_OR_NULL(ts->reset_gpio)) + return 0; + +- gpiod_set_value_cansleep(ts->reset_gpio, 1); +- + error = regulator_enable(ts->vcc33); + if (error) { + dev_err(&ts->client->dev, + "failed to enable vcc33 regulator: %d\n", + error); +- goto release_reset_gpio; ++ return error; + } + + error = regulator_enable(ts->vccio); +@@ -1345,7 +1343,7 @@ static int elants_i2c_power_on(struct elants_data *ts) + "failed to enable vccio regulator: %d\n", + error); + regulator_disable(ts->vcc33); +- goto release_reset_gpio; ++ return error; + } + + /* +@@ -1354,7 +1352,6 @@ static int elants_i2c_power_on(struct elants_data *ts) + */ + udelay(ELAN_POWERON_DELAY_USEC); + +-release_reset_gpio: + gpiod_set_value_cansleep(ts->reset_gpio, 0); + if (error) + return error; +@@ -1462,7 +1459,7 @@ static int elants_i2c_probe(struct i2c_client *client) + return error; + } + +- ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW); ++ ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) { + error = PTR_ERR(ts->reset_gpio); + +-- +2.35.1 + diff --git a/queue-5.15/input-joystick-fix-kconfig-warning-for-joystick_adc.patch b/queue-5.15/input-joystick-fix-kconfig-warning-for-joystick_adc.patch new file mode 100644 index 00000000000..899cc6b3a4c --- /dev/null +++ b/queue-5.15/input-joystick-fix-kconfig-warning-for-joystick_adc.patch @@ -0,0 +1,42 @@ +From 5482a87d6b2041678511a4486f715be8e37dabcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 13:12:38 -0700 +Subject: Input: joystick - fix Kconfig warning for JOYSTICK_ADC + +From: Randy Dunlap + +[ Upstream commit 6100a19c4fcfe154dd32f8a8ef4e8c0b1f607c75 ] + +Fix a Kconfig warning for JOYSTICK_ADC by also selecting +IIO_BUFFER. + +WARNING: unmet direct dependencies detected for IIO_BUFFER_CB + Depends on [n]: IIO [=y] && IIO_BUFFER [=n] + Selected by [y]: + - JOYSTICK_ADC [=y] && INPUT [=y] && INPUT_JOYSTICK [=y] && IIO [=y] + +Fixes: 2c2b364fddd5 ("Input: joystick - add ADC attached joystick driver.") +Reported-by: kernel test robot +Signed-off-by: Randy Dunlap +Link: https://lore.kernel.org/r/20221104201238.31628-1-rdunlap@infradead.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/joystick/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig +index 3b23078bc7b5..db4135bbd279 100644 +--- a/drivers/input/joystick/Kconfig ++++ b/drivers/input/joystick/Kconfig +@@ -46,6 +46,7 @@ config JOYSTICK_A3D + config JOYSTICK_ADC + tristate "Simple joystick connected over ADC" + depends on IIO ++ select IIO_BUFFER + select IIO_BUFFER_CB + help + Say Y here if you have a simple joystick connected over ADC. +-- +2.35.1 + diff --git a/queue-5.15/input-wistron_btns-disable-on-uml.patch b/queue-5.15/input-wistron_btns-disable-on-uml.patch new file mode 100644 index 00000000000..1b46841bf39 --- /dev/null +++ b/queue-5.15/input-wistron_btns-disable-on-uml.patch @@ -0,0 +1,42 @@ +From 13850451d59e160408c00740b41528eb68340980 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 15:01:07 -0800 +Subject: Input: wistron_btns - disable on UML + +From: Randy Dunlap + +[ Upstream commit b2b80d9dd14cb5b70dc254bddbc4eea932694791 ] + +The wistron_btns driver calls rtc_cmos_read(), which isn't +available with UML builds, so disable this driver on UML. + +Prevents this build error: + +ld: drivers/input/misc/wistron_btns.o: in function `poll_bios': +wistron_btns.c:(.text+0x4be): undefined reference to `rtc_cmos_read' + +Fixes: 0bbadafdc49d ("um: allow disabling NO_IOMEM") # v5.14+ +Signed-off-by: Randy Dunlap +Link: https://lore.kernel.org/r/20221130161604.1879-1-rdunlap@infradead.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Sasha Levin +--- + drivers/input/misc/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig +index dd5227cf8696..b5b8ddb536be 100644 +--- a/drivers/input/misc/Kconfig ++++ b/drivers/input/misc/Kconfig +@@ -330,7 +330,7 @@ config INPUT_CPCAP_PWRBUTTON + + config INPUT_WISTRON_BTNS + tristate "x86 Wistron laptop button interface" +- depends on X86_32 ++ depends on X86_32 && !UML + select INPUT_SPARSEKMAP + select NEW_LEDS + select LEDS_CLASS +-- +2.35.1 + diff --git a/queue-5.15/integrity-fix-memory-leakage-in-keyring-allocation-e.patch b/queue-5.15/integrity-fix-memory-leakage-in-keyring-allocation-e.patch new file mode 100644 index 00000000000..2287bfd1910 --- /dev/null +++ b/queue-5.15/integrity-fix-memory-leakage-in-keyring-allocation-e.patch @@ -0,0 +1,47 @@ +From dbb154344245db73c9db562c344d0e2259825ebb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 18:13:17 +0800 +Subject: integrity: Fix memory leakage in keyring allocation error path + +From: GUO Zihua + +[ Upstream commit 39419ef7af0916cc3620ecf1ed42d29659109bf3 ] + +Key restriction is allocated in integrity_init_keyring(). However, if +keyring allocation failed, it is not freed, causing memory leaks. + +Fixes: 2b6aa412ff23 ("KEYS: Use structure to capture key restriction function and data") +Signed-off-by: GUO Zihua +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/digsig.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c +index 3b06a01bd0fd..aa93b750a9f3 100644 +--- a/security/integrity/digsig.c ++++ b/security/integrity/digsig.c +@@ -122,6 +122,7 @@ int __init integrity_init_keyring(const unsigned int id) + { + struct key_restriction *restriction; + key_perm_t perm; ++ int ret; + + perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW + | KEY_USR_READ | KEY_USR_SEARCH; +@@ -142,7 +143,10 @@ int __init integrity_init_keyring(const unsigned int id) + perm |= KEY_USR_WRITE; + + out: +- return __integrity_init_keyring(id, perm, restriction); ++ ret = __integrity_init_keyring(id, perm, restriction); ++ if (ret) ++ kfree(restriction); ++ return ret; + } + + static int __init integrity_add_key(const unsigned int id, const void *data, +-- +2.35.1 + diff --git a/queue-5.15/iommu-amd-fix-pci-device-refcount-leak-in-ppr_notifi.patch b/queue-5.15/iommu-amd-fix-pci-device-refcount-leak-in-ppr_notifi.patch new file mode 100644 index 00000000000..ff7d5090e3b --- /dev/null +++ b/queue-5.15/iommu-amd-fix-pci-device-refcount-leak-in-ppr_notifi.patch @@ -0,0 +1,39 @@ +From 3d09f7dde7ebea03e0cd993e507cf571302fce6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 17:36:04 +0800 +Subject: iommu/amd: Fix pci device refcount leak in ppr_notifier() + +From: Yang Yingliang + +[ Upstream commit 6cf0981c2233f97d56938d9d61845383d6eb227c ] + +As comment of pci_get_domain_bus_and_slot() says, it returns +a pci device with refcount increment, when finish using it, +the caller must decrement the reference count by calling +pci_dev_put(). So call it before returning from ppr_notifier() +to avoid refcount leak. + +Fixes: daae2d25a477 ("iommu/amd: Don't copy GCR3 table root pointer") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221118093604.216371-1-yangyingliang@huawei.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/iommu_v2.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/iommu/amd/iommu_v2.c b/drivers/iommu/amd/iommu_v2.c +index a45c5536d250..c96cf9b21719 100644 +--- a/drivers/iommu/amd/iommu_v2.c ++++ b/drivers/iommu/amd/iommu_v2.c +@@ -588,6 +588,7 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data) + put_device_state(dev_state); + + out: ++ pci_dev_put(pdev); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/iommu-fsl_pamu-fix-resource-leak-in-fsl_pamu_probe.patch b/queue-5.15/iommu-fsl_pamu-fix-resource-leak-in-fsl_pamu_probe.patch new file mode 100644 index 00000000000..a210cce9eb1 --- /dev/null +++ b/queue-5.15/iommu-fsl_pamu-fix-resource-leak-in-fsl_pamu_probe.patch @@ -0,0 +1,38 @@ +From 150af560215ddd2f87213becca5947bcf7219605 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 08:20:22 +0000 +Subject: iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe() + +From: Yuan Can + +[ Upstream commit 73f5fc5f884ad0c5f7d57f66303af64f9f002526 ] + +The fsl_pamu_probe() returns directly when create_csd() failed, leaving +irq and memories unreleased. +Fix by jumping to error if create_csd() returns error. + +Fixes: 695093e38c3e ("iommu/fsl: Freescale PAMU driver and iommu implementation.") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221121082022.19091-1-yuancan@huawei.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/fsl_pamu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c +index fc38b1fba7cf..bb5d253188a1 100644 +--- a/drivers/iommu/fsl_pamu.c ++++ b/drivers/iommu/fsl_pamu.c +@@ -865,7 +865,7 @@ static int fsl_pamu_probe(struct platform_device *pdev) + ret = create_csd(ppaact_phys, mem_size, csd_port_id); + if (ret) { + dev_err(dev, "could not create coherence subdomain\n"); +- return ret; ++ goto error; + } + } + +-- +2.35.1 + diff --git a/queue-5.15/iommu-rockchip-fix-permission-bits-in-page-table-ent.patch b/queue-5.15/iommu-rockchip-fix-permission-bits-in-page-table-ent.patch new file mode 100644 index 00000000000..d0b9c195d8c --- /dev/null +++ b/queue-5.15/iommu-rockchip-fix-permission-bits-in-page-table-ent.patch @@ -0,0 +1,58 @@ +From 96fdc7de2fc5bb8e50f25c5f7cd58029206aa98b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 07:35:53 +0100 +Subject: iommu/rockchip: fix permission bits in page table entries v2 + +From: Michael Riesch + +[ Upstream commit 7eb99841f340b80be0d0973b0deb592d75fb8928 ] + +As pointed out in the corresponding downstream fix [0], the permission bits +of the page table entries are compatible between v1 and v2 of the IOMMU. +This is in contrast to the current mainline code that incorrectly assumes +that the read and write permission bits are switched. Fix the permission +bits by reusing the v1 bit defines. + +[0] https://github.com/rockchip-linux/kernel/commit/e3bc123a2260145e34b57454da3db0edd117eb8e + +Fixes: c55356c534aa ("iommu: rockchip: Add support for iommu v2") +Signed-off-by: Michael Riesch +Reviewed-by: Heiko Stuebner +Link: https://lore.kernel.org/r/20221102063553.2464161-1-michael.riesch@wolfvision.net +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/rockchip-iommu.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c +index 7f23ad61c094..823f1a7d8c6e 100644 +--- a/drivers/iommu/rockchip-iommu.c ++++ b/drivers/iommu/rockchip-iommu.c +@@ -280,19 +280,17 @@ static u32 rk_mk_pte(phys_addr_t page, int prot) + * 11:9 - Page address bit 34:32 + * 8:4 - Page address bit 39:35 + * 3 - Security +- * 2 - Readable +- * 1 - Writable ++ * 2 - Writable ++ * 1 - Readable + * 0 - 1 if Page @ Page address is valid + */ +-#define RK_PTE_PAGE_READABLE_V2 BIT(2) +-#define RK_PTE_PAGE_WRITABLE_V2 BIT(1) + + static u32 rk_mk_pte_v2(phys_addr_t page, int prot) + { + u32 flags = 0; + +- flags |= (prot & IOMMU_READ) ? RK_PTE_PAGE_READABLE_V2 : 0; +- flags |= (prot & IOMMU_WRITE) ? RK_PTE_PAGE_WRITABLE_V2 : 0; ++ flags |= (prot & IOMMU_READ) ? RK_PTE_PAGE_READABLE : 0; ++ flags |= (prot & IOMMU_WRITE) ? RK_PTE_PAGE_WRITABLE : 0; + + return rk_mk_dte_v2(page) | flags; + } +-- +2.35.1 + diff --git a/queue-5.15/iommu-sun50i-consider-all-fault-sources-for-reset.patch b/queue-5.15/iommu-sun50i-consider-all-fault-sources-for-reset.patch new file mode 100644 index 00000000000..a008e9ebc62 --- /dev/null +++ b/queue-5.15/iommu-sun50i-consider-all-fault-sources-for-reset.patch @@ -0,0 +1,60 @@ +From c62fb93cd72b4a90cee01bb7eb1b527b3cce35c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 18:54:12 +0200 +Subject: iommu/sun50i: Consider all fault sources for reset + +From: Jernej Skrabec + +[ Upstream commit cef20703e2b2276aaa402ec5a65ec9a09963b83e ] + +We have to reset masters for all faults - permissions, L1 fault or L2 +fault. Currently it's done only for permissions. If other type of fault +happens, master is in locked up state. Fix that by really considering +all fault sources. + +Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver") +Signed-off-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20221025165415.307591-3-jernej.skrabec@gmail.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/sun50i-iommu.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index 3fd1ee147953..5b87672c689f 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -870,8 +870,8 @@ static phys_addr_t sun50i_iommu_handle_perm_irq(struct sun50i_iommu *iommu) + + static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + { ++ u32 status, l1_status, l2_status, resets; + struct sun50i_iommu *iommu = dev_id; +- u32 status; + + spin_lock(&iommu->iommu_lock); + +@@ -881,6 +881,9 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + return IRQ_NONE; + } + ++ l1_status = iommu_read(iommu, IOMMU_L1PG_INT_REG); ++ l2_status = iommu_read(iommu, IOMMU_L2PG_INT_REG); ++ + if (status & IOMMU_INT_INVALID_L2PG) + sun50i_iommu_handle_pt_irq(iommu, + IOMMU_INT_ERR_ADDR_L2_REG, +@@ -894,7 +897,8 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + + iommu_write(iommu, IOMMU_INT_CLR_REG, status); + +- iommu_write(iommu, IOMMU_RESET_REG, ~status); ++ resets = (status | l1_status | l2_status) & IOMMU_INT_MASTER_MASK; ++ iommu_write(iommu, IOMMU_RESET_REG, ~resets); + iommu_write(iommu, IOMMU_RESET_REG, IOMMU_RESET_RELEASE_ALL); + + spin_unlock(&iommu->iommu_lock); +-- +2.35.1 + diff --git a/queue-5.15/iommu-sun50i-fix-flush-size.patch b/queue-5.15/iommu-sun50i-fix-flush-size.patch new file mode 100644 index 00000000000..cc8fd433f42 --- /dev/null +++ b/queue-5.15/iommu-sun50i-fix-flush-size.patch @@ -0,0 +1,37 @@ +From 93098dad5d0c43c9f62f3f83449a3f27f9114fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 18:54:14 +0200 +Subject: iommu/sun50i: Fix flush size + +From: Jernej Skrabec + +[ Upstream commit 67a8a67f9eceb72e4c73d1d09ed9ab04f4b8e12d ] + +Function sun50i_table_flush() takes number of entries as an argument, +not number of bytes. Fix that mistake in sun50i_dte_get_page_table(). + +Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver") +Signed-off-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20221025165415.307591-5-jernej.skrabec@gmail.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/sun50i-iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index 16bfba1faee1..ece3d4b4d7ca 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -512,7 +512,7 @@ static u32 *sun50i_dte_get_page_table(struct sun50i_iommu_domain *sun50i_domain, + sun50i_iommu_free_page_table(iommu, drop_pt); + } + +- sun50i_table_flush(sun50i_domain, page_table, PT_SIZE); ++ sun50i_table_flush(sun50i_domain, page_table, NUM_PT_ENTRIES); + sun50i_table_flush(sun50i_domain, dte_addr, 1); + + return page_table; +-- +2.35.1 + diff --git a/queue-5.15/iommu-sun50i-fix-r-w-permission-check.patch b/queue-5.15/iommu-sun50i-fix-r-w-permission-check.patch new file mode 100644 index 00000000000..ee6d621f6ed --- /dev/null +++ b/queue-5.15/iommu-sun50i-fix-r-w-permission-check.patch @@ -0,0 +1,43 @@ +From 199e79d4d8e1db2e89baaf1334a921429c833411 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 18:54:13 +0200 +Subject: iommu/sun50i: Fix R/W permission check + +From: Jernej Skrabec + +[ Upstream commit eac0104dc69be50bed86926d6f32e82b44f8c921 ] + +Because driver has enum type permissions and iommu subsystem has bitmap +type, we have to be careful how check for combined read and write +permissions is done. In such case, we have to mask both permissions and +check that both are set at the same time. + +Current code just masks both flags but doesn't check that both are set. +In short, it always sets R/W permission, regardles if requested +permissions were RO, WO or RW. Fix that. + +Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver") +Signed-off-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20221025165415.307591-4-jernej.skrabec@gmail.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/sun50i-iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index 5b87672c689f..16bfba1faee1 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -271,7 +271,7 @@ static u32 sun50i_mk_pte(phys_addr_t page, int prot) + enum sun50i_iommu_aci aci; + u32 flags = 0; + +- if (prot & (IOMMU_READ | IOMMU_WRITE)) ++ if ((prot & (IOMMU_READ | IOMMU_WRITE)) == (IOMMU_READ | IOMMU_WRITE)) + aci = SUN50I_IOMMU_ACI_RD_WR; + else if (prot & IOMMU_READ) + aci = SUN50I_IOMMU_ACI_RD; +-- +2.35.1 + diff --git a/queue-5.15/iommu-sun50i-fix-reset-release.patch b/queue-5.15/iommu-sun50i-fix-reset-release.patch new file mode 100644 index 00000000000..bf677e1305b --- /dev/null +++ b/queue-5.15/iommu-sun50i-fix-reset-release.patch @@ -0,0 +1,54 @@ +From c6e6280190bd63cae51b07fe016b64baf29dd4a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 18:54:11 +0200 +Subject: iommu/sun50i: Fix reset release + +From: Jernej Skrabec + +[ Upstream commit 9ad0c1252e84dbc664f0462707182245ed603237 ] + +Reset signal is asserted by writing 0 to the corresponding locations of +masters we want to reset. So in order to deassert all reset signals, we +should write 1's to all locations. + +Current code writes 1's to locations of masters which were just reset +which is good. However, at the same time it also writes 0's to other +locations and thus asserts reset signals of remaining masters. Fix code +by writing all 1's when we want to deassert all reset signals. + +This bug was discovered when working with Cedrus (video decoder). When +it faulted, display went blank due to reset signal assertion. + +Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver") +Signed-off-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20221025165415.307591-2-jernej.skrabec@gmail.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/sun50i-iommu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index 92997021e188..3fd1ee147953 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -27,6 +27,7 @@ + #include + + #define IOMMU_RESET_REG 0x010 ++#define IOMMU_RESET_RELEASE_ALL 0xffffffff + #define IOMMU_ENABLE_REG 0x020 + #define IOMMU_ENABLE_ENABLE BIT(0) + +@@ -894,7 +895,7 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id) + iommu_write(iommu, IOMMU_INT_CLR_REG, status); + + iommu_write(iommu, IOMMU_RESET_REG, ~status); +- iommu_write(iommu, IOMMU_RESET_REG, status); ++ iommu_write(iommu, IOMMU_RESET_REG, IOMMU_RESET_RELEASE_ALL); + + spin_unlock(&iommu->iommu_lock); + +-- +2.35.1 + diff --git a/queue-5.15/iommu-sun50i-remove-iommu_domain_identity.patch b/queue-5.15/iommu-sun50i-remove-iommu_domain_identity.patch new file mode 100644 index 00000000000..18d7fdb973e --- /dev/null +++ b/queue-5.15/iommu-sun50i-remove-iommu_domain_identity.patch @@ -0,0 +1,44 @@ +From 76bbba12ca6f0846e06e23480e4c134134c4fc6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 10:06:28 -0400 +Subject: iommu/sun50i: Remove IOMMU_DOMAIN_IDENTITY + +From: Jason Gunthorpe + +[ Upstream commit ef5bb8e7a7127218f826b9ccdf7508e7a339f4c2 ] + +This driver treats IOMMU_DOMAIN_IDENTITY the same as UNMANAGED, which +cannot possibly be correct. + +UNMANAGED domains are required to start out blocking all DMAs. This seems +to be what this driver does as it allocates a first level 'dt' for the IO +page table that is 0 filled. + +Thus UNMANAGED looks like a working IO page table, and so IDENTITY must be +a mistake. Remove it. + +Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver") +Signed-off-by: Jason Gunthorpe +Reviewed-by: Robin Murphy +Link: https://lore.kernel.org/r/0-v1-97f0adf27b5e+1f0-s50_identity_jgg@nvidia.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/sun50i-iommu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c +index ece3d4b4d7ca..ed3574195599 100644 +--- a/drivers/iommu/sun50i-iommu.c ++++ b/drivers/iommu/sun50i-iommu.c +@@ -602,7 +602,6 @@ static struct iommu_domain *sun50i_iommu_domain_alloc(unsigned type) + struct sun50i_iommu_domain *sun50i_domain; + + if (type != IOMMU_DOMAIN_DMA && +- type != IOMMU_DOMAIN_IDENTITY && + type != IOMMU_DOMAIN_UNMANAGED) + return NULL; + +-- +2.35.1 + diff --git a/queue-5.15/ipmi-fix-memleak-when-unload-ipmi-driver.patch b/queue-5.15/ipmi-fix-memleak-when-unload-ipmi-driver.patch new file mode 100644 index 00000000000..cc2ff662b18 --- /dev/null +++ b/queue-5.15/ipmi-fix-memleak-when-unload-ipmi-driver.patch @@ -0,0 +1,64 @@ +From 6e5778ba050d0fba5a8395a8b785f8572bb27942 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Oct 2022 17:26:17 +0800 +Subject: ipmi: fix memleak when unload ipmi driver + +From: Zhang Yuchen + +[ Upstream commit 36992eb6b9b83f7f9cdc8e74fb5799d7b52e83e9 ] + +After the IPMI disconnect problem, the memory kept rising and we tried +to unload the driver to free the memory. However, only part of the +free memory is recovered after the driver is uninstalled. Using +ebpf to hook free functions, we find that neither ipmi_user nor +ipmi_smi_msg is free, only ipmi_recv_msg is free. + +We find that the deliver_smi_err_response call in clean_smi_msgs does +the destroy processing on each message from the xmit_msg queue without +checking the return value and free ipmi_smi_msg. + +deliver_smi_err_response is called only at this location. Adding the +free handling has no effect. + +To verify, try using ebpf to trace the free function. + + $ bpftrace -e 'kretprobe:ipmi_alloc_recv_msg {printf("alloc rcv + %p\n",retval);} kprobe:free_recv_msg {printf("free recv %p\n", + arg0)} kretprobe:ipmi_alloc_smi_msg {printf("alloc smi %p\n", + retval);} kprobe:free_smi_msg {printf("free smi %p\n",arg0)}' + +Signed-off-by: Zhang Yuchen +Message-Id: <20221007092617.87597-4-zhangyuchen.lcr@bytedance.com> +[Fixed the comment above handle_one_recv_msg().] +Signed-off-by: Corey Minyard +Signed-off-by: Sasha Levin +--- + drivers/char/ipmi/ipmi_msghandler.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c +index 2badf36d4816..8dbc349a2edd 100644 +--- a/drivers/char/ipmi/ipmi_msghandler.c ++++ b/drivers/char/ipmi/ipmi_msghandler.c +@@ -3527,12 +3527,16 @@ static void deliver_smi_err_response(struct ipmi_smi *intf, + struct ipmi_smi_msg *msg, + unsigned char err) + { ++ int rv; + msg->rsp[0] = msg->data[0] | 4; + msg->rsp[1] = msg->data[1]; + msg->rsp[2] = err; + msg->rsp_size = 3; +- /* It's an error, so it will never requeue, no need to check return. */ +- handle_one_recv_msg(intf, msg); ++ ++ /* This will never requeue, but it may ask us to free the message. */ ++ rv = handle_one_recv_msg(intf, msg); ++ if (rv == 0) ++ ipmi_free_smi_msg(msg); + } + + static void cleanup_smi_msgs(struct ipmi_smi *intf) +-- +2.35.1 + diff --git a/queue-5.15/ipmi-kcs-poll-obf-briefly-to-reduce-obe-latency.patch b/queue-5.15/ipmi-kcs-poll-obf-briefly-to-reduce-obe-latency.patch new file mode 100644 index 00000000000..b53ac1d33ed --- /dev/null +++ b/queue-5.15/ipmi-kcs-poll-obf-briefly-to-reduce-obe-latency.patch @@ -0,0 +1,71 @@ +From 6a6783a60a7dc6c2de783fba08ed10dc4720eff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Aug 2022 00:17:41 +0930 +Subject: ipmi: kcs: Poll OBF briefly to reduce OBE latency + +From: Andrew Jeffery + +[ Upstream commit f90bc0f97f2b65af233a37b2e32fc81871a1e3cf ] + +The ASPEED KCS devices don't provide a BMC-side interrupt for the host +reading the output data register (ODR). The act of the host reading ODR +clears the output buffer full (OBF) flag in the status register (STR), +informing the BMC it can transmit a subsequent byte. + +On the BMC side the KCS client must enable the OBE event *and* perform a +subsequent read of STR anyway to avoid races - the polling provides a +window for the host to read ODR if data was freshly written while +minimising BMC-side latency. + +Fixes: 28651e6c4237 ("ipmi: kcs_bmc: Allow clients to control KCS IRQ state") +Signed-off-by: Andrew Jeffery +Reviewed-by: Joel Stanley +Message-Id: <20220812144741.240315-1-andrew@aj.id.au> +Signed-off-by: Corey Minyard +Signed-off-by: Sasha Levin +--- + drivers/char/ipmi/kcs_bmc_aspeed.c | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c +index 92a37b33494c..f23c146bb740 100644 +--- a/drivers/char/ipmi/kcs_bmc_aspeed.c ++++ b/drivers/char/ipmi/kcs_bmc_aspeed.c +@@ -404,13 +404,31 @@ static void aspeed_kcs_check_obe(struct timer_list *timer) + static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) + { + struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc); ++ int rc; ++ u8 str; + + /* We don't have an OBE IRQ, emulate it */ + if (mask & KCS_BMC_EVENT_TYPE_OBE) { +- if (KCS_BMC_EVENT_TYPE_OBE & state) +- mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); +- else ++ if (KCS_BMC_EVENT_TYPE_OBE & state) { ++ /* ++ * Given we don't have an OBE IRQ, delay by polling briefly to see if we can ++ * observe such an event before returning to the caller. This is not ++ * incorrect because OBF may have already become clear before enabling the ++ * IRQ if we had one, under which circumstance no event will be propagated ++ * anyway. ++ * ++ * The onus is on the client to perform a race-free check that it hasn't ++ * missed the event. ++ */ ++ rc = read_poll_timeout_atomic(aspeed_kcs_inb, str, ++ !(str & KCS_BMC_STR_OBF), 1, 100, false, ++ &priv->kcs_bmc, priv->kcs_bmc.ioreg.str); ++ /* Time for the slow path? */ ++ if (rc == -ETIMEDOUT) ++ mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); ++ } else { + del_timer(&priv->obe.timer); ++ } + } + + if (mask & KCS_BMC_EVENT_TYPE_IBF) { +-- +2.35.1 + diff --git a/queue-5.15/ipv6-sit-use-dev_stats_inc-to-avoid-data-races.patch b/queue-5.15/ipv6-sit-use-dev_stats_inc-to-avoid-data-races.patch new file mode 100644 index 00000000000..2edf296a41f --- /dev/null +++ b/queue-5.15/ipv6-sit-use-dev_stats_inc-to-avoid-data-races.patch @@ -0,0 +1,123 @@ +From 758e16d186e6ec9e745db90b668eac53281cc3d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 08:53:56 +0000 +Subject: ipv6/sit: use DEV_STATS_INC() to avoid data-races + +From: Eric Dumazet + +[ Upstream commit cb34b7cf17ecf33499c9298943f85af247abc1e9 ] + +syzbot/KCSAN reported that multiple cpus are updating dev->stats.tx_error +concurrently. + +This is because sit tunnels are NETIF_F_LLTX, meaning their ndo_start_xmit() +is not protected by a spinlock. + +While original KCSAN report was about tx path, rx path has the same issue. + +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv6/sit.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index 946871741f12..d4cdc2b1b468 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -696,7 +696,7 @@ static int ipip6_rcv(struct sk_buff *skb) + skb->dev = tunnel->dev; + + if (packet_is_spoofed(skb, iph, tunnel)) { +- tunnel->dev->stats.rx_errors++; ++ DEV_STATS_INC(tunnel->dev, rx_errors); + goto out; + } + +@@ -716,8 +716,8 @@ static int ipip6_rcv(struct sk_buff *skb) + net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n", + &iph->saddr, iph->tos); + if (err > 1) { +- ++tunnel->dev->stats.rx_frame_errors; +- ++tunnel->dev->stats.rx_errors; ++ DEV_STATS_INC(tunnel->dev, rx_frame_errors); ++ DEV_STATS_INC(tunnel->dev, rx_errors); + goto out; + } + } +@@ -948,7 +948,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + if (!rt) { + rt = ip_route_output_flow(tunnel->net, &fl4, NULL); + if (IS_ERR(rt)) { +- dev->stats.tx_carrier_errors++; ++ DEV_STATS_INC(dev, tx_carrier_errors); + goto tx_error_icmp; + } + dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, fl4.saddr); +@@ -956,14 +956,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + + if (rt->rt_type != RTN_UNICAST) { + ip_rt_put(rt); +- dev->stats.tx_carrier_errors++; ++ DEV_STATS_INC(dev, tx_carrier_errors); + goto tx_error_icmp; + } + tdev = rt->dst.dev; + + if (tdev == dev) { + ip_rt_put(rt); +- dev->stats.collisions++; ++ DEV_STATS_INC(dev, collisions); + goto tx_error; + } + +@@ -976,7 +976,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + mtu = dst_mtu(&rt->dst) - t_hlen; + + if (mtu < IPV4_MIN_MTU) { +- dev->stats.collisions++; ++ DEV_STATS_INC(dev, collisions); + ip_rt_put(rt); + goto tx_error; + } +@@ -1015,7 +1015,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) { + ip_rt_put(rt); +- dev->stats.tx_dropped++; ++ DEV_STATS_INC(dev, tx_dropped); + kfree_skb(skb); + return NETDEV_TX_OK; + } +@@ -1045,7 +1045,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + dst_link_failure(skb); + tx_error: + kfree_skb(skb); +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + return NETDEV_TX_OK; + } + +@@ -1064,7 +1064,7 @@ static netdev_tx_t sit_tunnel_xmit__(struct sk_buff *skb, + return NETDEV_TX_OK; + tx_error: + kfree_skb(skb); +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + return NETDEV_TX_OK; + } + +@@ -1093,7 +1093,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb, + return NETDEV_TX_OK; + + tx_err: +- dev->stats.tx_errors++; ++ DEV_STATS_INC(dev, tx_errors); + kfree_skb(skb); + return NETDEV_TX_OK; + +-- +2.35.1 + diff --git a/queue-5.15/irqchip-gic-pm-use-pm_runtime_resume_and_get-in-gic_.patch b/queue-5.15/irqchip-gic-pm-use-pm_runtime_resume_and_get-in-gic_.patch new file mode 100644 index 00000000000..8f4a98bfc82 --- /dev/null +++ b/queue-5.15/irqchip-gic-pm-use-pm_runtime_resume_and_get-in-gic_.patch @@ -0,0 +1,39 @@ +From 3c15f72c907a5f41d9e7ac0b4b7af66607ae631c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 14:51:50 +0800 +Subject: irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe() + +From: Shang XiaoJing + +[ Upstream commit f9ee20c85b3a3ba0afd3672630ec4f93d339f015 ] + +gic_probe() calls pm_runtime_get_sync() and added fail path as +rpm_put to put usage_counter. However, pm_runtime_get_sync() +will increment usage_counter even it failed. Fix it by replacing it with +pm_runtime_resume_and_get() to keep usage counter balanced. + +Fixes: 9c8edddfc992 ("irqchip/gic: Add platform driver for non-root GICs that require RPM") +Signed-off-by: Shang XiaoJing +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221124065150.22809-1-shangxiaojing@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-gic-pm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c +index b60e1853593f..3989d16f997b 100644 +--- a/drivers/irqchip/irq-gic-pm.c ++++ b/drivers/irqchip/irq-gic-pm.c +@@ -102,7 +102,7 @@ static int gic_probe(struct platform_device *pdev) + + pm_runtime_enable(dev); + +- ret = pm_runtime_get_sync(dev); ++ ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + goto rpm_disable; + +-- +2.35.1 + diff --git a/queue-5.15/irqchip-wpcm450-fix-memory-leak-in-wpcm450_aic_of_in.patch b/queue-5.15/irqchip-wpcm450-fix-memory-leak-in-wpcm450_aic_of_in.patch new file mode 100644 index 00000000000..341448750b7 --- /dev/null +++ b/queue-5.15/irqchip-wpcm450-fix-memory-leak-in-wpcm450_aic_of_in.patch @@ -0,0 +1,40 @@ +From 83381add4be74e2ab6b95555e2d94ceb2d8cbcc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 09:25:32 +0000 +Subject: irqchip/wpcm450: Fix memory leak in wpcm450_aic_of_init() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wei Yongjun + +[ Upstream commit 4208d4faf36573a507b5e5de17abe342e9276759 ] + +If of_iomap() failed, 'aic' should be freed before return. Otherwise +there is a memory leak. + +Fixes: fead4dd49663 ("irqchip: Add driver for WPCM450 interrupt controller") +Signed-off-by: Wei Yongjun +Reviewed-by: Jonathan Neuschäfer +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221115092532.1704032-1-weiyongjun@huaweicloud.com +Signed-off-by: Sasha Levin +--- + drivers/irqchip/irq-wpcm450-aic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/irqchip/irq-wpcm450-aic.c b/drivers/irqchip/irq-wpcm450-aic.c +index f3ac392d5bc8..36d0d0cf3fa2 100644 +--- a/drivers/irqchip/irq-wpcm450-aic.c ++++ b/drivers/irqchip/irq-wpcm450-aic.c +@@ -146,6 +146,7 @@ static int __init wpcm450_aic_of_init(struct device_node *node, + aic->regs = of_iomap(node, 0); + if (!aic->regs) { + pr_err("Failed to map WPCM450 AIC registers\n"); ++ kfree(aic); + return -ENOMEM; + } + +-- +2.35.1 + diff --git a/queue-5.15/jfs-fix-fortify-moan-in-symlink.patch b/queue-5.15/jfs-fix-fortify-moan-in-symlink.patch new file mode 100644 index 00000000000..7c165508eb7 --- /dev/null +++ b/queue-5.15/jfs-fix-fortify-moan-in-symlink.patch @@ -0,0 +1,60 @@ +From b8d72d1c3fe6deca570259d63f5e7b207d34b315 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Oct 2022 21:39:14 +0100 +Subject: jfs: Fix fortify moan in symlink + +From: Dr. David Alan Gilbert + +[ Upstream commit ebe060369f8d6e4588b115f252bebf5ba4d64350 ] + +JFS has in jfs_incore.h: + + /* _inline may overflow into _inline_ea when needed */ + /* _inline_ea may overlay the last part of + * file._xtroot if maxentry = XTROOTINITSLOT + */ + union { + struct { + /* 128: inline symlink */ + unchar _inline[128]; + /* 128: inline extended attr */ + unchar _inline_ea[128]; + }; + unchar _inline_all[256]; + +and currently the symlink code copies into _inline; +if this is larger than 128 bytes it triggers a fortify warning of the +form: + + memcpy: detected field-spanning write (size 132) of single field + "ip->i_link" at fs/jfs/namei.c:950 (size 18446744073709551615) + +when it's actually OK. + +Copy it into _inline_all instead. + +Reported-by: syzbot+5fc38b2ddbbca7f5c680@syzkaller.appspotmail.com +Signed-off-by: Dr. David Alan Gilbert +Reviewed-by: Kees Cook +Signed-off-by: Dave Kleikamp +Signed-off-by: Sasha Levin +--- + fs/jfs/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c +index 9db4f5789c0e..4fbbf88435e6 100644 +--- a/fs/jfs/namei.c ++++ b/fs/jfs/namei.c +@@ -946,7 +946,7 @@ static int jfs_symlink(struct user_namespace *mnt_userns, struct inode *dip, + if (ssize <= IDATASIZE) { + ip->i_op = &jfs_fast_symlink_inode_operations; + +- ip->i_link = JFS_IP(ip)->i_inline; ++ ip->i_link = JFS_IP(ip)->i_inline_all; + memcpy(ip->i_link, name, ssize); + ip->i_size = ssize - 1; + +-- +2.35.1 + diff --git a/queue-5.15/ksmbd-fix-resource-leak-in-ksmbd_session_rpc_open.patch b/queue-5.15/ksmbd-fix-resource-leak-in-ksmbd_session_rpc_open.patch new file mode 100644 index 00000000000..3077f5d99d7 --- /dev/null +++ b/queue-5.15/ksmbd-fix-resource-leak-in-ksmbd_session_rpc_open.patch @@ -0,0 +1,49 @@ +From fc9f18b842992d361af1e1883a9177884ddb3bcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 20:22:37 +0800 +Subject: ksmbd: Fix resource leak in ksmbd_session_rpc_open() + +From: Xiu Jianfeng + +[ Upstream commit bc044414fa0326a4e5c3c509c00b1fcaf621b5f4 ] + +When ksmbd_rpc_open() fails then it must call ksmbd_rpc_id_free() to +undo the result of ksmbd_ipc_id_alloc(). + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Signed-off-by: Xiu Jianfeng +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/ksmbd/mgmt/user_session.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c +index 8d8ffd8c6f19..0fa467f2c897 100644 +--- a/fs/ksmbd/mgmt/user_session.c ++++ b/fs/ksmbd/mgmt/user_session.c +@@ -106,15 +106,17 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name) + entry->method = method; + entry->id = ksmbd_ipc_id_alloc(); + if (entry->id < 0) +- goto error; ++ goto free_entry; + + resp = ksmbd_rpc_open(sess, entry->id); + if (!resp) +- goto error; ++ goto free_id; + + kvfree(resp); + return entry->id; +-error: ++free_id: ++ ksmbd_rpc_id_free(entry->id); ++free_entry: + list_del(&entry->list); + kfree(entry); + return -EINVAL; +-- +2.35.1 + diff --git a/queue-5.15/kvm-selftests-fix-build-regression-by-using-accessor.patch b/queue-5.15/kvm-selftests-fix-build-regression-by-using-accessor.patch new file mode 100644 index 00000000000..85037dc6336 --- /dev/null +++ b/queue-5.15/kvm-selftests-fix-build-regression-by-using-accessor.patch @@ -0,0 +1,41 @@ +From 461fbbc244f45b95a6d9e4a10d7616c9ec12e15e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Dec 2022 18:09:58 -0600 +Subject: KVM: selftests: Fix build regression by using accessor function + +From: Tyler Hicks + +Fix the stable backport of commit 05c2224d4b04 ("KVM: selftests: Fix +number of pages for memory slot in memslot_modification_stress_test"), +which caused memslot_modification_stress_test.c build failures due to +trying to access private members of struct kvm_vm. + +v6.0 commit b530eba14c70 ("KVM: selftests: Get rid of +kvm_util_internal.h") and some other commits got rid of the accessors +and made all of the KVM data structures public. Keep using the accessors +in older kernels. + +There is no corresponding upstream commit for this change. + +Signed-off-by: Tyler Hicks (Microsoft) +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/kvm/memslot_modification_stress_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/kvm/memslot_modification_stress_test.c b/tools/testing/selftests/kvm/memslot_modification_stress_test.c +index 1d806b8ffee2..766c1790df66 100644 +--- a/tools/testing/selftests/kvm/memslot_modification_stress_test.c ++++ b/tools/testing/selftests/kvm/memslot_modification_stress_test.c +@@ -72,7 +72,7 @@ struct memslot_antagonist_args { + static void add_remove_memslot(struct kvm_vm *vm, useconds_t delay, + uint64_t nr_modifications) + { +- uint64_t pages = max_t(int, vm->page_size, getpagesize()) / vm->page_size; ++ uint64_t pages = max_t(int, vm_get_page_size(vm), getpagesize()) / vm_get_page_size(vm); + uint64_t gpa; + int i; + +-- +2.35.1 + diff --git a/queue-5.15/lib-debugobjects-fix-stat-count-and-optimize-debug_o.patch b/queue-5.15/lib-debugobjects-fix-stat-count-and-optimize-debug_o.patch new file mode 100644 index 00000000000..fa3fcddf57b --- /dev/null +++ b/queue-5.15/lib-debugobjects-fix-stat-count-and-optimize-debug_o.patch @@ -0,0 +1,76 @@ +From 980ecdb091b2863ff941e82bafde94523158c1cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jun 2022 21:06:34 +0800 +Subject: lib/debugobjects: fix stat count and optimize debug_objects_mem_init + +From: wuchi + +[ Upstream commit eabb7f1ace53e127309407b2b5e74e8199e85270 ] + +1. Var debug_objects_allocated tracks valid kmem_cache_alloc calls, so + track it in debug_objects_replace_static_objects. Do similar things in + object_cpu_offline. + +2. In debug_objects_mem_init, there is no need to call function + cpuhp_setup_state_nocalls when debug_objects_enabled = 0 (out of + memory). + +Link: https://lkml.kernel.org/r/20220611130634.99741-1-wuchi.zero@gmail.com +Fixes: 634d61f45d6f ("debugobjects: Percpu pool lookahead freeing/allocation") +Fixes: c4b73aabd098 ("debugobjects: Track number of kmem_cache_alloc/kmem_cache_free done") +Signed-off-by: wuchi +Reviewed-by: Waiman Long +Cc: Thomas Gleixner +Cc: Christoph Hellwig +Cc: Kees Cook +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + lib/debugobjects.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/debugobjects.c b/lib/debugobjects.c +index 6946f8e204e3..793c31b7e417 100644 +--- a/lib/debugobjects.c ++++ b/lib/debugobjects.c +@@ -440,6 +440,7 @@ static int object_cpu_offline(unsigned int cpu) + struct debug_percpu_free *percpu_pool; + struct hlist_node *tmp; + struct debug_obj *obj; ++ unsigned long flags; + + /* Remote access is safe as the CPU is dead already */ + percpu_pool = per_cpu_ptr(&percpu_obj_pool, cpu); +@@ -447,6 +448,12 @@ static int object_cpu_offline(unsigned int cpu) + hlist_del(&obj->node); + kmem_cache_free(obj_cache, obj); + } ++ ++ raw_spin_lock_irqsave(&pool_lock, flags); ++ obj_pool_used -= percpu_pool->obj_free; ++ debug_objects_freed += percpu_pool->obj_free; ++ raw_spin_unlock_irqrestore(&pool_lock, flags); ++ + percpu_pool->obj_free = 0; + + return 0; +@@ -1321,6 +1328,8 @@ static int __init debug_objects_replace_static_objects(void) + hlist_add_head(&obj->node, &objects); + } + ++ debug_objects_allocated += i; ++ + /* + * debug_objects_mem_init() is now called early that only one CPU is up + * and interrupts have been disabled, so it is safe to replace the +@@ -1389,6 +1398,7 @@ void __init debug_objects_mem_init(void) + debug_objects_enabled = 0; + kmem_cache_destroy(obj_cache); + pr_warn("out of memory.\n"); ++ return; + } else + debug_objects_selftest(); + +-- +2.35.1 + diff --git a/queue-5.15/lib-fonts-fix-undefined-behavior-in-bit-shift-for-ge.patch b/queue-5.15/lib-fonts-fix-undefined-behavior-in-bit-shift-for-ge.patch new file mode 100644 index 00000000000..dc9b54c0ffa --- /dev/null +++ b/queue-5.15/lib-fonts-fix-undefined-behavior-in-bit-shift-for-ge.patch @@ -0,0 +1,79 @@ +From 74095355c2a47c442a452b6958c73a32f4e57061 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 19:38:29 +0800 +Subject: lib/fonts: fix undefined behavior in bit shift for get_default_font + +From: Gaosheng Cui + +[ Upstream commit 6fe888c4d2fb174408e4540bb2d5602b9f507f90 ] + +Shifting signed 32-bit value by 31 bits is undefined, so changing +significant bit to unsigned. The UBSAN warning calltrace like below: + +UBSAN: shift-out-of-bounds in lib/fonts/fonts.c:139:20 +left shift of 1 by 31 places cannot be represented in type 'int' + + dump_stack_lvl+0x7d/0xa5 + dump_stack+0x15/0x1b + ubsan_epilogue+0xe/0x4e + __ubsan_handle_shift_out_of_bounds+0x1e7/0x20c + get_default_font+0x1c7/0x1f0 + fbcon_startup+0x347/0x3a0 + do_take_over_console+0xce/0x270 + do_fbcon_takeover+0xa1/0x170 + do_fb_registered+0x2a8/0x340 + fbcon_fb_registered+0x47/0xe0 + register_framebuffer+0x294/0x4a0 + __drm_fb_helper_initial_config_and_unlock+0x43c/0x880 [drm_kms_helper] + drm_fb_helper_initial_config+0x52/0x80 [drm_kms_helper] + drm_fbdev_client_hotplug+0x156/0x1b0 [drm_kms_helper] + drm_fbdev_generic_setup+0xfc/0x290 [drm_kms_helper] + bochs_pci_probe+0x6ca/0x772 [bochs] + local_pci_probe+0x4d/0xb0 + pci_device_probe+0x119/0x320 + really_probe+0x181/0x550 + __driver_probe_device+0xc6/0x220 + driver_probe_device+0x32/0x100 + __driver_attach+0x195/0x200 + bus_for_each_dev+0xbb/0x120 + driver_attach+0x27/0x30 + bus_add_driver+0x22e/0x2f0 + driver_register+0xa9/0x190 + __pci_register_driver+0x90/0xa0 + bochs_pci_driver_init+0x52/0x1000 [bochs] + do_one_initcall+0x76/0x430 + do_init_module+0x61/0x28a + load_module+0x1f82/0x2e50 + __do_sys_finit_module+0xf8/0x190 + __x64_sys_finit_module+0x23/0x30 + do_syscall_64+0x58/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + + +Link: https://lkml.kernel.org/r/20221031113829.4183153-1-cuigaosheng1@huawei.com +Fixes: c81f717cb9e0 ("fbcon: Fix typo and bogus logic in get_default_font") +Signed-off-by: Gaosheng Cui +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + lib/fonts/fonts.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c +index 5f4b07b56cd9..973866438608 100644 +--- a/lib/fonts/fonts.c ++++ b/lib/fonts/fonts.c +@@ -135,8 +135,8 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, + if (res > 20) + c += 20 - res; + +- if ((font_w & (1 << (f->width - 1))) && +- (font_h & (1 << (f->height - 1)))) ++ if ((font_w & (1U << (f->width - 1))) && ++ (font_h & (1U << (f->height - 1)))) + c += 1000; + + if (c > cc) { +-- +2.35.1 + diff --git a/queue-5.15/lib-notifier-error-inject-fix-error-when-writing-err.patch b/queue-5.15/lib-notifier-error-inject-fix-error-when-writing-err.patch new file mode 100644 index 00000000000..741c15e3fd9 --- /dev/null +++ b/queue-5.15/lib-notifier-error-inject-fix-error-when-writing-err.patch @@ -0,0 +1,52 @@ +From 6d8acc26687075ba2cab115a43c4f2b75a705d71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 02:24:17 +0900 +Subject: lib/notifier-error-inject: fix error when writing -errno to debugfs + file + +From: Akinobu Mita + +[ Upstream commit f883c3edd2c432a2931ec8773c70a570115a50fe ] + +The simple attribute files do not accept a negative value since the commit +488dac0c9237 ("libfs: fix error cast of negative value in +simple_attr_write()"). + +This restores the previous behaviour by using newly introduced +DEFINE_SIMPLE_ATTRIBUTE_SIGNED instead of DEFINE_SIMPLE_ATTRIBUTE. + +Link: https://lkml.kernel.org/r/20220919172418.45257-3-akinobu.mita@gmail.com +Fixes: 488dac0c9237 ("libfs: fix error cast of negative value in simple_attr_write()") +Signed-off-by: Akinobu Mita +Reported-by: Zhao Gongyi +Reviewed-by: David Hildenbrand +Reviewed-by: Greg Kroah-Hartman +Cc: Alexander Viro +Cc: Jonathan Corbet +Cc: Oscar Salvador +Cc: Rafael J. Wysocki +Cc: Shuah Khan +Cc: Wei Yongjun +Cc: Yicong Yang +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + lib/notifier-error-inject.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/notifier-error-inject.c b/lib/notifier-error-inject.c +index 21016b32d313..2b24ea6c9497 100644 +--- a/lib/notifier-error-inject.c ++++ b/lib/notifier-error-inject.c +@@ -15,7 +15,7 @@ static int debugfs_errno_get(void *data, u64 *val) + return 0; + } + +-DEFINE_SIMPLE_ATTRIBUTE(fops_errno, debugfs_errno_get, debugfs_errno_set, ++DEFINE_SIMPLE_ATTRIBUTE_SIGNED(fops_errno, debugfs_errno_get, debugfs_errno_set, + "%lld\n"); + + static struct dentry *debugfs_create_errno(const char *name, umode_t mode, +-- +2.35.1 + diff --git a/queue-5.15/libbpf-avoid-enum-forward-declarations-in-public-api.patch b/queue-5.15/libbpf-avoid-enum-forward-declarations-in-public-api.patch new file mode 100644 index 00000000000..84bf9db9daa --- /dev/null +++ b/queue-5.15/libbpf-avoid-enum-forward-declarations-in-public-api.patch @@ -0,0 +1,71 @@ +From 2ae8d4e259b2811ceca974e701fb6b1d5ee36c94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 12:00:12 -0800 +Subject: libbpf: Avoid enum forward-declarations in public API in C++ mode + +From: Andrii Nakryiko + +[ Upstream commit b42693415b86f608049cf1b4870adc1dc65e58b0 ] + +C++ enum forward declarations are fundamentally not compatible with pure +C enum definitions, and so libbpf's use of `enum bpf_stats_type;` +forward declaration in libbpf/bpf.h public API header is causing C++ +compilation issues. + +More details can be found in [0], but it comes down to C++ supporting +enum forward declaration only with explicitly specified backing type: + + enum bpf_stats_type: int; + +In C (and I believe it's a GCC extension also), such forward declaration +is simply: + + enum bpf_stats_type; + +Further, in Linux UAPI this enum is defined in pure C way: + +enum bpf_stats_type { BPF_STATS_RUN_TIME = 0; } + +And even though in both cases backing type is int, which can be +confirmed by looking at DWARF information, for C++ compiler actual enum +definition and forward declaration are incompatible. + +To eliminate this problem, for C++ mode define input argument as int, +which makes enum unnecessary in libbpf public header. This solves the +issue and as demonstrated by next patch doesn't cause any unwanted +compiler warnings, at least with default warnings setting. + + [0] https://stackoverflow.com/questions/42766839/c11-enum-forward-causes-underlying-type-mismatch + [1] Closes: https://github.com/libbpf/libbpf/issues/249 + +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20221130200013.2997831-1-andrii@kernel.org +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/bpf.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h +index 6fffb3cdf39b..49bd43b998c8 100644 +--- a/tools/lib/bpf/bpf.h ++++ b/tools/lib/bpf/bpf.h +@@ -249,8 +249,15 @@ LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, + __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, + __u64 *probe_offset, __u64 *probe_addr); + ++#ifdef __cplusplus ++/* forward-declaring enums in C++ isn't compatible with pure C enums, so ++ * instead define bpf_enable_stats() as accepting int as an input ++ */ ++LIBBPF_API int bpf_enable_stats(int type); ++#else + enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */ + LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type); ++#endif + + struct bpf_prog_bind_opts { + size_t sz; /* size of this struct for forward/backward compatibility */ +-- +2.35.1 + diff --git a/queue-5.15/libbpf-btf-dedup-identical-struct-test-needs-check-f.patch b/queue-5.15/libbpf-btf-dedup-identical-struct-test-needs-check-f.patch new file mode 100644 index 00000000000..d489839e4fc --- /dev/null +++ b/queue-5.15/libbpf-btf-dedup-identical-struct-test-needs-check-f.patch @@ -0,0 +1,94 @@ +From c7561e9b85714277be8d129685211594f28b35fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 15:38:29 +0100 +Subject: libbpf: Btf dedup identical struct test needs check for nested + structs/arrays + +From: Alan Maguire + +[ Upstream commit f3c51fe02c55bd944662714e5b91b96dc271ad9f ] + +When examining module BTF, it is common to see core kernel structures +such as sk_buff, net_device duplicated in the module. After adding +debug messaging to BTF it turned out that much of the problem +was down to the identical struct test failing during deduplication; +sometimes the compiler adds identical structs. However +it turns out sometimes that type ids of identical struct members +can also differ, even when the containing structs are still identical. + +To take an example, for struct sk_buff, debug messaging revealed +that the identical struct matching was failing for the anon +struct "headers"; specifically for the first field: + +__u8 __pkt_type_offset[0]; /* 128 0 */ + +Looking at the code in BTF deduplication, we have code that guards +against the possibility of identical struct definitions, down to +type ids, and identical array definitions. However in this case +we have a struct which is being defined twice but does not have +identical type ids since each duplicate struct has separate type +ids for the above array member. A similar problem (though not +observed) could occur for struct-in-struct. + +The solution is to make the "identical struct" test check members +not just for matching ids, but to also check if they in turn are +identical structs or arrays. + +The results of doing this are quite dramatic (for some modules +at least); I see the number of type ids drop from around 10000 +to just over 1000 in one module for example. + +For testing use latest pahole or apply [1], otherwise dedups +can fail for the reasons described there. + +Also fix return type of btf_dedup_identical_arrays() as +suggested by Andrii to match boolean return type used +elsewhere. + +Fixes: efdd3eb8015e ("libbpf: Accommodate DWARF/compiler bug with duplicated structs") +Signed-off-by: Alan Maguire +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/1666622309-22289-1-git-send-email-alan.maguire@oracle.com + +[1] https://lore.kernel.org/bpf/1666364523-9648-1-git-send-email-alan.maguire + +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c +index 5f3d20ae66d5..3ed759f53e7c 100644 +--- a/tools/lib/bpf/btf.c ++++ b/tools/lib/bpf/btf.c +@@ -3718,14 +3718,14 @@ static inline __u16 btf_fwd_kind(struct btf_type *t) + } + + /* Check if given two types are identical ARRAY definitions */ +-static int btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2) ++static bool btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2) + { + struct btf_type *t1, *t2; + + t1 = btf_type_by_id(d->btf, id1); + t2 = btf_type_by_id(d->btf, id2); + if (!btf_is_array(t1) || !btf_is_array(t2)) +- return 0; ++ return false; + + return btf_equal_array(t1, t2); + } +@@ -3749,7 +3749,9 @@ static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id + m1 = btf_members(t1); + m2 = btf_members(t2); + for (i = 0, n = btf_vlen(t1); i < n; i++, m1++, m2++) { +- if (m1->type != m2->type) ++ if (m1->type != m2->type && ++ !btf_dedup_identical_arrays(d, m1->type, m2->type) && ++ !btf_dedup_identical_structs(d, m1->type, m2->type)) + return false; + } + return true; +-- +2.35.1 + diff --git a/queue-5.15/libbpf-fix-null-pointer-dereference-in-find_prog_by_.patch b/queue-5.15/libbpf-fix-null-pointer-dereference-in-find_prog_by_.patch new file mode 100644 index 00000000000..82ed85c4450 --- /dev/null +++ b/queue-5.15/libbpf-fix-null-pointer-dereference-in-find_prog_by_.patch @@ -0,0 +1,43 @@ +From 4cc8c4aff1b5dcd56d9f9dcf1cf4b662409ea1d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Oct 2022 10:23:53 +0800 +Subject: libbpf: Fix null-pointer dereference in find_prog_by_sec_insn() + +From: Shung-Hsi Yu + +[ Upstream commit d0d382f95a9270dcf803539d6781d6bd67e3f5b2 ] + +When there are no program sections, obj->programs is left unallocated, +and find_prog_by_sec_insn()'s search lands on &obj->programs[0] == NULL, +and will cause null-pointer dereference in the following access to +prog->sec_idx. + +Guard the search with obj->nr_programs similar to what's being done in +__bpf_program__iter() to prevent null-pointer access from happening. + +Fixes: db2b8b06423c ("libbpf: Support CO-RE relocations for multi-prog sections") +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20221012022353.7350-4-shung-hsi.yu@suse.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 050622649797..f87a15bbf53b 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -3763,6 +3763,9 @@ static struct bpf_program *find_prog_by_sec_insn(const struct bpf_object *obj, + int l = 0, r = obj->nr_programs - 1, m; + struct bpf_program *prog; + ++ if (!obj->nr_programs) ++ return NULL; ++ + while (l < r) { + m = l + (r - l + 1) / 2; + prog = &obj->programs[m]; +-- +2.35.1 + diff --git a/queue-5.15/libbpf-fix-uninitialized-warning-in-btf_dump_dump_ty.patch b/queue-5.15/libbpf-fix-uninitialized-warning-in-btf_dump_dump_ty.patch new file mode 100644 index 00000000000..f7e0130e0cc --- /dev/null +++ b/queue-5.15/libbpf-fix-uninitialized-warning-in-btf_dump_dump_ty.patch @@ -0,0 +1,48 @@ +From 1381914eb1f3251adb41d3908b609dbb39c42c7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 15:52:17 -0500 +Subject: libbpf: Fix uninitialized warning in btf_dump_dump_type_data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Michael + +[ Upstream commit dfd0afbf151d85411b371e841f62b81ee5d1ca54 ] + +GCC 11.3.0 fails to compile btf_dump.c due to the following error, +which seems to originate in btf_dump_struct_data where the returned +value would be uninitialized if btf_vlen returns zero. + +btf_dump.c: In function ‘btf_dump_dump_type_data’: +btf_dump.c:2363:12: error: ‘err’ may be used uninitialized in this function [-Werror=maybe-uninitialized] + 2363 | if (err < 0) + | ^ + +Fixes: 920d16af9b42 ("libbpf: BTF dumper support for typed data") +Signed-off-by: David Michael +Signed-off-by: Daniel Borkmann +Acked-by: Stanislav Fomichev +Acked-by: Alan Maguire +Link: https://lore.kernel.org/bpf/87zgcu60hq.fsf@gmail.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf_dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index 9bcd75dc12cc..f620911ad3bb 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -1915,7 +1915,7 @@ static int btf_dump_struct_data(struct btf_dump *d, + { + const struct btf_member *m = btf_members(t); + __u16 n = btf_vlen(t); +- int i, err; ++ int i, err = 0; + + /* note that we increment depth before calling btf_dump_print() below; + * this is intentional. btf_dump_data_newline() will not print a +-- +2.35.1 + diff --git a/queue-5.15/libbpf-fix-use-after-free-in-btf_dump_name_dups.patch b/queue-5.15/libbpf-fix-use-after-free-in-btf_dump_name_dups.patch new file mode 100644 index 00000000000..6ae130f0788 --- /dev/null +++ b/queue-5.15/libbpf-fix-use-after-free-in-btf_dump_name_dups.patch @@ -0,0 +1,141 @@ +From 8ddbd8e67a4461cf21b997ebbea527c7a735231e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Oct 2022 08:01:03 -0400 +Subject: libbpf: Fix use-after-free in btf_dump_name_dups + +From: Xu Kuohai + +[ Upstream commit 93c660ca40b5d2f7c1b1626e955a8e9fa30e0749 ] + +ASAN reports an use-after-free in btf_dump_name_dups: + +ERROR: AddressSanitizer: heap-use-after-free on address 0xffff927006db at pc 0xaaaab5dfb618 bp 0xffffdd89b890 sp 0xffffdd89b928 +READ of size 2 at 0xffff927006db thread T0 + #0 0xaaaab5dfb614 in __interceptor_strcmp.part.0 (test_progs+0x21b614) + #1 0xaaaab635f144 in str_equal_fn tools/lib/bpf/btf_dump.c:127 + #2 0xaaaab635e3e0 in hashmap_find_entry tools/lib/bpf/hashmap.c:143 + #3 0xaaaab635e72c in hashmap__find tools/lib/bpf/hashmap.c:212 + #4 0xaaaab6362258 in btf_dump_name_dups tools/lib/bpf/btf_dump.c:1525 + #5 0xaaaab636240c in btf_dump_resolve_name tools/lib/bpf/btf_dump.c:1552 + #6 0xaaaab6362598 in btf_dump_type_name tools/lib/bpf/btf_dump.c:1567 + #7 0xaaaab6360b48 in btf_dump_emit_struct_def tools/lib/bpf/btf_dump.c:912 + #8 0xaaaab6360630 in btf_dump_emit_type tools/lib/bpf/btf_dump.c:798 + #9 0xaaaab635f720 in btf_dump__dump_type tools/lib/bpf/btf_dump.c:282 + #10 0xaaaab608523c in test_btf_dump_incremental tools/testing/selftests/bpf/prog_tests/btf_dump.c:236 + #11 0xaaaab6097530 in test_btf_dump tools/testing/selftests/bpf/prog_tests/btf_dump.c:875 + #12 0xaaaab6314ed0 in run_one_test tools/testing/selftests/bpf/test_progs.c:1062 + #13 0xaaaab631a0a8 in main tools/testing/selftests/bpf/test_progs.c:1697 + #14 0xffff9676d214 in __libc_start_main ../csu/libc-start.c:308 + #15 0xaaaab5d65990 (test_progs+0x185990) + +0xffff927006db is located 11 bytes inside of 16-byte region [0xffff927006d0,0xffff927006e0) +freed by thread T0 here: + #0 0xaaaab5e2c7c4 in realloc (test_progs+0x24c7c4) + #1 0xaaaab634f4a0 in libbpf_reallocarray tools/lib/bpf/libbpf_internal.h:191 + #2 0xaaaab634f840 in libbpf_add_mem tools/lib/bpf/btf.c:163 + #3 0xaaaab636643c in strset_add_str_mem tools/lib/bpf/strset.c:106 + #4 0xaaaab6366560 in strset__add_str tools/lib/bpf/strset.c:157 + #5 0xaaaab6352d70 in btf__add_str tools/lib/bpf/btf.c:1519 + #6 0xaaaab6353e10 in btf__add_field tools/lib/bpf/btf.c:2032 + #7 0xaaaab6084fcc in test_btf_dump_incremental tools/testing/selftests/bpf/prog_tests/btf_dump.c:232 + #8 0xaaaab6097530 in test_btf_dump tools/testing/selftests/bpf/prog_tests/btf_dump.c:875 + #9 0xaaaab6314ed0 in run_one_test tools/testing/selftests/bpf/test_progs.c:1062 + #10 0xaaaab631a0a8 in main tools/testing/selftests/bpf/test_progs.c:1697 + #11 0xffff9676d214 in __libc_start_main ../csu/libc-start.c:308 + #12 0xaaaab5d65990 (test_progs+0x185990) + +previously allocated by thread T0 here: + #0 0xaaaab5e2c7c4 in realloc (test_progs+0x24c7c4) + #1 0xaaaab634f4a0 in libbpf_reallocarray tools/lib/bpf/libbpf_internal.h:191 + #2 0xaaaab634f840 in libbpf_add_mem tools/lib/bpf/btf.c:163 + #3 0xaaaab636643c in strset_add_str_mem tools/lib/bpf/strset.c:106 + #4 0xaaaab6366560 in strset__add_str tools/lib/bpf/strset.c:157 + #5 0xaaaab6352d70 in btf__add_str tools/lib/bpf/btf.c:1519 + #6 0xaaaab6353ff0 in btf_add_enum_common tools/lib/bpf/btf.c:2070 + #7 0xaaaab6354080 in btf__add_enum tools/lib/bpf/btf.c:2102 + #8 0xaaaab6082f50 in test_btf_dump_incremental tools/testing/selftests/bpf/prog_tests/btf_dump.c:162 + #9 0xaaaab6097530 in test_btf_dump tools/testing/selftests/bpf/prog_tests/btf_dump.c:875 + #10 0xaaaab6314ed0 in run_one_test tools/testing/selftests/bpf/test_progs.c:1062 + #11 0xaaaab631a0a8 in main tools/testing/selftests/bpf/test_progs.c:1697 + #12 0xffff9676d214 in __libc_start_main ../csu/libc-start.c:308 + #13 0xaaaab5d65990 (test_progs+0x185990) + +The reason is that the key stored in hash table name_map is a string +address, and the string memory is allocated by realloc() function, when +the memory is resized by realloc() later, the old memory may be freed, +so the address stored in name_map references to a freed memory, causing +use-after-free. + +Fix it by storing duplicated string address in name_map. + +Fixes: 919d2b1dbb07 ("libbpf: Allow modification of BTF and add btf__add_str API") +Signed-off-by: Xu Kuohai +Signed-off-by: Andrii Nakryiko +Acked-by: Martin KaFai Lau +Link: https://lore.kernel.org/bpf/20221011120108.782373-2-xukuohai@huaweicloud.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/btf_dump.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c +index 841cc68e3f42..9bcd75dc12cc 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -215,6 +215,17 @@ static int btf_dump_resize(struct btf_dump *d) + return 0; + } + ++static void btf_dump_free_names(struct hashmap *map) ++{ ++ size_t bkt; ++ struct hashmap_entry *cur; ++ ++ hashmap__for_each_entry(map, cur, bkt) ++ free((void *)cur->key); ++ ++ hashmap__free(map); ++} ++ + void btf_dump__free(struct btf_dump *d) + { + int i; +@@ -233,8 +244,8 @@ void btf_dump__free(struct btf_dump *d) + free(d->cached_names); + free(d->emit_queue); + free(d->decl_stack); +- hashmap__free(d->type_names); +- hashmap__free(d->ident_names); ++ btf_dump_free_names(d->type_names); ++ btf_dump_free_names(d->ident_names); + + free(d); + } +@@ -1457,11 +1468,23 @@ static void btf_dump_emit_type_cast(struct btf_dump *d, __u32 id, + static size_t btf_dump_name_dups(struct btf_dump *d, struct hashmap *name_map, + const char *orig_name) + { ++ char *old_name, *new_name; + size_t dup_cnt = 0; ++ int err; ++ ++ new_name = strdup(orig_name); ++ if (!new_name) ++ return 1; + + hashmap__find(name_map, orig_name, (void **)&dup_cnt); + dup_cnt++; +- hashmap__set(name_map, orig_name, (void *)dup_cnt, NULL, NULL); ++ ++ err = hashmap__set(name_map, new_name, (void *)dup_cnt, ++ (const void **)&old_name, NULL); ++ if (err) ++ free(new_name); ++ ++ free(old_name); + + return dup_cnt; + } +-- +2.35.1 + diff --git a/queue-5.15/libfs-add-define_simple_attribute_signed-for-signed-.patch b/queue-5.15/libfs-add-define_simple_attribute_signed-for-signed-.patch new file mode 100644 index 00000000000..41337b46a84 --- /dev/null +++ b/queue-5.15/libfs-add-define_simple_attribute_signed-for-signed-.patch @@ -0,0 +1,139 @@ +From dfde63bb86a030ee9b021984536dd61d30ee17dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 02:24:16 +0900 +Subject: libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value + +From: Akinobu Mita + +[ Upstream commit 2e41f274f9aa71cdcc69dc1f26a3f9304a651804 ] + +Patch series "fix error when writing negative value to simple attribute +files". + +The simple attribute files do not accept a negative value since the commit +488dac0c9237 ("libfs: fix error cast of negative value in +simple_attr_write()"), but some attribute files want to accept a negative +value. + +This patch (of 3): + +The simple attribute files do not accept a negative value since the commit +488dac0c9237 ("libfs: fix error cast of negative value in +simple_attr_write()"), so we have to use a 64-bit value to write a +negative value. + +This adds DEFINE_SIMPLE_ATTRIBUTE_SIGNED for a signed value. + +Link: https://lkml.kernel.org/r/20220919172418.45257-1-akinobu.mita@gmail.com +Link: https://lkml.kernel.org/r/20220919172418.45257-2-akinobu.mita@gmail.com +Fixes: 488dac0c9237 ("libfs: fix error cast of negative value in simple_attr_write()") +Signed-off-by: Akinobu Mita +Reported-by: Zhao Gongyi +Reviewed-by: David Hildenbrand +Reviewed-by: Greg Kroah-Hartman +Cc: Alexander Viro +Cc: Jonathan Corbet +Cc: Oscar Salvador +Cc: Rafael J. Wysocki +Cc: Shuah Khan +Cc: Wei Yongjun +Cc: Yicong Yang +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/libfs.c | 22 +++++++++++++++++++--- + include/linux/fs.h | 12 ++++++++++-- + 2 files changed, 29 insertions(+), 5 deletions(-) + +diff --git a/fs/libfs.c b/fs/libfs.c +index 51b4de3b3447..7bb5d90319cc 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -967,8 +967,8 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, + EXPORT_SYMBOL_GPL(simple_attr_read); + + /* interpret the buffer as a number to call the set function with */ +-ssize_t simple_attr_write(struct file *file, const char __user *buf, +- size_t len, loff_t *ppos) ++static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos, bool is_signed) + { + struct simple_attr *attr; + unsigned long long val; +@@ -989,7 +989,10 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, + goto out; + + attr->set_buf[size] = '\0'; +- ret = kstrtoull(attr->set_buf, 0, &val); ++ if (is_signed) ++ ret = kstrtoll(attr->set_buf, 0, &val); ++ else ++ ret = kstrtoull(attr->set_buf, 0, &val); + if (ret) + goto out; + ret = attr->set(attr->data, val); +@@ -999,8 +1002,21 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, + mutex_unlock(&attr->mutex); + return ret; + } ++ ++ssize_t simple_attr_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return simple_attr_write_xsigned(file, buf, len, ppos, false); ++} + EXPORT_SYMBOL_GPL(simple_attr_write); + ++ssize_t simple_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ return simple_attr_write_xsigned(file, buf, len, ppos, true); ++} ++EXPORT_SYMBOL_GPL(simple_attr_write_signed); ++ + /** + * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation + * @sb: filesystem to do the file handle conversion on +diff --git a/include/linux/fs.h b/include/linux/fs.h +index d55fdc02f82d..68fcf3ec9cf6 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -3507,7 +3507,7 @@ void simple_transaction_set(struct file *file, size_t n); + * All attributes contain a text representation of a numeric value + * that are accessed with the get() and set() functions. + */ +-#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++#define DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, __is_signed) \ + static int __fops ## _open(struct inode *inode, struct file *file) \ + { \ + __simple_attr_check_format(__fmt, 0ull); \ +@@ -3518,10 +3518,16 @@ static const struct file_operations __fops = { \ + .open = __fops ## _open, \ + .release = simple_attr_release, \ + .read = simple_attr_read, \ +- .write = simple_attr_write, \ ++ .write = (__is_signed) ? simple_attr_write_signed : simple_attr_write, \ + .llseek = generic_file_llseek, \ + } + ++#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ ++ DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, false) ++ ++#define DEFINE_SIMPLE_ATTRIBUTE_SIGNED(__fops, __get, __set, __fmt) \ ++ DEFINE_SIMPLE_ATTRIBUTE_XSIGNED(__fops, __get, __set, __fmt, true) ++ + static inline __printf(1, 2) + void __simple_attr_check_format(const char *fmt, ...) + { +@@ -3536,6 +3542,8 @@ ssize_t simple_attr_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); + ssize_t simple_attr_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos); ++ssize_t simple_attr_write_signed(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos); + + struct ctl_table; + int proc_nr_files(struct ctl_table *table, int write, +-- +2.35.1 + diff --git a/queue-5.15/lockd-set-other-missing-fields-when-unlocking-files.patch b/queue-5.15/lockd-set-other-missing-fields-when-unlocking-files.patch new file mode 100644 index 00000000000..d60fb88a34c --- /dev/null +++ b/queue-5.15/lockd-set-other-missing-fields-when-unlocking-files.patch @@ -0,0 +1,69 @@ +From e87316b46c16c54de78e1dfcf461364909734209 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Nov 2022 14:02:39 -0500 +Subject: lockd: set other missing fields when unlocking files + +From: Trond Myklebust + +[ Upstream commit 18ebd35b61b4693a0ddc270b6d4f18def232e770 ] + +vfs_lock_file() expects the struct file_lock to be fully initialised by +the caller. Re-exported NFSv3 has been seen to Oops if the fl_file field +is NULL. + +Fixes: aec158242b87 ("lockd: set fl_owner when unlocking files") +Signed-off-by: Trond Myklebust +Reviewed-by: Jeff Layton +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216582 +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/lockd/svcsubs.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c +index e1c4617de771..3515f17eaf3f 100644 +--- a/fs/lockd/svcsubs.c ++++ b/fs/lockd/svcsubs.c +@@ -176,7 +176,7 @@ nlm_delete_file(struct nlm_file *file) + } + } + +-static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner) ++static int nlm_unlock_files(struct nlm_file *file, const struct file_lock *fl) + { + struct file_lock lock; + +@@ -184,12 +184,15 @@ static int nlm_unlock_files(struct nlm_file *file, fl_owner_t owner) + lock.fl_type = F_UNLCK; + lock.fl_start = 0; + lock.fl_end = OFFSET_MAX; +- lock.fl_owner = owner; +- if (file->f_file[O_RDONLY] && +- vfs_lock_file(file->f_file[O_RDONLY], F_SETLK, &lock, NULL)) ++ lock.fl_owner = fl->fl_owner; ++ lock.fl_pid = fl->fl_pid; ++ lock.fl_flags = FL_POSIX; ++ ++ lock.fl_file = file->f_file[O_RDONLY]; ++ if (lock.fl_file && vfs_lock_file(lock.fl_file, F_SETLK, &lock, NULL)) + goto out_err; +- if (file->f_file[O_WRONLY] && +- vfs_lock_file(file->f_file[O_WRONLY], F_SETLK, &lock, NULL)) ++ lock.fl_file = file->f_file[O_WRONLY]; ++ if (lock.fl_file && vfs_lock_file(lock.fl_file, F_SETLK, &lock, NULL)) + goto out_err; + return 0; + out_err: +@@ -226,7 +229,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, + if (match(lockhost, host)) { + + spin_unlock(&flctx->flc_lock); +- if (nlm_unlock_files(file, fl->fl_owner)) ++ if (nlm_unlock_files(file, fl)) + return 1; + goto again; + } +-- +2.35.1 + diff --git a/queue-5.15/macintosh-fix-possible-memory-leak-in-macio_add_one_.patch b/queue-5.15/macintosh-fix-possible-memory-leak-in-macio_add_one_.patch new file mode 100644 index 00000000000..d1ce1ee7e5b --- /dev/null +++ b/queue-5.15/macintosh-fix-possible-memory-leak-in-macio_add_one_.patch @@ -0,0 +1,43 @@ +From 01c5096d490cbad8f9435d91043fbe7131139d24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 11:25:51 +0800 +Subject: macintosh: fix possible memory leak in macio_add_one_device() + +From: Yang Yingliang + +[ Upstream commit 5ca86eae55a2f006e6c1edd2029b2cacb6979515 ] + +Afer commit 1fa5ae857bb1 ("driver core: get rid of struct device's +bus_id string array"), the name of device is allocated dynamically. It +needs to be freed when of_device_register() fails. Call put_device() to +give up the reference that's taken in device_initialize(), so that it +can be freed in kobject_cleanup() when the refcount hits 0. + +macio device is freed in macio_release_dev(), so the kfree() can be +removed. + +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221104032551.1075335-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/macintosh/macio_asic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c +index c1fdf2896021..df69d648f6d0 100644 +--- a/drivers/macintosh/macio_asic.c ++++ b/drivers/macintosh/macio_asic.c +@@ -423,7 +423,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, + if (of_device_register(&dev->ofdev) != 0) { + printk(KERN_DEBUG"macio: device registration error for %s!\n", + dev_name(&dev->ofdev.dev)); +- kfree(dev); ++ put_device(&dev->ofdev.dev); + return NULL; + } + +-- +2.35.1 + diff --git a/queue-5.15/macintosh-macio-adb-check-the-return-value-of-iorema.patch b/queue-5.15/macintosh-macio-adb-check-the-return-value-of-iorema.patch new file mode 100644 index 00000000000..bae8be47792 --- /dev/null +++ b/queue-5.15/macintosh-macio-adb-check-the-return-value-of-iorema.patch @@ -0,0 +1,40 @@ +From b14341517c0cba60773a5f41c30923ec5b5fbccd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 15:41:48 +0800 +Subject: macintosh/macio-adb: check the return value of ioremap() + +From: Xie Shaowen + +[ Upstream commit dbaa3105736d4d73063ea0a3b01cd7fafce924e6 ] + +The function ioremap() in macio_init() can fail, so its return value +should be checked. + +Fixes: 36874579dbf4c ("[PATCH] powerpc: macio-adb build fix") +Reported-by: Hacash Robot +Signed-off-by: Xie Shaowen +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220802074148.3213659-1-studentxswpy@163.com +Signed-off-by: Sasha Levin +--- + drivers/macintosh/macio-adb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c +index dc634c2932fd..dd2465586140 100644 +--- a/drivers/macintosh/macio-adb.c ++++ b/drivers/macintosh/macio-adb.c +@@ -105,6 +105,10 @@ int macio_init(void) + return -ENXIO; + } + adb = ioremap(r.start, sizeof(struct adb_regs)); ++ if (!adb) { ++ of_node_put(adbs); ++ return -ENOMEM; ++ } + + out_8(&adb->ctrl.r, 0); + out_8(&adb->intr.r, 0); +-- +2.35.1 + diff --git a/queue-5.15/mailbox-arm_mhuv2-fix-return-value-check-in-mhuv2_pr.patch b/queue-5.15/mailbox-arm_mhuv2-fix-return-value-check-in-mhuv2_pr.patch new file mode 100644 index 00000000000..bf6425a5379 --- /dev/null +++ b/queue-5.15/mailbox-arm_mhuv2-fix-return-value-check-in-mhuv2_pr.patch @@ -0,0 +1,40 @@ +From ce099e496669371fe7324deee4791c0c9a9f3597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 14:35:48 +0800 +Subject: mailbox: arm_mhuv2: Fix return value check in mhuv2_probe() + +From: Yang Yingliang + +[ Upstream commit 165b7643f2df890066b1b4e8a387888a600ca9bf ] + +If devm_of_iomap() fails, it returns ERR_PTR() and never +return NULL, so replace NULL pointer check with IS_ERR() +to fix this problem. + +Fixes: 5a6338cce9f4 ("mailbox: arm_mhuv2: Add driver") +Signed-off-by: Yang Yingliang +Acked-by: Viresh Kumar +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/arm_mhuv2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mailbox/arm_mhuv2.c b/drivers/mailbox/arm_mhuv2.c +index d997f8ebfa98..3af15083a25a 100644 +--- a/drivers/mailbox/arm_mhuv2.c ++++ b/drivers/mailbox/arm_mhuv2.c +@@ -1061,8 +1061,8 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id) + int ret = -EINVAL; + + reg = devm_of_iomap(dev, dev->of_node, 0, NULL); +- if (!reg) +- return -ENOMEM; ++ if (IS_ERR(reg)) ++ return PTR_ERR(reg); + + mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL); + if (!mhu) +-- +2.35.1 + diff --git a/queue-5.15/mailbox-mpfs-read-the-system-controller-s-status.patch b/queue-5.15/mailbox-mpfs-read-the-system-controller-s-status.patch new file mode 100644 index 00000000000..de059f6dc2d --- /dev/null +++ b/queue-5.15/mailbox-mpfs-read-the-system-controller-s-status.patch @@ -0,0 +1,99 @@ +From d261f609f3d05d20cc647346562f2e323be8db81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 17:56:52 +0000 +Subject: mailbox: mpfs: read the system controller's status + +From: Conor Dooley + +[ Upstream commit ab47d0bfdf88faac0eb02749e5bfaa306e004300 ] + +Some services explicitly return an error code in their response, but +others rely on the system controller to set a status in its status +register. The meaning of the bits varies based on what service is +requested, so pass it back up to the driver that requested the service +in the first place. The field in the message struct already existed, but +was unused until now. + +If the system controller is busy, in which case we should never actually +be in the interrupt handler, or if the service fails the mailbox itself +should not be read. Callers should check the status before operating on +the response. + +There's an existing, but unused, #define for the mailbox mask - but it +was incorrect. It was doing a GENMASK_ULL(32, 16) which should've just +been a GENMASK(31, 16), so fix that up and start using it. + +Fixes: 83d7b1560810 ("mbox: add polarfire soc system controller mailbox") +Signed-off-by: Conor Dooley +Reviewed-by: Palmer Dabbelt +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-mpfs.c | 31 ++++++++++++++++++++++++++++--- + 1 file changed, 28 insertions(+), 3 deletions(-) + +diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c +index cfacb3f320a6..853901acaeec 100644 +--- a/drivers/mailbox/mailbox-mpfs.c ++++ b/drivers/mailbox/mailbox-mpfs.c +@@ -2,7 +2,7 @@ + /* + * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver + * +- * Copyright (c) 2020 Microchip Corporation. All rights reserved. ++ * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved. + * + * Author: Conor Dooley + * +@@ -56,7 +56,7 @@ + #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY) + + #define SCB_STATUS_POS (16) +-#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS) ++#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS) + + struct mpfs_mbox { + struct mbox_controller controller; +@@ -130,13 +130,38 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) + struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; + struct mpfs_mss_response *response = mbox->response; + u16 num_words = ALIGN((response->resp_size), (4)) / 4U; +- u32 i; ++ u32 i, status; + + if (!response->resp_msg) { + dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM); + return; + } + ++ /* ++ * The status is stored in bits 31:16 of the SERVICES_SR register. ++ * It is only valid when BUSY == 0. ++ * We should *never* get an interrupt while the controller is ++ * still in the busy state. If we do, something has gone badly ++ * wrong & the content of the mailbox would not be valid. ++ */ ++ if (mpfs_mbox_busy(mbox)) { ++ dev_err(mbox->dev, "got an interrupt but system controller is busy\n"); ++ response->resp_status = 0xDEAD; ++ return; ++ } ++ ++ status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); ++ ++ /* ++ * If the status of the individual servers is non-zero, the service has ++ * failed. The contents of the mailbox at this point are not be valid, ++ * so don't bother reading them. Set the status so that the driver ++ * implementing the service can handle the result. ++ */ ++ response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS; ++ if (response->resp_status) ++ return; ++ + if (!mpfs_mbox_busy(mbox)) { + for (i = 0; i < num_words; i++) { + response->resp_msg[i] = +-- +2.35.1 + diff --git a/queue-5.15/mailbox-zynq-ipi-fix-error-handling-while-device_reg.patch b/queue-5.15/mailbox-zynq-ipi-fix-error-handling-while-device_reg.patch new file mode 100644 index 00000000000..c1d6ff31fce --- /dev/null +++ b/queue-5.15/mailbox-zynq-ipi-fix-error-handling-while-device_reg.patch @@ -0,0 +1,52 @@ +From b6e2bfce6dec19dab3a4cd18c7c0755ddff9318e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 23:08:22 +0800 +Subject: mailbox: zynq-ipi: fix error handling while device_register() fails + +From: Yang Yingliang + +[ Upstream commit a6792a0cdef0b1c2d77920246283a72537e60e94 ] + +If device_register() fails, it has two issues: +1. The name allocated by dev_set_name() is leaked. +2. The parent of device is not NULL, device_unregister() is called + in zynqmp_ipi_free_mboxes(), it will lead a kernel crash because + of removing not added device. + +Call put_device() to give up the reference, so the name is freed in +kobject_cleanup(). Add device registered check in zynqmp_ipi_free_mboxes() +to avoid null-ptr-deref. + +Fixes: 4981b82ba2ff ("mailbox: ZynqMP IPI mailbox controller") +Signed-off-by: Yang Yingliang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/zynqmp-ipi-mailbox.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c +index f44079d62b1a..527204c6d5cd 100644 +--- a/drivers/mailbox/zynqmp-ipi-mailbox.c ++++ b/drivers/mailbox/zynqmp-ipi-mailbox.c +@@ -493,6 +493,7 @@ static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox, + ret = device_register(&ipi_mbox->dev); + if (ret) { + dev_err(dev, "Failed to register ipi mbox dev.\n"); ++ put_device(&ipi_mbox->dev); + return ret; + } + mdev = &ipi_mbox->dev; +@@ -619,7 +620,8 @@ static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata) + ipi_mbox = &pdata->ipi_mboxes[i]; + if (ipi_mbox->dev.parent) { + mbox_controller_unregister(&ipi_mbox->mbox); +- device_unregister(&ipi_mbox->dev); ++ if (device_is_registered(&ipi_mbox->dev)) ++ device_unregister(&ipi_mbox->dev); + } + } + } +-- +2.35.1 + diff --git a/queue-5.15/mcb-mcb-parse-fix-error-handing-in-chameleon_parse_g.patch b/queue-5.15/mcb-mcb-parse-fix-error-handing-in-chameleon_parse_g.patch new file mode 100644 index 00000000000..24232facdf3 --- /dev/null +++ b/queue-5.15/mcb-mcb-parse-fix-error-handing-in-chameleon_parse_g.patch @@ -0,0 +1,40 @@ +From bf67512f1f8b1ffd4d9a6a28d45de1ef818faa20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 01:38:50 -0800 +Subject: mcb: mcb-parse: fix error handing in chameleon_parse_gdd() + +From: Yang Yingliang + +[ Upstream commit 728ac3389296caf68638628c987aeae6c8851e2d ] + +If mcb_device_register() returns error in chameleon_parse_gdd(), the refcount +of bus and device name are leaked. Fix this by calling put_device() to give up +the reference, so they can be released in mcb_release_dev() and kobject_cleanup(). + +Fixes: 3764e82e5150 ("drivers: Introduce MEN Chameleon Bus") +Reviewed-by: Johannes Thumshirn +Signed-off-by: Yang Yingliang +Signed-off-by: Johannes Thumshirn +Link: https://lore.kernel.org/r/ebfb06e39b19272f0197fa9136b5e4b6f34ad732.1669624063.git.johannes.thumshirn@wdc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/mcb/mcb-parse.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c +index 0266bfddfbe2..aa6938da0db8 100644 +--- a/drivers/mcb/mcb-parse.c ++++ b/drivers/mcb/mcb-parse.c +@@ -108,7 +108,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus, + return 0; + + err: +- mcb_free_dev(mdev); ++ put_device(&mdev->dev); + + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/md-raid1-stop-mdx_raid1-thread-when-raid1-array-run-.patch b/queue-5.15/md-raid1-stop-mdx_raid1-thread-when-raid1-array-run-.patch new file mode 100644 index 00000000000..e30b6f0dc79 --- /dev/null +++ b/queue-5.15/md-raid1-stop-mdx_raid1-thread-when-raid1-array-run-.patch @@ -0,0 +1,71 @@ +From e9fc9cde9c1f9c36d6c631bdfe170553b0e3c935 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 22:16:59 +0800 +Subject: md/raid1: stop mdx_raid1 thread when raid1 array run failed + +From: Jiang Li + +[ Upstream commit b611ad14006e5be2170d9e8e611bf49dff288911 ] + +fail run raid1 array when we assemble array with the inactive disk only, +but the mdx_raid1 thread were not stop, Even if the associated resources +have been released. it will caused a NULL dereference when we do poweroff. + +This causes the following Oops: + [ 287.587787] BUG: kernel NULL pointer dereference, address: 0000000000000070 + [ 287.594762] #PF: supervisor read access in kernel mode + [ 287.599912] #PF: error_code(0x0000) - not-present page + [ 287.605061] PGD 0 P4D 0 + [ 287.607612] Oops: 0000 [#1] SMP NOPTI + [ 287.611287] CPU: 3 PID: 5265 Comm: md0_raid1 Tainted: G U 5.10.146 #0 + [ 287.619029] Hardware name: xxxxxxx/To be filled by O.E.M, BIOS 5.19 06/16/2022 + [ 287.626775] RIP: 0010:md_check_recovery+0x57/0x500 [md_mod] + [ 287.632357] Code: fe 01 00 00 48 83 bb 10 03 00 00 00 74 08 48 89 ...... + [ 287.651118] RSP: 0018:ffffc90000433d78 EFLAGS: 00010202 + [ 287.656347] RAX: 0000000000000000 RBX: ffff888105986800 RCX: 0000000000000000 + [ 287.663491] RDX: ffffc90000433bb0 RSI: 00000000ffffefff RDI: ffff888105986800 + [ 287.670634] RBP: ffffc90000433da0 R08: 0000000000000000 R09: c0000000ffffefff + [ 287.677771] R10: 0000000000000001 R11: ffffc90000433ba8 R12: ffff888105986800 + [ 287.684907] R13: 0000000000000000 R14: fffffffffffffe00 R15: ffff888100b6b500 + [ 287.692052] FS: 0000000000000000(0000) GS:ffff888277f80000(0000) knlGS:0000000000000000 + [ 287.700149] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [ 287.705897] CR2: 0000000000000070 CR3: 000000000320a000 CR4: 0000000000350ee0 + [ 287.713033] Call Trace: + [ 287.715498] raid1d+0x6c/0xbbb [raid1] + [ 287.719256] ? __schedule+0x1ff/0x760 + [ 287.722930] ? schedule+0x3b/0xb0 + [ 287.726260] ? schedule_timeout+0x1ed/0x290 + [ 287.730456] ? __switch_to+0x11f/0x400 + [ 287.734219] md_thread+0xe9/0x140 [md_mod] + [ 287.738328] ? md_thread+0xe9/0x140 [md_mod] + [ 287.742601] ? wait_woken+0x80/0x80 + [ 287.746097] ? md_register_thread+0xe0/0xe0 [md_mod] + [ 287.751064] kthread+0x11a/0x140 + [ 287.754300] ? kthread_park+0x90/0x90 + [ 287.757974] ret_from_fork+0x1f/0x30 + +In fact, when raid1 array run fail, we need to do +md_unregister_thread() before raid1_free(). + +Signed-off-by: Jiang Li +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid1.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c +index 9fa479493642..783763f6845f 100644 +--- a/drivers/md/raid1.c ++++ b/drivers/md/raid1.c +@@ -3141,6 +3141,7 @@ static int raid1_run(struct mddev *mddev) + * RAID1 needs at least one disk in active + */ + if (conf->raid_disks - mddev->degraded < 1) { ++ md_unregister_thread(&conf->thread); + ret = -EINVAL; + goto abort; + } +-- +2.35.1 + diff --git a/queue-5.15/media-adv748x-afe-select-input-port-when-initializin.patch b/queue-5.15/media-adv748x-afe-select-input-port-when-initializin.patch new file mode 100644 index 00000000000..068bdd60db3 --- /dev/null +++ b/queue-5.15/media-adv748x-afe-select-input-port-when-initializin.patch @@ -0,0 +1,48 @@ +From 67d19cc2d12fca58b81fefa8fcbb8c1177a6da40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Oct 2022 16:41:46 +0200 +Subject: media: adv748x: afe: Select input port when initializing AFE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Niklas Söderlund + +[ Upstream commit 23ddb85dafefdace1ad79d1a30b0a4e7c4b5cd8d ] + +When moving the input selection to adv748x_reset() it was missed that +during probe the device is reset _before_ the initialization and parsing +of DT by the AFE subdevice. This can lead to the wrong input port (in +case it's not port 0) being selected until the device is reset for the +first time. + +Fix this by restoring the call to adv748x_afe_s_input() in the AFE +initialization while also keeping it in the adv748x_reset(). + +Fixes: c30ed81afe89 ("media: adv748x: afe: Select input port when device is reset") +Signed-off-by: Niklas Söderlund +Reviewed-by: Kieran Bingham +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/adv748x/adv748x-afe.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/media/i2c/adv748x/adv748x-afe.c b/drivers/media/i2c/adv748x/adv748x-afe.c +index 02eabe10ab97..00095c7762c2 100644 +--- a/drivers/media/i2c/adv748x/adv748x-afe.c ++++ b/drivers/media/i2c/adv748x/adv748x-afe.c +@@ -521,6 +521,10 @@ int adv748x_afe_init(struct adv748x_afe *afe) + } + } + ++ adv748x_afe_s_input(afe, afe->input); ++ ++ adv_dbg(state, "AFE Default input set to %d\n", afe->input); ++ + /* Entity pads and sinks are 0-indexed to match the pads */ + for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++) + afe->pads[i].flags = MEDIA_PAD_FL_SINK; +-- +2.35.1 + diff --git a/queue-5.15/media-c8sectpfe-add-of_node_put-when-breaking-out-of.patch b/queue-5.15/media-c8sectpfe-add-of_node_put-when-breaking-out-of.patch new file mode 100644 index 00000000000..39c7b36f036 --- /dev/null +++ b/queue-5.15/media-c8sectpfe-add-of_node_put-when-breaking-out-of.patch @@ -0,0 +1,36 @@ +From 1047cad6a5d0929e8caab96eacf861d3aa439434 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jul 2022 22:10:23 +0800 +Subject: media: c8sectpfe: Add of_node_put() when breaking out of loop + +From: Liang He + +[ Upstream commit 63ff05a1ad242a5a0f897921c87b70d601bda59c ] + +In configure_channels(), we should call of_node_put() when breaking +out of for_each_child_of_node() which will automatically increase +and decrease the refcount. + +Fixes: c5f5d0f99794 ("[media] c8sectpfe: STiH407/10 Linux DVB demux support") +Signed-off-by: Liang He +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +index 338b205ae3a7..88d0188397e7 100644 +--- a/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c ++++ b/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c +@@ -940,6 +940,7 @@ static int configure_channels(struct c8sectpfei *fei) + if (ret) { + dev_err(fei->dev, + "configure_memdma_and_inputblock failed\n"); ++ of_node_put(child); + goto err_unmap; + } + index++; +-- +2.35.1 + diff --git a/queue-5.15/media-camss-clean-up-received-buffers-on-failed-star.patch b/queue-5.15/media-camss-clean-up-received-buffers-on-failed-star.patch new file mode 100644 index 00000000000..216211bca28 --- /dev/null +++ b/queue-5.15/media-camss-clean-up-received-buffers-on-failed-star.patch @@ -0,0 +1,62 @@ +From 7806eb0e3bcae8d36cf2fe6057945ef2f207b474 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 10:44:37 +0100 +Subject: media: camss: Clean up received buffers on failed start of streaming + +From: Vladimir Zapolskiy + +[ Upstream commit c8f3582345e6a69da65ab588f7c4c2d1685b0e80 ] + +It is required to return the received buffers, if streaming can not be +started. For instance media_pipeline_start() may fail with EPIPE, if +a link validation between entities is not passed, and in such a case +a user gets a kernel warning: + + WARNING: CPU: 1 PID: 520 at drivers/media/common/videobuf2/videobuf2-core.c:1592 vb2_start_streaming+0xec/0x160 + + Call trace: + vb2_start_streaming+0xec/0x160 + vb2_core_streamon+0x9c/0x1a0 + vb2_ioctl_streamon+0x68/0xbc + v4l_streamon+0x30/0x3c + __video_do_ioctl+0x184/0x3e0 + video_usercopy+0x37c/0x7b0 + video_ioctl2+0x24/0x40 + v4l2_ioctl+0x4c/0x70 + +The fix is to correct the error path in video_start_streaming() of camss. + +Fixes: 0ac2586c410f ("media: camss: Add files which handle the video device nodes") +Signed-off-by: Vladimir Zapolskiy +Reviewed-by: Robert Foss +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/camss/camss-video.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c +index f282275af626..5173b79995ee 100644 +--- a/drivers/media/platform/qcom/camss/camss-video.c ++++ b/drivers/media/platform/qcom/camss/camss-video.c +@@ -493,7 +493,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) + + ret = media_pipeline_start(&vdev->entity, &video->pipe); + if (ret < 0) +- return ret; ++ goto flush_buffers; + + ret = video_check_format(video); + if (ret < 0) +@@ -522,6 +522,7 @@ static int video_start_streaming(struct vb2_queue *q, unsigned int count) + error: + media_pipeline_stop(&vdev->entity); + ++flush_buffers: + video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED); + + return ret; +-- +2.35.1 + diff --git a/queue-5.15/media-coda-add-check-for-dcoda_iram_alloc.patch b/queue-5.15/media-coda-add-check-for-dcoda_iram_alloc.patch new file mode 100644 index 00000000000..7769059c838 --- /dev/null +++ b/queue-5.15/media-coda-add-check-for-dcoda_iram_alloc.patch @@ -0,0 +1,47 @@ +From 8ebc694bf99b6f77813ad1acdf24e5db2a22900c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 14:56:52 +0800 +Subject: media: coda: Add check for dcoda_iram_alloc + +From: Jiasheng Jiang + +[ Upstream commit 6b8082238fb8bb20f67e46388123e67a5bbc558d ] + +As the coda_iram_alloc may return NULL pointer, +it should be better to check the return value +in order to avoid NULL poineter dereference, +same as the others. + +Fixes: b313bcc9a467 ("[media] coda: simplify IRAM setup") +Signed-off-by: Jiasheng Jiang +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/coda/coda-bit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c +index c484c008ab02..284608845b85 100644 +--- a/drivers/media/platform/coda/coda-bit.c ++++ b/drivers/media/platform/coda/coda-bit.c +@@ -852,7 +852,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) + /* Only H.264BP and H.263P3 are considered */ + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64); + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64); +- if (!iram_info->buf_dbk_c_use) ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) + goto out; + iram_info->axi_sram_use |= dbk_bits; + +@@ -876,7 +876,7 @@ static void coda_setup_iram(struct coda_ctx *ctx) + + iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128); + iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128); +- if (!iram_info->buf_dbk_c_use) ++ if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use) + goto out; + iram_info->axi_sram_use |= dbk_bits; + +-- +2.35.1 + diff --git a/queue-5.15/media-coda-add-check-for-kmalloc.patch b/queue-5.15/media-coda-add-check-for-kmalloc.patch new file mode 100644 index 00000000000..0e6ad1bd541 --- /dev/null +++ b/queue-5.15/media-coda-add-check-for-kmalloc.patch @@ -0,0 +1,48 @@ +From 0574080de0d88020c647932357b8111f3fe580f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:02:36 +0800 +Subject: media: coda: Add check for kmalloc + +From: Jiasheng Jiang + +[ Upstream commit 6e5e5defdb8b0186312c2f855ace175aee6daf9b ] + +As the kmalloc may return NULL pointer, +it should be better to check the return value +in order to avoid NULL poineter dereference, +same as the others. + +Fixes: cb1d3a336371 ("[media] coda: add CODA7541 JPEG support") +Signed-off-by: Jiasheng Jiang +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/coda/coda-bit.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c +index 284608845b85..582a6c581f3c 100644 +--- a/drivers/media/platform/coda/coda-bit.c ++++ b/drivers/media/platform/coda/coda-bit.c +@@ -1082,10 +1082,16 @@ static int coda_start_encoding(struct coda_ctx *ctx) + } + + if (dst_fourcc == V4L2_PIX_FMT_JPEG) { +- if (!ctx->params.jpeg_qmat_tab[0]) ++ if (!ctx->params.jpeg_qmat_tab[0]) { + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); + } + +-- +2.35.1 + diff --git a/queue-5.15/media-coda-jpeg-add-check-for-kmalloc.patch b/queue-5.15/media-coda-jpeg-add-check-for-kmalloc.patch new file mode 100644 index 00000000000..14f380d8d9f --- /dev/null +++ b/queue-5.15/media-coda-jpeg-add-check-for-kmalloc.patch @@ -0,0 +1,47 @@ +From deed9c8dd476bc79a9ab7c89aeaf8bd373f2eab1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 09:28:13 +0800 +Subject: media: coda: jpeg: Add check for kmalloc + +From: Jiasheng Jiang + +[ Upstream commit f30ce3d3760b22ee33c8d9c2e223764ad30bdc5f ] + +As kmalloc can return NULL pointer, it should be better to +check the return value and return error, same as +coda_jpeg_decode_header. + +Fixes: 96f6f62c4656 ("media: coda: jpeg: add CODA960 JPEG encoder support") +Signed-off-by: Jiasheng Jiang +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/coda/coda-jpeg.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c +index a72f4655e5ad..b7bf529f18f7 100644 +--- a/drivers/media/platform/coda/coda-jpeg.c ++++ b/drivers/media/platform/coda/coda-jpeg.c +@@ -1052,10 +1052,16 @@ static int coda9_jpeg_start_encoding(struct coda_ctx *ctx) + v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n"); + return ret; + } +- if (!ctx->params.jpeg_qmat_tab[0]) ++ if (!ctx->params.jpeg_qmat_tab[0]) { + ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL); +- if (!ctx->params.jpeg_qmat_tab[1]) ++ if (!ctx->params.jpeg_qmat_tab[0]) ++ return -ENOMEM; ++ } ++ if (!ctx->params.jpeg_qmat_tab[1]) { + ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL); ++ if (!ctx->params.jpeg_qmat_tab[1]) ++ return -ENOMEM; ++ } + coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality); + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/media-dvb-core-fix-ignored-return-value-in-dvb_regis.patch b/queue-5.15/media-dvb-core-fix-ignored-return-value-in-dvb_regis.patch new file mode 100644 index 00000000000..07319ed30e8 --- /dev/null +++ b/queue-5.15/media-dvb-core-fix-ignored-return-value-in-dvb_regis.patch @@ -0,0 +1,71 @@ +From e06bce6dd5d937ce2a2dc11b44761c0767775fb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 03:30:05 +0000 +Subject: media: dvb-core: Fix ignored return value in dvb_register_frontend() + +From: Chen Zhongjin + +[ Upstream commit a574359e2e71ce16be212df3a082ed60a4bd2c5f ] + +In dvb_register_frontend(), dvb_register_device() is possible to fail +but its return value is ignored. + +It will cause use-after-free when module is removed, because in +dvb_unregister_frontend() it tries to unregister a not registered +device. + +BUG: KASAN: use-after-free in dvb_remove_device+0x18b/0x1f0 [dvb_core] +Read of size 4 at addr ffff88800dff4824 by task rmmod/428 +CPU: 3 PID: 428 Comm: rmmod +Call Trace: + + ... + dvb_remove_device+0x18b/0x1f0 [dvb_core] + dvb_unregister_frontend+0x7b/0x130 [dvb_core] + vidtv_bridge_remove+0x6e/0x160 [dvb_vidtv_bridge] + ... + +Fix this by catching return value of dvb_register_device(). +However the fe->refcount can't be put to zero immediately, because +there are still modules calling dvb_frontend_detach() when +dvb_register_frontend() fails. + +Link: https://lore.kernel.org/linux-media/20221108033005.169095-1-chenzhongjin@huawei.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Chen Zhongjin +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/dvb-core/dvb_frontend.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c +index 258637d762d6..70d07cdcb2a6 100644 +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -2985,6 +2985,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb, + .name = fe->ops.info.name, + #endif + }; ++ int ret; + + dev_dbg(dvb->device, "%s:\n", __func__); + +@@ -3018,8 +3019,13 @@ int dvb_register_frontend(struct dvb_adapter *dvb, + "DVB: registering adapter %i frontend %i (%s)...\n", + fe->dvb->num, fe->id, fe->ops.info.name); + +- dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, ++ ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template, + fe, DVB_DEVICE_FRONTEND, 0); ++ if (ret) { ++ dvb_frontend_put(fe); ++ mutex_unlock(&frontend_mutex); ++ return ret; ++ } + + /* + * Initialize the cache to the proper values according with the +-- +2.35.1 + diff --git a/queue-5.15/media-dvb-frontends-fix-leak-of-memory-fw.patch b/queue-5.15/media-dvb-frontends-fix-leak-of-memory-fw.patch new file mode 100644 index 00000000000..5a62fb3b98e --- /dev/null +++ b/queue-5.15/media-dvb-frontends-fix-leak-of-memory-fw.patch @@ -0,0 +1,32 @@ +From 34aa5c6408e52ff60524587bb6fd4f18e291300e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 10 Apr 2022 07:19:25 +0100 +Subject: media: dvb-frontends: fix leak of memory fw + +From: Yan Lei + +[ Upstream commit a15fe8d9f1bf460a804bcf18a890bfd2cf0d5caa ] + +Link: https://lore.kernel.org/linux-media/20220410061925.4107-1-chinayanlei2002@163.com +Signed-off-by: Yan Lei +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/dvb-frontends/bcm3510.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c +index da0ff7b44da4..68b92b4419cf 100644 +--- a/drivers/media/dvb-frontends/bcm3510.c ++++ b/drivers/media/dvb-frontends/bcm3510.c +@@ -649,6 +649,7 @@ static int bcm3510_download_firmware(struct dvb_frontend* fe) + deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size); + if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) { + err("firmware download failed: %d\n",ret); ++ release_firmware(fw); + return ret; + } + i += 4 + len; +-- +2.35.1 + diff --git a/queue-5.15/media-dvb-usb-az6027-fix-null-ptr-deref-in-az6027_i2.patch b/queue-5.15/media-dvb-usb-az6027-fix-null-ptr-deref-in-az6027_i2.patch new file mode 100644 index 00000000000..289f1097cfb --- /dev/null +++ b/queue-5.15/media-dvb-usb-az6027-fix-null-ptr-deref-in-az6027_i2.patch @@ -0,0 +1,64 @@ +From 881d7df94e596cf4aa1dfb01d0b7efd3428b4bd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 06:59:18 +0000 +Subject: media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer() + +From: Baisong Zhong + +[ Upstream commit 0ed554fd769a19ea8464bb83e9ac201002ef74ad ] + +Wei Chen reports a kernel bug as blew: + +general protection fault, probably for non-canonical address +KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017] +... +Call Trace: + +__i2c_transfer+0x77e/0x1930 drivers/i2c/i2c-core-base.c:2109 +i2c_transfer+0x1d5/0x3d0 drivers/i2c/i2c-core-base.c:2170 +i2cdev_ioctl_rdwr+0x393/0x660 drivers/i2c/i2c-dev.c:297 +i2cdev_ioctl+0x75d/0x9f0 drivers/i2c/i2c-dev.c:458 +vfs_ioctl fs/ioctl.c:51 [inline] +__do_sys_ioctl fs/ioctl.c:870 [inline] +__se_sys_ioctl+0xfb/0x170 fs/ioctl.c:856 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x3d/0x90 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd +RIP: 0033:0x7fd834a8bded + +In az6027_i2c_xfer(), if msg[i].addr is 0x99, +a null-ptr-deref will caused when accessing msg[i].buf. +For msg[i].len is 0 and msg[i].buf is null. + +Fix this by checking msg[i].len in az6027_i2c_xfer(). + +Link: https://lore.kernel.org/lkml/CAO4mrfcPHB5aQJO=mpqV+p8mPLNg-Fok0gw8gZ=zemAfMGTzMg@mail.gmail.com/ + +Link: https://lore.kernel.org/linux-media/20221120065918.2160782-1-zhongbaisong@huawei.com +Fixes: 76f9a820c867 ("V4L/DVB: AZ6027: Initial import of the driver") +Reported-by: Wei Chen +Signed-off-by: Baisong Zhong +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/dvb-usb/az6027.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c +index 86788771175b..32b4ee65c280 100644 +--- a/drivers/media/usb/dvb-usb/az6027.c ++++ b/drivers/media/usb/dvb-usb/az6027.c +@@ -975,6 +975,10 @@ static int az6027_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], int n + if (msg[i].addr == 0x99) { + req = 0xBE; + index = 0; ++ if (msg[i].len < 1) { ++ i = -EOPNOTSUPP; ++ break; ++ } + value = msg[i].buf[0] & 0x00ff; + length = 1; + az6027_usb_out_op(d, req, value, index, data, length); +-- +2.35.1 + diff --git a/queue-5.15/media-dvb-usb-fix-memory-leak-in-dvb_usb_adapter_ini.patch b/queue-5.15/media-dvb-usb-fix-memory-leak-in-dvb_usb_adapter_ini.patch new file mode 100644 index 00000000000..53d157fba26 --- /dev/null +++ b/queue-5.15/media-dvb-usb-fix-memory-leak-in-dvb_usb_adapter_ini.patch @@ -0,0 +1,97 @@ +From 26af189b17501aae3721ff9ce51c956785a97ed0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 02:21:52 +0100 +Subject: media: dvb-usb: fix memory leak in dvb_usb_adapter_init() + +From: Mazin Al Haddad + +[ Upstream commit 94d90fb06b94a90c176270d38861bcba34ce377d ] + +Syzbot reports a memory leak in "dvb_usb_adapter_init()". +The leak is due to not accounting for and freeing current iteration's +adapter->priv in case of an error. Currently if an error occurs, +it will exit before incrementing "num_adapters_initalized", +which is used as a reference counter to free all adap->priv +in "dvb_usb_adapter_exit()". There are multiple error paths that +can exit from before incrementing the counter. Including the +error handling paths for "dvb_usb_adapter_stream_init()", +"dvb_usb_adapter_dvb_init()" and "dvb_usb_adapter_frontend_init()" +within "dvb_usb_adapter_init()". + +This means that in case of an error in any of these functions the +current iteration is not accounted for and the current iteration's +adap->priv is not freed. + +Fix this by freeing the current iteration's adap->priv in the +"stream_init_err:" label in the error path. The rest of the +(accounted for) adap->priv objects are freed in dvb_usb_adapter_exit() +as expected using the num_adapters_initalized variable. + +Syzbot report: + +BUG: memory leak +unreferenced object 0xffff8881172f1a00 (size 512): + comm "kworker/0:2", pid 139, jiffies 4294994873 (age 10.960s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +backtrace: + [] dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:75 [inline] + [] dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:184 [inline] + [] dvb_usb_device_init.cold+0x4e5/0x79e drivers/media/usb/dvb-usb/dvb-usb-init.c:308 + [] dib0700_probe+0x8d/0x1b0 drivers/media/usb/dvb-usb/dib0700_core.c:883 + [] usb_probe_interface+0x177/0x370 drivers/usb/core/driver.c:396 + [] call_driver_probe drivers/base/dd.c:542 [inline] + [] really_probe.part.0+0xe7/0x310 drivers/base/dd.c:621 + [] really_probe drivers/base/dd.c:583 [inline] + [] __driver_probe_device+0x10c/0x1e0 drivers/base/dd.c:752 + [] driver_probe_device+0x2a/0x120 drivers/base/dd.c:782 + [] __device_attach_driver+0xf6/0x140 drivers/base/dd.c:899 + [] bus_for_each_drv+0xb7/0x100 drivers/base/bus.c:427 + [] __device_attach+0x122/0x260 drivers/base/dd.c:970 + [] bus_probe_device+0xc6/0xe0 drivers/base/bus.c:487 + [] device_add+0x5fb/0xdf0 drivers/base/core.c:3405 + [] usb_set_configuration+0x8f2/0xb80 drivers/usb/core/message.c:2170 + [] usb_generic_driver_probe+0x8c/0xc0 drivers/usb/core/generic.c:238 + [] usb_probe_device+0x5c/0x140 drivers/usb/core/driver.c:293 + [] call_driver_probe drivers/base/dd.c:542 [inline] + [] really_probe.part.0+0xe7/0x310 drivers/base/dd.c:621 + [] really_probe drivers/base/dd.c:583 [inline] + [] __driver_probe_device+0x10c/0x1e0 drivers/base/dd.c:752 + +Link: https://syzkaller.appspot.com/bug?extid=f66dd31987e6740657be +Reported-and-tested-by: syzbot+f66dd31987e6740657be@syzkaller.appspotmail.com + +Link: https://lore.kernel.org/linux-media/20220824012152.539788-1-mazinalhaddad05@gmail.com +Signed-off-by: Mazin Al Haddad +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/dvb-usb/dvb-usb-init.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c +index 61439c8f33ca..58eea8ab5477 100644 +--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c ++++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c +@@ -81,7 +81,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) + + ret = dvb_usb_adapter_stream_init(adap); + if (ret) +- return ret; ++ goto stream_init_err; + + ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs); + if (ret) +@@ -114,6 +114,8 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs) + dvb_usb_adapter_dvb_exit(adap); + dvb_init_err: + dvb_usb_adapter_stream_exit(adap); ++stream_init_err: ++ kfree(adap->priv); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/media-dvbdev-adopts-refcnt-to-avoid-uaf.patch b/queue-5.15/media-dvbdev-adopts-refcnt-to-avoid-uaf.patch new file mode 100644 index 00000000000..d3ca633b7ba --- /dev/null +++ b/queue-5.15/media-dvbdev-adopts-refcnt-to-avoid-uaf.patch @@ -0,0 +1,210 @@ +From 8b472a53318d331865138fb1019ca0192deb2f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Aug 2022 15:59:52 +0100 +Subject: media: dvbdev: adopts refcnt to avoid UAF + +From: Lin Ma + +[ Upstream commit 0fc044b2b5e2d05a1fa1fb0d7f270367a7855d79 ] + +dvb_unregister_device() is known that prone to use-after-free. +That is, the cleanup from dvb_unregister_device() releases the dvb_device +even if there are pointers stored in file->private_data still refer to it. + +This patch adds a reference counter into struct dvb_device and delays its +deallocation until no pointer refers to the object. + +Link: https://lore.kernel.org/linux-media/20220807145952.10368-1-linma@zju.edu.cn +Signed-off-by: Lin Ma +Reported-by: kernel test robot +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/dvb-core/dvb_ca_en50221.c | 2 +- + drivers/media/dvb-core/dvb_frontend.c | 2 +- + drivers/media/dvb-core/dvbdev.c | 32 +++++++++++++++++++------ + include/media/dvbdev.h | 31 +++++++++++++----------- + 4 files changed, 44 insertions(+), 23 deletions(-) + +diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c +index 15a08d8c69ef..c2d2792227f8 100644 +--- a/drivers/media/dvb-core/dvb_ca_en50221.c ++++ b/drivers/media/dvb-core/dvb_ca_en50221.c +@@ -157,7 +157,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca) + { + unsigned int i; + +- dvb_free_device(ca->dvbdev); ++ dvb_device_put(ca->dvbdev); + for (i = 0; i < ca->slot_count; i++) + vfree(ca->slot_info[i].rx_buffer.data); + +diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c +index 70d07cdcb2a6..09facc78d88a 100644 +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -136,7 +136,7 @@ static void __dvb_frontend_free(struct dvb_frontend *fe) + struct dvb_frontend_private *fepriv = fe->frontend_priv; + + if (fepriv) +- dvb_free_device(fepriv->dvbdev); ++ dvb_device_put(fepriv->dvbdev); + + dvb_frontend_invoke_release(fe, fe->ops.release); + +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index 795d9bfaba5c..6406653e46a4 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -107,7 +107,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) + new_fops = fops_get(dvbdev->fops); + if (!new_fops) + goto fail; +- file->private_data = dvbdev; ++ file->private_data = dvb_device_get(dvbdev); + replace_fops(file, new_fops); + if (file->f_op->open) + err = file->f_op->open(inode, file); +@@ -171,6 +171,9 @@ int dvb_generic_release(struct inode *inode, struct file *file) + } + + dvbdev->users++; ++ ++ dvb_device_put(dvbdev); ++ + return 0; + } + EXPORT_SYMBOL(dvb_generic_release); +@@ -487,6 +490,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + return -ENOMEM; + } + ++ kref_init(&dvbdev->ref); + memcpy(dvbdev, template, sizeof(struct dvb_device)); + dvbdev->type = type; + dvbdev->id = id; +@@ -518,7 +522,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + #endif + + dvbdev->minor = minor; +- dvb_minors[minor] = dvbdev; ++ dvb_minors[minor] = dvb_device_get(dvbdev); + up_write(&minor_rwsem); + + ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); +@@ -563,6 +567,7 @@ void dvb_remove_device(struct dvb_device *dvbdev) + + down_write(&minor_rwsem); + dvb_minors[dvbdev->minor] = NULL; ++ dvb_device_put(dvbdev); + up_write(&minor_rwsem); + + dvb_media_device_free(dvbdev); +@@ -574,21 +579,34 @@ void dvb_remove_device(struct dvb_device *dvbdev) + EXPORT_SYMBOL(dvb_remove_device); + + +-void dvb_free_device(struct dvb_device *dvbdev) ++static void dvb_free_device(struct kref *ref) + { +- if (!dvbdev) +- return; ++ struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref); + + kfree (dvbdev->fops); + kfree (dvbdev); + } +-EXPORT_SYMBOL(dvb_free_device); ++ ++ ++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev) ++{ ++ kref_get(&dvbdev->ref); ++ return dvbdev; ++} ++EXPORT_SYMBOL(dvb_device_get); ++ ++ ++void dvb_device_put(struct dvb_device *dvbdev) ++{ ++ if (dvbdev) ++ kref_put(&dvbdev->ref, dvb_free_device); ++} + + + void dvb_unregister_device(struct dvb_device *dvbdev) + { + dvb_remove_device(dvbdev); +- dvb_free_device(dvbdev); ++ dvb_device_put(dvbdev); + } + EXPORT_SYMBOL(dvb_unregister_device); + +diff --git a/include/media/dvbdev.h b/include/media/dvbdev.h +index 2f6b0861322a..149b3d33c24b 100644 +--- a/include/media/dvbdev.h ++++ b/include/media/dvbdev.h +@@ -156,6 +156,7 @@ struct dvb_adapter { + */ + struct dvb_device { + struct list_head list_head; ++ struct kref ref; + const struct file_operations *fops; + struct dvb_adapter *adapter; + enum dvb_device_type type; +@@ -187,6 +188,20 @@ struct dvb_device { + void *priv; + }; + ++/** ++ * dvb_device_get - Increase dvb_device reference ++ * ++ * @dvbdev: pointer to struct dvb_device ++ */ ++struct dvb_device *dvb_device_get(struct dvb_device *dvbdev); ++ ++/** ++ * dvb_device_get - Decrease dvb_device reference ++ * ++ * @dvbdev: pointer to struct dvb_device ++ */ ++void dvb_device_put(struct dvb_device *dvbdev); ++ + /** + * dvb_register_adapter - Registers a new DVB adapter + * +@@ -231,29 +246,17 @@ int dvb_register_device(struct dvb_adapter *adap, + /** + * dvb_remove_device - Remove a registered DVB device + * +- * This does not free memory. To do that, call dvb_free_device(). ++ * This does not free memory. dvb_free_device() will do that when ++ * reference counter is empty + * + * @dvbdev: pointer to struct dvb_device + */ + void dvb_remove_device(struct dvb_device *dvbdev); + +-/** +- * dvb_free_device - Free memory occupied by a DVB device. +- * +- * Call dvb_unregister_device() before calling this function. +- * +- * @dvbdev: pointer to struct dvb_device +- */ +-void dvb_free_device(struct dvb_device *dvbdev); + + /** + * dvb_unregister_device - Unregisters a DVB device + * +- * This is a combination of dvb_remove_device() and dvb_free_device(). +- * Using this function is usually a mistake, and is often an indicator +- * for a use-after-free bug (when a userspace process keeps a file +- * handle to a detached device). +- * + * @dvbdev: pointer to struct dvb_device + */ + void dvb_unregister_device(struct dvb_device *dvbdev); +-- +2.35.1 + diff --git a/queue-5.15/media-exynos4-is-don-t-rely-on-the-v4l2_async_subdev.patch b/queue-5.15/media-exynos4-is-don-t-rely-on-the-v4l2_async_subdev.patch new file mode 100644 index 00000000000..049248bb22a --- /dev/null +++ b/queue-5.15/media-exynos4-is-don-t-rely-on-the-v4l2_async_subdev.patch @@ -0,0 +1,45 @@ +From 55a58a2d859a9a1b9f978c7043eefd473d1cefc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Sep 2022 11:42:01 +0200 +Subject: media: exynos4-is: don't rely on the v4l2_async_subdev internals + +From: Marek Szyprowski + +[ Upstream commit f98a5c2e1c4396488c27274ba82afc11725a4bcc ] + +Commit 1f391df44607 ("media: v4l2-async: Use endpoints in +__v4l2_async_nf_add_fwnode_remote()") changed the data that is stored in +the v4l2_async_subdev internals from the fwnode pointer to the parent +device to the fwnode pointer to the matched endpoint. This broke the +sensor matching code, which relied on the particular fwnode data in the +v4l2_async_subdev internals. Fix this by simply matching the +v4l2_async_subdev pointer, which is already available there. + +Reported-by: Daniel Scally +Fixes: fa91f1056f17 ("[media] exynos4-is: Add support for asynchronous subdevices registration") +Signed-off-by: Marek Szyprowski +Reviewed-by: Daniel Scally +Signed-off-by: Sakari Ailus +Signed-off-by: Sasha Levin +--- + drivers/media/platform/exynos4-is/media-dev.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c +index fa648721eaab..aa5982e32b2b 100644 +--- a/drivers/media/platform/exynos4-is/media-dev.c ++++ b/drivers/media/platform/exynos4-is/media-dev.c +@@ -1380,9 +1380,7 @@ static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, + + /* Find platform data for this sensor subdev */ + for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++) +- if (fmd->sensor[i].asd && +- fmd->sensor[i].asd->match.fwnode == +- of_fwnode_handle(subdev->dev->of_node)) ++ if (fmd->sensor[i].asd == asd) + si = &fmd->sensor[i]; + + if (si == NULL) +-- +2.35.1 + diff --git a/queue-5.15/media-i2c-ad5820-fix-error-path.patch b/queue-5.15/media-i2c-ad5820-fix-error-path.patch new file mode 100644 index 00000000000..782699b43f4 --- /dev/null +++ b/queue-5.15/media-i2c-ad5820-fix-error-path.patch @@ -0,0 +1,51 @@ +From 4af8b860e27feee0850ec1c2540a7c53021743f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 13:38:00 +0200 +Subject: media: i2c: ad5820: Fix error path + +From: Ricardo Ribalda + +[ Upstream commit 9fce241660f37d9e95e93c0ae6fba8cfefa5797b ] + +Error path seems to be swaped. Fix the order and provide some meaningful +names. + +Fixes: bee3d5115611 ("[media] ad5820: Add driver for auto-focus coil") +Signed-off-by: Ricardo Ribalda +Signed-off-by: Sakari Ailus +Signed-off-by: Sasha Levin +--- + drivers/media/i2c/ad5820.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/i2c/ad5820.c b/drivers/media/i2c/ad5820.c +index 2958a4694461..07639ecc85aa 100644 +--- a/drivers/media/i2c/ad5820.c ++++ b/drivers/media/i2c/ad5820.c +@@ -327,18 +327,18 @@ static int ad5820_probe(struct i2c_client *client, + + ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL); + if (ret < 0) +- goto cleanup2; ++ goto clean_mutex; + + ret = v4l2_async_register_subdev(&coil->subdev); + if (ret < 0) +- goto cleanup; ++ goto clean_entity; + + return ret; + +-cleanup2: +- mutex_destroy(&coil->power_lock); +-cleanup: ++clean_entity: + media_entity_cleanup(&coil->subdev.entity); ++clean_mutex: ++ mutex_destroy(&coil->power_lock); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/media-imon-fix-a-race-condition-in-send_packet.patch b/queue-5.15/media-imon-fix-a-race-condition-in-send_packet.patch new file mode 100644 index 00000000000..8e1302341e0 --- /dev/null +++ b/queue-5.15/media-imon-fix-a-race-condition-in-send_packet.patch @@ -0,0 +1,79 @@ +From 62281788f4fc43bd310ff6fbc3d1e5e7f015638d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Oct 2022 06:02:14 +0100 +Subject: media: imon: fix a race condition in send_packet() + +From: Gautam Menghani + +[ Upstream commit 813ceef062b53d68f296aa3cb944b21a091fabdb ] + +The function send_packet() has a race condition as follows: + +func send_packet() +{ + // do work + call usb_submit_urb() + mutex_unlock() + wait_for_event_interruptible() <-- lock gone + mutex_lock() +} + +func vfd_write() +{ + mutex_lock() + call send_packet() <- prev call is not completed + mutex_unlock() +} + +When the mutex is unlocked and the function send_packet() waits for the +call to complete, vfd_write() can start another call, which leads to the +"URB submitted while active" warning in usb_submit_urb(). +Fix this by removing the mutex_unlock() call in send_packet() and using +mutex_lock_interruptible(). + +Link: https://syzkaller.appspot.com/bug?id=e378e6a51fbe6c5cc43e34f131cc9a315ef0337e + +Fixes: 21677cfc562a ("V4L/DVB: ir-core: add imon driver") +Reported-by: syzbot+0c3cb6dc05fbbdc3ad66@syzkaller.appspotmail.com +Signed-off-by: Gautam Menghani +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/rc/imon.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c +index 97355e3ebdfd..72e4bb0fb71e 100644 +--- a/drivers/media/rc/imon.c ++++ b/drivers/media/rc/imon.c +@@ -646,15 +646,14 @@ static int send_packet(struct imon_context *ictx) + pr_err_ratelimited("error submitting urb(%d)\n", retval); + } else { + /* Wait for transmission to complete (or abort) */ +- mutex_unlock(&ictx->lock); + retval = wait_for_completion_interruptible( + &ictx->tx.finished); + if (retval) { + usb_kill_urb(ictx->tx_urb); + pr_err_ratelimited("task interrupted\n"); + } +- mutex_lock(&ictx->lock); + ++ ictx->tx.busy = false; + retval = ictx->tx.status; + if (retval) + pr_err_ratelimited("packet tx failed (%d)\n", retval); +@@ -955,7 +954,8 @@ static ssize_t vfd_write(struct file *file, const char __user *buf, + if (ictx->disconnected) + return -ENODEV; + +- mutex_lock(&ictx->lock); ++ if (mutex_lock_interruptible(&ictx->lock)) ++ return -ERESTARTSYS; + + if (!ictx->dev_present_intf0) { + pr_err_ratelimited("no iMON device present\n"); +-- +2.35.1 + diff --git a/queue-5.15/media-imx-jpeg-disable-useless-interrupt-to-avoid-ke.patch b/queue-5.15/media-imx-jpeg-disable-useless-interrupt-to-avoid-ke.patch new file mode 100644 index 00000000000..761008ed2f0 --- /dev/null +++ b/queue-5.15/media-imx-jpeg-disable-useless-interrupt-to-avoid-ke.patch @@ -0,0 +1,48 @@ +From a8b97a8ed86b622f02081ecb9cc06e25d5fdae08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 17:38:41 +0800 +Subject: media: imx-jpeg: Disable useless interrupt to avoid kernel panic + +From: Ming Qian + +[ Upstream commit c3720e65c9013a7b2a5dbb63e6bf6d74a35dd894 ] + +There is a hardware bug that the interrupt STMBUF_HALF may be triggered +after or when disable interrupt. +It may led to unexpected kernel panic. +And interrupt STMBUF_HALF and STMBUF_RTND have no other effect. +So disable them and the unused interrupts. + +meanwhile clear the interrupt status when disable interrupt. + +Signed-off-by: Ming Qian +Reviewed-by: Mirela Rabulea +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c +index 718b7b08f93e..8936d5ce886c 100644 +--- a/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c ++++ b/drivers/media/platform/imx-jpeg/mxc-jpeg-hw.c +@@ -76,12 +76,14 @@ void print_wrapper_info(struct device *dev, void __iomem *reg) + + void mxc_jpeg_enable_irq(void __iomem *reg, int slot) + { +- writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); ++ writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); ++ writel(0xF0C, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); + } + + void mxc_jpeg_disable_irq(void __iomem *reg, int slot) + { + writel(0x0, reg + MXC_SLOT_OFFSET(slot, SLOT_IRQ_EN)); ++ writel(0xFFFFFFFF, reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS)); + } + + void mxc_jpeg_sw_reset(void __iomem *reg) +-- +2.35.1 + diff --git a/queue-5.15/media-platform-exynos4-is-fix-error-handling-in-fimc.patch b/queue-5.15/media-platform-exynos4-is-fix-error-handling-in-fimc.patch new file mode 100644 index 00000000000..c0b9f3ee177 --- /dev/null +++ b/queue-5.15/media-platform-exynos4-is-fix-error-handling-in-fimc.patch @@ -0,0 +1,75 @@ +From 25a0a55fff0d4ae0c52816de094b5601aff6d69e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 06:08:53 +0000 +Subject: media: platform: exynos4-is: Fix error handling in fimc_md_init() + +From: Yuan Can + +[ Upstream commit b434422c45282a0573d8123239abc41fa72665d4 ] + +A problem about modprobe s5p_fimc failed is triggered with the +following log given: + + [ 272.075275] Error: Driver 'exynos4-fimc' is already registered, aborting... + modprobe: ERROR: could not insert 's5p_fimc': Device or resource busy + +The reason is that fimc_md_init() returns platform_driver_register() +directly without checking its return value, if platform_driver_register() +failed, it returns without unregister fimc_driver, resulting the +s5p_fimc can never be installed later. +A simple call graph is shown as below: + + fimc_md_init() + fimc_register_driver() # register fimc_driver + platform_driver_register() + platform_driver_register() + driver_register() + bus_add_driver() + dev = kzalloc(...) # OOM happened + # return without unregister fimc_driver + +Fix by unregister fimc_driver when platform_driver_register() returns +error. + +Fixes: d3953223b090 ("[media] s5p-fimc: Add the media device driver") +Signed-off-by: Yuan Can +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/exynos4-is/fimc-core.c | 2 +- + drivers/media/platform/exynos4-is/media-dev.c | 6 +++++- + 2 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c +index bfdee771cef9..4afe0b9b1773 100644 +--- a/drivers/media/platform/exynos4-is/fimc-core.c ++++ b/drivers/media/platform/exynos4-is/fimc-core.c +@@ -1174,7 +1174,7 @@ int __init fimc_register_driver(void) + return platform_driver_register(&fimc_driver); + } + +-void __exit fimc_unregister_driver(void) ++void fimc_unregister_driver(void) + { + platform_driver_unregister(&fimc_driver); + } +diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c +index 00225e16dd49..b19d7c8ddc06 100644 +--- a/drivers/media/platform/exynos4-is/media-dev.c ++++ b/drivers/media/platform/exynos4-is/media-dev.c +@@ -1584,7 +1584,11 @@ static int __init fimc_md_init(void) + if (ret) + return ret; + +- return platform_driver_register(&fimc_md_driver); ++ ret = platform_driver_register(&fimc_md_driver); ++ if (ret) ++ fimc_unregister_driver(); ++ ++ return ret; + } + + static void __exit fimc_md_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/media-platform-exynos4-is-fix-return-value-check-in-.patch b/queue-5.15/media-platform-exynos4-is-fix-return-value-check-in-.patch new file mode 100644 index 00000000000..e8c93a1c916 --- /dev/null +++ b/queue-5.15/media-platform-exynos4-is-fix-return-value-check-in-.patch @@ -0,0 +1,37 @@ +From 84ff26d405bec67f020e67a9833830f33d873eee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 21:46:50 +0800 +Subject: media: platform: exynos4-is: fix return value check in + fimc_md_probe() + +From: Yang Yingliang + +[ Upstream commit e38e42c078da4af962d322b97e726dcb2f184e3f ] + +devm_pinctrl_get() may return ERR_PTR(-EPROBE_DEFER), add a minus sign +to fix it. + +Fixes: 4163851f7b99 ("[media] s5p-fimc: Use pinctrl API for camera ports configuration") +Signed-off-by: Yang Yingliang +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/platform/exynos4-is/media-dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c +index aa5982e32b2b..00225e16dd49 100644 +--- a/drivers/media/platform/exynos4-is/media-dev.c ++++ b/drivers/media/platform/exynos4-is/media-dev.c +@@ -1472,7 +1472,7 @@ static int fimc_md_probe(struct platform_device *pdev) + pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(pinctrl)) { + ret = PTR_ERR(pinctrl); +- if (ret != EPROBE_DEFER) ++ if (ret != -EPROBE_DEFER) + dev_err(dev, "Failed to get pinctrl: %d\n", ret); + goto err_clk; + } +-- +2.35.1 + diff --git a/queue-5.15/media-s5p-mfc-add-variant-data-for-mfc-v7-hardware-f.patch b/queue-5.15/media-s5p-mfc-add-variant-data-for-mfc-v7-hardware-f.patch new file mode 100644 index 00000000000..a5e6d4a3c04 --- /dev/null +++ b/queue-5.15/media-s5p-mfc-add-variant-data-for-mfc-v7-hardware-f.patch @@ -0,0 +1,66 @@ +From ba5ba8b5e8bee21e1a70a395b369e82b386a0890 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 11:50:23 +0000 +Subject: media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 + SoC + +From: Aakarsh Jain + +[ Upstream commit f50ebe10f5d8092c37e2bd430c78e03bf38b1e20 ] + +Commit 5441e9dafdfc6dc40 ("[media] s5p-mfc: Core support for MFC v7") +which adds mfc v7 support for Exynos3250 and use the same compatible +string as used by Exynos5240 but both the IPs are a bit different in +terms of IP clock. +Add variant driver data based on the new compatible string +"samsung,exynos3250-mfc" for Exynos3250 SoC. + +Suggested-by: Alim Akhtar +Fixes: 5441e9dafdfc ("[media] s5p-mfc: Core support for MFC v7") +Signed-off-by: Aakarsh Jain +Reviewed-by: Alim Akhtar +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/s5p-mfc/s5p_mfc.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c +index 4fc135d9f38b..4c511b026bd7 100644 +--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c ++++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c +@@ -1583,8 +1583,18 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = { + .port_num = MFC_NUM_PORTS_V7, + .buf_size = &buf_size_v7, + .fw_name[0] = "s5p-mfc-v7.fw", +- .clk_names = {"mfc", "sclk_mfc"}, +- .num_clocks = 2, ++ .clk_names = {"mfc"}, ++ .num_clocks = 1, ++}; ++ ++static struct s5p_mfc_variant mfc_drvdata_v7_3250 = { ++ .version = MFC_VERSION_V7, ++ .version_bit = MFC_V7_BIT, ++ .port_num = MFC_NUM_PORTS_V7, ++ .buf_size = &buf_size_v7, ++ .fw_name[0] = "s5p-mfc-v7.fw", ++ .clk_names = {"mfc", "sclk_mfc"}, ++ .num_clocks = 2, + }; + + static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = { +@@ -1654,6 +1664,9 @@ static const struct of_device_id exynos_mfc_match[] = { + }, { + .compatible = "samsung,mfc-v7", + .data = &mfc_drvdata_v7, ++ }, { ++ .compatible = "samsung,exynos3250-mfc", ++ .data = &mfc_drvdata_v7_3250, + }, { + .compatible = "samsung,mfc-v8", + .data = &mfc_drvdata_v8, +-- +2.35.1 + diff --git a/queue-5.15/media-saa7164-fix-missing-pci_disable_device.patch b/queue-5.15/media-saa7164-fix-missing-pci_disable_device.patch new file mode 100644 index 00000000000..25ea92b61e4 --- /dev/null +++ b/queue-5.15/media-saa7164-fix-missing-pci_disable_device.patch @@ -0,0 +1,45 @@ +From 791b4b813db7f51ab0ad21bb5a4b10fb37d440ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 11:31:26 +0000 +Subject: media: saa7164: fix missing pci_disable_device() + +From: Liu Shixin + +[ Upstream commit 57fb35d7542384cac8f198cd1c927540ad38b61a ] + +Add missing pci_disable_device() in the error path in saa7164_initdev(). + +Fixes: 443c1228d505 ("V4L/DVB (12923): SAA7164: Add support for the NXP SAA7164 silicon") +Signed-off-by: Liu Shixin +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/pci/saa7164/saa7164-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c +index 7973ae42873a..c10997e2271d 100644 +--- a/drivers/media/pci/saa7164/saa7164-core.c ++++ b/drivers/media/pci/saa7164/saa7164-core.c +@@ -1259,7 +1259,7 @@ static int saa7164_initdev(struct pci_dev *pci_dev, + + if (saa7164_dev_setup(dev) < 0) { + err = -EINVAL; +- goto fail_free; ++ goto fail_dev; + } + + /* print pci info */ +@@ -1427,6 +1427,8 @@ static int saa7164_initdev(struct pci_dev *pci_dev, + + fail_irq: + saa7164_dev_unregister(dev); ++fail_dev: ++ pci_disable_device(pci_dev); + fail_free: + v4l2_device_unregister(&dev->v4l2_dev); + kfree(dev); +-- +2.35.1 + diff --git a/queue-5.15/media-si470x-fix-use-after-free-in-si470x_int_in_cal.patch b/queue-5.15/media-si470x-fix-use-after-free-in-si470x_int_in_cal.patch new file mode 100644 index 00000000000..68192d683b7 --- /dev/null +++ b/queue-5.15/media-si470x-fix-use-after-free-in-si470x_int_in_cal.patch @@ -0,0 +1,64 @@ +From 55ebd74f9c426a74aefcbe8d7327f2fcb6ca0ae6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 03:51:59 +0900 +Subject: media: si470x: Fix use-after-free in si470x_int_in_callback() + +From: Shigeru Yoshida + +[ Upstream commit 7d21e0b1b41b21d628bf2afce777727bd4479aa5 ] + +syzbot reported use-after-free in si470x_int_in_callback() [1]. This +indicates that urb->context, which contains struct si470x_device +object, is freed when si470x_int_in_callback() is called. + +The cause of this issue is that si470x_int_in_callback() is called for +freed urb. + +si470x_usb_driver_probe() calls si470x_start_usb(), which then calls +usb_submit_urb() and si470x_start(). If si470x_start_usb() fails, +si470x_usb_driver_probe() doesn't kill urb, but it just frees struct +si470x_device object, as depicted below: + +si470x_usb_driver_probe() + ... + si470x_start_usb() + ... + usb_submit_urb() + retval = si470x_start() + return retval + if (retval < 0) + free struct si470x_device object, but don't kill urb + +This patch fixes this issue by killing urb when si470x_start_usb() +fails and urb is submitted. If si470x_start_usb() fails and urb is +not submitted, i.e. submitting usb fails, it just frees struct +si470x_device object. + +Reported-by: syzbot+9ca7a12fd736d93e0232@syzkaller.appspotmail.com +Link: https://syzkaller.appspot.com/bug?id=94ed6dddd5a55e90fd4bab942aa4bb297741d977 [1] +Signed-off-by: Shigeru Yoshida +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/radio/si470x/radio-si470x-usb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c +index 3f8634a46573..1365ae732b79 100644 +--- a/drivers/media/radio/si470x/radio-si470x-usb.c ++++ b/drivers/media/radio/si470x/radio-si470x-usb.c +@@ -733,8 +733,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf, + + /* start radio */ + retval = si470x_start_usb(radio); +- if (retval < 0) ++ if (retval < 0 && !radio->int_in_running) + goto err_buf; ++ else if (retval < 0) /* in case of radio->int_in_running == 1 */ ++ goto err_all; + + /* set initial frequency */ + si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */ +-- +2.35.1 + diff --git a/queue-5.15/media-solo6x10-fix-possible-memory-leak-in-solo_sysf.patch b/queue-5.15/media-solo6x10-fix-possible-memory-leak-in-solo_sysf.patch new file mode 100644 index 00000000000..a67f3923acc --- /dev/null +++ b/queue-5.15/media-solo6x10-fix-possible-memory-leak-in-solo_sysf.patch @@ -0,0 +1,38 @@ +From 750c8acd2db2a0a3d7971908f2fe74715a88669f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 16:24:23 +0800 +Subject: media: solo6x10: fix possible memory leak in solo_sysfs_init() + +From: Yang Yingliang + +[ Upstream commit 7f5866dd96d95b74e439f6ee17b8abd8195179fb ] + +If device_register() returns error in solo_sysfs_init(), the +name allocated by dev_set_name() need be freed. As comment of +device_register() says, it should use put_device() to give up +the reference in the error path. So fix this by calling +put_device(), then the name can be freed in kobject_cleanup(). + +Fixes: dcae5dacbce5 ("[media] solo6x10: sync to latest code from Bluecherry's git repo") +Signed-off-by: Yang Yingliang +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/pci/solo6x10/solo6x10-core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c +index 4a546eeefe38..6d87fbb0ee04 100644 +--- a/drivers/media/pci/solo6x10/solo6x10-core.c ++++ b/drivers/media/pci/solo6x10/solo6x10-core.c +@@ -420,6 +420,7 @@ static int solo_sysfs_init(struct solo_dev *solo_dev) + solo_dev->nr_chans); + + if (device_register(dev)) { ++ put_device(dev); + dev->parent = NULL; + return -ENOMEM; + } +-- +2.35.1 + diff --git a/queue-5.15/media-v4l2-ctrls-fix-off-by-one-error-in-integer-men.patch b/queue-5.15/media-v4l2-ctrls-fix-off-by-one-error-in-integer-men.patch new file mode 100644 index 00000000000..a5a14ee5c05 --- /dev/null +++ b/queue-5.15/media-v4l2-ctrls-fix-off-by-one-error-in-integer-men.patch @@ -0,0 +1,38 @@ +From 1e2569a1885a3f14526e5021707be292ccc92f0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 19:31:51 +0300 +Subject: media: v4l2-ctrls: Fix off-by-one error in integer menu control check + +From: Laurent Pinchart + +[ Upstream commit b6bcdf763db1f5ea602bf876cfe91debfb3c7773 ] + +The V4L2 API defines the maximum value for an integer menu control as +the number of elements minus one. The v4l2_ctrl_new_std_menu() validates +this constraint with an off-by-one error. Fix it. + +Fixes: d1e9b7c12b74 ("[media] V4L: Add support for integer menu controls with standard menu items") +Signed-off-by: Laurent Pinchart +Reviewed-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/v4l2-ctrls-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c +index 45a76f40deeb..3798a57bbbd4 100644 +--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c ++++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c +@@ -1456,7 +1456,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, + else if (type == V4L2_CTRL_TYPE_INTEGER_MENU) + qmenu_int = v4l2_ctrl_get_int_menu(id, &qmenu_int_len); + +- if ((!qmenu && !qmenu_int) || (qmenu_int && max > qmenu_int_len)) { ++ if ((!qmenu && !qmenu_int) || (qmenu_int && max >= qmenu_int_len)) { + handler_set_err(hdl, -EINVAL); + return NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/media-videobuf-dma-contig-use-dma_mmap_coherent.patch b/queue-5.15/media-videobuf-dma-contig-use-dma_mmap_coherent.patch new file mode 100644 index 00000000000..75cb8a7ef57 --- /dev/null +++ b/queue-5.15/media-videobuf-dma-contig-use-dma_mmap_coherent.patch @@ -0,0 +1,87 @@ +From 804cf1afd0b778fb744d2fa1a9efc4939c737b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Dec 2019 11:39:07 +0100 +Subject: media: videobuf-dma-contig: use dma_mmap_coherent + +From: Christoph Hellwig + +[ Upstream commit b3dc3f8e49577840dc8ac8a365c5b3da4edb10b8 ] + +dma_alloc_coherent does not return a physical address, but a DMA address, +which might be remapped or have an offset. Passing the DMA address to +vm_iomap_memory is thus broken. + +Use the proper dma_mmap_coherent helper instead, and stop passing +__GFP_COMP to dma_alloc_coherent, as the memory management inside the +DMA allocator is hidden from the callers and does not require it. + +With this the gfp_t argument to __videobuf_dc_alloc can be removed and +hard coded to GFP_KERNEL. + +Fixes: a8f3c203e19b ("[media] videobuf-dma-contig: add cache support") +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/media/v4l2-core/videobuf-dma-contig.c | 22 +++++++------------ + 1 file changed, 8 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c +index 52312ce2ba05..f2c439359557 100644 +--- a/drivers/media/v4l2-core/videobuf-dma-contig.c ++++ b/drivers/media/v4l2-core/videobuf-dma-contig.c +@@ -36,12 +36,11 @@ struct videobuf_dma_contig_memory { + + static int __videobuf_dc_alloc(struct device *dev, + struct videobuf_dma_contig_memory *mem, +- unsigned long size, gfp_t flags) ++ unsigned long size) + { + mem->size = size; +- mem->vaddr = dma_alloc_coherent(dev, mem->size, +- &mem->dma_handle, flags); +- ++ mem->vaddr = dma_alloc_coherent(dev, mem->size, &mem->dma_handle, ++ GFP_KERNEL); + if (!mem->vaddr) { + dev_err(dev, "memory alloc size %ld failed\n", mem->size); + return -ENOMEM; +@@ -258,8 +257,7 @@ static int __videobuf_iolock(struct videobuf_queue *q, + return videobuf_dma_contig_user_get(mem, vb); + + /* allocate memory for the read() method */ +- if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size), +- GFP_KERNEL)) ++ if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size))) + return -ENOMEM; + break; + case V4L2_MEMORY_OVERLAY: +@@ -295,22 +293,18 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q, + BUG_ON(!mem); + MAGIC_CHECK(mem->magic, MAGIC_DC_MEM); + +- if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize), +- GFP_KERNEL | __GFP_COMP)) ++ if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize))) + goto error; + +- /* Try to remap memory */ +- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); +- + /* the "vm_pgoff" is just used in v4l2 to find the + * corresponding buffer data structure which is allocated + * earlier and it does not mean the offset from the physical + * buffer start address as usual. So set it to 0 to pass +- * the sanity check in vm_iomap_memory(). ++ * the sanity check in dma_mmap_coherent(). + */ + vma->vm_pgoff = 0; +- +- retval = vm_iomap_memory(vma, mem->dma_handle, mem->size); ++ retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle, ++ mem->size); + if (retval) { + dev_err(q->dev, "mmap: remap failed with error %d. ", + retval); +-- +2.35.1 + diff --git a/queue-5.15/media-vidtv-fix-use-after-free-in-vidtv_bridge_dvb_i.patch b/queue-5.15/media-vidtv-fix-use-after-free-in-vidtv_bridge_dvb_i.patch new file mode 100644 index 00000000000..e2f680cc62a --- /dev/null +++ b/queue-5.15/media-vidtv-fix-use-after-free-in-vidtv_bridge_dvb_i.patch @@ -0,0 +1,91 @@ +From 5b9acb67ec3546d9595de7067c2ce38e957009f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 15:06:30 +0800 +Subject: media: vidtv: Fix use-after-free in vidtv_bridge_dvb_init() + +From: Chen Zhongjin + +[ Upstream commit ba8d9405935097e296bcf7a942c3a01df0edb865 ] + +KASAN reports a use-after-free: +BUG: KASAN: use-after-free in dvb_dmxdev_release+0x4d5/0x5d0 [dvb_core] +Call Trace: + ... + dvb_dmxdev_release+0x4d5/0x5d0 [dvb_core] + vidtv_bridge_probe+0x7bf/0xa40 [dvb_vidtv_bridge] + platform_probe+0xb6/0x170 + ... +Allocated by task 1238: + ... + dvb_register_device+0x1a7/0xa70 [dvb_core] + dvb_dmxdev_init+0x2af/0x4a0 [dvb_core] + vidtv_bridge_probe+0x766/0xa40 [dvb_vidtv_bridge] + ... +Freed by task 1238: + dvb_register_device+0x6d2/0xa70 [dvb_core] + dvb_dmxdev_init+0x2af/0x4a0 [dvb_core] + vidtv_bridge_probe+0x766/0xa40 [dvb_vidtv_bridge] + ... + +It is because the error handling in vidtv_bridge_dvb_init() is wrong. + +First, vidtv_bridge_dmx(dev)_init() will clean themselves when fail, but +goto fail_dmx(_dev): calls release functions again, which causes +use-after-free. + +Also, in fail_fe, fail_tuner_probe and fail_demod_probe, j = i will cause +out-of-bound when i finished its loop (i == NUM_FE). And the loop +releasing is wrong, although now NUM_FE is 1 so it won't cause problem. + +Fix this by correctly releasing everything. + +Fixes: f90cf6079bf6 ("media: vidtv: add a bridge driver") +Signed-off-by: Chen Zhongjin +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + .../media/test-drivers/vidtv/vidtv_bridge.c | 22 +++++++------------ + 1 file changed, 8 insertions(+), 14 deletions(-) + +diff --git a/drivers/media/test-drivers/vidtv/vidtv_bridge.c b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +index 82620613d56b..dff7265a42ca 100644 +--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c ++++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c +@@ -459,26 +459,20 @@ static int vidtv_bridge_dvb_init(struct vidtv_dvb *dvb) + for (j = j - 1; j >= 0; --j) + dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, + &dvb->dmx_fe[j]); +-fail_dmx_dev: + dvb_dmxdev_release(&dvb->dmx_dev); +-fail_dmx: ++fail_dmx_dev: + dvb_dmx_release(&dvb->demux); ++fail_dmx: ++fail_demod_probe: ++ for (i = i - 1; i >= 0; --i) { ++ dvb_unregister_frontend(dvb->fe[i]); + fail_fe: +- for (j = i; j >= 0; --j) +- dvb_unregister_frontend(dvb->fe[j]); ++ dvb_module_release(dvb->i2c_client_tuner[i]); + fail_tuner_probe: +- for (j = i; j >= 0; --j) +- if (dvb->i2c_client_tuner[j]) +- dvb_module_release(dvb->i2c_client_tuner[j]); +- +-fail_demod_probe: +- for (j = i; j >= 0; --j) +- if (dvb->i2c_client_demod[j]) +- dvb_module_release(dvb->i2c_client_demod[j]); +- ++ dvb_module_release(dvb->i2c_client_demod[i]); ++ } + fail_adapter: + dvb_unregister_adapter(&dvb->adapter); +- + fail_i2c: + i2c_del_adapter(&dvb->i2c_adapter); + +-- +2.35.1 + diff --git a/queue-5.15/media-vimc-fix-wrong-function-called-when-vimc_init-.patch b/queue-5.15/media-vimc-fix-wrong-function-called-when-vimc_init-.patch new file mode 100644 index 00000000000..05c9aa36180 --- /dev/null +++ b/queue-5.15/media-vimc-fix-wrong-function-called-when-vimc_init-.patch @@ -0,0 +1,48 @@ +From e2ae50073a4c5b2aa9375c6d9aaf4a2ed58391f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 07:26:33 +0000 +Subject: media: vimc: Fix wrong function called when vimc_init() fails + +From: Chen Zhongjin + +[ Upstream commit f74d3f326d1d5b8951ce263c59a121ecfa65e7c0 ] + +In vimc_init(), when platform_driver_register(&vimc_pdrv) fails, +platform_driver_unregister(&vimc_pdrv) is wrongly called rather than +platform_device_unregister(&vimc_pdev), which causes kernel warning: + + Unexpected driver unregister! + WARNING: CPU: 1 PID: 14517 at drivers/base/driver.c:270 driver_unregister+0x8f/0xb0 + RIP: 0010:driver_unregister+0x8f/0xb0 + Call Trace: + + vimc_init+0x7d/0x1000 [vimc] + do_one_initcall+0xd0/0x4e0 + do_init_module+0x1cf/0x6b0 + load_module+0x65c2/0x7820 + +Fixes: 4a29b7090749 ("[media] vimc: Subdevices as modules") +Signed-off-by: Chen Zhongjin +Signed-off-by: Shuah Khan +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/test-drivers/vimc/vimc-core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/test-drivers/vimc/vimc-core.c b/drivers/media/test-drivers/vimc/vimc-core.c +index 4b0ae6f51d76..857529ce3638 100644 +--- a/drivers/media/test-drivers/vimc/vimc-core.c ++++ b/drivers/media/test-drivers/vimc/vimc-core.c +@@ -357,7 +357,7 @@ static int __init vimc_init(void) + if (ret) { + dev_err(&vimc_pdev.dev, + "platform driver registration failed (err=%d)\n", ret); +- platform_driver_unregister(&vimc_pdrv); ++ platform_device_unregister(&vimc_pdev); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/media-vivid-fix-compose-size-exceed-boundary.patch b/queue-5.15/media-vivid-fix-compose-size-exceed-boundary.patch new file mode 100644 index 00000000000..d44d674fb4f --- /dev/null +++ b/queue-5.15/media-vivid-fix-compose-size-exceed-boundary.patch @@ -0,0 +1,57 @@ +From 062dad15b6d0b71cc02b7d050ae92cdb30ee953c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 20:38:55 +0800 +Subject: media: vivid: fix compose size exceed boundary + +From: Liu Shixin + +[ Upstream commit 94a7ad9283464b75b12516c5512541d467cefcf8 ] + +syzkaller found a bug: + + BUG: unable to handle page fault for address: ffffc9000a3b1000 + #PF: supervisor write access in kernel mode + #PF: error_code(0x0002) - not-present page + PGD 100000067 P4D 100000067 PUD 10015f067 PMD 1121ca067 PTE 0 + Oops: 0002 [#1] PREEMPT SMP + CPU: 0 PID: 23489 Comm: vivid-000-vid-c Not tainted 6.1.0-rc1+ #512 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 + RIP: 0010:memcpy_erms+0x6/0x10 +[...] + Call Trace: + + ? tpg_fill_plane_buffer+0x856/0x15b0 + vivid_fillbuff+0x8ac/0x1110 + vivid_thread_vid_cap_tick+0x361/0xc90 + vivid_thread_vid_cap+0x21a/0x3a0 + kthread+0x143/0x180 + ret_from_fork+0x1f/0x30 + + +This is because we forget to check boundary after adjust compose->height +int V4L2_SEL_TGT_CROP case. Add v4l2_rect_map_inside() to fix this problem +for this case. + +Fixes: ef834f7836ec ("[media] vivid: add the video capture and output parts") +Signed-off-by: Liu Shixin +Signed-off-by: Hans Verkuil +Signed-off-by: Sasha Levin +--- + drivers/media/test-drivers/vivid/vivid-vid-cap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/test-drivers/vivid/vivid-vid-cap.c b/drivers/media/test-drivers/vivid/vivid-vid-cap.c +index 99139a8cd4c4..331a3f4286d2 100644 +--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c ++++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c +@@ -961,6 +961,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection + if (dev->has_compose_cap) { + v4l2_rect_set_min_size(compose, &min_rect); + v4l2_rect_set_max_size(compose, &max_rect); ++ v4l2_rect_map_inside(compose, &fmt); + } + dev->fmt_cap_rect = fmt; + tpg_s_buf_height(&dev->tpg, fmt.height); +-- +2.35.1 + diff --git a/queue-5.15/memstick-ms_block-add-check-for-alloc_ordered_workqu.patch b/queue-5.15/memstick-ms_block-add-check-for-alloc_ordered_workqu.patch new file mode 100644 index 00000000000..67f27c93b5f --- /dev/null +++ b/queue-5.15/memstick-ms_block-add-check-for-alloc_ordered_workqu.patch @@ -0,0 +1,55 @@ +From 5902f1a02f5a08f894c8c0f4e4b4790c0bca35eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 09:25:58 +0800 +Subject: memstick/ms_block: Add check for alloc_ordered_workqueue + +From: Jiasheng Jiang + +[ Upstream commit 4f431a047a5c8698ed4b67e2760cfbeb5fffb69d ] + +As the alloc_ordered_workqueue may return NULL pointer, it should be better +to add check for the return value. Moreover, the msb->io_queue should be +freed if error occurs later. + +Fixes: 0ab30494bc4f ("memstick: add support for legacy memorysticks") +Signed-off-by: Jiasheng Jiang +Link: https://lore.kernel.org/r/20221126012558.34374-1-jiasheng@iscas.ac.cn +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/memstick/core/ms_block.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c +index 29a69243cbd0..7619c30b4ee1 100644 +--- a/drivers/memstick/core/ms_block.c ++++ b/drivers/memstick/core/ms_block.c +@@ -2150,6 +2150,11 @@ static int msb_init_disk(struct memstick_dev *card) + + msb->usage_count = 1; + msb->io_queue = alloc_ordered_workqueue("ms_block", WQ_MEM_RECLAIM); ++ if (!msb->io_queue) { ++ rc = -ENOMEM; ++ goto out_cleanup_disk; ++ } ++ + INIT_WORK(&msb->io_work, msb_io_work); + sg_init_table(msb->prealloc_sg, MS_BLOCK_MAX_SEGS+1); + +@@ -2159,10 +2164,12 @@ static int msb_init_disk(struct memstick_dev *card) + msb_start(card); + rc = device_add_disk(&card->dev, msb->disk, NULL); + if (rc) +- goto out_cleanup_disk; ++ goto out_destroy_workqueue; + dbg("Disk added"); + return 0; + ++out_destroy_workqueue: ++ destroy_workqueue(msb->io_queue); + out_cleanup_disk: + blk_cleanup_disk(msb->disk); + out_free_tag_set: +-- +2.35.1 + diff --git a/queue-5.15/memstick-ms_block-add-error-handling-support-for-add.patch b/queue-5.15/memstick-ms_block-add-error-handling-support-for-add.patch new file mode 100644 index 00000000000..2f909192526 --- /dev/null +++ b/queue-5.15/memstick-ms_block-add-error-handling-support-for-add.patch @@ -0,0 +1,48 @@ +From e74dfbf521ca3faaa6b2e7490965401d132342f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Sep 2021 10:40:58 -0700 +Subject: memstick: ms_block: Add error handling support for add_disk() + +From: Luis Chamberlain + +[ Upstream commit 2304c55fd506fcd5e1a59ae21a306ee82507340b ] + +We never checked for errors on add_disk() as this function returned void. +Now that this is fixed, use the shiny new error handling. + +Contrary to the typical removal which delays the put_disk() until later, +since we are failing on a probe we immediately put the disk on failure from +add_disk by using blk_cleanup_disk(). + +Signed-off-by: Luis Chamberlain +Link: https://lore.kernel.org/r/20210902174105.2418771-3-mcgrof@kernel.org +Signed-off-by: Ulf Hansson +Stable-dep-of: 4f431a047a5c ("memstick/ms_block: Add check for alloc_ordered_workqueue") +Signed-off-by: Sasha Levin +--- + drivers/memstick/core/ms_block.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c +index f854822f84d6..29a69243cbd0 100644 +--- a/drivers/memstick/core/ms_block.c ++++ b/drivers/memstick/core/ms_block.c +@@ -2157,10 +2157,14 @@ static int msb_init_disk(struct memstick_dev *card) + set_disk_ro(msb->disk, 1); + + msb_start(card); +- device_add_disk(&card->dev, msb->disk, NULL); ++ rc = device_add_disk(&card->dev, msb->disk, NULL); ++ if (rc) ++ goto out_cleanup_disk; + dbg("Disk added"); + return 0; + ++out_cleanup_disk: ++ blk_cleanup_disk(msb->disk); + out_free_tag_set: + blk_mq_free_tag_set(&msb->tag_set); + out_release_id: +-- +2.35.1 + diff --git a/queue-5.15/mfd-bd957x-fix-kconfig-dependency-on-regmap_irq.patch b/queue-5.15/mfd-bd957x-fix-kconfig-dependency-on-regmap_irq.patch new file mode 100644 index 00000000000..50e2993790b --- /dev/null +++ b/queue-5.15/mfd-bd957x-fix-kconfig-dependency-on-regmap_irq.patch @@ -0,0 +1,36 @@ +From 2d02af5161e8febf6f889e5e940ba7414d65e79b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 10:19:21 +0200 +Subject: mfd: bd957x: Fix Kconfig dependency on REGMAP_IRQ + +From: Matti Vaittinen + +[ Upstream commit 85842c46fd47fa6bd78681c154223bed27d5fd19 ] + +The BD957x driver uses REGMAP_IRQ but does not 'select' to depend on +it. This can cause build failures. Select REGMAP_IRQ for BD957X. + +Fixes: 0e9692607f94 ("mfd: bd9576: Add IRQ support") +Signed-off-by: Matti Vaittinen +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/Y3SdCWkRr1L64SWK@dc75zzyyyyyyyyyyyyydt-3.rev.dnainternet.fi +Signed-off-by: Sasha Levin +--- + drivers/mfd/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig +index d2f345245538..5dd7ea0ebd46 100644 +--- a/drivers/mfd/Kconfig ++++ b/drivers/mfd/Kconfig +@@ -1995,6 +1995,7 @@ config MFD_ROHM_BD957XMUF + depends on I2C=y + depends on OF + select REGMAP_I2C ++ select REGMAP_IRQ + select MFD_CORE + help + Select this option to get support for the ROHM BD9576MUF and +-- +2.35.1 + diff --git a/queue-5.15/mfd-pm8008-fix-return-value-check-in-pm8008_probe.patch b/queue-5.15/mfd-pm8008-fix-return-value-check-in-pm8008_probe.patch new file mode 100644 index 00000000000..b02757a0eac --- /dev/null +++ b/queue-5.15/mfd-pm8008-fix-return-value-check-in-pm8008_probe.patch @@ -0,0 +1,42 @@ +From 3eff7a153b539a1e38931983c759f5ff0dc59cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 15:36:26 +0800 +Subject: mfd: pm8008: Fix return value check in pm8008_probe() + +From: Yang Yingliang + +[ Upstream commit 14f8c55d48e02157519fbcb3a5de557abd8a06e2 ] + +In case of error, the function devm_regmap_init_i2c() returns +ERR_PTR() and never returns NULL. The NULL test in the return +value check should be replaced with IS_ERR(). + +Fixes: 6b149f3310a4 ("mfd: pm8008: Add driver for QCOM PM8008 PMIC") +Signed-off-by: Yang Yingliang +Reviewed-by: Bjorn Andersson +Acked-by: Guru Das Srinagesh +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20221125073626.1868229-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/mfd/qcom-pm8008.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c +index 4b8ff947762f..9f3c4a01b4c1 100644 +--- a/drivers/mfd/qcom-pm8008.c ++++ b/drivers/mfd/qcom-pm8008.c +@@ -215,8 +215,8 @@ static int pm8008_probe(struct i2c_client *client) + + dev = &client->dev; + regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); +- if (!regmap) +- return -ENODEV; ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); + + i2c_set_clientdata(client, regmap); + +-- +2.35.1 + diff --git a/queue-5.15/mfd-pm8008-remove-driver-data-structure-pm8008_data.patch b/queue-5.15/mfd-pm8008-remove-driver-data-structure-pm8008_data.patch new file mode 100644 index 00000000000..5287c9e3127 --- /dev/null +++ b/queue-5.15/mfd-pm8008-remove-driver-data-structure-pm8008_data.patch @@ -0,0 +1,144 @@ +From dc88bc3af526753e5ddd5ab1c6f874df8ca68e45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jun 2022 09:14:02 +0100 +Subject: mfd: pm8008: Remove driver data structure pm8008_data + +From: Lee Jones + +[ Upstream commit 915696927cd6e7838d25dab8fbd2ae05d4acce84 ] + +Maintaining a local driver data structure that is never shared +outside of the core device is an unnecessary complexity. Half of the +attributes were not used outside of a single function, one of which +was not used at all. The remaining 2 are generic and can be passed +around as required. + +Signed-off-by: Lee Jones +Stable-dep-of: 14f8c55d48e0 ("mfd: pm8008: Fix return value check in pm8008_probe()") +Signed-off-by: Sasha Levin +--- + drivers/mfd/qcom-pm8008.c | 53 +++++++++++++++------------------------ + 1 file changed, 20 insertions(+), 33 deletions(-) + +diff --git a/drivers/mfd/qcom-pm8008.c b/drivers/mfd/qcom-pm8008.c +index c472d7f8103c..4b8ff947762f 100644 +--- a/drivers/mfd/qcom-pm8008.c ++++ b/drivers/mfd/qcom-pm8008.c +@@ -54,13 +54,6 @@ enum { + + #define PM8008_PERIPH_OFFSET(paddr) (paddr - PM8008_PERIPH_0_BASE) + +-struct pm8008_data { +- struct device *dev; +- struct regmap *regmap; +- int irq; +- struct regmap_irq_chip_data *irq_data; +-}; +- + static unsigned int p0_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_0_BASE)}; + static unsigned int p1_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_1_BASE)}; + static unsigned int p2_offs[] = {PM8008_PERIPH_OFFSET(PM8008_PERIPH_2_BASE)}; +@@ -150,7 +143,7 @@ static struct regmap_config qcom_mfd_regmap_cfg = { + .max_register = 0xFFFF, + }; + +-static int pm8008_init(struct pm8008_data *chip) ++static int pm8008_init(struct regmap *regmap) + { + int rc; + +@@ -160,34 +153,31 @@ static int pm8008_init(struct pm8008_data *chip) + * This is required to enable the writing of TYPE registers in + * regmap_irq_sync_unlock(). + */ +- rc = regmap_write(chip->regmap, +- (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), +- BIT(0)); ++ rc = regmap_write(regmap, (PM8008_TEMP_ALARM_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); + if (rc) + return rc; + + /* Do the same for GPIO1 and GPIO2 peripherals */ +- rc = regmap_write(chip->regmap, +- (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); ++ rc = regmap_write(regmap, (PM8008_GPIO1_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); + if (rc) + return rc; + +- rc = regmap_write(chip->regmap, +- (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); ++ rc = regmap_write(regmap, (PM8008_GPIO2_ADDR | INT_SET_TYPE_OFFSET), BIT(0)); + + return rc; + } + +-static int pm8008_probe_irq_peripherals(struct pm8008_data *chip, ++static int pm8008_probe_irq_peripherals(struct device *dev, ++ struct regmap *regmap, + int client_irq) + { + int rc, i; + struct regmap_irq_type *type; + struct regmap_irq_chip_data *irq_data; + +- rc = pm8008_init(chip); ++ rc = pm8008_init(regmap); + if (rc) { +- dev_err(chip->dev, "Init failed: %d\n", rc); ++ dev_err(dev, "Init failed: %d\n", rc); + return rc; + } + +@@ -207,10 +197,10 @@ static int pm8008_probe_irq_peripherals(struct pm8008_data *chip, + IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW); + } + +- rc = devm_regmap_add_irq_chip(chip->dev, chip->regmap, client_irq, ++ rc = devm_regmap_add_irq_chip(dev, regmap, client_irq, + IRQF_SHARED, 0, &pm8008_irq_chip, &irq_data); + if (rc) { +- dev_err(chip->dev, "Failed to add IRQ chip: %d\n", rc); ++ dev_err(dev, "Failed to add IRQ chip: %d\n", rc); + return rc; + } + +@@ -220,26 +210,23 @@ static int pm8008_probe_irq_peripherals(struct pm8008_data *chip, + static int pm8008_probe(struct i2c_client *client) + { + int rc; +- struct pm8008_data *chip; +- +- chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); +- if (!chip) +- return -ENOMEM; ++ struct device *dev; ++ struct regmap *regmap; + +- chip->dev = &client->dev; +- chip->regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); +- if (!chip->regmap) ++ dev = &client->dev; ++ regmap = devm_regmap_init_i2c(client, &qcom_mfd_regmap_cfg); ++ if (!regmap) + return -ENODEV; + +- i2c_set_clientdata(client, chip); ++ i2c_set_clientdata(client, regmap); + +- if (of_property_read_bool(chip->dev->of_node, "interrupt-controller")) { +- rc = pm8008_probe_irq_peripherals(chip, client->irq); ++ if (of_property_read_bool(dev->of_node, "interrupt-controller")) { ++ rc = pm8008_probe_irq_peripherals(dev, regmap, client->irq); + if (rc) +- dev_err(chip->dev, "Failed to probe irq periphs: %d\n", rc); ++ dev_err(dev, "Failed to probe irq periphs: %d\n", rc); + } + +- return devm_of_platform_populate(chip->dev); ++ return devm_of_platform_populate(dev); + } + + static const struct of_device_id pm8008_match[] = { +-- +2.35.1 + diff --git a/queue-5.15/mfd-qcom_rpm-fix-an-error-handling-path-in-qcom_rpm_.patch b/queue-5.15/mfd-qcom_rpm-fix-an-error-handling-path-in-qcom_rpm_.patch new file mode 100644 index 00000000000..ae23e217042 --- /dev/null +++ b/queue-5.15/mfd-qcom_rpm-fix-an-error-handling-path-in-qcom_rpm_.patch @@ -0,0 +1,55 @@ +From 03df98df886693fb99ffa363daaf90d35beae268 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 18:19:01 +0100 +Subject: mfd: qcom_rpm: Fix an error handling path in qcom_rpm_probe() + +From: Christophe JAILLET + +[ Upstream commit 36579aca877a62f67ecd77eb3edefc4c86292406 ] + +If an error occurs after the clk_prepare_enable() call, a corresponding +clk_disable_unprepare() should be called. + +Simplify code and switch to devm_clk_get_enabled() to fix it. + +Fixes: 3526403353c2 ("mfd: qcom_rpm: Handle message RAM clock") +Signed-off-by: Christophe JAILLET +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/e39752476d02605b2be46cab7115f71255ce13a8.1668949256.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/mfd/qcom_rpm.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c +index 71bc34b74bc9..ea5eb94427c4 100644 +--- a/drivers/mfd/qcom_rpm.c ++++ b/drivers/mfd/qcom_rpm.c +@@ -547,7 +547,7 @@ static int qcom_rpm_probe(struct platform_device *pdev) + init_completion(&rpm->ack); + + /* Enable message RAM clock */ +- rpm->ramclk = devm_clk_get(&pdev->dev, "ram"); ++ rpm->ramclk = devm_clk_get_enabled(&pdev->dev, "ram"); + if (IS_ERR(rpm->ramclk)) { + ret = PTR_ERR(rpm->ramclk); + if (ret == -EPROBE_DEFER) +@@ -558,7 +558,6 @@ static int qcom_rpm_probe(struct platform_device *pdev) + */ + rpm->ramclk = NULL; + } +- clk_prepare_enable(rpm->ramclk); /* Accepts NULL */ + + irq_ack = platform_get_irq_byname(pdev, "ack"); + if (irq_ack < 0) +@@ -681,7 +680,6 @@ static int qcom_rpm_remove(struct platform_device *pdev) + struct qcom_rpm *rpm = dev_get_drvdata(&pdev->dev); + + of_platform_depopulate(&pdev->dev); +- clk_disable_unprepare(rpm->ramclk); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/mips-bcm63xx-add-check-for-null-for-clk-in-clk_enabl.patch b/queue-5.15/mips-bcm63xx-add-check-for-null-for-clk-in-clk_enabl.patch new file mode 100644 index 00000000000..359101aefbe --- /dev/null +++ b/queue-5.15/mips-bcm63xx-add-check-for-null-for-clk-in-clk_enabl.patch @@ -0,0 +1,44 @@ +From af64416ab6923dd1ce9d6b97aacbb9ad0517f32d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 13:05:50 +0300 +Subject: MIPS: BCM63xx: Add check for NULL for clk in clk_enable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Anastasia Belova + +[ Upstream commit ee9ef11bd2a59c2fefaa0959e5efcdf040d7c654 ] + +Check clk for NULL before calling clk_enable_unlocked where clk +is dereferenced. There is such check in other implementations +of clk_enable. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: e7300d04bd08 ("MIPS: BCM63xx: Add support for the Broadcom BCM63xx family of SOCs.") +Signed-off-by: Anastasia Belova +Reviewed-by: Philippe Mathieu-Daudé +Acked-by: Florian Fainelli +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/bcm63xx/clk.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c +index 6e6756e8fa0a..86a6e2590866 100644 +--- a/arch/mips/bcm63xx/clk.c ++++ b/arch/mips/bcm63xx/clk.c +@@ -361,6 +361,8 @@ static struct clk clk_periph = { + */ + int clk_enable(struct clk *clk) + { ++ if (!clk) ++ return 0; + mutex_lock(&clocks_mutex); + clk_enable_unlocked(clk); + mutex_unlock(&clocks_mutex); +-- +2.35.1 + diff --git a/queue-5.15/mips-octeon-warn-only-once-if-deprecated-link-status.patch b/queue-5.15/mips-octeon-warn-only-once-if-deprecated-link-status.patch new file mode 100644 index 00000000000..818c8412392 --- /dev/null +++ b/queue-5.15/mips-octeon-warn-only-once-if-deprecated-link-status.patch @@ -0,0 +1,53 @@ +From b255f483c580808d1d95799f95086b34ae7f38fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 12:25:57 +0100 +Subject: MIPS: OCTEON: warn only once if deprecated link status is being used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ladislav Michl + +[ Upstream commit 4c587a982603d7e7e751b4925809a1512099a690 ] + +Avoid flooding kernel log with warnings. + +Fixes: 2c0756d306c2 ("MIPS: OCTEON: warn if deprecated link status is being used") +Signed-off-by: Ladislav Michl +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/cavium-octeon/executive/cvmx-helper-board.c | 2 +- + arch/mips/cavium-octeon/executive/cvmx-helper.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +index 1daa0c6b6f4e..572a053e30ed 100644 +--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c +@@ -211,7 +211,7 @@ union cvmx_helper_link_info __cvmx_helper_board_link_get(int ipd_port) + { + union cvmx_helper_link_info result; + +- WARN(!octeon_is_simulation(), ++ WARN_ONCE(!octeon_is_simulation(), + "Using deprecated link status - please update your DT"); + + /* Unless we fix it later, all links are defaulted to down */ +diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c +index 6044ff471002..a18ad2daf005 100644 +--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c ++++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c +@@ -1100,7 +1100,7 @@ union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port) + if (index == 0) + result = __cvmx_helper_rgmii_link_get(ipd_port); + else { +- WARN(1, "Using deprecated link status - please update your DT"); ++ WARN_ONCE(1, "Using deprecated link status - please update your DT"); + result.s.full_duplex = 1; + result.s.link_up = 1; + result.s.speed = 1000; +-- +2.35.1 + diff --git a/queue-5.15/mips-ralink-mt7621-define-mt7621_sysc_base-with-__io.patch b/queue-5.15/mips-ralink-mt7621-define-mt7621_sysc_base-with-__io.patch new file mode 100644 index 00000000000..37c1561fe32 --- /dev/null +++ b/queue-5.15/mips-ralink-mt7621-define-mt7621_sysc_base-with-__io.patch @@ -0,0 +1,74 @@ +From 642699598e653c123c31d41dfcf2bd6393aec405 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 11:56:56 +1000 +Subject: mips: ralink: mt7621: define MT7621_SYSC_BASE with __iomem + +From: John Thomson + +[ Upstream commit a2cab953b4c077cc02878d424466d3a6eac32aaf ] + +So that MT7621_SYSC_BASE can be used later in multiple functions without +needing to repeat this __iomem declaration each time + +Signed-off-by: John Thomson +Signed-off-by: Thomas Bogendoerfer +Stable-dep-of: 7c18b64bba3b ("mips: ralink: mt7621: do not use kzalloc too early") +Signed-off-by: Sasha Levin +--- + arch/mips/include/asm/mach-ralink/mt7621.h | 4 +++- + arch/mips/ralink/mt7621.c | 7 +++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/arch/mips/include/asm/mach-ralink/mt7621.h b/arch/mips/include/asm/mach-ralink/mt7621.h +index 6bbf082dd149..79d5bb0e06d6 100644 +--- a/arch/mips/include/asm/mach-ralink/mt7621.h ++++ b/arch/mips/include/asm/mach-ralink/mt7621.h +@@ -7,10 +7,12 @@ + #ifndef _MT7621_REGS_H_ + #define _MT7621_REGS_H_ + ++#define IOMEM(x) ((void __iomem *)(KSEG1ADDR(x))) ++ + #define MT7621_PALMBUS_BASE 0x1C000000 + #define MT7621_PALMBUS_SIZE 0x03FFFFFF + +-#define MT7621_SYSC_BASE 0x1E000000 ++#define MT7621_SYSC_BASE IOMEM(0x1E000000) + + #define SYSC_REG_CHIP_NAME0 0x00 + #define SYSC_REG_CHIP_NAME1 0x04 +diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c +index 4c8378661219..af66886f1366 100644 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -95,7 +95,6 @@ static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) + + void __init prom_soc_init(struct ralink_soc_info *soc_info) + { +- void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); + unsigned char *name = NULL; + u32 n0; + u32 n1; +@@ -123,8 +122,8 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info) + __sync(); + } + +- n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0); +- n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1); ++ n0 = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); ++ n1 = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME1); + + if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) { + name = "MT7621"; +@@ -133,7 +132,7 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info) + panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1); + } + ralink_soc = MT762X_SOC_MT7621AT; +- rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); ++ rev = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_REV); + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "MediaTek %s ver:%u eco:%u", +-- +2.35.1 + diff --git a/queue-5.15/mips-ralink-mt7621-do-not-use-kzalloc-too-early.patch b/queue-5.15/mips-ralink-mt7621-do-not-use-kzalloc-too-early.patch new file mode 100644 index 00000000000..ff35bdea2db --- /dev/null +++ b/queue-5.15/mips-ralink-mt7621-do-not-use-kzalloc-too-early.patch @@ -0,0 +1,138 @@ +From be7c2f8a64472570bc47add9dce2f8dfc4bf8bd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 11:56:58 +1000 +Subject: mips: ralink: mt7621: do not use kzalloc too early + +From: John Thomson + +[ Upstream commit 7c18b64bba3bcad1be94b404f47b94a04b91ce79 ] + +With CONFIG_SLUB=y, following commit 6edf2576a6cc ("mm/slub: enable +debugging memory wasting of kmalloc") mt7621 failed to boot very early, +without showing any console messages. +This exposed the pre-existing bug of mt7621.c using kzalloc before normal +memory management was available. +Prior to this slub change, there existed the unintended protection against +"kmem_cache *s" being NULL as slab_pre_alloc_hook() happened to +return NULL and bailed out of slab_alloc_node(). +This allowed mt7621 prom_soc_init to fail in the soc_dev_init kzalloc, +but continue booting without the SOC_BUS driver device registered. + +Console output from a DEBUG_ZBOOT vmlinuz kernel loading, +with mm/slub modified to warn on kmem_cache zero or null: + +zimage at: 80B842A0 810B4BC0 +Uncompressing Linux at load address 80001000 +Copy device tree to address 80B80EE0 +Now, booting the kernel... + +[ 0.000000] Linux version 6.1.0-rc3+ (john@john) +(mipsel-buildroot-linux-gnu-gcc.br_real (Buildroot +2021.11-4428-g6b6741b) 12.2.0, GNU ld (GNU Binutils) 2.39) #73 SMP Wed + Nov 2 05:10:01 AEST 2022 +[ 0.000000] ------------[ cut here ]------------ +[ 0.000000] WARNING: CPU: 0 PID: 0 at mm/slub.c:3416 +kmem_cache_alloc+0x5a4/0x5e8 +[ 0.000000] Modules linked in: +[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 6.1.0-rc3+ #73 +[ 0.000000] Stack : 810fff78 80084d98 00000000 00000004 00000000 +00000000 80889d04 80c90000 +[ 0.000000] 80920000 807bd328 8089d368 80923bd3 00000000 +00000001 80889cb0 00000000 +[ 0.000000] 00000000 00000000 807bd328 8084bcb1 00000002 +00000002 00000001 6d6f4320 +[ 0.000000] 00000000 80c97d3d 80c97d68 fffffffc 807bd328 +00000000 00000000 00000000 +[ 0.000000] 00000000 a0000000 80910000 8110a0b4 00000000 +00000020 80010000 80010000 +[ 0.000000] ... +[ 0.000000] Call Trace: +[ 0.000000] [<80008260>] show_stack+0x28/0xf0 +[ 0.000000] [<8070c958>] dump_stack_lvl+0x60/0x80 +[ 0.000000] [<8002e184>] __warn+0xc4/0xf8 +[ 0.000000] [<8002e210>] warn_slowpath_fmt+0x58/0xa4 +[ 0.000000] [<801c0fac>] kmem_cache_alloc+0x5a4/0x5e8 +[ 0.000000] [<8092856c>] prom_soc_init+0x1fc/0x2b4 +[ 0.000000] [<80928060>] prom_init+0x44/0xf0 +[ 0.000000] [<80929214>] setup_arch+0x4c/0x6a8 +[ 0.000000] [<809257e0>] start_kernel+0x88/0x7c0 +[ 0.000000] +[ 0.000000] ---[ end trace 0000000000000000 ]--- +[ 0.000000] SoC Type: MediaTek MT7621 ver:1 eco:3 +[ 0.000000] printk: bootconsole [early0] enabled + +Allowing soc_device_register to work exposed oops in the mt7621 phy pci, +and pci controller drivers from soc_device_match_attr, due to missing +sentinels in the quirks tables. These were fixed with: +commit 819b885cd886 ("phy: ralink: mt7621-pci: add sentinel to quirks +table") +not yet applied ("PCI: mt7621: add sentinel to quirks table") + +Link: https://lore.kernel.org/linux-mm/becf2ac3-2a90-4f3a-96d9-a70f67c66e4a@app.fastmail.com/ +Fixes: 71b9b5e0130d ("MIPS: ralink: mt7621: introduce 'soc_device' initialization") +Signed-off-by: John Thomson +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/ralink/mt7621.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c +index 6b4c291d6d1b..0db23bcf2a97 100644 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -23,6 +23,7 @@ + #define MT7621_MEM_TEST_PATTERN 0xaa5555aa + + static u32 detect_magic __initdata; ++static struct ralink_soc_info *soc_info_ptr; + + phys_addr_t mips_cpc_default_phys_base(void) + { +@@ -116,27 +117,30 @@ static const char __init *mt7621_get_soc_revision(void) + return "E1"; + } + +-static void soc_dev_init(struct ralink_soc_info *soc_info) ++static int __init mt7621_soc_dev_init(void) + { + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) +- return; ++ return -ENOMEM; + + soc_dev_attr->soc_id = "mt7621"; + soc_dev_attr->family = "Ralink"; + soc_dev_attr->revision = mt7621_get_soc_revision(); + +- soc_dev_attr->data = soc_info; ++ soc_dev_attr->data = soc_info_ptr; + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr); +- return; ++ return PTR_ERR(soc_dev); + } ++ ++ return 0; + } ++device_initcall(mt7621_soc_dev_init); + + void __init prom_soc_init(struct ralink_soc_info *soc_info) + { +@@ -178,7 +182,7 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info) + + soc_info->mem_detect = mt7621_memory_detect; + +- soc_dev_init(soc_info); ++ soc_info_ptr = soc_info; + + if (!register_cps_smp_ops()) + return; +-- +2.35.1 + diff --git a/queue-5.15/mips-ralink-mt7621-soc-queries-and-tests-as-function.patch b/queue-5.15/mips-ralink-mt7621-soc-queries-and-tests-as-function.patch new file mode 100644 index 00000000000..701e2bd7386 --- /dev/null +++ b/queue-5.15/mips-ralink-mt7621-soc-queries-and-tests-as-function.patch @@ -0,0 +1,150 @@ +From 34e2bf63dab5373861fa997377dd60d72fb81cca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 11:56:57 +1000 +Subject: mips: ralink: mt7621: soc queries and tests as functions + +From: John Thomson + +[ Upstream commit b4767d4c072583dec987225b6fe3f5524a735f42 ] + +Move the SoC register value queries and tests to specific functions, +to remove repetition of logic +No functional changes intended + +Signed-off-by: John Thomson +Signed-off-by: Thomas Bogendoerfer +Stable-dep-of: 7c18b64bba3b ("mips: ralink: mt7621: do not use kzalloc too early") +Signed-off-by: Sasha Levin +--- + arch/mips/ralink/mt7621.c | 86 +++++++++++++++++++++++++++------------ + 1 file changed, 61 insertions(+), 25 deletions(-) + +diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c +index af66886f1366..6b4c291d6d1b 100644 +--- a/arch/mips/ralink/mt7621.c ++++ b/arch/mips/ralink/mt7621.c +@@ -66,7 +66,57 @@ void __init ralink_of_remap(void) + panic("Failed to remap core resources"); + } + +-static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) ++static unsigned int __init mt7621_get_soc_name0(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); ++} ++ ++static unsigned int __init mt7621_get_soc_name1(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME1); ++} ++ ++static bool __init mt7621_soc_valid(void) ++{ ++ if (mt7621_get_soc_name0() == MT7621_CHIP_NAME0 && ++ mt7621_get_soc_name1() == MT7621_CHIP_NAME1) ++ return true; ++ else ++ return false; ++} ++ ++static const char __init *mt7621_get_soc_id(void) ++{ ++ if (mt7621_soc_valid()) ++ return "MT7621"; ++ else ++ return "invalid"; ++} ++ ++static unsigned int __init mt7621_get_soc_rev(void) ++{ ++ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_REV); ++} ++ ++static unsigned int __init mt7621_get_soc_ver(void) ++{ ++ return (mt7621_get_soc_rev() >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK; ++} ++ ++static unsigned int __init mt7621_get_soc_eco(void) ++{ ++ return (mt7621_get_soc_rev() & CHIP_REV_ECO_MASK); ++} ++ ++static const char __init *mt7621_get_soc_revision(void) ++{ ++ if (mt7621_get_soc_rev() == 1 && mt7621_get_soc_eco() == 1) ++ return "E2"; ++ else ++ return "E1"; ++} ++ ++static void soc_dev_init(struct ralink_soc_info *soc_info) + { + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; +@@ -77,12 +127,7 @@ static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) + + soc_dev_attr->soc_id = "mt7621"; + soc_dev_attr->family = "Ralink"; +- +- if (((rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK) == 1 && +- (rev & CHIP_REV_ECO_MASK) == 1) +- soc_dev_attr->revision = "E2"; +- else +- soc_dev_attr->revision = "E1"; ++ soc_dev_attr->revision = mt7621_get_soc_revision(); + + soc_dev_attr->data = soc_info; + +@@ -95,11 +140,6 @@ static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev) + + void __init prom_soc_init(struct ralink_soc_info *soc_info) + { +- unsigned char *name = NULL; +- u32 n0; +- u32 n1; +- u32 rev; +- + /* Early detection of CMP support */ + mips_cm_probe(); + mips_cpc_probe(); +@@ -122,27 +162,23 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info) + __sync(); + } + +- n0 = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0); +- n1 = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME1); +- +- if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) { +- name = "MT7621"; ++ if (mt7621_soc_valid()) + soc_info->compatible = "mediatek,mt7621-soc"; +- } else { +- panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1); +- } ++ else ++ panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", ++ mt7621_get_soc_name0(), ++ mt7621_get_soc_name1()); + ralink_soc = MT762X_SOC_MT7621AT; +- rev = __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_REV); + + snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, + "MediaTek %s ver:%u eco:%u", +- name, +- (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK, +- (rev & CHIP_REV_ECO_MASK)); ++ mt7621_get_soc_id(), ++ mt7621_get_soc_ver(), ++ mt7621_get_soc_eco()); + + soc_info->mem_detect = mt7621_memory_detect; + +- soc_dev_init(soc_info, rev); ++ soc_dev_init(soc_info); + + if (!register_cps_smp_ops()) + return; +-- +2.35.1 + diff --git a/queue-5.15/mips-vpe-cmp-fix-possible-memory-leak-while-module-e.patch b/queue-5.15/mips-vpe-cmp-fix-possible-memory-leak-while-module-e.patch new file mode 100644 index 00000000000..289020b0937 --- /dev/null +++ b/queue-5.15/mips-vpe-cmp-fix-possible-memory-leak-while-module-e.patch @@ -0,0 +1,55 @@ +From 5ee47304104bf243a3225758825a248b84da7fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 11:39:45 +0800 +Subject: MIPS: vpe-cmp: fix possible memory leak while module exiting + +From: Yang Yingliang + +[ Upstream commit c5ed1fe0801f0c66b0fbce2785239a5664629057 ] + +dev_set_name() allocates memory for name, it need be freed +when module exiting, call put_device() to give up reference, +so that it can be freed in kobject_cleanup() when the refcount +hit to 0. The vpe_device is static, so remove kfree() from +vpe_device_release(). + +Fixes: 17a1d523aa58 ("MIPS: APRP: Add VPE loader support for CMP platforms.") +Signed-off-by: Yang Yingliang +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/vpe-cmp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c +index e673603e11e5..92140edb3ce3 100644 +--- a/arch/mips/kernel/vpe-cmp.c ++++ b/arch/mips/kernel/vpe-cmp.c +@@ -75,7 +75,6 @@ ATTRIBUTE_GROUPS(vpe); + + static void vpe_device_release(struct device *cd) + { +- kfree(cd); + } + + static struct class vpe_class = { +@@ -157,6 +156,7 @@ int __init vpe_module_init(void) + device_del(&vpe_device); + + out_class: ++ put_device(&vpe_device); + class_unregister(&vpe_class); + + out_chrdev: +@@ -169,7 +169,7 @@ void __exit vpe_module_exit(void) + { + struct vpe *v, *n; + +- device_del(&vpe_device); ++ device_unregister(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + +-- +2.35.1 + diff --git a/queue-5.15/mips-vpe-mt-fix-possible-memory-leak-while-module-ex.patch b/queue-5.15/mips-vpe-mt-fix-possible-memory-leak-while-module-ex.patch new file mode 100644 index 00000000000..ed8127dd1e4 --- /dev/null +++ b/queue-5.15/mips-vpe-mt-fix-possible-memory-leak-while-module-ex.patch @@ -0,0 +1,56 @@ +From 7ddb3762b347906931125524d4ad48775243c6e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 11:39:44 +0800 +Subject: MIPS: vpe-mt: fix possible memory leak while module exiting + +From: Yang Yingliang + +[ Upstream commit 5822e8cc84ee37338ab0bdc3124f6eec04dc232d ] + +Afer commit 1fa5ae857bb1 ("driver core: get rid of struct device's +bus_id string array"), the name of device is allocated dynamically, +it need be freed when module exiting, call put_device() to give up +reference, so that it can be freed in kobject_cleanup() when the +refcount hit to 0. The vpe_device is static, so remove kfree() from +vpe_device_release(). + +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/kernel/vpe-mt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c +index bad6b0891b2b..84a82b551ec3 100644 +--- a/arch/mips/kernel/vpe-mt.c ++++ b/arch/mips/kernel/vpe-mt.c +@@ -313,7 +313,6 @@ ATTRIBUTE_GROUPS(vpe); + + static void vpe_device_release(struct device *cd) + { +- kfree(cd); + } + + static struct class vpe_class = { +@@ -497,6 +496,7 @@ int __init vpe_module_init(void) + device_del(&vpe_device); + + out_class: ++ put_device(&vpe_device); + class_unregister(&vpe_class); + + out_chrdev: +@@ -509,7 +509,7 @@ void __exit vpe_module_exit(void) + { + struct vpe *v, *n; + +- device_del(&vpe_device); ++ device_unregister(&vpe_device); + class_unregister(&vpe_class); + unregister_chrdev(major, VPE_MODULE_NAME); + +-- +2.35.1 + diff --git a/queue-5.15/misc-ocxl-fix-possible-name-leak-in-ocxl_file_regist.patch b/queue-5.15/misc-ocxl-fix-possible-name-leak-in-ocxl_file_regist.patch new file mode 100644 index 00000000000..88edebff0d0 --- /dev/null +++ b/queue-5.15/misc-ocxl-fix-possible-name-leak-in-ocxl_file_regist.patch @@ -0,0 +1,48 @@ +From 0dae9e8fe5ae92935035e9769e677e206af3094e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 22:59:29 +0800 +Subject: misc: ocxl: fix possible name leak in ocxl_file_register_afu() + +From: Yang Yingliang + +[ Upstream commit a4cb1004aeed2ab893a058fad00a5b41a12c4691 ] + +If device_register() returns error in ocxl_file_register_afu(), +the name allocated by dev_set_name() need be freed. As comment +of device_register() says, it should use put_device() to give +up the reference in the error path. So fix this by calling +put_device(), then the name can be freed in kobject_cleanup(), +and info is freed in info_release(). + +Fixes: 75ca758adbaf ("ocxl: Create a clear delineation between ocxl backend & frontend") +Signed-off-by: Yang Yingliang +Acked-by: Andrew Donnellan +Acked-by: Frederic Barrat +Link: https://lore.kernel.org/r/20221111145929.2429271-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/ocxl/file.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c +index 134806c2e67e..a199c7ce3f81 100644 +--- a/drivers/misc/ocxl/file.c ++++ b/drivers/misc/ocxl/file.c +@@ -543,8 +543,11 @@ int ocxl_file_register_afu(struct ocxl_afu *afu) + goto err_put; + + rc = device_register(&info->dev); +- if (rc) +- goto err_put; ++ if (rc) { ++ free_minor(info); ++ put_device(&info->dev); ++ return rc; ++ } + + rc = ocxl_sysfs_register_afu(info); + if (rc) +-- +2.35.1 + diff --git a/queue-5.15/misc-sgi-gru-fix-use-after-free-error-in-gru_set_con.patch b/queue-5.15/misc-sgi-gru-fix-use-after-free-error-in-gru_set_con.patch new file mode 100644 index 00000000000..0c70e5126e4 --- /dev/null +++ b/queue-5.15/misc-sgi-gru-fix-use-after-free-error-in-gru_set_con.patch @@ -0,0 +1,140 @@ +From 14df393305c7086e7a156b3dfb1bc980ac45a860 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 11:50:33 +0800 +Subject: misc: sgi-gru: fix use-after-free error in gru_set_context_option, + gru_fault and gru_handle_user_call_os + +From: Zheng Wang + +[ Upstream commit 643a16a0eb1d6ac23744bb6e90a00fc21148a9dc ] + +In some bad situation, the gts may be freed gru_check_chiplet_assignment. +The call chain can be gru_unload_context->gru_free_gru_context->gts_drop +and kfree finally. However, the caller didn't know if the gts is freed +or not and use it afterwards. This will trigger a Use after Free bug. + +Fix it by introducing a return value to see if it's in error path or not. +Free the gts in caller if gru_check_chiplet_assignment check failed. + +Fixes: 55484c45dbec ("gru: allow users to specify gru chiplet 2") +Signed-off-by: Zheng Wang +Acked-by: Dimitri Sivanich +Link: https://lore.kernel.org/r/20221110035033.19498-1-zyytlz.wz@163.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/sgi-gru/grufault.c | 13 +++++++++++-- + drivers/misc/sgi-gru/grumain.c | 22 ++++++++++++++++++---- + drivers/misc/sgi-gru/grutables.h | 2 +- + 3 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c +index d7ef61e602ed..b836936e9747 100644 +--- a/drivers/misc/sgi-gru/grufault.c ++++ b/drivers/misc/sgi-gru/grufault.c +@@ -648,6 +648,7 @@ int gru_handle_user_call_os(unsigned long cb) + if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB) + return -EINVAL; + ++again: + gts = gru_find_lock_gts(cb); + if (!gts) + return -EINVAL; +@@ -656,7 +657,11 @@ int gru_handle_user_call_os(unsigned long cb) + if (ucbnum >= gts->ts_cbr_au_count * GRU_CBR_AU_SIZE) + goto exit; + +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ gru_unlock_gts(gts); ++ gru_unload_context(gts, 1); ++ goto again; ++ } + + /* + * CCH may contain stale data if ts_force_cch_reload is set. +@@ -874,7 +879,11 @@ int gru_set_context_option(unsigned long arg) + } else { + gts->ts_user_blade_id = req.val1; + gts->ts_user_chiplet_id = req.val0; +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ gru_unlock_gts(gts); ++ gru_unload_context(gts, 1); ++ return ret; ++ } + } + break; + case sco_gseg_owner: +diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c +index 9afda47efbf2..3a16eb8e03f7 100644 +--- a/drivers/misc/sgi-gru/grumain.c ++++ b/drivers/misc/sgi-gru/grumain.c +@@ -716,9 +716,10 @@ static int gru_check_chiplet_assignment(struct gru_state *gru, + * chiplet. Misassignment can occur if the process migrates to a different + * blade or if the user changes the selected blade/chiplet. + */ +-void gru_check_context_placement(struct gru_thread_state *gts) ++int gru_check_context_placement(struct gru_thread_state *gts) + { + struct gru_state *gru; ++ int ret = 0; + + /* + * If the current task is the context owner, verify that the +@@ -726,15 +727,23 @@ void gru_check_context_placement(struct gru_thread_state *gts) + * references. Pthread apps use non-owner references to the CBRs. + */ + gru = gts->ts_gru; ++ /* ++ * If gru or gts->ts_tgid_owner isn't initialized properly, return ++ * success to indicate that the caller does not need to unload the ++ * gru context.The caller is responsible for their inspection and ++ * reinitialization if needed. ++ */ + if (!gru || gts->ts_tgid_owner != current->tgid) +- return; ++ return ret; + + if (!gru_check_chiplet_assignment(gru, gts)) { + STAT(check_context_unload); +- gru_unload_context(gts, 1); ++ ret = -EINVAL; + } else if (gru_retarget_intr(gts)) { + STAT(check_context_retarget_intr); + } ++ ++ return ret; + } + + +@@ -934,7 +943,12 @@ vm_fault_t gru_fault(struct vm_fault *vmf) + mutex_lock(>s->ts_ctxlock); + preempt_disable(); + +- gru_check_context_placement(gts); ++ if (gru_check_context_placement(gts)) { ++ preempt_enable(); ++ mutex_unlock(>s->ts_ctxlock); ++ gru_unload_context(gts, 1); ++ return VM_FAULT_NOPAGE; ++ } + + if (!gts->ts_gru) { + STAT(load_user_context); +diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h +index e4c067c61251..5c9783150cdf 100644 +--- a/drivers/misc/sgi-gru/grutables.h ++++ b/drivers/misc/sgi-gru/grutables.h +@@ -638,7 +638,7 @@ extern int gru_user_flush_tlb(unsigned long arg); + extern int gru_user_unload_context(unsigned long arg); + extern int gru_get_exception_detail(unsigned long arg); + extern int gru_set_context_option(unsigned long address); +-extern void gru_check_context_placement(struct gru_thread_state *gts); ++extern int gru_check_context_placement(struct gru_thread_state *gts); + extern int gru_cpu_fault_map_id(void); + extern struct vm_area_struct *gru_find_vma(unsigned long vaddr); + extern void gru_flush_all_tlb(struct gru_state *gru); +-- +2.35.1 + diff --git a/queue-5.15/misc-tifm-fix-possible-memory-leak-in-tifm_7xx1_swit.patch b/queue-5.15/misc-tifm-fix-possible-memory-leak-in-tifm_7xx1_swit.patch new file mode 100644 index 00000000000..3aeda8c2d9e --- /dev/null +++ b/queue-5.15/misc-tifm-fix-possible-memory-leak-in-tifm_7xx1_swit.patch @@ -0,0 +1,42 @@ +From cf5ba248de4868f6575d008e09a40d4ca884944c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 14:47:25 +0800 +Subject: misc: tifm: fix possible memory leak in tifm_7xx1_switch_media() + +From: ruanjinjie + +[ Upstream commit fd2c930cf6a5b9176382c15f9acb1996e76e25ad ] + +If device_register() returns error in tifm_7xx1_switch_media(), +name of kobject which is allocated in dev_set_name() called in device_add() +is leaked. + +Never directly free @dev after calling device_register(), even +if it returned an error! Always use put_device() to give up the +reference initialized. + +Fixes: 2428a8fe2261 ("tifm: move common device management tasks from tifm_7xx1 to tifm_core") +Signed-off-by: ruanjinjie +Link: https://lore.kernel.org/r/20221117064725.3478402-1-ruanjinjie@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/tifm_7xx1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c +index 228f2eb1d476..2aebbfda104d 100644 +--- a/drivers/misc/tifm_7xx1.c ++++ b/drivers/misc/tifm_7xx1.c +@@ -190,7 +190,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) + spin_unlock_irqrestore(&fm->lock, flags); + } + if (sock) +- tifm_free_device(&sock->dev); ++ put_device(&sock->dev); + } + spin_lock_irqsave(&fm->lock, flags); + } +-- +2.35.1 + diff --git a/queue-5.15/misdn-hfcmulti-don-t-call-dev_kfree_skb-kfree_skb-un.patch b/queue-5.15/misdn-hfcmulti-don-t-call-dev_kfree_skb-kfree_skb-un.patch new file mode 100644 index 00000000000..4288baf4701 --- /dev/null +++ b/queue-5.15/misdn-hfcmulti-don-t-call-dev_kfree_skb-kfree_skb-un.patch @@ -0,0 +1,112 @@ +From 775b532561a580ef5180ae0c47883ca811842ba6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 16:41:39 +0800 +Subject: mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 1232946cf522b8de9e398828bde325d7c41f29dd ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +skb_queue_purge() is called under spin_lock_irqsave() in handle_dmsg() +and hfcm_l1callback(), kfree_skb() is called in them, to fix this, use +skb_queue_splice_init() to move the dch->squeue to a free queue, also +enqueue the tx_skb and rx_skb, at last calling __skb_queue_purge() to +free the SKBs afer unlock. + +Fixes: af69fb3a8ffa ("Add mISDN HFC multiport driver") +Signed-off-by: Yang Yingliang +Reviewed-by: Alexander Duyck +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/isdn/hardware/mISDN/hfcmulti.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c +index 4f7eaa17fb27..e840609c50eb 100644 +--- a/drivers/isdn/hardware/mISDN/hfcmulti.c ++++ b/drivers/isdn/hardware/mISDN/hfcmulti.c +@@ -3217,6 +3217,7 @@ static int + hfcm_l1callback(struct dchannel *dch, u_int cmd) + { + struct hfc_multi *hc = dch->hw; ++ struct sk_buff_head free_queue; + u_long flags; + + switch (cmd) { +@@ -3245,6 +3246,7 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) + l1_event(dch->l1, HW_POWERUP_IND); + break; + case HW_DEACT_REQ: ++ __skb_queue_head_init(&free_queue); + /* start deactivation */ + spin_lock_irqsave(&hc->lock, flags); + if (hc->ctype == HFC_TYPE_E1) { +@@ -3264,20 +3266,21 @@ hfcm_l1callback(struct dchannel *dch, u_int cmd) + plxsd_checksync(hc, 0); + } + } +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); + if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags)) + del_timer(&dch->timer); + spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + break; + case HW_POWERUP_REQ: + spin_lock_irqsave(&hc->lock, flags); +@@ -3384,6 +3387,9 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + case PH_DEACTIVATE_REQ: + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + if (dch->dev.D.protocol != ISDN_P_TE_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + spin_lock_irqsave(&hc->lock, flags); + if (debug & DEBUG_HFCMULTI_MSG) + printk(KERN_DEBUG +@@ -3405,14 +3411,14 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + /* deactivate */ + dch->state = 1; + } +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); +@@ -3424,6 +3430,7 @@ handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) + #endif + ret = 0; + spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + } else + ret = l1_event(dch->l1, hh->prim); + break; +-- +2.35.1 + diff --git a/queue-5.15/misdn-hfcpci-don-t-call-dev_kfree_skb-kfree_skb-unde.patch b/queue-5.15/misdn-hfcpci-don-t-call-dev_kfree_skb-kfree_skb-unde.patch new file mode 100644 index 00000000000..f6ae393f1fe --- /dev/null +++ b/queue-5.15/misdn-hfcpci-don-t-call-dev_kfree_skb-kfree_skb-unde.patch @@ -0,0 +1,71 @@ +From c2569fb664bd93112a5249ca1874f33e6314018e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 16:41:38 +0800 +Subject: mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit f0f596bd75a9d573ca9b587abb39cee0b916bb82 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +skb_queue_purge() is called under spin_lock_irqsave() in hfcpci_l2l1D(), +kfree_skb() is called in it, to fix this, use skb_queue_splice_init() +to move the dch->squeue to a free queue, also enqueue the tx_skb and +rx_skb, at last calling __skb_queue_purge() to free the SKBs afer unlock. + +Fixes: 1700fe1a10dc ("Add mISDN HFC PCI driver") +Signed-off-by: Yang Yingliang +Reviewed-by: Alexander Duyck +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/isdn/hardware/mISDN/hfcpci.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c +index af17459c1a5c..eba58b99cd29 100644 +--- a/drivers/isdn/hardware/mISDN/hfcpci.c ++++ b/drivers/isdn/hardware/mISDN/hfcpci.c +@@ -1617,16 +1617,19 @@ hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + spin_lock_irqsave(&hc->lock, flags); + if (hc->hw.protocol == ISDN_P_NT_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + /* prepare deactivation */ + Write_hfc(hc, HFCPCI_STATES, 0x40); +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); +@@ -1639,10 +1642,12 @@ hfcpci_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + hc->hw.mst_m &= ~HFCPCI_MASTER; + Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m); + ret = 0; ++ spin_unlock_irqrestore(&hc->lock, flags); ++ __skb_queue_purge(&free_queue); + } else { + ret = l1_event(dch->l1, hh->prim); ++ spin_unlock_irqrestore(&hc->lock, flags); + } +- spin_unlock_irqrestore(&hc->lock, flags); + break; + } + if (!ret) +-- +2.35.1 + diff --git a/queue-5.15/misdn-hfcsusb-don-t-call-dev_kfree_skb-kfree_skb-und.patch b/queue-5.15/misdn-hfcsusb-don-t-call-dev_kfree_skb-kfree_skb-und.patch new file mode 100644 index 00000000000..d93abe6a902 --- /dev/null +++ b/queue-5.15/misdn-hfcsusb-don-t-call-dev_kfree_skb-kfree_skb-und.patch @@ -0,0 +1,79 @@ +From 4eafda9fca3ce381600fa09b9bc0cad2f21e8811 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 16:41:37 +0800 +Subject: mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit ddc9648db162eee556edd5222d2808fe33730203 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +skb_queue_purge() is called under spin_lock_irqsave() in hfcusb_l2l1D(), +kfree_skb() is called in it, to fix this, use skb_queue_splice_init() +to move the dch->squeue to a free queue, also enqueue the tx_skb and +rx_skb, at last calling __skb_queue_purge() to free the SKBs afer unlock. + +In tx_iso_complete(), dev_kfree_skb() is called to consume the transmitted +SKB, so replace it with dev_consume_skb_irq(). + +Fixes: 69f52adb2d53 ("mISDN: Add HFC USB driver") +Signed-off-by: Yang Yingliang +Reviewed-by: Alexander Duyck +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/isdn/hardware/mISDN/hfcsusb.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c +index cd5642cef01f..e8b37bd5e34a 100644 +--- a/drivers/isdn/hardware/mISDN/hfcsusb.c ++++ b/drivers/isdn/hardware/mISDN/hfcsusb.c +@@ -326,20 +326,24 @@ hfcusb_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb) + test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags); + + if (hw->protocol == ISDN_P_NT_S0) { ++ struct sk_buff_head free_queue; ++ ++ __skb_queue_head_init(&free_queue); + hfcsusb_ph_command(hw, HFC_L1_DEACTIVATE_NT); + spin_lock_irqsave(&hw->lock, flags); +- skb_queue_purge(&dch->squeue); ++ skb_queue_splice_init(&dch->squeue, &free_queue); + if (dch->tx_skb) { +- dev_kfree_skb(dch->tx_skb); ++ __skb_queue_tail(&free_queue, dch->tx_skb); + dch->tx_skb = NULL; + } + dch->tx_idx = 0; + if (dch->rx_skb) { +- dev_kfree_skb(dch->rx_skb); ++ __skb_queue_tail(&free_queue, dch->rx_skb); + dch->rx_skb = NULL; + } + test_and_clear_bit(FLG_TX_BUSY, &dch->Flags); + spin_unlock_irqrestore(&hw->lock, flags); ++ __skb_queue_purge(&free_queue); + #ifdef FIXME + if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags)) + dchannel_sched_event(&hc->dch, D_CLEARBUSY); +@@ -1330,7 +1334,7 @@ tx_iso_complete(struct urb *urb) + printk("\n"); + } + +- dev_kfree_skb(tx_skb); ++ dev_consume_skb_irq(tx_skb); + tx_skb = NULL; + if (fifo->dch && get_next_dframe(fifo->dch)) + tx_skb = fifo->dch->tx_skb; +-- +2.35.1 + diff --git a/queue-5.15/mmc-alcor-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-alcor-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..c6337d7a233 --- /dev/null +++ b/queue-5.15/mmc-alcor-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,44 @@ +From 8f906d24b4df344d74f00e6a5e743a430728b1d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:15 +0800 +Subject: mmc: alcor: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit e93d1468f429475a753d6baa79b853b7ee5ef8c0 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and calling mmc_free_host() in the +error path. + +Fixes: c5413ad815a6 ("mmc: add new Alcor Micro Cardreader SD/MMC driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-2-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/alcor.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c +index bfb8efeb7eb8..d01df01d4b4d 100644 +--- a/drivers/mmc/host/alcor.c ++++ b/drivers/mmc/host/alcor.c +@@ -1114,7 +1114,10 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev) + alcor_hw_init(host); + + dev_set_drvdata(&pdev->dev, host); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto free_host; ++ + return 0; + + free_host: +-- +2.35.1 + diff --git a/queue-5.15/mmc-atmel-mci-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-atmel-mci-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..07c5ee40f1f --- /dev/null +++ b/queue-5.15/mmc-atmel-mci-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,60 @@ +From f1eff76c83780b932f07664113272a194d7af1a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 20:28:19 +0800 +Subject: mmc: atmel-mci: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 9e6e8c43726673ca2abcaac87640b9215fd72f4c ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +So fix this by checking the return value and calling mmc_free_host() +in the error path. + +Fixes: 7d2be0749a59 ("atmel-mci: Driver for Atmel on-chip MMC controllers") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221108122819.429975-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/atmel-mci.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c +index 807177c953f3..6f971a3e7e49 100644 +--- a/drivers/mmc/host/atmel-mci.c ++++ b/drivers/mmc/host/atmel-mci.c +@@ -2223,6 +2223,7 @@ static int atmci_init_slot(struct atmel_mci *host, + { + struct mmc_host *mmc; + struct atmel_mci_slot *slot; ++ int ret; + + mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev); + if (!mmc) +@@ -2306,11 +2307,13 @@ static int atmci_init_slot(struct atmel_mci *host, + + host->slot[id] = slot; + mmc_regulator_get_supply(mmc); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ mmc_free_host(mmc); ++ return ret; ++ } + + if (gpio_is_valid(slot->detect_pin)) { +- int ret; +- + timer_setup(&slot->detect_timer, atmci_detect_change, 0); + + ret = request_irq(gpio_to_irq(slot->detect_pin), +-- +2.35.1 + diff --git a/queue-5.15/mmc-core-normalize-the-error-handling-branch-in-sd_r.patch b/queue-5.15/mmc-core-normalize-the-error-handling-branch-in-sd_r.patch new file mode 100644 index 00000000000..6f700ce7d24 --- /dev/null +++ b/queue-5.15/mmc-core-normalize-the-error-handling-branch-in-sd_r.patch @@ -0,0 +1,61 @@ +From 0aa40c8f06d83023da975fc26318ed26366a2d05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 21:49:20 +0800 +Subject: mmc: core: Normalize the error handling branch in sd_read_ext_regs() + +From: Zhen Lei + +[ Upstream commit fc02e2b52389c8fde02852b2f959c0b45f042bbd ] + +Let's use pr_err() to output the error messages and let's extend a comment +to clarify why returning 0 (success) in one case make sense. + +Fixes: c784f92769ae ("mmc: core: Read the SD function extension registers for power management") +Signed-off-by: Zhen Lei +[Ulf: Clarified the comment and the commit-msg] +Link: https://lore.kernel.org/r/20221130134920.2109-1-thunder.leizhen@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/core/sd.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c +index 86a8a1f56583..592166e53dce 100644 +--- a/drivers/mmc/core/sd.c ++++ b/drivers/mmc/core/sd.c +@@ -1252,7 +1252,7 @@ static int sd_read_ext_regs(struct mmc_card *card) + */ + err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + if (err) { +- pr_warn("%s: error %d reading general info of SD ext reg\n", ++ pr_err("%s: error %d reading general info of SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } +@@ -1266,7 +1266,12 @@ static int sd_read_ext_regs(struct mmc_card *card) + /* Number of extensions to be find. */ + num_ext = gen_info_buf[4]; + +- /* We support revision 0, but limit it to 512 bytes for simplicity. */ ++ /* ++ * We only support revision 0 and limit it to 512 bytes for simplicity. ++ * No matter what, let's return zero to allow us to continue using the ++ * card, even if we can't support the features from the SD function ++ * extensions registers. ++ */ + if (rev != 0 || len > 512) { + pr_warn("%s: non-supported SD ext reg layout\n", + mmc_hostname(card->host)); +@@ -1281,7 +1286,7 @@ static int sd_read_ext_regs(struct mmc_card *card) + for (i = 0; i < num_ext; i++) { + err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr); + if (err) { +- pr_warn("%s: error %d parsing SD ext reg\n", ++ pr_err("%s: error %d parsing SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } +-- +2.35.1 + diff --git a/queue-5.15/mmc-f-sdh30-add-quirks-for-broken-timeout-clock-capa.patch b/queue-5.15/mmc-f-sdh30-add-quirks-for-broken-timeout-clock-capa.patch new file mode 100644 index 00000000000..e3f99bdb6ec --- /dev/null +++ b/queue-5.15/mmc-f-sdh30-add-quirks-for-broken-timeout-clock-capa.patch @@ -0,0 +1,38 @@ +From 94a57d9874aa849ef651bcf6ca56e309fe5725a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 17:10:33 +0900 +Subject: mmc: f-sdh30: Add quirks for broken timeout clock capability + +From: Kunihiko Hayashi + +[ Upstream commit aae9d3a440736691b3c1cb09ae2c32c4f1ee2e67 ] + +There is a case where the timeout clock is not supplied to the capability. +Add a quirk for that. + +Signed-off-by: Kunihiko Hayashi +Acked-by: Jassi Brar +Link: https://lore.kernel.org/r/20221111081033.3813-7-hayashi.kunihiko@socionext.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/sdhci_f_sdh30.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c +index 3f5977979cf2..6c4f43e11282 100644 +--- a/drivers/mmc/host/sdhci_f_sdh30.c ++++ b/drivers/mmc/host/sdhci_f_sdh30.c +@@ -168,6 +168,9 @@ static int sdhci_f_sdh30_probe(struct platform_device *pdev) + if (reg & SDHCI_CAN_DO_8BIT) + priv->vendor_hs200 = F_SDH30_EMMC_HS200; + ++ if (!(reg & SDHCI_TIMEOUT_CLK_MASK)) ++ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; ++ + ret = sdhci_add_host(host); + if (ret) + goto err_add_host; +-- +2.35.1 + diff --git a/queue-5.15/mmc-meson-gx-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-meson-gx-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..a29096276e7 --- /dev/null +++ b/queue-5.15/mmc-meson-gx-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,47 @@ +From 1b770b89bb25a82c6fd8fa34637311555aa55ab4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 20:34:17 +0800 +Subject: mmc: meson-gx: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 90935f16f2650ab7416fa2ffbe5c28cb39cf3f1e ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +Fix this by checking the return value and goto error path which +will call mmc_free_host(). + +Fixes: 51c5d8447bd7 ("MMC: meson: initial support for GX platforms") +Signed-off-by: Yang Yingliang +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20221108123417.479045-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/meson-gx-mmc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c +index 9b2e2548bd18..753f9ea254d4 100644 +--- a/drivers/mmc/host/meson-gx-mmc.c ++++ b/drivers/mmc/host/meson-gx-mmc.c +@@ -1291,7 +1291,9 @@ static int meson_mmc_probe(struct platform_device *pdev) + } + + mmc->ops = &meson_mmc_ops; +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_free_irq; + + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/mmc-mmci-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-mmci-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..1b929532b3a --- /dev/null +++ b/queue-5.15/mmc-mmci-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,46 @@ +From ee9934f7904fd571625c237eaa04d67955fc1b97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 21:35:39 +0800 +Subject: mmc: mmci: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit b38a20f29a49ae04d23750d104b25400b792b98c ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +So fix this by checking the return value and goto error path which +will call mmc_free_host(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221109133539.3275664-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/mmci.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c +index 3765e2f4ad98..2c4eda83ca18 100644 +--- a/drivers/mmc/host/mmci.c ++++ b/drivers/mmc/host/mmci.c +@@ -2254,7 +2254,9 @@ static int mmci_probe(struct amba_device *dev, + pm_runtime_set_autosuspend_delay(&dev->dev, 50); + pm_runtime_use_autosuspend(&dev->dev); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto clk_disable; + + pm_runtime_put(&dev->dev); + return 0; +-- +2.35.1 + diff --git a/queue-5.15/mmc-moxart-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-moxart-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..243bbe27639 --- /dev/null +++ b/queue-5.15/mmc-moxart-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,43 @@ +From 13206368a0cec06ea473b419dbb2e06d4c46f2a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:16 +0800 +Subject: mmc: moxart: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 0ca18d09c744fb030ae9bc5836c3e357e0237dea ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(). + +Fixes: 1b66e94e6b99 ("mmc: moxart: Add MOXA ART SD/MMC driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-3-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/moxart-mmc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c +index dfc3ffd5b1f8..52ed30f2d9f4 100644 +--- a/drivers/mmc/host/moxart-mmc.c ++++ b/drivers/mmc/host/moxart-mmc.c +@@ -665,7 +665,9 @@ static int moxart_probe(struct platform_device *pdev) + goto out; + + dev_set_drvdata(dev, mmc); +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto out; + + dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width); + +-- +2.35.1 + diff --git a/queue-5.15/mmc-mxcmmc-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-mxcmmc-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..e9cf15bc37f --- /dev/null +++ b/queue-5.15/mmc-mxcmmc-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,43 @@ +From fa74320943366cbc408d3e669efa7e6986625587 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:17 +0800 +Subject: mmc: mxcmmc: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit cde600af7b413c9fe03e85c58c4279df90e91d13 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(). + +Fixes: d96be879ff46 ("mmc: Add a MX2/MX3 specific SDHC driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-4-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/mxcmmc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c +index 9bf95ba217fa..97227ad71715 100644 +--- a/drivers/mmc/host/mxcmmc.c ++++ b/drivers/mmc/host/mxcmmc.c +@@ -1143,7 +1143,9 @@ static int mxcmci_probe(struct platform_device *pdev) + + timer_setup(&host->watchdog, mxcmci_watchdog, 0); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto out_free_dma; + + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/mmc-omap_hsmmc-fix-return-value-check-of-mmc_add_hos.patch b/queue-5.15/mmc-omap_hsmmc-fix-return-value-check-of-mmc_add_hos.patch new file mode 100644 index 00000000000..185e7cd4548 --- /dev/null +++ b/queue-5.15/mmc-omap_hsmmc-fix-return-value-check-of-mmc_add_hos.patch @@ -0,0 +1,46 @@ +From f60c5684e04454fc05a498c61281ed66e8e670d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 20:13:16 +0800 +Subject: mmc: omap_hsmmc: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit a525cad241c339ca00bf7ebf03c5180f2a9b767c ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +Fix this by checking the return value and goto error path wihch +will call mmc_free_host(). + +Fixes: a45c6cb81647 ("[ARM] 5369/1: omap mmc: Add new omap hsmmc controller for 2430 and 34xx, v3") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221108121316.340354-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/omap_hsmmc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 2f8038d69f67..eb0bd46b7e81 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -1987,7 +1987,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + if (!ret) + mmc->caps |= MMC_CAP_SDIO_IRQ; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto err_irq; + + if (mmc_pdata(host)->name != NULL) { + ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name); +-- +2.35.1 + diff --git a/queue-5.15/mmc-pxamci-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-pxamci-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..3203c734d2b --- /dev/null +++ b/queue-5.15/mmc-pxamci-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,46 @@ +From 103be4c1bd917d2505beb6b988a8a288cd884eca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:18 +0800 +Subject: mmc: pxamci: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 80e1ef3afb8bfbe768380b70ffe1b6cab87d1a3b ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(), besides, ->exit() need be called to uninit the pdata. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-5-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/pxamci.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c +index 55868b6b8658..e25e9bb34eb3 100644 +--- a/drivers/mmc/host/pxamci.c ++++ b/drivers/mmc/host/pxamci.c +@@ -763,7 +763,12 @@ static int pxamci_probe(struct platform_device *pdev) + dev_warn(dev, "gpio_ro and get_ro() both defined\n"); + } + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ if (host->pdata && host->pdata->exit) ++ host->pdata->exit(dev, mmc); ++ goto out; ++ } + + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/mmc-renesas_sdhi-alway-populate-scc-pointer.patch b/queue-5.15/mmc-renesas_sdhi-alway-populate-scc-pointer.patch new file mode 100644 index 00000000000..4a69be1be37 --- /dev/null +++ b/queue-5.15/mmc-renesas_sdhi-alway-populate-scc-pointer.patch @@ -0,0 +1,59 @@ +From 1890fba0e65413c0833c40532c16a3bedb12b133 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 12:34:54 +0100 +Subject: mmc: renesas_sdhi: alway populate SCC pointer + +From: Wolfram Sang + +[ Upstream commit 3d4f9898c1c74323dd61d6a8a0efca9401232ad4 ] + +We need the SCC pointer to reset the device, so populate it even when we +don't need it for tuning. + +Fixes: 45bffc371fef ("mmc: renesas_sdhi: only reset SCC when its pointer is populated") +Signed-off-by: Takeshi Saito +Signed-off-by: Takeshi Kihara +Signed-off-by: Wolfram Sang +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Link: https://lore.kernel.org/r/20221120113457.42010-2-wsa+renesas@sang-engineering.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/renesas_sdhi_core.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index 387f2a4f693a..f443debbcb98 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -1037,11 +1037,14 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (ver >= SDHI_VER_GEN3_SD) + host->get_timeout_cycles = renesas_sdhi_gen3_get_cycles; + ++ /* Check for SCC so we can reset it if needed */ ++ if (of_data && of_data->scc_offset && ver >= SDHI_VER_GEN2_SDR104) ++ priv->scc_ctl = host->ctl + of_data->scc_offset; ++ + /* Enable tuning iff we have an SCC and a supported mode */ +- if (of_data && of_data->scc_offset && +- (host->mmc->caps & MMC_CAP_UHS_SDR104 || +- host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | +- MMC_CAP2_HS400_1_8V))) { ++ if (priv->scc_ctl && (host->mmc->caps & MMC_CAP_UHS_SDR104 || ++ host->mmc->caps2 & (MMC_CAP2_HS200_1_8V_SDR | ++ MMC_CAP2_HS400_1_8V))) { + const struct renesas_sdhi_scc *taps = of_data->taps; + bool use_4tap = priv->quirks && priv->quirks->hs400_4taps; + bool hit = false; +@@ -1061,7 +1064,6 @@ int renesas_sdhi_probe(struct platform_device *pdev, + if (!hit) + dev_warn(&host->pdev->dev, "Unknown clock rate for tuning\n"); + +- priv->scc_ctl = host->ctl + of_data->scc_offset; + host->check_retune = renesas_sdhi_check_scc_error; + host->ops.execute_tuning = renesas_sdhi_execute_tuning; + host->ops.prepare_hs400_tuning = renesas_sdhi_prepare_hs400_tuning; +-- +2.35.1 + diff --git a/queue-5.15/mmc-renesas_sdhi-better-reset-from-hs400-mode.patch b/queue-5.15/mmc-renesas_sdhi-better-reset-from-hs400-mode.patch new file mode 100644 index 00000000000..ab0e58b9bb7 --- /dev/null +++ b/queue-5.15/mmc-renesas_sdhi-better-reset-from-hs400-mode.patch @@ -0,0 +1,40 @@ +From 9fbf797bc6626b9be2e854a89c88640f5cbbef78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 12:34:55 +0100 +Subject: mmc: renesas_sdhi: better reset from HS400 mode + +From: Wolfram Sang + +[ Upstream commit 0da69dd2155019ed4c444ede0e79ce7a4a6af627 ] + +Up to now, HS400 adjustment mode was only disabled on soft reset when a +calibration table was in use. It is safer, though, to disable it as soon +as the instance has an adjustment related quirk set, i.e. bad taps or a +calibration table. + +Signed-off-by: Wolfram Sang +Reviewed-by: Yoshihiro Shimoda +Tested-by: Yoshihiro Shimoda +Link: https://lore.kernel.org/r/20221120113457.42010-3-wsa+renesas@sang-engineering.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/renesas_sdhi_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c +index f443debbcb98..12921fba4f52 100644 +--- a/drivers/mmc/host/renesas_sdhi_core.c ++++ b/drivers/mmc/host/renesas_sdhi_core.c +@@ -520,7 +520,7 @@ static void renesas_sdhi_reset_hs400_mode(struct tmio_mmc_host *host, + SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) & + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2)); + +- if (priv->adjust_hs400_calib_table) ++ if (priv->quirks && (priv->quirks->hs400_calib_table || priv->quirks->hs400_bad_taps)) + renesas_sdhi_adjust_hs400_mode_disable(host); + + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN | +-- +2.35.1 + diff --git a/queue-5.15/mmc-rtsx_pci-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-rtsx_pci-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..1685fe2e861 --- /dev/null +++ b/queue-5.15/mmc-rtsx_pci-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,55 @@ +From ed6f597747e8565ec2f3ad1247cf560a58cfb12a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:19 +0800 +Subject: mmc: rtsx_pci: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 0c87db77423a282b3b38b8a6daf057b822680516 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and calling mmc_free_host() in the +error path, beside, runtime PM also needs be disabled. + +Fixes: ff984e57d36e ("mmc: Add realtek pcie sdmmc host driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-6-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/rtsx_pci_sdmmc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c +index e1580f78c6b2..8098726dcc0b 100644 +--- a/drivers/mmc/host/rtsx_pci_sdmmc.c ++++ b/drivers/mmc/host/rtsx_pci_sdmmc.c +@@ -1474,6 +1474,7 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) + struct realtek_pci_sdmmc *host; + struct rtsx_pcr *pcr; + struct pcr_handle *handle = pdev->dev.platform_data; ++ int ret; + + if (!handle) + return -ENXIO; +@@ -1511,7 +1512,13 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_use_autosuspend(&pdev->dev); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ pm_runtime_dont_use_autosuspend(&pdev->dev); ++ pm_runtime_disable(&pdev->dev); ++ mmc_free_host(mmc); ++ return ret; ++ } + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/mmc-rtsx_usb_sdmmc-fix-return-value-check-of-mmc_add.patch b/queue-5.15/mmc-rtsx_usb_sdmmc-fix-return-value-check-of-mmc_add.patch new file mode 100644 index 00000000000..5e8889380fa --- /dev/null +++ b/queue-5.15/mmc-rtsx_usb_sdmmc-fix-return-value-check-of-mmc_add.patch @@ -0,0 +1,58 @@ +From ab9e25ee9c64f330aabc2919913ce7b8dae6a06c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:20 +0800 +Subject: mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit fc38a5a10e9e5a75eb9189854abeb8405b214cc9 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and calling mmc_free_host() in the +error path, besides, led_classdev_unregister() and pm_runtime_disable() also +need be called. + +Fixes: c7f6558d84af ("mmc: Add realtek USB sdmmc host driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-7-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/rtsx_usb_sdmmc.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c +index 5fe4528e296e..1be3a355f10d 100644 +--- a/drivers/mmc/host/rtsx_usb_sdmmc.c ++++ b/drivers/mmc/host/rtsx_usb_sdmmc.c +@@ -1332,6 +1332,7 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) + #ifdef RTSX_USB_USE_LEDS_CLASS + int err; + #endif ++ int ret; + + ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent)); + if (!ucr) +@@ -1368,7 +1369,15 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) + INIT_WORK(&host->led_work, rtsx_usb_update_led); + + #endif +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++#ifdef RTSX_USB_USE_LEDS_CLASS ++ led_classdev_unregister(&host->led); ++#endif ++ mmc_free_host(mmc); ++ pm_runtime_disable(&pdev->dev); ++ return ret; ++ } + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/mmc-toshsd-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-toshsd-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..0d086151bc3 --- /dev/null +++ b/queue-5.15/mmc-toshsd-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,52 @@ +From a0bf6d5759cfa44debdb6da44aef311867895364 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:21 +0800 +Subject: mmc: toshsd: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit f670744a316ea983113a65313dcd387b5a992444 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(), besides, free_irq() also needs be called. + +Fixes: a5eb8bbd66cc ("mmc: add Toshiba PCI SD controller driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-8-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/toshsd.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/toshsd.c b/drivers/mmc/host/toshsd.c +index 8d037c2071ab..497791ffada6 100644 +--- a/drivers/mmc/host/toshsd.c ++++ b/drivers/mmc/host/toshsd.c +@@ -651,7 +651,9 @@ static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + if (ret) + goto unmap; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto free_irq; + + base = pci_resource_start(pdev, 0); + dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq); +@@ -660,6 +662,8 @@ static int toshsd_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + + return 0; + ++free_irq: ++ free_irq(pdev->irq, host); + unmap: + pci_iounmap(pdev, host->ioaddr); + release: +-- +2.35.1 + diff --git a/queue-5.15/mmc-via-sdmmc-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-via-sdmmc-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..e625ec31bb7 --- /dev/null +++ b/queue-5.15/mmc-via-sdmmc-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,46 @@ +From ca6b08a91884d144fe803d3ee6892179fe67b3f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 21:09:49 +0800 +Subject: mmc: via-sdmmc: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit e4e46fb61e3bb4628170810d3f2b996b709b90d9 ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +Fix this by checking the return value and goto error path which +will call mmc_free_host(). + +Fixes: f0bf7f61b840 ("mmc: Add new via-sdmmc host controller driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221108130949.1067699-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/via-sdmmc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c +index 88662a90ed96..a2b0d9461665 100644 +--- a/drivers/mmc/host/via-sdmmc.c ++++ b/drivers/mmc/host/via-sdmmc.c +@@ -1151,7 +1151,9 @@ static int via_sd_probe(struct pci_dev *pcidev, + pcidev->subsystem_device == 0x3891) + sdhost->quirks = VIA_CRDR_QUIRK_300MS_PWRDELAY; + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto unmap; + + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/mmc-vub300-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-vub300-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..3a6fb6dd56a --- /dev/null +++ b/queue-5.15/mmc-vub300-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,67 @@ +From f96900325d4382113fab420f468771a6cac814b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:22 +0800 +Subject: mmc: vub300: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 0613ad2401f88bdeae5594c30afe318e93b14676 ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(), besides, the timer added before mmc_add_host() needs be del. + +And this patch fixes another missing call mmc_free_host() if usb_control_msg() +fails. + +Fixes: 88095e7b473a ("mmc: Add new VUB300 USB-to-SD/SDIO/MMC driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-9-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/vub300.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c +index 97beece62fec..ab36ec479747 100644 +--- a/drivers/mmc/host/vub300.c ++++ b/drivers/mmc/host/vub300.c +@@ -2299,14 +2299,14 @@ static int vub300_probe(struct usb_interface *interface, + 0x0000, 0x0000, &vub300->system_port_status, + sizeof(vub300->system_port_status), 1000); + if (retval < 0) { +- goto error4; ++ goto error5; + } else if (sizeof(vub300->system_port_status) == retval) { + vub300->card_present = + (0x0001 & vub300->system_port_status.port_flags) ? 1 : 0; + vub300->read_only = + (0x0010 & vub300->system_port_status.port_flags) ? 1 : 0; + } else { +- goto error4; ++ goto error5; + } + usb_set_intfdata(interface, vub300); + INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread); +@@ -2329,8 +2329,13 @@ static int vub300_probe(struct usb_interface *interface, + "USB vub300 remote SDIO host controller[%d]" + "connected with no SD/SDIO card inserted\n", + interface_to_InterfaceNumber(interface)); +- mmc_add_host(mmc); ++ retval = mmc_add_host(mmc); ++ if (retval) ++ goto error6; ++ + return 0; ++error6: ++ del_timer_sync(&vub300->inactivity_timer); + error5: + mmc_free_host(mmc); + /* +-- +2.35.1 + diff --git a/queue-5.15/mmc-wbsd-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-wbsd-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..6e5cef26ec4 --- /dev/null +++ b/queue-5.15/mmc-wbsd-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,55 @@ +From 83dac88e8a9b7de3b9e5c47d57cf6251eda58c12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 21:32:37 +0800 +Subject: mmc: wbsd: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit dc5b9b50fc9d1334407e316e6e29a5097ef833bd ] + +mmc_add_host() may return error, if we ignore its return value, +it will lead two issues: +1. The memory that allocated in mmc_alloc_host() is leaked. +2. In the remove() path, mmc_remove_host() will be called to + delete device, but it's not added yet, it will lead a kernel + crash because of null-ptr-deref in device_del(). + +So fix this by checking the return value and goto error path which +will call mmc_free_host(), besides, other resources also need be +released. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221109133237.3273558-1-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/wbsd.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c +index 67ecd342fe5f..7c7ec8d10232 100644 +--- a/drivers/mmc/host/wbsd.c ++++ b/drivers/mmc/host/wbsd.c +@@ -1698,7 +1698,17 @@ static int wbsd_init(struct device *dev, int base, int irq, int dma, + */ + wbsd_init_device(host); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) { ++ if (!pnp) ++ wbsd_chip_poweroff(host); ++ ++ wbsd_release_resources(host); ++ wbsd_free_mmc(dev); ++ ++ mmc_free_host(mmc); ++ return ret; ++ } + + pr_info("%s: W83L51xD", mmc_hostname(mmc)); + if (host->chip_id != 0) +-- +2.35.1 + diff --git a/queue-5.15/mmc-wmt-sdmmc-fix-return-value-check-of-mmc_add_host.patch b/queue-5.15/mmc-wmt-sdmmc-fix-return-value-check-of-mmc_add_host.patch new file mode 100644 index 00000000000..49fe5db2f81 --- /dev/null +++ b/queue-5.15/mmc-wmt-sdmmc-fix-return-value-check-of-mmc_add_host.patch @@ -0,0 +1,49 @@ +From 6cbca3c5fd28b2cadd373ca4a9c9dd0ab36092b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 14:30:23 +0800 +Subject: mmc: wmt-sdmmc: fix return value check of mmc_add_host() + +From: Yang Yingliang + +[ Upstream commit 29276d56f6ed138db0f38cd31aedc0b725c8c76c ] + +mmc_add_host() may return error, if we ignore its return value, the memory +that allocated in mmc_alloc_host() will be leaked and it will lead a kernel +crash because of deleting not added device in the remove path. + +So fix this by checking the return value and goto error path which will call +mmc_free_host(), besides, clk_disable_unprepare() also needs be called. + +Fixes: 3a96dff0f828 ("mmc: SD/MMC Host Controller for Wondermedia WM8505/WM8650") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221101063023.1664968-10-yangyingliang@huawei.com +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/wmt-sdmmc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c +index 8df722ec57ed..393319548857 100644 +--- a/drivers/mmc/host/wmt-sdmmc.c ++++ b/drivers/mmc/host/wmt-sdmmc.c +@@ -859,11 +859,15 @@ static int wmt_mci_probe(struct platform_device *pdev) + /* configure the controller to a known 'ready' state */ + wmt_reset_hardware(mmc); + +- mmc_add_host(mmc); ++ ret = mmc_add_host(mmc); ++ if (ret) ++ goto fail7; + + dev_info(&pdev->dev, "WMT SDHC Controller initialized\n"); + + return 0; ++fail7: ++ clk_disable_unprepare(priv->clk_sdmmc); + fail6: + clk_put(priv->clk_sdmmc); + fail5_and_a_half: +-- +2.35.1 + diff --git a/queue-5.15/mrp-introduce-active-flags-to-prevent-uaf-when-appli.patch b/queue-5.15/mrp-introduce-active-flags-to-prevent-uaf-when-appli.patch new file mode 100644 index 00000000000..337e8b097d3 --- /dev/null +++ b/queue-5.15/mrp-introduce-active-flags-to-prevent-uaf-when-appli.patch @@ -0,0 +1,126 @@ +From 5aa7f9dbdd9234d6f3d666238a878ca770b0a560 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 19:45:11 +0800 +Subject: mrp: introduce active flags to prevent UAF when applicant uninit + +From: Schspa Shi + +[ Upstream commit ab0377803dafc58f1e22296708c1c28e309414d6 ] + +The caller of del_timer_sync must prevent restarting of the timer, If +we have no this synchronization, there is a small probability that the +cancellation will not be successful. + +And syzbot report the fellowing crash: +================================================================== +BUG: KASAN: use-after-free in hlist_add_head include/linux/list.h:929 [inline] +BUG: KASAN: use-after-free in enqueue_timer+0x18/0xa4 kernel/time/timer.c:605 +Write at addr f9ff000024df6058 by task syz-fuzzer/2256 +Pointer tag: [f9], memory tag: [fe] + +CPU: 1 PID: 2256 Comm: syz-fuzzer Not tainted 6.1.0-rc5-syzkaller-00008- +ge01d50cbd6ee #0 +Hardware name: linux,dummy-virt (DT) +Call trace: + dump_backtrace.part.0+0xe0/0xf0 arch/arm64/kernel/stacktrace.c:156 + dump_backtrace arch/arm64/kernel/stacktrace.c:162 [inline] + show_stack+0x18/0x40 arch/arm64/kernel/stacktrace.c:163 + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x68/0x84 lib/dump_stack.c:106 + print_address_description mm/kasan/report.c:284 [inline] + print_report+0x1a8/0x4a0 mm/kasan/report.c:395 + kasan_report+0x94/0xb4 mm/kasan/report.c:495 + __do_kernel_fault+0x164/0x1e0 arch/arm64/mm/fault.c:320 + do_bad_area arch/arm64/mm/fault.c:473 [inline] + do_tag_check_fault+0x78/0x8c arch/arm64/mm/fault.c:749 + do_mem_abort+0x44/0x94 arch/arm64/mm/fault.c:825 + el1_abort+0x40/0x60 arch/arm64/kernel/entry-common.c:367 + el1h_64_sync_handler+0xd8/0xe4 arch/arm64/kernel/entry-common.c:427 + el1h_64_sync+0x64/0x68 arch/arm64/kernel/entry.S:576 + hlist_add_head include/linux/list.h:929 [inline] + enqueue_timer+0x18/0xa4 kernel/time/timer.c:605 + mod_timer+0x14/0x20 kernel/time/timer.c:1161 + mrp_periodic_timer_arm net/802/mrp.c:614 [inline] + mrp_periodic_timer+0xa0/0xc0 net/802/mrp.c:627 + call_timer_fn.constprop.0+0x24/0x80 kernel/time/timer.c:1474 + expire_timers+0x98/0xc4 kernel/time/timer.c:1519 + +To fix it, we can introduce a new active flags to make sure the timer will +not restart. + +Reported-by: syzbot+6fd64001c20aa99e34a4@syzkaller.appspotmail.com + +Signed-off-by: Schspa Shi +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/mrp.h | 1 + + net/802/mrp.c | 18 +++++++++++++----- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/include/net/mrp.h b/include/net/mrp.h +index 1c308c034e1a..a8102661fd61 100644 +--- a/include/net/mrp.h ++++ b/include/net/mrp.h +@@ -120,6 +120,7 @@ struct mrp_applicant { + struct sk_buff *pdu; + struct rb_root mad; + struct rcu_head rcu; ++ bool active; + }; + + struct mrp_port { +diff --git a/net/802/mrp.c b/net/802/mrp.c +index 35e04cc5390c..c10a432a5b43 100644 +--- a/net/802/mrp.c ++++ b/net/802/mrp.c +@@ -606,7 +606,10 @@ static void mrp_join_timer(struct timer_list *t) + spin_unlock(&app->lock); + + mrp_queue_xmit(app); +- mrp_join_timer_arm(app); ++ spin_lock(&app->lock); ++ if (likely(app->active)) ++ mrp_join_timer_arm(app); ++ spin_unlock(&app->lock); + } + + static void mrp_periodic_timer_arm(struct mrp_applicant *app) +@@ -620,11 +623,12 @@ static void mrp_periodic_timer(struct timer_list *t) + struct mrp_applicant *app = from_timer(app, t, periodic_timer); + + spin_lock(&app->lock); +- mrp_mad_event(app, MRP_EVENT_PERIODIC); +- mrp_pdu_queue(app); ++ if (likely(app->active)) { ++ mrp_mad_event(app, MRP_EVENT_PERIODIC); ++ mrp_pdu_queue(app); ++ mrp_periodic_timer_arm(app); ++ } + spin_unlock(&app->lock); +- +- mrp_periodic_timer_arm(app); + } + + static int mrp_pdu_parse_end_mark(struct sk_buff *skb, int *offset) +@@ -872,6 +876,7 @@ int mrp_init_applicant(struct net_device *dev, struct mrp_application *appl) + app->dev = dev; + app->app = appl; + app->mad = RB_ROOT; ++ app->active = true; + spin_lock_init(&app->lock); + skb_queue_head_init(&app->queue); + rcu_assign_pointer(dev->mrp_port->applicants[appl->type], app); +@@ -900,6 +905,9 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl) + + RCU_INIT_POINTER(port->applicants[appl->type], NULL); + ++ spin_lock_bh(&app->lock); ++ app->active = false; ++ spin_unlock_bh(&app->lock); + /* Delete timer and generate a final TX event to flush out + * all pending messages before the applicant is gone. + */ +-- +2.35.1 + diff --git a/queue-5.15/mt76-stop-the-radar-detector-after-leaving-dfs-chann.patch b/queue-5.15/mt76-stop-the-radar-detector-after-leaving-dfs-chann.patch new file mode 100644 index 00000000000..e76e7815212 --- /dev/null +++ b/queue-5.15/mt76-stop-the-radar-detector-after-leaving-dfs-chann.patch @@ -0,0 +1,55 @@ +From 945d93a625a4fc46b72f0eacdbc73008356121e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Jan 2022 11:28:11 +0800 +Subject: mt76: stop the radar detector after leaving dfs channel + +From: Xing Song + +[ Upstream commit 4e58ef4b6d727abdb071f7799aef763f8d6f2ad8 ] + +The radar detctor is used for dfs channel. So it will start after switching +to dfs channel and will stop after leaving. The TX will be blocked if radar +detctor isn't stopped in non-dfs channel. + +This patch resets the dfs state to indicate the radar detector needs to be +stopped. + +Signed-off-by: Xing Song +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7615/main.c | 3 ++- + drivers/net/wireless/mediatek/mt76/mt7915/main.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +index 8f1338dae211..96667b7d722d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +@@ -290,7 +290,8 @@ static void mt7615_init_dfs_state(struct mt7615_phy *phy) + if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + +- if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) ++ if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) && ++ !(mphy->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return; + + if (mphy->chandef.chan->center_freq == chandef->chan->center_freq && +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +index 6aca470e2401..7a4f277a1622 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c +@@ -302,7 +302,8 @@ static void mt7915_init_dfs_state(struct mt7915_phy *phy) + if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) + return; + +- if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) ++ if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR) && ++ !(mphy->chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return; + + if (mphy->chandef.chan->center_freq == chandef->chan->center_freq && +-- +2.35.1 + diff --git a/queue-5.15/mtd-fix-device-name-leak-when-register-device-failed.patch b/queue-5.15/mtd-fix-device-name-leak-when-register-device-failed.patch new file mode 100644 index 00000000000..4973a301366 --- /dev/null +++ b/queue-5.15/mtd-fix-device-name-leak-when-register-device-failed.patch @@ -0,0 +1,62 @@ +From ad890e21daa5de8816d8a3c426756590f875d807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 22 Oct 2022 20:13:52 +0800 +Subject: mtd: Fix device name leak when register device failed in + add_mtd_device() + +From: Zhang Xiaoxu + +[ Upstream commit 895d68a39481a75c680aa421546931fb11942fa6 ] + +There is a kmemleak when register device failed: + unreferenced object 0xffff888101aab550 (size 8): + comm "insmod", pid 3922, jiffies 4295277753 (age 925.408s) + hex dump (first 8 bytes): + 6d 74 64 30 00 88 ff ff mtd0.... + backtrace: + [<00000000bde26724>] __kmalloc_node_track_caller+0x4e/0x150 + [<000000003c32b416>] kvasprintf+0xb0/0x130 + [<000000001f7a8f15>] kobject_set_name_vargs+0x2f/0xb0 + [<000000006e781163>] dev_set_name+0xab/0xe0 + [<00000000e30d0c78>] add_mtd_device+0x4bb/0x700 + [<00000000f3d34de7>] mtd_device_parse_register+0x2ac/0x3f0 + [<00000000c0d88488>] 0xffffffffa0238457 + [<00000000b40d0922>] 0xffffffffa02a008f + [<0000000023d17b9d>] do_one_initcall+0x87/0x2a0 + [<00000000770f6ca6>] do_init_module+0xdf/0x320 + [<000000007b6768fe>] load_module+0x2f98/0x3330 + [<00000000346bed5a>] __do_sys_finit_module+0x113/0x1b0 + [<00000000674c2290>] do_syscall_64+0x35/0x80 + [<000000004c6a8d97>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +If register device failed, should call put_device() to give up the +reference. + +Fixes: 1f24b5a8ecbb ("[MTD] driver model updates") +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221022121352.2534682-1-zhangxiaoxu5@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/mtdcore.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c +index 61f236e0378a..3abaac109e75 100644 +--- a/drivers/mtd/mtdcore.c ++++ b/drivers/mtd/mtdcore.c +@@ -671,8 +671,10 @@ int add_mtd_device(struct mtd_info *mtd) + dev_set_drvdata(&mtd->dev, mtd); + of_node_get(mtd_get_of_node(mtd)); + error = device_register(&mtd->dev); +- if (error) ++ if (error) { ++ put_device(&mtd->dev); + goto fail_added; ++ } + + /* Add the nvmem provider */ + error = mtd_nvmem_add(mtd); +-- +2.35.1 + diff --git a/queue-5.15/mtd-lpddr2_nvm-fix-possible-null-ptr-deref.patch b/queue-5.15/mtd-lpddr2_nvm-fix-possible-null-ptr-deref.patch new file mode 100644 index 00000000000..097594d1a06 --- /dev/null +++ b/queue-5.15/mtd-lpddr2_nvm-fix-possible-null-ptr-deref.patch @@ -0,0 +1,41 @@ +From b088e225e6c8928d7004361d8806dacf457b3374 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 17:02:40 +0800 +Subject: mtd: lpddr2_nvm: Fix possible null-ptr-deref +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hui Tang + +[ Upstream commit 6bdd45d795adf9e73b38ced5e7f750cd199499ff ] + +It will cause null-ptr-deref when resource_size(add_range) invoked, +if platform_get_resource() returns NULL. + +Fixes: 96ba9dd65788 ("mtd: lpddr: add driver for LPDDR2-NVM PCM memories") +Signed-off-by: Hui Tang +Acked-by: Uwe Kleine-König +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221114090240.244172-1-tanghui20@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/lpddr/lpddr2_nvm.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/mtd/lpddr/lpddr2_nvm.c b/drivers/mtd/lpddr/lpddr2_nvm.c +index 72f5c7b30079..add4386f99f0 100644 +--- a/drivers/mtd/lpddr/lpddr2_nvm.c ++++ b/drivers/mtd/lpddr/lpddr2_nvm.c +@@ -433,6 +433,8 @@ static int lpddr2_nvm_probe(struct platform_device *pdev) + + /* lpddr2_nvm address range */ + add_range = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!add_range) ++ return -ENODEV; + + /* Populate map_info data structure */ + *map = (struct map_info) { +-- +2.35.1 + diff --git a/queue-5.15/mtd-maps-pxa2xx-flash-fix-memory-leak-in-probe.patch b/queue-5.15/mtd-maps-pxa2xx-flash-fix-memory-leak-in-probe.patch new file mode 100644 index 00000000000..96b3ae5f2ff --- /dev/null +++ b/queue-5.15/mtd-maps-pxa2xx-flash-fix-memory-leak-in-probe.patch @@ -0,0 +1,44 @@ +From cf298dfa9bd6f94d66cfbb4903a63d8bdc66e593 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 07:33:07 +0000 +Subject: mtd: maps: pxa2xx-flash: fix memory leak in probe + +From: Zheng Yongjun + +[ Upstream commit 2399401feee27c639addc5b7e6ba519d3ca341bf ] + +Free 'info' upon remapping error to avoid a memory leak. + +Fixes: e644f7d62894 ("[MTD] MAPS: Merge Lubbock and Mainstone drivers into common PXA2xx driver") +Signed-off-by: Zheng Yongjun +[: Reword the commit log] +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20221119073307.22929-1-zhengyongjun3@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/maps/pxa2xx-flash.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c +index 7d96758a8f04..6e5e55755970 100644 +--- a/drivers/mtd/maps/pxa2xx-flash.c ++++ b/drivers/mtd/maps/pxa2xx-flash.c +@@ -66,6 +66,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) + if (!info->map.virt) { + printk(KERN_WARNING "Failed to ioremap %s\n", + info->map.name); ++ kfree(info); + return -ENOMEM; + } + info->map.cached = ioremap_cache(info->map.phys, info->map.size); +@@ -87,6 +88,7 @@ static int pxa2xx_flash_probe(struct platform_device *pdev) + iounmap((void *)info->map.virt); + if (info->map.cached) + iounmap(info->map.cached); ++ kfree(info); + return -EIO; + } + info->mtd->dev.parent = &pdev->dev; +-- +2.35.1 + diff --git a/queue-5.15/mtd-spi-nor-fix-the-number-of-bytes-for-the-dummy-cy.patch b/queue-5.15/mtd-spi-nor-fix-the-number-of-bytes-for-the-dummy-cy.patch new file mode 100644 index 00000000000..6ea43543c7a --- /dev/null +++ b/queue-5.15/mtd-spi-nor-fix-the-number-of-bytes-for-the-dummy-cy.patch @@ -0,0 +1,46 @@ +From c23db36ac29aa92d14215c22c484bd60dff1cf0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 20:46:33 +0800 +Subject: mtd: spi-nor: Fix the number of bytes for the dummy cycles + +From: Allen-KH Cheng + +[ Upstream commit fdc20370d93e8c6d2f448a539d08c2c064af7694 ] + +The number of bytes used by spi_nor_spimem_check_readop() may be +incorrect for the dummy cycles. Since nor->read_dummy is not initialized +before spi_nor_spimem_adjust_hwcaps(). + +We use both mode and wait state clock cycles instead of nor->read_dummy. + +Fixes: 0e30f47232ab ("mtd: spi-nor: add support for DTR protocol") +Co-developed-by: Bayi Cheng +Signed-off-by: Bayi Cheng +Signed-off-by: Allen-KH Cheng +Signed-off-by: Tudor Ambarus +Tested-by: Dhruva Gole +Tested-by: AngeloGioacchino Del Regno +Reviewed-by: Pratyush Yadav +Link: https://lore.kernel.org/r/20221031124633.13189-1-allen-kh.cheng@mediatek.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/spi-nor/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c +index eb5d7b3d1860..aad7076ae020 100644 +--- a/drivers/mtd/spi-nor/core.c ++++ b/drivers/mtd/spi-nor/core.c +@@ -2155,7 +2155,8 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, + spi_nor_spimem_setup_op(nor, &op, read->proto); + + /* convert the dummy cycles to the number of bytes */ +- op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; ++ op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) * ++ op.dummy.buswidth / 8; + if (spi_nor_protocol_is_dtr(nor->read_proto)) + op.dummy.nbytes *= 2; + +-- +2.35.1 + diff --git a/queue-5.15/mtd-spi-nor-hide-jedec_id-sysfs-attribute-if-not-pre.patch b/queue-5.15/mtd-spi-nor-hide-jedec_id-sysfs-attribute-if-not-pre.patch new file mode 100644 index 00000000000..660c348bcba --- /dev/null +++ b/queue-5.15/mtd-spi-nor-hide-jedec_id-sysfs-attribute-if-not-pre.patch @@ -0,0 +1,72 @@ +From 4436f440b2588a60d151488bc311ef56a3c7bb5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 00:06:48 +0200 +Subject: mtd: spi-nor: hide jedec_id sysfs attribute if not present + +From: Michael Walle + +[ Upstream commit 7d388551b6888f3725e6c957f472526b35161a5b ] + +Some non-jedec compliant flashes (like the Everspin flashes) don't have +an ID at all. Hide the attribute in this case. + +Fixes: 36ac02286265 ("mtd: spi-nor: add initial sysfs support") +Signed-off-by: Michael Walle +Signed-off-by: Tudor Ambarus +Reviewed-by: Takahiro Kuwano +Link: https://lore.kernel.org/r/20220810220654.1297699-2-michael@walle.cc +Signed-off-by: Sasha Levin +--- + .../ABI/testing/sysfs-bus-spi-devices-spi-nor | 3 +++ + drivers/mtd/spi-nor/sysfs.c | 14 ++++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor +index d76cd3946434..e9ef69aef20b 100644 +--- a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor ++++ b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor +@@ -5,6 +5,9 @@ Contact: linux-mtd@lists.infradead.org + Description: (RO) The JEDEC ID of the SPI NOR flash as reported by the + flash device. + ++ The attribute is not present if the flash doesn't support ++ the "Read JEDEC ID" command (9Fh). This is the case for ++ non-JEDEC compliant flashes. + + What: /sys/bus/spi/devices/.../spi-nor/manufacturer + Date: April 2021 +diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c +index 9aec9d8a98ad..4c3b351aef24 100644 +--- a/drivers/mtd/spi-nor/sysfs.c ++++ b/drivers/mtd/spi-nor/sysfs.c +@@ -67,6 +67,19 @@ static struct bin_attribute *spi_nor_sysfs_bin_entries[] = { + NULL + }; + ++static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj, ++ struct attribute *attr, int n) ++{ ++ struct spi_device *spi = to_spi_device(kobj_to_dev(kobj)); ++ struct spi_mem *spimem = spi_get_drvdata(spi); ++ struct spi_nor *nor = spi_mem_get_drvdata(spimem); ++ ++ if (attr == &dev_attr_jedec_id.attr && !nor->info->id_len) ++ return 0; ++ ++ return 0444; ++} ++ + static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj, + struct bin_attribute *attr, int n) + { +@@ -82,6 +95,7 @@ static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj, + + static const struct attribute_group spi_nor_sysfs_group = { + .name = "spi-nor", ++ .is_visible = spi_nor_sysfs_is_visible, + .is_bin_visible = spi_nor_sysfs_is_bin_visible, + .attrs = spi_nor_sysfs_entries, + .bin_attrs = spi_nor_sysfs_bin_entries, +-- +2.35.1 + diff --git a/queue-5.15/myri10ge-fix-an-error-handling-path-in-myri10ge_prob.patch b/queue-5.15/myri10ge-fix-an-error-handling-path-in-myri10ge_prob.patch new file mode 100644 index 00000000000..dd09c3857fb --- /dev/null +++ b/queue-5.15/myri10ge-fix-an-error-handling-path-in-myri10ge_prob.patch @@ -0,0 +1,37 @@ +From 229dd04f6a79b9ad34a54b0e85dea2a687ef3b14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Dec 2022 19:08:40 +0100 +Subject: myri10ge: Fix an error handling path in myri10ge_probe() + +From: Christophe JAILLET + +[ Upstream commit d83b950d44d2982c0e62e3d81b0f35ab09431008 ] + +Some memory allocated in myri10ge_probe_slices() is not released in the +error handling path of myri10ge_probe(). + +Add the corresponding kfree(), as already done in the remove function. + +Fixes: 0dcffac1a329 ("myri10ge: add multislices support") +Signed-off-by: Christophe JAILLET +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +index 052696ce5096..97c2604df019 100644 +--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c ++++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +@@ -3923,6 +3923,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + myri10ge_free_slices(mgp); + + abort_with_firmware: ++ kfree(mgp->msix_vectors); + myri10ge_dummy_rdma(mgp, 0); + + abort_with_ioremap: +-- +2.35.1 + diff --git a/queue-5.15/net-add-atomic_long_t-to-net_device_stats-fields.patch b/queue-5.15/net-add-atomic_long_t-to-net_device_stats-fields.patch new file mode 100644 index 00000000000..ed477b06e8a --- /dev/null +++ b/queue-5.15/net-add-atomic_long_t-to-net_device_stats-fields.patch @@ -0,0 +1,165 @@ +From 554c2aee094c40007b4474d331c4ea8be3a587cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 08:53:55 +0000 +Subject: net: add atomic_long_t to net_device_stats fields + +From: Eric Dumazet + +[ Upstream commit 6c1c5097781f563b70a81683ea6fdac21637573b ] + +Long standing KCSAN issues are caused by data-race around +some dev->stats changes. + +Most performance critical paths already use per-cpu +variables, or per-queue ones. + +It is reasonable (and more correct) to use atomic operations +for the slow paths. + +This patch adds an union for each field of net_device_stats, +so that we can convert paths that are not yet protected +by a spinlock or a mutex. + +netdev_stats_to_stats64() no longer has an #if BITS_PER_LONG==64 + +Note that the memcpy() we were using on 64bit arches +had no provision to avoid load-tearing, +while atomic_long_read() is providing the needed protection +at no cost. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/netdevice.h | 58 +++++++++++++++++++++++---------------- + include/net/dst.h | 5 ++-- + net/core/dev.c | 14 ++-------- + 3 files changed, 40 insertions(+), 37 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 3b97438afe3e..3a75d644a120 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -167,31 +167,38 @@ static inline bool dev_xmit_complete(int rc) + * (unsigned long) so they can be read and written atomically. + */ + ++#define NET_DEV_STAT(FIELD) \ ++ union { \ ++ unsigned long FIELD; \ ++ atomic_long_t __##FIELD; \ ++ } ++ + struct net_device_stats { +- unsigned long rx_packets; +- unsigned long tx_packets; +- unsigned long rx_bytes; +- unsigned long tx_bytes; +- unsigned long rx_errors; +- unsigned long tx_errors; +- unsigned long rx_dropped; +- unsigned long tx_dropped; +- unsigned long multicast; +- unsigned long collisions; +- unsigned long rx_length_errors; +- unsigned long rx_over_errors; +- unsigned long rx_crc_errors; +- unsigned long rx_frame_errors; +- unsigned long rx_fifo_errors; +- unsigned long rx_missed_errors; +- unsigned long tx_aborted_errors; +- unsigned long tx_carrier_errors; +- unsigned long tx_fifo_errors; +- unsigned long tx_heartbeat_errors; +- unsigned long tx_window_errors; +- unsigned long rx_compressed; +- unsigned long tx_compressed; ++ NET_DEV_STAT(rx_packets); ++ NET_DEV_STAT(tx_packets); ++ NET_DEV_STAT(rx_bytes); ++ NET_DEV_STAT(tx_bytes); ++ NET_DEV_STAT(rx_errors); ++ NET_DEV_STAT(tx_errors); ++ NET_DEV_STAT(rx_dropped); ++ NET_DEV_STAT(tx_dropped); ++ NET_DEV_STAT(multicast); ++ NET_DEV_STAT(collisions); ++ NET_DEV_STAT(rx_length_errors); ++ NET_DEV_STAT(rx_over_errors); ++ NET_DEV_STAT(rx_crc_errors); ++ NET_DEV_STAT(rx_frame_errors); ++ NET_DEV_STAT(rx_fifo_errors); ++ NET_DEV_STAT(rx_missed_errors); ++ NET_DEV_STAT(tx_aborted_errors); ++ NET_DEV_STAT(tx_carrier_errors); ++ NET_DEV_STAT(tx_fifo_errors); ++ NET_DEV_STAT(tx_heartbeat_errors); ++ NET_DEV_STAT(tx_window_errors); ++ NET_DEV_STAT(rx_compressed); ++ NET_DEV_STAT(tx_compressed); + }; ++#undef NET_DEV_STAT + + + #include +@@ -5477,4 +5484,9 @@ extern struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly; + + extern struct net_device *blackhole_netdev; + ++/* Note: Avoid these macros in fast path, prefer per-cpu or per-queue counters. */ ++#define DEV_STATS_INC(DEV, FIELD) atomic_long_inc(&(DEV)->stats.__##FIELD) ++#define DEV_STATS_ADD(DEV, FIELD, VAL) \ ++ atomic_long_add((VAL), &(DEV)->stats.__##FIELD) ++ + #endif /* _LINUX_NETDEVICE_H */ +diff --git a/include/net/dst.h b/include/net/dst.h +index a057319aabef..17697ec79949 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -361,9 +361,8 @@ static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + static inline void skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev, + struct net *net) + { +- /* TODO : stats should be SMP safe */ +- dev->stats.rx_packets++; +- dev->stats.rx_bytes += skb->len; ++ DEV_STATS_INC(dev, rx_packets); ++ DEV_STATS_ADD(dev, rx_bytes, skb->len); + __skb_tunnel_rx(skb, dev, net); + } + +diff --git a/net/core/dev.c b/net/core/dev.c +index be51644e95da..33d6b691e15e 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -10640,24 +10640,16 @@ void netdev_run_todo(void) + void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, + const struct net_device_stats *netdev_stats) + { +-#if BITS_PER_LONG == 64 +- BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats)); +- memcpy(stats64, netdev_stats, sizeof(*netdev_stats)); +- /* zero out counters that only exist in rtnl_link_stats64 */ +- memset((char *)stats64 + sizeof(*netdev_stats), 0, +- sizeof(*stats64) - sizeof(*netdev_stats)); +-#else +- size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long); +- const unsigned long *src = (const unsigned long *)netdev_stats; ++ size_t i, n = sizeof(*netdev_stats) / sizeof(atomic_long_t); ++ const atomic_long_t *src = (atomic_long_t *)netdev_stats; + u64 *dst = (u64 *)stats64; + + BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64)); + for (i = 0; i < n; i++) +- dst[i] = src[i]; ++ dst[i] = atomic_long_read(&src[i]); + /* zero out counters that only exist in rtnl_link_stats64 */ + memset((char *)stats64 + n * sizeof(u64), 0, + sizeof(*stats64) - n * sizeof(u64)); +-#endif + } + EXPORT_SYMBOL(netdev_stats_to_stats64); + +-- +2.35.1 + diff --git a/queue-5.15/net-amd-lance-don-t-call-dev_kfree_skb-under-spin_lo.patch b/queue-5.15/net-amd-lance-don-t-call-dev_kfree_skb-under-spin_lo.patch new file mode 100644 index 00000000000..f8ae4cf4891 --- /dev/null +++ b/queue-5.15/net-amd-lance-don-t-call-dev_kfree_skb-under-spin_lo.patch @@ -0,0 +1,58 @@ +From 67fac6a31cd134cb6018b794f9027caf398d0d74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 22:21:47 +0800 +Subject: net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 6151d105dfce8c23edf30eed35e97f3d9b96a35c ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In these two cases, dev_kfree_skb() is called consume the xmited SKB, +so replace it with dev_consume_skb_irq(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/atarilance.c | 2 +- + drivers/net/ethernet/amd/lance.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c +index 9d2f49fd945e..a0971ed00453 100644 +--- a/drivers/net/ethernet/amd/atarilance.c ++++ b/drivers/net/ethernet/amd/atarilance.c +@@ -821,7 +821,7 @@ lance_start_xmit(struct sk_buff *skb, struct net_device *dev) + lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); + head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; + dev->stats.tx_bytes += skb->len; +- dev_kfree_skb( skb ); ++ dev_consume_skb_irq(skb); + lp->cur_tx++; + while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) { + lp->cur_tx -= TX_RING_SIZE; +diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c +index 945bf1d87507..6c2d72024e21 100644 +--- a/drivers/net/ethernet/amd/lance.c ++++ b/drivers/net/ethernet/amd/lance.c +@@ -999,7 +999,7 @@ static netdev_tx_t lance_start_xmit(struct sk_buff *skb, + skb_copy_from_linear_data(skb, &lp->tx_bounce_buffs[entry], skb->len); + lp->tx_ring[entry].base = + ((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000; +- dev_kfree_skb(skb); ++ dev_consume_skb_irq(skb); + } else { + lp->tx_skbuff[entry] = skb; + lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000; +-- +2.35.1 + diff --git a/queue-5.15/net-amd-xgbe-check-only-the-minimum-speed-for-active.patch b/queue-5.15/net-amd-xgbe-check-only-the-minimum-speed-for-active.patch new file mode 100644 index 00000000000..aa722e38bd8 --- /dev/null +++ b/queue-5.15/net-amd-xgbe-check-only-the-minimum-speed-for-active.patch @@ -0,0 +1,75 @@ +From 0ad63be51b7cf8f96cf4694354277ae24c958d29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 10:22:25 -0600 +Subject: net: amd-xgbe: Check only the minimum speed for active/passive cables + +From: Tom Lendacky + +[ Upstream commit f8ab263d4d48e6dab752029bf562f20a2ee630ed ] + +There are cables that exist that can support speeds in excess of 10GbE. +The driver, however, restricts the EEPROM advertised nominal bitrate to +a specific range, which can prevent usage of cables that can support, +for example, up to 25GbE. + +Rather than checking that an active or passive cable supports a specific +range, only check for a minimum supported speed. + +Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index a9a734454973..97e32c0490f8 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -237,10 +237,7 @@ enum xgbe_sfp_speed { + + #define XGBE_SFP_BASE_BR 12 + #define XGBE_SFP_BASE_BR_1GBE_MIN 0x0a +-#define XGBE_SFP_BASE_BR_1GBE_MAX 0x0d + #define XGBE_SFP_BASE_BR_10GBE_MIN 0x64 +-#define XGBE_SFP_BASE_BR_10GBE_MAX 0x68 +-#define XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX 0x78 + + #define XGBE_SFP_BASE_CU_CABLE_LEN 18 + +@@ -827,29 +824,22 @@ static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata) + static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom, + enum xgbe_sfp_speed sfp_speed) + { +- u8 *sfp_base, min, max; ++ u8 *sfp_base, min; + + sfp_base = sfp_eeprom->base; + + switch (sfp_speed) { + case XGBE_SFP_SPEED_1000: + min = XGBE_SFP_BASE_BR_1GBE_MIN; +- max = XGBE_SFP_BASE_BR_1GBE_MAX; + break; + case XGBE_SFP_SPEED_10000: + min = XGBE_SFP_BASE_BR_10GBE_MIN; +- if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME], +- XGBE_MOLEX_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN) == 0) +- max = XGBE_MOLEX_SFP_BASE_BR_10GBE_MAX; +- else +- max = XGBE_SFP_BASE_BR_10GBE_MAX; + break; + default: + return false; + } + +- return ((sfp_base[XGBE_SFP_BASE_BR] >= min) && +- (sfp_base[XGBE_SFP_BASE_BR] <= max)); ++ return sfp_base[XGBE_SFP_BASE_BR] >= min; + } + + static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata) +-- +2.35.1 + diff --git a/queue-5.15/net-amd-xgbe-fix-logic-around-active-and-passive-cab.patch b/queue-5.15/net-amd-xgbe-fix-logic-around-active-and-passive-cab.patch new file mode 100644 index 00000000000..66ed5c44672 --- /dev/null +++ b/queue-5.15/net-amd-xgbe-fix-logic-around-active-and-passive-cab.patch @@ -0,0 +1,63 @@ +From c16f4718173eac655e54d44492d4c83336a212d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 10:22:24 -0600 +Subject: net: amd-xgbe: Fix logic around active and passive cables + +From: Tom Lendacky + +[ Upstream commit 4998006c73afe44e2f639d55bd331c6c26eb039f ] + +SFP+ active and passive cables are copper cables with fixed SFP+ end +connectors. Due to a misinterpretation of this, SFP+ active cables could +end up not being recognized, causing the driver to fail to establish a +connection. + +Introduce a new enum in SFP+ cable types, XGBE_SFP_CABLE_FIBER, that is +the default cable type, and handle active and passive cables when they are +specifically detected. + +Fixes: abf0a1c2b26a ("amd-xgbe: Add support for SFP+ modules") +Signed-off-by: Tom Lendacky +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +index a7166cd1179f..a9a734454973 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +@@ -189,6 +189,7 @@ enum xgbe_sfp_cable { + XGBE_SFP_CABLE_UNKNOWN = 0, + XGBE_SFP_CABLE_ACTIVE, + XGBE_SFP_CABLE_PASSIVE, ++ XGBE_SFP_CABLE_FIBER, + }; + + enum xgbe_sfp_base { +@@ -1149,16 +1150,18 @@ static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata) + phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data); + phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data); + +- /* Assume ACTIVE cable unless told it is PASSIVE */ ++ /* Assume FIBER cable unless told otherwise */ + if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) { + phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE; + phy_data->sfp_cable_len = sfp_base[XGBE_SFP_BASE_CU_CABLE_LEN]; +- } else { ++ } else if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_ACTIVE) { + phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE; ++ } else { ++ phy_data->sfp_cable = XGBE_SFP_CABLE_FIBER; + } + + /* Determine the type of SFP */ +- if (phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE && ++ if (phy_data->sfp_cable != XGBE_SFP_CABLE_FIBER && + xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000)) + phy_data->sfp_base = XGBE_SFP_BASE_10000_CR; + else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR) +-- +2.35.1 + diff --git a/queue-5.15/net-apple-bmac-don-t-call-dev_kfree_skb-under-spin_l.patch b/queue-5.15/net-apple-bmac-don-t-call-dev_kfree_skb-under-spin_l.patch new file mode 100644 index 00000000000..da26b4f1179 --- /dev/null +++ b/queue-5.15/net-apple-bmac-don-t-call-dev_kfree_skb-under-spin_l.patch @@ -0,0 +1,45 @@ +From d96955e5d2fe6df5dc7dfeecece252ca5de9c981 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 21:37:35 +0800 +Subject: net: apple: bmac: don't call dev_kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 5fe02e046e6422c4adfdbc50206ec7186077da24 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In this case, dev_kfree_skb() is called in bmac_tx_timeout() to drop +the SKB, when tx timeout, so replace it with dev_kfree_skb_irq(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/apple/bmac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c +index a989d2df59ad..7a966361d83f 100644 +--- a/drivers/net/ethernet/apple/bmac.c ++++ b/drivers/net/ethernet/apple/bmac.c +@@ -1511,7 +1511,7 @@ static void bmac_tx_timeout(struct timer_list *t) + i = bp->tx_empty; + ++dev->stats.tx_errors; + if (i != bp->tx_fill) { +- dev_kfree_skb(bp->tx_bufs[i]); ++ dev_kfree_skb_irq(bp->tx_bufs[i]); + bp->tx_bufs[i] = NULL; + if (++i >= N_TX_RING) i = 0; + bp->tx_empty = i; +-- +2.35.1 + diff --git a/queue-5.15/net-apple-mace-don-t-call-dev_kfree_skb-under-spin_l.patch b/queue-5.15/net-apple-mace-don-t-call-dev_kfree_skb-under-spin_l.patch new file mode 100644 index 00000000000..afc5f5973d0 --- /dev/null +++ b/queue-5.15/net-apple-mace-don-t-call-dev_kfree_skb-under-spin_l.patch @@ -0,0 +1,45 @@ +From a2e0782b77bff9daf74e3986c9e129d16acc0f05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 21:37:34 +0800 +Subject: net: apple: mace: don't call dev_kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit 3dfe3486c1cd4f82b466b7d307f23777137b8acc ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In this case, dev_kfree_skb() is called in mace_tx_timeout() to drop +the SKB, when tx timeout, so replace it with dev_kfree_skb_irq(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/apple/mace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c +index 4b80e3a52a19..44037e9e197f 100644 +--- a/drivers/net/ethernet/apple/mace.c ++++ b/drivers/net/ethernet/apple/mace.c +@@ -841,7 +841,7 @@ static void mace_tx_timeout(struct timer_list *t) + if (mp->tx_bad_runt) { + mp->tx_bad_runt = 0; + } else if (i != mp->tx_fill) { +- dev_kfree_skb(mp->tx_bufs[i]); ++ dev_kfree_skb_irq(mp->tx_bufs[i]); + if (++i >= N_TX_RING) + i = 0; + mp->tx_empty = i; +-- +2.35.1 + diff --git a/queue-5.15/net-defxx-fix-missing-err-handling-in-dfx_init.patch b/queue-5.15/net-defxx-fix-missing-err-handling-in-dfx_init.patch new file mode 100644 index 00000000000..26c578fd891 --- /dev/null +++ b/queue-5.15/net-defxx-fix-missing-err-handling-in-dfx_init.patch @@ -0,0 +1,61 @@ +From d8cc084fba30b6b81eb743f089ef00488779950a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 07:20:45 +0000 +Subject: net: defxx: Fix missing err handling in dfx_init() + +From: Yongqiang Liu + +[ Upstream commit ae18dcdff0f8d7e84cd3fd9f496518b5e72d185d ] + +When eisa_driver_register() or tc_register_driver() failed, +the modprobe defxx would fail with some err log as follows: + + Error: Driver 'defxx' is already registered, aborting... + +Fix this issue by adding err hanling in dfx_init(). + +Fixes: e89a2cfb7d7b5 ("[TC] defxx: TURBOchannel support") +Signed-off-by: Yongqiang Liu +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/fddi/defxx.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c +index 6d1e3f49a3d3..ebf502290e5f 100644 +--- a/drivers/net/fddi/defxx.c ++++ b/drivers/net/fddi/defxx.c +@@ -3831,10 +3831,24 @@ static int dfx_init(void) + int status; + + status = pci_register_driver(&dfx_pci_driver); +- if (!status) +- status = eisa_driver_register(&dfx_eisa_driver); +- if (!status) +- status = tc_register_driver(&dfx_tc_driver); ++ if (status) ++ goto err_pci_register; ++ ++ status = eisa_driver_register(&dfx_eisa_driver); ++ if (status) ++ goto err_eisa_register; ++ ++ status = tc_register_driver(&dfx_tc_driver); ++ if (status) ++ goto err_tc_register; ++ ++ return 0; ++ ++err_tc_register: ++ eisa_driver_unregister(&dfx_eisa_driver); ++err_eisa_register: ++ pci_unregister_driver(&dfx_pci_driver); ++err_pci_register: + return status; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-dpaa2-publish-mac-stringset-to-ethtool-s-even-if.patch b/queue-5.15/net-dpaa2-publish-mac-stringset-to-ethtool-s-even-if.patch new file mode 100644 index 00000000000..f7479fd5870 --- /dev/null +++ b/queue-5.15/net-dpaa2-publish-mac-stringset-to-ethtool-s-even-if.patch @@ -0,0 +1,123 @@ +From 56aeb6903aecfae9f65677d2625a15b7d68a56cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 16:12:16 +0200 +Subject: net: dpaa2: publish MAC stringset to ethtool -S even if MAC is + missing + +From: Vladimir Oltean + +[ Upstream commit 29811d6e19d795efcf26644b66c4152abbac35a6 ] + +DPNIs and DPSW objects can connect and disconnect at runtime from DPMAC +objects on the same fsl-mc bus. The DPMAC object also holds "ethtool -S" +unstructured counters. Those counters are only shown for the entity +owning the netdev (DPNI, DPSW) if it's connected to a DPMAC. + +The ethtool stringset code path is split into multiple callbacks, but +currently, connecting and disconnecting the DPMAC takes the rtnl_lock(). +This blocks the entire ethtool code path from running, see +ethnl_default_doit() -> rtnl_lock() -> ops->prepare_data() -> +strset_prepare_data(). + +This is going to be a problem if we are going to no longer require +rtnl_lock() when connecting/disconnecting the DPMAC, because the DPMAC +could appear between ops->get_sset_count() and ops->get_strings(). +If it appears out of the blue, we will provide a stringset into an array +that was dimensioned thinking the DPMAC wouldn't be there => array +accessed out of bounds. + +There isn't really a good way to work around that, and I don't want to +put too much pressure on the ethtool framework by playing locking games. +Just make the DPMAC counters be always available. They'll be zeroes if +the DPNI or DPSW isn't connected to a DPMAC. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Andrew Lunn +Reviewed-by: Ioana Ciornei +Tested-by: Ioana Ciornei +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c | 12 +++--------- + .../ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c | 11 ++--------- + 2 files changed, 5 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c +index 2da5f881f630..714a0a058faf 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c +@@ -184,7 +184,6 @@ static int dpaa2_eth_set_pauseparam(struct net_device *net_dev, + static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) + { +- struct dpaa2_eth_priv *priv = netdev_priv(netdev); + u8 *p = data; + int i; + +@@ -198,22 +197,17 @@ static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset, + strscpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } +- if (dpaa2_eth_has_mac(priv)) +- dpaa2_mac_get_strings(p); ++ dpaa2_mac_get_strings(p); + break; + } + } + + static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset) + { +- int num_ss_stats = DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS; +- struct dpaa2_eth_priv *priv = netdev_priv(net_dev); +- + switch (sset) { + case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */ +- if (dpaa2_eth_has_mac(priv)) +- num_ss_stats += dpaa2_mac_get_sset_count(); +- return num_ss_stats; ++ return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS + ++ dpaa2_mac_get_sset_count(); + default: + return -EOPNOTSUPP; + } +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c +index 720c9230cab5..40ee57ef55be 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c +@@ -145,14 +145,9 @@ dpaa2_switch_set_link_ksettings(struct net_device *netdev, + static int + dpaa2_switch_ethtool_get_sset_count(struct net_device *netdev, int sset) + { +- struct ethsw_port_priv *port_priv = netdev_priv(netdev); +- int num_ss_stats = DPAA2_SWITCH_NUM_COUNTERS; +- + switch (sset) { + case ETH_SS_STATS: +- if (port_priv->mac) +- num_ss_stats += dpaa2_mac_get_sset_count(); +- return num_ss_stats; ++ return DPAA2_SWITCH_NUM_COUNTERS + dpaa2_mac_get_sset_count(); + default: + return -EOPNOTSUPP; + } +@@ -161,7 +156,6 @@ dpaa2_switch_ethtool_get_sset_count(struct net_device *netdev, int sset) + static void dpaa2_switch_ethtool_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) + { +- struct ethsw_port_priv *port_priv = netdev_priv(netdev); + u8 *p = data; + int i; + +@@ -172,8 +166,7 @@ static void dpaa2_switch_ethtool_get_strings(struct net_device *netdev, + ETH_GSTRING_LEN); + p += ETH_GSTRING_LEN; + } +- if (port_priv->mac) +- dpaa2_mac_get_strings(p); ++ dpaa2_mac_get_strings(p); + break; + } + } +-- +2.35.1 + diff --git a/queue-5.15/net-dsa-tag_8021q-avoid-leaking-ctx-on-dsa_tag_8021q.patch b/queue-5.15/net-dsa-tag_8021q-avoid-leaking-ctx-on-dsa_tag_8021q.patch new file mode 100644 index 00000000000..6593fb346d3 --- /dev/null +++ b/queue-5.15/net-dsa-tag_8021q-avoid-leaking-ctx-on-dsa_tag_8021q.patch @@ -0,0 +1,55 @@ +From 608234bab069b4cc724c92df0c1ac87ce1e4b9d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Dec 2022 01:52:42 +0200 +Subject: net: dsa: tag_8021q: avoid leaking ctx on dsa_tag_8021q_register() + error path + +From: Vladimir Oltean + +[ Upstream commit e095493091e850d5292ad01d8fbf5cde1d89ac53 ] + +If dsa_tag_8021q_setup() fails, for example due to the inability of the +device to install a VLAN, the tag_8021q context of the switch will leak. +Make sure it is freed on the error path. + +Fixes: 328621f6131f ("net: dsa: tag_8021q: absorb dsa_8021q_setup into dsa_tag_8021q_{,un}register") +Signed-off-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20221209235242.480344-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/dsa/tag_8021q.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c +index f8f7b7c34e7d..e443088ab0f6 100644 +--- a/net/dsa/tag_8021q.c ++++ b/net/dsa/tag_8021q.c +@@ -529,6 +529,7 @@ static void dsa_tag_8021q_teardown(struct dsa_switch *ds) + int dsa_tag_8021q_register(struct dsa_switch *ds, __be16 proto) + { + struct dsa_8021q_context *ctx; ++ int err; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) +@@ -541,7 +542,15 @@ int dsa_tag_8021q_register(struct dsa_switch *ds, __be16 proto) + + ds->tag_8021q_ctx = ctx; + +- return dsa_tag_8021q_setup(ds); ++ err = dsa_tag_8021q_setup(ds); ++ if (err) ++ goto err_free; ++ ++ return 0; ++ ++err_free: ++ kfree(ctx); ++ return err; + } + EXPORT_SYMBOL_GPL(dsa_tag_8021q_register); + +-- +2.35.1 + diff --git a/queue-5.15/net-emaclite-don-t-call-dev_kfree_skb-under-spin_loc.patch b/queue-5.15/net-emaclite-don-t-call-dev_kfree_skb-under-spin_loc.patch new file mode 100644 index 00000000000..326ff606290 --- /dev/null +++ b/queue-5.15/net-emaclite-don-t-call-dev_kfree_skb-under-spin_loc.patch @@ -0,0 +1,44 @@ +From fab8eb70887d386c708554b6c23daca5e51baa65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 22:21:44 +0800 +Subject: net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit d1678bf45f21fa5ae4a456f821858679556ea5f8 ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +It should use dev_kfree_skb_irq() or dev_consume_skb_irq() instead. +The difference between them is free reason, dev_kfree_skb_irq() means +the SKB is dropped in error and dev_consume_skb_irq() means the SKB +is consumed in normal. + +In this case, dev_kfree_skb() is called in xemaclite_tx_timeout() to +drop the SKB, when tx timeout, so replace it with dev_kfree_skb_irq(). + +Fixes: bb81b2ddfa19 ("net: add Xilinx emac lite device driver") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +index 97c1d1ecba34..b1971c4d5313 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -543,7 +543,7 @@ static void xemaclite_tx_timeout(struct net_device *dev, unsigned int txqueue) + xemaclite_enable_interrupts(lp); + + if (lp->deferred_skb) { +- dev_kfree_skb(lp->deferred_skb); ++ dev_kfree_skb_irq(lp->deferred_skb); + lp->deferred_skb = NULL; + dev->stats.tx_errors++; + } +-- +2.35.1 + diff --git a/queue-5.15/net-enetc-avoid-buffer-leaks-on-xdp_do_redirect-fail.patch b/queue-5.15/net-enetc-avoid-buffer-leaks-on-xdp_do_redirect-fail.patch new file mode 100644 index 00000000000..3dff91d1eec --- /dev/null +++ b/queue-5.15/net-enetc-avoid-buffer-leaks-on-xdp_do_redirect-fail.patch @@ -0,0 +1,148 @@ +From 1b5f5e82f6365a7ade393a2e7762904e9ae2648f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 02:19:08 +0200 +Subject: net: enetc: avoid buffer leaks on xdp_do_redirect() failure + +From: Vladimir Oltean + +[ Upstream commit 628050ec952d2e2e46ec9fb6aa07e41139e030c8 ] + +Before enetc_clean_rx_ring_xdp() calls xdp_do_redirect(), each software +BD in the RX ring between index orig_i and i can have one of 2 refcount +values on its page. + +We are the owner of the current buffer that is being processed, so the +refcount will be at least 1. + +If the current owner of the buffer at the diametrically opposed index +in the RX ring (i.o.w, the other half of this page) has not yet called +kfree(), this page's refcount could even be 2. + +enetc_page_reusable() in enetc_flip_rx_buff() tests for the page +refcount against 1, and [ if it's 2 ] does not attempt to reuse it. + +But if enetc_flip_rx_buff() is put after the xdp_do_redirect() call, +the page refcount can have one of 3 values. It can also be 0, if there +is no owner of the other page half, and xdp_do_redirect() for this +buffer ran so far that it triggered a flush of the devmap/cpumap bulk +queue, and the consumers of those bulk queues also freed the buffer, +all by the time xdp_do_redirect() returns the execution back to enetc. + +This is the reason why enetc_flip_rx_buff() is called before +xdp_do_redirect(), but there is a big flaw with that reasoning: +enetc_flip_rx_buff() will set rx_swbd->page = NULL on both sides of the +enetc_page_reusable() branch, and if xdp_do_redirect() returns an error, +we call enetc_xdp_free(), which does not deal gracefully with that. + +In fact, what happens is quite special. The page refcounts start as 1. +enetc_flip_rx_buff() figures they're reusable, transfers these +rx_swbd->page pointers to a different rx_swbd in enetc_reuse_page(), and +bumps the refcount to 2. When xdp_do_redirect() later returns an error, +we call the no-op enetc_xdp_free(), but we still haven't lost the +reference to that page. A copy of it is still at rx_ring->next_to_alloc, +but that has refcount 2 (and there are no concurrent owners of it in +flight, to drop the refcount). What really kills the system is when +we'll flip the rx_swbd->page the second time around. With an updated +refcount of 2, the page will not be reusable and we'll really leak it. +Then enetc_new_page() will have to allocate more pages, which will then +eventually leak again on further errors from xdp_do_redirect(). + +The problem, summarized, is that we zeroize rx_swbd->page before we're +completely done with it, and this makes it impossible for the error path +to do something with it. + +Since the packet is potentially multi-buffer and therefore the +rx_swbd->page is potentially an array, manual passing of the old +pointers between enetc_flip_rx_buff() and enetc_xdp_free() is a bit +difficult. + +For the sake of going with a simple solution, we accept the possibility +of racing with xdp_do_redirect(), and we move the flip procedure to +execute only on the redirect success path. By racing, I mean that the +page may be deemed as not reusable by enetc (having a refcount of 0), +but there will be no leak in that case, either. + +Once we accept that, we have something better to do with buffers on +XDP_REDIRECT failure. Since we haven't performed half-page flipping yet, +we won't, either (and this way, we can avoid enetc_xdp_free() +completely, which gives the entire page to the slab allocator). +Instead, we'll call enetc_xdp_drop(), which will recycle this half of +the buffer back to the RX ring. + +Fixes: 9d2b68cc108d ("net: enetc: add support for XDP_REDIRECT") +Suggested-by: Lorenzo Bianconi +Signed-off-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20221213001908.2347046-1-vladimir.oltean@nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/enetc/enetc.c | 35 +++++--------------- + 1 file changed, 8 insertions(+), 27 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c +index 222a250fba84..adccb14c1644 100644 +--- a/drivers/net/ethernet/freescale/enetc/enetc.c ++++ b/drivers/net/ethernet/freescale/enetc/enetc.c +@@ -1220,23 +1220,6 @@ static void enetc_xdp_drop(struct enetc_bdr *rx_ring, int rx_ring_first, + rx_ring->stats.xdp_drops++; + } + +-static void enetc_xdp_free(struct enetc_bdr *rx_ring, int rx_ring_first, +- int rx_ring_last) +-{ +- while (rx_ring_first != rx_ring_last) { +- struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[rx_ring_first]; +- +- if (rx_swbd->page) { +- dma_unmap_page(rx_ring->dev, rx_swbd->dma, PAGE_SIZE, +- rx_swbd->dir); +- __free_page(rx_swbd->page); +- rx_swbd->page = NULL; +- } +- enetc_bdr_idx_inc(rx_ring, &rx_ring_first); +- } +- rx_ring->stats.xdp_redirect_failures++; +-} +- + static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + struct napi_struct *napi, int work_limit, + struct bpf_prog *prog) +@@ -1258,8 +1241,8 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + int orig_i, orig_cleaned_cnt; + struct xdp_buff xdp_buff; + struct sk_buff *skb; +- int tmp_orig_i, err; + u32 bd_status; ++ int err; + + rxbd = enetc_rxbd(rx_ring, i); + bd_status = le32_to_cpu(rxbd->r.lstatus); +@@ -1346,18 +1329,16 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, + break; + } + +- tmp_orig_i = orig_i; +- +- while (orig_i != i) { +- enetc_flip_rx_buff(rx_ring, +- &rx_ring->rx_swbd[orig_i]); +- enetc_bdr_idx_inc(rx_ring, &orig_i); +- } +- + err = xdp_do_redirect(rx_ring->ndev, &xdp_buff, prog); + if (unlikely(err)) { +- enetc_xdp_free(rx_ring, tmp_orig_i, i); ++ enetc_xdp_drop(rx_ring, orig_i, i); ++ rx_ring->stats.xdp_redirect_failures++; + } else { ++ while (orig_i != i) { ++ enetc_flip_rx_buff(rx_ring, ++ &rx_ring->rx_swbd[orig_i]); ++ enetc_bdr_idx_inc(rx_ring, &orig_i); ++ } + xdp_redirect_frm_cnt++; + rx_ring->stats.xdp_redirect++; + } +-- +2.35.1 + diff --git a/queue-5.15/net-ethernet-dnet-don-t-call-dev_kfree_skb-under-spi.patch b/queue-5.15/net-ethernet-dnet-don-t-call-dev_kfree_skb-under-spi.patch new file mode 100644 index 00000000000..70c7454b4c3 --- /dev/null +++ b/queue-5.15/net-ethernet-dnet-don-t-call-dev_kfree_skb-under-spi.patch @@ -0,0 +1,45 @@ +From b2f90e64308d47e1162d9071504e8b43e6c5c72b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 22:21:45 +0800 +Subject: net: ethernet: dnet: don't call dev_kfree_skb() under + spin_lock_irqsave() + +From: Yang Yingliang + +[ Upstream commit f07fadcbee2a5e84caa67c7c445424200bffb60b ] + +It is not allowed to call kfree_skb() or consume_skb() from hardware +interrupt context or with hardware interrupts being disabled. + +In this case, the lock is used to protected 'bp', so we can move +dev_kfree_skb() after the spin_unlock_irqrestore(). + +Fixes: 4796417417a6 ("dnet: Dave DNET ethernet controller driver (updated)") +Signed-off-by: Yang Yingliang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/dnet.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/dnet.c b/drivers/net/ethernet/dnet.c +index 6c51cf991dad..14dc2e13bf03 100644 +--- a/drivers/net/ethernet/dnet.c ++++ b/drivers/net/ethernet/dnet.c +@@ -550,11 +550,11 @@ static netdev_tx_t dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) + + skb_tx_timestamp(skb); + ++ spin_unlock_irqrestore(&bp->lock, flags); ++ + /* free the buffer */ + dev_kfree_skb(skb); + +- spin_unlock_irqrestore(&bp->lock, flags); +- + return NETDEV_TX_OK; + } + +-- +2.35.1 + diff --git a/queue-5.15/net-ethernet-ti-fix-return-type-of-netcp_ndo_start_x.patch b/queue-5.15/net-ethernet-ti-fix-return-type-of-netcp_ndo_start_x.patch new file mode 100644 index 00000000000..0fb6a2ffe9a --- /dev/null +++ b/queue-5.15/net-ethernet-ti-fix-return-type-of-netcp_ndo_start_x.patch @@ -0,0 +1,53 @@ +From 3511f82a9a6db0f71a83a3a29929b2f1f36fc205 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 09:09:33 -0700 +Subject: net: ethernet: ti: Fix return type of netcp_ndo_start_xmit() + +From: Nathan Chancellor + +[ Upstream commit 63fe6ff674a96cfcfc0fa8df1051a27aa31c70b4 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/net/ethernet/ti/netcp_core.c:1944:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = netcp_ndo_start_xmit, + ^~~~~~~~~~~~~~~~~~~~ + 1 error generated. + +->ndo_start_xmit() in 'struct net_device_ops' expects a return type of +'netdev_tx_t', not 'int'. Adjust the return type of +netcp_ndo_start_xmit() to match the prototype's to resolve the warning +and CFI failure. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Signed-off-by: Nathan Chancellor +Reviewed-by: Kees Cook +Link: https://lore.kernel.org/r/20221102160933.1601260-1-nathan@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/netcp_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c +index eda2961c0fe2..07bdeece1723 100644 +--- a/drivers/net/ethernet/ti/netcp_core.c ++++ b/drivers/net/ethernet/ti/netcp_core.c +@@ -1262,7 +1262,7 @@ static int netcp_tx_submit_skb(struct netcp_intf *netcp, + } + + /* Submit the packet */ +-static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++static netdev_tx_t netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct netcp_intf *netcp = netdev_priv(ndev); + struct netcp_stats *tx_stats = &netcp->stats; +-- +2.35.1 + diff --git a/queue-5.15/net-farsync-fix-kmemleak-when-rmmods-farsync.patch b/queue-5.15/net-farsync-fix-kmemleak-when-rmmods-farsync.patch new file mode 100644 index 00000000000..85e232823f6 --- /dev/null +++ b/queue-5.15/net-farsync-fix-kmemleak-when-rmmods-farsync.patch @@ -0,0 +1,75 @@ +From 8ba10b2c6b77217cab8a958ae2af3b82000b264d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 20:05:40 +0800 +Subject: net: farsync: Fix kmemleak when rmmods farsync + +From: Li Zetao + +[ Upstream commit 2f623aaf9f31de968dea6169849706a2f9be444c ] + +There are two memory leaks reported by kmemleak: + + unreferenced object 0xffff888114b20200 (size 128): + comm "modprobe", pid 4846, jiffies 4295146524 (age 401.345s) + hex dump (first 32 bytes): + e0 62 57 09 81 88 ff ff e0 62 57 09 81 88 ff ff .bW......bW..... + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [] kmalloc_trace+0x22/0x60 + [] __hw_addr_add_ex+0x198/0x6c0 + [] dev_addr_init+0x13d/0x230 + [] alloc_netdev_mqs+0x10d/0xe50 + [] alloc_hdlcdev+0x2e/0x80 + [] fst_add_one+0x601/0x10e0 [farsync] + ... + + unreferenced object 0xffff88810b85b000 (size 1024): + comm "modprobe", pid 4846, jiffies 4295146523 (age 401.346s) + hex dump (first 32 bytes): + 00 00 b0 02 00 c9 ff ff 00 70 0a 00 00 c9 ff ff .........p...... + 00 00 00 f2 00 00 00 f3 0a 00 00 00 02 00 00 00 ................ + backtrace: + [] kmalloc_trace+0x22/0x60 + [] fst_add_one+0x154/0x10e0 [farsync] + [] local_pci_probe+0xd3/0x170 + ... + +The root cause is traced to the netdev and fst_card_info are not freed +when removes one fst in fst_remove_one(), which may trigger oom if +repeated insmod and rmmod module. + +Fix it by adding free_netdev() and kfree() in fst_remove_one(), just as +the operations on the error handling path in fst_add_one(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Li Zetao +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/wan/farsync.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c +index 6a212c085435..5b01642ca44e 100644 +--- a/drivers/net/wan/farsync.c ++++ b/drivers/net/wan/farsync.c +@@ -2545,6 +2545,7 @@ fst_remove_one(struct pci_dev *pdev) + struct net_device *dev = port_to_dev(&card->ports[i]); + + unregister_hdlc_device(dev); ++ free_netdev(dev); + } + + fst_disable_intr(card); +@@ -2564,6 +2565,7 @@ fst_remove_one(struct pci_dev *pdev) + card->tx_dma_handle_card); + } + fst_card_array[card->card_no] = NULL; ++ kfree(card); + } + + static struct pci_driver fst_driver = { +-- +2.35.1 + diff --git a/queue-5.15/net-lan9303-fix-read-error-execution-path.patch b/queue-5.15/net-lan9303-fix-read-error-execution-path.patch new file mode 100644 index 00000000000..c926b6c911e --- /dev/null +++ b/queue-5.15/net-lan9303-fix-read-error-execution-path.patch @@ -0,0 +1,44 @@ +From b8afbf321f53e957d27b5911a461d0154327e910 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 09:35:02 -0600 +Subject: net: lan9303: Fix read error execution path + +From: Jerry Ray + +[ Upstream commit 8964916d206071b058c6351f88b1966bd58cbde0 ] + +This patch fixes an issue where a read failure of a port statistic counter +will return unknown results. While it is highly unlikely the read will +ever fail, it is much cleaner to return a zero for the stat count. + +Fixes: a1292595e006 ("net: dsa: add new DSA switch driver for the SMSC-LAN9303") +Signed-off-by: Jerry Ray +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20221209153502.7429-1-jerry.ray@microchip.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/lan9303-core.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c +index 59a803e3c8d0..22547b10dfe5 100644 +--- a/drivers/net/dsa/lan9303-core.c ++++ b/drivers/net/dsa/lan9303-core.c +@@ -1003,9 +1003,11 @@ static void lan9303_get_ethtool_stats(struct dsa_switch *ds, int port, + ret = lan9303_read_switch_port( + chip, port, lan9303_mib[u].offset, ®); + +- if (ret) ++ if (ret) { + dev_warn(chip->dev, "Reading status port %d reg %u failed\n", + port, lan9303_mib[u].offset); ++ reg = 0; ++ } + data[u] = reg; + } + } +-- +2.35.1 + diff --git a/queue-5.15/net-macsec-fix-net-device-access-prior-to-holding-a-.patch b/queue-5.15/net-macsec-fix-net-device-access-prior-to-holding-a-.patch new file mode 100644 index 00000000000..6713aaf83a2 --- /dev/null +++ b/queue-5.15/net-macsec-fix-net-device-access-prior-to-holding-a-.patch @@ -0,0 +1,96 @@ +From db51e8aad479bee9c58e0a63de145d3990c0e53f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Dec 2022 09:55:32 +0200 +Subject: net: macsec: fix net device access prior to holding a lock + +From: Emeel Hakim + +[ Upstream commit f3b4a00f0f62da252c598310698dfc82ef2f2e2e ] + +Currently macsec offload selection update routine accesses +the net device prior to holding the relevant lock. +Fix by holding the lock prior to the device access. + +Fixes: dcb780fb2795 ("net: macsec: add nla support for changing the offloading selection") +Reviewed-by: Raed Salem +Signed-off-by: Emeel Hakim +Link: https://lore.kernel.org/r/20221211075532.28099-1-ehakim@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/macsec.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index 88e44eb39285..10b3f4fb2612 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -2580,7 +2580,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + const struct macsec_ops *ops; + struct macsec_context ctx; + struct macsec_dev *macsec; +- int ret; ++ int ret = 0; + + if (!attrs[MACSEC_ATTR_IFINDEX]) + return -EINVAL; +@@ -2593,28 +2593,36 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + macsec_genl_offload_policy, NULL)) + return -EINVAL; + ++ rtnl_lock(); ++ + dev = get_dev_from_nl(genl_info_net(info), attrs); +- if (IS_ERR(dev)) +- return PTR_ERR(dev); ++ if (IS_ERR(dev)) { ++ ret = PTR_ERR(dev); ++ goto out; ++ } + macsec = macsec_priv(dev); + +- if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) +- return -EINVAL; ++ if (!tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]) { ++ ret = -EINVAL; ++ goto out; ++ } + + offload = nla_get_u8(tb_offload[MACSEC_OFFLOAD_ATTR_TYPE]); + if (macsec->offload == offload) +- return 0; ++ goto out; + + /* Check if the offloading mode is supported by the underlying layers */ + if (offload != MACSEC_OFFLOAD_OFF && +- !macsec_check_offload(offload, macsec)) +- return -EOPNOTSUPP; ++ !macsec_check_offload(offload, macsec)) { ++ ret = -EOPNOTSUPP; ++ goto out; ++ } + + /* Check if the net device is busy. */ +- if (netif_running(dev)) +- return -EBUSY; +- +- rtnl_lock(); ++ if (netif_running(dev)) { ++ ret = -EBUSY; ++ goto out; ++ } + + prev_offload = macsec->offload; + macsec->offload = offload; +@@ -2649,7 +2657,7 @@ static int macsec_upd_offload(struct sk_buff *skb, struct genl_info *info) + + rollback: + macsec->offload = prev_offload; +- ++out: + rtnl_unlock(); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/net-proc-provide-proc_fs-n-fallback-for-proc_create_.patch b/queue-5.15/net-proc-provide-proc_fs-n-fallback-for-proc_create_.patch new file mode 100644 index 00000000000..e642bf0a1fd --- /dev/null +++ b/queue-5.15/net-proc-provide-proc_fs-n-fallback-for-proc_create_.patch @@ -0,0 +1,43 @@ +From 60ede655fa5b957a4f3ded40fd26dc6404303e9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Oct 2022 07:34:21 +0100 +Subject: net, proc: Provide PROC_FS=n fallback for + proc_create_net_single_write() + +From: David Howells + +[ Upstream commit c3d96f690a790074b508fe183a41e36a00cd7ddd ] + +Provide a CONFIG_PROC_FS=n fallback for proc_create_net_single_write(). + +Also provide a fallback for proc_create_net_data_write(). + +Fixes: 564def71765c ("proc: Add a way to make network proc files writable") +Reported-by: kernel test robot +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +cc: netdev@vger.kernel.org +Signed-off-by: Sasha Levin +--- + include/linux/proc_fs.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h +index 069c7fd95396..a2f25b26ae1e 100644 +--- a/include/linux/proc_fs.h ++++ b/include/linux/proc_fs.h +@@ -191,8 +191,10 @@ static inline void proc_remove(struct proc_dir_entry *de) {} + static inline int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) { return 0; } + + #define proc_create_net_data(name, mode, parent, ops, state_size, data) ({NULL;}) ++#define proc_create_net_data_write(name, mode, parent, ops, write, state_size, data) ({NULL;}) + #define proc_create_net(name, mode, parent, state_size, ops) ({NULL;}) + #define proc_create_net_single(name, mode, parent, show, data) ({NULL;}) ++#define proc_create_net_single_write(name, mode, parent, show, write, data) ({NULL;}) + + static inline struct pid *tgid_pidfd_to_pid(const struct file *file) + { +-- +2.35.1 + diff --git a/queue-5.15/net-stmmac-fix-possible-memory-leak-in-stmmac_dvr_pr.patch b/queue-5.15/net-stmmac-fix-possible-memory-leak-in-stmmac_dvr_pr.patch new file mode 100644 index 00000000000..984432f0bc5 --- /dev/null +++ b/queue-5.15/net-stmmac-fix-possible-memory-leak-in-stmmac_dvr_pr.patch @@ -0,0 +1,46 @@ +From 815bed9bb57564ac2f30b48ec6ac3e93a7546d20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 16:34:13 +0800 +Subject: net: stmmac: fix possible memory leak in stmmac_dvr_probe() + +From: Gaosheng Cui + +[ Upstream commit a137f3f27f9290933fe7e40e6dc8a445781c31a2 ] + +The bitmap_free() should be called to free priv->af_xdp_zc_qps +when create_singlethread_workqueue() fails, otherwise there will +be a memory leak, so we add the err path error_wq_init to fix it. + +Fixes: bba2556efad6 ("net: stmmac: Enable RX via AF_XDP zero-copy") +Signed-off-by: Gaosheng Cui +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index eba97adaf1fb..d987ca727a21 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -7046,7 +7046,7 @@ int stmmac_dvr_probe(struct device *device, + priv->wq = create_singlethread_workqueue("stmmac_wq"); + if (!priv->wq) { + dev_err(priv->device, "failed to create workqueue\n"); +- return -ENOMEM; ++ goto error_wq_init; + } + + INIT_WORK(&priv->service_task, stmmac_service_task); +@@ -7273,6 +7273,7 @@ int stmmac_dvr_probe(struct device *device, + stmmac_napi_del(ndev); + error_hw_init: + destroy_workqueue(priv->wq); ++error_wq_init: + bitmap_free(priv->af_xdp_zc_qps); + + return ret; +-- +2.35.1 + diff --git a/queue-5.15/net-stmmac-selftests-fix-potential-memleak-in-stmmac.patch b/queue-5.15/net-stmmac-selftests-fix-potential-memleak-in-stmmac.patch new file mode 100644 index 00000000000..b5c2a2839c7 --- /dev/null +++ b/queue-5.15/net-stmmac-selftests-fix-potential-memleak-in-stmmac.patch @@ -0,0 +1,50 @@ +From 6b855d8bb966bc231a89e3064c92d3d6693e3fe9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 16:31:59 +0800 +Subject: net: stmmac: selftests: fix potential memleak in + stmmac_test_arpoffload() + +From: Zhang Changzhong + +[ Upstream commit f150b63f3fa5fdd81e0dd6151e8850268e29438c ] + +The skb allocated by stmmac_test_get_arp_skb() hasn't been released in +some error handling case, which will lead to a memory leak. Fix this up +by adding kfree_skb() to release skb. + +Compile tested only. + +Fixes: 5e3fb0a6e2b3 ("net: stmmac: selftests: Implement the ARP Offload test") +Signed-off-by: Zhang Changzhong +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +index dd5c4ef92ef3..ea7200b7b647 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +@@ -1654,12 +1654,16 @@ static int stmmac_test_arpoffload(struct stmmac_priv *priv) + } + + ret = stmmac_set_arp_offload(priv, priv->hw, true, ip_addr); +- if (ret) ++ if (ret) { ++ kfree_skb(skb); + goto cleanup; ++ } + + ret = dev_set_promiscuity(priv->dev, 1); +- if (ret) ++ if (ret) { ++ kfree_skb(skb); + goto cleanup; ++ } + + ret = dev_direct_xmit(skb, 0); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/net-stream-purge-sk_error_queue-in-sk_stream_kill_qu.patch b/queue-5.15/net-stream-purge-sk_error_queue-in-sk_stream_kill_qu.patch new file mode 100644 index 00000000000..2a0ccebf158 --- /dev/null +++ b/queue-5.15/net-stream-purge-sk_error_queue-in-sk_stream_kill_qu.patch @@ -0,0 +1,69 @@ +From 066d3c2d38460b00b0f481c520a211f5bcd528ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Dec 2022 16:29:17 +0000 +Subject: net: stream: purge sk_error_queue in sk_stream_kill_queues() + +From: Eric Dumazet + +[ Upstream commit e0c8bccd40fc1c19e1d246c39bcf79e357e1ada3 ] + +Changheon Lee reported TCP socket leaks, with a nice repro. + +It seems we leak TCP sockets with the following sequence: + +1) SOF_TIMESTAMPING_TX_ACK is enabled on the socket. + + Each ACK will cook an skb put in error queue, from __skb_tstamp_tx(). + __skb_tstamp_tx() is using skb_clone(), unless + SOF_TIMESTAMPING_OPT_TSONLY was also requested. + +2) If the application is also using MSG_ZEROCOPY, then we put in the + error queue cloned skbs that had a struct ubuf_info attached to them. + + Whenever an struct ubuf_info is allocated, sock_zerocopy_alloc() + does a sock_hold(). + + As long as the cloned skbs are still in sk_error_queue, + socket refcount is kept elevated. + +3) Application closes the socket, while error queue is not empty. + +Since tcp_close() no longer purges the socket error queue, +we might end up with a TCP socket with at least one skb in +error queue keeping the socket alive forever. + +This bug can be (ab)used to consume all kernel memory +and freeze the host. + +We need to purge the error queue, with proper synchronization +against concurrent writers. + +Fixes: 24bcbe1cc69f ("net: stream: don't purge sk_error_queue in sk_stream_kill_queues()") +Reported-by: Changheon Lee +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/stream.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/net/core/stream.c b/net/core/stream.c +index a61130504827..d7c5413d16d5 100644 +--- a/net/core/stream.c ++++ b/net/core/stream.c +@@ -196,6 +196,12 @@ void sk_stream_kill_queues(struct sock *sk) + /* First the read buffer. */ + __skb_queue_purge(&sk->sk_receive_queue); + ++ /* Next, the error queue. ++ * We need to use queue lock, because other threads might ++ * add packets to the queue without socket lock being held. ++ */ ++ skb_queue_purge(&sk->sk_error_queue); ++ + /* Next, the write queue. */ + WARN_ON(!skb_queue_empty(&sk->sk_write_queue)); + +-- +2.35.1 + diff --git a/queue-5.15/net-tunnel-wait-until-all-sk_user_data-reader-finish.patch b/queue-5.15/net-tunnel-wait-until-all-sk_user_data-reader-finish.patch new file mode 100644 index 00000000000..da260ddea50 --- /dev/null +++ b/queue-5.15/net-tunnel-wait-until-all-sk_user_data-reader-finish.patch @@ -0,0 +1,75 @@ +From a309e38042212835372ef3fb183f2210f15c0580 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 20:04:52 +0800 +Subject: net/tunnel: wait until all sk_user_data reader finish before + releasing the sock + +From: Hangbin Liu + +[ Upstream commit 3cf7203ca620682165706f70a1b12b5194607dce ] + +There is a race condition in vxlan that when deleting a vxlan device +during receiving packets, there is a possibility that the sock is +released after getting vxlan_sock vs from sk_user_data. Then in +later vxlan_ecn_decapsulate(), vxlan_get_sk_family() we will got +NULL pointer dereference. e.g. + + #0 [ffffa25ec6978a38] machine_kexec at ffffffff8c669757 + #1 [ffffa25ec6978a90] __crash_kexec at ffffffff8c7c0a4d + #2 [ffffa25ec6978b58] crash_kexec at ffffffff8c7c1c48 + #3 [ffffa25ec6978b60] oops_end at ffffffff8c627f2b + #4 [ffffa25ec6978b80] page_fault_oops at ffffffff8c678fcb + #5 [ffffa25ec6978bd8] exc_page_fault at ffffffff8d109542 + #6 [ffffa25ec6978c00] asm_exc_page_fault at ffffffff8d200b62 + [exception RIP: vxlan_ecn_decapsulate+0x3b] + RIP: ffffffffc1014e7b RSP: ffffa25ec6978cb0 RFLAGS: 00010246 + RAX: 0000000000000008 RBX: ffff8aa000888000 RCX: 0000000000000000 + RDX: 000000000000000e RSI: ffff8a9fc7ab803e RDI: ffff8a9fd1168700 + RBP: ffff8a9fc7ab803e R8: 0000000000700000 R9: 00000000000010ae + R10: ffff8a9fcb748980 R11: 0000000000000000 R12: ffff8a9fd1168700 + R13: ffff8aa000888000 R14: 00000000002a0000 R15: 00000000000010ae + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + #7 [ffffa25ec6978ce8] vxlan_rcv at ffffffffc10189cd [vxlan] + #8 [ffffa25ec6978d90] udp_queue_rcv_one_skb at ffffffff8cfb6507 + #9 [ffffa25ec6978dc0] udp_unicast_rcv_skb at ffffffff8cfb6e45 + #10 [ffffa25ec6978dc8] __udp4_lib_rcv at ffffffff8cfb8807 + #11 [ffffa25ec6978e20] ip_protocol_deliver_rcu at ffffffff8cf76951 + #12 [ffffa25ec6978e48] ip_local_deliver at ffffffff8cf76bde + #13 [ffffa25ec6978ea0] __netif_receive_skb_one_core at ffffffff8cecde9b + #14 [ffffa25ec6978ec8] process_backlog at ffffffff8cece139 + #15 [ffffa25ec6978f00] __napi_poll at ffffffff8ceced1a + #16 [ffffa25ec6978f28] net_rx_action at ffffffff8cecf1f3 + #17 [ffffa25ec6978fa0] __softirqentry_text_start at ffffffff8d4000ca + #18 [ffffa25ec6978ff0] do_softirq at ffffffff8c6fbdc3 + +Reproducer: https://github.com/Mellanox/ovs-tests/blob/master/test-ovs-vxlan-remove-tunnel-during-traffic.sh + +Fix this by waiting for all sk_user_data reader to finish before +releasing the sock. + +Reported-by: Jianlin Shi +Suggested-by: Jakub Sitnicki +Fixes: 6a93cc905274 ("udp-tunnel: Add a few more UDP tunnel APIs") +Signed-off-by: Hangbin Liu +Reviewed-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/udp_tunnel_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c +index 46101fd67a47..1ff5b8e30bb9 100644 +--- a/net/ipv4/udp_tunnel_core.c ++++ b/net/ipv4/udp_tunnel_core.c +@@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); + void udp_tunnel_sock_release(struct socket *sock) + { + rcu_assign_sk_user_data(sock->sk, NULL); ++ synchronize_rcu(); + kernel_sock_shutdown(sock, SHUT_RDWR); + sock_release(sock); + } +-- +2.35.1 + diff --git a/queue-5.15/net-vmw_vsock-vmci-check-memcpy_from_msg.patch b/queue-5.15/net-vmw_vsock-vmci-check-memcpy_from_msg.patch new file mode 100644 index 00000000000..382f6da382a --- /dev/null +++ b/queue-5.15/net-vmw_vsock-vmci-check-memcpy_from_msg.patch @@ -0,0 +1,47 @@ +From 7cc8088611a406cd7f74088b6a20169a74dfccda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 09:58:34 +0300 +Subject: net: vmw_vsock: vmci: Check memcpy_from_msg() + +From: Artem Chernyshev + +[ Upstream commit 44aa5a6dba8283bfda28b1517af4de711c5652a4 ] + +vmci_transport_dgram_enqueue() does not check the return value +of memcpy_from_msg(). If memcpy_from_msg() fails, it is possible that +uninitialized memory contents are sent unintentionally instead of user's +message in the datagram to the destination. Return with an error if +memcpy_from_msg() fails. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 0f7db23a07af ("vmci_transport: switch ->enqeue_dgram, ->enqueue_stream and ->dequeue_stream to msghdr") +Signed-off-by: Artem Chernyshev +Reviewed-by: Stefano Garzarella +Reviewed-by: Vishnu Dasa +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/vmw_vsock/vmci_transport.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c +index b17dc9745188..94c1112f1c8c 100644 +--- a/net/vmw_vsock/vmci_transport.c ++++ b/net/vmw_vsock/vmci_transport.c +@@ -1711,7 +1711,11 @@ static int vmci_transport_dgram_enqueue( + if (!dg) + return -ENOMEM; + +- memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); ++ err = memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); ++ if (err) { ++ kfree(dg); ++ return err; ++ } + + dg->dst = vmci_make_handle(remote_addr->svm_cid, + remote_addr->svm_port); +-- +2.35.1 + diff --git a/queue-5.15/net_sched-reject-tcf_em_simple-case-for-complex-emat.patch b/queue-5.15/net_sched-reject-tcf_em_simple-case-for-complex-emat.patch new file mode 100644 index 00000000000..4086c21181e --- /dev/null +++ b/queue-5.15/net_sched-reject-tcf_em_simple-case-for-complex-emat.patch @@ -0,0 +1,52 @@ +From 0f2868252fe42aedc8801a7340ee21a21861a18d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Dec 2022 14:17:07 -0800 +Subject: net_sched: reject TCF_EM_SIMPLE case for complex ematch module + +From: Cong Wang + +[ Upstream commit 9cd3fd2054c3b3055163accbf2f31a4426f10317 ] + +When TCF_EM_SIMPLE was introduced, it is supposed to be convenient +for ematch implementation: + +https://lore.kernel.org/all/20050105110048.GO26856@postel.suug.ch/ + +"You don't have to, providing a 32bit data chunk without TCF_EM_SIMPLE +set will simply result in allocating & copy. It's an optimization, +nothing more." + +So if an ematch module provides ops->datalen that means it wants a +complex data structure (saved in its em->data) instead of a simple u32 +value. We should simply reject such a combination, otherwise this u32 +could be misinterpreted as a pointer. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-and-tested-by: syzbot+4caeae4c7103813598ae@syzkaller.appspotmail.com +Reported-by: Jun Nie +Cc: Jamal Hadi Salim +Cc: Paolo Abeni +Signed-off-by: Cong Wang +Acked-by: Paolo Abeni +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sched/ematch.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/sched/ematch.c b/net/sched/ematch.c +index 4ce681361851..5c1235e6076a 100644 +--- a/net/sched/ematch.c ++++ b/net/sched/ematch.c +@@ -255,6 +255,8 @@ static int tcf_em_validate(struct tcf_proto *tp, + * the value carried. + */ + if (em_hdr->flags & TCF_EM_SIMPLE) { ++ if (em->ops->datalen > 0) ++ goto errout; + if (data_len < sizeof(u32)) + goto errout; + em->data = *(u32 *) data; +-- +2.35.1 + diff --git a/queue-5.15/netfilter-conntrack-set-icmpv6-redirects-as-related.patch b/queue-5.15/netfilter-conntrack-set-icmpv6-redirects-as-related.patch new file mode 100644 index 00000000000..a953095b15e --- /dev/null +++ b/queue-5.15/netfilter-conntrack-set-icmpv6-redirects-as-related.patch @@ -0,0 +1,173 @@ +From 634ec270dc24e5d87ca6562e910e8286f87e1872 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 16:00:09 +0100 +Subject: netfilter: conntrack: set icmpv6 redirects as RELATED + +From: Florian Westphal + +[ Upstream commit 7d7cfb48d81353e826493d24c7cec7360950968f ] + +icmp conntrack will set icmp redirects as RELATED, but icmpv6 will not +do this. + +For icmpv6, only icmp errors (code <= 128) are examined for RELATED state. +ICMPV6 Redirects are part of neighbour discovery mechanism, those are +handled by marking a selected subset (e.g. neighbour solicitations) as +UNTRACKED, but not REDIRECT -- they will thus be flagged as INVALID. + +Add minimal support for REDIRECTs. No parsing of neighbour options is +added for simplicity, so this will only check that we have the embeeded +original header (ND_OPT_REDIRECT_HDR), and then attempt to do a flow +lookup for this tuple. + +Also extend the existing test case to cover redirects. + +Fixes: 9fb9cbb1082d ("[NETFILTER]: Add nf_conntrack subsystem.") +Reported-by: Eric Garver +Link: https://github.com/firewalld/firewalld/issues/1046 +Signed-off-by: Florian Westphal +Acked-by: Eric Garver +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_proto_icmpv6.c | 53 +++++++++++++++++++ + .../netfilter/conntrack_icmp_related.sh | 36 ++++++++++++- + 2 files changed, 87 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_proto_icmpv6.c b/net/netfilter/nf_conntrack_proto_icmpv6.c +index 61e3b05cf02c..1020d67600a9 100644 +--- a/net/netfilter/nf_conntrack_proto_icmpv6.c ++++ b/net/netfilter/nf_conntrack_proto_icmpv6.c +@@ -129,6 +129,56 @@ static void icmpv6_error_log(const struct sk_buff *skb, + nf_l4proto_log_invalid(skb, state, IPPROTO_ICMPV6, "%s", msg); + } + ++static noinline_for_stack int ++nf_conntrack_icmpv6_redirect(struct nf_conn *tmpl, struct sk_buff *skb, ++ unsigned int dataoff, ++ const struct nf_hook_state *state) ++{ ++ u8 hl = ipv6_hdr(skb)->hop_limit; ++ union nf_inet_addr outer_daddr; ++ union { ++ struct nd_opt_hdr nd_opt; ++ struct rd_msg rd_msg; ++ } tmp; ++ const struct nd_opt_hdr *nd_opt; ++ const struct rd_msg *rd_msg; ++ ++ rd_msg = skb_header_pointer(skb, dataoff, sizeof(*rd_msg), &tmp.rd_msg); ++ if (!rd_msg) { ++ icmpv6_error_log(skb, state, "short redirect"); ++ return -NF_ACCEPT; ++ } ++ ++ if (rd_msg->icmph.icmp6_code != 0) ++ return NF_ACCEPT; ++ ++ if (hl != 255 || !(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { ++ icmpv6_error_log(skb, state, "invalid saddr or hoplimit for redirect"); ++ return -NF_ACCEPT; ++ } ++ ++ dataoff += sizeof(*rd_msg); ++ ++ /* warning: rd_msg no longer usable after this call */ ++ nd_opt = skb_header_pointer(skb, dataoff, sizeof(*nd_opt), &tmp.nd_opt); ++ if (!nd_opt || nd_opt->nd_opt_len == 0) { ++ icmpv6_error_log(skb, state, "redirect without options"); ++ return -NF_ACCEPT; ++ } ++ ++ /* We could call ndisc_parse_options(), but it would need ++ * skb_linearize() and a bit more work. ++ */ ++ if (nd_opt->nd_opt_type != ND_OPT_REDIRECT_HDR) ++ return NF_ACCEPT; ++ ++ memcpy(&outer_daddr.ip6, &ipv6_hdr(skb)->daddr, ++ sizeof(outer_daddr.ip6)); ++ dataoff += 8; ++ return nf_conntrack_inet_error(tmpl, skb, dataoff, state, ++ IPPROTO_ICMPV6, &outer_daddr); ++} ++ + int nf_conntrack_icmpv6_error(struct nf_conn *tmpl, + struct sk_buff *skb, + unsigned int dataoff, +@@ -159,6 +209,9 @@ int nf_conntrack_icmpv6_error(struct nf_conn *tmpl, + return NF_ACCEPT; + } + ++ if (icmp6h->icmp6_type == NDISC_REDIRECT) ++ return nf_conntrack_icmpv6_redirect(tmpl, skb, dataoff, state); ++ + /* is not error message ? */ + if (icmp6h->icmp6_type >= 128) + return NF_ACCEPT; +diff --git a/tools/testing/selftests/netfilter/conntrack_icmp_related.sh b/tools/testing/selftests/netfilter/conntrack_icmp_related.sh +index b48e1833bc89..76645aaf2b58 100755 +--- a/tools/testing/selftests/netfilter/conntrack_icmp_related.sh ++++ b/tools/testing/selftests/netfilter/conntrack_icmp_related.sh +@@ -35,6 +35,8 @@ cleanup() { + for i in 1 2;do ip netns del nsrouter$i;done + } + ++trap cleanup EXIT ++ + ipv4() { + echo -n 192.168.$1.2 + } +@@ -146,11 +148,17 @@ ip netns exec nsclient1 nft -f - < /dev/null ++ ++expect="packets 1 bytes 112" ++check_counter nsclient1 "redir4" "$expect" ++if [ $? -ne 0 ];then ++ ret=1 ++fi ++ ++ip netns exec "nsclient1" ping -c 1 dead:1::42 > /dev/null ++expect="packets 1 bytes 192" ++check_counter nsclient1 "redir6" "$expect" ++if [ $? -ne 0 ];then ++ ret=1 ++fi ++ ++if [ $ret -eq 0 ];then ++ echo "PASS: icmp redirects had RELATED state" ++else ++ echo "ERROR: icmp redirect RELATED state test has failed" ++fi ++ + exit $ret +-- +2.35.1 + diff --git a/queue-5.15/netfilter-flowtable-really-fix-nat-ipv6-offload.patch b/queue-5.15/netfilter-flowtable-really-fix-nat-ipv6-offload.patch new file mode 100644 index 00000000000..21145ce8c81 --- /dev/null +++ b/queue-5.15/netfilter-flowtable-really-fix-nat-ipv6-offload.patch @@ -0,0 +1,50 @@ +From 72f22fde1220f14a4426c0a55117189f88b02bc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 20:35:29 +0800 +Subject: netfilter: flowtable: really fix NAT IPv6 offload + +From: Qingfang DENG + +[ Upstream commit 5fb45f95eec682621748b7cb012c6a8f0f981e6a ] + +The for-loop was broken from the start. It translates to: + + for (i = 0; i < 4; i += 4) + +which means the loop statement is run only once, so only the highest +32-bit of the IPv6 address gets mangled. + +Fix the loop increment. + +Fixes: 0e07e25b481a ("netfilter: flowtable: fix NAT IPv6 offload mangling") +Fixes: 5c27d8d76ce8 ("netfilter: nf_flow_table_offload: add IPv6 support") +Signed-off-by: Qingfang DENG +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_flow_table_offload.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c +index 66c9a6c2b9cf..336f282a221f 100644 +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -372,12 +372,12 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, + const __be32 *addr, const __be32 *mask) + { + struct flow_action_entry *entry; +- int i, j; ++ int i; + +- for (i = 0, j = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32), j++) { ++ for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i++) { + entry = flow_action_entry_next(flow_rule); + flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6, +- offset + i, &addr[j], mask); ++ offset + i * sizeof(u32), &addr[i], mask); + } + } + +-- +2.35.1 + diff --git a/queue-5.15/nfc-pn533-clear-nfc_target-before-being-used.patch b/queue-5.15/nfc-pn533-clear-nfc_target-before-being-used.patch new file mode 100644 index 00000000000..9c3a9b94b17 --- /dev/null +++ b/queue-5.15/nfc-pn533-clear-nfc_target-before-being-used.patch @@ -0,0 +1,73 @@ +From c16da813f5e3ee27753c9784eb25fc354ae6fe23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Dec 2022 10:51:39 +0900 +Subject: nfc: pn533: Clear nfc_target before being used + +From: Minsuk Kang + +[ Upstream commit 9f28157778ede0d4f183f7ab3b46995bb400abbe ] + +Fix a slab-out-of-bounds read that occurs in nla_put() called from +nfc_genl_send_target() when target->sensb_res_len, which is duplicated +from an nfc_target in pn533, is too large as the nfc_target is not +properly initialized and retains garbage values. Clear nfc_targets with +memset() before they are used. + +Found by a modified version of syzkaller. + +BUG: KASAN: slab-out-of-bounds in nla_put +Call Trace: + memcpy + nla_put + nfc_genl_dump_targets + genl_lock_dumpit + netlink_dump + __netlink_dump_start + genl_family_rcv_msg_dumpit + genl_rcv_msg + netlink_rcv_skb + genl_rcv + netlink_unicast + netlink_sendmsg + sock_sendmsg + ____sys_sendmsg + ___sys_sendmsg + __sys_sendmsg + do_syscall_64 + +Fixes: 673088fb42d0 ("NFC: pn533: Send ATR_REQ directly for active device detection") +Fixes: 361f3cb7f9cf ("NFC: DEP link hook implementation for pn533") +Signed-off-by: Minsuk Kang +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20221214015139.119673-1-linuxlovemin@yonsei.ac.kr +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/nfc/pn533/pn533.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c +index 6dc0af63440f..939d27652a4c 100644 +--- a/drivers/nfc/pn533/pn533.c ++++ b/drivers/nfc/pn533/pn533.c +@@ -1297,6 +1297,8 @@ static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, + if (IS_ERR(resp)) + return PTR_ERR(resp); + ++ memset(&nfc_target, 0, sizeof(struct nfc_target)); ++ + rsp = (struct pn533_cmd_jump_dep_response *)resp->data; + + rc = rsp->status & PN533_CMD_RET_MASK; +@@ -1928,6 +1930,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, + + dev_dbg(dev->dev, "Creating new target\n"); + ++ memset(&nfc_target, 0, sizeof(struct nfc_target)); ++ + nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; + nfc_target.nfcid1_len = 10; + memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); +-- +2.35.1 + diff --git a/queue-5.15/nfs-fix-an-oops-in-nfs_d_automount.patch b/queue-5.15/nfs-fix-an-oops-in-nfs_d_automount.patch new file mode 100644 index 00000000000..f2f03316214 --- /dev/null +++ b/queue-5.15/nfs-fix-an-oops-in-nfs_d_automount.patch @@ -0,0 +1,36 @@ +From d4cf9ee6097c6659bab7886e32ff3cc6da1f4b32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 17:30:39 -0500 +Subject: NFS: Fix an Oops in nfs_d_automount() + +From: Trond Myklebust + +[ Upstream commit 35e3b6ae84935d0d7ff76cbdaa83411b0ad5e471 ] + +When mounting from a NFSv4 referral, path->dentry can end up being a +negative dentry, so derive the struct nfs_server from the dentry +itself instead. + +Fixes: 2b0143b5c986 ("VFS: normal filesystems (and lustre): d_inode() annotations") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/namespace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c +index bc0c698f3350..565421c6682e 100644 +--- a/fs/nfs/namespace.c ++++ b/fs/nfs/namespace.c +@@ -147,7 +147,7 @@ struct vfsmount *nfs_d_automount(struct path *path) + struct nfs_fs_context *ctx; + struct fs_context *fc; + struct vfsmount *mnt = ERR_PTR(-ENOMEM); +- struct nfs_server *server = NFS_SERVER(d_inode(path->dentry)); ++ struct nfs_server *server = NFS_SB(path->dentry->d_sb); + struct nfs_client *client = server->nfs_client; + int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout); + int ret; +-- +2.35.1 + diff --git a/queue-5.15/nfsd-don-t-call-nfsd_file_put-from-client-states-seq.patch b/queue-5.15/nfsd-don-t-call-nfsd_file_put-from-client-states-seq.patch new file mode 100644 index 00000000000..86d141a9970 --- /dev/null +++ b/queue-5.15/nfsd-don-t-call-nfsd_file_put-from-client-states-seq.patch @@ -0,0 +1,147 @@ +From cba3422f0eaaa33a311b18c01c38dfc25cace482 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 08:13:53 -0400 +Subject: nfsd: don't call nfsd_file_put from client states seqfile display + +From: Jeff Layton + +[ Upstream commit e0aa651068bfd520afcd357af8ecd2de005fc83d ] + +We had a report of this: + + BUG: sleeping function called from invalid context at fs/nfsd/filecache.c:440 + +...with a stack trace showing nfsd_file_put being called from +nfs4_show_open. This code has always tried to call fput while holding a +spinlock, but we recently changed this to use the filecache, and that +started triggering the might_sleep() in nfsd_file_put. + +states_start takes and holds the cl_lock while iterating over the +client's states, and we can't sleep with that held. + +Have the various nfs4_show_* functions instead hold the fi_lock instead +of taking a nfsd_file reference. + +Fixes: 78599c42ae3c ("nfsd4: add file to display list of client's opens") +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2138357 +Reported-by: Zhi Li +Signed-off-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4state.c | 51 +++++++++++++++++++++++++++++---------------- + 1 file changed, 33 insertions(+), 18 deletions(-) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 7b763f146b62..c062728034ad 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -627,15 +627,26 @@ find_any_file(struct nfs4_file *f) + return ret; + } + +-static struct nfsd_file *find_deleg_file(struct nfs4_file *f) ++static struct nfsd_file *find_any_file_locked(struct nfs4_file *f) + { +- struct nfsd_file *ret = NULL; ++ lockdep_assert_held(&f->fi_lock); ++ ++ if (f->fi_fds[O_RDWR]) ++ return f->fi_fds[O_RDWR]; ++ if (f->fi_fds[O_WRONLY]) ++ return f->fi_fds[O_WRONLY]; ++ if (f->fi_fds[O_RDONLY]) ++ return f->fi_fds[O_RDONLY]; ++ return NULL; ++} ++ ++static struct nfsd_file *find_deleg_file_locked(struct nfs4_file *f) ++{ ++ lockdep_assert_held(&f->fi_lock); + +- spin_lock(&f->fi_lock); + if (f->fi_deleg_file) +- ret = nfsd_file_get(f->fi_deleg_file); +- spin_unlock(&f->fi_lock); +- return ret; ++ return f->fi_deleg_file; ++ return NULL; + } + + static atomic_long_t num_delegations; +@@ -2501,9 +2512,11 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) + ols = openlockstateid(st); + oo = ols->st_stateowner; + nf = st->sc_file; +- file = find_any_file(nf); ++ ++ spin_lock(&nf->fi_lock); ++ file = find_any_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2525,8 +2538,8 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_owner(s, oo); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +@@ -2540,9 +2553,10 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) + ols = openlockstateid(st); + oo = ols->st_stateowner; + nf = st->sc_file; +- file = find_any_file(nf); ++ spin_lock(&nf->fi_lock); ++ file = find_any_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2562,8 +2576,8 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_owner(s, oo); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +@@ -2575,9 +2589,10 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) + + ds = delegstateid(st); + nf = st->sc_file; +- file = find_deleg_file(nf); ++ spin_lock(&nf->fi_lock); ++ file = find_deleg_file_locked(nf); + if (!file) +- return 0; ++ goto out; + + seq_printf(s, "- "); + nfs4_show_stateid(s, &st->sc_stateid); +@@ -2593,8 +2608,8 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) + seq_printf(s, ", "); + nfs4_show_fname(s, file); + seq_printf(s, " }\n"); +- nfsd_file_put(file); +- ++out: ++ spin_unlock(&nf->fi_lock); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/nfsd-finish-converting-the-nfsv2-getacl-result-encod.patch b/queue-5.15/nfsd-finish-converting-the-nfsv2-getacl-result-encod.patch new file mode 100644 index 00000000000..c3b3dcfc827 --- /dev/null +++ b/queue-5.15/nfsd-finish-converting-the-nfsv2-getacl-result-encod.patch @@ -0,0 +1,56 @@ +From 0a93a3d3996840bc52a29b10fa0b2bc783636fda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 16 Oct 2022 11:47:02 -0400 +Subject: NFSD: Finish converting the NFSv2 GETACL result encoder + +From: Chuck Lever + +[ Upstream commit ea5021e911d3479346a75ac9b7d9dcd751b0fb99 ] + +The xdr_stream conversion inadvertently left some code that set the +page_len of the send buffer. The XDR stream encoders should handle +this automatically now. + +This oversight adds garbage past the end of the Reply message. +Clients typically ignore the garbage, but NFSD does not need to send +it, as it leaks stale memory contents onto the wire. + +Fixes: f8cba47344f7 ("NFSD: Update the NFSv2 GETACL result encoder to use struct xdr_stream") +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs2acl.c | 10 ---------- + 1 file changed, 10 deletions(-) + +diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c +index ec7776b0e868..30a1782a03f0 100644 +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -246,7 +246,6 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) + struct nfsd3_getaclres *resp = rqstp->rq_resp; + struct dentry *dentry = resp->fh.fh_dentry; + struct inode *inode; +- int w; + + if (!svcxdr_encode_stat(xdr, resp->status)) + return false; +@@ -260,15 +259,6 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) + if (xdr_stream_encode_u32(xdr, resp->mask) < 0) + return false; + +- rqstp->rq_res.page_len = w = nfsacl_size( +- (resp->mask & NFS_ACL) ? resp->acl_access : NULL, +- (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); +- while (w > 0) { +- if (!*(rqstp->rq_next_page++)) +- return true; +- w -= PAGE_SIZE; +- } +- + if (!nfs_stream_encode_acl(xdr, inode, resp->acl_access, + resp->mask & NFS_ACL, 0)) + return false; +-- +2.35.1 + diff --git a/queue-5.15/nfsd-under-nfsv4.1-fix-double-svc_xprt_put-on-rpc_cr.patch b/queue-5.15/nfsd-under-nfsv4.1-fix-double-svc_xprt_put-on-rpc_cr.patch new file mode 100644 index 00000000000..ba04d8af935 --- /dev/null +++ b/queue-5.15/nfsd-under-nfsv4.1-fix-double-svc_xprt_put-on-rpc_cr.patch @@ -0,0 +1,87 @@ +From b3abfaa08bf0ec8117343d828f244da0a5776401 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 13:11:06 +0200 +Subject: nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure + +From: Dan Aloni + +[ Upstream commit 3bc8edc98bd43540dbe648e4ef91f443d6d20a24 ] + +On error situation `clp->cl_cb_conn.cb_xprt` should not be given +a reference to the xprt otherwise both client cleanup and the +error handling path of the caller call to put it. Better to +delay handing over the reference to a later branch. + +[ 72.530665] refcount_t: underflow; use-after-free. +[ 72.531933] WARNING: CPU: 0 PID: 173 at lib/refcount.c:28 refcount_warn_saturate+0xcf/0x120 +[ 72.533075] Modules linked in: nfsd(OE) nfsv4(OE) nfsv3(OE) nfs(OE) lockd(OE) compat_nfs_ssc(OE) nfs_acl(OE) rpcsec_gss_krb5(OE) auth_rpcgss(OE) rpcrdma(OE) dns_resolver fscache netfs grace rdma_cm iw_cm ib_cm sunrpc(OE) mlx5_ib mlx5_core mlxfw pci_hyperv_intf ib_uverbs ib_core xt_MASQUERADE nf_conntrack_netlink nft_counter xt_addrtype nft_compat br_netfilter bridge stp llc nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set overlay nf_tables nfnetlink crct10dif_pclmul crc32_pclmul ghash_clmulni_intel xfs serio_raw virtio_net virtio_blk net_failover failover fuse [last unloaded: sunrpc] +[ 72.540389] CPU: 0 PID: 173 Comm: kworker/u16:5 Tainted: G OE 5.15.82-dan #1 +[ 72.541511] Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.16.0-3.module+el8.7.0+1084+97b81f61 04/01/2014 +[ 72.542717] Workqueue: nfsd4_callbacks nfsd4_run_cb_work [nfsd] +[ 72.543575] RIP: 0010:refcount_warn_saturate+0xcf/0x120 +[ 72.544299] Code: 55 00 0f 0b 5d e9 01 50 98 00 80 3d 75 9e 39 08 00 0f 85 74 ff ff ff 48 c7 c7 e8 d1 60 8e c6 05 61 9e 39 08 01 e8 f6 51 55 00 <0f> 0b 5d e9 d9 4f 98 00 80 3d 4b 9e 39 08 00 0f 85 4c ff ff ff 48 +[ 72.546666] RSP: 0018:ffffb3f841157cf0 EFLAGS: 00010286 +[ 72.547393] RAX: 0000000000000026 RBX: ffff89ac6231d478 RCX: 0000000000000000 +[ 72.548324] RDX: ffff89adb7c2c2c0 RSI: ffff89adb7c205c0 RDI: ffff89adb7c205c0 +[ 72.549271] RBP: ffffb3f841157cf0 R08: 0000000000000000 R09: c0000000ffefffff +[ 72.550209] R10: 0000000000000001 R11: ffffb3f841157ad0 R12: ffff89ac6231d180 +[ 72.551142] R13: ffff89ac6231d478 R14: ffff89ac40c06180 R15: ffff89ac6231d4b0 +[ 72.552089] FS: 0000000000000000(0000) GS:ffff89adb7c00000(0000) knlGS:0000000000000000 +[ 72.553175] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 72.553934] CR2: 0000563a310506a8 CR3: 0000000109a66000 CR4: 0000000000350ef0 +[ 72.554874] Call Trace: +[ 72.555278] +[ 72.555614] svc_xprt_put+0xaf/0xe0 [sunrpc] +[ 72.556276] nfsd4_process_cb_update.isra.11+0xb7/0x410 [nfsd] +[ 72.557087] ? update_load_avg+0x82/0x610 +[ 72.557652] ? cpuacct_charge+0x60/0x70 +[ 72.558212] ? dequeue_entity+0xdb/0x3e0 +[ 72.558765] ? queued_spin_unlock+0x9/0x20 +[ 72.559358] nfsd4_run_cb_work+0xfc/0x270 [nfsd] +[ 72.560031] process_one_work+0x1df/0x390 +[ 72.560600] worker_thread+0x37/0x3b0 +[ 72.561644] ? process_one_work+0x390/0x390 +[ 72.562247] kthread+0x12f/0x150 +[ 72.562710] ? set_kthread_struct+0x50/0x50 +[ 72.563309] ret_from_fork+0x22/0x30 +[ 72.563818] +[ 72.564189] ---[ end trace 031117b1c72ec616 ]--- +[ 72.566019] list_add corruption. next->prev should be prev (ffff89ac4977e538), but was ffff89ac4763e018. (next=ffff89ac4763e018). +[ 72.567647] ------------[ cut here ]------------ + +Fixes: a4abc6b12eb1 ("nfsd: Fix svc_xprt refcnt leak when setup callback client failed") +Cc: Xiyu Yang +Cc: J. Bruce Fields +Signed-off-by: Dan Aloni +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4callback.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index 0f8b10f363e7..2e0040d3bca7 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -917,7 +917,6 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + } else { + if (!conn->cb_xprt) + return -EINVAL; +- clp->cl_cb_conn.cb_xprt = conn->cb_xprt; + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; + args.prognumber = clp->cl_cb_session->se_cb_prog; +@@ -937,6 +936,9 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + rpc_shutdown_client(client); + return -ENOMEM; + } ++ ++ if (clp->cl_minorversion != 0) ++ clp->cl_cb_conn.cb_xprt = conn->cb_xprt; + clp->cl_cb_client = client; + clp->cl_cb_cred = cred; + rcu_read_lock(); +-- +2.35.1 + diff --git a/queue-5.15/nfsv4-fix-a-credential-leak-in-_nfs4_discover_trunki.patch b/queue-5.15/nfsv4-fix-a-credential-leak-in-_nfs4_discover_trunki.patch new file mode 100644 index 00000000000..031ddda48b9 --- /dev/null +++ b/queue-5.15/nfsv4-fix-a-credential-leak-in-_nfs4_discover_trunki.patch @@ -0,0 +1,41 @@ +From c7208f984850c4f1901a9623613334aa91aa78bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 16:50:12 -0400 +Subject: NFSv4: Fix a credential leak in _nfs4_discover_trunking() + +From: Trond Myklebust + +[ Upstream commit e83458fce080dc23c25353a1af90bfecf79c7369 ] + +Fixes: 4f40a5b55446 ("NFSv4: Add an fattr allocation to _nfs4_discover_trunking()") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index dcc0677d1546..3c9ed63710a9 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -3987,7 +3987,7 @@ static int _nfs4_discover_trunking(struct nfs_server *server, + + page = alloc_page(GFP_KERNEL); + if (!page) +- return -ENOMEM; ++ goto out_put_cred; + locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); + if (!locations) + goto out_free; +@@ -4003,6 +4003,8 @@ static int _nfs4_discover_trunking(struct nfs_server *server, + kfree(locations); + out_free: + __free_page(page); ++out_put_cred: ++ put_cred(cred); + return status; + } + +-- +2.35.1 + diff --git a/queue-5.15/nfsv4-fix-a-deadlock-between-nfs4_open_recover_helpe.patch b/queue-5.15/nfsv4-fix-a-deadlock-between-nfs4_open_recover_helpe.patch new file mode 100644 index 00000000000..84ea240150b --- /dev/null +++ b/queue-5.15/nfsv4-fix-a-deadlock-between-nfs4_open_recover_helpe.patch @@ -0,0 +1,73 @@ +From d1fef794331dc6ee46d04a94e32e94c02bebbb3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 13:20:01 -0400 +Subject: NFSv4: Fix a deadlock between nfs4_open_recover_helper() and + delegreturn + +From: Trond Myklebust + +[ Upstream commit 51069e4aef6257b0454057359faed0ab0c9af083 ] + +If we're asked to recover open state while a delegation return is +outstanding, then the state manager thread cannot use a cached open, so +if the server returns a delegation, we can end up deadlocked behind the +pending delegreturn. +To avoid this problem, let's just ask the server not to give us a +delegation unless we're explicitly reclaiming one. + +Fixes: be36e185bd26 ("NFSv4: nfs4_open_recover_helper() must set share access") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index 3c9ed63710a9..b6b1fad031c7 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -2144,18 +2144,18 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context + } + + static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, +- fmode_t fmode) ++ fmode_t fmode) + { + struct nfs4_state *newstate; ++ struct nfs_server *server = NFS_SB(opendata->dentry->d_sb); ++ int openflags = opendata->o_arg.open_flags; + int ret; + + if (!nfs4_mode_match_open_stateid(opendata->state, fmode)) + return 0; +- opendata->o_arg.open_flags = 0; + opendata->o_arg.fmode = fmode; +- opendata->o_arg.share_access = nfs4_map_atomic_open_share( +- NFS_SB(opendata->dentry->d_sb), +- fmode, 0); ++ opendata->o_arg.share_access = ++ nfs4_map_atomic_open_share(server, fmode, openflags); + memset(&opendata->o_res, 0, sizeof(opendata->o_res)); + memset(&opendata->c_res, 0, sizeof(opendata->c_res)); + nfs4_init_opendata_res(opendata); +@@ -2735,10 +2735,15 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s + struct nfs4_opendata *opendata; + int ret; + +- opendata = nfs4_open_recoverdata_alloc(ctx, state, +- NFS4_OPEN_CLAIM_FH); ++ opendata = nfs4_open_recoverdata_alloc(ctx, state, NFS4_OPEN_CLAIM_FH); + if (IS_ERR(opendata)) + return PTR_ERR(opendata); ++ /* ++ * We're not recovering a delegation, so ask for no delegation. ++ * Otherwise the recovery thread could deadlock with an outstanding ++ * delegation return. ++ */ ++ opendata->o_arg.open_flags = O_DIRECT; + ret = nfs4_open_recover(opendata, state); + if (ret == -ESTALE) + d_drop(ctx->dentry); +-- +2.35.1 + diff --git a/queue-5.15/nfsv4.2-clear-fattr4_word2_security_label-when-done-.patch b/queue-5.15/nfsv4.2-clear-fattr4_word2_security_label-when-done-.patch new file mode 100644 index 00000000000..499ee39f183 --- /dev/null +++ b/queue-5.15/nfsv4.2-clear-fattr4_word2_security_label-when-done-.patch @@ -0,0 +1,42 @@ +From 705c051d7edac03c332652bbb8d2292c164eb418 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 16:44:47 -0400 +Subject: NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding + +From: Trond Myklebust + +[ Upstream commit eef7314caf2d73a94b68ba293cd105154d3a664e ] + +We need to clear the FATTR4_WORD2_SECURITY_LABEL bitmap flag +irrespective of whether or not the label is too long. + +Fixes: aa9c2669626c ("NFS: Client implementation of Labeled-NFS") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4xdr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 046788afb6d9..9d19b801cb39 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4179,6 +4179,7 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + return -EIO; ++ bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + if (len < NFS4_MAXLABELLEN) { + if (label) { + if (label->len) { +@@ -4191,7 +4192,6 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, + label->lfs = lfs; + status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; + } +- bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + } else + printk(KERN_WARNING "%s: label too long (%u)!\n", + __func__, len); +-- +2.35.1 + diff --git a/queue-5.15/nfsv4.2-fix-a-memory-stomp-in-decode_attr_security_l.patch b/queue-5.15/nfsv4.2-fix-a-memory-stomp-in-decode_attr_security_l.patch new file mode 100644 index 00000000000..9b1710658ab --- /dev/null +++ b/queue-5.15/nfsv4.2-fix-a-memory-stomp-in-decode_attr_security_l.patch @@ -0,0 +1,43 @@ +From 64292fda8b3b158b2e824b91aedac21da954985f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 18:21:14 -0400 +Subject: NFSv4.2: Fix a memory stomp in decode_attr_security_label + +From: Trond Myklebust + +[ Upstream commit 43c1031f7110967c240cb6e922adcfc4b8899183 ] + +We must not change the value of label->len if it is zero, since that +indicates we stored a label. + +Fixes: b4487b935452 ("nfs: Fix getxattr kernel panic and memory overflow") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4xdr.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c +index 9d19b801cb39..0ae9e06a0bba 100644 +--- a/fs/nfs/nfs4xdr.c ++++ b/fs/nfs/nfs4xdr.c +@@ -4181,12 +4181,10 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, + return -EIO; + bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + if (len < NFS4_MAXLABELLEN) { +- if (label) { +- if (label->len) { +- if (label->len < len) +- return -ERANGE; +- memcpy(label->label, p, len); +- } ++ if (label && label->len) { ++ if (label->len < len) ++ return -ERANGE; ++ memcpy(label->label, p, len); + label->len = len; + label->pi = pi; + label->lfs = lfs; +-- +2.35.1 + diff --git a/queue-5.15/nfsv4.2-fix-initialisation-of-struct-nfs4_label.patch b/queue-5.15/nfsv4.2-fix-initialisation-of-struct-nfs4_label.patch new file mode 100644 index 00000000000..4dd20472525 --- /dev/null +++ b/queue-5.15/nfsv4.2-fix-initialisation-of-struct-nfs4_label.patch @@ -0,0 +1,83 @@ +From 650bd348ec6ea92ec7721225e276ba31b1d40262 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Oct 2022 13:12:11 -0400 +Subject: NFSv4.2: Fix initialisation of struct nfs4_label + +From: Trond Myklebust + +[ Upstream commit c528f70f504434eaff993a5ddd52203a2010d51f ] + +The call to nfs4_label_init_security() should return a fully initialised +label. + +Fixes: aa9c2669626c ("NFS: Client implementation of Labeled-NFS") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index dc03924b6b71..dcc0677d1546 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -126,6 +126,11 @@ nfs4_label_init_security(struct inode *dir, struct dentry *dentry, + if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) + return NULL; + ++ label->lfs = 0; ++ label->pi = 0; ++ label->len = 0; ++ label->label = NULL; ++ + err = security_dentry_init_security(dentry, sattr->ia_mode, + &dentry->d_name, (void **)&label->label, &label->len); + if (err == 0) +@@ -3823,7 +3828,7 @@ nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, + int open_flags, struct iattr *attr, int *opened) + { + struct nfs4_state *state; +- struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; ++ struct nfs4_label l, *label; + + label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); + +@@ -4657,7 +4662,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, + int flags) + { + struct nfs_server *server = NFS_SERVER(dir); +- struct nfs4_label l, *ilabel = NULL; ++ struct nfs4_label l, *ilabel; + struct nfs_open_context *ctx; + struct nfs4_state *state; + int status = 0; +@@ -5017,7 +5022,7 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +@@ -5058,7 +5063,7 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +@@ -5177,7 +5182,7 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, + struct nfs4_exception exception = { + .interruptible = true, + }; +- struct nfs4_label l, *label = NULL; ++ struct nfs4_label l, *label; + int err; + + label = nfs4_label_init_security(dir, dentry, sattr, &l); +-- +2.35.1 + diff --git a/queue-5.15/nfsv4.x-fail-client-initialisation-if-state-manager-.patch b/queue-5.15/nfsv4.x-fail-client-initialisation-if-state-manager-.patch new file mode 100644 index 00000000000..2ffc0d89c3f --- /dev/null +++ b/queue-5.15/nfsv4.x-fail-client-initialisation-if-state-manager-.patch @@ -0,0 +1,37 @@ +From b5cf19e74c5211a3869a21e33e396fc53e10f785 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 12:42:59 -0500 +Subject: NFSv4.x: Fail client initialisation if state manager thread can't run + +From: Trond Myklebust + +[ Upstream commit b4e4f66901658fae0614dea5bf91062a5387eda7 ] + +If the state manager thread fails to start, then we should just mark the +client initialisation as failed so that other processes or threads don't +get stuck in nfs_wait_client_init_complete(). + +Reported-by: ChenXiaoSong +Fixes: 4697bd5e9419 ("NFSv4: Fix a race in the net namespace mount notification") +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4state.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index ecac56be6cb7..0cd803b4d90c 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -1227,6 +1227,8 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) + if (IS_ERR(task)) { + printk(KERN_ERR "%s: kthread_run: %ld\n", + __func__, PTR_ERR(task)); ++ if (!nfs_client_init_is_complete(clp)) ++ nfs_mark_client_ready(clp, PTR_ERR(task)); + nfs4_clear_state_manager_bit(clp); + nfs_put_client(clp); + module_put(THIS_MODULE); +-- +2.35.1 + diff --git a/queue-5.15/nilfs2-fix-shift-out-of-bounds-due-to-too-large-expo.patch b/queue-5.15/nilfs2-fix-shift-out-of-bounds-due-to-too-large-expo.patch new file mode 100644 index 00000000000..a5898b30a69 --- /dev/null +++ b/queue-5.15/nilfs2-fix-shift-out-of-bounds-due-to-too-large-expo.patch @@ -0,0 +1,110 @@ +From f9e9e74a44b50035b7b7536572dd7481002f01c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 13:43:06 +0900 +Subject: nilfs2: fix shift-out-of-bounds due to too large exponent of block + size + +From: Ryusuke Konishi + +[ Upstream commit ebeccaaef67a4895d2496ab8d9c2fb8d89201211 ] + +If field s_log_block_size of superblock data is corrupted and too large, +init_nilfs() and load_nilfs() still can trigger a shift-out-of-bounds +warning followed by a kernel panic (if panic_on_warn is set): + + shift exponent 38973 is too large for 32-bit type 'int' + Call Trace: + + dump_stack_lvl+0xcd/0x134 + ubsan_epilogue+0xb/0x50 + __ubsan_handle_shift_out_of_bounds.cold.12+0x17b/0x1f5 + init_nilfs.cold.11+0x18/0x1d [nilfs2] + nilfs_mount+0x9b5/0x12b0 [nilfs2] + ... + +This fixes the issue by adding and using a new helper function for getting +block size with sanity check. + +Link: https://lkml.kernel.org/r/20221027044306.42774-3-konishi.ryusuke@gmail.com +Signed-off-by: Ryusuke Konishi +Tested-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/nilfs2/the_nilfs.c | 42 ++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 38 insertions(+), 4 deletions(-) + +diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c +index 6a86acd35696..6aa6cef0757f 100644 +--- a/fs/nilfs2/the_nilfs.c ++++ b/fs/nilfs2/the_nilfs.c +@@ -193,6 +193,34 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs, + return ret; + } + ++/** ++ * nilfs_get_blocksize - get block size from raw superblock data ++ * @sb: super block instance ++ * @sbp: superblock raw data buffer ++ * @blocksize: place to store block size ++ * ++ * nilfs_get_blocksize() calculates the block size from the block size ++ * exponent information written in @sbp and stores it in @blocksize, ++ * or aborts with an error message if it's too large. ++ * ++ * Return Value: On success, 0 is returned. If the block size is too ++ * large, -EINVAL is returned. ++ */ ++static int nilfs_get_blocksize(struct super_block *sb, ++ struct nilfs_super_block *sbp, int *blocksize) ++{ ++ unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); ++ ++ if (unlikely(shift_bits > ++ ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS)) { ++ nilfs_err(sb, "too large filesystem blocksize: 2 ^ %u KiB", ++ shift_bits); ++ return -EINVAL; ++ } ++ *blocksize = BLOCK_SIZE << shift_bits; ++ return 0; ++} ++ + /** + * load_nilfs - load and recover the nilfs + * @nilfs: the_nilfs structure to be released +@@ -246,11 +274,15 @@ int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb) + nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); + + /* verify consistency between two super blocks */ +- blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); ++ err = nilfs_get_blocksize(sb, sbp[0], &blocksize); ++ if (err) ++ goto scan_error; ++ + if (blocksize != nilfs->ns_blocksize) { + nilfs_warn(sb, + "blocksize differs between two super blocks (%d != %d)", + blocksize, nilfs->ns_blocksize); ++ err = -EINVAL; + goto scan_error; + } + +@@ -609,9 +641,11 @@ int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data) + if (err) + goto failed_sbh; + +- blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); +- if (blocksize < NILFS_MIN_BLOCK_SIZE || +- blocksize > NILFS_MAX_BLOCK_SIZE) { ++ err = nilfs_get_blocksize(sb, sbp, &blocksize); ++ if (err) ++ goto failed_sbh; ++ ++ if (blocksize < NILFS_MIN_BLOCK_SIZE) { + nilfs_err(sb, + "couldn't mount because of unsupported filesystem blocksize %d", + blocksize); +-- +2.35.1 + diff --git a/queue-5.15/nilfs2-fix-shift-out-of-bounds-overflow-in-nilfs_sb2.patch b/queue-5.15/nilfs2-fix-shift-out-of-bounds-overflow-in-nilfs_sb2.patch new file mode 100644 index 00000000000..bbf3762f44c --- /dev/null +++ b/queue-5.15/nilfs2-fix-shift-out-of-bounds-overflow-in-nilfs_sb2.patch @@ -0,0 +1,114 @@ +From 406f030b8a571ade6821fb7a43b48502655def12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 13:43:05 +0900 +Subject: nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset() + +From: Ryusuke Konishi + +[ Upstream commit 610a2a3d7d8be3537458a378ec69396a76c385b6 ] + +Patch series "nilfs2: fix UBSAN shift-out-of-bounds warnings on mount +time". + +The first patch fixes a bug reported by syzbot, and the second one fixes +the remaining bug of the same kind. Although they are triggered by the +same super block data anomaly, I divided it into the above two because the +details of the issues and how to fix it are different. + +Both are required to eliminate the shift-out-of-bounds issues at mount +time. + +This patch (of 2): + +If the block size exponent information written in an on-disk superblock is +corrupted, nilfs_sb2_bad_offset helper function can trigger +shift-out-of-bounds warning followed by a kernel panic (if panic_on_warn +is set): + + shift exponent 38983 is too large for 64-bit type 'unsigned long long' + Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106 + ubsan_epilogue lib/ubsan.c:151 [inline] + __ubsan_handle_shift_out_of_bounds+0x33d/0x3b0 lib/ubsan.c:322 + nilfs_sb2_bad_offset fs/nilfs2/the_nilfs.c:449 [inline] + nilfs_load_super_block+0xdf5/0xe00 fs/nilfs2/the_nilfs.c:523 + init_nilfs+0xb7/0x7d0 fs/nilfs2/the_nilfs.c:577 + nilfs_fill_super+0xb1/0x5d0 fs/nilfs2/super.c:1047 + nilfs_mount+0x613/0x9b0 fs/nilfs2/super.c:1317 + ... + +In addition, since nilfs_sb2_bad_offset() performs multiplication without +considering the upper bound, the computation may overflow if the disk +layout parameters are not normal. + +This fixes these issues by inserting preliminary sanity checks for those +parameters and by converting the comparison from one involving +multiplication and left bit-shifting to one using division and right +bit-shifting. + +Link: https://lkml.kernel.org/r/20221027044306.42774-1-konishi.ryusuke@gmail.com +Link: https://lkml.kernel.org/r/20221027044306.42774-2-konishi.ryusuke@gmail.com +Signed-off-by: Ryusuke Konishi +Reported-by: syzbot+e91619dd4c11c4960706@syzkaller.appspotmail.com +Tested-by: Ryusuke Konishi +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/nilfs2/the_nilfs.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c +index 16994598a8db..6a86acd35696 100644 +--- a/fs/nilfs2/the_nilfs.c ++++ b/fs/nilfs2/the_nilfs.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + #include "nilfs.h" + #include "segment.h" +@@ -443,11 +444,33 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp) + return crc == le32_to_cpu(sbp->s_sum); + } + +-static int nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) ++/** ++ * nilfs_sb2_bad_offset - check the location of the second superblock ++ * @sbp: superblock raw data buffer ++ * @offset: byte offset of second superblock calculated from device size ++ * ++ * nilfs_sb2_bad_offset() checks if the position on the second ++ * superblock is valid or not based on the filesystem parameters ++ * stored in @sbp. If @offset points to a location within the segment ++ * area, or if the parameters themselves are not normal, it is ++ * determined to be invalid. ++ * ++ * Return Value: true if invalid, false if valid. ++ */ ++static bool nilfs_sb2_bad_offset(struct nilfs_super_block *sbp, u64 offset) + { +- return offset < ((le64_to_cpu(sbp->s_nsegments) * +- le32_to_cpu(sbp->s_blocks_per_segment)) << +- (le32_to_cpu(sbp->s_log_block_size) + 10)); ++ unsigned int shift_bits = le32_to_cpu(sbp->s_log_block_size); ++ u32 blocks_per_segment = le32_to_cpu(sbp->s_blocks_per_segment); ++ u64 nsegments = le64_to_cpu(sbp->s_nsegments); ++ u64 index; ++ ++ if (blocks_per_segment < NILFS_SEG_MIN_BLOCKS || ++ shift_bits > ilog2(NILFS_MAX_BLOCK_SIZE) - BLOCK_SIZE_BITS) ++ return true; ++ ++ index = offset >> (shift_bits + BLOCK_SIZE_BITS); ++ do_div(index, blocks_per_segment); ++ return index < nsegments; + } + + static void nilfs_release_super_block(struct the_nilfs *nilfs) +-- +2.35.1 + diff --git a/queue-5.15/ntb_netdev-use-dev_kfree_skb_any-in-interrupt-contex.patch b/queue-5.15/ntb_netdev-use-dev_kfree_skb_any-in-interrupt-contex.patch new file mode 100644 index 00000000000..b7e12ea96fd --- /dev/null +++ b/queue-5.15/ntb_netdev-use-dev_kfree_skb_any-in-interrupt-contex.patch @@ -0,0 +1,73 @@ +From 68290abcabe76aa95ab61b5b8b2a553e7936bd41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 16:06:59 -0800 +Subject: ntb_netdev: Use dev_kfree_skb_any() in interrupt context + +From: Eric Pilmore + +[ Upstream commit 5f7d78b2b12a9d561f48fa00bab29b40f4616dad ] + +TX/RX callback handlers (ntb_netdev_tx_handler(), +ntb_netdev_rx_handler()) can be called in interrupt +context via the DMA framework when the respective +DMA operations have completed. As such, any calls +by these routines to free skb's, should use the +interrupt context safe dev_kfree_skb_any() function. + +Previously, these callback handlers would call the +interrupt unsafe version of dev_kfree_skb(). This has +not presented an issue on Intel IOAT DMA engines as +that driver utilizes tasklets rather than a hard +interrupt handler, like the AMD PTDMA DMA driver. +On AMD systems, a kernel WARNING message is +encountered, which is being issued from +skb_release_head_state() due to in_hardirq() +being true. + +Besides the user visible WARNING from the kernel, +the other symptom of this bug was that TCP/IP performance +across the ntb_netdev interface was very poor, i.e. +approximately an order of magnitude below what was +expected. With the repair to use dev_kfree_skb_any(), +kernel WARNINGs from skb_release_head_state() ceased +and TCP/IP performance, as measured by iperf, was on +par with expected results, approximately 20 Gb/s on +AMD Milan based server. Note that this performance +is comparable with Intel based servers. + +Fixes: 765ccc7bc3d91 ("ntb_netdev: correct skb leak") +Fixes: 548c237c0a997 ("net: Add support for NTB virtual ethernet device") +Signed-off-by: Eric Pilmore +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20221209000659.8318-1-epilmore@gigaio.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ntb_netdev.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c +index 1b7d588ff3c5..b701ee83e64a 100644 +--- a/drivers/net/ntb_netdev.c ++++ b/drivers/net/ntb_netdev.c +@@ -137,7 +137,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data, + enqueue_again: + rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN); + if (rc) { +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + ndev->stats.rx_errors++; + ndev->stats.rx_fifo_errors++; + } +@@ -192,7 +192,7 @@ static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data, + ndev->stats.tx_aborted_errors++; + } + +- dev_kfree_skb(skb); ++ dev_kfree_skb_any(skb); + + if (ntb_transport_tx_free_entry(dev->qp) >= tx_start) { + /* Make sure anybody stopping the queue after this sees the new +-- +2.35.1 + diff --git a/queue-5.15/nvme-return-err-on-nvme_init_non_mdts_limits-fail.patch b/queue-5.15/nvme-return-err-on-nvme_init_non_mdts_limits-fail.patch new file mode 100644 index 00000000000..b9366443aa2 --- /dev/null +++ b/queue-5.15/nvme-return-err-on-nvme_init_non_mdts_limits-fail.patch @@ -0,0 +1,37 @@ +From 992852b60d346e413e9d646275eacc68fb857081 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 18:17:08 +0100 +Subject: nvme: return err on nvme_init_non_mdts_limits fail + +From: Joel Granados + +[ Upstream commit bcaf434b8f04e1ee82a8b1e1bce0de99fbff67fa ] + +In nvme_init_non_mdts_limits function we were returning 0 when kzalloc +failed; it now returns -ENOMEM. + +Fixes: 5befc7c26e5a ("nvme: implement non-mdts command limits") +Signed-off-by: Joel Granados +Reviewed-by: Chaitanya Kulkarni +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 692ee0f4a1ec..2d5b5e0fb66a 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -2874,7 +2874,7 @@ static int nvme_init_non_mdts_limits(struct nvme_ctrl *ctrl) + + id = kzalloc(sizeof(*id), GFP_KERNEL); + if (!id) +- return 0; ++ return -ENOMEM; + + c.identify.opcode = nvme_admin_identify; + c.identify.cns = NVME_ID_CNS_CS_CTRL; +-- +2.35.1 + diff --git a/queue-5.15/nvmet-only-allocate-a-single-slab-for-bvecs.patch b/queue-5.15/nvmet-only-allocate-a-single-slab-for-bvecs.patch new file mode 100644 index 00000000000..8492a52e6c5 --- /dev/null +++ b/queue-5.15/nvmet-only-allocate-a-single-slab-for-bvecs.patch @@ -0,0 +1,166 @@ +From 0e6f8bb98e55c9173edbf2eabee5548cb7f672cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 14:01:24 +0100 +Subject: nvmet: only allocate a single slab for bvecs + +From: Christoph Hellwig + +[ Upstream commit fa8f9ac42350edd3ce82d0d148a60f0fa088f995 ] + +There is no need to have a separate slab cache for each namespace, +and having separate ones creates duplicate debugs file names as well. + +Fixes: d5eff33ee6f8 ("nvmet: add simple file backed ns support") +Signed-off-by: Christoph Hellwig +Reviewed-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/core.c | 22 ++++++++++++++-------- + drivers/nvme/target/io-cmd-file.c | 16 +++------------- + drivers/nvme/target/nvmet.h | 3 ++- + 3 files changed, 19 insertions(+), 22 deletions(-) + +diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c +index 87a347248c38..cfd038551156 100644 +--- a/drivers/nvme/target/core.c ++++ b/drivers/nvme/target/core.c +@@ -15,6 +15,7 @@ + + #include "nvmet.h" + ++struct kmem_cache *nvmet_bvec_cache; + struct workqueue_struct *buffered_io_wq; + struct workqueue_struct *zbd_wq; + static const struct nvmet_fabrics_ops *nvmet_transports[NVMF_TRTYPE_MAX]; +@@ -1607,26 +1608,28 @@ void nvmet_subsys_put(struct nvmet_subsys *subsys) + + static int __init nvmet_init(void) + { +- int error; ++ int error = -ENOMEM; + + nvmet_ana_group_enabled[NVMET_DEFAULT_ANA_GRPID] = 1; + ++ nvmet_bvec_cache = kmem_cache_create("nvmet-bvec", ++ NVMET_MAX_MPOOL_BVEC * sizeof(struct bio_vec), 0, ++ SLAB_HWCACHE_ALIGN, NULL); ++ if (!nvmet_bvec_cache) ++ return -ENOMEM; ++ + zbd_wq = alloc_workqueue("nvmet-zbd-wq", WQ_MEM_RECLAIM, 0); + if (!zbd_wq) +- return -ENOMEM; ++ goto out_destroy_bvec_cache; + + buffered_io_wq = alloc_workqueue("nvmet-buffered-io-wq", + WQ_MEM_RECLAIM, 0); +- if (!buffered_io_wq) { +- error = -ENOMEM; ++ if (!buffered_io_wq) + goto out_free_zbd_work_queue; +- } + + nvmet_wq = alloc_workqueue("nvmet-wq", WQ_MEM_RECLAIM, 0); +- if (!nvmet_wq) { +- error = -ENOMEM; ++ if (!nvmet_wq) + goto out_free_buffered_work_queue; +- } + + error = nvmet_init_discovery(); + if (error) +@@ -1645,6 +1648,8 @@ static int __init nvmet_init(void) + destroy_workqueue(buffered_io_wq); + out_free_zbd_work_queue: + destroy_workqueue(zbd_wq); ++out_destroy_bvec_cache: ++ kmem_cache_destroy(nvmet_bvec_cache); + return error; + } + +@@ -1656,6 +1661,7 @@ static void __exit nvmet_exit(void) + destroy_workqueue(nvmet_wq); + destroy_workqueue(buffered_io_wq); + destroy_workqueue(zbd_wq); ++ kmem_cache_destroy(nvmet_bvec_cache); + + BUILD_BUG_ON(sizeof(struct nvmf_disc_rsp_page_entry) != 1024); + BUILD_BUG_ON(sizeof(struct nvmf_disc_rsp_page_hdr) != 1024); +diff --git a/drivers/nvme/target/io-cmd-file.c b/drivers/nvme/target/io-cmd-file.c +index 228871d48106..eadba13b276d 100644 +--- a/drivers/nvme/target/io-cmd-file.c ++++ b/drivers/nvme/target/io-cmd-file.c +@@ -11,7 +11,6 @@ + #include + #include "nvmet.h" + +-#define NVMET_MAX_MPOOL_BVEC 16 + #define NVMET_MIN_MPOOL_OBJ 16 + + int nvmet_file_ns_revalidate(struct nvmet_ns *ns) +@@ -33,8 +32,6 @@ void nvmet_file_ns_disable(struct nvmet_ns *ns) + flush_workqueue(buffered_io_wq); + mempool_destroy(ns->bvec_pool); + ns->bvec_pool = NULL; +- kmem_cache_destroy(ns->bvec_cache); +- ns->bvec_cache = NULL; + fput(ns->file); + ns->file = NULL; + } +@@ -68,16 +65,8 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns) + ns->blksize_shift = min_t(u8, + file_inode(ns->file)->i_blkbits, 12); + +- ns->bvec_cache = kmem_cache_create("nvmet-bvec", +- NVMET_MAX_MPOOL_BVEC * sizeof(struct bio_vec), +- 0, SLAB_HWCACHE_ALIGN, NULL); +- if (!ns->bvec_cache) { +- ret = -ENOMEM; +- goto err; +- } +- + ns->bvec_pool = mempool_create(NVMET_MIN_MPOOL_OBJ, mempool_alloc_slab, +- mempool_free_slab, ns->bvec_cache); ++ mempool_free_slab, nvmet_bvec_cache); + + if (!ns->bvec_pool) { + ret = -ENOMEM; +@@ -86,9 +75,10 @@ int nvmet_file_ns_enable(struct nvmet_ns *ns) + + return ret; + err: ++ fput(ns->file); ++ ns->file = NULL; + ns->size = 0; + ns->blksize_shift = 0; +- nvmet_file_ns_disable(ns); + return ret; + } + +diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h +index dbeb0b8c1194..fdb06a9d430d 100644 +--- a/drivers/nvme/target/nvmet.h ++++ b/drivers/nvme/target/nvmet.h +@@ -77,7 +77,6 @@ struct nvmet_ns { + + struct completion disable_done; + mempool_t *bvec_pool; +- struct kmem_cache *bvec_cache; + + int use_p2pmem; + struct pci_dev *p2p_dev; +@@ -363,6 +362,8 @@ struct nvmet_req { + u64 error_slba; + }; + ++#define NVMET_MAX_MPOOL_BVEC 16 ++extern struct kmem_cache *nvmet_bvec_cache; + extern struct workqueue_struct *buffered_io_wq; + extern struct workqueue_struct *zbd_wq; + extern struct workqueue_struct *nvmet_wq; +-- +2.35.1 + diff --git a/queue-5.15/objtool-kcsan-add-volatile-read-write-instrumentatio.patch b/queue-5.15/objtool-kcsan-add-volatile-read-write-instrumentatio.patch new file mode 100644 index 00000000000..c2387d213c1 --- /dev/null +++ b/queue-5.15/objtool-kcsan-add-volatile-read-write-instrumentatio.patch @@ -0,0 +1,49 @@ +From ce828efcc5f1300b5d9989c6dfd8641555a99087 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 11:45:41 +0200 +Subject: objtool, kcsan: Add volatile read/write instrumentation to whitelist + +From: Marco Elver + +[ Upstream commit 63646fcba5bb4b59a19031c21913f94e46a3d0d4 ] + +Adds KCSAN's volatile instrumentation to objtool's uaccess whitelist. + +Recent kernel change have shown that this was missing from the uaccess +whitelist (since the first upstreamed version of KCSAN): + + mm/gup.o: warning: objtool: fault_in_readable+0x101: call to __tsan_volatile_write1() with UACCESS enabled + +Fixes: 75d75b7a4d54 ("kcsan: Support distinguishing volatile accesses") +Signed-off-by: Marco Elver +Reviewed-by: Dmitry Vyukov +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + tools/objtool/check.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/tools/objtool/check.c b/tools/objtool/check.c +index 72e5d23f1ad8..edac5aaa2802 100644 +--- a/tools/objtool/check.c ++++ b/tools/objtool/check.c +@@ -846,6 +846,16 @@ static const char *uaccess_safe_builtin[] = { + "__tsan_read_write4", + "__tsan_read_write8", + "__tsan_read_write16", ++ "__tsan_volatile_read1", ++ "__tsan_volatile_read2", ++ "__tsan_volatile_read4", ++ "__tsan_volatile_read8", ++ "__tsan_volatile_read16", ++ "__tsan_volatile_write1", ++ "__tsan_volatile_write2", ++ "__tsan_volatile_write4", ++ "__tsan_volatile_write8", ++ "__tsan_volatile_write16", + "__tsan_atomic8_load", + "__tsan_atomic16_load", + "__tsan_atomic32_load", +-- +2.35.1 + diff --git a/queue-5.15/ocfs2-fix-memory-leak-in-ocfs2_stack_glue_init.patch b/queue-5.15/ocfs2-fix-memory-leak-in-ocfs2_stack_glue_init.patch new file mode 100644 index 00000000000..96b60dc3cd0 --- /dev/null +++ b/queue-5.15/ocfs2-fix-memory-leak-in-ocfs2_stack_glue_init.patch @@ -0,0 +1,73 @@ +From 11c3de5b5a02852574beea719405536a7471b006 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 19:15:33 +0800 +Subject: ocfs2: fix memory leak in ocfs2_stack_glue_init() + +From: Shang XiaoJing + +[ Upstream commit 13b6269dd022aaa69ca8d1df374ab327504121cf ] + +ocfs2_table_header should be free in ocfs2_stack_glue_init() if +ocfs2_sysfs_init() failed, otherwise kmemleak will report memleak. + +BUG: memory leak +unreferenced object 0xffff88810eeb5800 (size 128): + comm "modprobe", pid 4507, jiffies 4296182506 (age 55.888s) + hex dump (first 32 bytes): + c0 40 14 a0 ff ff ff ff 00 00 00 00 01 00 00 00 .@.............. + 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<000000001e59e1cd>] __register_sysctl_table+0xca/0xef0 + [<00000000c04f70f7>] 0xffffffffa0050037 + [<000000001bd12912>] do_one_initcall+0xdb/0x480 + [<0000000064f766c9>] do_init_module+0x1cf/0x680 + [<000000002ba52db0>] load_module+0x6441/0x6f20 + [<000000009772580d>] __do_sys_finit_module+0x12f/0x1c0 + [<00000000380c1f22>] do_syscall_64+0x3f/0x90 + [<000000004cf473bc>] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Link: https://lkml.kernel.org/r/41651ca1-432a-db34-eb97-d35744559de1@linux.alibaba.com +Fixes: 3878f110f71a ("ocfs2: Move the hb_ctl_path sysctl into the stack glue.") +Signed-off-by: Shang XiaoJing +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Junxiao Bi +Cc: Changwei Ge +Cc: Gang He +Cc: Jun Piao +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/ocfs2/stackglue.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c +index 16f1bfc407f2..955f475f9aca 100644 +--- a/fs/ocfs2/stackglue.c ++++ b/fs/ocfs2/stackglue.c +@@ -703,6 +703,8 @@ static struct ctl_table_header *ocfs2_table_header; + + static int __init ocfs2_stack_glue_init(void) + { ++ int ret; ++ + strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); + + ocfs2_table_header = register_sysctl_table(ocfs2_root_table); +@@ -712,7 +714,11 @@ static int __init ocfs2_stack_glue_init(void) + return -ENOMEM; /* or something. */ + } + +- return ocfs2_sysfs_init(); ++ ret = ocfs2_sysfs_init(); ++ if (ret) ++ unregister_sysctl_table(ocfs2_table_header); ++ ++ return ret; + } + + static void __exit ocfs2_stack_glue_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/ocxl-fix-pci-device-refcount-leak-when-calling-get_f.patch b/queue-5.15/ocxl-fix-pci-device-refcount-leak-when-calling-get_f.patch new file mode 100644 index 00000000000..c4ae1400afe --- /dev/null +++ b/queue-5.15/ocxl-fix-pci-device-refcount-leak-when-calling-get_f.patch @@ -0,0 +1,87 @@ +From eb5ea3c818a159b9d410419168f90be865d44713 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 23:43:39 +0800 +Subject: ocxl: fix pci device refcount leak when calling get_function_0() + +From: Yang Yingliang + +[ Upstream commit 27158c72678b39ee01cc01de1aba6b51c71abe2f ] + +get_function_0() calls pci_get_domain_bus_and_slot(), as comment +says, it returns a pci device with refcount increment, so after +using it, pci_dev_put() needs be called. + +Get the device reference when get_function_0() is not called, so +pci_dev_put() can be called in the error path and callers +unconditionally. And add comment above get_dvsec_vendor0() to tell +callers to call pci_dev_put(). + +Fixes: 87db7579ebd5 ("ocxl: control via sysfs whether the FPGA is reloaded on a link reset") +Suggested-by: Andrew Donnellan +Signed-off-by: Yang Yingliang +Acked-by: Andrew Donnellan +Link: https://lore.kernel.org/r/20221121154339.4088935-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/ocxl/config.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/ocxl/config.c b/drivers/misc/ocxl/config.c +index a68738f38252..f1f669efe050 100644 +--- a/drivers/misc/ocxl/config.c ++++ b/drivers/misc/ocxl/config.c +@@ -204,6 +204,18 @@ static int read_dvsec_vendor(struct pci_dev *dev) + return 0; + } + ++/** ++ * get_dvsec_vendor0() - Find a related PCI device (function 0) ++ * @dev: PCI device to match ++ * @dev0: The PCI device (function 0) found ++ * @out_pos: The position of PCI device (function 0) ++ * ++ * Returns 0 on success, negative on failure. ++ * ++ * NOTE: If it's successful, the reference of dev0 is increased, ++ * so after using it, the callers must call pci_dev_put() to give ++ * up the reference. ++ */ + static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0, + int *out_pos) + { +@@ -213,10 +225,14 @@ static int get_dvsec_vendor0(struct pci_dev *dev, struct pci_dev **dev0, + dev = get_function_0(dev); + if (!dev) + return -1; ++ } else { ++ dev = pci_dev_get(dev); + } + pos = find_dvsec(dev, OCXL_DVSEC_VENDOR_ID); +- if (!pos) ++ if (!pos) { ++ pci_dev_put(dev); + return -1; ++ } + *dev0 = dev; + *out_pos = pos; + return 0; +@@ -233,6 +249,7 @@ int ocxl_config_get_reset_reload(struct pci_dev *dev, int *val) + + pci_read_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD, + &reset_reload); ++ pci_dev_put(dev0); + *val = !!(reset_reload & BIT(0)); + return 0; + } +@@ -254,6 +271,7 @@ int ocxl_config_set_reset_reload(struct pci_dev *dev, int val) + reset_reload &= ~BIT(0); + pci_write_config_dword(dev0, pos + OCXL_DVSEC_VENDOR_RESET_RELOAD, + reset_reload); ++ pci_dev_put(dev0); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/of-overlay-fix-null-pointer-dereferencing-in-find_du.patch b/queue-5.15/of-overlay-fix-null-pointer-dereferencing-in-find_du.patch new file mode 100644 index 00000000000..2c3befee340 --- /dev/null +++ b/queue-5.15/of-overlay-fix-null-pointer-dereferencing-in-find_du.patch @@ -0,0 +1,47 @@ +From c61f1649b3404f274da09aac958d3d9d9ae716a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Dec 2022 10:33:37 +0800 +Subject: of: overlay: fix null pointer dereferencing in + find_dup_cset_node_entry() and find_dup_cset_prop() + +From: ruanjinjie + +[ Upstream commit ee9d7a0e754568180a2f8ebc4aad226278a9116f ] + +When kmalloc() fail to allocate memory in kasprintf(), fn_1 or fn_2 will +be NULL, and strcmp() will cause null pointer dereference. + +Fixes: 2fe0e8769df9 ("of: overlay: check prevents multiple fragments touching same property") +Signed-off-by: ruanjinjie +Link: https://lore.kernel.org/r/20221211023337.592266-1-ruanjinjie@huawei.com +Signed-off-by: Rob Herring +Signed-off-by: Sasha Levin +--- + drivers/of/overlay.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c +index d1187123c4fc..424682372417 100644 +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -547,7 +547,7 @@ static int find_dup_cset_node_entry(struct overlay_changeset *ovcs, + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); +- node_path_match = !strcmp(fn_1, fn_2); ++ node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match) { +@@ -582,7 +582,7 @@ static int find_dup_cset_prop(struct overlay_changeset *ovcs, + + fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np); + fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np); +- node_path_match = !strcmp(fn_1, fn_2); ++ node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2); + kfree(fn_1); + kfree(fn_2); + if (node_path_match && +-- +2.35.1 + diff --git a/queue-5.15/openvswitch-fix-flow-lookup-to-use-unmasked-key.patch b/queue-5.15/openvswitch-fix-flow-lookup-to-use-unmasked-key.patch new file mode 100644 index 00000000000..5959977231c --- /dev/null +++ b/queue-5.15/openvswitch-fix-flow-lookup-to-use-unmasked-key.patch @@ -0,0 +1,121 @@ +From 116c659ca27c518bf2bd3815eac1816db4f854e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Dec 2022 15:46:33 +0100 +Subject: openvswitch: Fix flow lookup to use unmasked key + +From: Eelco Chaudron + +[ Upstream commit 68bb10101e6b0a6bb44e9c908ef795fc4af99eae ] + +The commit mentioned below causes the ovs_flow_tbl_lookup() function +to be called with the masked key. However, it's supposed to be called +with the unmasked key. This due to the fact that the datapath supports +installing wider flows, and OVS relies on this behavior. For example +if ipv4(src=1.1.1.1/192.0.0.0, dst=1.1.1.2/192.0.0.0) exists, a wider +flow (smaller mask) of ipv4(src=192.1.1.1/128.0.0.0,dst=192.1.1.2/ +128.0.0.0) is allowed to be added. + +However, if we try to add a wildcard rule, the installation fails: + +$ ovs-appctl dpctl/add-flow system@myDP "in_port(1),eth_type(0x0800), \ + ipv4(src=1.1.1.1/192.0.0.0,dst=1.1.1.2/192.0.0.0,frag=no)" 2 +$ ovs-appctl dpctl/add-flow system@myDP "in_port(1),eth_type(0x0800), \ + ipv4(src=192.1.1.1/0.0.0.0,dst=49.1.1.2/0.0.0.0,frag=no)" 2 +ovs-vswitchd: updating flow table (File exists) + +The reason is that the key used to determine if the flow is already +present in the system uses the original key ANDed with the mask. +This results in the IP address not being part of the (miniflow) key, +i.e., being substituted with an all-zero value. When doing the actual +lookup, this results in the key wrongfully matching the first flow, +and therefore the flow does not get installed. + +This change reverses the commit below, but rather than having the key +on the stack, it's allocated. + +Fixes: 190aa3e77880 ("openvswitch: Fix Frame-size larger than 1024 bytes warning.") + +Signed-off-by: Eelco Chaudron +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/openvswitch/datapath.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 94c48122fdc3..795a25ecb893 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -946,6 +946,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + struct sw_flow_mask mask; + struct sk_buff *reply; + struct datapath *dp; ++ struct sw_flow_key *key; + struct sw_flow_actions *acts; + struct sw_flow_match match; + u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]); +@@ -973,24 +974,26 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + } + + /* Extract key. */ +- ovs_match_init(&match, &new_flow->key, false, &mask); ++ key = kzalloc(sizeof(*key), GFP_KERNEL); ++ if (!key) { ++ error = -ENOMEM; ++ goto err_kfree_key; ++ } ++ ++ ovs_match_init(&match, key, false, &mask); + error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], + a[OVS_FLOW_ATTR_MASK], log); + if (error) + goto err_kfree_flow; + ++ ovs_flow_mask_key(&new_flow->key, key, true, &mask); ++ + /* Extract flow identifier. */ + error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID], +- &new_flow->key, log); ++ key, log); + if (error) + goto err_kfree_flow; + +- /* unmasked key is needed to match when ufid is not used. */ +- if (ovs_identifier_is_key(&new_flow->id)) +- match.key = new_flow->id.unmasked_key; +- +- ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask); +- + /* Validate actions. */ + error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS], + &new_flow->key, &acts, log); +@@ -1017,7 +1020,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + if (ovs_identifier_is_ufid(&new_flow->id)) + flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id); + if (!flow) +- flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key); ++ flow = ovs_flow_tbl_lookup(&dp->table, key); + if (likely(!flow)) { + rcu_assign_pointer(new_flow->sf_acts, acts); + +@@ -1087,6 +1090,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + + if (reply) + ovs_notify(&dp_flow_genl_family, reply, info); ++ ++ kfree(key); + return 0; + + err_unlock_ovs: +@@ -1096,6 +1101,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info) + ovs_nla_free_flow_actions(acts); + err_kfree_flow: + ovs_flow_free(new_flow, false); ++err_kfree_key: ++ kfree(key); + error: + return error; + } +-- +2.35.1 + diff --git a/queue-5.15/orangefs-fix-kmemleak-in-orangefs_-kernel-client-_de.patch b/queue-5.15/orangefs-fix-kmemleak-in-orangefs_-kernel-client-_de.patch new file mode 100644 index 00000000000..2b3beac135b --- /dev/null +++ b/queue-5.15/orangefs-fix-kmemleak-in-orangefs_-kernel-client-_de.patch @@ -0,0 +1,107 @@ +From 8cbd4344bb9b470a3a19e15f93b73f5597f72ef6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 12:40:07 +0800 +Subject: orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init() + +From: Zhang Xiaoxu + +[ Upstream commit 31720a2b109b3080eb77e97b8f6f50a27b4ae599 ] + +When insert and remove the orangefs module, there are memory leaked +as below: + +unreferenced object 0xffff88816b0cc000 (size 2048): + comm "insmod", pid 783, jiffies 4294813439 (age 65.512s) + hex dump (first 32 bytes): + 6e 6f 6e 65 0a 00 00 00 00 00 00 00 00 00 00 00 none............ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<0000000031ab7788>] kmalloc_trace+0x27/0xa0 + [<000000005b405fee>] orangefs_debugfs_init.cold+0xaf/0x17f + [<00000000e5a0085b>] 0xffffffffa02780f9 + [<000000004232d9f7>] do_one_initcall+0x87/0x2a0 + [<0000000054f22384>] do_init_module+0xdf/0x320 + [<000000003263bdea>] load_module+0x2f98/0x3330 + [<0000000052cd4153>] __do_sys_finit_module+0x113/0x1b0 + [<00000000250ae02b>] do_syscall_64+0x35/0x80 + [<00000000f11c03c7>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +Use the golbal variable as the buffer rather than dynamic allocate to +slove the problem. + +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Mike Marshall +Signed-off-by: Sasha Levin +--- + fs/orangefs/orangefs-debugfs.c | 26 +++----------------------- + 1 file changed, 3 insertions(+), 23 deletions(-) + +diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c +index a848b6ef9599..1b508f543384 100644 +--- a/fs/orangefs/orangefs-debugfs.c ++++ b/fs/orangefs/orangefs-debugfs.c +@@ -194,15 +194,10 @@ void orangefs_debugfs_init(int debug_mask) + */ + static void orangefs_kernel_debug_init(void) + { +- int rc = -ENOMEM; +- char *k_buffer = NULL; ++ static char k_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; + + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); + +- k_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); +- if (!k_buffer) +- goto out; +- + if (strlen(kernel_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { + strcpy(k_buffer, kernel_debug_string); + strcat(k_buffer, "\n"); +@@ -213,9 +208,6 @@ static void orangefs_kernel_debug_init(void) + + debugfs_create_file(ORANGEFS_KMOD_DEBUG_FILE, 0444, debug_dir, k_buffer, + &kernel_debug_fops); +- +-out: +- gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); + } + + +@@ -299,18 +291,13 @@ static int help_show(struct seq_file *m, void *v) + /* + * initialize the client-debug file. + */ +-static int orangefs_client_debug_init(void) ++static void orangefs_client_debug_init(void) + { + +- int rc = -ENOMEM; +- char *c_buffer = NULL; ++ static char c_buffer[ORANGEFS_MAX_DEBUG_STRING_LEN] = { }; + + gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: start\n", __func__); + +- c_buffer = kzalloc(ORANGEFS_MAX_DEBUG_STRING_LEN, GFP_KERNEL); +- if (!c_buffer) +- goto out; +- + if (strlen(client_debug_string) + 1 < ORANGEFS_MAX_DEBUG_STRING_LEN) { + strcpy(c_buffer, client_debug_string); + strcat(c_buffer, "\n"); +@@ -324,13 +311,6 @@ static int orangefs_client_debug_init(void) + debug_dir, + c_buffer, + &kernel_debug_fops); +- +- rc = 0; +- +-out: +- +- gossip_debug(GOSSIP_DEBUGFS_DEBUG, "%s: rc:%d:\n", __func__, rc); +- return rc; + } + + /* open ORANGEFS_KMOD_DEBUG_FILE or ORANGEFS_CLIENT_DEBUG_FILE.*/ +-- +2.35.1 + diff --git a/queue-5.15/orangefs-fix-kmemleak-in-orangefs_prepare_debugfs_he.patch b/queue-5.15/orangefs-fix-kmemleak-in-orangefs_prepare_debugfs_he.patch new file mode 100644 index 00000000000..9769482b928 --- /dev/null +++ b/queue-5.15/orangefs-fix-kmemleak-in-orangefs_prepare_debugfs_he.patch @@ -0,0 +1,62 @@ +From f16a8fb4e12dd32894dab193714c7297bd6d2deb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 12:40:05 +0800 +Subject: orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string() + +From: Zhang Xiaoxu + +[ Upstream commit d23417a5bf3a3afc55de5442eb46e1e60458b0a1 ] + +When insert and remove the orangefs module, then debug_help_string will +be leaked: + + unreferenced object 0xffff8881652ba000 (size 4096): + comm "insmod", pid 1701, jiffies 4294893639 (age 13218.530s) + hex dump (first 32 bytes): + 43 6c 69 65 6e 74 20 44 65 62 75 67 20 4b 65 79 Client Debug Key + 77 6f 72 64 73 20 61 72 65 20 75 6e 6b 6e 6f 77 words are unknow + backtrace: + [<0000000004e6f8e3>] kmalloc_trace+0x27/0xa0 + [<0000000006f75d85>] orangefs_prepare_debugfs_help_string+0x5e/0x480 [orangefs] + [<0000000091270a2a>] _sub_I_65535_1+0x57/0xf70 [crc_itu_t] + [<000000004b1ee1a3>] do_one_initcall+0x87/0x2a0 + [<000000001d0614ae>] do_init_module+0xdf/0x320 + [<00000000efef068c>] load_module+0x2f98/0x3330 + [<000000006533b44d>] __do_sys_finit_module+0x113/0x1b0 + [<00000000a0da6f99>] do_syscall_64+0x35/0x80 + [<000000007790b19b>] entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +When remove the module, should always free debug_help_string. Should +always free the allocated buffer when change the free_debug_help_string. + +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Mike Marshall +Signed-off-by: Sasha Levin +--- + fs/orangefs/orangefs-debugfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c +index 29eaa4544372..a848b6ef9599 100644 +--- a/fs/orangefs/orangefs-debugfs.c ++++ b/fs/orangefs/orangefs-debugfs.c +@@ -222,6 +222,8 @@ static void orangefs_kernel_debug_init(void) + void orangefs_debugfs_cleanup(void) + { + debugfs_remove_recursive(debug_dir); ++ kfree(debug_help_string); ++ debug_help_string = NULL; + } + + /* open ORANGEFS_KMOD_DEBUG_HELP_FILE */ +@@ -671,6 +673,7 @@ int orangefs_prepare_debugfs_help_string(int at_boot) + memset(debug_help_string, 0, DEBUG_HELP_STRING_SIZE); + strlcat(debug_help_string, new, string_size); + mutex_unlock(&orangefs_help_file_lock); ++ kfree(new); + } + + rc = 0; +-- +2.35.1 + diff --git a/queue-5.15/orangefs-fix-sysfs-not-cleanup-when-dev-init-failed.patch b/queue-5.15/orangefs-fix-sysfs-not-cleanup-when-dev-init-failed.patch new file mode 100644 index 00000000000..4fe43f36426 --- /dev/null +++ b/queue-5.15/orangefs-fix-sysfs-not-cleanup-when-dev-init-failed.patch @@ -0,0 +1,74 @@ +From dc7f3fe72ec99da47521586f6502622790995567 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 12:40:04 +0800 +Subject: orangefs: Fix sysfs not cleanup when dev init failed + +From: Zhang Xiaoxu + +[ Upstream commit ea60a4ad0cf88b411cde6888b8c890935686ecd7 ] + +When the dev init failed, should cleanup the sysfs, otherwise, the +module will never be loaded since can not create duplicate sysfs +directory: + + sysfs: cannot create duplicate filename '/fs/orangefs' + + CPU: 1 PID: 6549 Comm: insmod Tainted: G W 6.0.0+ #44 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014 + Call Trace: + + dump_stack_lvl+0x34/0x44 + sysfs_warn_dup.cold+0x17/0x24 + sysfs_create_dir_ns+0x16d/0x180 + kobject_add_internal+0x156/0x3a0 + kobject_init_and_add+0xcf/0x120 + orangefs_sysfs_init+0x7e/0x3a0 [orangefs] + orangefs_init+0xfe/0x1000 [orangefs] + do_one_initcall+0x87/0x2a0 + do_init_module+0xdf/0x320 + load_module+0x2f98/0x3330 + __do_sys_finit_module+0x113/0x1b0 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + + kobject_add_internal failed for orangefs with -EEXIST, don't try to register things with the same name in the same directory. + +Fixes: 2f83ace37181 ("orangefs: put register_chrdev immediately before register_filesystem") +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Mike Marshall +Signed-off-by: Sasha Levin +--- + fs/orangefs/orangefs-mod.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/orangefs/orangefs-mod.c b/fs/orangefs/orangefs-mod.c +index cd7297815f91..5ab741c60b7e 100644 +--- a/fs/orangefs/orangefs-mod.c ++++ b/fs/orangefs/orangefs-mod.c +@@ -141,7 +141,7 @@ static int __init orangefs_init(void) + gossip_err("%s: could not initialize device subsystem %d!\n", + __func__, + ret); +- goto cleanup_device; ++ goto cleanup_sysfs; + } + + ret = register_filesystem(&orangefs_fs_type); +@@ -152,11 +152,11 @@ static int __init orangefs_init(void) + goto out; + } + +- orangefs_sysfs_exit(); +- +-cleanup_device: + orangefs_dev_cleanup(); + ++cleanup_sysfs: ++ orangefs_sysfs_exit(); ++ + sysfs_init_failed: + orangefs_debugfs_cleanup(); + +-- +2.35.1 + diff --git a/queue-5.15/overflow-implement-size_t-saturating-arithmetic-help.patch b/queue-5.15/overflow-implement-size_t-saturating-arithmetic-help.patch new file mode 100644 index 00000000000..ff5bc236b97 --- /dev/null +++ b/queue-5.15/overflow-implement-size_t-saturating-arithmetic-help.patch @@ -0,0 +1,377 @@ +From 5f514cbb5d5a485fdcd4ad9754e7aefc93138bcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Sep 2021 15:17:53 -0700 +Subject: overflow: Implement size_t saturating arithmetic helpers + +From: Kees Cook + +[ Upstream commit e1be43d9b5d0d1310dbd90185a8e5c7145dde40f ] + +In order to perform more open-coded replacements of common allocation +size arithmetic, the kernel needs saturating (SIZE_MAX) helpers for +multiplication, addition, and subtraction. For example, it is common in +allocators, especially on realloc, to add to an existing size: + + p = krealloc(map->patch, + sizeof(struct reg_sequence) * (map->patch_regs + num_regs), + GFP_KERNEL); + +There is no existing saturating replacement for this calculation, and +just leaving the addition open coded inside array_size() could +potentially overflow as well. For example, an overflow in an expression +for a size_t argument might wrap to zero: + + array_size(anything, something_at_size_max + 1) == 0 + +Introduce size_mul(), size_add(), and size_sub() helpers that +implicitly promote arguments to size_t and saturated calculations for +use in allocations. With these helpers it is also possible to redefine +array_size(), array3_size(), flex_array_size(), and struct_size() in +terms of the new helpers. + +As with the check_*_overflow() helpers, the new helpers use __must_check, +though what is really desired is a way to make sure that assignment is +only to a size_t lvalue. Without this, it's still possible to introduce +overflow/underflow via type conversion (i.e. from size_t to int). +Enforcing this will currently need to be left to static analysis or +future use of -Wconversion. + +Additionally update the overflow unit tests to force runtime evaluation +for the pathological cases. + +Cc: Rasmus Villemoes +Cc: Gustavo A. R. Silva +Cc: Nathan Chancellor +Cc: Jason Gunthorpe +Cc: Nick Desaulniers +Cc: Leon Romanovsky +Cc: Keith Busch +Cc: Len Baker +Signed-off-by: Kees Cook +Stable-dep-of: e001e6086939 ("fs/ntfs3: Harden against integer overflows") +Signed-off-by: Sasha Levin +--- + Documentation/process/deprecated.rst | 20 ++++- + include/linux/overflow.h | 110 +++++++++++++++++---------- + lib/test_overflow.c | 98 ++++++++++++++++++++++++ + 3 files changed, 184 insertions(+), 44 deletions(-) + +diff --git a/Documentation/process/deprecated.rst b/Documentation/process/deprecated.rst +index 8ced754a5a0f..f3484f60eae5 100644 +--- a/Documentation/process/deprecated.rst ++++ b/Documentation/process/deprecated.rst +@@ -70,6 +70,9 @@ Instead, the 2-factor form of the allocator should be used:: + + foo = kmalloc_array(count, size, GFP_KERNEL); + ++Specifically, kmalloc() can be replaced with kmalloc_array(), and ++kzalloc() can be replaced with kcalloc(). ++ + If no 2-factor form is available, the saturate-on-overflow helpers should + be used:: + +@@ -90,9 +93,20 @@ Instead, use the helper:: + array usage and switch to a `flexible array member + <#zero-length-and-one-element-arrays>`_ instead. + +-See array_size(), array3_size(), and struct_size(), +-for more details as well as the related check_add_overflow() and +-check_mul_overflow() family of functions. ++For other calculations, please compose the use of the size_mul(), ++size_add(), and size_sub() helpers. For example, in the case of:: ++ ++ foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); ++ ++Instead, use the helpers:: ++ ++ foo = krealloc(size_add(current_size, ++ size_mul(chunk_size, ++ size_sub(count, 3))), GFP_KERNEL); ++ ++For more details, also see array3_size() and flex_array_size(), ++as well as the related check_mul_overflow(), check_add_overflow(), ++check_sub_overflow(), and check_shl_overflow() family of functions. + + simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() + ---------------------------------------------------------------------- +diff --git a/include/linux/overflow.h b/include/linux/overflow.h +index 4669632bd72b..59d7228104d0 100644 +--- a/include/linux/overflow.h ++++ b/include/linux/overflow.h +@@ -118,81 +118,94 @@ static inline bool __must_check __must_check_overflow(bool overflow) + })) + + /** +- * array_size() - Calculate size of 2-dimensional array. +- * +- * @a: dimension one +- * @b: dimension two ++ * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX + * +- * Calculates size of 2-dimensional array: @a * @b. ++ * @factor1: first factor ++ * @factor2: second factor + * +- * Returns: number of bytes needed to represent the array or SIZE_MAX on +- * overflow. ++ * Returns: calculate @factor1 * @factor2, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. The ++ * lvalue must be size_t to avoid implicit type conversion. + */ +-static inline __must_check size_t array_size(size_t a, size_t b) ++static inline size_t __must_check size_mul(size_t factor1, size_t factor2) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &bytes)) ++ if (check_mul_overflow(factor1, factor2, &bytes)) + return SIZE_MAX; + + return bytes; + } + + /** +- * array3_size() - Calculate size of 3-dimensional array. ++ * size_add() - Calculate size_t addition with saturation at SIZE_MAX + * +- * @a: dimension one +- * @b: dimension two +- * @c: dimension three +- * +- * Calculates size of 3-dimensional array: @a * @b * @c. ++ * @addend1: first addend ++ * @addend2: second addend + * +- * Returns: number of bytes needed to represent the array or SIZE_MAX on +- * overflow. ++ * Returns: calculate @addend1 + @addend2, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. The ++ * lvalue must be size_t to avoid implicit type conversion. + */ +-static inline __must_check size_t array3_size(size_t a, size_t b, size_t c) ++static inline size_t __must_check size_add(size_t addend1, size_t addend2) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &bytes)) +- return SIZE_MAX; +- if (check_mul_overflow(bytes, c, &bytes)) ++ if (check_add_overflow(addend1, addend2, &bytes)) + return SIZE_MAX; + + return bytes; + } + +-/* +- * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for +- * struct_size() below. ++/** ++ * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX ++ * ++ * @minuend: value to subtract from ++ * @subtrahend: value to subtract from @minuend ++ * ++ * Returns: calculate @minuend - @subtrahend, both promoted to size_t, ++ * with any overflow causing the return value to be SIZE_MAX. For ++ * composition with the size_add() and size_mul() helpers, neither ++ * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX). ++ * The lvalue must be size_t to avoid implicit type conversion. + */ +-static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c) ++static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) + { + size_t bytes; + +- if (check_mul_overflow(a, b, &bytes)) +- return SIZE_MAX; +- if (check_add_overflow(bytes, c, &bytes)) ++ if (minuend == SIZE_MAX || subtrahend == SIZE_MAX || ++ check_sub_overflow(minuend, subtrahend, &bytes)) + return SIZE_MAX; + + return bytes; + } + + /** +- * struct_size() - Calculate size of structure with trailing array. +- * @p: Pointer to the structure. +- * @member: Name of the array member. +- * @count: Number of elements in the array. ++ * array_size() - Calculate size of 2-dimensional array. + * +- * Calculates size of memory needed for structure @p followed by an +- * array of @count number of @member elements. ++ * @a: dimension one ++ * @b: dimension two + * +- * Return: number of bytes needed or SIZE_MAX on overflow. ++ * Calculates size of 2-dimensional array: @a * @b. ++ * ++ * Returns: number of bytes needed to represent the array or SIZE_MAX on ++ * overflow. + */ +-#define struct_size(p, member, count) \ +- __ab_c_size(count, \ +- sizeof(*(p)->member) + __must_be_array((p)->member),\ +- sizeof(*(p))) ++#define array_size(a, b) size_mul(a, b) ++ ++/** ++ * array3_size() - Calculate size of 3-dimensional array. ++ * ++ * @a: dimension one ++ * @b: dimension two ++ * @c: dimension three ++ * ++ * Calculates size of 3-dimensional array: @a * @b * @c. ++ * ++ * Returns: number of bytes needed to represent the array or SIZE_MAX on ++ * overflow. ++ */ ++#define array3_size(a, b, c) size_mul(size_mul(a, b), c) + + /** + * flex_array_size() - Calculate size of a flexible array member +@@ -208,7 +221,22 @@ static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c) + * Return: number of bytes needed or SIZE_MAX on overflow. + */ + #define flex_array_size(p, member, count) \ +- array_size(count, \ +- sizeof(*(p)->member) + __must_be_array((p)->member)) ++ size_mul(count, \ ++ sizeof(*(p)->member) + __must_be_array((p)->member)) ++ ++/** ++ * struct_size() - Calculate size of structure with trailing flexible array. ++ * ++ * @p: Pointer to the structure. ++ * @member: Name of the array member. ++ * @count: Number of elements in the array. ++ * ++ * Calculates size of memory needed for structure @p followed by an ++ * array of @count number of @member elements. ++ * ++ * Return: number of bytes needed or SIZE_MAX on overflow. ++ */ ++#define struct_size(p, member, count) \ ++ size_add(sizeof(*(p)), flex_array_size(p, member, count)) + + #endif /* __LINUX_OVERFLOW_H */ +diff --git a/lib/test_overflow.c b/lib/test_overflow.c +index 7a4b6f6c5473..7a5a5738d2d2 100644 +--- a/lib/test_overflow.c ++++ b/lib/test_overflow.c +@@ -588,12 +588,110 @@ static int __init test_overflow_allocation(void) + return err; + } + ++struct __test_flex_array { ++ unsigned long flags; ++ size_t count; ++ unsigned long data[]; ++}; ++ ++static int __init test_overflow_size_helpers(void) ++{ ++ struct __test_flex_array *obj; ++ int count = 0; ++ int err = 0; ++ int var; ++ ++#define check_one_size_helper(expected, func, args...) ({ \ ++ bool __failure = false; \ ++ size_t _r; \ ++ \ ++ _r = func(args); \ ++ if (_r != (expected)) { \ ++ pr_warn("expected " #func "(" #args ") " \ ++ "to return %zu but got %zu instead\n", \ ++ (size_t)(expected), _r); \ ++ __failure = true; \ ++ } \ ++ count++; \ ++ __failure; \ ++}) ++ ++ var = 4; ++ err |= check_one_size_helper(20, size_mul, var++, 5); ++ err |= check_one_size_helper(20, size_mul, 4, var++); ++ err |= check_one_size_helper(0, size_mul, 0, 3); ++ err |= check_one_size_helper(0, size_mul, 3, 0); ++ err |= check_one_size_helper(6, size_mul, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 1); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_mul, SIZE_MAX, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(9, size_add, var++, 5); ++ err |= check_one_size_helper(9, size_add, 4, var++); ++ err |= check_one_size_helper(9, size_add, 9, 0); ++ err |= check_one_size_helper(9, size_add, 0, 9); ++ err |= check_one_size_helper(5, size_add, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 1); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_add, SIZE_MAX, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(1, size_sub, var--, 3); ++ err |= check_one_size_helper(1, size_sub, 4, var--); ++ err |= check_one_size_helper(1, size_sub, 3, 2); ++ err |= check_one_size_helper(9, size_sub, 9, 0); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 9, -3); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 0, 9); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 2, 3); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 0); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, SIZE_MAX, 10); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 0, SIZE_MAX); ++ err |= check_one_size_helper(SIZE_MAX, size_sub, 14, SIZE_MAX); ++ err |= check_one_size_helper(SIZE_MAX - 2, size_sub, SIZE_MAX - 1, 1); ++ err |= check_one_size_helper(SIZE_MAX - 4, size_sub, SIZE_MAX - 1, 3); ++ err |= check_one_size_helper(1, size_sub, SIZE_MAX - 1, -3); ++ ++ var = 4; ++ err |= check_one_size_helper(4 * sizeof(*obj->data), ++ flex_array_size, obj, data, var++); ++ err |= check_one_size_helper(5 * sizeof(*obj->data), ++ flex_array_size, obj, data, var++); ++ err |= check_one_size_helper(0, flex_array_size, obj, data, 0); ++ err |= check_one_size_helper(sizeof(*obj->data), ++ flex_array_size, obj, data, 1); ++ err |= check_one_size_helper(7 * sizeof(*obj->data), ++ flex_array_size, obj, data, 7); ++ err |= check_one_size_helper(SIZE_MAX, ++ flex_array_size, obj, data, -1); ++ err |= check_one_size_helper(SIZE_MAX, ++ flex_array_size, obj, data, SIZE_MAX - 4); ++ ++ var = 4; ++ err |= check_one_size_helper(sizeof(*obj) + (4 * sizeof(*obj->data)), ++ struct_size, obj, data, var++); ++ err |= check_one_size_helper(sizeof(*obj) + (5 * sizeof(*obj->data)), ++ struct_size, obj, data, var++); ++ err |= check_one_size_helper(sizeof(*obj), struct_size, obj, data, 0); ++ err |= check_one_size_helper(sizeof(*obj) + sizeof(*obj->data), ++ struct_size, obj, data, 1); ++ err |= check_one_size_helper(SIZE_MAX, ++ struct_size, obj, data, -3); ++ err |= check_one_size_helper(SIZE_MAX, ++ struct_size, obj, data, SIZE_MAX - 3); ++ ++ pr_info("%d overflow size helper tests finished\n", count); ++ ++ return err; ++} ++ + static int __init test_module_init(void) + { + int err = 0; + + err |= test_overflow_calculation(); + err |= test_overflow_shift(); ++ err |= test_overflow_size_helpers(); + err |= test_overflow_allocation(); + + if (err) { +-- +2.35.1 + diff --git a/queue-5.15/ovl-remove-privs-in-ovl_copyfile.patch b/queue-5.15/ovl-remove-privs-in-ovl_copyfile.patch new file mode 100644 index 00000000000..1472f49109f --- /dev/null +++ b/queue-5.15/ovl-remove-privs-in-ovl_copyfile.patch @@ -0,0 +1,66 @@ +From fc3f12aae31fa57fbf1508866b62110e06b07f13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 17:06:38 +0200 +Subject: ovl: remove privs in ovl_copyfile() + +From: Amir Goldstein + +[ Upstream commit b306e90ffabdaa7e3b3350dbcd19b7663e71ab17 ] + +Underlying fs doesn't remove privs because copy_range/remap_range are +called with privileged mounter credentials. + +This fixes some failures in fstest generic/673. + +Fixes: 8ede205541ff ("ovl: add reflink/copyfile/dedup support") +Acked-by: Miklos Szeredi +Signed-off-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/file.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index 535da9eb4d8b..b56e1f7a8c62 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -566,14 +566,23 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + const struct cred *old_cred; + loff_t ret; + ++ inode_lock(inode_out); ++ if (op != OVL_DEDUPE) { ++ /* Update mode */ ++ ovl_copyattr(inode_out); ++ ret = file_remove_privs(file_out); ++ if (ret) ++ goto out_unlock; ++ } ++ + ret = ovl_real_fdget(file_out, &real_out); + if (ret) +- return ret; ++ goto out_unlock; + + ret = ovl_real_fdget(file_in, &real_in); + if (ret) { + fdput(real_out); +- return ret; ++ goto out_unlock; + } + + old_cred = ovl_override_creds(file_inode(file_out)->i_sb); +@@ -602,6 +611,9 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + fdput(real_in); + fdput(real_out); + ++out_unlock: ++ inode_unlock(inode_out); ++ + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/ovl-remove-privs-in-ovl_fallocate.patch b/queue-5.15/ovl-remove-privs-in-ovl_fallocate.patch new file mode 100644 index 00000000000..142e95b81ea --- /dev/null +++ b/queue-5.15/ovl-remove-privs-in-ovl_fallocate.patch @@ -0,0 +1,58 @@ +From 864c21b0280e80c2a4217b16107b9152600edf6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 17:06:39 +0200 +Subject: ovl: remove privs in ovl_fallocate() + +From: Amir Goldstein + +[ Upstream commit 23a8ce16419a3066829ad4a8b7032a75817af65b ] + +Underlying fs doesn't remove privs because fallocate is called with +privileged mounter credentials. + +This fixes some failure in fstests generic/683..687. + +Fixes: aab8848cee5e ("ovl: add ovl_fallocate()") +Acked-by: Miklos Szeredi +Signed-off-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/file.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index b56e1f7a8c62..28cb05ef018c 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -516,9 +516,16 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len + const struct cred *old_cred; + int ret; + ++ inode_lock(inode); ++ /* Update mode */ ++ ovl_copyattr(inode); ++ ret = file_remove_privs(file); ++ if (ret) ++ goto out_unlock; ++ + ret = ovl_real_fdget(file, &real); + if (ret) +- return ret; ++ goto out_unlock; + + old_cred = ovl_override_creds(file_inode(file)->i_sb); + ret = vfs_fallocate(real.file, mode, offset, len); +@@ -529,6 +536,9 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len + + fdput(real); + ++out_unlock: ++ inode_unlock(inode); ++ + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/ovl-store-lower-path-in-ovl_inode.patch b/queue-5.15/ovl-store-lower-path-in-ovl_inode.patch new file mode 100644 index 00000000000..3f62b1250a8 --- /dev/null +++ b/queue-5.15/ovl-store-lower-path-in-ovl_inode.patch @@ -0,0 +1,148 @@ +From 7677c886f947bb705cda030e328b113f43fdb736 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 12:51:53 +0200 +Subject: ovl: store lower path in ovl_inode + +From: Amir Goldstein + +[ Upstream commit ffa5723c6d259b3191f851a50a98d0352b345b39 ] + +Create some ovl_i_* helpers to get real path from ovl inode. Instead of +just stashing struct inode for the lower layer we stash struct path for +the lower layer. The helpers allow to retrieve a struct path for the +relevant upper or lower layer. This will be used when retrieving +information based on struct inode when copying up inode attributes from +upper or lower inodes to ovl inodes and when checking permissions in +ovl_permission() in following patches. This is needed to support +idmapped base layers with overlay. + +Cc: +Tested-by: Giuseppe Scrivano +Reviewed-by: Christian Brauner (Microsoft) +Signed-off-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Miklos Szeredi +Stable-dep-of: b306e90ffabd ("ovl: remove privs in ovl_copyfile()") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/inode.c | 11 +++++++---- + fs/overlayfs/overlayfs.h | 2 ++ + fs/overlayfs/ovl_entry.h | 2 +- + fs/overlayfs/super.c | 5 +++-- + fs/overlayfs/util.c | 15 ++++++++++++++- + 5 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index 1f36158c7dbe..06479bc88b7e 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -777,13 +777,16 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip, + unsigned long ino, int fsid) + { + struct inode *realinode; ++ struct ovl_inode *oi = OVL_I(inode); + + if (oip->upperdentry) +- OVL_I(inode)->__upperdentry = oip->upperdentry; +- if (oip->lowerpath && oip->lowerpath->dentry) +- OVL_I(inode)->lower = igrab(d_inode(oip->lowerpath->dentry)); ++ oi->__upperdentry = oip->upperdentry; ++ if (oip->lowerpath && oip->lowerpath->dentry) { ++ oi->lowerpath.dentry = dget(oip->lowerpath->dentry); ++ oi->lowerpath.layer = oip->lowerpath->layer; ++ } + if (oip->lowerdata) +- OVL_I(inode)->lowerdata = igrab(d_inode(oip->lowerdata)); ++ oi->lowerdata = igrab(d_inode(oip->lowerdata)); + + realinode = ovl_inode_real(inode); + ovl_copyattr(realinode, inode); +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 2cd5741c873b..27f221962665 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -293,10 +293,12 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry); + void ovl_path_upper(struct dentry *dentry, struct path *path); + void ovl_path_lower(struct dentry *dentry, struct path *path); + void ovl_path_lowerdata(struct dentry *dentry, struct path *path); ++void ovl_i_path_real(struct inode *inode, struct path *path); + enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); + struct dentry *ovl_dentry_upper(struct dentry *dentry); + struct dentry *ovl_dentry_lower(struct dentry *dentry); + struct dentry *ovl_dentry_lowerdata(struct dentry *dentry); ++const struct ovl_layer *ovl_i_layer_lower(struct inode *inode); + const struct ovl_layer *ovl_layer_lower(struct dentry *dentry); + struct dentry *ovl_dentry_real(struct dentry *dentry); + struct dentry *ovl_i_dentry_upper(struct inode *inode); +diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h +index 63efee554f69..b2d64f3c974b 100644 +--- a/fs/overlayfs/ovl_entry.h ++++ b/fs/overlayfs/ovl_entry.h +@@ -129,7 +129,7 @@ struct ovl_inode { + unsigned long flags; + struct inode vfs_inode; + struct dentry *__upperdentry; +- struct inode *lower; ++ struct ovl_path lowerpath; + + /* synchronize copy up and more */ + struct mutex lock; +diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c +index 9837aaf9caf1..e2ed38c5f721 100644 +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -184,7 +184,8 @@ static struct inode *ovl_alloc_inode(struct super_block *sb) + oi->version = 0; + oi->flags = 0; + oi->__upperdentry = NULL; +- oi->lower = NULL; ++ oi->lowerpath.dentry = NULL; ++ oi->lowerpath.layer = NULL; + oi->lowerdata = NULL; + mutex_init(&oi->lock); + +@@ -205,7 +206,7 @@ static void ovl_destroy_inode(struct inode *inode) + struct ovl_inode *oi = OVL_I(inode); + + dput(oi->__upperdentry); +- iput(oi->lower); ++ dput(oi->lowerpath.dentry); + if (S_ISDIR(inode->i_mode)) + ovl_dir_cache_free(inode); + else +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index f48284a2a896..2567918dc684 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -236,6 +236,17 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode) + return ovl_upperdentry_dereference(OVL_I(inode)); + } + ++void ovl_i_path_real(struct inode *inode, struct path *path) ++{ ++ path->dentry = ovl_i_dentry_upper(inode); ++ if (!path->dentry) { ++ path->dentry = OVL_I(inode)->lowerpath.dentry; ++ path->mnt = OVL_I(inode)->lowerpath.layer->mnt; ++ } else { ++ path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb)); ++ } ++} ++ + struct inode *ovl_inode_upper(struct inode *inode) + { + struct dentry *upperdentry = ovl_i_dentry_upper(inode); +@@ -245,7 +256,9 @@ struct inode *ovl_inode_upper(struct inode *inode) + + struct inode *ovl_inode_lower(struct inode *inode) + { +- return OVL_I(inode)->lower; ++ struct dentry *lowerdentry = OVL_I(inode)->lowerpath.dentry; ++ ++ return lowerdentry ? d_inode(lowerdentry) : NULL; + } + + struct inode *ovl_inode_real(struct inode *inode) +-- +2.35.1 + diff --git a/queue-5.15/ovl-use-ovl_copy_-real-upper-attr-wrappers.patch b/queue-5.15/ovl-use-ovl_copy_-real-upper-attr-wrappers.patch new file mode 100644 index 00000000000..39cd9c49433 --- /dev/null +++ b/queue-5.15/ovl-use-ovl_copy_-real-upper-attr-wrappers.patch @@ -0,0 +1,263 @@ +From 2fa8f9143d3b5a4dc5df0cea5edde2a8cd4191a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 12:51:54 +0200 +Subject: ovl: use ovl_copy_{real,upper}attr() wrappers + +From: Christian Brauner + +[ Upstream commit 2878dffc7db0b5a51e308ccb6b571296b57c82e7 ] + +When copying inode attributes from the upper or lower layer to ovl inodes +we need to take the upper or lower layer's mount's idmapping into +account. In a lot of places we call ovl_copyattr() only on upper inodes and +in some we call it on either upper or lower inodes. Split this into two +separate helpers. + +The first one should only be called on upper +inodes and is thus called ovl_copy_upperattr(). The second one can be +called on upper or lower inodes. We add ovl_copy_realattr() for this +task. The new helper makes use of the previously added ovl_i_path_real() +helper. This is needed to support idmapped base layers with overlay. + +When overlay copies the inode information from an upper or lower layer +to the relevant overlay inode it will apply the idmapping of the upper +or lower layer when doing so. The ovl inode ownership will thus always +correctly reflect the ownership of the idmapped upper or lower layer. + +All idmapping helpers are nops when no idmapped base layers are used. + +Cc: +Tested-by: Giuseppe Scrivano +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner (Microsoft) +Signed-off-by: Miklos Szeredi +Stable-dep-of: b306e90ffabd ("ovl: remove privs in ovl_copyfile()") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/dir.c | 10 ++++------ + fs/overlayfs/file.c | 15 +++++++-------- + fs/overlayfs/inode.c | 8 ++++---- + fs/overlayfs/overlayfs.h | 11 +---------- + fs/overlayfs/util.c | 32 +++++++++++++++++++++++++++++++- + 5 files changed, 47 insertions(+), 29 deletions(-) + +diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c +index f18490813170..3fc86c51e260 100644 +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -880,7 +880,6 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) + { + int err; + const struct cred *old_cred; +- struct dentry *upperdentry; + bool lower_positive = ovl_lower_positive(dentry); + LIST_HEAD(list); + +@@ -923,9 +922,8 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir) + * Note: we fail to update ctime if there was no copy-up, only a + * whiteout + */ +- upperdentry = ovl_dentry_upper(dentry); +- if (upperdentry) +- ovl_copyattr(d_inode(upperdentry), d_inode(dentry)); ++ if (ovl_dentry_upper(dentry)) ++ ovl_copyattr(d_inode(dentry)); + + out_drop_write: + ovl_drop_write(dentry); +@@ -1272,9 +1270,9 @@ static int ovl_rename(struct user_namespace *mnt_userns, struct inode *olddir, + (d_inode(new) && ovl_type_origin(new))); + + /* copy ctime: */ +- ovl_copyattr(d_inode(olddentry), d_inode(old)); ++ ovl_copyattr(d_inode(old)); + if (d_inode(new) && ovl_dentry_upper(new)) +- ovl_copyattr(d_inode(newdentry), d_inode(new)); ++ ovl_copyattr(d_inode(new)); + + out_dput: + dput(newdentry); +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index 44fea16751f1..535da9eb4d8b 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -273,7 +273,7 @@ static void ovl_aio_cleanup_handler(struct ovl_aio_req *aio_req) + __sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb, + SB_FREEZE_WRITE); + file_end_write(iocb->ki_filp); +- ovl_copyattr(ovl_inode_real(inode), inode); ++ ovl_copyattr(inode); + } + + orig_iocb->ki_pos = iocb->ki_pos; +@@ -356,7 +356,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) + + inode_lock(inode); + /* Update mode */ +- ovl_copyattr(ovl_inode_real(inode), inode); ++ ovl_copyattr(inode); + ret = file_remove_privs(file); + if (ret) + goto out_unlock; +@@ -381,7 +381,7 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) + ovl_iocb_to_rwf(ifl)); + file_end_write(real.file); + /* Update size */ +- ovl_copyattr(ovl_inode_real(inode), inode); ++ ovl_copyattr(inode); + } else { + struct ovl_aio_req *aio_req; + +@@ -431,12 +431,11 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, + struct fd real; + const struct cred *old_cred; + struct inode *inode = file_inode(out); +- struct inode *realinode = ovl_inode_real(inode); + ssize_t ret; + + inode_lock(inode); + /* Update mode */ +- ovl_copyattr(realinode, inode); ++ ovl_copyattr(inode); + ret = file_remove_privs(out); + if (ret) + goto out_unlock; +@@ -452,7 +451,7 @@ static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out, + + file_end_write(real.file); + /* Update size */ +- ovl_copyattr(realinode, inode); ++ ovl_copyattr(inode); + revert_creds(old_cred); + fdput(real); + +@@ -526,7 +525,7 @@ static long ovl_fallocate(struct file *file, int mode, loff_t offset, loff_t len + revert_creds(old_cred); + + /* Update size */ +- ovl_copyattr(ovl_inode_real(inode), inode); ++ ovl_copyattr(inode); + + fdput(real); + +@@ -598,7 +597,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + revert_creds(old_cred); + + /* Update size */ +- ovl_copyattr(ovl_inode_real(inode_out), inode_out); ++ ovl_copyattr(inode_out); + + fdput(real_in); + fdput(real_out); +diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c +index 06479bc88b7e..d41f0c8e0e2a 100644 +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -80,7 +80,7 @@ int ovl_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, + err = notify_change(&init_user_ns, upperdentry, attr, NULL); + revert_creds(old_cred); + if (!err) +- ovl_copyattr(upperdentry->d_inode, dentry->d_inode); ++ ovl_copyattr(dentry->d_inode); + inode_unlock(upperdentry->d_inode); + + if (winode) +@@ -377,7 +377,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, + revert_creds(old_cred); + + /* copy c/mtime */ +- ovl_copyattr(d_inode(realdentry), inode); ++ ovl_copyattr(inode); + + out_drop_write: + ovl_drop_write(dentry); +@@ -579,7 +579,7 @@ int ovl_fileattr_set(struct user_namespace *mnt_userns, + inode_set_flags(inode, flags, OVL_COPY_I_FLAGS_MASK); + + /* Update ctime */ +- ovl_copyattr(ovl_inode_real(inode), inode); ++ ovl_copyattr(inode); + } + ovl_drop_write(dentry); + out: +@@ -789,7 +789,7 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip, + oi->lowerdata = igrab(d_inode(oip->lowerdata)); + + realinode = ovl_inode_real(inode); +- ovl_copyattr(realinode, inode); ++ ovl_copyattr(inode); + ovl_copyflags(realinode, inode); + ovl_map_ino(inode, ino, fsid); + } +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index 27f221962665..2df3e74cdf0f 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -522,16 +522,7 @@ bool ovl_lookup_trap_inode(struct super_block *sb, struct dentry *dir); + struct inode *ovl_get_trap_inode(struct super_block *sb, struct dentry *dir); + struct inode *ovl_get_inode(struct super_block *sb, + struct ovl_inode_params *oip); +-static inline void ovl_copyattr(struct inode *from, struct inode *to) +-{ +- to->i_uid = from->i_uid; +- to->i_gid = from->i_gid; +- to->i_mode = from->i_mode; +- to->i_atime = from->i_atime; +- to->i_mtime = from->i_mtime; +- to->i_ctime = from->i_ctime; +- i_size_write(to, i_size_read(from)); +-} ++void ovl_copyattr(struct inode *to); + + /* vfs inode flags copied from real to ovl inode */ + #define OVL_COPY_I_FLAGS_MASK (S_SYNC | S_NOATIME | S_APPEND | S_IMMUTABLE) +diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c +index 2567918dc684..9d33ce385bef 100644 +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -456,7 +456,7 @@ static void ovl_dir_version_inc(struct dentry *dentry, bool impurity) + void ovl_dir_modified(struct dentry *dentry, bool impurity) + { + /* Copy mtime/ctime */ +- ovl_copyattr(d_inode(ovl_dentry_upper(dentry)), d_inode(dentry)); ++ ovl_copyattr(d_inode(dentry)); + + ovl_dir_version_inc(dentry, impurity); + } +@@ -1073,3 +1073,33 @@ int ovl_sync_status(struct ovl_fs *ofs) + + return errseq_check(&mnt->mnt_sb->s_wb_err, ofs->errseq); + } ++ ++/* ++ * ovl_copyattr() - copy inode attributes from layer to ovl inode ++ * ++ * When overlay copies inode information from an upper or lower layer to the ++ * relevant overlay inode it will apply the idmapping of the upper or lower ++ * layer when doing so ensuring that the ovl inode ownership will correctly ++ * reflect the ownership of the idmapped upper or lower layer. For example, an ++ * idmapped upper or lower layer mapping id 1001 to id 1000 will take care to ++ * map any lower or upper inode owned by id 1001 to id 1000. These mapping ++ * helpers are nops when the relevant layer isn't idmapped. ++ */ ++void ovl_copyattr(struct inode *inode) ++{ ++ struct path realpath; ++ struct inode *realinode; ++ struct user_namespace *real_mnt_userns; ++ ++ ovl_i_path_real(inode, &realpath); ++ realinode = d_inode(realpath.dentry); ++ real_mnt_userns = mnt_user_ns(realpath.mnt); ++ ++ inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode); ++ inode->i_gid = i_gid_into_mnt(real_mnt_userns, realinode); ++ inode->i_mode = realinode->i_mode; ++ inode->i_atime = realinode->i_atime; ++ inode->i_mtime = realinode->i_mtime; ++ inode->i_ctime = realinode->i_ctime; ++ i_size_write(inode, i_size_read(realinode)); ++} +-- +2.35.1 + diff --git a/queue-5.15/padata-always-leave-bhs-disabled-when-running-parall.patch b/queue-5.15/padata-always-leave-bhs-disabled-when-running-parall.patch new file mode 100644 index 00000000000..7beb47635ee --- /dev/null +++ b/queue-5.15/padata-always-leave-bhs-disabled-when-running-parall.patch @@ -0,0 +1,65 @@ +From 857f2cb25e7985bffab80634c31355b05c8ffbaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 20:28:02 -0500 +Subject: padata: Always leave BHs disabled when running ->parallel() + +From: Daniel Jordan + +[ Upstream commit 34c3a47d20ae55b3600fed733bf96eafe9c500d5 ] + +A deadlock can happen when an overloaded system runs ->parallel() in the +context of the current task: + + padata_do_parallel + ->parallel() + pcrypt_aead_enc/dec + padata_do_serial + spin_lock(&reorder->lock) // BHs still enabled + + ... + __do_softirq + ... + padata_do_serial + spin_lock(&reorder->lock) + +It's a bug for BHs to be on in _do_serial as Steffen points out, so +ensure they're off in the "current task" case like they are in +padata_parallel_worker to avoid this situation. + +Reported-by: syzbot+bc05445bc14148d51915@syzkaller.appspotmail.com +Fixes: 4611ce224688 ("padata: allocate work structures for parallel jobs from a pool") +Signed-off-by: Daniel Jordan +Acked-by: Steffen Klassert +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + kernel/padata.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/kernel/padata.c b/kernel/padata.c +index 18d3a5c699d8..9395b77fabb1 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -207,14 +207,16 @@ int padata_do_parallel(struct padata_shell *ps, + pw = padata_work_alloc(); + spin_unlock(&padata_works_lock); + ++ if (!pw) { ++ /* Maximum works limit exceeded, run in the current task. */ ++ padata->parallel(padata); ++ } ++ + rcu_read_unlock_bh(); + + if (pw) { + padata_work_init(pw, padata_parallel_worker, padata, 0); + queue_work(pinst->parallel_wq, &pw->pw_work); +- } else { +- /* Maximum works limit exceeded, run in the current task. */ +- padata->parallel(padata); + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/padata-fix-list-iterator-in-padata_do_serial.patch b/queue-5.15/padata-fix-list-iterator-in-padata_do_serial.patch new file mode 100644 index 00000000000..373a2c29118 --- /dev/null +++ b/queue-5.15/padata-fix-list-iterator-in-padata_do_serial.patch @@ -0,0 +1,51 @@ +From cf669ad51d22c4c6fa17840bb317bbba93142600 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Nov 2022 20:28:04 -0500 +Subject: padata: Fix list iterator in padata_do_serial() + +From: Daniel Jordan + +[ Upstream commit 57ddfecc72a6c9941d159543e1c0c0a74fe9afdd ] + +list_for_each_entry_reverse() assumes that the iterated list is nonempty +and that every list_head is embedded in the same type, but its use in +padata_do_serial() breaks both rules. + +This doesn't cause any issues now because padata_priv and padata_list +happen to have their list fields at the same offset, but we really +shouldn't be relying on that. + +Fixes: bfde23ce200e ("padata: unbind parallel jobs from specific CPUs") +Signed-off-by: Daniel Jordan +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + kernel/padata.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/kernel/padata.c b/kernel/padata.c +index 9395b77fabb1..c17f772cc315 100644 +--- a/kernel/padata.c ++++ b/kernel/padata.c +@@ -390,13 +390,16 @@ void padata_do_serial(struct padata_priv *padata) + int hashed_cpu = padata_cpu_hash(pd, padata->seq_nr); + struct padata_list *reorder = per_cpu_ptr(pd->reorder_list, hashed_cpu); + struct padata_priv *cur; ++ struct list_head *pos; + + spin_lock(&reorder->lock); + /* Sort in ascending order of sequence number. */ +- list_for_each_entry_reverse(cur, &reorder->list, list) ++ list_for_each_prev(pos, &reorder->list) { ++ cur = list_entry(pos, struct padata_priv, list); + if (cur->seq_nr < padata->seq_nr) + break; +- list_add(&padata->list, &cur->list); ++ } ++ list_add(&padata->list, pos); + spin_unlock(&reorder->lock); + + /* +-- +2.35.1 + diff --git a/queue-5.15/pci-check-for-alloc-failure-in-pci_request_irq.patch b/queue-5.15/pci-check-for-alloc-failure-in-pci_request_irq.patch new file mode 100644 index 00000000000..1374fc84685 --- /dev/null +++ b/queue-5.15/pci-check-for-alloc-failure-in-pci_request_irq.patch @@ -0,0 +1,39 @@ +From 538643917a462ee806a16449fc15818aa442491d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 10:00:29 +0800 +Subject: PCI: Check for alloc failure in pci_request_irq() + +From: Zeng Heng + +[ Upstream commit 2d9cd957d40c3ac491b358e7cff0515bb07a3a9c ] + +When kvasprintf() fails to allocate memory, it returns a NULL pointer. +Return error from pci_request_irq() so we don't dereference it. + +[bhelgaas: commit log] +Fixes: 704e8953d3e9 ("PCI/irq: Add pci_request_irq() and pci_free_irq() helpers") +Link: https://lore.kernel.org/r/20221121020029.3759444-1-zengheng4@huawei.com +Signed-off-by: Zeng Heng +Signed-off-by: Bjorn Helgaas +Reviewed-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/pci/irq.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c +index 12ecd0aaa28d..0050e8f6814e 100644 +--- a/drivers/pci/irq.c ++++ b/drivers/pci/irq.c +@@ -44,6 +44,8 @@ int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler, + va_start(ap, fmt); + devname = kvasprintf(GFP_KERNEL, fmt, ap); + va_end(ap); ++ if (!devname) ++ return -ENOMEM; + + ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn, + irqflags, devname, dev_id); +-- +2.35.1 + diff --git a/queue-5.15/pci-dwc-fix-n_fts-array-overrun.patch b/queue-5.15/pci-dwc-fix-n_fts-array-overrun.patch new file mode 100644 index 00000000000..31448a713fd --- /dev/null +++ b/queue-5.15/pci-dwc-fix-n_fts-array-overrun.patch @@ -0,0 +1,42 @@ +From 229bc1e5af47a093d1042be5051bc4a6f9bb1db8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 16:49:23 +0530 +Subject: PCI: dwc: Fix n_fts[] array overrun + +From: Vidya Sagar + +[ Upstream commit 66110361281b2f7da0c8bd51eaf1f152f4236035 ] + +commit aeaa0bfe89654 ("PCI: dwc: Move N_FTS setup to common setup") +incorrectly uses pci->link_gen in deriving the index to the +n_fts[] array also introducing the issue of accessing beyond the +boundaries of array for greater than Gen-2 speeds. This change fixes +that issue. + +Link: https://lore.kernel.org/r/20220926111923.22487-1-vidyas@nvidia.com +Fixes: aeaa0bfe8965 ("PCI: dwc: Move N_FTS setup to common setup") +Signed-off-by: Vidya Sagar +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Jingoo Han +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/dwc/pcie-designware.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c +index e408ebf5bd73..00972a7bc976 100644 +--- a/drivers/pci/controller/dwc/pcie-designware.c ++++ b/drivers/pci/controller/dwc/pcie-designware.c +@@ -730,7 +730,7 @@ void dw_pcie_setup(struct dw_pcie *pci) + if (pci->n_fts[1]) { + val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + val &= ~PORT_LOGIC_N_FTS_MASK; +- val |= pci->n_fts[pci->link_gen - 1]; ++ val |= pci->n_fts[1]; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); + } + +-- +2.35.1 + diff --git a/queue-5.15/pci-mt7621-add-sentinel-to-quirks-table.patch b/queue-5.15/pci-mt7621-add-sentinel-to-quirks-table.patch new file mode 100644 index 00000000000..61fc2da4b50 --- /dev/null +++ b/queue-5.15/pci-mt7621-add-sentinel-to-quirks-table.patch @@ -0,0 +1,48 @@ +From 148f0633fdb43ebe2ad624b6f7c58dfaa371cd74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 06:46:45 +1000 +Subject: PCI: mt7621: Add sentinel to quirks table + +From: John Thomson + +[ Upstream commit 19098934f910b4d47cb30251dd39ffa57bef9523 ] + +Current driver is missing a sentinel in the struct soc_device_attribute +array, which causes an oops when assessed by the +soc_device_match(mt7621_pcie_quirks_match) call. + +This was only exposed once the CONFIG_SOC_MT7621 mt7621 soc_dev_attr +was fixed to register the SOC as a device, in: + +commit 7c18b64bba3b ("mips: ralink: mt7621: do not use kzalloc too early") + +Fix it by adding the required sentinel. + +Link: https://lore.kernel.org/lkml/26ebbed1-0fe9-4af9-8466-65f841d0b382@app.fastmail.com +Link: https://lore.kernel.org/r/20221205204645.301301-1-git@johnthomson.fastmail.com.au +Fixes: b483b4e4d3f6 ("staging: mt7621-pci: add quirks for 'E2' revision using 'soc_device_attribute'") +Signed-off-by: John Thomson +Signed-off-by: Lorenzo Pieralisi +Acked-by: Sergio Paracuellos +Signed-off-by: Sasha Levin +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c +index c4f57bb63482..b520d1e0edd1 100644 +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -511,7 +511,8 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host) + } + + static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { +- { .soc_id = "mt7621", .revision = "E2" } ++ { .soc_id = "mt7621", .revision = "E2" }, ++ { /* sentinel */ } + }; + + static int mt7621_pcie_probe(struct platform_device *pdev) +-- +2.35.1 + diff --git a/queue-5.15/pci-mt7621-rename-mt7621_pci_-to-mt7621_pcie_.patch b/queue-5.15/pci-mt7621-rename-mt7621_pci_-to-mt7621_pcie_.patch new file mode 100644 index 00000000000..89ebc86b4c3 --- /dev/null +++ b/queue-5.15/pci-mt7621-rename-mt7621_pci_-to-mt7621_pcie_.patch @@ -0,0 +1,148 @@ +From 739a8279455511d57d14205bd1b22a64fbd9b2d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Dec 2021 19:10:48 -0600 +Subject: PCI: mt7621: Rename mt7621_pci_ to mt7621_pcie_ + +From: Bjorn Helgaas + +[ Upstream commit 4793895f597d42eb54a0f54711b61263b6a8dd03 ] + +Rename mt7621_pci_* structs and functions to mt7621_pcie_* for consistency +with the rest of the file. + +Link: https://lore.kernel.org/r/20211223011054.1227810-18-helgaas@kernel.org +Signed-off-by: Bjorn Helgaas +Reviewed-by: Sergio Paracuellos +Cc: Matthias Brugger +Stable-dep-of: 19098934f910 ("PCI: mt7621: Add sentinel to quirks table") +Signed-off-by: Sasha Levin +--- + drivers/staging/mt7621-pci/pci-mt7621.c | 36 ++++++++++++------------- + 1 file changed, 18 insertions(+), 18 deletions(-) + +diff --git a/drivers/staging/mt7621-pci/pci-mt7621.c b/drivers/staging/mt7621-pci/pci-mt7621.c +index 6acfc94a16e7..c4f57bb63482 100644 +--- a/drivers/staging/mt7621-pci/pci-mt7621.c ++++ b/drivers/staging/mt7621-pci/pci-mt7621.c +@@ -93,8 +93,8 @@ struct mt7621_pcie_port { + * reset lines are inverted. + */ + struct mt7621_pcie { +- void __iomem *base; + struct device *dev; ++ void __iomem *base; + struct list_head ports; + bool resets_inverted; + }; +@@ -129,7 +129,7 @@ static inline void pcie_port_write(struct mt7621_pcie_port *port, + writel_relaxed(val, port->base + reg); + } + +-static inline u32 mt7621_pci_get_cfgaddr(unsigned int bus, unsigned int slot, ++static inline u32 mt7621_pcie_get_cfgaddr(unsigned int bus, unsigned int slot, + unsigned int func, unsigned int where) + { + return (((where & 0xF00) >> 8) << 24) | (bus << 16) | (slot << 11) | +@@ -140,7 +140,7 @@ static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus, + unsigned int devfn, int where) + { + struct mt7621_pcie *pcie = bus->sysdata; +- u32 address = mt7621_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), ++ u32 address = mt7621_pcie_get_cfgaddr(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where); + + writel_relaxed(address, pcie->base + RALINK_PCI_CONFIG_ADDR); +@@ -148,7 +148,7 @@ static void __iomem *mt7621_pcie_map_bus(struct pci_bus *bus, + return pcie->base + RALINK_PCI_CONFIG_DATA + (where & 3); + } + +-struct pci_ops mt7621_pci_ops = { ++struct pci_ops mt7621_pcie_ops = { + .map_bus = mt7621_pcie_map_bus, + .read = pci_generic_config_read, + .write = pci_generic_config_write, +@@ -156,7 +156,7 @@ struct pci_ops mt7621_pci_ops = { + + static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg) + { +- u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); ++ u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); + + pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); + return pcie_read(pcie, RALINK_PCI_CONFIG_DATA); +@@ -165,7 +165,7 @@ static u32 read_config(struct mt7621_pcie *pcie, unsigned int dev, u32 reg) + static void write_config(struct mt7621_pcie *pcie, unsigned int dev, + u32 reg, u32 val) + { +- u32 address = mt7621_pci_get_cfgaddr(0, dev, 0, reg); ++ u32 address = mt7621_pcie_get_cfgaddr(0, dev, 0, reg); + + pcie_write(pcie, address, RALINK_PCI_CONFIG_ADDR); + pcie_write(pcie, val, RALINK_PCI_CONFIG_DATA); +@@ -505,16 +505,16 @@ static int mt7621_pcie_register_host(struct pci_host_bridge *host) + { + struct mt7621_pcie *pcie = pci_host_bridge_priv(host); + +- host->ops = &mt7621_pci_ops; ++ host->ops = &mt7621_pcie_ops; + host->sysdata = pcie; + return pci_host_probe(host); + } + +-static const struct soc_device_attribute mt7621_pci_quirks_match[] = { ++static const struct soc_device_attribute mt7621_pcie_quirks_match[] = { + { .soc_id = "mt7621", .revision = "E2" } + }; + +-static int mt7621_pci_probe(struct platform_device *pdev) ++static int mt7621_pcie_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + const struct soc_device_attribute *attr; +@@ -535,7 +535,7 @@ static int mt7621_pci_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, pcie); + INIT_LIST_HEAD(&pcie->ports); + +- attr = soc_device_match(mt7621_pci_quirks_match); ++ attr = soc_device_match(mt7621_pcie_quirks_match); + if (attr) + pcie->resets_inverted = true; + +@@ -572,7 +572,7 @@ static int mt7621_pci_probe(struct platform_device *pdev) + return err; + } + +-static int mt7621_pci_remove(struct platform_device *pdev) ++static int mt7621_pcie_remove(struct platform_device *pdev) + { + struct mt7621_pcie *pcie = platform_get_drvdata(pdev); + struct mt7621_pcie_port *port; +@@ -583,18 +583,18 @@ static int mt7621_pci_remove(struct platform_device *pdev) + return 0; + } + +-static const struct of_device_id mt7621_pci_ids[] = { ++static const struct of_device_id mt7621_pcie_ids[] = { + { .compatible = "mediatek,mt7621-pci" }, + {}, + }; +-MODULE_DEVICE_TABLE(of, mt7621_pci_ids); ++MODULE_DEVICE_TABLE(of, mt7621_pcie_ids); + +-static struct platform_driver mt7621_pci_driver = { +- .probe = mt7621_pci_probe, +- .remove = mt7621_pci_remove, ++static struct platform_driver mt7621_pcie_driver = { ++ .probe = mt7621_pcie_probe, ++ .remove = mt7621_pcie_remove, + .driver = { + .name = "mt7621-pci", +- .of_match_table = of_match_ptr(mt7621_pci_ids), ++ .of_match_table = of_match_ptr(mt7621_pcie_ids), + }, + }; +-builtin_platform_driver(mt7621_pci_driver); ++builtin_platform_driver(mt7621_pcie_driver); +-- +2.35.1 + diff --git a/queue-5.15/pci-pci-epf-test-register-notifier-if-only-core_init.patch b/queue-5.15/pci-pci-epf-test-register-notifier-if-only-core_init.patch new file mode 100644 index 00000000000..63a9bd5dfa5 --- /dev/null +++ b/queue-5.15/pci-pci-epf-test-register-notifier-if-only-core_init.patch @@ -0,0 +1,40 @@ +From 2716c1ea1e379354420fa5aa1e9d52956f3bb53a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 18:01:01 +0900 +Subject: PCI: pci-epf-test: Register notifier if only core_init_notifier is + enabled + +From: Kunihiko Hayashi + +[ Upstream commit 6acd25cc98ce0c9ee4fefdaf44fc8bca534b26e5 ] + +The pci_epf_test_notifier function should be installed also if only +core_init_notifier is enabled. Fix the current logic. + +Link: https://lore.kernel.org/r/20220825090101.20474-1-hayashi.kunihiko@socionext.com +Fixes: 5e50ee27d4a5 ("PCI: pci-epf-test: Add support to defer core initialization") +Signed-off-by: Kunihiko Hayashi +Signed-off-by: Lorenzo Pieralisi +Acked-by: Om Prakash Singh +Acked-by: Kishon Vijay Abraham I +Signed-off-by: Sasha Levin +--- + drivers/pci/endpoint/functions/pci-epf-test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c +index a5ed779b0a51..45535d4ae644 100644 +--- a/drivers/pci/endpoint/functions/pci-epf-test.c ++++ b/drivers/pci/endpoint/functions/pci-epf-test.c +@@ -883,7 +883,7 @@ static int pci_epf_test_bind(struct pci_epf *epf) + if (ret) + epf_test->dma_supported = false; + +- if (linkup_notifier) { ++ if (linkup_notifier || core_init_notifier) { + epf->nb.notifier_call = pci_epf_test_notifier; + pci_epc_register_notifier(epc, &epf->nb); + } else { +-- +2.35.1 + diff --git a/queue-5.15/pci-vmd-disable-msi-remapping-after-suspend.patch b/queue-5.15/pci-vmd-disable-msi-remapping-after-suspend.patch new file mode 100644 index 00000000000..fe93bcb864b --- /dev/null +++ b/queue-5.15/pci-vmd-disable-msi-remapping-after-suspend.patch @@ -0,0 +1,46 @@ +From cff5cc2279a1dd6122c47b415850660cbae86eb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 07:26:52 -0700 +Subject: PCI: vmd: Disable MSI remapping after suspend + +From: Nirmal Patel + +[ Upstream commit d899aa668498c07ff217b666ae9712990306e682 ] + +MSI remapping is disabled by VMD driver for Intel's Icelake and +newer systems in order to improve performance by setting +VMCONFIG_MSI_REMAP. By design VMCONFIG_MSI_REMAP register is cleared +by firmware during boot. The same register gets cleared when system +is put in S3 power state. VMD driver needs to set this register again +in order to avoid interrupt issues with devices behind VMD if MSI +remapping was disabled before. + +Link: https://lore.kernel.org/r/20221109142652.450998-1-nirmal.patel@linux.intel.com +Fixes: ee81ee84f873 ("PCI: vmd: Disable MSI-X remapping when possible") +Signed-off-by: Nirmal Patel +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Francisco Munoz +Signed-off-by: Sasha Levin +--- + drivers/pci/controller/vmd.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c +index a5987e52700e..8dce71142e10 100644 +--- a/drivers/pci/controller/vmd.c ++++ b/drivers/pci/controller/vmd.c +@@ -900,6 +900,11 @@ static int vmd_resume(struct device *dev) + struct vmd_dev *vmd = pci_get_drvdata(pdev); + int err, i; + ++ if (vmd->irq_domain) ++ vmd_set_msi_remapping(vmd, true); ++ else ++ vmd_set_msi_remapping(vmd, false); ++ + for (i = 0; i < vmd->msix_count; i++) { + err = devm_request_irq(dev, pci_irq_vector(pdev, i), + vmd_irq, IRQF_NO_THREAD, +-- +2.35.1 + diff --git a/queue-5.15/perf-arm_dmc620-fix-hotplug-callback-leak-in-dmc620_.patch b/queue-5.15/perf-arm_dmc620-fix-hotplug-callback-leak-in-dmc620_.patch new file mode 100644 index 00000000000..7ddf06c8f5a --- /dev/null +++ b/queue-5.15/perf-arm_dmc620-fix-hotplug-callback-leak-in-dmc620_.patch @@ -0,0 +1,55 @@ +From 58860a56c4d02678e6e6d4d87835c456783883d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 19:55:39 +0800 +Subject: perf/arm_dmc620: Fix hotplug callback leak in dmc620_pmu_init() + +From: Shang XiaoJing + +[ Upstream commit d9f564c966e63925aac4ba273a9319d7fb6f4b4e ] + +dmc620_pmu_init() won't remove the callback added by +cpuhp_setup_state_multi() when platform_driver_register() failed. Remove +the callback by cpuhp_remove_multi_state() in fail path. + +Similar to the handling of arm_ccn_init() in commit 26242b330093 ("bus: +arm-ccn: Prevent hotplug callback leak") + +Fixes: 53c218da220c ("driver/perf: Add PMU driver for the ARM DMC-620 memory controller") +Signed-off-by: Shang XiaoJing +Reviewed-by: Punit Agrawal +Link: https://lore.kernel.org/r/20221115115540.6245-2-shangxiaojing@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/perf/arm_dmc620_pmu.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c +index 280a6ae3e27c..54aa4658fb36 100644 +--- a/drivers/perf/arm_dmc620_pmu.c ++++ b/drivers/perf/arm_dmc620_pmu.c +@@ -725,6 +725,8 @@ static struct platform_driver dmc620_pmu_driver = { + + static int __init dmc620_pmu_init(void) + { ++ int ret; ++ + cpuhp_state_num = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + DMC620_DRVNAME, + NULL, +@@ -732,7 +734,11 @@ static int __init dmc620_pmu_init(void) + if (cpuhp_state_num < 0) + return cpuhp_state_num; + +- return platform_driver_register(&dmc620_pmu_driver); ++ ret = platform_driver_register(&dmc620_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(cpuhp_state_num); ++ ++ return ret; + } + + static void __exit dmc620_pmu_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/perf-arm_dsu-fix-hotplug-callback-leak-in-dsu_pmu_in.patch b/queue-5.15/perf-arm_dsu-fix-hotplug-callback-leak-in-dsu_pmu_in.patch new file mode 100644 index 00000000000..505cf0dee02 --- /dev/null +++ b/queue-5.15/perf-arm_dsu-fix-hotplug-callback-leak-in-dsu_pmu_in.patch @@ -0,0 +1,46 @@ +From 095b626586518d9eaa366600b0ec082b717a3c41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 07:02:06 +0000 +Subject: perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init() + +From: Yuan Can + +[ Upstream commit facafab7611f7b872c6b9eeaff53461ef11f482e ] + +dsu_pmu_init() won't remove the callback added by cpuhp_setup_state_multi() +when platform_driver_register() failed. Remove the callback by +cpuhp_remove_multi_state() in fail path. + +Similar to the handling of arm_ccn_init() in commit 26242b330093 ("bus: +arm-ccn: Prevent hotplug callback leak") + +Fixes: 7520fa99246d ("perf: ARM DynamIQ Shared Unit PMU support") +Signed-off-by: Yuan Can +Acked-by: Suzuki K Poulose +Link: https://lore.kernel.org/r/20221115070207.32634-2-yuancan@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/perf/arm_dsu_pmu.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c +index a36698a90d2f..54b8ba032c78 100644 +--- a/drivers/perf/arm_dsu_pmu.c ++++ b/drivers/perf/arm_dsu_pmu.c +@@ -858,7 +858,11 @@ static int __init dsu_pmu_init(void) + if (ret < 0) + return ret; + dsu_pmu_cpuhp_state = ret; +- return platform_driver_register(&dsu_pmu_driver); ++ ret = platform_driver_register(&dsu_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(dsu_pmu_cpuhp_state); ++ ++ return ret; + } + + static void __exit dsu_pmu_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/perf-fix-possible-memleak-in-pmu_dev_alloc.patch b/queue-5.15/perf-fix-possible-memleak-in-pmu_dev_alloc.patch new file mode 100644 index 00000000000..f4060e429c5 --- /dev/null +++ b/queue-5.15/perf-fix-possible-memleak-in-pmu_dev_alloc.patch @@ -0,0 +1,71 @@ +From eb16f2bfe281aa87cd2277f4cb616702d6640297 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 18:36:53 +0800 +Subject: perf: Fix possible memleak in pmu_dev_alloc() + +From: Chen Zhongjin + +[ Upstream commit e8d7a90c08ce963c592fb49845f2ccc606a2ac21 ] + +In pmu_dev_alloc(), when dev_set_name() failed, it will goto free_dev +and call put_device(pmu->dev) to release it. +However pmu->dev->release is assigned after this, which makes warning +and memleak. +Call dev_set_name() after pmu->dev->release = pmu_dev_release to fix it. + + Device '(null)' does not have a release() function... + WARNING: CPU: 2 PID: 441 at drivers/base/core.c:2332 device_release+0x1b9/0x240 + ... + Call Trace: + + kobject_put+0x17f/0x460 + put_device+0x20/0x30 + pmu_dev_alloc+0x152/0x400 + perf_pmu_register+0x96b/0xee0 + ... + kmemleak: 1 new suspected memory leaks (see /sys/kernel/debug/kmemleak) + unreferenced object 0xffff888014759000 (size 2048): + comm "modprobe", pid 441, jiffies 4294931444 (age 38.332s) + backtrace: + [<0000000005aed3b4>] kmalloc_trace+0x27/0x110 + [<000000006b38f9b8>] pmu_dev_alloc+0x50/0x400 + [<00000000735f17be>] perf_pmu_register+0x96b/0xee0 + [<00000000e38477f1>] 0xffffffffc0ad8603 + [<000000004e162216>] do_one_initcall+0xd0/0x4e0 + ... + +Fixes: abe43400579d ("perf: Sysfs enumeration") +Signed-off-by: Chen Zhongjin +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20221111103653.91058-1-chenzhongjin@huawei.com +Signed-off-by: Sasha Levin +--- + kernel/events/core.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/kernel/events/core.c b/kernel/events/core.c +index 5422bd77c7d4..e95088144471 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -11175,13 +11175,15 @@ static int pmu_dev_alloc(struct pmu *pmu) + + pmu->dev->groups = pmu->attr_groups; + device_initialize(pmu->dev); +- ret = dev_set_name(pmu->dev, "%s", pmu->name); +- if (ret) +- goto free_dev; + + dev_set_drvdata(pmu->dev, pmu); + pmu->dev->bus = &pmu_bus; + pmu->dev->release = pmu_dev_release; ++ ++ ret = dev_set_name(pmu->dev, "%s", pmu->name); ++ if (ret) ++ goto free_dev; ++ + ret = device_add(pmu->dev); + if (ret) + goto free_dev; +-- +2.35.1 + diff --git a/queue-5.15/perf-smmuv3-fix-hotplug-callback-leak-in-arm_smmu_pm.patch b/queue-5.15/perf-smmuv3-fix-hotplug-callback-leak-in-arm_smmu_pm.patch new file mode 100644 index 00000000000..2515422e787 --- /dev/null +++ b/queue-5.15/perf-smmuv3-fix-hotplug-callback-leak-in-arm_smmu_pm.patch @@ -0,0 +1,55 @@ +From 41f663ed5fe4474ac9c6f3ee53e2c0a460a02fe2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 19:55:40 +0800 +Subject: perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init() + +From: Shang XiaoJing + +[ Upstream commit 6f2d566b46436a50a80d6445e82879686b89588c ] + +arm_smmu_pmu_init() won't remove the callback added by +cpuhp_setup_state_multi() when platform_driver_register() failed. Remove +the callback by cpuhp_remove_multi_state() in fail path. + +Similar to the handling of arm_ccn_init() in commit 26242b330093 ("bus: +arm-ccn: Prevent hotplug callback leak") + +Fixes: 7d839b4b9e00 ("perf/smmuv3: Add arm64 smmuv3 pmu driver") +Signed-off-by: Shang XiaoJing +Reviewed-by: Punit Agrawal +Link: https://lore.kernel.org/r/20221115115540.6245-3-shangxiaojing@huawei.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/perf/arm_smmuv3_pmu.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c +index 226348822ab3..5933ad151f86 100644 +--- a/drivers/perf/arm_smmuv3_pmu.c ++++ b/drivers/perf/arm_smmuv3_pmu.c +@@ -896,6 +896,8 @@ static struct platform_driver smmu_pmu_driver = { + + static int __init arm_smmu_pmu_init(void) + { ++ int ret; ++ + cpuhp_state_num = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, + "perf/arm/pmcg:online", + NULL, +@@ -903,7 +905,11 @@ static int __init arm_smmu_pmu_init(void) + if (cpuhp_state_num < 0) + return cpuhp_state_num; + +- return platform_driver_register(&smmu_pmu_driver); ++ ret = platform_driver_register(&smmu_pmu_driver); ++ if (ret) ++ cpuhp_remove_multi_state(cpuhp_state_num); ++ ++ return ret; + } + module_init(arm_smmu_pmu_init); + +-- +2.35.1 + diff --git a/queue-5.15/perf-stat-do-not-delay-the-workload-with-delay.patch b/queue-5.15/perf-stat-do-not-delay-the-workload-with-delay.patch new file mode 100644 index 00000000000..693c0a33613 --- /dev/null +++ b/queue-5.15/perf-stat-do-not-delay-the-workload-with-delay.patch @@ -0,0 +1,138 @@ +From 7c2203bc0e3e87975bb1eb1111ad6ecd6177db8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Dec 2022 15:08:20 -0800 +Subject: perf stat: Do not delay the workload with --delay + +From: Namhyung Kim + +[ Upstream commit c587e77e100fa40eb6af10e00497c67acf493f33 ] + +The -D/--delay option is to delay the measure after the program starts. +But the current code goes to sleep before starting the program so the +program is delayed too. This is not the intention, let's fix it. + +Before: + + $ time sudo ./perf stat -a -e cycles -D 3000 sleep 4 + Events disabled + Events enabled + + Performance counter stats for 'system wide': + + 4,326,949,337 cycles + + 4.007494118 seconds time elapsed + + real 0m7.474s + user 0m0.356s + sys 0m0.120s + +It ran the workload for 4 seconds and gave the 3 second delay. So it +should skip the first 3 second and measure the last 1 second only. But +as you can see, it delays 3 seconds and ran the workload after that for +4 seconds. So the total time (real) was 7 seconds. + +After: + + $ time sudo ./perf stat -a -e cycles -D 3000 sleep 4 + Events disabled + Events enabled + + Performance counter stats for 'system wide': + + 1,063,551,013 cycles + + 1.002769510 seconds time elapsed + + real 0m4.484s + user 0m0.385s + sys 0m0.086s + +The bug was introduced when it changed enablement of system-wide events +with a command line workload. But it should've considered the initial +delay case. The code was reworked since then (in bb8bc52e7578) so I'm +afraid it won't be applied cleanly. + +Fixes: d0a0a511493d2695 ("perf stat: Fix forked applications enablement of counters") +Reported-by: Kevin Nomura +Signed-off-by: Namhyung Kim +Tested-by: Thomas Richter +Cc: Adrian Hunter +Cc: Ian Rogers +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Peter Zijlstra +Cc: Sumanth Korikkar +Link: https://lore.kernel.org/r/20221212230820.901382-1-namhyung@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-stat.c | 33 +++++++++++++++++---------------- + 1 file changed, 17 insertions(+), 16 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index 2602c750779d..aad65c95c371 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -558,26 +558,14 @@ static int enable_counters(void) + return err; + } + +- if (stat_config.initial_delay < 0) { +- pr_info(EVLIST_DISABLED_MSG); +- return 0; +- } +- +- if (stat_config.initial_delay > 0) { +- pr_info(EVLIST_DISABLED_MSG); +- usleep(stat_config.initial_delay * USEC_PER_MSEC); +- } +- + /* + * We need to enable counters only if: + * - we don't have tracee (attaching to task or cpu) + * - we have initial delay configured + */ +- if (!target__none(&target) || stat_config.initial_delay) { ++ if (!target__none(&target)) { + if (!all_counters_use_bpf) + evlist__enable(evsel_list); +- if (stat_config.initial_delay > 0) +- pr_info(EVLIST_ENABLED_MSG); + } + return 0; + } +@@ -953,14 +941,27 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + return err; + } + +- err = enable_counters(); +- if (err) +- return -1; ++ if (stat_config.initial_delay) { ++ pr_info(EVLIST_DISABLED_MSG); ++ } else { ++ err = enable_counters(); ++ if (err) ++ return -1; ++ } + + /* Exec the command, if any */ + if (forks) + evlist__start_workload(evsel_list); + ++ if (stat_config.initial_delay > 0) { ++ usleep(stat_config.initial_delay * USEC_PER_MSEC); ++ err = enable_counters(); ++ if (err) ++ return -1; ++ ++ pr_info(EVLIST_ENABLED_MSG); ++ } ++ + t0 = rdclock(); + clock_gettime(CLOCK_MONOTONIC, &ref_time); + +-- +2.35.1 + diff --git a/queue-5.15/perf-stat-refactor-__run_perf_stat-common-code.patch b/queue-5.15/perf-stat-refactor-__run_perf_stat-common-code.patch new file mode 100644 index 00000000000..7e7e576056c --- /dev/null +++ b/queue-5.15/perf-stat-refactor-__run_perf_stat-common-code.patch @@ -0,0 +1,86 @@ +From 15c6c1fd3fa27105055c7bd1a548df2715517b5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 16:12:43 +0000 +Subject: perf stat: Refactor __run_perf_stat() common code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Herrera Arcila + +[ Upstream commit bb8bc52e75785af94b9ba079277547d50d018a52 ] + +This extracts common code from the branches of the forks if-then-else. + +enable_counters(), which was at the beginning of both branches of the +conditional, is now unconditional; evlist__start_workload() is extracted +to a different if, which enables making the common clocking code +unconditional. + +Reviewed-by: Leo Yan +Signed-off-by: Adrián Herrera Arcila +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: James Clark +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Song Liu +Link: https://lore.kernel.org/r/20220729161244.10522-1-adrian.herrera@arm.com +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: c587e77e100f ("perf stat: Do not delay the workload with --delay") +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-stat.c | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c +index abf88a1ad455..2602c750779d 100644 +--- a/tools/perf/builtin-stat.c ++++ b/tools/perf/builtin-stat.c +@@ -953,18 +953,18 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + return err; + } + +- /* +- * Enable counters and exec the command: +- */ +- if (forks) { +- err = enable_counters(); +- if (err) +- return -1; ++ err = enable_counters(); ++ if (err) ++ return -1; ++ ++ /* Exec the command, if any */ ++ if (forks) + evlist__start_workload(evsel_list); + +- t0 = rdclock(); +- clock_gettime(CLOCK_MONOTONIC, &ref_time); ++ t0 = rdclock(); ++ clock_gettime(CLOCK_MONOTONIC, &ref_time); + ++ if (forks) { + if (interval || timeout || evlist__ctlfd_initialized(evsel_list)) + status = dispatch_events(forks, timeout, interval, ×); + if (child_pid != -1) { +@@ -982,13 +982,6 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx) + if (WIFSIGNALED(status)) + psignal(WTERMSIG(status), argv[0]); + } else { +- err = enable_counters(); +- if (err) +- return -1; +- +- t0 = rdclock(); +- clock_gettime(CLOCK_MONOTONIC, &ref_time); +- + status = dispatch_events(forks, timeout, interval, ×); + } + +-- +2.35.1 + diff --git a/queue-5.15/perf-symbol-correction-while-adjusting-symbol.patch b/queue-5.15/perf-symbol-correction-while-adjusting-symbol.patch new file mode 100644 index 00000000000..0a30f339cc3 --- /dev/null +++ b/queue-5.15/perf-symbol-correction-while-adjusting-symbol.patch @@ -0,0 +1,76 @@ +From e3275a4d2a52819b29ee54b21b387f7495bf5eff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 15:48:16 +0530 +Subject: perf symbol: correction while adjusting symbol + +From: Ajay Kaher + +[ Upstream commit 6f520ce17920b3cdfbd2479b3ccf27f9706219d0 ] + +perf doesn't provide proper symbol information for specially crafted +.debug files. + +Sometimes .debug file may not have similar program header as runtime +ELF file. For example if we generate .debug file using objcopy +--only-keep-debug resulting file will not contain .text, .data and +other runtime sections. That means corresponding program headers will +have zero FileSiz and modified Offset. + +Example: program header of text section of libxxx.so: + +Type Offset VirtAddr PhysAddr + FileSiz MemSiz Flags Align +LOAD 0x00000000003d3000 0x00000000003d3000 0x00000000003d3000 + 0x000000000055ae80 0x000000000055ae80 R E 0x1000 + +Same program header after executing: +objcopy --only-keep-debug libxxx.so libxxx.so.debug + +LOAD 0x0000000000001000 0x00000000003d3000 0x00000000003d3000 + 0x0000000000000000 0x000000000055ae80 R E 0x1000 + +Offset and FileSiz have been changed. + +Following formula will not provide correct value, if program header +taken from .debug file (syms_ss): + + sym.st_value -= phdr.p_vaddr - phdr.p_offset; + +Correct program header information is located inside runtime ELF +file (runtime_ss). + +Fixes: 2d86612aacb7805f ("perf symbol: Correct address for bss symbols") +Signed-off-by: Ajay Kaher +Cc: Alexander Shishkin +Cc: Alexey Makhalov +Cc: Jiri Olsa +Cc: Leo Yan +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: Srivatsa S. Bhat +Cc: Steven Rostedt (VMware) +Cc: Vasavi Sirnapalli +Link: http://lore.kernel.org/lkml/1669198696-50547-1-git-send-email-akaher@vmware.com +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + tools/perf/util/symbol-elf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c +index 6c183df191aa..fd42f768e584 100644 +--- a/tools/perf/util/symbol-elf.c ++++ b/tools/perf/util/symbol-elf.c +@@ -1292,7 +1292,7 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, + (!used_opd && syms_ss->adjust_symbols)) { + GElf_Phdr phdr; + +- if (elf_read_program_header(syms_ss->elf, ++ if (elf_read_program_header(runtime_ss->elf, + (u64)sym.st_value, &phdr)) { + pr_debug4("%s: failed to find program header for " + "symbol: %s st_value: %#" PRIx64 "\n", +-- +2.35.1 + diff --git a/queue-5.15/perf-trace-handle-failure-when-trace-point-folder-is.patch b/queue-5.15/perf-trace-handle-failure-when-trace-point-folder-is.patch new file mode 100644 index 00000000000..41a2f17a736 --- /dev/null +++ b/queue-5.15/perf-trace-handle-failure-when-trace-point-folder-is.patch @@ -0,0 +1,93 @@ +From 694bffb834583f999091377704d968c7bdac1773 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 07:52:35 +0000 +Subject: perf trace: Handle failure when trace point folder is missed + +From: Leo Yan + +[ Upstream commit 03e9a5d8eb552a1bf692a9c8a5ecd50f4e428006 ] + +On Arm64 a case is perf tools fails to find the corresponding trace +point folder for system calls listed in the table 'syscalltbl_arm64', +e.g. the generated system call table contains "lookup_dcookie" but we +cannot find out the matched trace point folder for it. + +We need to figure out if there have any issue for the generated system +call table, on the other hand, we need to handle the case when trace +point folder is missed under sysfs, this patch sets the flag +syscall::nonexistent as true and returns the error from +trace__read_syscall_info(). + +Another problem is for trace__syscall_info(), it returns two different +values if a system call doesn't exist: at the first time calling +trace__syscall_info() it returns NULL when the system call doesn't exist, +later if call trace__syscall_info() again for the same missed system +call, it returns pointer of syscall. trace__syscall_info() checks the +condition 'syscalls.table[id].name == NULL', but the name will be +assigned in the first invoking even the system call is not found. + +So checking system call's name in trace__syscall_info() is not the right +thing to do, this patch simply checks flag syscall::nonexistent to make +decision if a system call exists or not, finally trace__syscall_info() +returns the consistent result (NULL) if a system call doesn't existed. + +Fixes: b8b1033fcaa091d8 ("perf trace: Mark syscall ids that are not allocated to avoid unnecessary error messages") +Signed-off-by: Leo Yan +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: bpf@vger.kernel.org +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20221121075237.127706-4-leo.yan@linaro.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-trace.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index c1db48ff01a5..2fea9952818f 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -1802,13 +1802,19 @@ static int trace__read_syscall_info(struct trace *trace, int id) + sc->tp_format = trace_event__tp_format("syscalls", tp_name); + } + ++ /* ++ * Fails to read trace point format via sysfs node, so the trace point ++ * doesn't exist. Set the 'nonexistent' flag as true. ++ */ ++ if (IS_ERR(sc->tp_format)) { ++ sc->nonexistent = true; ++ return PTR_ERR(sc->tp_format); ++ } ++ + if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? + RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields)) + return -ENOMEM; + +- if (IS_ERR(sc->tp_format)) +- return PTR_ERR(sc->tp_format); +- + sc->args = sc->tp_format->format.fields; + /* + * We need to check and discard the first variable '__syscall_nr' +@@ -2125,11 +2131,8 @@ static struct syscall *trace__syscall_info(struct trace *trace, + (err = trace__read_syscall_info(trace, id)) != 0) + goto out_cant_read; + +- if (trace->syscalls.table[id].name == NULL) { +- if (trace->syscalls.table[id].nonexistent) +- return NULL; ++ if (trace->syscalls.table && trace->syscalls.table[id].nonexistent) + goto out_cant_read; +- } + + return &trace->syscalls.table[id]; + +-- +2.35.1 + diff --git a/queue-5.15/perf-trace-return-error-if-a-system-call-doesn-t-exi.patch b/queue-5.15/perf-trace-return-error-if-a-system-call-doesn-t-exi.patch new file mode 100644 index 00000000000..93ec56aca9f --- /dev/null +++ b/queue-5.15/perf-trace-return-error-if-a-system-call-doesn-t-exi.patch @@ -0,0 +1,55 @@ +From b2672bb338397c3de54e93efb282ef47da990b53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 07:52:34 +0000 +Subject: perf trace: Return error if a system call doesn't exist + +From: Leo Yan + +[ Upstream commit d4223e1776c30b2ce8d0e6eaadcbf696e60fca3c ] + +When a system call is not detected, the reason is either because the +system call ID is out of scope or failure to find the corresponding path +in the sysfs, trace__read_syscall_info() returns zero. Finally, without +returning an error value it introduces confusion for the caller. + +This patch lets the function trace__read_syscall_info() to return +-EEXIST when a system call doesn't exist. + +Fixes: b8b1033fcaa091d8 ("perf trace: Mark syscall ids that are not allocated to avoid unnecessary error messages") +Signed-off-by: Leo Yan +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: bpf@vger.kernel.org +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Link: https://lore.kernel.org/r/20221121075237.127706-3-leo.yan@linaro.org +Signed-off-by: Arnaldo Carvalho de Melo +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-trace.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index 2bf21194c7b3..aaa465d7f011 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -1782,11 +1782,11 @@ static int trace__read_syscall_info(struct trace *trace, int id) + #endif + sc = trace->syscalls.table + id; + if (sc->nonexistent) +- return 0; ++ return -EEXIST; + + if (name == NULL) { + sc->nonexistent = true; +- return 0; ++ return -EEXIST; + } + + sc->name = name; +-- +2.35.1 + diff --git a/queue-5.15/perf-trace-use-macro-raw_syscall_args_num-to-replace.patch b/queue-5.15/perf-trace-use-macro-raw_syscall_args_num-to-replace.patch new file mode 100644 index 00000000000..34b66893393 --- /dev/null +++ b/queue-5.15/perf-trace-use-macro-raw_syscall_args_num-to-replace.patch @@ -0,0 +1,82 @@ +From 450172826524e3bd53152742f8f4072533baabb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 07:52:33 +0000 +Subject: perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number + +From: Leo Yan + +[ Upstream commit eadcab4c7a66e1df03d32da0db55d89fd9343fcc ] + +This patch defines a macro RAW_SYSCALL_ARGS_NUM to replace the open +coded number '6'. + +Signed-off-by: Leo Yan +Acked-by: Ian Rogers +Cc: Alexander Shishkin +Cc: Ingo Molnar +Cc: Jiri Olsa +Cc: Mark Rutland +Cc: Namhyung Kim +Cc: Peter Zijlstra +Cc: bpf@vger.kernel.org +Link: https://lore.kernel.org/r/20221121075237.127706-2-leo.yan@linaro.org +Signed-off-by: Arnaldo Carvalho de Melo +Stable-dep-of: 03e9a5d8eb55 ("perf trace: Handle failure when trace point folder is missed") +Signed-off-by: Sasha Levin +--- + tools/perf/builtin-trace.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c +index aaa465d7f011..c1db48ff01a5 100644 +--- a/tools/perf/builtin-trace.c ++++ b/tools/perf/builtin-trace.c +@@ -87,6 +87,8 @@ + # define F_LINUX_SPECIFIC_BASE 1024 + #endif + ++#define RAW_SYSCALL_ARGS_NUM 6 ++ + /* + * strtoul: Go from a string to a value, i.e. for msr: MSR_FS_BASE to 0xc0000100 + */ +@@ -107,7 +109,7 @@ struct syscall_fmt { + const char *sys_enter, + *sys_exit; + } bpf_prog_name; +- struct syscall_arg_fmt arg[6]; ++ struct syscall_arg_fmt arg[RAW_SYSCALL_ARGS_NUM]; + u8 nr_args; + bool errpid; + bool timeout; +@@ -1224,7 +1226,7 @@ struct syscall { + */ + struct bpf_map_syscall_entry { + bool enabled; +- u16 string_args_len[6]; ++ u16 string_args_len[RAW_SYSCALL_ARGS_NUM]; + }; + + /* +@@ -1649,7 +1651,7 @@ static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args) + { + int idx; + +- if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0) ++ if (nr_args == RAW_SYSCALL_ARGS_NUM && sc->fmt && sc->fmt->nr_args != 0) + nr_args = sc->fmt->nr_args; + + sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt)); +@@ -1800,7 +1802,8 @@ static int trace__read_syscall_info(struct trace *trace, int id) + sc->tp_format = trace_event__tp_format("syscalls", tp_name); + } + +- if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields)) ++ if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? ++ RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields)) + return -ENOMEM; + + if (IS_ERR(sc->tp_format)) +-- +2.35.1 + diff --git a/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-__.patch b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-__.patch new file mode 100644 index 00000000000..02c02c6c525 --- /dev/null +++ b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-__.patch @@ -0,0 +1,50 @@ +From 663e083b8f5e3d2995b7ddcd9a4c9006e94076c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 14:31:37 +0800 +Subject: perf/x86/intel/uncore: Fix reference count leak in + __uncore_imc_init_box() + +From: Xiongfeng Wang + +[ Upstream commit 17b8d847b92d815d1638f0de154654081d66b281 ] + +pci_get_device() will increase the reference count for the returned +pci_dev, so tgl_uncore_get_mc_dev() will return a pci_dev with its +reference count increased. We need to call pci_dev_put() to decrease the +reference count before exiting from __uncore_imc_init_box(). Add +pci_dev_put() for both normal and error path. + +Fixes: fdb64822443e ("perf/x86: Add Intel Tiger Lake uncore support") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20221118063137.121512-5-wangxiongfeng2@huawei.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/intel/uncore_snb.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c +index dc3ae55f79e0..912fb3821a6b 100644 +--- a/arch/x86/events/intel/uncore_snb.c ++++ b/arch/x86/events/intel/uncore_snb.c +@@ -1423,6 +1423,7 @@ static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box) + /* MCHBAR is disabled */ + if (!(mch_bar & BIT(0))) { + pr_warn("perf uncore: MCHBAR is disabled. Failed to map IMC free-running counters.\n"); ++ pci_dev_put(pdev); + return; + } + mch_bar &= ~BIT(0); +@@ -1436,6 +1437,8 @@ static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box) + box->io_addr = ioremap(addr, type->mmio_map_size); + if (!box->io_addr) + pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name); ++ ++ pci_dev_put(pdev); + } + + static struct intel_uncore_ops tgl_uncore_imc_freerunning_ops = { +-- +2.35.1 + diff --git a/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-hs.patch b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-hs.patch new file mode 100644 index 00000000000..fac8e7a07ae --- /dev/null +++ b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-hs.patch @@ -0,0 +1,40 @@ +From 8c1bc42c62aa0fe38d841e1a9883532103d86396 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 14:31:35 +0800 +Subject: perf/x86/intel/uncore: Fix reference count leak in + hswep_has_limit_sbox() + +From: Xiongfeng Wang + +[ Upstream commit 1ff9dd6e7071a561f803135c1d684b13c7a7d01d ] + +pci_get_device() will increase the reference count for the returned +'dev'. We need to call pci_dev_put() to decrease the reference count. +Since 'dev' is only used in pci_read_config_dword(), let's add +pci_dev_put() right after it. + +Fixes: 9d480158ee86 ("perf/x86/intel/uncore: Remove uncore extra PCI dev HSWEP_PCI_PCU_3") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20221118063137.121512-3-wangxiongfeng2@huawei.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/intel/uncore_snbep.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c +index 76fedc8e12dd..f5d89d06c66a 100644 +--- a/arch/x86/events/intel/uncore_snbep.c ++++ b/arch/x86/events/intel/uncore_snbep.c +@@ -2891,6 +2891,7 @@ static bool hswep_has_limit_sbox(unsigned int device) + return false; + + pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4); ++ pci_dev_put(dev); + if (!hswep_get_chop(capid4)) + return true; + +-- +2.35.1 + diff --git a/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sa.patch b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sa.patch new file mode 100644 index 00000000000..2ca9c0f84ec --- /dev/null +++ b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sa.patch @@ -0,0 +1,45 @@ +From 5b9132232f368580e1ba09779615157bef6ac33c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 14:31:34 +0800 +Subject: perf/x86/intel/uncore: Fix reference count leak in + sad_cfg_iio_topology() + +From: Xiongfeng Wang + +[ Upstream commit c508eb042d9739bf9473526f53303721b70e9100 ] + +pci_get_device() will increase the reference count for the returned +pci_dev, and also decrease the reference count for the input parameter +*from* if it is not NULL. + +If we break the loop in sad_cfg_iio_topology() with 'dev' not NULL. We +need to call pci_dev_put() to decrease the reference count. Since +pci_dev_put() can handle the NULL input parameter, we can just add one +pci_dev_put() right before 'return ret'. + +Fixes: c1777be3646b ("perf/x86/intel/uncore: Enable I/O stacks to IIO PMON mapping on SNR") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20221118063137.121512-2-wangxiongfeng2@huawei.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/intel/uncore_snbep.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c +index ed869443efb2..76fedc8e12dd 100644 +--- a/arch/x86/events/intel/uncore_snbep.c ++++ b/arch/x86/events/intel/uncore_snbep.c +@@ -4492,6 +4492,8 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map + type->topology = NULL; + } + ++ pci_dev_put(dev); ++ + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sn.patch b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sn.patch new file mode 100644 index 00000000000..1b2f2c31b81 --- /dev/null +++ b/queue-5.15/perf-x86-intel-uncore-fix-reference-count-leak-in-sn.patch @@ -0,0 +1,41 @@ +From b8645122bad5c3914f378b73f8ffe839158118b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 14:31:36 +0800 +Subject: perf/x86/intel/uncore: Fix reference count leak in + snr_uncore_mmio_map() + +From: Xiongfeng Wang + +[ Upstream commit 8ebd16c11c346751b3944d708e6c181ed4746c39 ] + +pci_get_device() will increase the reference count for the returned +pci_dev, so snr_uncore_get_mc_dev() will return a pci_dev with its +reference count increased. We need to call pci_dev_put() to decrease the +reference count. Let's add the missing pci_dev_put(). + +Fixes: ee49532b38dd ("perf/x86/intel/uncore: Add IMC uncore support for Snow Ridge") +Signed-off-by: Xiongfeng Wang +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Kan Liang +Link: https://lore.kernel.org/r/20221118063137.121512-4-wangxiongfeng2@huawei.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/intel/uncore_snbep.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c +index f5d89d06c66a..fcd95e93f479 100644 +--- a/arch/x86/events/intel/uncore_snbep.c ++++ b/arch/x86/events/intel/uncore_snbep.c +@@ -4860,6 +4860,8 @@ static int snr_uncore_mmio_map(struct intel_uncore_box *box, + + addr += box_ctl; + ++ pci_dev_put(pdev); ++ + box->io_addr = ioremap(addr, type->mmio_map_size); + if (!box->io_addr) { + pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name); +-- +2.35.1 + diff --git a/queue-5.15/phy-qcom-qmp-combo-fix-runtime-suspend.patch b/queue-5.15/phy-qcom-qmp-combo-fix-runtime-suspend.patch new file mode 100644 index 00000000000..c5625506c5c --- /dev/null +++ b/queue-5.15/phy-qcom-qmp-combo-fix-runtime-suspend.patch @@ -0,0 +1,69 @@ +From d17b3a7b0119f7d92788acbe0f3d3b31bd8f892b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 09:13:45 +0100 +Subject: phy: qcom-qmp-combo: fix runtime suspend + +From: Johan Hovold + +[ Upstream commit c7b98de745cffdceefc077ad5cf9cda032ef8959 ] + +Drop the confused runtime-suspend type check which effectively broke +runtime PM if the DP child node happens to be parsed before the USB +child node during probe (e.g. due to order of child nodes in the +devicetree). + +Instead use the new driver data USB PHY pointer to access the USB +configuration and resources. + +Fixes: 52e013d0bffa ("phy: qcom-qmp: Add support for DP in USB3+DP combo phy") +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20221114081346.5116-6-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +index c7309e981bfb..013fe758f5ad 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -5501,15 +5501,11 @@ static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) + static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); +- struct qmp_phy *qphy = qmp->phys[0]; ++ struct qmp_phy *qphy = qmp->usb_phy; + const struct qmp_phy_cfg *cfg = qphy->cfg; + + dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); + +- /* Supported only for USB3 PHY and luckily USB3 is the first phy */ +- if (cfg->type != PHY_TYPE_USB3) +- return 0; +- + if (!qmp->init_count) { + dev_vdbg(dev, "PHY not initialized, bailing out\n"); + return 0; +@@ -5526,16 +5522,12 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); +- struct qmp_phy *qphy = qmp->phys[0]; ++ struct qmp_phy *qphy = qmp->usb_phy; + const struct qmp_phy_cfg *cfg = qphy->cfg; + int ret = 0; + + dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); + +- /* Supported only for USB3 PHY and luckily USB3 is the first phy */ +- if (cfg->type != PHY_TYPE_USB3) +- return 0; +- + if (!qmp->init_count) { + dev_vdbg(dev, "PHY not initialized, bailing out\n"); + return 0; +-- +2.35.1 + diff --git a/queue-5.15/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch b/queue-5.15/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch new file mode 100644 index 00000000000..dfc8201e234 --- /dev/null +++ b/queue-5.15/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch @@ -0,0 +1,31819 @@ +From 937cedd853e6fded6f1456c9a7f6d9c23a52793f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:35:32 +0300 +Subject: phy: qcom-qmp: create copies of QMP PHY driver + +From: Dmitry Baryshkov + +[ Upstream commit 94a407cc17a445ddb3f7315cee0b0916d35d177c ] + +In order to split and cleanup the single monstrous QMP PHY driver, +create blind copies of the current file. They will be used for: +- PCIe (and a separate msm8996 PCIe PHY driver) +- UFS +- USB +- Combo DP + USB + +Acked-by: Bjorn Andersson +Tested-by: Bjorn Andersson # UFS, PCIe and USB on SC8180X +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220607213203.2819885-2-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: c7b98de745cf ("phy: qcom-qmp-combo: fix runtime suspend") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 6350 +++++++++++++++++ + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 6350 +++++++++++++++++ + drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 6350 +++++++++++++++++ + drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 6350 +++++++++++++++++ + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 6350 +++++++++++++++++ + 5 files changed, 31750 insertions(+) + create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-combo.c + create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c + create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-pcie.c + create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-ufs.c + create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-usb.c + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +new file mode 100644 +index 000000000000..c7309e981bfb +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -0,0 +1,6350 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "phy-qcom-qmp.h" ++ ++/* QPHY_SW_RESET bit */ ++#define SW_RESET BIT(0) ++/* QPHY_POWER_DOWN_CONTROL */ ++#define SW_PWRDN BIT(0) ++#define REFCLK_DRV_DSBL BIT(1) ++/* QPHY_START_CONTROL bits */ ++#define SERDES_START BIT(0) ++#define PCS_START BIT(1) ++#define PLL_READY_GATE_EN BIT(3) ++/* QPHY_PCS_STATUS bit */ ++#define PHYSTATUS BIT(6) ++#define PHYSTATUS_4_20 BIT(7) ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ ++#define PCS_READY BIT(0) ++ ++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ ++/* DP PHY soft reset */ ++#define SW_DPPHY_RESET BIT(0) ++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ ++#define SW_DPPHY_RESET_MUX BIT(1) ++/* USB3 PHY soft reset */ ++#define SW_USB3PHY_RESET BIT(2) ++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ ++#define SW_USB3PHY_RESET_MUX BIT(3) ++ ++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ ++#define USB3_MODE BIT(0) /* enables USB3 mode */ ++#define DP_MODE BIT(1) /* enables DP mode */ ++ ++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ ++#define ARCVR_DTCT_EN BIT(0) ++#define ALFPS_DTCT_EN BIT(1) ++#define ARCVR_DTCT_EVENT_SEL BIT(4) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ ++#define IRQ_CLEAR BIT(0) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ ++#define RCVR_DETECT BIT(0) ++ ++/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ ++#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ ++ ++#define PHY_INIT_COMPLETE_TIMEOUT 10000 ++#define POWER_DOWN_DELAY_US_MIN 10 ++#define POWER_DOWN_DELAY_US_MAX 11 ++ ++#define MAX_PROP_NAME 32 ++ ++/* Define the assumed distance between lanes for underspecified device trees. */ ++#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 ++ ++struct qmp_phy_init_tbl { ++ unsigned int offset; ++ unsigned int val; ++ /* ++ * register part of layout ? ++ * if yes, then offset gives index in the reg-layout ++ */ ++ bool in_layout; ++ /* ++ * mask of lanes for which this register is written ++ * for cases when second lane needs different values ++ */ ++ u8 lane_mask; ++}; ++ ++#define QMP_PHY_INIT_CFG(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_L(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .in_layout = true, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = l, \ ++ } ++ ++/* set of registers with offsets different per-PHY */ ++enum qphy_reg_layout { ++ /* Common block control registers */ ++ QPHY_COM_SW_RESET, ++ QPHY_COM_POWER_DOWN_CONTROL, ++ QPHY_COM_START_CONTROL, ++ QPHY_COM_PCS_READY_STATUS, ++ /* PCS registers */ ++ QPHY_PLL_LOCK_CHK_DLY_TIME, ++ QPHY_FLL_CNTRL1, ++ QPHY_FLL_CNTRL2, ++ QPHY_FLL_CNT_VAL_L, ++ QPHY_FLL_CNT_VAL_H_TOL, ++ QPHY_FLL_MAN_CODE, ++ QPHY_SW_RESET, ++ QPHY_START_CTRL, ++ QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, ++ QPHY_PCS_AUTONOMOUS_MODE_CTRL, ++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, ++ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, ++ QPHY_PCS_POWER_DOWN_CONTROL, ++ /* PCS_MISC registers */ ++ QPHY_PCS_MISC_TYPEC_CTRL, ++ /* Keep last to ensure regs_layout arrays are properly initialized */ ++ QPHY_LAYOUT_SIZE ++}; ++ ++static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_COM_SW_RESET] = 0x400, ++ [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, ++ [QPHY_COM_START_CONTROL] = 0x408, ++ [QPHY_COM_PCS_READY_STATUS] = 0x448, ++ [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, ++ [QPHY_FLL_CNTRL1] = 0xc4, ++ [QPHY_FLL_CNTRL2] = 0xc8, ++ [QPHY_FLL_CNT_VAL_L] = 0xcc, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, ++ [QPHY_FLL_MAN_CODE] = 0xd4, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_FLL_CNTRL1] = 0xc0, ++ [QPHY_FLL_CNTRL2] = 0xc4, ++ [QPHY_FLL_CNT_VAL_L] = 0xc8, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, ++ [QPHY_FLL_MAN_CODE] = 0xd0, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x17c, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++}; ++ ++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++}; ++ ++static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x2ac, ++}; ++ ++static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x308, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x314, ++}; ++ ++static const unsigned int qmp_v4_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x608, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x614, ++}; ++ ++static const unsigned int sm8350_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x1008, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x1014, ++}; ++ ++static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0xd8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0xdc, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_MISC_TYPEC_CTRL] = 0x00, ++}; ++ ++static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x160, ++}; ++ ++static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, ++ [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, ++ [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), ++ ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4), ++ QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe), ++ QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0), ++ QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1), ++ ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x95), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x26), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x048), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_PLL_CNTL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB, 0xd8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_PWM_GEAR_BAND, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HS_GEAR_BAND, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xd8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_TX_ADAPT_POST_THRESH, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0xd0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_RX, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0xc5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xad), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xb6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xc7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x05), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), ++}; ++ ++/* Register names should be validated, they might be different for this PHY */ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), ++}; ++ ++struct qmp_phy; ++ ++/* struct qmp_phy_cfg - per-PHY initialization config */ ++struct qmp_phy_cfg { ++ /* phy-type - PCIE/UFS/USB */ ++ unsigned int type; ++ /* number of lanes provided by phy */ ++ int nlanes; ++ ++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_init_tbl *serdes_tbl; ++ int serdes_tbl_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_sec; ++ int serdes_tbl_num_sec; ++ const struct qmp_phy_init_tbl *tx_tbl; ++ int tx_tbl_num; ++ const struct qmp_phy_init_tbl *tx_tbl_sec; ++ int tx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *rx_tbl; ++ int rx_tbl_num; ++ const struct qmp_phy_init_tbl *rx_tbl_sec; ++ int rx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_tbl; ++ int pcs_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_tbl_sec; ++ int pcs_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl; ++ int pcs_misc_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; ++ int pcs_misc_tbl_num_sec; ++ ++ /* Init sequence for DP PHY block link rates */ ++ const struct qmp_phy_init_tbl *serdes_tbl_rbr; ++ int serdes_tbl_rbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr; ++ int serdes_tbl_hbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr2; ++ int serdes_tbl_hbr2_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr3; ++ int serdes_tbl_hbr3_num; ++ ++ /* DP PHY callbacks */ ++ int (*configure_dp_phy)(struct qmp_phy *qphy); ++ void (*configure_dp_tx)(struct qmp_phy *qphy); ++ int (*calibrate_dp_phy)(struct qmp_phy *qphy); ++ void (*dp_aux_init)(struct qmp_phy *qphy); ++ ++ /* clock ids to be requested */ ++ const char * const *clk_list; ++ int num_clks; ++ /* resets to be requested */ ++ const char * const *reset_list; ++ int num_resets; ++ /* regulators to be requested */ ++ const char * const *vreg_list; ++ int num_vregs; ++ ++ /* array of registers with different offsets */ ++ const unsigned int *regs; ++ ++ unsigned int start_ctrl; ++ unsigned int pwrdn_ctrl; ++ unsigned int mask_com_pcs_ready; ++ /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ ++ unsigned int phy_status; ++ ++ /* true, if PHY has a separate PHY_COM control block */ ++ bool has_phy_com_ctrl; ++ /* true, if PHY has a reset for individual lanes */ ++ bool has_lane_rst; ++ /* true, if PHY needs delay after POWER_DOWN */ ++ bool has_pwrdn_delay; ++ /* power_down delay in usec */ ++ int pwrdn_delay_min; ++ int pwrdn_delay_max; ++ ++ /* true, if PHY has a separate DP_COM control block */ ++ bool has_phy_dp_com_ctrl; ++ /* true, if PHY has secondary tx/rx lanes to be configured */ ++ bool is_dual_lane_phy; ++ ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; ++}; ++ ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; ++}; ++ ++/** ++ * struct qmp_phy - per-lane phy descriptor ++ * ++ * @phy: generic phy ++ * @cfg: phy specific configuration ++ * @serdes: iomapped memory space for phy's serdes (i.e. PLL) ++ * @tx: iomapped memory space for lane's tx ++ * @rx: iomapped memory space for lane's rx ++ * @pcs: iomapped memory space for lane's pcs ++ * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) ++ * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) ++ * @pcs_misc: iomapped memory space for lane's pcs_misc ++ * @pipe_clk: pipe clock ++ * @index: lane index ++ * @qmp: QMP phy to which this lane belongs ++ * @lane_rst: lane's reset controller ++ * @mode: current PHY mode ++ * @dp_aux_cfg: Display port aux config ++ * @dp_opts: Display port optional config ++ * @dp_clks: Display port clocks ++ */ ++struct qmp_phy { ++ struct phy *phy; ++ const struct qmp_phy_cfg *cfg; ++ void __iomem *serdes; ++ void __iomem *tx; ++ void __iomem *rx; ++ void __iomem *pcs; ++ void __iomem *tx2; ++ void __iomem *rx2; ++ void __iomem *pcs_misc; ++ struct clk *pipe_clk; ++ unsigned int index; ++ struct qcom_qmp *qmp; ++ struct reset_control *lane_rst; ++ enum phy_mode mode; ++ unsigned int dp_aux_cfg; ++ struct phy_configure_opts_dp dp_opts; ++ struct qmp_phy_dp_clks *dp_clks; ++}; ++ ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; ++ ++/** ++ * struct qcom_qmp - structure holding QMP phy block attributes ++ * ++ * @dev: device ++ * @dp_com: iomapped memory space for phy's dp_com control block ++ * ++ * @clks: array of clocks required by phy ++ * @resets: array of resets required by phy ++ * @vregs: regulator supplies bulk data ++ * ++ * @phys: array of per-lane phy descriptors ++ * @phy_mutex: mutex lock for PHY common block initialization ++ * @init_count: phy common block initialization count ++ * @ufs_reset: optional UFS PHY reset handle ++ */ ++struct qcom_qmp { ++ struct device *dev; ++ void __iomem *dp_com; ++ ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; ++ ++ struct qmp_phy **phys; ++ ++ struct mutex phy_mutex; ++ int init_count; ++ ++ struct reset_control *ufs_reset; ++}; ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", ++}; ++ ++static const char * const msm8996_ufs_phy_clk_l[] = { ++ "ref", ++}; ++ ++static const char * const qmp_v3_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "com_aux", ++}; ++ ++static const char * const sdm845_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "refgen", ++}; ++ ++static const char * const qmp_v4_phy_clk_l[] = { ++ "aux", "ref_clk_src", "ref", "com_aux", ++}; ++ ++/* the primary usb3 phy on sm8250 doesn't have a ref clock */ ++static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { ++ "aux", "ref_clk_src", "com_aux" ++}; ++ ++static const char * const sm8450_ufs_phy_clk_l[] = { ++ "qref", "ref", "ref_aux", ++}; ++ ++static const char * const sdm845_ufs_phy_clk_l[] = { ++ "ref", "ref_aux", ++}; ++ ++/* usb3 phy on sdx55 doesn't have com_aux clock */ ++static const char * const qmp_v4_sdx55_usbphy_clk_l[] = { ++ "aux", "cfg_ahb", "ref" ++}; ++ ++static const char * const qcm2290_usb3phy_clk_l[] = { ++ "cfg_ahb", "ref", "com_aux", ++}; ++ ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", ++}; ++ ++static const char * const msm8996_usb3phy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const char * const sc7180_usb3phy_reset_l[] = { ++ "phy", ++}; ++ ++static const char * const qcm2290_usb3phy_reset_l[] = { ++ "phy_phy", "phy", ++}; ++ ++static const char * const sdm845_pciephy_reset_l[] = { ++ "phy", ++}; ++ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = ipq8074_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), ++ .pcs_tbl = ipq8074_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, ++ ++ .serdes_tbl = msm8996_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), ++ .tx_tbl = msm8996_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), ++ .rx_tbl = msm8996_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), ++ .pcs_tbl = msm8996_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = true, ++ .has_lane_rst = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg msm8996_ufs_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_ufs_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), ++ .tx_tbl = msm8996_ufs_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl), ++ .rx_tbl = msm8996_ufs_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl), ++ ++ .clk_list = msm8996_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l), ++ ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ ++ .regs = msm8996_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = msm8996_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), ++ .pcs_tbl = msm8996_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const char * const ipq8074_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", ++}; ++/* list of resets */ ++static const char * const ipq8074_pciephy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx_tbl = ipq8074_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx_tbl = ipq8074_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs_tbl = ipq8074_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq6018_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx_tbl = ipq6018_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx_tbl = ipq6018_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs_tbl = ipq6018_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = ipq_pciephy_gen3_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qmp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qhp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qhp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qhp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), ++ .tx_tbl = qmp_v3_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { ++ .usb_cfg = &sc7180_usb3phy_cfg, ++ .dp_cfg = &sc7180_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdm845_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), ++ .tx_tbl = sdm845_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), ++ .rx_tbl = sdm845_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), ++ .pcs_tbl = sdm845_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm6115_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), ++ .tx_tbl = sm6115_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), ++ .rx_tbl = sm6115_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), ++ .pcs_tbl = sm6115_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm6115_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ ++ .is_dual_lane_phy = false, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8998_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx_tbl = msm8998_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx_tbl = msm8998_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs_tbl = msm8998_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), ++ .tx_tbl = msm8998_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl), ++ .rx_tbl = msm8998_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), ++ .pcs_tbl = msm8998_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8150_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), ++ .tx_tbl = sm8150_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_tx_tbl), ++ .rx_tbl = sm8150_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_rx_tbl), ++ .pcs_tbl = sm8150_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8150_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), ++ .rx_tbl = sm8150_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), ++ .pcs_tbl = sm8150_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx_tbl = sc8180x_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx_tbl = sc8180x_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { ++ .usb_cfg = &sm8150_usb3phy_cfg, ++ .dp_cfg = &sc8180x_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8150_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8150_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8150_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8250_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), ++ .rx_tbl = sm8250_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), ++ .pcs_tbl = sm8250_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8250_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8250_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { ++ .usb_cfg = &sm8250_usb3phy_cfg, ++ .dp_cfg = &sm8250_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx55_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx55_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdx55_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx_tbl = sdx55_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx65_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx65_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8350_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), ++ .rx_tbl = sm8350_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), ++ .pcs_tbl = sm8350_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8350_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8350_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sm8450_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qcm2290_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ++ .tx_tbl = qcm2290_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), ++ .rx_tbl = qcm2290_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), ++ .pcs_tbl = qcm2290_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), ++ .clk_list = qcm2290_usb3phy_clk_l, ++ .num_clks = ARRAY_SIZE(qcm2290_usb3phy_clk_l), ++ .reset_list = qcm2290_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qcm2290_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static void qcom_qmp_phy_configure_lane(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num, ++ u8 lane_mask) ++{ ++ int i; ++ const struct qmp_phy_init_tbl *t = tbl; ++ ++ if (!t) ++ return; ++ ++ for (i = 0; i < num; i++, t++) { ++ if (!(t->lane_mask & lane_mask)) ++ continue; ++ ++ if (t->in_layout) ++ writel(t->val, base + regs[t->offset]); ++ else ++ writel(t->val, base + t->offset); ++ } ++} ++ ++static void qcom_qmp_phy_configure(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num) ++{ ++ qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); ++} ++ ++static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; ++ int serdes_tbl_num = cfg->serdes_tbl_num; ++ int ret; ++ ++ qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ if (cfg->serdes_tbl_sec) ++ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, ++ cfg->serdes_tbl_num_sec); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ switch (dp_opts->link_rate) { ++ case 1620: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_rbr, ++ cfg->serdes_tbl_rbr_num); ++ break; ++ case 2700: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr, ++ cfg->serdes_tbl_hbr_num); ++ break; ++ case 5400: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr2, ++ cfg->serdes_tbl_hbr2_num); ++ break; ++ case 8100: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr3, ++ cfg->serdes_tbl_hbr3_num); ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ } ++ ++ ++ if (cfg->has_phy_com_ctrl) { ++ void __iomem *status; ++ unsigned int mask, val; ++ ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ ++ status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; ++ mask = cfg->mask_com_pcs_ready; ++ ++ ret = readl_poll_timeout(status, val, (val & mask), 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, ++ "phy common block init timed-out\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_LANE_0_1_PWRDN | ++ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | ++ DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(QSERDES_V3_COM_BIAS_EN | ++ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | ++ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { ++ { 0x00, 0x0c, 0x15, 0x1a }, ++ { 0x02, 0x0e, 0x16, 0xff }, ++ { 0x02, 0x11, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { ++ { 0x02, 0x12, 0x16, 0x1a }, ++ { 0x09, 0x19, 0x1f, 0xff }, ++ { 0x10, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { ++ { 0x00, 0x0c, 0x14, 0x19 }, ++ { 0x00, 0x0b, 0x12, 0xff }, ++ { 0x00, 0x0b, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { ++ { 0x08, 0x0f, 0x16, 0x1f }, ++ { 0x11, 0x1e, 0x1f, 0xff }, ++ { 0x19, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, ++ unsigned int drv_lvl_reg, unsigned int emp_post_reg) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ unsigned int v_level = 0, p_level = 0; ++ u8 voltage_swing_cfg, pre_emphasis_cfg; ++ int i; ++ ++ for (i = 0; i < dp_opts->lanes; i++) { ++ v_level = max(v_level, dp_opts->voltage[i]); ++ p_level = max(p_level, dp_opts->pre[i]); ++ } ++ ++ if (dp_opts->link_rate <= 2700) { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; ++ } else { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; ++ } ++ ++ /* TODO: Move check to config check */ ++ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) ++ return -EINVAL; ++ ++ /* Enable MUX to use Cursor values from these registers */ ++ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; ++ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; ++ ++ writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); ++ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 bias_en, drvr_en; ++ ++ if (qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V3_TX_TX_DRV_LVL, ++ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) ++ return; ++ ++ if (dp_opts->lanes == 1) { ++ bias_en = 0x3e; ++ drvr_en = 0x13; ++ } else { ++ bias_en = 0x3f; ++ drvr_en = 0x10; ++ } ++ ++ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++} ++ ++static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) ++{ ++ u32 val; ++ bool reverse = false; ++ ++ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ++ ++ /* ++ * TODO: Assume orientation is CC1 for now and two lanes, need to ++ * use type-c connector to understand orientation and lanes. ++ * ++ * Otherwise val changes to be like below if this code understood ++ * the orientation of the type-c cable. ++ * ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) ++ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) ++ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ * if (orientation == ORIENTATION_CC2) ++ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); ++ */ ++ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); ++ ++ return reverse; ++} ++ ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ ++ qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000); ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ /* Program default values before writing proper values */ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V4_TX_TX_DRV_LVL, ++ QSERDES_V4_TX_TX_EMP_POST1_LVL); ++} ++ ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ u32 bias0_en, drvr0_en, bias1_en, drvr1_en; ++ bool reverse; ++ ++ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); ++ ++ reverse = qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ /* ++ * At least for 7nm DP PHY this has to be done after enabling link ++ * clock. ++ */ ++ ++ if (dp_opts->lanes == 1) { ++ bias0_en = reverse ? 0x3e : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3e; ++ drvr0_en = reverse ? 0x13 : 0x10; ++ drvr1_en = reverse ? 0x10 : 0x13; ++ } else if (dp_opts->lanes == 2) { ++ bias0_en = reverse ? 0x3f : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } else { ++ bias0_en = 0x3f; ++ bias1_en = 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } ++ ++ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); ++ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); ++ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ return 0; ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); ++ if (qphy->dp_opts.set_voltages) { ++ cfg->configure_dp_tx(qphy); ++ qphy->dp_opts.set_voltages = 0; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_calibrate(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->calibrate_dp_phy) ++ return cfg->calibrate_dp_phy(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *dp_com = qmp->dp_com; ++ int ret, i; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (qmp->init_count++) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ /* turn on regulator supplies */ ++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); ++ if (ret) { ++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); ++ goto err_unlock; ++ } ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ ret = reset_control_assert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset assert failed\n", ++ cfg->reset_list[i]); ++ goto err_disable_regulators; ++ } ++ } ++ ++ for (i = cfg->num_resets - 1; i >= 0; i--) { ++ ret = reset_control_deassert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset deassert failed\n", ++ qphy->cfg->reset_list[i]); ++ goto err_assert_reset; ++ } ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ goto err_assert_reset; ++ ++ if (cfg->has_phy_dp_com_ctrl) { ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, ++ SW_PWRDN); ++ /* override hardware control for reset of qmp phy */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ /* Default type-c orientation, i.e CC1 */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); ++ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, ++ USB3_MODE | DP_MODE); ++ ++ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); ++ } ++ ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } else { ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(pcs, ++ cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ else ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++ ++err_assert_reset: ++ while (++i < cfg->num_resets) ++ reset_control_assert(qmp->resets[i]); ++err_disable_regulators: ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++err_unlock: ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ int i = cfg->num_resets; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (--qmp->init_count) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ reset_control_assert(qmp->ufs_reset); ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], ++ SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } ++ ++ while (--i >= 0) ++ reset_control_assert(qmp->resets[i]); ++ ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_init(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret; ++ dev_vdbg(qmp->dev, "Initializing QMP phy\n"); ++ ++ if (cfg->no_pcs_sw_reset) { ++ /* ++ * Get UFS reset, which is delayed until now to avoid a ++ * circular dependency where UFS needs its PHY, but the PHY ++ * needs this UFS reset. ++ */ ++ if (!qmp->ufs_reset) { ++ qmp->ufs_reset = ++ devm_reset_control_get_exclusive(qmp->dev, ++ "ufsphy"); ++ ++ if (IS_ERR(qmp->ufs_reset)) { ++ ret = PTR_ERR(qmp->ufs_reset); ++ dev_err(qmp->dev, ++ "failed to get UFS reset: %d\n", ++ ret); ++ ++ qmp->ufs_reset = NULL; ++ return ret; ++ } ++ } ++ ++ ret = reset_control_assert(qmp->ufs_reset); ++ if (ret) ++ return ret; ++ } ++ ++ ret = qcom_qmp_phy_com_init(qphy); ++ if (ret) ++ return ret; ++ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->dp_aux_init(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_power_on(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ void __iomem *status; ++ unsigned int mask, val, ready; ++ int ret; ++ ++ qcom_qmp_phy_serdes_init(qphy); ++ ++ if (cfg->has_lane_rst) { ++ ret = reset_control_deassert(qphy->lane_rst); ++ if (ret) { ++ dev_err(qmp->dev, "lane%d reset deassert failed\n", ++ qphy->index); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); ++ goto err_reset_lane; ++ } ++ ++ /* Tx, Rx, and PCS configurations */ ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 1); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 1); ++ ++ /* Configuration for other LANE for USB-DP combo PHY */ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 2); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 2); ++ } ++ ++ /* Configure special DP tx tunings */ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->configure_dp_tx(qphy); ++ ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 1); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); ++ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 2); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl_sec, ++ cfg->rx_tbl_num_sec, 2); ++ } ++ ++ /* Configure link rate, swing, etc. */ ++ if (cfg->type == PHY_TYPE_DP) { ++ cfg->configure_dp_phy(qphy); ++ } else { ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); ++ } ++ ++ ret = reset_control_deassert(qmp->ufs_reset); ++ if (ret) ++ goto err_disable_pipe_clk; ++ ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ cfg->pcs_misc_tbl_num); ++ if (cfg->pcs_misc_tbl_sec) ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, ++ cfg->pcs_misc_tbl_num_sec); ++ ++ /* ++ * Pull out PHY from POWER DOWN state. ++ * This is active low enable signal to power-down PHY. ++ */ ++ if(cfg->type == PHY_TYPE_PCIE) ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); ++ ++ if (cfg->has_pwrdn_delay) ++ usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ ++ if (cfg->type != PHY_TYPE_DP) { ++ /* Pull PHY out of reset state */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ /* start SerDes and Phy-Coding-Sublayer */ ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = cfg->phy_status; ++ ready = 0; ++ } ++ ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, "phy initialization timed-out\n"); ++ goto err_disable_pipe_clk; ++ } ++ } ++ return 0; ++ ++err_disable_pipe_clk: ++ clk_disable_unprepare(qphy->pipe_clk); ++err_reset_lane: ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_power_off(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ /* Assert DP PHY power down */ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ } else { ++ /* PHY reset */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ ++ /* stop SerDes and Phy-Coding-Sublayer */ ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ /* Put PHY into POWER DOWN state: active low */ ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ } else { ++ qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_exit(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ qcom_qmp_phy_com_exit(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_enable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_power_on(phy); ++ if (ret) ++ qcom_qmp_phy_exit(phy); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_disable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_power_off(phy); ++ if (ret) ++ return ret; ++ return qcom_qmp_phy_exit(phy); ++} ++ ++static int qcom_qmp_phy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ qphy->mode = mode; ++ ++ return 0; ++} ++ ++static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ u32 intr_mask; ++ ++ if (qphy->mode == PHY_MODE_USB_HOST_SS || ++ qphy->mode == PHY_MODE_USB_DEVICE_SS) ++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; ++ else ++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; ++ ++ /* Clear any pending interrupts status */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); ++ ++ /* Enable required PHY autonomous mode interrupts */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); ++ ++ /* Enable i/o clamp_n for autonomous mode */ ++ if (pcs_misc) ++ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++} ++ ++static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ /* Disable i/o clamp_n on resume for normal mode */ ++ if (pcs_misc) ++ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); ++ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ qcom_qmp_phy_enable_autonomous_mode(qphy); ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret = 0; ++ ++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ return ret; ++ } ++ ++ qcom_qmp_phy_disable_autonomous_mode(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_vregs; ++ int i; ++ ++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); ++ if (!qmp->vregs) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->vregs[i].supply = cfg->vreg_list[i]; ++ ++ return devm_regulator_bulk_get(dev, num, qmp->vregs); ++} ++ ++static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int i; ++ ++ qmp->resets = devm_kcalloc(dev, cfg->num_resets, ++ sizeof(*qmp->resets), GFP_KERNEL); ++ if (!qmp->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ struct reset_control *rst; ++ const char *name = cfg->reset_list[i]; ++ ++ rst = devm_reset_control_get_exclusive(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ return PTR_ERR(rst); ++ } ++ qmp->resets[i] = rst; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_clks; ++ int i; ++ ++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); ++ if (!qmp->clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->clks[i].id = cfg->clk_list[i]; ++ ++ return devm_clk_bulk_get(dev, num, qmp->clks); ++} ++ ++static void phy_clk_release_provider(void *res) ++{ ++ of_clk_del_provider(res); ++} ++ ++/* ++ * Register a fixed rate pipe clock. ++ * ++ * The _pipe_clksrc generated by PHY goes to the GCC that gate ++ * controls it. The _pipe_clk coming out of the GCC is requested ++ * by the PHY driver for its operations. ++ * We register the _pipe_clksrc here. The gcc driver takes care ++ * of assigning this _pipe_clksrc as parent to _pipe_clk. ++ * Below picture shows this relationship. ++ * ++ * +---------------+ ++ * | PHY block |<<---------------------------------------+ ++ * | | | ++ * | +-------+ | +-----+ | ++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ ++ * clk | +-------+ | +-----+ ++ * +---------------+ ++ */ ++static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) ++{ ++ struct clk_fixed_rate *fixed; ++ struct clk_init_data init = { }; ++ int ret; ++ ++ ret = of_property_read_string(np, "clock-output-names", &init.name); ++ if (ret) { ++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); ++ return ret; ++ } ++ ++ fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); ++ if (!fixed) ++ return -ENOMEM; ++ ++ init.ops = &clk_fixed_rate_ops; ++ ++ /* controllers using QMP phys use 125MHz pipe clock interface */ ++ fixed->fixed_rate = 125000000; ++ fixed->hw.init = &init; ++ ++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++/* ++ * Display Port PLL driver block diagram for branch clocks ++ * ++ * +------------------------------+ ++ * | DP_VCO_CLK | ++ * | | ++ * | +-------------------+ | ++ * | | (DP PLL/VCO) | | ++ * | +---------+---------+ | ++ * | v | ++ * | +----------+-----------+ | ++ * | | hsclk_divsel_clk_src | | ++ * | +----------+-----------+ | ++ * +------------------------------+ ++ * | ++ * +---------<---------v------------>----------+ ++ * | | ++ * +--------v----------------+ | ++ * | dp_phy_pll_link_clk | | ++ * | link_clk | | ++ * +--------+----------------+ | ++ * | | ++ * | | ++ * v v ++ * Input to DISPCC block | ++ * for link clk, crypto clk | ++ * and interface clock | ++ * | ++ * | ++ * +--------<------------+-----------------+---<---+ ++ * | | | ++ * +----v---------+ +--------v-----+ +--------v------+ ++ * | vco_divided | | vco_divided | | vco_divided | ++ * | _clk_src | | _clk_src | | _clk_src | ++ * | | | | | | ++ * |divsel_six | | divsel_two | | divsel_four | ++ * +-------+------+ +-----+--------+ +--------+------+ ++ * | | | ++ * v---->----------v-------------<------v ++ * | ++ * +----------+-----------------+ ++ * | dp_phy_pll_vco_div_clk | ++ * +---------+------------------+ ++ * | ++ * v ++ * Input to DISPCC block ++ * for DP pixel clock ++ * ++ */ ++static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 1620000000UL / 2: ++ case 2700000000UL / 2: ++ /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ return 1620000000UL / 2; ++ case 2700: ++ return 2700000000UL / 2; ++ case 5400: ++ return 5400000000UL / 4; ++ case 8100: ++ return 8100000000UL / 6; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { ++ .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, ++}; ++ ++static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 162000000: ++ case 270000000: ++ case 540000000: ++ case 810000000: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ return dp_opts->link_rate * 100000; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_link_clk_ops = { ++ .determine_rate = qcom_qmp_dp_link_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, ++}; ++ ++static struct clk_hw * ++qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct qmp_phy_dp_clks *dp_clks = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx >= 2) { ++ pr_err("%s: invalid index %u\n", __func__, idx); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (idx == 0) ++ return &dp_clks->dp_link_hw; ++ ++ return &dp_clks->dp_pixel_hw; ++} ++ ++static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, ++ struct device_node *np) ++{ ++ struct clk_init_data init = { }; ++ struct qmp_phy_dp_clks *dp_clks; ++ char name[64]; ++ int ret; ++ ++ dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); ++ if (!dp_clks) ++ return -ENOMEM; ++ ++ dp_clks->qphy = qphy; ++ qphy->dp_clks = dp_clks; ++ ++ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_link_clk_ops; ++ init.name = name; ++ dp_clks->dp_link_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); ++ if (ret) ++ return ret; ++ ++ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_pixel_clk_ops; ++ init.name = name; ++ dp_clks->dp_pixel_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++static const struct phy_ops qcom_qmp_phy_gen_ops = { ++ .init = qcom_qmp_phy_enable, ++ .exit = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_phy_dp_ops = { ++ .init = qcom_qmp_phy_init, ++ .configure = qcom_qmp_dp_phy_configure, ++ .power_on = qcom_qmp_phy_power_on, ++ .calibrate = qcom_qmp_dp_phy_calibrate, ++ .power_off = qcom_qmp_phy_power_off, ++ .exit = qcom_qmp_phy_exit, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_pcie_ufs_ops = { ++ .power_on = qcom_qmp_phy_enable, ++ .power_off = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static void qcom_qmp_reset_control_put(void *data) ++{ ++ reset_control_put(data); ++} ++ ++static ++int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++ void __iomem *serdes, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct phy *generic_phy; ++ struct qmp_phy *qphy; ++ const struct phy_ops *ops; ++ char prop_name[MAX_PROP_NAME]; ++ int ret; ++ ++ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); ++ if (!qphy) ++ return -ENOMEM; ++ ++ qphy->cfg = cfg; ++ qphy->serdes = serdes; ++ /* ++ * Get memory resources for each phy lane: ++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. ++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 ++ * For single lane PHYs: pcs_misc (optional) -> 3. ++ */ ++ qphy->tx = of_iomap(np, 0); ++ if (!qphy->tx) ++ return -ENOMEM; ++ ++ qphy->rx = of_iomap(np, 1); ++ if (!qphy->rx) ++ return -ENOMEM; ++ ++ qphy->pcs = of_iomap(np, 2); ++ if (!qphy->pcs) ++ return -ENOMEM; ++ ++ /* ++ * If this is a dual-lane PHY, then there should be registers for the ++ * second lane. Some old device trees did not specify this, so fall ++ * back to old legacy behavior of assuming they can be reached at an ++ * offset from the first lane. ++ */ ++ if (cfg->is_dual_lane_phy) { ++ qphy->tx2 = of_iomap(np, 3); ++ qphy->rx2 = of_iomap(np, 4); ++ if (!qphy->tx2 || !qphy->rx2) { ++ dev_warn(dev, ++ "Underspecified device tree, falling back to legacy register regions\n"); ++ ++ /* In the old version, pcs_misc is at index 3. */ ++ qphy->pcs_misc = qphy->tx2; ++ qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; ++ qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 5); ++ } ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 3); ++ } ++ ++ if (!qphy->pcs_misc) ++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ ++ /* ++ * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 ++ * based phys, so they essentially have pipe clock. So, ++ * we return error in case phy is USB3 or PIPE type. ++ * Otherwise, we initialize pipe clock to NULL for ++ * all phys that don't need this. ++ */ ++ snprintf(prop_name, sizeof(prop_name), "pipe%d", id); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ if (IS_ERR(qphy->pipe_clk)) { ++ if (cfg->type == PHY_TYPE_PCIE || ++ cfg->type == PHY_TYPE_USB3) { ++ ret = PTR_ERR(qphy->pipe_clk); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to get lane%d pipe_clk, %d\n", ++ id, ret); ++ return ret; ++ } ++ qphy->pipe_clk = NULL; ++ } ++ ++ /* Get lane reset, if any */ ++ if (cfg->has_lane_rst) { ++ snprintf(prop_name, sizeof(prop_name), "lane%d", id); ++ qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); ++ if (IS_ERR(qphy->lane_rst)) { ++ dev_err(dev, "failed to get lane%d reset\n", id); ++ return PTR_ERR(qphy->lane_rst); ++ } ++ ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put, ++ qphy->lane_rst); ++ if (ret) ++ return ret; ++ } ++ ++ if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) ++ ops = &qcom_qmp_pcie_ufs_ops; ++ else if (cfg->type == PHY_TYPE_DP) ++ ops = &qcom_qmp_phy_dp_ops; ++ else ++ ops = &qcom_qmp_phy_gen_ops; ++ ++ generic_phy = devm_phy_create(dev, np, ops); ++ if (IS_ERR(generic_phy)) { ++ ret = PTR_ERR(generic_phy); ++ dev_err(dev, "failed to create qphy %d\n", ret); ++ return ret; ++ } ++ ++ qphy->phy = generic_phy; ++ qphy->index = id; ++ qphy->qmp = qmp; ++ qmp->phys[id] = qphy; ++ phy_set_drvdata(generic_phy, qphy); ++ ++ return 0; ++} ++ ++static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,ipq8074-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-pcie-phy", ++ .data = &msm8996_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-ufs-phy", ++ .data = &msm8996_ufs_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-usb3-phy", ++ .data = &msm8996_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-pcie-phy", ++ .data = &msm8998_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,ipq8074-qmp-pcie-phy", ++ .data = &ipq8074_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-pcie-phy", ++ .data = &ipq6018_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-phy", ++ .data = &sc7180_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sc8180x-qmp-pcie-phy", ++ .data = &sc8180x_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8280xp-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sdm845-qhp-pcie-phy", ++ .data = &sdm845_qhp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-pcie-phy", ++ .data = &sdm845_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-phy", ++ .data = &qmp_v3_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-uni-phy", ++ .data = &qmp_v3_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-usb3-phy", ++ .data = &msm8998_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm6115-qmp-ufs-phy", ++ .data = &sm6115_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm6350-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-uni-phy", ++ .data = &sm8150_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-phy", ++ .data = &sm8250_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-uni-phy", ++ .data = &sm8250_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy", ++ .data = &sm8250_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-modem-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-pcie-phy", ++ .data = &sdx55_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-usb3-uni-phy", ++ .data = &sdx55_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdx65-qmp-usb3-uni-phy", ++ .data = &sdx65_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-uni-phy", ++ .data = &sm8350_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy", ++ .data = &sm8450_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy", ++ .data = &sm8450_qmp_gen4x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-ufs-phy", ++ .data = &sm8450_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,qcm2290-qmp-usb3-phy", ++ .data = &qcm2290_usb3phy_cfg, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++ ++static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ .data = &sc7180_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ .data = &sm8250_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ .data = &sc8180x_usb3dpphy_cfg, ++ }, ++ { } ++}; ++ ++static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, ++ qcom_qmp_phy_runtime_resume, NULL) ++}; ++ ++static int qcom_qmp_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_qmp *qmp; ++ struct device *dev = &pdev->dev; ++ struct device_node *child; ++ struct phy_provider *phy_provider; ++ void __iomem *serdes; ++ void __iomem *usb_serdes; ++ void __iomem *dp_serdes = NULL; ++ const struct qmp_phy_combo_cfg *combo_cfg = NULL; ++ const struct qmp_phy_cfg *cfg = NULL; ++ const struct qmp_phy_cfg *usb_cfg = NULL; ++ const struct qmp_phy_cfg *dp_cfg = NULL; ++ int num, id, expected_phys; ++ int ret; ++ ++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); ++ if (!qmp) ++ return -ENOMEM; ++ ++ qmp->dev = dev; ++ dev_set_drvdata(dev, qmp); ++ ++ /* Get the specific init parameters of QMP phy */ ++ cfg = of_device_get_match_data(dev); ++ if (!cfg) { ++ const struct of_device_id *match; ++ ++ match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); ++ if (!match) ++ return -EINVAL; ++ ++ combo_cfg = match->data; ++ if (!combo_cfg) ++ return -EINVAL; ++ ++ usb_cfg = combo_cfg->usb_cfg; ++ cfg = usb_cfg; /* Setup clks and regulators */ ++ } ++ ++ /* per PHY serdes; usually located at base address */ ++ usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(serdes)) ++ return PTR_ERR(serdes); ++ ++ /* per PHY dp_com; if PHY has dp_com control block */ ++ if (combo_cfg || cfg->has_phy_dp_com_ctrl) { ++ qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(qmp->dp_com)) ++ return PTR_ERR(qmp->dp_com); ++ } ++ ++ if (combo_cfg) { ++ /* Only two serdes for combo PHY */ ++ dp_serdes = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(dp_serdes)) ++ return PTR_ERR(dp_serdes); ++ ++ dp_cfg = combo_cfg->dp_cfg; ++ expected_phys = 2; ++ } else { ++ expected_phys = cfg->nlanes; ++ } ++ ++ mutex_init(&qmp->phy_mutex); ++ ++ ret = qcom_qmp_phy_clk_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_reset_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get regulator supplies: %d\n", ++ ret); ++ return ret; ++ } ++ ++ num = of_get_available_child_count(dev->of_node); ++ /* do we have a rogue child node ? */ ++ if (num > expected_phys) ++ return -EINVAL; ++ ++ qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); ++ if (!qmp->phys) ++ return -ENOMEM; ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ /* ++ * Prevent runtime pm from being ON by default. Users can enable ++ * it using power/control in sysfs. ++ */ ++ pm_runtime_forbid(dev); ++ ++ id = 0; ++ for_each_available_child_of_node(dev->of_node, child) { ++ if (of_node_name_eq(child, "dp-phy")) { ++ cfg = dp_cfg; ++ serdes = dp_serdes; ++ } else if (of_node_name_eq(child, "usb3-phy")) { ++ cfg = usb_cfg; ++ serdes = usb_serdes; ++ } ++ ++ /* Create per-lane phy */ ++ ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ if (ret) { ++ dev_err(dev, "failed to create lane%d phy, %d\n", ++ id, ret); ++ goto err_node_put; ++ } ++ ++ /* ++ * Register the pipe clock provided by phy. ++ * See function description to see details of this pipe clock. ++ */ ++ if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; ++ } ++ } else if (cfg->type == PHY_TYPE_DP) { ++ ret = phy_dp_clks_register(qmp, qmp->phys[id], child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register DP clock source\n"); ++ goto err_node_put; ++ } ++ } ++ id++; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (!IS_ERR(phy_provider)) ++ dev_info(dev, "Registered Qcom-QMP phy\n"); ++ else ++ pm_runtime_disable(dev); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++ ++err_node_put: ++ pm_runtime_disable(dev); ++ of_node_put(child); ++ return ret; ++} ++ ++static struct platform_driver qcom_qmp_phy_driver = { ++ .probe = qcom_qmp_phy_probe, ++ .driver = { ++ .name = "qcom-qmp-phy", ++ .pm = &qcom_qmp_phy_pm_ops, ++ .of_match_table = qcom_qmp_phy_of_match_table, ++ }, ++}; ++ ++module_platform_driver(qcom_qmp_phy_driver); ++ ++MODULE_AUTHOR("Vivek Gautam "); ++MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +new file mode 100644 +index 000000000000..c7309e981bfb +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -0,0 +1,6350 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "phy-qcom-qmp.h" ++ ++/* QPHY_SW_RESET bit */ ++#define SW_RESET BIT(0) ++/* QPHY_POWER_DOWN_CONTROL */ ++#define SW_PWRDN BIT(0) ++#define REFCLK_DRV_DSBL BIT(1) ++/* QPHY_START_CONTROL bits */ ++#define SERDES_START BIT(0) ++#define PCS_START BIT(1) ++#define PLL_READY_GATE_EN BIT(3) ++/* QPHY_PCS_STATUS bit */ ++#define PHYSTATUS BIT(6) ++#define PHYSTATUS_4_20 BIT(7) ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ ++#define PCS_READY BIT(0) ++ ++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ ++/* DP PHY soft reset */ ++#define SW_DPPHY_RESET BIT(0) ++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ ++#define SW_DPPHY_RESET_MUX BIT(1) ++/* USB3 PHY soft reset */ ++#define SW_USB3PHY_RESET BIT(2) ++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ ++#define SW_USB3PHY_RESET_MUX BIT(3) ++ ++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ ++#define USB3_MODE BIT(0) /* enables USB3 mode */ ++#define DP_MODE BIT(1) /* enables DP mode */ ++ ++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ ++#define ARCVR_DTCT_EN BIT(0) ++#define ALFPS_DTCT_EN BIT(1) ++#define ARCVR_DTCT_EVENT_SEL BIT(4) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ ++#define IRQ_CLEAR BIT(0) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ ++#define RCVR_DETECT BIT(0) ++ ++/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ ++#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ ++ ++#define PHY_INIT_COMPLETE_TIMEOUT 10000 ++#define POWER_DOWN_DELAY_US_MIN 10 ++#define POWER_DOWN_DELAY_US_MAX 11 ++ ++#define MAX_PROP_NAME 32 ++ ++/* Define the assumed distance between lanes for underspecified device trees. */ ++#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 ++ ++struct qmp_phy_init_tbl { ++ unsigned int offset; ++ unsigned int val; ++ /* ++ * register part of layout ? ++ * if yes, then offset gives index in the reg-layout ++ */ ++ bool in_layout; ++ /* ++ * mask of lanes for which this register is written ++ * for cases when second lane needs different values ++ */ ++ u8 lane_mask; ++}; ++ ++#define QMP_PHY_INIT_CFG(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_L(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .in_layout = true, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = l, \ ++ } ++ ++/* set of registers with offsets different per-PHY */ ++enum qphy_reg_layout { ++ /* Common block control registers */ ++ QPHY_COM_SW_RESET, ++ QPHY_COM_POWER_DOWN_CONTROL, ++ QPHY_COM_START_CONTROL, ++ QPHY_COM_PCS_READY_STATUS, ++ /* PCS registers */ ++ QPHY_PLL_LOCK_CHK_DLY_TIME, ++ QPHY_FLL_CNTRL1, ++ QPHY_FLL_CNTRL2, ++ QPHY_FLL_CNT_VAL_L, ++ QPHY_FLL_CNT_VAL_H_TOL, ++ QPHY_FLL_MAN_CODE, ++ QPHY_SW_RESET, ++ QPHY_START_CTRL, ++ QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, ++ QPHY_PCS_AUTONOMOUS_MODE_CTRL, ++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, ++ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, ++ QPHY_PCS_POWER_DOWN_CONTROL, ++ /* PCS_MISC registers */ ++ QPHY_PCS_MISC_TYPEC_CTRL, ++ /* Keep last to ensure regs_layout arrays are properly initialized */ ++ QPHY_LAYOUT_SIZE ++}; ++ ++static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_COM_SW_RESET] = 0x400, ++ [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, ++ [QPHY_COM_START_CONTROL] = 0x408, ++ [QPHY_COM_PCS_READY_STATUS] = 0x448, ++ [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, ++ [QPHY_FLL_CNTRL1] = 0xc4, ++ [QPHY_FLL_CNTRL2] = 0xc8, ++ [QPHY_FLL_CNT_VAL_L] = 0xcc, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, ++ [QPHY_FLL_MAN_CODE] = 0xd4, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_FLL_CNTRL1] = 0xc0, ++ [QPHY_FLL_CNTRL2] = 0xc4, ++ [QPHY_FLL_CNT_VAL_L] = 0xc8, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, ++ [QPHY_FLL_MAN_CODE] = 0xd0, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x17c, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++}; ++ ++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++}; ++ ++static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x2ac, ++}; ++ ++static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x308, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x314, ++}; ++ ++static const unsigned int qmp_v4_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x608, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x614, ++}; ++ ++static const unsigned int sm8350_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x1008, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x1014, ++}; ++ ++static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0xd8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0xdc, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_MISC_TYPEC_CTRL] = 0x00, ++}; ++ ++static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x160, ++}; ++ ++static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, ++ [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, ++ [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), ++ ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4), ++ QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe), ++ QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0), ++ QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1), ++ ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x95), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x26), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x048), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_PLL_CNTL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB, 0xd8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_PWM_GEAR_BAND, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HS_GEAR_BAND, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xd8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_TX_ADAPT_POST_THRESH, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0xd0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_RX, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0xc5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xad), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xb6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xc7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x05), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), ++}; ++ ++/* Register names should be validated, they might be different for this PHY */ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), ++}; ++ ++struct qmp_phy; ++ ++/* struct qmp_phy_cfg - per-PHY initialization config */ ++struct qmp_phy_cfg { ++ /* phy-type - PCIE/UFS/USB */ ++ unsigned int type; ++ /* number of lanes provided by phy */ ++ int nlanes; ++ ++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_init_tbl *serdes_tbl; ++ int serdes_tbl_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_sec; ++ int serdes_tbl_num_sec; ++ const struct qmp_phy_init_tbl *tx_tbl; ++ int tx_tbl_num; ++ const struct qmp_phy_init_tbl *tx_tbl_sec; ++ int tx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *rx_tbl; ++ int rx_tbl_num; ++ const struct qmp_phy_init_tbl *rx_tbl_sec; ++ int rx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_tbl; ++ int pcs_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_tbl_sec; ++ int pcs_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl; ++ int pcs_misc_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; ++ int pcs_misc_tbl_num_sec; ++ ++ /* Init sequence for DP PHY block link rates */ ++ const struct qmp_phy_init_tbl *serdes_tbl_rbr; ++ int serdes_tbl_rbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr; ++ int serdes_tbl_hbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr2; ++ int serdes_tbl_hbr2_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr3; ++ int serdes_tbl_hbr3_num; ++ ++ /* DP PHY callbacks */ ++ int (*configure_dp_phy)(struct qmp_phy *qphy); ++ void (*configure_dp_tx)(struct qmp_phy *qphy); ++ int (*calibrate_dp_phy)(struct qmp_phy *qphy); ++ void (*dp_aux_init)(struct qmp_phy *qphy); ++ ++ /* clock ids to be requested */ ++ const char * const *clk_list; ++ int num_clks; ++ /* resets to be requested */ ++ const char * const *reset_list; ++ int num_resets; ++ /* regulators to be requested */ ++ const char * const *vreg_list; ++ int num_vregs; ++ ++ /* array of registers with different offsets */ ++ const unsigned int *regs; ++ ++ unsigned int start_ctrl; ++ unsigned int pwrdn_ctrl; ++ unsigned int mask_com_pcs_ready; ++ /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ ++ unsigned int phy_status; ++ ++ /* true, if PHY has a separate PHY_COM control block */ ++ bool has_phy_com_ctrl; ++ /* true, if PHY has a reset for individual lanes */ ++ bool has_lane_rst; ++ /* true, if PHY needs delay after POWER_DOWN */ ++ bool has_pwrdn_delay; ++ /* power_down delay in usec */ ++ int pwrdn_delay_min; ++ int pwrdn_delay_max; ++ ++ /* true, if PHY has a separate DP_COM control block */ ++ bool has_phy_dp_com_ctrl; ++ /* true, if PHY has secondary tx/rx lanes to be configured */ ++ bool is_dual_lane_phy; ++ ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; ++}; ++ ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; ++}; ++ ++/** ++ * struct qmp_phy - per-lane phy descriptor ++ * ++ * @phy: generic phy ++ * @cfg: phy specific configuration ++ * @serdes: iomapped memory space for phy's serdes (i.e. PLL) ++ * @tx: iomapped memory space for lane's tx ++ * @rx: iomapped memory space for lane's rx ++ * @pcs: iomapped memory space for lane's pcs ++ * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) ++ * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) ++ * @pcs_misc: iomapped memory space for lane's pcs_misc ++ * @pipe_clk: pipe clock ++ * @index: lane index ++ * @qmp: QMP phy to which this lane belongs ++ * @lane_rst: lane's reset controller ++ * @mode: current PHY mode ++ * @dp_aux_cfg: Display port aux config ++ * @dp_opts: Display port optional config ++ * @dp_clks: Display port clocks ++ */ ++struct qmp_phy { ++ struct phy *phy; ++ const struct qmp_phy_cfg *cfg; ++ void __iomem *serdes; ++ void __iomem *tx; ++ void __iomem *rx; ++ void __iomem *pcs; ++ void __iomem *tx2; ++ void __iomem *rx2; ++ void __iomem *pcs_misc; ++ struct clk *pipe_clk; ++ unsigned int index; ++ struct qcom_qmp *qmp; ++ struct reset_control *lane_rst; ++ enum phy_mode mode; ++ unsigned int dp_aux_cfg; ++ struct phy_configure_opts_dp dp_opts; ++ struct qmp_phy_dp_clks *dp_clks; ++}; ++ ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; ++ ++/** ++ * struct qcom_qmp - structure holding QMP phy block attributes ++ * ++ * @dev: device ++ * @dp_com: iomapped memory space for phy's dp_com control block ++ * ++ * @clks: array of clocks required by phy ++ * @resets: array of resets required by phy ++ * @vregs: regulator supplies bulk data ++ * ++ * @phys: array of per-lane phy descriptors ++ * @phy_mutex: mutex lock for PHY common block initialization ++ * @init_count: phy common block initialization count ++ * @ufs_reset: optional UFS PHY reset handle ++ */ ++struct qcom_qmp { ++ struct device *dev; ++ void __iomem *dp_com; ++ ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; ++ ++ struct qmp_phy **phys; ++ ++ struct mutex phy_mutex; ++ int init_count; ++ ++ struct reset_control *ufs_reset; ++}; ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", ++}; ++ ++static const char * const msm8996_ufs_phy_clk_l[] = { ++ "ref", ++}; ++ ++static const char * const qmp_v3_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "com_aux", ++}; ++ ++static const char * const sdm845_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "refgen", ++}; ++ ++static const char * const qmp_v4_phy_clk_l[] = { ++ "aux", "ref_clk_src", "ref", "com_aux", ++}; ++ ++/* the primary usb3 phy on sm8250 doesn't have a ref clock */ ++static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { ++ "aux", "ref_clk_src", "com_aux" ++}; ++ ++static const char * const sm8450_ufs_phy_clk_l[] = { ++ "qref", "ref", "ref_aux", ++}; ++ ++static const char * const sdm845_ufs_phy_clk_l[] = { ++ "ref", "ref_aux", ++}; ++ ++/* usb3 phy on sdx55 doesn't have com_aux clock */ ++static const char * const qmp_v4_sdx55_usbphy_clk_l[] = { ++ "aux", "cfg_ahb", "ref" ++}; ++ ++static const char * const qcm2290_usb3phy_clk_l[] = { ++ "cfg_ahb", "ref", "com_aux", ++}; ++ ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", ++}; ++ ++static const char * const msm8996_usb3phy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const char * const sc7180_usb3phy_reset_l[] = { ++ "phy", ++}; ++ ++static const char * const qcm2290_usb3phy_reset_l[] = { ++ "phy_phy", "phy", ++}; ++ ++static const char * const sdm845_pciephy_reset_l[] = { ++ "phy", ++}; ++ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = ipq8074_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), ++ .pcs_tbl = ipq8074_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, ++ ++ .serdes_tbl = msm8996_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), ++ .tx_tbl = msm8996_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), ++ .rx_tbl = msm8996_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), ++ .pcs_tbl = msm8996_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = true, ++ .has_lane_rst = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg msm8996_ufs_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_ufs_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), ++ .tx_tbl = msm8996_ufs_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl), ++ .rx_tbl = msm8996_ufs_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl), ++ ++ .clk_list = msm8996_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l), ++ ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ ++ .regs = msm8996_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = msm8996_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), ++ .pcs_tbl = msm8996_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const char * const ipq8074_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", ++}; ++/* list of resets */ ++static const char * const ipq8074_pciephy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx_tbl = ipq8074_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx_tbl = ipq8074_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs_tbl = ipq8074_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq6018_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx_tbl = ipq6018_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx_tbl = ipq6018_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs_tbl = ipq6018_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = ipq_pciephy_gen3_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qmp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qhp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qhp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qhp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), ++ .tx_tbl = qmp_v3_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { ++ .usb_cfg = &sc7180_usb3phy_cfg, ++ .dp_cfg = &sc7180_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdm845_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), ++ .tx_tbl = sdm845_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), ++ .rx_tbl = sdm845_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), ++ .pcs_tbl = sdm845_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm6115_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), ++ .tx_tbl = sm6115_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), ++ .rx_tbl = sm6115_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), ++ .pcs_tbl = sm6115_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm6115_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ ++ .is_dual_lane_phy = false, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8998_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx_tbl = msm8998_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx_tbl = msm8998_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs_tbl = msm8998_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), ++ .tx_tbl = msm8998_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl), ++ .rx_tbl = msm8998_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), ++ .pcs_tbl = msm8998_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8150_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), ++ .tx_tbl = sm8150_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_tx_tbl), ++ .rx_tbl = sm8150_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_rx_tbl), ++ .pcs_tbl = sm8150_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8150_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), ++ .rx_tbl = sm8150_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), ++ .pcs_tbl = sm8150_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx_tbl = sc8180x_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx_tbl = sc8180x_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { ++ .usb_cfg = &sm8150_usb3phy_cfg, ++ .dp_cfg = &sc8180x_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8150_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8150_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8150_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8250_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), ++ .rx_tbl = sm8250_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), ++ .pcs_tbl = sm8250_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8250_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8250_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { ++ .usb_cfg = &sm8250_usb3phy_cfg, ++ .dp_cfg = &sm8250_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx55_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx55_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdx55_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx_tbl = sdx55_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx65_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx65_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8350_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), ++ .rx_tbl = sm8350_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), ++ .pcs_tbl = sm8350_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8350_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8350_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sm8450_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qcm2290_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ++ .tx_tbl = qcm2290_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), ++ .rx_tbl = qcm2290_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), ++ .pcs_tbl = qcm2290_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), ++ .clk_list = qcm2290_usb3phy_clk_l, ++ .num_clks = ARRAY_SIZE(qcm2290_usb3phy_clk_l), ++ .reset_list = qcm2290_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qcm2290_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static void qcom_qmp_phy_configure_lane(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num, ++ u8 lane_mask) ++{ ++ int i; ++ const struct qmp_phy_init_tbl *t = tbl; ++ ++ if (!t) ++ return; ++ ++ for (i = 0; i < num; i++, t++) { ++ if (!(t->lane_mask & lane_mask)) ++ continue; ++ ++ if (t->in_layout) ++ writel(t->val, base + regs[t->offset]); ++ else ++ writel(t->val, base + t->offset); ++ } ++} ++ ++static void qcom_qmp_phy_configure(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num) ++{ ++ qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); ++} ++ ++static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; ++ int serdes_tbl_num = cfg->serdes_tbl_num; ++ int ret; ++ ++ qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ if (cfg->serdes_tbl_sec) ++ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, ++ cfg->serdes_tbl_num_sec); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ switch (dp_opts->link_rate) { ++ case 1620: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_rbr, ++ cfg->serdes_tbl_rbr_num); ++ break; ++ case 2700: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr, ++ cfg->serdes_tbl_hbr_num); ++ break; ++ case 5400: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr2, ++ cfg->serdes_tbl_hbr2_num); ++ break; ++ case 8100: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr3, ++ cfg->serdes_tbl_hbr3_num); ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ } ++ ++ ++ if (cfg->has_phy_com_ctrl) { ++ void __iomem *status; ++ unsigned int mask, val; ++ ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ ++ status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; ++ mask = cfg->mask_com_pcs_ready; ++ ++ ret = readl_poll_timeout(status, val, (val & mask), 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, ++ "phy common block init timed-out\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_LANE_0_1_PWRDN | ++ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | ++ DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(QSERDES_V3_COM_BIAS_EN | ++ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | ++ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { ++ { 0x00, 0x0c, 0x15, 0x1a }, ++ { 0x02, 0x0e, 0x16, 0xff }, ++ { 0x02, 0x11, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { ++ { 0x02, 0x12, 0x16, 0x1a }, ++ { 0x09, 0x19, 0x1f, 0xff }, ++ { 0x10, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { ++ { 0x00, 0x0c, 0x14, 0x19 }, ++ { 0x00, 0x0b, 0x12, 0xff }, ++ { 0x00, 0x0b, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { ++ { 0x08, 0x0f, 0x16, 0x1f }, ++ { 0x11, 0x1e, 0x1f, 0xff }, ++ { 0x19, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, ++ unsigned int drv_lvl_reg, unsigned int emp_post_reg) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ unsigned int v_level = 0, p_level = 0; ++ u8 voltage_swing_cfg, pre_emphasis_cfg; ++ int i; ++ ++ for (i = 0; i < dp_opts->lanes; i++) { ++ v_level = max(v_level, dp_opts->voltage[i]); ++ p_level = max(p_level, dp_opts->pre[i]); ++ } ++ ++ if (dp_opts->link_rate <= 2700) { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; ++ } else { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; ++ } ++ ++ /* TODO: Move check to config check */ ++ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) ++ return -EINVAL; ++ ++ /* Enable MUX to use Cursor values from these registers */ ++ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; ++ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; ++ ++ writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); ++ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 bias_en, drvr_en; ++ ++ if (qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V3_TX_TX_DRV_LVL, ++ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) ++ return; ++ ++ if (dp_opts->lanes == 1) { ++ bias_en = 0x3e; ++ drvr_en = 0x13; ++ } else { ++ bias_en = 0x3f; ++ drvr_en = 0x10; ++ } ++ ++ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++} ++ ++static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) ++{ ++ u32 val; ++ bool reverse = false; ++ ++ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ++ ++ /* ++ * TODO: Assume orientation is CC1 for now and two lanes, need to ++ * use type-c connector to understand orientation and lanes. ++ * ++ * Otherwise val changes to be like below if this code understood ++ * the orientation of the type-c cable. ++ * ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) ++ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) ++ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ * if (orientation == ORIENTATION_CC2) ++ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); ++ */ ++ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); ++ ++ return reverse; ++} ++ ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ ++ qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000); ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ /* Program default values before writing proper values */ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V4_TX_TX_DRV_LVL, ++ QSERDES_V4_TX_TX_EMP_POST1_LVL); ++} ++ ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ u32 bias0_en, drvr0_en, bias1_en, drvr1_en; ++ bool reverse; ++ ++ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); ++ ++ reverse = qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ /* ++ * At least for 7nm DP PHY this has to be done after enabling link ++ * clock. ++ */ ++ ++ if (dp_opts->lanes == 1) { ++ bias0_en = reverse ? 0x3e : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3e; ++ drvr0_en = reverse ? 0x13 : 0x10; ++ drvr1_en = reverse ? 0x10 : 0x13; ++ } else if (dp_opts->lanes == 2) { ++ bias0_en = reverse ? 0x3f : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } else { ++ bias0_en = 0x3f; ++ bias1_en = 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } ++ ++ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); ++ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); ++ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ return 0; ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); ++ if (qphy->dp_opts.set_voltages) { ++ cfg->configure_dp_tx(qphy); ++ qphy->dp_opts.set_voltages = 0; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_calibrate(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->calibrate_dp_phy) ++ return cfg->calibrate_dp_phy(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *dp_com = qmp->dp_com; ++ int ret, i; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (qmp->init_count++) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ /* turn on regulator supplies */ ++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); ++ if (ret) { ++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); ++ goto err_unlock; ++ } ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ ret = reset_control_assert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset assert failed\n", ++ cfg->reset_list[i]); ++ goto err_disable_regulators; ++ } ++ } ++ ++ for (i = cfg->num_resets - 1; i >= 0; i--) { ++ ret = reset_control_deassert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset deassert failed\n", ++ qphy->cfg->reset_list[i]); ++ goto err_assert_reset; ++ } ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ goto err_assert_reset; ++ ++ if (cfg->has_phy_dp_com_ctrl) { ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, ++ SW_PWRDN); ++ /* override hardware control for reset of qmp phy */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ /* Default type-c orientation, i.e CC1 */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); ++ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, ++ USB3_MODE | DP_MODE); ++ ++ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); ++ } ++ ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } else { ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(pcs, ++ cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ else ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++ ++err_assert_reset: ++ while (++i < cfg->num_resets) ++ reset_control_assert(qmp->resets[i]); ++err_disable_regulators: ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++err_unlock: ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ int i = cfg->num_resets; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (--qmp->init_count) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ reset_control_assert(qmp->ufs_reset); ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], ++ SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } ++ ++ while (--i >= 0) ++ reset_control_assert(qmp->resets[i]); ++ ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_init(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret; ++ dev_vdbg(qmp->dev, "Initializing QMP phy\n"); ++ ++ if (cfg->no_pcs_sw_reset) { ++ /* ++ * Get UFS reset, which is delayed until now to avoid a ++ * circular dependency where UFS needs its PHY, but the PHY ++ * needs this UFS reset. ++ */ ++ if (!qmp->ufs_reset) { ++ qmp->ufs_reset = ++ devm_reset_control_get_exclusive(qmp->dev, ++ "ufsphy"); ++ ++ if (IS_ERR(qmp->ufs_reset)) { ++ ret = PTR_ERR(qmp->ufs_reset); ++ dev_err(qmp->dev, ++ "failed to get UFS reset: %d\n", ++ ret); ++ ++ qmp->ufs_reset = NULL; ++ return ret; ++ } ++ } ++ ++ ret = reset_control_assert(qmp->ufs_reset); ++ if (ret) ++ return ret; ++ } ++ ++ ret = qcom_qmp_phy_com_init(qphy); ++ if (ret) ++ return ret; ++ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->dp_aux_init(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_power_on(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ void __iomem *status; ++ unsigned int mask, val, ready; ++ int ret; ++ ++ qcom_qmp_phy_serdes_init(qphy); ++ ++ if (cfg->has_lane_rst) { ++ ret = reset_control_deassert(qphy->lane_rst); ++ if (ret) { ++ dev_err(qmp->dev, "lane%d reset deassert failed\n", ++ qphy->index); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); ++ goto err_reset_lane; ++ } ++ ++ /* Tx, Rx, and PCS configurations */ ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 1); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 1); ++ ++ /* Configuration for other LANE for USB-DP combo PHY */ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 2); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 2); ++ } ++ ++ /* Configure special DP tx tunings */ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->configure_dp_tx(qphy); ++ ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 1); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); ++ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 2); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl_sec, ++ cfg->rx_tbl_num_sec, 2); ++ } ++ ++ /* Configure link rate, swing, etc. */ ++ if (cfg->type == PHY_TYPE_DP) { ++ cfg->configure_dp_phy(qphy); ++ } else { ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); ++ } ++ ++ ret = reset_control_deassert(qmp->ufs_reset); ++ if (ret) ++ goto err_disable_pipe_clk; ++ ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ cfg->pcs_misc_tbl_num); ++ if (cfg->pcs_misc_tbl_sec) ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, ++ cfg->pcs_misc_tbl_num_sec); ++ ++ /* ++ * Pull out PHY from POWER DOWN state. ++ * This is active low enable signal to power-down PHY. ++ */ ++ if(cfg->type == PHY_TYPE_PCIE) ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); ++ ++ if (cfg->has_pwrdn_delay) ++ usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ ++ if (cfg->type != PHY_TYPE_DP) { ++ /* Pull PHY out of reset state */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ /* start SerDes and Phy-Coding-Sublayer */ ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = cfg->phy_status; ++ ready = 0; ++ } ++ ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, "phy initialization timed-out\n"); ++ goto err_disable_pipe_clk; ++ } ++ } ++ return 0; ++ ++err_disable_pipe_clk: ++ clk_disable_unprepare(qphy->pipe_clk); ++err_reset_lane: ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_power_off(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ /* Assert DP PHY power down */ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ } else { ++ /* PHY reset */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ ++ /* stop SerDes and Phy-Coding-Sublayer */ ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ /* Put PHY into POWER DOWN state: active low */ ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ } else { ++ qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_exit(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ qcom_qmp_phy_com_exit(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_enable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_power_on(phy); ++ if (ret) ++ qcom_qmp_phy_exit(phy); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_disable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_power_off(phy); ++ if (ret) ++ return ret; ++ return qcom_qmp_phy_exit(phy); ++} ++ ++static int qcom_qmp_phy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ qphy->mode = mode; ++ ++ return 0; ++} ++ ++static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ u32 intr_mask; ++ ++ if (qphy->mode == PHY_MODE_USB_HOST_SS || ++ qphy->mode == PHY_MODE_USB_DEVICE_SS) ++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; ++ else ++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; ++ ++ /* Clear any pending interrupts status */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); ++ ++ /* Enable required PHY autonomous mode interrupts */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); ++ ++ /* Enable i/o clamp_n for autonomous mode */ ++ if (pcs_misc) ++ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++} ++ ++static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ /* Disable i/o clamp_n on resume for normal mode */ ++ if (pcs_misc) ++ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); ++ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ qcom_qmp_phy_enable_autonomous_mode(qphy); ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret = 0; ++ ++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ return ret; ++ } ++ ++ qcom_qmp_phy_disable_autonomous_mode(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_vregs; ++ int i; ++ ++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); ++ if (!qmp->vregs) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->vregs[i].supply = cfg->vreg_list[i]; ++ ++ return devm_regulator_bulk_get(dev, num, qmp->vregs); ++} ++ ++static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int i; ++ ++ qmp->resets = devm_kcalloc(dev, cfg->num_resets, ++ sizeof(*qmp->resets), GFP_KERNEL); ++ if (!qmp->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ struct reset_control *rst; ++ const char *name = cfg->reset_list[i]; ++ ++ rst = devm_reset_control_get_exclusive(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ return PTR_ERR(rst); ++ } ++ qmp->resets[i] = rst; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_clks; ++ int i; ++ ++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); ++ if (!qmp->clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->clks[i].id = cfg->clk_list[i]; ++ ++ return devm_clk_bulk_get(dev, num, qmp->clks); ++} ++ ++static void phy_clk_release_provider(void *res) ++{ ++ of_clk_del_provider(res); ++} ++ ++/* ++ * Register a fixed rate pipe clock. ++ * ++ * The _pipe_clksrc generated by PHY goes to the GCC that gate ++ * controls it. The _pipe_clk coming out of the GCC is requested ++ * by the PHY driver for its operations. ++ * We register the _pipe_clksrc here. The gcc driver takes care ++ * of assigning this _pipe_clksrc as parent to _pipe_clk. ++ * Below picture shows this relationship. ++ * ++ * +---------------+ ++ * | PHY block |<<---------------------------------------+ ++ * | | | ++ * | +-------+ | +-----+ | ++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ ++ * clk | +-------+ | +-----+ ++ * +---------------+ ++ */ ++static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) ++{ ++ struct clk_fixed_rate *fixed; ++ struct clk_init_data init = { }; ++ int ret; ++ ++ ret = of_property_read_string(np, "clock-output-names", &init.name); ++ if (ret) { ++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); ++ return ret; ++ } ++ ++ fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); ++ if (!fixed) ++ return -ENOMEM; ++ ++ init.ops = &clk_fixed_rate_ops; ++ ++ /* controllers using QMP phys use 125MHz pipe clock interface */ ++ fixed->fixed_rate = 125000000; ++ fixed->hw.init = &init; ++ ++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++/* ++ * Display Port PLL driver block diagram for branch clocks ++ * ++ * +------------------------------+ ++ * | DP_VCO_CLK | ++ * | | ++ * | +-------------------+ | ++ * | | (DP PLL/VCO) | | ++ * | +---------+---------+ | ++ * | v | ++ * | +----------+-----------+ | ++ * | | hsclk_divsel_clk_src | | ++ * | +----------+-----------+ | ++ * +------------------------------+ ++ * | ++ * +---------<---------v------------>----------+ ++ * | | ++ * +--------v----------------+ | ++ * | dp_phy_pll_link_clk | | ++ * | link_clk | | ++ * +--------+----------------+ | ++ * | | ++ * | | ++ * v v ++ * Input to DISPCC block | ++ * for link clk, crypto clk | ++ * and interface clock | ++ * | ++ * | ++ * +--------<------------+-----------------+---<---+ ++ * | | | ++ * +----v---------+ +--------v-----+ +--------v------+ ++ * | vco_divided | | vco_divided | | vco_divided | ++ * | _clk_src | | _clk_src | | _clk_src | ++ * | | | | | | ++ * |divsel_six | | divsel_two | | divsel_four | ++ * +-------+------+ +-----+--------+ +--------+------+ ++ * | | | ++ * v---->----------v-------------<------v ++ * | ++ * +----------+-----------------+ ++ * | dp_phy_pll_vco_div_clk | ++ * +---------+------------------+ ++ * | ++ * v ++ * Input to DISPCC block ++ * for DP pixel clock ++ * ++ */ ++static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 1620000000UL / 2: ++ case 2700000000UL / 2: ++ /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ return 1620000000UL / 2; ++ case 2700: ++ return 2700000000UL / 2; ++ case 5400: ++ return 5400000000UL / 4; ++ case 8100: ++ return 8100000000UL / 6; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { ++ .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, ++}; ++ ++static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 162000000: ++ case 270000000: ++ case 540000000: ++ case 810000000: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ return dp_opts->link_rate * 100000; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_link_clk_ops = { ++ .determine_rate = qcom_qmp_dp_link_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, ++}; ++ ++static struct clk_hw * ++qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct qmp_phy_dp_clks *dp_clks = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx >= 2) { ++ pr_err("%s: invalid index %u\n", __func__, idx); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (idx == 0) ++ return &dp_clks->dp_link_hw; ++ ++ return &dp_clks->dp_pixel_hw; ++} ++ ++static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, ++ struct device_node *np) ++{ ++ struct clk_init_data init = { }; ++ struct qmp_phy_dp_clks *dp_clks; ++ char name[64]; ++ int ret; ++ ++ dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); ++ if (!dp_clks) ++ return -ENOMEM; ++ ++ dp_clks->qphy = qphy; ++ qphy->dp_clks = dp_clks; ++ ++ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_link_clk_ops; ++ init.name = name; ++ dp_clks->dp_link_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); ++ if (ret) ++ return ret; ++ ++ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_pixel_clk_ops; ++ init.name = name; ++ dp_clks->dp_pixel_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++static const struct phy_ops qcom_qmp_phy_gen_ops = { ++ .init = qcom_qmp_phy_enable, ++ .exit = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_phy_dp_ops = { ++ .init = qcom_qmp_phy_init, ++ .configure = qcom_qmp_dp_phy_configure, ++ .power_on = qcom_qmp_phy_power_on, ++ .calibrate = qcom_qmp_dp_phy_calibrate, ++ .power_off = qcom_qmp_phy_power_off, ++ .exit = qcom_qmp_phy_exit, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_pcie_ufs_ops = { ++ .power_on = qcom_qmp_phy_enable, ++ .power_off = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static void qcom_qmp_reset_control_put(void *data) ++{ ++ reset_control_put(data); ++} ++ ++static ++int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++ void __iomem *serdes, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct phy *generic_phy; ++ struct qmp_phy *qphy; ++ const struct phy_ops *ops; ++ char prop_name[MAX_PROP_NAME]; ++ int ret; ++ ++ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); ++ if (!qphy) ++ return -ENOMEM; ++ ++ qphy->cfg = cfg; ++ qphy->serdes = serdes; ++ /* ++ * Get memory resources for each phy lane: ++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. ++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 ++ * For single lane PHYs: pcs_misc (optional) -> 3. ++ */ ++ qphy->tx = of_iomap(np, 0); ++ if (!qphy->tx) ++ return -ENOMEM; ++ ++ qphy->rx = of_iomap(np, 1); ++ if (!qphy->rx) ++ return -ENOMEM; ++ ++ qphy->pcs = of_iomap(np, 2); ++ if (!qphy->pcs) ++ return -ENOMEM; ++ ++ /* ++ * If this is a dual-lane PHY, then there should be registers for the ++ * second lane. Some old device trees did not specify this, so fall ++ * back to old legacy behavior of assuming they can be reached at an ++ * offset from the first lane. ++ */ ++ if (cfg->is_dual_lane_phy) { ++ qphy->tx2 = of_iomap(np, 3); ++ qphy->rx2 = of_iomap(np, 4); ++ if (!qphy->tx2 || !qphy->rx2) { ++ dev_warn(dev, ++ "Underspecified device tree, falling back to legacy register regions\n"); ++ ++ /* In the old version, pcs_misc is at index 3. */ ++ qphy->pcs_misc = qphy->tx2; ++ qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; ++ qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 5); ++ } ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 3); ++ } ++ ++ if (!qphy->pcs_misc) ++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ ++ /* ++ * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 ++ * based phys, so they essentially have pipe clock. So, ++ * we return error in case phy is USB3 or PIPE type. ++ * Otherwise, we initialize pipe clock to NULL for ++ * all phys that don't need this. ++ */ ++ snprintf(prop_name, sizeof(prop_name), "pipe%d", id); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ if (IS_ERR(qphy->pipe_clk)) { ++ if (cfg->type == PHY_TYPE_PCIE || ++ cfg->type == PHY_TYPE_USB3) { ++ ret = PTR_ERR(qphy->pipe_clk); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to get lane%d pipe_clk, %d\n", ++ id, ret); ++ return ret; ++ } ++ qphy->pipe_clk = NULL; ++ } ++ ++ /* Get lane reset, if any */ ++ if (cfg->has_lane_rst) { ++ snprintf(prop_name, sizeof(prop_name), "lane%d", id); ++ qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); ++ if (IS_ERR(qphy->lane_rst)) { ++ dev_err(dev, "failed to get lane%d reset\n", id); ++ return PTR_ERR(qphy->lane_rst); ++ } ++ ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put, ++ qphy->lane_rst); ++ if (ret) ++ return ret; ++ } ++ ++ if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) ++ ops = &qcom_qmp_pcie_ufs_ops; ++ else if (cfg->type == PHY_TYPE_DP) ++ ops = &qcom_qmp_phy_dp_ops; ++ else ++ ops = &qcom_qmp_phy_gen_ops; ++ ++ generic_phy = devm_phy_create(dev, np, ops); ++ if (IS_ERR(generic_phy)) { ++ ret = PTR_ERR(generic_phy); ++ dev_err(dev, "failed to create qphy %d\n", ret); ++ return ret; ++ } ++ ++ qphy->phy = generic_phy; ++ qphy->index = id; ++ qphy->qmp = qmp; ++ qmp->phys[id] = qphy; ++ phy_set_drvdata(generic_phy, qphy); ++ ++ return 0; ++} ++ ++static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,ipq8074-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-pcie-phy", ++ .data = &msm8996_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-ufs-phy", ++ .data = &msm8996_ufs_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-usb3-phy", ++ .data = &msm8996_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-pcie-phy", ++ .data = &msm8998_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,ipq8074-qmp-pcie-phy", ++ .data = &ipq8074_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-pcie-phy", ++ .data = &ipq6018_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-phy", ++ .data = &sc7180_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sc8180x-qmp-pcie-phy", ++ .data = &sc8180x_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8280xp-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sdm845-qhp-pcie-phy", ++ .data = &sdm845_qhp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-pcie-phy", ++ .data = &sdm845_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-phy", ++ .data = &qmp_v3_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-uni-phy", ++ .data = &qmp_v3_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-usb3-phy", ++ .data = &msm8998_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm6115-qmp-ufs-phy", ++ .data = &sm6115_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm6350-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-uni-phy", ++ .data = &sm8150_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-phy", ++ .data = &sm8250_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-uni-phy", ++ .data = &sm8250_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy", ++ .data = &sm8250_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-modem-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-pcie-phy", ++ .data = &sdx55_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-usb3-uni-phy", ++ .data = &sdx55_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdx65-qmp-usb3-uni-phy", ++ .data = &sdx65_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-uni-phy", ++ .data = &sm8350_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy", ++ .data = &sm8450_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy", ++ .data = &sm8450_qmp_gen4x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-ufs-phy", ++ .data = &sm8450_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,qcm2290-qmp-usb3-phy", ++ .data = &qcm2290_usb3phy_cfg, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++ ++static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ .data = &sc7180_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ .data = &sm8250_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ .data = &sc8180x_usb3dpphy_cfg, ++ }, ++ { } ++}; ++ ++static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, ++ qcom_qmp_phy_runtime_resume, NULL) ++}; ++ ++static int qcom_qmp_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_qmp *qmp; ++ struct device *dev = &pdev->dev; ++ struct device_node *child; ++ struct phy_provider *phy_provider; ++ void __iomem *serdes; ++ void __iomem *usb_serdes; ++ void __iomem *dp_serdes = NULL; ++ const struct qmp_phy_combo_cfg *combo_cfg = NULL; ++ const struct qmp_phy_cfg *cfg = NULL; ++ const struct qmp_phy_cfg *usb_cfg = NULL; ++ const struct qmp_phy_cfg *dp_cfg = NULL; ++ int num, id, expected_phys; ++ int ret; ++ ++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); ++ if (!qmp) ++ return -ENOMEM; ++ ++ qmp->dev = dev; ++ dev_set_drvdata(dev, qmp); ++ ++ /* Get the specific init parameters of QMP phy */ ++ cfg = of_device_get_match_data(dev); ++ if (!cfg) { ++ const struct of_device_id *match; ++ ++ match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); ++ if (!match) ++ return -EINVAL; ++ ++ combo_cfg = match->data; ++ if (!combo_cfg) ++ return -EINVAL; ++ ++ usb_cfg = combo_cfg->usb_cfg; ++ cfg = usb_cfg; /* Setup clks and regulators */ ++ } ++ ++ /* per PHY serdes; usually located at base address */ ++ usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(serdes)) ++ return PTR_ERR(serdes); ++ ++ /* per PHY dp_com; if PHY has dp_com control block */ ++ if (combo_cfg || cfg->has_phy_dp_com_ctrl) { ++ qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(qmp->dp_com)) ++ return PTR_ERR(qmp->dp_com); ++ } ++ ++ if (combo_cfg) { ++ /* Only two serdes for combo PHY */ ++ dp_serdes = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(dp_serdes)) ++ return PTR_ERR(dp_serdes); ++ ++ dp_cfg = combo_cfg->dp_cfg; ++ expected_phys = 2; ++ } else { ++ expected_phys = cfg->nlanes; ++ } ++ ++ mutex_init(&qmp->phy_mutex); ++ ++ ret = qcom_qmp_phy_clk_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_reset_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get regulator supplies: %d\n", ++ ret); ++ return ret; ++ } ++ ++ num = of_get_available_child_count(dev->of_node); ++ /* do we have a rogue child node ? */ ++ if (num > expected_phys) ++ return -EINVAL; ++ ++ qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); ++ if (!qmp->phys) ++ return -ENOMEM; ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ /* ++ * Prevent runtime pm from being ON by default. Users can enable ++ * it using power/control in sysfs. ++ */ ++ pm_runtime_forbid(dev); ++ ++ id = 0; ++ for_each_available_child_of_node(dev->of_node, child) { ++ if (of_node_name_eq(child, "dp-phy")) { ++ cfg = dp_cfg; ++ serdes = dp_serdes; ++ } else if (of_node_name_eq(child, "usb3-phy")) { ++ cfg = usb_cfg; ++ serdes = usb_serdes; ++ } ++ ++ /* Create per-lane phy */ ++ ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ if (ret) { ++ dev_err(dev, "failed to create lane%d phy, %d\n", ++ id, ret); ++ goto err_node_put; ++ } ++ ++ /* ++ * Register the pipe clock provided by phy. ++ * See function description to see details of this pipe clock. ++ */ ++ if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; ++ } ++ } else if (cfg->type == PHY_TYPE_DP) { ++ ret = phy_dp_clks_register(qmp, qmp->phys[id], child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register DP clock source\n"); ++ goto err_node_put; ++ } ++ } ++ id++; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (!IS_ERR(phy_provider)) ++ dev_info(dev, "Registered Qcom-QMP phy\n"); ++ else ++ pm_runtime_disable(dev); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++ ++err_node_put: ++ pm_runtime_disable(dev); ++ of_node_put(child); ++ return ret; ++} ++ ++static struct platform_driver qcom_qmp_phy_driver = { ++ .probe = qcom_qmp_phy_probe, ++ .driver = { ++ .name = "qcom-qmp-phy", ++ .pm = &qcom_qmp_phy_pm_ops, ++ .of_match_table = qcom_qmp_phy_of_match_table, ++ }, ++}; ++ ++module_platform_driver(qcom_qmp_phy_driver); ++ ++MODULE_AUTHOR("Vivek Gautam "); ++MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +new file mode 100644 +index 000000000000..c7309e981bfb +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -0,0 +1,6350 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "phy-qcom-qmp.h" ++ ++/* QPHY_SW_RESET bit */ ++#define SW_RESET BIT(0) ++/* QPHY_POWER_DOWN_CONTROL */ ++#define SW_PWRDN BIT(0) ++#define REFCLK_DRV_DSBL BIT(1) ++/* QPHY_START_CONTROL bits */ ++#define SERDES_START BIT(0) ++#define PCS_START BIT(1) ++#define PLL_READY_GATE_EN BIT(3) ++/* QPHY_PCS_STATUS bit */ ++#define PHYSTATUS BIT(6) ++#define PHYSTATUS_4_20 BIT(7) ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ ++#define PCS_READY BIT(0) ++ ++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ ++/* DP PHY soft reset */ ++#define SW_DPPHY_RESET BIT(0) ++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ ++#define SW_DPPHY_RESET_MUX BIT(1) ++/* USB3 PHY soft reset */ ++#define SW_USB3PHY_RESET BIT(2) ++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ ++#define SW_USB3PHY_RESET_MUX BIT(3) ++ ++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ ++#define USB3_MODE BIT(0) /* enables USB3 mode */ ++#define DP_MODE BIT(1) /* enables DP mode */ ++ ++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ ++#define ARCVR_DTCT_EN BIT(0) ++#define ALFPS_DTCT_EN BIT(1) ++#define ARCVR_DTCT_EVENT_SEL BIT(4) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ ++#define IRQ_CLEAR BIT(0) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ ++#define RCVR_DETECT BIT(0) ++ ++/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ ++#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ ++ ++#define PHY_INIT_COMPLETE_TIMEOUT 10000 ++#define POWER_DOWN_DELAY_US_MIN 10 ++#define POWER_DOWN_DELAY_US_MAX 11 ++ ++#define MAX_PROP_NAME 32 ++ ++/* Define the assumed distance between lanes for underspecified device trees. */ ++#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 ++ ++struct qmp_phy_init_tbl { ++ unsigned int offset; ++ unsigned int val; ++ /* ++ * register part of layout ? ++ * if yes, then offset gives index in the reg-layout ++ */ ++ bool in_layout; ++ /* ++ * mask of lanes for which this register is written ++ * for cases when second lane needs different values ++ */ ++ u8 lane_mask; ++}; ++ ++#define QMP_PHY_INIT_CFG(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_L(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .in_layout = true, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = l, \ ++ } ++ ++/* set of registers with offsets different per-PHY */ ++enum qphy_reg_layout { ++ /* Common block control registers */ ++ QPHY_COM_SW_RESET, ++ QPHY_COM_POWER_DOWN_CONTROL, ++ QPHY_COM_START_CONTROL, ++ QPHY_COM_PCS_READY_STATUS, ++ /* PCS registers */ ++ QPHY_PLL_LOCK_CHK_DLY_TIME, ++ QPHY_FLL_CNTRL1, ++ QPHY_FLL_CNTRL2, ++ QPHY_FLL_CNT_VAL_L, ++ QPHY_FLL_CNT_VAL_H_TOL, ++ QPHY_FLL_MAN_CODE, ++ QPHY_SW_RESET, ++ QPHY_START_CTRL, ++ QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, ++ QPHY_PCS_AUTONOMOUS_MODE_CTRL, ++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, ++ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, ++ QPHY_PCS_POWER_DOWN_CONTROL, ++ /* PCS_MISC registers */ ++ QPHY_PCS_MISC_TYPEC_CTRL, ++ /* Keep last to ensure regs_layout arrays are properly initialized */ ++ QPHY_LAYOUT_SIZE ++}; ++ ++static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_COM_SW_RESET] = 0x400, ++ [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, ++ [QPHY_COM_START_CONTROL] = 0x408, ++ [QPHY_COM_PCS_READY_STATUS] = 0x448, ++ [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, ++ [QPHY_FLL_CNTRL1] = 0xc4, ++ [QPHY_FLL_CNTRL2] = 0xc8, ++ [QPHY_FLL_CNT_VAL_L] = 0xcc, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, ++ [QPHY_FLL_MAN_CODE] = 0xd4, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_FLL_CNTRL1] = 0xc0, ++ [QPHY_FLL_CNTRL2] = 0xc4, ++ [QPHY_FLL_CNT_VAL_L] = 0xc8, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, ++ [QPHY_FLL_MAN_CODE] = 0xd0, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x17c, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++}; ++ ++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++}; ++ ++static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x2ac, ++}; ++ ++static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x308, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x314, ++}; ++ ++static const unsigned int qmp_v4_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x608, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x614, ++}; ++ ++static const unsigned int sm8350_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x1008, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x1014, ++}; ++ ++static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0xd8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0xdc, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_MISC_TYPEC_CTRL] = 0x00, ++}; ++ ++static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x160, ++}; ++ ++static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, ++ [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, ++ [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), ++ ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4), ++ QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe), ++ QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0), ++ QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1), ++ ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x95), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x26), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x048), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_PLL_CNTL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB, 0xd8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_PWM_GEAR_BAND, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HS_GEAR_BAND, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xd8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_TX_ADAPT_POST_THRESH, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0xd0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_RX, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0xc5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xad), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xb6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xc7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x05), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), ++}; ++ ++/* Register names should be validated, they might be different for this PHY */ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), ++}; ++ ++struct qmp_phy; ++ ++/* struct qmp_phy_cfg - per-PHY initialization config */ ++struct qmp_phy_cfg { ++ /* phy-type - PCIE/UFS/USB */ ++ unsigned int type; ++ /* number of lanes provided by phy */ ++ int nlanes; ++ ++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_init_tbl *serdes_tbl; ++ int serdes_tbl_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_sec; ++ int serdes_tbl_num_sec; ++ const struct qmp_phy_init_tbl *tx_tbl; ++ int tx_tbl_num; ++ const struct qmp_phy_init_tbl *tx_tbl_sec; ++ int tx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *rx_tbl; ++ int rx_tbl_num; ++ const struct qmp_phy_init_tbl *rx_tbl_sec; ++ int rx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_tbl; ++ int pcs_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_tbl_sec; ++ int pcs_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl; ++ int pcs_misc_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; ++ int pcs_misc_tbl_num_sec; ++ ++ /* Init sequence for DP PHY block link rates */ ++ const struct qmp_phy_init_tbl *serdes_tbl_rbr; ++ int serdes_tbl_rbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr; ++ int serdes_tbl_hbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr2; ++ int serdes_tbl_hbr2_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr3; ++ int serdes_tbl_hbr3_num; ++ ++ /* DP PHY callbacks */ ++ int (*configure_dp_phy)(struct qmp_phy *qphy); ++ void (*configure_dp_tx)(struct qmp_phy *qphy); ++ int (*calibrate_dp_phy)(struct qmp_phy *qphy); ++ void (*dp_aux_init)(struct qmp_phy *qphy); ++ ++ /* clock ids to be requested */ ++ const char * const *clk_list; ++ int num_clks; ++ /* resets to be requested */ ++ const char * const *reset_list; ++ int num_resets; ++ /* regulators to be requested */ ++ const char * const *vreg_list; ++ int num_vregs; ++ ++ /* array of registers with different offsets */ ++ const unsigned int *regs; ++ ++ unsigned int start_ctrl; ++ unsigned int pwrdn_ctrl; ++ unsigned int mask_com_pcs_ready; ++ /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ ++ unsigned int phy_status; ++ ++ /* true, if PHY has a separate PHY_COM control block */ ++ bool has_phy_com_ctrl; ++ /* true, if PHY has a reset for individual lanes */ ++ bool has_lane_rst; ++ /* true, if PHY needs delay after POWER_DOWN */ ++ bool has_pwrdn_delay; ++ /* power_down delay in usec */ ++ int pwrdn_delay_min; ++ int pwrdn_delay_max; ++ ++ /* true, if PHY has a separate DP_COM control block */ ++ bool has_phy_dp_com_ctrl; ++ /* true, if PHY has secondary tx/rx lanes to be configured */ ++ bool is_dual_lane_phy; ++ ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; ++}; ++ ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; ++}; ++ ++/** ++ * struct qmp_phy - per-lane phy descriptor ++ * ++ * @phy: generic phy ++ * @cfg: phy specific configuration ++ * @serdes: iomapped memory space for phy's serdes (i.e. PLL) ++ * @tx: iomapped memory space for lane's tx ++ * @rx: iomapped memory space for lane's rx ++ * @pcs: iomapped memory space for lane's pcs ++ * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) ++ * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) ++ * @pcs_misc: iomapped memory space for lane's pcs_misc ++ * @pipe_clk: pipe clock ++ * @index: lane index ++ * @qmp: QMP phy to which this lane belongs ++ * @lane_rst: lane's reset controller ++ * @mode: current PHY mode ++ * @dp_aux_cfg: Display port aux config ++ * @dp_opts: Display port optional config ++ * @dp_clks: Display port clocks ++ */ ++struct qmp_phy { ++ struct phy *phy; ++ const struct qmp_phy_cfg *cfg; ++ void __iomem *serdes; ++ void __iomem *tx; ++ void __iomem *rx; ++ void __iomem *pcs; ++ void __iomem *tx2; ++ void __iomem *rx2; ++ void __iomem *pcs_misc; ++ struct clk *pipe_clk; ++ unsigned int index; ++ struct qcom_qmp *qmp; ++ struct reset_control *lane_rst; ++ enum phy_mode mode; ++ unsigned int dp_aux_cfg; ++ struct phy_configure_opts_dp dp_opts; ++ struct qmp_phy_dp_clks *dp_clks; ++}; ++ ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; ++ ++/** ++ * struct qcom_qmp - structure holding QMP phy block attributes ++ * ++ * @dev: device ++ * @dp_com: iomapped memory space for phy's dp_com control block ++ * ++ * @clks: array of clocks required by phy ++ * @resets: array of resets required by phy ++ * @vregs: regulator supplies bulk data ++ * ++ * @phys: array of per-lane phy descriptors ++ * @phy_mutex: mutex lock for PHY common block initialization ++ * @init_count: phy common block initialization count ++ * @ufs_reset: optional UFS PHY reset handle ++ */ ++struct qcom_qmp { ++ struct device *dev; ++ void __iomem *dp_com; ++ ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; ++ ++ struct qmp_phy **phys; ++ ++ struct mutex phy_mutex; ++ int init_count; ++ ++ struct reset_control *ufs_reset; ++}; ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", ++}; ++ ++static const char * const msm8996_ufs_phy_clk_l[] = { ++ "ref", ++}; ++ ++static const char * const qmp_v3_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "com_aux", ++}; ++ ++static const char * const sdm845_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "refgen", ++}; ++ ++static const char * const qmp_v4_phy_clk_l[] = { ++ "aux", "ref_clk_src", "ref", "com_aux", ++}; ++ ++/* the primary usb3 phy on sm8250 doesn't have a ref clock */ ++static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { ++ "aux", "ref_clk_src", "com_aux" ++}; ++ ++static const char * const sm8450_ufs_phy_clk_l[] = { ++ "qref", "ref", "ref_aux", ++}; ++ ++static const char * const sdm845_ufs_phy_clk_l[] = { ++ "ref", "ref_aux", ++}; ++ ++/* usb3 phy on sdx55 doesn't have com_aux clock */ ++static const char * const qmp_v4_sdx55_usbphy_clk_l[] = { ++ "aux", "cfg_ahb", "ref" ++}; ++ ++static const char * const qcm2290_usb3phy_clk_l[] = { ++ "cfg_ahb", "ref", "com_aux", ++}; ++ ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", ++}; ++ ++static const char * const msm8996_usb3phy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const char * const sc7180_usb3phy_reset_l[] = { ++ "phy", ++}; ++ ++static const char * const qcm2290_usb3phy_reset_l[] = { ++ "phy_phy", "phy", ++}; ++ ++static const char * const sdm845_pciephy_reset_l[] = { ++ "phy", ++}; ++ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = ipq8074_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), ++ .pcs_tbl = ipq8074_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, ++ ++ .serdes_tbl = msm8996_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), ++ .tx_tbl = msm8996_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), ++ .rx_tbl = msm8996_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), ++ .pcs_tbl = msm8996_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = true, ++ .has_lane_rst = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg msm8996_ufs_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_ufs_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), ++ .tx_tbl = msm8996_ufs_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl), ++ .rx_tbl = msm8996_ufs_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl), ++ ++ .clk_list = msm8996_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l), ++ ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ ++ .regs = msm8996_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = msm8996_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), ++ .pcs_tbl = msm8996_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const char * const ipq8074_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", ++}; ++/* list of resets */ ++static const char * const ipq8074_pciephy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx_tbl = ipq8074_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx_tbl = ipq8074_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs_tbl = ipq8074_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq6018_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx_tbl = ipq6018_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx_tbl = ipq6018_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs_tbl = ipq6018_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = ipq_pciephy_gen3_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qmp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qhp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qhp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qhp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), ++ .tx_tbl = qmp_v3_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { ++ .usb_cfg = &sc7180_usb3phy_cfg, ++ .dp_cfg = &sc7180_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdm845_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), ++ .tx_tbl = sdm845_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), ++ .rx_tbl = sdm845_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), ++ .pcs_tbl = sdm845_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm6115_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), ++ .tx_tbl = sm6115_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), ++ .rx_tbl = sm6115_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), ++ .pcs_tbl = sm6115_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm6115_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ ++ .is_dual_lane_phy = false, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8998_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx_tbl = msm8998_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx_tbl = msm8998_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs_tbl = msm8998_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), ++ .tx_tbl = msm8998_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl), ++ .rx_tbl = msm8998_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), ++ .pcs_tbl = msm8998_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8150_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), ++ .tx_tbl = sm8150_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_tx_tbl), ++ .rx_tbl = sm8150_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_rx_tbl), ++ .pcs_tbl = sm8150_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8150_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), ++ .rx_tbl = sm8150_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), ++ .pcs_tbl = sm8150_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx_tbl = sc8180x_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx_tbl = sc8180x_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { ++ .usb_cfg = &sm8150_usb3phy_cfg, ++ .dp_cfg = &sc8180x_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8150_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8150_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8150_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8250_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), ++ .rx_tbl = sm8250_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), ++ .pcs_tbl = sm8250_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8250_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8250_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { ++ .usb_cfg = &sm8250_usb3phy_cfg, ++ .dp_cfg = &sm8250_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx55_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx55_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdx55_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx_tbl = sdx55_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx65_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx65_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8350_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), ++ .rx_tbl = sm8350_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), ++ .pcs_tbl = sm8350_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8350_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8350_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sm8450_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qcm2290_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ++ .tx_tbl = qcm2290_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), ++ .rx_tbl = qcm2290_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), ++ .pcs_tbl = qcm2290_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), ++ .clk_list = qcm2290_usb3phy_clk_l, ++ .num_clks = ARRAY_SIZE(qcm2290_usb3phy_clk_l), ++ .reset_list = qcm2290_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qcm2290_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static void qcom_qmp_phy_configure_lane(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num, ++ u8 lane_mask) ++{ ++ int i; ++ const struct qmp_phy_init_tbl *t = tbl; ++ ++ if (!t) ++ return; ++ ++ for (i = 0; i < num; i++, t++) { ++ if (!(t->lane_mask & lane_mask)) ++ continue; ++ ++ if (t->in_layout) ++ writel(t->val, base + regs[t->offset]); ++ else ++ writel(t->val, base + t->offset); ++ } ++} ++ ++static void qcom_qmp_phy_configure(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num) ++{ ++ qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); ++} ++ ++static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; ++ int serdes_tbl_num = cfg->serdes_tbl_num; ++ int ret; ++ ++ qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ if (cfg->serdes_tbl_sec) ++ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, ++ cfg->serdes_tbl_num_sec); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ switch (dp_opts->link_rate) { ++ case 1620: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_rbr, ++ cfg->serdes_tbl_rbr_num); ++ break; ++ case 2700: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr, ++ cfg->serdes_tbl_hbr_num); ++ break; ++ case 5400: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr2, ++ cfg->serdes_tbl_hbr2_num); ++ break; ++ case 8100: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr3, ++ cfg->serdes_tbl_hbr3_num); ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ } ++ ++ ++ if (cfg->has_phy_com_ctrl) { ++ void __iomem *status; ++ unsigned int mask, val; ++ ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ ++ status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; ++ mask = cfg->mask_com_pcs_ready; ++ ++ ret = readl_poll_timeout(status, val, (val & mask), 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, ++ "phy common block init timed-out\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_LANE_0_1_PWRDN | ++ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | ++ DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(QSERDES_V3_COM_BIAS_EN | ++ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | ++ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { ++ { 0x00, 0x0c, 0x15, 0x1a }, ++ { 0x02, 0x0e, 0x16, 0xff }, ++ { 0x02, 0x11, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { ++ { 0x02, 0x12, 0x16, 0x1a }, ++ { 0x09, 0x19, 0x1f, 0xff }, ++ { 0x10, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { ++ { 0x00, 0x0c, 0x14, 0x19 }, ++ { 0x00, 0x0b, 0x12, 0xff }, ++ { 0x00, 0x0b, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { ++ { 0x08, 0x0f, 0x16, 0x1f }, ++ { 0x11, 0x1e, 0x1f, 0xff }, ++ { 0x19, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, ++ unsigned int drv_lvl_reg, unsigned int emp_post_reg) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ unsigned int v_level = 0, p_level = 0; ++ u8 voltage_swing_cfg, pre_emphasis_cfg; ++ int i; ++ ++ for (i = 0; i < dp_opts->lanes; i++) { ++ v_level = max(v_level, dp_opts->voltage[i]); ++ p_level = max(p_level, dp_opts->pre[i]); ++ } ++ ++ if (dp_opts->link_rate <= 2700) { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; ++ } else { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; ++ } ++ ++ /* TODO: Move check to config check */ ++ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) ++ return -EINVAL; ++ ++ /* Enable MUX to use Cursor values from these registers */ ++ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; ++ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; ++ ++ writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); ++ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 bias_en, drvr_en; ++ ++ if (qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V3_TX_TX_DRV_LVL, ++ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) ++ return; ++ ++ if (dp_opts->lanes == 1) { ++ bias_en = 0x3e; ++ drvr_en = 0x13; ++ } else { ++ bias_en = 0x3f; ++ drvr_en = 0x10; ++ } ++ ++ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++} ++ ++static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) ++{ ++ u32 val; ++ bool reverse = false; ++ ++ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ++ ++ /* ++ * TODO: Assume orientation is CC1 for now and two lanes, need to ++ * use type-c connector to understand orientation and lanes. ++ * ++ * Otherwise val changes to be like below if this code understood ++ * the orientation of the type-c cable. ++ * ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) ++ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) ++ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ * if (orientation == ORIENTATION_CC2) ++ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); ++ */ ++ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); ++ ++ return reverse; ++} ++ ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ ++ qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000); ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ /* Program default values before writing proper values */ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V4_TX_TX_DRV_LVL, ++ QSERDES_V4_TX_TX_EMP_POST1_LVL); ++} ++ ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ u32 bias0_en, drvr0_en, bias1_en, drvr1_en; ++ bool reverse; ++ ++ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); ++ ++ reverse = qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ /* ++ * At least for 7nm DP PHY this has to be done after enabling link ++ * clock. ++ */ ++ ++ if (dp_opts->lanes == 1) { ++ bias0_en = reverse ? 0x3e : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3e; ++ drvr0_en = reverse ? 0x13 : 0x10; ++ drvr1_en = reverse ? 0x10 : 0x13; ++ } else if (dp_opts->lanes == 2) { ++ bias0_en = reverse ? 0x3f : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } else { ++ bias0_en = 0x3f; ++ bias1_en = 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } ++ ++ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); ++ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); ++ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ return 0; ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); ++ if (qphy->dp_opts.set_voltages) { ++ cfg->configure_dp_tx(qphy); ++ qphy->dp_opts.set_voltages = 0; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_calibrate(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->calibrate_dp_phy) ++ return cfg->calibrate_dp_phy(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *dp_com = qmp->dp_com; ++ int ret, i; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (qmp->init_count++) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ /* turn on regulator supplies */ ++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); ++ if (ret) { ++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); ++ goto err_unlock; ++ } ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ ret = reset_control_assert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset assert failed\n", ++ cfg->reset_list[i]); ++ goto err_disable_regulators; ++ } ++ } ++ ++ for (i = cfg->num_resets - 1; i >= 0; i--) { ++ ret = reset_control_deassert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset deassert failed\n", ++ qphy->cfg->reset_list[i]); ++ goto err_assert_reset; ++ } ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ goto err_assert_reset; ++ ++ if (cfg->has_phy_dp_com_ctrl) { ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, ++ SW_PWRDN); ++ /* override hardware control for reset of qmp phy */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ /* Default type-c orientation, i.e CC1 */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); ++ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, ++ USB3_MODE | DP_MODE); ++ ++ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); ++ } ++ ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } else { ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(pcs, ++ cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ else ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++ ++err_assert_reset: ++ while (++i < cfg->num_resets) ++ reset_control_assert(qmp->resets[i]); ++err_disable_regulators: ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++err_unlock: ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ int i = cfg->num_resets; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (--qmp->init_count) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ reset_control_assert(qmp->ufs_reset); ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], ++ SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } ++ ++ while (--i >= 0) ++ reset_control_assert(qmp->resets[i]); ++ ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_init(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret; ++ dev_vdbg(qmp->dev, "Initializing QMP phy\n"); ++ ++ if (cfg->no_pcs_sw_reset) { ++ /* ++ * Get UFS reset, which is delayed until now to avoid a ++ * circular dependency where UFS needs its PHY, but the PHY ++ * needs this UFS reset. ++ */ ++ if (!qmp->ufs_reset) { ++ qmp->ufs_reset = ++ devm_reset_control_get_exclusive(qmp->dev, ++ "ufsphy"); ++ ++ if (IS_ERR(qmp->ufs_reset)) { ++ ret = PTR_ERR(qmp->ufs_reset); ++ dev_err(qmp->dev, ++ "failed to get UFS reset: %d\n", ++ ret); ++ ++ qmp->ufs_reset = NULL; ++ return ret; ++ } ++ } ++ ++ ret = reset_control_assert(qmp->ufs_reset); ++ if (ret) ++ return ret; ++ } ++ ++ ret = qcom_qmp_phy_com_init(qphy); ++ if (ret) ++ return ret; ++ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->dp_aux_init(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_power_on(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ void __iomem *status; ++ unsigned int mask, val, ready; ++ int ret; ++ ++ qcom_qmp_phy_serdes_init(qphy); ++ ++ if (cfg->has_lane_rst) { ++ ret = reset_control_deassert(qphy->lane_rst); ++ if (ret) { ++ dev_err(qmp->dev, "lane%d reset deassert failed\n", ++ qphy->index); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); ++ goto err_reset_lane; ++ } ++ ++ /* Tx, Rx, and PCS configurations */ ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 1); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 1); ++ ++ /* Configuration for other LANE for USB-DP combo PHY */ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 2); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 2); ++ } ++ ++ /* Configure special DP tx tunings */ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->configure_dp_tx(qphy); ++ ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 1); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); ++ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 2); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl_sec, ++ cfg->rx_tbl_num_sec, 2); ++ } ++ ++ /* Configure link rate, swing, etc. */ ++ if (cfg->type == PHY_TYPE_DP) { ++ cfg->configure_dp_phy(qphy); ++ } else { ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); ++ } ++ ++ ret = reset_control_deassert(qmp->ufs_reset); ++ if (ret) ++ goto err_disable_pipe_clk; ++ ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ cfg->pcs_misc_tbl_num); ++ if (cfg->pcs_misc_tbl_sec) ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, ++ cfg->pcs_misc_tbl_num_sec); ++ ++ /* ++ * Pull out PHY from POWER DOWN state. ++ * This is active low enable signal to power-down PHY. ++ */ ++ if(cfg->type == PHY_TYPE_PCIE) ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); ++ ++ if (cfg->has_pwrdn_delay) ++ usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ ++ if (cfg->type != PHY_TYPE_DP) { ++ /* Pull PHY out of reset state */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ /* start SerDes and Phy-Coding-Sublayer */ ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = cfg->phy_status; ++ ready = 0; ++ } ++ ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, "phy initialization timed-out\n"); ++ goto err_disable_pipe_clk; ++ } ++ } ++ return 0; ++ ++err_disable_pipe_clk: ++ clk_disable_unprepare(qphy->pipe_clk); ++err_reset_lane: ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_power_off(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ /* Assert DP PHY power down */ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ } else { ++ /* PHY reset */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ ++ /* stop SerDes and Phy-Coding-Sublayer */ ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ /* Put PHY into POWER DOWN state: active low */ ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ } else { ++ qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_exit(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ qcom_qmp_phy_com_exit(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_enable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_power_on(phy); ++ if (ret) ++ qcom_qmp_phy_exit(phy); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_disable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_power_off(phy); ++ if (ret) ++ return ret; ++ return qcom_qmp_phy_exit(phy); ++} ++ ++static int qcom_qmp_phy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ qphy->mode = mode; ++ ++ return 0; ++} ++ ++static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ u32 intr_mask; ++ ++ if (qphy->mode == PHY_MODE_USB_HOST_SS || ++ qphy->mode == PHY_MODE_USB_DEVICE_SS) ++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; ++ else ++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; ++ ++ /* Clear any pending interrupts status */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); ++ ++ /* Enable required PHY autonomous mode interrupts */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); ++ ++ /* Enable i/o clamp_n for autonomous mode */ ++ if (pcs_misc) ++ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++} ++ ++static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ /* Disable i/o clamp_n on resume for normal mode */ ++ if (pcs_misc) ++ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); ++ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ qcom_qmp_phy_enable_autonomous_mode(qphy); ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret = 0; ++ ++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ return ret; ++ } ++ ++ qcom_qmp_phy_disable_autonomous_mode(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_vregs; ++ int i; ++ ++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); ++ if (!qmp->vregs) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->vregs[i].supply = cfg->vreg_list[i]; ++ ++ return devm_regulator_bulk_get(dev, num, qmp->vregs); ++} ++ ++static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int i; ++ ++ qmp->resets = devm_kcalloc(dev, cfg->num_resets, ++ sizeof(*qmp->resets), GFP_KERNEL); ++ if (!qmp->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ struct reset_control *rst; ++ const char *name = cfg->reset_list[i]; ++ ++ rst = devm_reset_control_get_exclusive(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ return PTR_ERR(rst); ++ } ++ qmp->resets[i] = rst; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_clks; ++ int i; ++ ++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); ++ if (!qmp->clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->clks[i].id = cfg->clk_list[i]; ++ ++ return devm_clk_bulk_get(dev, num, qmp->clks); ++} ++ ++static void phy_clk_release_provider(void *res) ++{ ++ of_clk_del_provider(res); ++} ++ ++/* ++ * Register a fixed rate pipe clock. ++ * ++ * The _pipe_clksrc generated by PHY goes to the GCC that gate ++ * controls it. The _pipe_clk coming out of the GCC is requested ++ * by the PHY driver for its operations. ++ * We register the _pipe_clksrc here. The gcc driver takes care ++ * of assigning this _pipe_clksrc as parent to _pipe_clk. ++ * Below picture shows this relationship. ++ * ++ * +---------------+ ++ * | PHY block |<<---------------------------------------+ ++ * | | | ++ * | +-------+ | +-----+ | ++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ ++ * clk | +-------+ | +-----+ ++ * +---------------+ ++ */ ++static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) ++{ ++ struct clk_fixed_rate *fixed; ++ struct clk_init_data init = { }; ++ int ret; ++ ++ ret = of_property_read_string(np, "clock-output-names", &init.name); ++ if (ret) { ++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); ++ return ret; ++ } ++ ++ fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); ++ if (!fixed) ++ return -ENOMEM; ++ ++ init.ops = &clk_fixed_rate_ops; ++ ++ /* controllers using QMP phys use 125MHz pipe clock interface */ ++ fixed->fixed_rate = 125000000; ++ fixed->hw.init = &init; ++ ++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++/* ++ * Display Port PLL driver block diagram for branch clocks ++ * ++ * +------------------------------+ ++ * | DP_VCO_CLK | ++ * | | ++ * | +-------------------+ | ++ * | | (DP PLL/VCO) | | ++ * | +---------+---------+ | ++ * | v | ++ * | +----------+-----------+ | ++ * | | hsclk_divsel_clk_src | | ++ * | +----------+-----------+ | ++ * +------------------------------+ ++ * | ++ * +---------<---------v------------>----------+ ++ * | | ++ * +--------v----------------+ | ++ * | dp_phy_pll_link_clk | | ++ * | link_clk | | ++ * +--------+----------------+ | ++ * | | ++ * | | ++ * v v ++ * Input to DISPCC block | ++ * for link clk, crypto clk | ++ * and interface clock | ++ * | ++ * | ++ * +--------<------------+-----------------+---<---+ ++ * | | | ++ * +----v---------+ +--------v-----+ +--------v------+ ++ * | vco_divided | | vco_divided | | vco_divided | ++ * | _clk_src | | _clk_src | | _clk_src | ++ * | | | | | | ++ * |divsel_six | | divsel_two | | divsel_four | ++ * +-------+------+ +-----+--------+ +--------+------+ ++ * | | | ++ * v---->----------v-------------<------v ++ * | ++ * +----------+-----------------+ ++ * | dp_phy_pll_vco_div_clk | ++ * +---------+------------------+ ++ * | ++ * v ++ * Input to DISPCC block ++ * for DP pixel clock ++ * ++ */ ++static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 1620000000UL / 2: ++ case 2700000000UL / 2: ++ /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ return 1620000000UL / 2; ++ case 2700: ++ return 2700000000UL / 2; ++ case 5400: ++ return 5400000000UL / 4; ++ case 8100: ++ return 8100000000UL / 6; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { ++ .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, ++}; ++ ++static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 162000000: ++ case 270000000: ++ case 540000000: ++ case 810000000: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ return dp_opts->link_rate * 100000; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_link_clk_ops = { ++ .determine_rate = qcom_qmp_dp_link_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, ++}; ++ ++static struct clk_hw * ++qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct qmp_phy_dp_clks *dp_clks = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx >= 2) { ++ pr_err("%s: invalid index %u\n", __func__, idx); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (idx == 0) ++ return &dp_clks->dp_link_hw; ++ ++ return &dp_clks->dp_pixel_hw; ++} ++ ++static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, ++ struct device_node *np) ++{ ++ struct clk_init_data init = { }; ++ struct qmp_phy_dp_clks *dp_clks; ++ char name[64]; ++ int ret; ++ ++ dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); ++ if (!dp_clks) ++ return -ENOMEM; ++ ++ dp_clks->qphy = qphy; ++ qphy->dp_clks = dp_clks; ++ ++ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_link_clk_ops; ++ init.name = name; ++ dp_clks->dp_link_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); ++ if (ret) ++ return ret; ++ ++ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_pixel_clk_ops; ++ init.name = name; ++ dp_clks->dp_pixel_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++static const struct phy_ops qcom_qmp_phy_gen_ops = { ++ .init = qcom_qmp_phy_enable, ++ .exit = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_phy_dp_ops = { ++ .init = qcom_qmp_phy_init, ++ .configure = qcom_qmp_dp_phy_configure, ++ .power_on = qcom_qmp_phy_power_on, ++ .calibrate = qcom_qmp_dp_phy_calibrate, ++ .power_off = qcom_qmp_phy_power_off, ++ .exit = qcom_qmp_phy_exit, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_pcie_ufs_ops = { ++ .power_on = qcom_qmp_phy_enable, ++ .power_off = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static void qcom_qmp_reset_control_put(void *data) ++{ ++ reset_control_put(data); ++} ++ ++static ++int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++ void __iomem *serdes, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct phy *generic_phy; ++ struct qmp_phy *qphy; ++ const struct phy_ops *ops; ++ char prop_name[MAX_PROP_NAME]; ++ int ret; ++ ++ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); ++ if (!qphy) ++ return -ENOMEM; ++ ++ qphy->cfg = cfg; ++ qphy->serdes = serdes; ++ /* ++ * Get memory resources for each phy lane: ++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. ++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 ++ * For single lane PHYs: pcs_misc (optional) -> 3. ++ */ ++ qphy->tx = of_iomap(np, 0); ++ if (!qphy->tx) ++ return -ENOMEM; ++ ++ qphy->rx = of_iomap(np, 1); ++ if (!qphy->rx) ++ return -ENOMEM; ++ ++ qphy->pcs = of_iomap(np, 2); ++ if (!qphy->pcs) ++ return -ENOMEM; ++ ++ /* ++ * If this is a dual-lane PHY, then there should be registers for the ++ * second lane. Some old device trees did not specify this, so fall ++ * back to old legacy behavior of assuming they can be reached at an ++ * offset from the first lane. ++ */ ++ if (cfg->is_dual_lane_phy) { ++ qphy->tx2 = of_iomap(np, 3); ++ qphy->rx2 = of_iomap(np, 4); ++ if (!qphy->tx2 || !qphy->rx2) { ++ dev_warn(dev, ++ "Underspecified device tree, falling back to legacy register regions\n"); ++ ++ /* In the old version, pcs_misc is at index 3. */ ++ qphy->pcs_misc = qphy->tx2; ++ qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; ++ qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 5); ++ } ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 3); ++ } ++ ++ if (!qphy->pcs_misc) ++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ ++ /* ++ * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 ++ * based phys, so they essentially have pipe clock. So, ++ * we return error in case phy is USB3 or PIPE type. ++ * Otherwise, we initialize pipe clock to NULL for ++ * all phys that don't need this. ++ */ ++ snprintf(prop_name, sizeof(prop_name), "pipe%d", id); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ if (IS_ERR(qphy->pipe_clk)) { ++ if (cfg->type == PHY_TYPE_PCIE || ++ cfg->type == PHY_TYPE_USB3) { ++ ret = PTR_ERR(qphy->pipe_clk); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to get lane%d pipe_clk, %d\n", ++ id, ret); ++ return ret; ++ } ++ qphy->pipe_clk = NULL; ++ } ++ ++ /* Get lane reset, if any */ ++ if (cfg->has_lane_rst) { ++ snprintf(prop_name, sizeof(prop_name), "lane%d", id); ++ qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); ++ if (IS_ERR(qphy->lane_rst)) { ++ dev_err(dev, "failed to get lane%d reset\n", id); ++ return PTR_ERR(qphy->lane_rst); ++ } ++ ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put, ++ qphy->lane_rst); ++ if (ret) ++ return ret; ++ } ++ ++ if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) ++ ops = &qcom_qmp_pcie_ufs_ops; ++ else if (cfg->type == PHY_TYPE_DP) ++ ops = &qcom_qmp_phy_dp_ops; ++ else ++ ops = &qcom_qmp_phy_gen_ops; ++ ++ generic_phy = devm_phy_create(dev, np, ops); ++ if (IS_ERR(generic_phy)) { ++ ret = PTR_ERR(generic_phy); ++ dev_err(dev, "failed to create qphy %d\n", ret); ++ return ret; ++ } ++ ++ qphy->phy = generic_phy; ++ qphy->index = id; ++ qphy->qmp = qmp; ++ qmp->phys[id] = qphy; ++ phy_set_drvdata(generic_phy, qphy); ++ ++ return 0; ++} ++ ++static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,ipq8074-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-pcie-phy", ++ .data = &msm8996_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-ufs-phy", ++ .data = &msm8996_ufs_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-usb3-phy", ++ .data = &msm8996_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-pcie-phy", ++ .data = &msm8998_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,ipq8074-qmp-pcie-phy", ++ .data = &ipq8074_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-pcie-phy", ++ .data = &ipq6018_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-phy", ++ .data = &sc7180_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sc8180x-qmp-pcie-phy", ++ .data = &sc8180x_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8280xp-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sdm845-qhp-pcie-phy", ++ .data = &sdm845_qhp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-pcie-phy", ++ .data = &sdm845_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-phy", ++ .data = &qmp_v3_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-uni-phy", ++ .data = &qmp_v3_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-usb3-phy", ++ .data = &msm8998_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm6115-qmp-ufs-phy", ++ .data = &sm6115_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm6350-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-uni-phy", ++ .data = &sm8150_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-phy", ++ .data = &sm8250_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-uni-phy", ++ .data = &sm8250_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy", ++ .data = &sm8250_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-modem-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-pcie-phy", ++ .data = &sdx55_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-usb3-uni-phy", ++ .data = &sdx55_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdx65-qmp-usb3-uni-phy", ++ .data = &sdx65_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-uni-phy", ++ .data = &sm8350_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy", ++ .data = &sm8450_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy", ++ .data = &sm8450_qmp_gen4x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-ufs-phy", ++ .data = &sm8450_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,qcm2290-qmp-usb3-phy", ++ .data = &qcm2290_usb3phy_cfg, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++ ++static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ .data = &sc7180_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ .data = &sm8250_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ .data = &sc8180x_usb3dpphy_cfg, ++ }, ++ { } ++}; ++ ++static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, ++ qcom_qmp_phy_runtime_resume, NULL) ++}; ++ ++static int qcom_qmp_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_qmp *qmp; ++ struct device *dev = &pdev->dev; ++ struct device_node *child; ++ struct phy_provider *phy_provider; ++ void __iomem *serdes; ++ void __iomem *usb_serdes; ++ void __iomem *dp_serdes = NULL; ++ const struct qmp_phy_combo_cfg *combo_cfg = NULL; ++ const struct qmp_phy_cfg *cfg = NULL; ++ const struct qmp_phy_cfg *usb_cfg = NULL; ++ const struct qmp_phy_cfg *dp_cfg = NULL; ++ int num, id, expected_phys; ++ int ret; ++ ++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); ++ if (!qmp) ++ return -ENOMEM; ++ ++ qmp->dev = dev; ++ dev_set_drvdata(dev, qmp); ++ ++ /* Get the specific init parameters of QMP phy */ ++ cfg = of_device_get_match_data(dev); ++ if (!cfg) { ++ const struct of_device_id *match; ++ ++ match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); ++ if (!match) ++ return -EINVAL; ++ ++ combo_cfg = match->data; ++ if (!combo_cfg) ++ return -EINVAL; ++ ++ usb_cfg = combo_cfg->usb_cfg; ++ cfg = usb_cfg; /* Setup clks and regulators */ ++ } ++ ++ /* per PHY serdes; usually located at base address */ ++ usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(serdes)) ++ return PTR_ERR(serdes); ++ ++ /* per PHY dp_com; if PHY has dp_com control block */ ++ if (combo_cfg || cfg->has_phy_dp_com_ctrl) { ++ qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(qmp->dp_com)) ++ return PTR_ERR(qmp->dp_com); ++ } ++ ++ if (combo_cfg) { ++ /* Only two serdes for combo PHY */ ++ dp_serdes = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(dp_serdes)) ++ return PTR_ERR(dp_serdes); ++ ++ dp_cfg = combo_cfg->dp_cfg; ++ expected_phys = 2; ++ } else { ++ expected_phys = cfg->nlanes; ++ } ++ ++ mutex_init(&qmp->phy_mutex); ++ ++ ret = qcom_qmp_phy_clk_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_reset_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get regulator supplies: %d\n", ++ ret); ++ return ret; ++ } ++ ++ num = of_get_available_child_count(dev->of_node); ++ /* do we have a rogue child node ? */ ++ if (num > expected_phys) ++ return -EINVAL; ++ ++ qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); ++ if (!qmp->phys) ++ return -ENOMEM; ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ /* ++ * Prevent runtime pm from being ON by default. Users can enable ++ * it using power/control in sysfs. ++ */ ++ pm_runtime_forbid(dev); ++ ++ id = 0; ++ for_each_available_child_of_node(dev->of_node, child) { ++ if (of_node_name_eq(child, "dp-phy")) { ++ cfg = dp_cfg; ++ serdes = dp_serdes; ++ } else if (of_node_name_eq(child, "usb3-phy")) { ++ cfg = usb_cfg; ++ serdes = usb_serdes; ++ } ++ ++ /* Create per-lane phy */ ++ ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ if (ret) { ++ dev_err(dev, "failed to create lane%d phy, %d\n", ++ id, ret); ++ goto err_node_put; ++ } ++ ++ /* ++ * Register the pipe clock provided by phy. ++ * See function description to see details of this pipe clock. ++ */ ++ if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; ++ } ++ } else if (cfg->type == PHY_TYPE_DP) { ++ ret = phy_dp_clks_register(qmp, qmp->phys[id], child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register DP clock source\n"); ++ goto err_node_put; ++ } ++ } ++ id++; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (!IS_ERR(phy_provider)) ++ dev_info(dev, "Registered Qcom-QMP phy\n"); ++ else ++ pm_runtime_disable(dev); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++ ++err_node_put: ++ pm_runtime_disable(dev); ++ of_node_put(child); ++ return ret; ++} ++ ++static struct platform_driver qcom_qmp_phy_driver = { ++ .probe = qcom_qmp_phy_probe, ++ .driver = { ++ .name = "qcom-qmp-phy", ++ .pm = &qcom_qmp_phy_pm_ops, ++ .of_match_table = qcom_qmp_phy_of_match_table, ++ }, ++}; ++ ++module_platform_driver(qcom_qmp_phy_driver); ++ ++MODULE_AUTHOR("Vivek Gautam "); ++MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +new file mode 100644 +index 000000000000..c7309e981bfb +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +@@ -0,0 +1,6350 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "phy-qcom-qmp.h" ++ ++/* QPHY_SW_RESET bit */ ++#define SW_RESET BIT(0) ++/* QPHY_POWER_DOWN_CONTROL */ ++#define SW_PWRDN BIT(0) ++#define REFCLK_DRV_DSBL BIT(1) ++/* QPHY_START_CONTROL bits */ ++#define SERDES_START BIT(0) ++#define PCS_START BIT(1) ++#define PLL_READY_GATE_EN BIT(3) ++/* QPHY_PCS_STATUS bit */ ++#define PHYSTATUS BIT(6) ++#define PHYSTATUS_4_20 BIT(7) ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ ++#define PCS_READY BIT(0) ++ ++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ ++/* DP PHY soft reset */ ++#define SW_DPPHY_RESET BIT(0) ++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ ++#define SW_DPPHY_RESET_MUX BIT(1) ++/* USB3 PHY soft reset */ ++#define SW_USB3PHY_RESET BIT(2) ++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ ++#define SW_USB3PHY_RESET_MUX BIT(3) ++ ++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ ++#define USB3_MODE BIT(0) /* enables USB3 mode */ ++#define DP_MODE BIT(1) /* enables DP mode */ ++ ++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ ++#define ARCVR_DTCT_EN BIT(0) ++#define ALFPS_DTCT_EN BIT(1) ++#define ARCVR_DTCT_EVENT_SEL BIT(4) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ ++#define IRQ_CLEAR BIT(0) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ ++#define RCVR_DETECT BIT(0) ++ ++/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ ++#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ ++ ++#define PHY_INIT_COMPLETE_TIMEOUT 10000 ++#define POWER_DOWN_DELAY_US_MIN 10 ++#define POWER_DOWN_DELAY_US_MAX 11 ++ ++#define MAX_PROP_NAME 32 ++ ++/* Define the assumed distance between lanes for underspecified device trees. */ ++#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 ++ ++struct qmp_phy_init_tbl { ++ unsigned int offset; ++ unsigned int val; ++ /* ++ * register part of layout ? ++ * if yes, then offset gives index in the reg-layout ++ */ ++ bool in_layout; ++ /* ++ * mask of lanes for which this register is written ++ * for cases when second lane needs different values ++ */ ++ u8 lane_mask; ++}; ++ ++#define QMP_PHY_INIT_CFG(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_L(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .in_layout = true, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = l, \ ++ } ++ ++/* set of registers with offsets different per-PHY */ ++enum qphy_reg_layout { ++ /* Common block control registers */ ++ QPHY_COM_SW_RESET, ++ QPHY_COM_POWER_DOWN_CONTROL, ++ QPHY_COM_START_CONTROL, ++ QPHY_COM_PCS_READY_STATUS, ++ /* PCS registers */ ++ QPHY_PLL_LOCK_CHK_DLY_TIME, ++ QPHY_FLL_CNTRL1, ++ QPHY_FLL_CNTRL2, ++ QPHY_FLL_CNT_VAL_L, ++ QPHY_FLL_CNT_VAL_H_TOL, ++ QPHY_FLL_MAN_CODE, ++ QPHY_SW_RESET, ++ QPHY_START_CTRL, ++ QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, ++ QPHY_PCS_AUTONOMOUS_MODE_CTRL, ++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, ++ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, ++ QPHY_PCS_POWER_DOWN_CONTROL, ++ /* PCS_MISC registers */ ++ QPHY_PCS_MISC_TYPEC_CTRL, ++ /* Keep last to ensure regs_layout arrays are properly initialized */ ++ QPHY_LAYOUT_SIZE ++}; ++ ++static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_COM_SW_RESET] = 0x400, ++ [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, ++ [QPHY_COM_START_CONTROL] = 0x408, ++ [QPHY_COM_PCS_READY_STATUS] = 0x448, ++ [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, ++ [QPHY_FLL_CNTRL1] = 0xc4, ++ [QPHY_FLL_CNTRL2] = 0xc8, ++ [QPHY_FLL_CNT_VAL_L] = 0xcc, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, ++ [QPHY_FLL_MAN_CODE] = 0xd4, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_FLL_CNTRL1] = 0xc0, ++ [QPHY_FLL_CNTRL2] = 0xc4, ++ [QPHY_FLL_CNT_VAL_L] = 0xc8, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, ++ [QPHY_FLL_MAN_CODE] = 0xd0, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x17c, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++}; ++ ++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++}; ++ ++static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x2ac, ++}; ++ ++static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x308, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x314, ++}; ++ ++static const unsigned int qmp_v4_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x608, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x614, ++}; ++ ++static const unsigned int sm8350_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x1008, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x1014, ++}; ++ ++static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0xd8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0xdc, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_MISC_TYPEC_CTRL] = 0x00, ++}; ++ ++static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x160, ++}; ++ ++static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, ++ [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, ++ [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), ++ ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4), ++ QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe), ++ QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0), ++ QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1), ++ ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x95), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x26), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x048), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_PLL_CNTL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB, 0xd8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_PWM_GEAR_BAND, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HS_GEAR_BAND, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xd8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_TX_ADAPT_POST_THRESH, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0xd0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_RX, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0xc5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xad), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xb6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xc7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x05), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), ++}; ++ ++/* Register names should be validated, they might be different for this PHY */ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), ++}; ++ ++struct qmp_phy; ++ ++/* struct qmp_phy_cfg - per-PHY initialization config */ ++struct qmp_phy_cfg { ++ /* phy-type - PCIE/UFS/USB */ ++ unsigned int type; ++ /* number of lanes provided by phy */ ++ int nlanes; ++ ++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_init_tbl *serdes_tbl; ++ int serdes_tbl_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_sec; ++ int serdes_tbl_num_sec; ++ const struct qmp_phy_init_tbl *tx_tbl; ++ int tx_tbl_num; ++ const struct qmp_phy_init_tbl *tx_tbl_sec; ++ int tx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *rx_tbl; ++ int rx_tbl_num; ++ const struct qmp_phy_init_tbl *rx_tbl_sec; ++ int rx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_tbl; ++ int pcs_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_tbl_sec; ++ int pcs_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl; ++ int pcs_misc_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; ++ int pcs_misc_tbl_num_sec; ++ ++ /* Init sequence for DP PHY block link rates */ ++ const struct qmp_phy_init_tbl *serdes_tbl_rbr; ++ int serdes_tbl_rbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr; ++ int serdes_tbl_hbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr2; ++ int serdes_tbl_hbr2_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr3; ++ int serdes_tbl_hbr3_num; ++ ++ /* DP PHY callbacks */ ++ int (*configure_dp_phy)(struct qmp_phy *qphy); ++ void (*configure_dp_tx)(struct qmp_phy *qphy); ++ int (*calibrate_dp_phy)(struct qmp_phy *qphy); ++ void (*dp_aux_init)(struct qmp_phy *qphy); ++ ++ /* clock ids to be requested */ ++ const char * const *clk_list; ++ int num_clks; ++ /* resets to be requested */ ++ const char * const *reset_list; ++ int num_resets; ++ /* regulators to be requested */ ++ const char * const *vreg_list; ++ int num_vregs; ++ ++ /* array of registers with different offsets */ ++ const unsigned int *regs; ++ ++ unsigned int start_ctrl; ++ unsigned int pwrdn_ctrl; ++ unsigned int mask_com_pcs_ready; ++ /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ ++ unsigned int phy_status; ++ ++ /* true, if PHY has a separate PHY_COM control block */ ++ bool has_phy_com_ctrl; ++ /* true, if PHY has a reset for individual lanes */ ++ bool has_lane_rst; ++ /* true, if PHY needs delay after POWER_DOWN */ ++ bool has_pwrdn_delay; ++ /* power_down delay in usec */ ++ int pwrdn_delay_min; ++ int pwrdn_delay_max; ++ ++ /* true, if PHY has a separate DP_COM control block */ ++ bool has_phy_dp_com_ctrl; ++ /* true, if PHY has secondary tx/rx lanes to be configured */ ++ bool is_dual_lane_phy; ++ ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; ++}; ++ ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; ++}; ++ ++/** ++ * struct qmp_phy - per-lane phy descriptor ++ * ++ * @phy: generic phy ++ * @cfg: phy specific configuration ++ * @serdes: iomapped memory space for phy's serdes (i.e. PLL) ++ * @tx: iomapped memory space for lane's tx ++ * @rx: iomapped memory space for lane's rx ++ * @pcs: iomapped memory space for lane's pcs ++ * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) ++ * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) ++ * @pcs_misc: iomapped memory space for lane's pcs_misc ++ * @pipe_clk: pipe clock ++ * @index: lane index ++ * @qmp: QMP phy to which this lane belongs ++ * @lane_rst: lane's reset controller ++ * @mode: current PHY mode ++ * @dp_aux_cfg: Display port aux config ++ * @dp_opts: Display port optional config ++ * @dp_clks: Display port clocks ++ */ ++struct qmp_phy { ++ struct phy *phy; ++ const struct qmp_phy_cfg *cfg; ++ void __iomem *serdes; ++ void __iomem *tx; ++ void __iomem *rx; ++ void __iomem *pcs; ++ void __iomem *tx2; ++ void __iomem *rx2; ++ void __iomem *pcs_misc; ++ struct clk *pipe_clk; ++ unsigned int index; ++ struct qcom_qmp *qmp; ++ struct reset_control *lane_rst; ++ enum phy_mode mode; ++ unsigned int dp_aux_cfg; ++ struct phy_configure_opts_dp dp_opts; ++ struct qmp_phy_dp_clks *dp_clks; ++}; ++ ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; ++ ++/** ++ * struct qcom_qmp - structure holding QMP phy block attributes ++ * ++ * @dev: device ++ * @dp_com: iomapped memory space for phy's dp_com control block ++ * ++ * @clks: array of clocks required by phy ++ * @resets: array of resets required by phy ++ * @vregs: regulator supplies bulk data ++ * ++ * @phys: array of per-lane phy descriptors ++ * @phy_mutex: mutex lock for PHY common block initialization ++ * @init_count: phy common block initialization count ++ * @ufs_reset: optional UFS PHY reset handle ++ */ ++struct qcom_qmp { ++ struct device *dev; ++ void __iomem *dp_com; ++ ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; ++ ++ struct qmp_phy **phys; ++ ++ struct mutex phy_mutex; ++ int init_count; ++ ++ struct reset_control *ufs_reset; ++}; ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", ++}; ++ ++static const char * const msm8996_ufs_phy_clk_l[] = { ++ "ref", ++}; ++ ++static const char * const qmp_v3_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "com_aux", ++}; ++ ++static const char * const sdm845_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "refgen", ++}; ++ ++static const char * const qmp_v4_phy_clk_l[] = { ++ "aux", "ref_clk_src", "ref", "com_aux", ++}; ++ ++/* the primary usb3 phy on sm8250 doesn't have a ref clock */ ++static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { ++ "aux", "ref_clk_src", "com_aux" ++}; ++ ++static const char * const sm8450_ufs_phy_clk_l[] = { ++ "qref", "ref", "ref_aux", ++}; ++ ++static const char * const sdm845_ufs_phy_clk_l[] = { ++ "ref", "ref_aux", ++}; ++ ++/* usb3 phy on sdx55 doesn't have com_aux clock */ ++static const char * const qmp_v4_sdx55_usbphy_clk_l[] = { ++ "aux", "cfg_ahb", "ref" ++}; ++ ++static const char * const qcm2290_usb3phy_clk_l[] = { ++ "cfg_ahb", "ref", "com_aux", ++}; ++ ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", ++}; ++ ++static const char * const msm8996_usb3phy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const char * const sc7180_usb3phy_reset_l[] = { ++ "phy", ++}; ++ ++static const char * const qcm2290_usb3phy_reset_l[] = { ++ "phy_phy", "phy", ++}; ++ ++static const char * const sdm845_pciephy_reset_l[] = { ++ "phy", ++}; ++ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = ipq8074_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), ++ .pcs_tbl = ipq8074_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, ++ ++ .serdes_tbl = msm8996_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), ++ .tx_tbl = msm8996_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), ++ .rx_tbl = msm8996_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), ++ .pcs_tbl = msm8996_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = true, ++ .has_lane_rst = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg msm8996_ufs_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_ufs_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), ++ .tx_tbl = msm8996_ufs_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl), ++ .rx_tbl = msm8996_ufs_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl), ++ ++ .clk_list = msm8996_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l), ++ ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ ++ .regs = msm8996_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = msm8996_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), ++ .pcs_tbl = msm8996_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const char * const ipq8074_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", ++}; ++/* list of resets */ ++static const char * const ipq8074_pciephy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx_tbl = ipq8074_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx_tbl = ipq8074_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs_tbl = ipq8074_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq6018_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx_tbl = ipq6018_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx_tbl = ipq6018_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs_tbl = ipq6018_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = ipq_pciephy_gen3_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qmp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qhp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qhp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qhp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), ++ .tx_tbl = qmp_v3_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { ++ .usb_cfg = &sc7180_usb3phy_cfg, ++ .dp_cfg = &sc7180_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdm845_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), ++ .tx_tbl = sdm845_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), ++ .rx_tbl = sdm845_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), ++ .pcs_tbl = sdm845_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm6115_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), ++ .tx_tbl = sm6115_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), ++ .rx_tbl = sm6115_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), ++ .pcs_tbl = sm6115_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm6115_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ ++ .is_dual_lane_phy = false, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8998_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx_tbl = msm8998_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx_tbl = msm8998_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs_tbl = msm8998_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), ++ .tx_tbl = msm8998_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl), ++ .rx_tbl = msm8998_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), ++ .pcs_tbl = msm8998_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8150_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), ++ .tx_tbl = sm8150_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_tx_tbl), ++ .rx_tbl = sm8150_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_rx_tbl), ++ .pcs_tbl = sm8150_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8150_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), ++ .rx_tbl = sm8150_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), ++ .pcs_tbl = sm8150_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx_tbl = sc8180x_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx_tbl = sc8180x_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { ++ .usb_cfg = &sm8150_usb3phy_cfg, ++ .dp_cfg = &sc8180x_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8150_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8150_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8150_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8250_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), ++ .rx_tbl = sm8250_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), ++ .pcs_tbl = sm8250_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8250_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8250_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { ++ .usb_cfg = &sm8250_usb3phy_cfg, ++ .dp_cfg = &sm8250_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx55_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx55_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdx55_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx_tbl = sdx55_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx65_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx65_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8350_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), ++ .rx_tbl = sm8350_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), ++ .pcs_tbl = sm8350_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8350_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8350_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sm8450_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qcm2290_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ++ .tx_tbl = qcm2290_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), ++ .rx_tbl = qcm2290_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), ++ .pcs_tbl = qcm2290_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), ++ .clk_list = qcm2290_usb3phy_clk_l, ++ .num_clks = ARRAY_SIZE(qcm2290_usb3phy_clk_l), ++ .reset_list = qcm2290_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qcm2290_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static void qcom_qmp_phy_configure_lane(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num, ++ u8 lane_mask) ++{ ++ int i; ++ const struct qmp_phy_init_tbl *t = tbl; ++ ++ if (!t) ++ return; ++ ++ for (i = 0; i < num; i++, t++) { ++ if (!(t->lane_mask & lane_mask)) ++ continue; ++ ++ if (t->in_layout) ++ writel(t->val, base + regs[t->offset]); ++ else ++ writel(t->val, base + t->offset); ++ } ++} ++ ++static void qcom_qmp_phy_configure(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num) ++{ ++ qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); ++} ++ ++static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; ++ int serdes_tbl_num = cfg->serdes_tbl_num; ++ int ret; ++ ++ qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ if (cfg->serdes_tbl_sec) ++ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, ++ cfg->serdes_tbl_num_sec); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ switch (dp_opts->link_rate) { ++ case 1620: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_rbr, ++ cfg->serdes_tbl_rbr_num); ++ break; ++ case 2700: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr, ++ cfg->serdes_tbl_hbr_num); ++ break; ++ case 5400: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr2, ++ cfg->serdes_tbl_hbr2_num); ++ break; ++ case 8100: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr3, ++ cfg->serdes_tbl_hbr3_num); ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ } ++ ++ ++ if (cfg->has_phy_com_ctrl) { ++ void __iomem *status; ++ unsigned int mask, val; ++ ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ ++ status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; ++ mask = cfg->mask_com_pcs_ready; ++ ++ ret = readl_poll_timeout(status, val, (val & mask), 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, ++ "phy common block init timed-out\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_LANE_0_1_PWRDN | ++ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | ++ DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(QSERDES_V3_COM_BIAS_EN | ++ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | ++ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { ++ { 0x00, 0x0c, 0x15, 0x1a }, ++ { 0x02, 0x0e, 0x16, 0xff }, ++ { 0x02, 0x11, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { ++ { 0x02, 0x12, 0x16, 0x1a }, ++ { 0x09, 0x19, 0x1f, 0xff }, ++ { 0x10, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { ++ { 0x00, 0x0c, 0x14, 0x19 }, ++ { 0x00, 0x0b, 0x12, 0xff }, ++ { 0x00, 0x0b, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { ++ { 0x08, 0x0f, 0x16, 0x1f }, ++ { 0x11, 0x1e, 0x1f, 0xff }, ++ { 0x19, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, ++ unsigned int drv_lvl_reg, unsigned int emp_post_reg) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ unsigned int v_level = 0, p_level = 0; ++ u8 voltage_swing_cfg, pre_emphasis_cfg; ++ int i; ++ ++ for (i = 0; i < dp_opts->lanes; i++) { ++ v_level = max(v_level, dp_opts->voltage[i]); ++ p_level = max(p_level, dp_opts->pre[i]); ++ } ++ ++ if (dp_opts->link_rate <= 2700) { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; ++ } else { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; ++ } ++ ++ /* TODO: Move check to config check */ ++ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) ++ return -EINVAL; ++ ++ /* Enable MUX to use Cursor values from these registers */ ++ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; ++ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; ++ ++ writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); ++ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 bias_en, drvr_en; ++ ++ if (qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V3_TX_TX_DRV_LVL, ++ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) ++ return; ++ ++ if (dp_opts->lanes == 1) { ++ bias_en = 0x3e; ++ drvr_en = 0x13; ++ } else { ++ bias_en = 0x3f; ++ drvr_en = 0x10; ++ } ++ ++ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++} ++ ++static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) ++{ ++ u32 val; ++ bool reverse = false; ++ ++ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ++ ++ /* ++ * TODO: Assume orientation is CC1 for now and two lanes, need to ++ * use type-c connector to understand orientation and lanes. ++ * ++ * Otherwise val changes to be like below if this code understood ++ * the orientation of the type-c cable. ++ * ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) ++ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) ++ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ * if (orientation == ORIENTATION_CC2) ++ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); ++ */ ++ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); ++ ++ return reverse; ++} ++ ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ ++ qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000); ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ /* Program default values before writing proper values */ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V4_TX_TX_DRV_LVL, ++ QSERDES_V4_TX_TX_EMP_POST1_LVL); ++} ++ ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ u32 bias0_en, drvr0_en, bias1_en, drvr1_en; ++ bool reverse; ++ ++ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); ++ ++ reverse = qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ /* ++ * At least for 7nm DP PHY this has to be done after enabling link ++ * clock. ++ */ ++ ++ if (dp_opts->lanes == 1) { ++ bias0_en = reverse ? 0x3e : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3e; ++ drvr0_en = reverse ? 0x13 : 0x10; ++ drvr1_en = reverse ? 0x10 : 0x13; ++ } else if (dp_opts->lanes == 2) { ++ bias0_en = reverse ? 0x3f : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } else { ++ bias0_en = 0x3f; ++ bias1_en = 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } ++ ++ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); ++ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); ++ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ return 0; ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); ++ if (qphy->dp_opts.set_voltages) { ++ cfg->configure_dp_tx(qphy); ++ qphy->dp_opts.set_voltages = 0; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_calibrate(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->calibrate_dp_phy) ++ return cfg->calibrate_dp_phy(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *dp_com = qmp->dp_com; ++ int ret, i; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (qmp->init_count++) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ /* turn on regulator supplies */ ++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); ++ if (ret) { ++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); ++ goto err_unlock; ++ } ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ ret = reset_control_assert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset assert failed\n", ++ cfg->reset_list[i]); ++ goto err_disable_regulators; ++ } ++ } ++ ++ for (i = cfg->num_resets - 1; i >= 0; i--) { ++ ret = reset_control_deassert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset deassert failed\n", ++ qphy->cfg->reset_list[i]); ++ goto err_assert_reset; ++ } ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ goto err_assert_reset; ++ ++ if (cfg->has_phy_dp_com_ctrl) { ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, ++ SW_PWRDN); ++ /* override hardware control for reset of qmp phy */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ /* Default type-c orientation, i.e CC1 */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); ++ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, ++ USB3_MODE | DP_MODE); ++ ++ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); ++ } ++ ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } else { ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(pcs, ++ cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ else ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++ ++err_assert_reset: ++ while (++i < cfg->num_resets) ++ reset_control_assert(qmp->resets[i]); ++err_disable_regulators: ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++err_unlock: ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ int i = cfg->num_resets; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (--qmp->init_count) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ reset_control_assert(qmp->ufs_reset); ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], ++ SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } ++ ++ while (--i >= 0) ++ reset_control_assert(qmp->resets[i]); ++ ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_init(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret; ++ dev_vdbg(qmp->dev, "Initializing QMP phy\n"); ++ ++ if (cfg->no_pcs_sw_reset) { ++ /* ++ * Get UFS reset, which is delayed until now to avoid a ++ * circular dependency where UFS needs its PHY, but the PHY ++ * needs this UFS reset. ++ */ ++ if (!qmp->ufs_reset) { ++ qmp->ufs_reset = ++ devm_reset_control_get_exclusive(qmp->dev, ++ "ufsphy"); ++ ++ if (IS_ERR(qmp->ufs_reset)) { ++ ret = PTR_ERR(qmp->ufs_reset); ++ dev_err(qmp->dev, ++ "failed to get UFS reset: %d\n", ++ ret); ++ ++ qmp->ufs_reset = NULL; ++ return ret; ++ } ++ } ++ ++ ret = reset_control_assert(qmp->ufs_reset); ++ if (ret) ++ return ret; ++ } ++ ++ ret = qcom_qmp_phy_com_init(qphy); ++ if (ret) ++ return ret; ++ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->dp_aux_init(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_power_on(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ void __iomem *status; ++ unsigned int mask, val, ready; ++ int ret; ++ ++ qcom_qmp_phy_serdes_init(qphy); ++ ++ if (cfg->has_lane_rst) { ++ ret = reset_control_deassert(qphy->lane_rst); ++ if (ret) { ++ dev_err(qmp->dev, "lane%d reset deassert failed\n", ++ qphy->index); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); ++ goto err_reset_lane; ++ } ++ ++ /* Tx, Rx, and PCS configurations */ ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 1); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 1); ++ ++ /* Configuration for other LANE for USB-DP combo PHY */ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 2); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 2); ++ } ++ ++ /* Configure special DP tx tunings */ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->configure_dp_tx(qphy); ++ ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 1); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); ++ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 2); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl_sec, ++ cfg->rx_tbl_num_sec, 2); ++ } ++ ++ /* Configure link rate, swing, etc. */ ++ if (cfg->type == PHY_TYPE_DP) { ++ cfg->configure_dp_phy(qphy); ++ } else { ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); ++ } ++ ++ ret = reset_control_deassert(qmp->ufs_reset); ++ if (ret) ++ goto err_disable_pipe_clk; ++ ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ cfg->pcs_misc_tbl_num); ++ if (cfg->pcs_misc_tbl_sec) ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, ++ cfg->pcs_misc_tbl_num_sec); ++ ++ /* ++ * Pull out PHY from POWER DOWN state. ++ * This is active low enable signal to power-down PHY. ++ */ ++ if(cfg->type == PHY_TYPE_PCIE) ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); ++ ++ if (cfg->has_pwrdn_delay) ++ usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ ++ if (cfg->type != PHY_TYPE_DP) { ++ /* Pull PHY out of reset state */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ /* start SerDes and Phy-Coding-Sublayer */ ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = cfg->phy_status; ++ ready = 0; ++ } ++ ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, "phy initialization timed-out\n"); ++ goto err_disable_pipe_clk; ++ } ++ } ++ return 0; ++ ++err_disable_pipe_clk: ++ clk_disable_unprepare(qphy->pipe_clk); ++err_reset_lane: ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_power_off(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ /* Assert DP PHY power down */ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ } else { ++ /* PHY reset */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ ++ /* stop SerDes and Phy-Coding-Sublayer */ ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ /* Put PHY into POWER DOWN state: active low */ ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ } else { ++ qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_exit(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ qcom_qmp_phy_com_exit(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_enable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_power_on(phy); ++ if (ret) ++ qcom_qmp_phy_exit(phy); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_disable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_power_off(phy); ++ if (ret) ++ return ret; ++ return qcom_qmp_phy_exit(phy); ++} ++ ++static int qcom_qmp_phy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ qphy->mode = mode; ++ ++ return 0; ++} ++ ++static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ u32 intr_mask; ++ ++ if (qphy->mode == PHY_MODE_USB_HOST_SS || ++ qphy->mode == PHY_MODE_USB_DEVICE_SS) ++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; ++ else ++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; ++ ++ /* Clear any pending interrupts status */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); ++ ++ /* Enable required PHY autonomous mode interrupts */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); ++ ++ /* Enable i/o clamp_n for autonomous mode */ ++ if (pcs_misc) ++ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++} ++ ++static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ /* Disable i/o clamp_n on resume for normal mode */ ++ if (pcs_misc) ++ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); ++ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ qcom_qmp_phy_enable_autonomous_mode(qphy); ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret = 0; ++ ++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ return ret; ++ } ++ ++ qcom_qmp_phy_disable_autonomous_mode(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_vregs; ++ int i; ++ ++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); ++ if (!qmp->vregs) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->vregs[i].supply = cfg->vreg_list[i]; ++ ++ return devm_regulator_bulk_get(dev, num, qmp->vregs); ++} ++ ++static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int i; ++ ++ qmp->resets = devm_kcalloc(dev, cfg->num_resets, ++ sizeof(*qmp->resets), GFP_KERNEL); ++ if (!qmp->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ struct reset_control *rst; ++ const char *name = cfg->reset_list[i]; ++ ++ rst = devm_reset_control_get_exclusive(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ return PTR_ERR(rst); ++ } ++ qmp->resets[i] = rst; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_clks; ++ int i; ++ ++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); ++ if (!qmp->clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->clks[i].id = cfg->clk_list[i]; ++ ++ return devm_clk_bulk_get(dev, num, qmp->clks); ++} ++ ++static void phy_clk_release_provider(void *res) ++{ ++ of_clk_del_provider(res); ++} ++ ++/* ++ * Register a fixed rate pipe clock. ++ * ++ * The _pipe_clksrc generated by PHY goes to the GCC that gate ++ * controls it. The _pipe_clk coming out of the GCC is requested ++ * by the PHY driver for its operations. ++ * We register the _pipe_clksrc here. The gcc driver takes care ++ * of assigning this _pipe_clksrc as parent to _pipe_clk. ++ * Below picture shows this relationship. ++ * ++ * +---------------+ ++ * | PHY block |<<---------------------------------------+ ++ * | | | ++ * | +-------+ | +-----+ | ++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ ++ * clk | +-------+ | +-----+ ++ * +---------------+ ++ */ ++static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) ++{ ++ struct clk_fixed_rate *fixed; ++ struct clk_init_data init = { }; ++ int ret; ++ ++ ret = of_property_read_string(np, "clock-output-names", &init.name); ++ if (ret) { ++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); ++ return ret; ++ } ++ ++ fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); ++ if (!fixed) ++ return -ENOMEM; ++ ++ init.ops = &clk_fixed_rate_ops; ++ ++ /* controllers using QMP phys use 125MHz pipe clock interface */ ++ fixed->fixed_rate = 125000000; ++ fixed->hw.init = &init; ++ ++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++/* ++ * Display Port PLL driver block diagram for branch clocks ++ * ++ * +------------------------------+ ++ * | DP_VCO_CLK | ++ * | | ++ * | +-------------------+ | ++ * | | (DP PLL/VCO) | | ++ * | +---------+---------+ | ++ * | v | ++ * | +----------+-----------+ | ++ * | | hsclk_divsel_clk_src | | ++ * | +----------+-----------+ | ++ * +------------------------------+ ++ * | ++ * +---------<---------v------------>----------+ ++ * | | ++ * +--------v----------------+ | ++ * | dp_phy_pll_link_clk | | ++ * | link_clk | | ++ * +--------+----------------+ | ++ * | | ++ * | | ++ * v v ++ * Input to DISPCC block | ++ * for link clk, crypto clk | ++ * and interface clock | ++ * | ++ * | ++ * +--------<------------+-----------------+---<---+ ++ * | | | ++ * +----v---------+ +--------v-----+ +--------v------+ ++ * | vco_divided | | vco_divided | | vco_divided | ++ * | _clk_src | | _clk_src | | _clk_src | ++ * | | | | | | ++ * |divsel_six | | divsel_two | | divsel_four | ++ * +-------+------+ +-----+--------+ +--------+------+ ++ * | | | ++ * v---->----------v-------------<------v ++ * | ++ * +----------+-----------------+ ++ * | dp_phy_pll_vco_div_clk | ++ * +---------+------------------+ ++ * | ++ * v ++ * Input to DISPCC block ++ * for DP pixel clock ++ * ++ */ ++static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 1620000000UL / 2: ++ case 2700000000UL / 2: ++ /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ return 1620000000UL / 2; ++ case 2700: ++ return 2700000000UL / 2; ++ case 5400: ++ return 5400000000UL / 4; ++ case 8100: ++ return 8100000000UL / 6; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { ++ .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, ++}; ++ ++static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 162000000: ++ case 270000000: ++ case 540000000: ++ case 810000000: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ return dp_opts->link_rate * 100000; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_link_clk_ops = { ++ .determine_rate = qcom_qmp_dp_link_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, ++}; ++ ++static struct clk_hw * ++qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct qmp_phy_dp_clks *dp_clks = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx >= 2) { ++ pr_err("%s: invalid index %u\n", __func__, idx); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (idx == 0) ++ return &dp_clks->dp_link_hw; ++ ++ return &dp_clks->dp_pixel_hw; ++} ++ ++static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, ++ struct device_node *np) ++{ ++ struct clk_init_data init = { }; ++ struct qmp_phy_dp_clks *dp_clks; ++ char name[64]; ++ int ret; ++ ++ dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); ++ if (!dp_clks) ++ return -ENOMEM; ++ ++ dp_clks->qphy = qphy; ++ qphy->dp_clks = dp_clks; ++ ++ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_link_clk_ops; ++ init.name = name; ++ dp_clks->dp_link_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); ++ if (ret) ++ return ret; ++ ++ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_pixel_clk_ops; ++ init.name = name; ++ dp_clks->dp_pixel_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++static const struct phy_ops qcom_qmp_phy_gen_ops = { ++ .init = qcom_qmp_phy_enable, ++ .exit = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_phy_dp_ops = { ++ .init = qcom_qmp_phy_init, ++ .configure = qcom_qmp_dp_phy_configure, ++ .power_on = qcom_qmp_phy_power_on, ++ .calibrate = qcom_qmp_dp_phy_calibrate, ++ .power_off = qcom_qmp_phy_power_off, ++ .exit = qcom_qmp_phy_exit, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_pcie_ufs_ops = { ++ .power_on = qcom_qmp_phy_enable, ++ .power_off = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static void qcom_qmp_reset_control_put(void *data) ++{ ++ reset_control_put(data); ++} ++ ++static ++int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++ void __iomem *serdes, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct phy *generic_phy; ++ struct qmp_phy *qphy; ++ const struct phy_ops *ops; ++ char prop_name[MAX_PROP_NAME]; ++ int ret; ++ ++ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); ++ if (!qphy) ++ return -ENOMEM; ++ ++ qphy->cfg = cfg; ++ qphy->serdes = serdes; ++ /* ++ * Get memory resources for each phy lane: ++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. ++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 ++ * For single lane PHYs: pcs_misc (optional) -> 3. ++ */ ++ qphy->tx = of_iomap(np, 0); ++ if (!qphy->tx) ++ return -ENOMEM; ++ ++ qphy->rx = of_iomap(np, 1); ++ if (!qphy->rx) ++ return -ENOMEM; ++ ++ qphy->pcs = of_iomap(np, 2); ++ if (!qphy->pcs) ++ return -ENOMEM; ++ ++ /* ++ * If this is a dual-lane PHY, then there should be registers for the ++ * second lane. Some old device trees did not specify this, so fall ++ * back to old legacy behavior of assuming they can be reached at an ++ * offset from the first lane. ++ */ ++ if (cfg->is_dual_lane_phy) { ++ qphy->tx2 = of_iomap(np, 3); ++ qphy->rx2 = of_iomap(np, 4); ++ if (!qphy->tx2 || !qphy->rx2) { ++ dev_warn(dev, ++ "Underspecified device tree, falling back to legacy register regions\n"); ++ ++ /* In the old version, pcs_misc is at index 3. */ ++ qphy->pcs_misc = qphy->tx2; ++ qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; ++ qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 5); ++ } ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 3); ++ } ++ ++ if (!qphy->pcs_misc) ++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ ++ /* ++ * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 ++ * based phys, so they essentially have pipe clock. So, ++ * we return error in case phy is USB3 or PIPE type. ++ * Otherwise, we initialize pipe clock to NULL for ++ * all phys that don't need this. ++ */ ++ snprintf(prop_name, sizeof(prop_name), "pipe%d", id); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ if (IS_ERR(qphy->pipe_clk)) { ++ if (cfg->type == PHY_TYPE_PCIE || ++ cfg->type == PHY_TYPE_USB3) { ++ ret = PTR_ERR(qphy->pipe_clk); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to get lane%d pipe_clk, %d\n", ++ id, ret); ++ return ret; ++ } ++ qphy->pipe_clk = NULL; ++ } ++ ++ /* Get lane reset, if any */ ++ if (cfg->has_lane_rst) { ++ snprintf(prop_name, sizeof(prop_name), "lane%d", id); ++ qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); ++ if (IS_ERR(qphy->lane_rst)) { ++ dev_err(dev, "failed to get lane%d reset\n", id); ++ return PTR_ERR(qphy->lane_rst); ++ } ++ ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put, ++ qphy->lane_rst); ++ if (ret) ++ return ret; ++ } ++ ++ if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) ++ ops = &qcom_qmp_pcie_ufs_ops; ++ else if (cfg->type == PHY_TYPE_DP) ++ ops = &qcom_qmp_phy_dp_ops; ++ else ++ ops = &qcom_qmp_phy_gen_ops; ++ ++ generic_phy = devm_phy_create(dev, np, ops); ++ if (IS_ERR(generic_phy)) { ++ ret = PTR_ERR(generic_phy); ++ dev_err(dev, "failed to create qphy %d\n", ret); ++ return ret; ++ } ++ ++ qphy->phy = generic_phy; ++ qphy->index = id; ++ qphy->qmp = qmp; ++ qmp->phys[id] = qphy; ++ phy_set_drvdata(generic_phy, qphy); ++ ++ return 0; ++} ++ ++static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,ipq8074-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-pcie-phy", ++ .data = &msm8996_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-ufs-phy", ++ .data = &msm8996_ufs_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-usb3-phy", ++ .data = &msm8996_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-pcie-phy", ++ .data = &msm8998_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,ipq8074-qmp-pcie-phy", ++ .data = &ipq8074_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-pcie-phy", ++ .data = &ipq6018_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-phy", ++ .data = &sc7180_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sc8180x-qmp-pcie-phy", ++ .data = &sc8180x_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8280xp-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sdm845-qhp-pcie-phy", ++ .data = &sdm845_qhp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-pcie-phy", ++ .data = &sdm845_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-phy", ++ .data = &qmp_v3_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-uni-phy", ++ .data = &qmp_v3_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-usb3-phy", ++ .data = &msm8998_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm6115-qmp-ufs-phy", ++ .data = &sm6115_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm6350-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-uni-phy", ++ .data = &sm8150_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-phy", ++ .data = &sm8250_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-uni-phy", ++ .data = &sm8250_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy", ++ .data = &sm8250_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-modem-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-pcie-phy", ++ .data = &sdx55_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-usb3-uni-phy", ++ .data = &sdx55_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdx65-qmp-usb3-uni-phy", ++ .data = &sdx65_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-uni-phy", ++ .data = &sm8350_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy", ++ .data = &sm8450_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy", ++ .data = &sm8450_qmp_gen4x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-ufs-phy", ++ .data = &sm8450_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,qcm2290-qmp-usb3-phy", ++ .data = &qcm2290_usb3phy_cfg, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++ ++static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ .data = &sc7180_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ .data = &sm8250_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ .data = &sc8180x_usb3dpphy_cfg, ++ }, ++ { } ++}; ++ ++static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, ++ qcom_qmp_phy_runtime_resume, NULL) ++}; ++ ++static int qcom_qmp_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_qmp *qmp; ++ struct device *dev = &pdev->dev; ++ struct device_node *child; ++ struct phy_provider *phy_provider; ++ void __iomem *serdes; ++ void __iomem *usb_serdes; ++ void __iomem *dp_serdes = NULL; ++ const struct qmp_phy_combo_cfg *combo_cfg = NULL; ++ const struct qmp_phy_cfg *cfg = NULL; ++ const struct qmp_phy_cfg *usb_cfg = NULL; ++ const struct qmp_phy_cfg *dp_cfg = NULL; ++ int num, id, expected_phys; ++ int ret; ++ ++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); ++ if (!qmp) ++ return -ENOMEM; ++ ++ qmp->dev = dev; ++ dev_set_drvdata(dev, qmp); ++ ++ /* Get the specific init parameters of QMP phy */ ++ cfg = of_device_get_match_data(dev); ++ if (!cfg) { ++ const struct of_device_id *match; ++ ++ match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); ++ if (!match) ++ return -EINVAL; ++ ++ combo_cfg = match->data; ++ if (!combo_cfg) ++ return -EINVAL; ++ ++ usb_cfg = combo_cfg->usb_cfg; ++ cfg = usb_cfg; /* Setup clks and regulators */ ++ } ++ ++ /* per PHY serdes; usually located at base address */ ++ usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(serdes)) ++ return PTR_ERR(serdes); ++ ++ /* per PHY dp_com; if PHY has dp_com control block */ ++ if (combo_cfg || cfg->has_phy_dp_com_ctrl) { ++ qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(qmp->dp_com)) ++ return PTR_ERR(qmp->dp_com); ++ } ++ ++ if (combo_cfg) { ++ /* Only two serdes for combo PHY */ ++ dp_serdes = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(dp_serdes)) ++ return PTR_ERR(dp_serdes); ++ ++ dp_cfg = combo_cfg->dp_cfg; ++ expected_phys = 2; ++ } else { ++ expected_phys = cfg->nlanes; ++ } ++ ++ mutex_init(&qmp->phy_mutex); ++ ++ ret = qcom_qmp_phy_clk_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_reset_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get regulator supplies: %d\n", ++ ret); ++ return ret; ++ } ++ ++ num = of_get_available_child_count(dev->of_node); ++ /* do we have a rogue child node ? */ ++ if (num > expected_phys) ++ return -EINVAL; ++ ++ qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); ++ if (!qmp->phys) ++ return -ENOMEM; ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ /* ++ * Prevent runtime pm from being ON by default. Users can enable ++ * it using power/control in sysfs. ++ */ ++ pm_runtime_forbid(dev); ++ ++ id = 0; ++ for_each_available_child_of_node(dev->of_node, child) { ++ if (of_node_name_eq(child, "dp-phy")) { ++ cfg = dp_cfg; ++ serdes = dp_serdes; ++ } else if (of_node_name_eq(child, "usb3-phy")) { ++ cfg = usb_cfg; ++ serdes = usb_serdes; ++ } ++ ++ /* Create per-lane phy */ ++ ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ if (ret) { ++ dev_err(dev, "failed to create lane%d phy, %d\n", ++ id, ret); ++ goto err_node_put; ++ } ++ ++ /* ++ * Register the pipe clock provided by phy. ++ * See function description to see details of this pipe clock. ++ */ ++ if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; ++ } ++ } else if (cfg->type == PHY_TYPE_DP) { ++ ret = phy_dp_clks_register(qmp, qmp->phys[id], child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register DP clock source\n"); ++ goto err_node_put; ++ } ++ } ++ id++; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (!IS_ERR(phy_provider)) ++ dev_info(dev, "Registered Qcom-QMP phy\n"); ++ else ++ pm_runtime_disable(dev); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++ ++err_node_put: ++ pm_runtime_disable(dev); ++ of_node_put(child); ++ return ret; ++} ++ ++static struct platform_driver qcom_qmp_phy_driver = { ++ .probe = qcom_qmp_phy_probe, ++ .driver = { ++ .name = "qcom-qmp-phy", ++ .pm = &qcom_qmp_phy_pm_ops, ++ .of_match_table = qcom_qmp_phy_of_match_table, ++ }, ++}; ++ ++module_platform_driver(qcom_qmp_phy_driver); ++ ++MODULE_AUTHOR("Vivek Gautam "); ++MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +new file mode 100644 +index 000000000000..c7309e981bfb +--- /dev/null ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -0,0 +1,6350 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (c) 2017, The Linux Foundation. All rights reserved. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "phy-qcom-qmp.h" ++ ++/* QPHY_SW_RESET bit */ ++#define SW_RESET BIT(0) ++/* QPHY_POWER_DOWN_CONTROL */ ++#define SW_PWRDN BIT(0) ++#define REFCLK_DRV_DSBL BIT(1) ++/* QPHY_START_CONTROL bits */ ++#define SERDES_START BIT(0) ++#define PCS_START BIT(1) ++#define PLL_READY_GATE_EN BIT(3) ++/* QPHY_PCS_STATUS bit */ ++#define PHYSTATUS BIT(6) ++#define PHYSTATUS_4_20 BIT(7) ++/* QPHY_PCS_READY_STATUS & QPHY_COM_PCS_READY_STATUS bit */ ++#define PCS_READY BIT(0) ++ ++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */ ++/* DP PHY soft reset */ ++#define SW_DPPHY_RESET BIT(0) ++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */ ++#define SW_DPPHY_RESET_MUX BIT(1) ++/* USB3 PHY soft reset */ ++#define SW_USB3PHY_RESET BIT(2) ++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */ ++#define SW_USB3PHY_RESET_MUX BIT(3) ++ ++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */ ++#define USB3_MODE BIT(0) /* enables USB3 mode */ ++#define DP_MODE BIT(1) /* enables DP mode */ ++ ++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */ ++#define ARCVR_DTCT_EN BIT(0) ++#define ALFPS_DTCT_EN BIT(1) ++#define ARCVR_DTCT_EVENT_SEL BIT(4) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */ ++#define IRQ_CLEAR BIT(0) ++ ++/* QPHY_PCS_LFPS_RXTERM_IRQ_STATUS register bits */ ++#define RCVR_DETECT BIT(0) ++ ++/* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */ ++#define CLAMP_EN BIT(0) /* enables i/o clamp_n */ ++ ++#define PHY_INIT_COMPLETE_TIMEOUT 10000 ++#define POWER_DOWN_DELAY_US_MIN 10 ++#define POWER_DOWN_DELAY_US_MAX 11 ++ ++#define MAX_PROP_NAME 32 ++ ++/* Define the assumed distance between lanes for underspecified device trees. */ ++#define QMP_PHY_LEGACY_LANE_STRIDE 0x400 ++ ++struct qmp_phy_init_tbl { ++ unsigned int offset; ++ unsigned int val; ++ /* ++ * register part of layout ? ++ * if yes, then offset gives index in the reg-layout ++ */ ++ bool in_layout; ++ /* ++ * mask of lanes for which this register is written ++ * for cases when second lane needs different values ++ */ ++ u8 lane_mask; ++}; ++ ++#define QMP_PHY_INIT_CFG(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_L(o, v) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .in_layout = true, \ ++ .lane_mask = 0xff, \ ++ } ++ ++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ ++ { \ ++ .offset = o, \ ++ .val = v, \ ++ .lane_mask = l, \ ++ } ++ ++/* set of registers with offsets different per-PHY */ ++enum qphy_reg_layout { ++ /* Common block control registers */ ++ QPHY_COM_SW_RESET, ++ QPHY_COM_POWER_DOWN_CONTROL, ++ QPHY_COM_START_CONTROL, ++ QPHY_COM_PCS_READY_STATUS, ++ /* PCS registers */ ++ QPHY_PLL_LOCK_CHK_DLY_TIME, ++ QPHY_FLL_CNTRL1, ++ QPHY_FLL_CNTRL2, ++ QPHY_FLL_CNT_VAL_L, ++ QPHY_FLL_CNT_VAL_H_TOL, ++ QPHY_FLL_MAN_CODE, ++ QPHY_SW_RESET, ++ QPHY_START_CTRL, ++ QPHY_PCS_READY_STATUS, ++ QPHY_PCS_STATUS, ++ QPHY_PCS_AUTONOMOUS_MODE_CTRL, ++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR, ++ QPHY_PCS_LFPS_RXTERM_IRQ_STATUS, ++ QPHY_PCS_POWER_DOWN_CONTROL, ++ /* PCS_MISC registers */ ++ QPHY_PCS_MISC_TYPEC_CTRL, ++ /* Keep last to ensure regs_layout arrays are properly initialized */ ++ QPHY_LAYOUT_SIZE ++}; ++ ++static const unsigned int msm8996_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int ipq_pciephy_gen3_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_COM_SW_RESET] = 0x400, ++ [QPHY_COM_POWER_DOWN_CONTROL] = 0x404, ++ [QPHY_COM_START_CONTROL] = 0x408, ++ [QPHY_COM_PCS_READY_STATUS] = 0x448, ++ [QPHY_PLL_LOCK_CHK_DLY_TIME] = 0xa8, ++ [QPHY_FLL_CNTRL1] = 0xc4, ++ [QPHY_FLL_CNTRL2] = 0xc8, ++ [QPHY_FLL_CNT_VAL_L] = 0xcc, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xd0, ++ [QPHY_FLL_MAN_CODE] = 0xd4, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_FLL_CNTRL1] = 0xc0, ++ [QPHY_FLL_CNTRL2] = 0xc4, ++ [QPHY_FLL_CNT_VAL_L] = 0xc8, ++ [QPHY_FLL_CNT_VAL_H_TOL] = 0xcc, ++ [QPHY_FLL_MAN_CODE] = 0xd0, ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x17c, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d4, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x178, ++}; ++ ++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x0d8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x0dc, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_STATUS] = 0x170, ++}; ++ ++static const unsigned int sdm845_qmp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x174, ++}; ++ ++static const unsigned int sdm845_qhp_pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_STATUS] = 0x2ac, ++}; ++ ++static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x308, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x314, ++}; ++ ++static const unsigned int qmp_v4_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x608, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x614, ++}; ++ ++static const unsigned int sm8350_usb3_uniphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0x1008, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0x1014, ++}; ++ ++static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x04, ++ [QPHY_START_CTRL] = 0x08, ++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = 0xd8, ++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = 0xdc, ++ [QPHY_PCS_STATUS] = 0x174, ++ [QPHY_PCS_MISC_TYPEC_CTRL] = 0x00, ++}; ++ ++static const unsigned int sdm845_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x160, ++}; ++ ++static const unsigned int sm6115_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = 0x00, ++ [QPHY_PCS_READY_STATUS] = 0x168, ++}; ++ ++static const unsigned int sm8250_pcie_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_SW_RESET] = 0x00, ++ [QPHY_START_CTRL] = 0x44, ++ [QPHY_PCS_STATUS] = 0x14, ++ [QPHY_PCS_POWER_DOWN_CONTROL] = 0x40, ++}; ++ ++static const unsigned int sm8150_ufsphy_regs_layout[QPHY_LAYOUT_SIZE] = { ++ [QPHY_START_CTRL] = QPHY_V4_PCS_UFS_PHY_START, ++ [QPHY_PCS_READY_STATUS] = QPHY_V4_PCS_UFS_READY_STATUS, ++ [QPHY_SW_RESET] = QPHY_V4_PCS_UFS_SW_RESET, ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x0), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESCODE_DIV_NUM, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_IDLE_DTCT_CNTRL, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x05), ++ ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG4, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG1, 0xa3), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_POWER_DOWN_CONTROL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xd7), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_ufs_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0E), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x04), ++ /* PLL and Loop filter settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ /* SSC settings */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++}; ++ ++static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_CNT_VAL_H_TOL, 0x42), ++ QMP_PHY_INIT_CFG_L(QPHY_FLL_MAN_CODE, 0x85), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE1_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SSC_STEP_SIZE2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE0, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP1_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP2_MODE1, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CP_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_BIAS_EN_CTRL_BY_PSM, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE0, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DEC_START_MODE1, 0x53), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE0, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE0, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_INTEGLOOP_GAIN0_MODE1, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CLK_SELECT, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_PLL_CORECLK_DIV_MODE1, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_TX0_RCV_DETECT_LVL_2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_GAIN, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL2, 0x61), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQU_ADAPTOR_CNTRL4, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x73), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_LOW, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH2, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH3, 0xd3), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_00_HIGH4, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_LOW, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_RX_MODE_10_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_RX0_DFE_EN_TIMER, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCS_COM_FLL_CNTRL1, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_COM_G12S1_TXDEEMPH_M3P5DB, 0x10), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(PCS_COM_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_RX_DCC_CAL_CONFIG, 0x01), ++ QMP_PHY_INIT_CFG(PCS_COM_EQ_CONFIG5, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++ QMP_PHY_INIT_CFG(PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_EQ_CONFIG1, 0x11), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(PCS_PCIE_PRESET_P10_POST, 0x58), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2), ++ QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4), ++}; ++ ++static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4), ++ QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0), ++ QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40), ++ QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe), ++ QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0), ++ QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x007), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_EP_DIV, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x33), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x7e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x15), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_01, 0x59), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x71), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x40), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_ENDPOINT_REFCLK_DRIVE, 0x04), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LP_WAKEUP_DLY_TIME_AUXCLK, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PLL_LOCK_CHK_DLY_TIME, 0x73), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xbb), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2, 0x52), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4, 0x1a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL, 0x27), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_ENABLE1, 0xb0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_RESTRIM_CTRL2, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VCO_TUNE_MAP, 0x10), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CLK_SELECT, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_HSCLK_SEL1, 0x30), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORE_CLK_EN, 0x73), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV1, 0x22), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_VREGCLK_DIV2, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BGV_TRIM, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_COM_BG_CTRL, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL0, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_TAP_EN, 0x0d), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TX_BAND_MODE, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_LANE_MODE, 0x1a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PARALLEL_RATE, 0x2f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE0, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE1, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CML_CTRL_MODE2, 0x1b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1, 0x31), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CGA_THRESH_DFE, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXENGINE_EN0, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME, 0x25), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME, 0x05), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_GAIN, 0x26), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DFE_GAIN, 0x12), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_OFFSET_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PRE_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EQ_INTVAL, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_EDAC_INITVAL, 0x28), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB0, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_INITB1, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RXEQ_CTRL, 0x70), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0, 0x8b), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2, 0x0a), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_BAND, 0x02), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0, 0x5c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1, 0x3e), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_ENABLES, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_CNTRL, 0xa0), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL, 0x08), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DCC_GAIN, 0x01), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_EN_SIGNAL, 0xc3), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL, 0x00), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0, 0xbc), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_TS0_TIMER, 0x7f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE, 0x15), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_DRVR_CTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET, 0x04), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_VGA_INITVAL, 0x20), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_L0_RSM_START, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_qhp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG, 0x3f), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG, 0x50), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB, 0x19), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB, 0x07), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB, 0x17), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB, 0x09), ++ QMP_PHY_INIT_CFG(PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5, 0x9f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_ENABLE1, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRANSCEIVER_BIAS_EN, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_INTERFACE_SELECT, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TRAN_DRVR_EMP_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_DRV_LVL, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_TX_EMP_POST1_LVL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { ++ /* FLL settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0xba), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb5), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4c), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x64), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x1d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE1, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE1, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE1, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE1_MODE1, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_INITVAL2, 0x00), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45), ++ QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x0F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x1E), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_FASTLOCK_FO_GAIN, 0x0B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_TERM_BW, 0x5B), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN1_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQ_GAIN2_MSB, 0x3F), ++ QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0D), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5B), ++}; ++ ++static const struct qmp_phy_init_tbl sm6115_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_RX_PWM_GEAR_BAND, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_DRV_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_STALL_NOCONFIG_TIME_CAP, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_TX_LARGE_AMP_POST_EMP_LVL, 0x12), ++ QMP_PHY_INIT_CFG(QPHY_TX_SMALL_AMP_POST_EMP_LVL, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_RX_MIN_HIBERN8_TIME, 0x9a), /* 8 us */ ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xda), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE1, 0xc1), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE1, 0x0f), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x44), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_INTERFACE_MODE, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_TERM_BW, 0x5b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_HALF, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN_QUARTER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SVS_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x59), ++}; ++ ++static const struct qmp_phy_init_tbl sdm845_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SYM_RESYNC_CTRL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_CTRL1, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_MIN_HIBERN8_TIME, 0x9a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85), ++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TX_LARGE_AMP_DRV_LVL, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x32), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x3d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb1), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0xb1), ++ ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x94), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_pcs_tbl[] = { ++ /* Lock Det settings */ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xea), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_IPTRIM, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x95), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb3), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_TX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_RX, 0x60), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x40, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_TX_PI_QEC_CTRL, 0x54, 2), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0xff, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f, 2), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0xb8), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xa9), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SVS_MODE_CLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_CTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORE_CLK_EN, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_rbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x6f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr2[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x8c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_serdes_tbl_hbr3[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x69), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl qmp_v4_dp_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_VMODE_CTRL1, 0x40), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PRE_STALL_LDO_BOOST_EN, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_INTERFACE_SELECT, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_CLKBUF_ENABLE, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RESET_TSYNC_EN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TRAN_DRVR_EMP_EN, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PARRATE_REC_DETECT_IDLE_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_INTERFACE_MODE, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_RX, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_BAND, 0x4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_POL_INV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_DRV_LVL, 0x2a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_TX_EMP_POST1_LVL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x5), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x6e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x39), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl sc8180x_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_BUF_ENABLE, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x11), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_AUX_DATA_TCOARSE_TFINE, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x70), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_ENABLES, 0x1c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_LOW, 0xd4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH2, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_10_HIGH4, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0xec), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0x36), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RCLK_AUXDATA_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_P2U3_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RATE_SLEW_CNTRL1, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE, 0x33), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_PRE, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_PRESET_P10_POST, 0x58), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x05), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG2, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8250_qmp_gen3x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2, 0x0d), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_1, 0xd5), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_LANE_MODE_2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V4_TX_RES_CODE_LANE_OFFSET_TX, 0x08), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH4, 0x26), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH3, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH4, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH1, 0x048), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_VGA_CAL_CNTRL2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_RX_GM_CAL, 0x1f), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BG_TIMER, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYS_CLK_CTRL, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CP_CTRL_MODE1, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_RCTRL_MODE1, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_PLL_CCTRL_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE0, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE0, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP1_MODE1, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_LOCK_CMP2_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE0, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DEC_START_MODE1, 0x50), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_DIV_FRAC_START3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE0, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE0, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN0_MODE1, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTEGLOOP_GAIN1_MODE1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE0, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_CONFIG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_INTERNAL_DIG_CORECLK_DIV, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_CMN_MODE, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_VCO_DC_LEVEL_CTRL, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0x56), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0x4b), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x22), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_LANE_MODE_3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_VMODE_CTRL1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_TX_PI_QEC_CTRL, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_AUX_DATA_TCOARSE_TFINE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_3, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_DAC_ENABLE2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_VGA_CAL_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x27), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B1, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B2, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B3, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE_0_1_B4, 0x37), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B0, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B1, 0xf9), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B3, 0xce), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE2_B4, 0x62), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B0, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B1, 0x7d), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B3, 0xcf), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_RX_MODE_RATE3_B4, 0xd6), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_PHPRE_CTRL, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V4_20_RX_MARG_COARSE_CTRL2, 0x12), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG4, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_EQ_CONFIG5, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sdx55_qmp_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_EQ_CONFIG1, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2, 0x01), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0b), ++}; ++ ++static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), ++ ++ /* Rate B */ ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_ufsphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_PLL_CNTL, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_MSB, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TIMER_20US_CORECLK_STEPS_LSB, 0xd8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_PWM_GEAR_BAND, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HS_GEAR_BAND, 0x06), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_HSGEAR_CAPABILITY, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_RX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x35), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_5, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbb), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3d, 1), ++ QMP_PHY_INIT_CFG_LANE(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3c, 2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xd2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x13), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_EN_TIMER, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VTH_CODE, 0x10), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_RXEQTRAINING_DFE_TIME_S2, 0x07), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xa5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_2, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x21), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x0e), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0xbd), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa9), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x7b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xe4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x64), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0x99), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_GAIN2, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x47), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x0e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_ENABLES, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG1, 0xd0), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG3, 0x20), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_LOCK_DETECT_CONFIG6, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_RX_SIGDET_LVL, 0xaa), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_PCS_TX_RX_CONFIG, 0x0c), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_RXEQTRAINING_DFE_TIME_S2, 0x07), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_UNI_LFPS_DET_HIGH_COUNT_VAL, 0xf8), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_CDR_RESET_TIME, 0x0a), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG1, 0x88), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_ALIGN_DETECT_CONFIG2, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG1, 0x4b), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_EQ_CONFIG5, 0x10), ++ QMP_PHY_INIT_CFG(QPHY_V4_PCS_REFGEN_REQ_CONFIG1, 0x21), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00), ++}; ++ ++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE0, 0x24), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE2_MODE1, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE1_MODE1, 0xb4), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x68), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0xaa), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0xab), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xca), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x18), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xa2), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_BUF_ENABLE, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_EN_CENTER, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x4c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_PI_QEC_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0x75), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_4, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x04), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xff), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0xd8), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xdc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0x5c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xa6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_GM_CAL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH1, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SB2_THRESH2, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_TX_ADAPT_POST_THRESH, 0xf0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x09), ++ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x77), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RATE_SLEW_CNTRL1, 0x0b), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_REFGEN_REQ_CONFIG1, 0x05), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen3x1_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_EQ_CONFIG2, 0x0f), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_serdes_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER1, 0x31), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_PER2, 0x01), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0, 0x07), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1, 0x97), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_ENABLE1, 0x90), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x36), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x08), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x46), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_CFG, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0xd0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE0, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE0, 0x03), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START1_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START2_MODE1, 0x55), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_DIV_FRAC_START3_MODE1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CLK_SELECT, 0x34), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE0, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORECLK_DIV_MODE1, 0x04), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MISC1, 0x88), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CORE_CLK_EN, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_CONFIG, 0x06), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_CMN_MODE, 0x14), ++ QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_DC_LEVEL_CTRL, 0x0f), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_tx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_1, 0x05), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_LANE_MODE_2, 0xf6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_TX_RES_CODE_LANE_OFFSET_RX, 0x0c), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_rx_tbl[] = { ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_PI_CONTROLS, 0x16), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B1, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B2, 0x12), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B3, 0xcc), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B5, 0x4a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE_0_1_B6, 0x29), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B0, 0xc5), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B1, 0xad), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B2, 0xb6), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B3, 0xc0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B4, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B5, 0xfb), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE2_B6, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B0, 0xc7), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B1, 0xef), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B2, 0xbf), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B3, 0xa0), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B4, 0x81), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B5, 0xde), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MODE_RATE3_B6, 0x7f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_PHPRE_CTRL, 0x20), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_0_1, 0x3f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_AUX_DATA_THRESH_BIN_RATE_2_3, 0x37), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_3, 0x05), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), ++ ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE2, 0x0c), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_UCDR_FO_GAIN_RATE3, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_VGA_CAL_MAN_VAL, 0x0a), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0b), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_RX_IDAC_SAOFFSET, 0x10), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_DFE_DAC_ENABLE1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_GM_CAL, 0x0f), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH1, 0x00), ++ QMP_PHY_INIT_CFG(QSERDES_V5_20_RX_TX_ADAPT_POST_THRESH2, 0x1f), ++}; ++ ++/* Register names should be validated, they might be different for this PHY */ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG2, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_EQ_CONFIG3, 0x22), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_G3S2_PRE_GAIN, 0x2e), ++ QMP_PHY_INIT_CFG(QPHY_V5_PCS_RX_SIGDET_LVL, 0x99), ++}; ++ ++static const struct qmp_phy_init_tbl sm8450_qmp_gen4x2_pcie_pcs_misc_tbl[] = { ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5, 0x02), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_EQ_CONFIG1, 0x16), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3, 0x28), ++ QMP_PHY_INIT_CFG(QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN, 0x2e), ++}; ++ ++struct qmp_phy; ++ ++/* struct qmp_phy_cfg - per-PHY initialization config */ ++struct qmp_phy_cfg { ++ /* phy-type - PCIE/UFS/USB */ ++ unsigned int type; ++ /* number of lanes provided by phy */ ++ int nlanes; ++ ++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ ++ const struct qmp_phy_init_tbl *serdes_tbl; ++ int serdes_tbl_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_sec; ++ int serdes_tbl_num_sec; ++ const struct qmp_phy_init_tbl *tx_tbl; ++ int tx_tbl_num; ++ const struct qmp_phy_init_tbl *tx_tbl_sec; ++ int tx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *rx_tbl; ++ int rx_tbl_num; ++ const struct qmp_phy_init_tbl *rx_tbl_sec; ++ int rx_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_tbl; ++ int pcs_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_tbl_sec; ++ int pcs_tbl_num_sec; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl; ++ int pcs_misc_tbl_num; ++ const struct qmp_phy_init_tbl *pcs_misc_tbl_sec; ++ int pcs_misc_tbl_num_sec; ++ ++ /* Init sequence for DP PHY block link rates */ ++ const struct qmp_phy_init_tbl *serdes_tbl_rbr; ++ int serdes_tbl_rbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr; ++ int serdes_tbl_hbr_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr2; ++ int serdes_tbl_hbr2_num; ++ const struct qmp_phy_init_tbl *serdes_tbl_hbr3; ++ int serdes_tbl_hbr3_num; ++ ++ /* DP PHY callbacks */ ++ int (*configure_dp_phy)(struct qmp_phy *qphy); ++ void (*configure_dp_tx)(struct qmp_phy *qphy); ++ int (*calibrate_dp_phy)(struct qmp_phy *qphy); ++ void (*dp_aux_init)(struct qmp_phy *qphy); ++ ++ /* clock ids to be requested */ ++ const char * const *clk_list; ++ int num_clks; ++ /* resets to be requested */ ++ const char * const *reset_list; ++ int num_resets; ++ /* regulators to be requested */ ++ const char * const *vreg_list; ++ int num_vregs; ++ ++ /* array of registers with different offsets */ ++ const unsigned int *regs; ++ ++ unsigned int start_ctrl; ++ unsigned int pwrdn_ctrl; ++ unsigned int mask_com_pcs_ready; ++ /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ ++ unsigned int phy_status; ++ ++ /* true, if PHY has a separate PHY_COM control block */ ++ bool has_phy_com_ctrl; ++ /* true, if PHY has a reset for individual lanes */ ++ bool has_lane_rst; ++ /* true, if PHY needs delay after POWER_DOWN */ ++ bool has_pwrdn_delay; ++ /* power_down delay in usec */ ++ int pwrdn_delay_min; ++ int pwrdn_delay_max; ++ ++ /* true, if PHY has a separate DP_COM control block */ ++ bool has_phy_dp_com_ctrl; ++ /* true, if PHY has secondary tx/rx lanes to be configured */ ++ bool is_dual_lane_phy; ++ ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; ++}; ++ ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; ++}; ++ ++/** ++ * struct qmp_phy - per-lane phy descriptor ++ * ++ * @phy: generic phy ++ * @cfg: phy specific configuration ++ * @serdes: iomapped memory space for phy's serdes (i.e. PLL) ++ * @tx: iomapped memory space for lane's tx ++ * @rx: iomapped memory space for lane's rx ++ * @pcs: iomapped memory space for lane's pcs ++ * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) ++ * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) ++ * @pcs_misc: iomapped memory space for lane's pcs_misc ++ * @pipe_clk: pipe clock ++ * @index: lane index ++ * @qmp: QMP phy to which this lane belongs ++ * @lane_rst: lane's reset controller ++ * @mode: current PHY mode ++ * @dp_aux_cfg: Display port aux config ++ * @dp_opts: Display port optional config ++ * @dp_clks: Display port clocks ++ */ ++struct qmp_phy { ++ struct phy *phy; ++ const struct qmp_phy_cfg *cfg; ++ void __iomem *serdes; ++ void __iomem *tx; ++ void __iomem *rx; ++ void __iomem *pcs; ++ void __iomem *tx2; ++ void __iomem *rx2; ++ void __iomem *pcs_misc; ++ struct clk *pipe_clk; ++ unsigned int index; ++ struct qcom_qmp *qmp; ++ struct reset_control *lane_rst; ++ enum phy_mode mode; ++ unsigned int dp_aux_cfg; ++ struct phy_configure_opts_dp dp_opts; ++ struct qmp_phy_dp_clks *dp_clks; ++}; ++ ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; ++ ++/** ++ * struct qcom_qmp - structure holding QMP phy block attributes ++ * ++ * @dev: device ++ * @dp_com: iomapped memory space for phy's dp_com control block ++ * ++ * @clks: array of clocks required by phy ++ * @resets: array of resets required by phy ++ * @vregs: regulator supplies bulk data ++ * ++ * @phys: array of per-lane phy descriptors ++ * @phy_mutex: mutex lock for PHY common block initialization ++ * @init_count: phy common block initialization count ++ * @ufs_reset: optional UFS PHY reset handle ++ */ ++struct qcom_qmp { ++ struct device *dev; ++ void __iomem *dp_com; ++ ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; ++ ++ struct qmp_phy **phys; ++ ++ struct mutex phy_mutex; ++ int init_count; ++ ++ struct reset_control *ufs_reset; ++}; ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy); ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy); ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy); ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy); ++ ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; ++ ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); ++ ++ /* ensure that above write is through */ ++ readl(base + offset); ++} ++ ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", ++}; ++ ++static const char * const msm8996_ufs_phy_clk_l[] = { ++ "ref", ++}; ++ ++static const char * const qmp_v3_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "com_aux", ++}; ++ ++static const char * const sdm845_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", "refgen", ++}; ++ ++static const char * const qmp_v4_phy_clk_l[] = { ++ "aux", "ref_clk_src", "ref", "com_aux", ++}; ++ ++/* the primary usb3 phy on sm8250 doesn't have a ref clock */ ++static const char * const qmp_v4_sm8250_usbphy_clk_l[] = { ++ "aux", "ref_clk_src", "com_aux" ++}; ++ ++static const char * const sm8450_ufs_phy_clk_l[] = { ++ "qref", "ref", "ref_aux", ++}; ++ ++static const char * const sdm845_ufs_phy_clk_l[] = { ++ "ref", "ref_aux", ++}; ++ ++/* usb3 phy on sdx55 doesn't have com_aux clock */ ++static const char * const qmp_v4_sdx55_usbphy_clk_l[] = { ++ "aux", "cfg_ahb", "ref" ++}; ++ ++static const char * const qcm2290_usb3phy_clk_l[] = { ++ "cfg_ahb", "ref", "com_aux", ++}; ++ ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", ++}; ++ ++static const char * const msm8996_usb3phy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const char * const sc7180_usb3phy_reset_l[] = { ++ "phy", ++}; ++ ++static const char * const qcm2290_usb3phy_reset_l[] = { ++ "phy_phy", "phy", ++}; ++ ++static const char * const sdm845_pciephy_reset_l[] = { ++ "phy", ++}; ++ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = ipq8074_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_usb3_rx_tbl), ++ .pcs_tbl = ipq8074_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, ++ ++ .serdes_tbl = msm8996_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_pcie_serdes_tbl), ++ .tx_tbl = msm8996_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_pcie_tx_tbl), ++ .rx_tbl = msm8996_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_pcie_rx_tbl), ++ .pcs_tbl = msm8996_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = true, ++ .has_lane_rst = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg msm8996_ufs_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_ufs_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_ufs_serdes_tbl), ++ .tx_tbl = msm8996_ufs_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_ufs_tx_tbl), ++ .rx_tbl = msm8996_ufs_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_ufs_rx_tbl), ++ ++ .clk_list = msm8996_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_ufs_phy_clk_l), ++ ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ ++ .regs = msm8996_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8996_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8996_usb3_serdes_tbl), ++ .tx_tbl = msm8996_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8996_usb3_tx_tbl), ++ .rx_tbl = msm8996_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8996_usb3_rx_tbl), ++ .pcs_tbl = msm8996_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8996_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const char * const ipq8074_pciephy_clk_l[] = { ++ "aux", "cfg_ahb", ++}; ++/* list of resets */ ++static const char * const ipq8074_pciephy_reset_l[] = { ++ "phy", "common", ++}; ++ ++static const struct qmp_phy_cfg ipq8074_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq8074_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl), ++ .tx_tbl = ipq8074_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl), ++ .rx_tbl = ipq8074_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl), ++ .pcs_tbl = ipq8074_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = ipq6018_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(ipq6018_pcie_serdes_tbl), ++ .tx_tbl = ipq6018_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(ipq6018_pcie_tx_tbl), ++ .rx_tbl = ipq6018_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), ++ .pcs_tbl = ipq6018_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .clk_list = ipq8074_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = NULL, ++ .num_vregs = 0, ++ .regs = ipq_pciephy_gen3_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_phy_com_ctrl = false, ++ .has_lane_rst = false, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdm845_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdm845_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qmp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdm845_qhp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sdm845_qhp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_serdes_tbl), ++ .tx_tbl = sdm845_qhp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_tx_tbl), ++ .rx_tbl = sdm845_qhp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_rx_tbl), ++ .pcs_tbl = sdm845_qhp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_qhp_pcie_pcs_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_qhp_pciephy_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .serdes_tbl_sec = sm8250_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8250_qmp_gen3x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8250_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_serdes_tbl), ++ .tx_tbl = sm8250_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_tx_tbl), ++ .tx_tbl_sec = sm8250_qmp_gen3x2_pcie_tx_tbl, ++ .tx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_tx_tbl), ++ .rx_tbl = sm8250_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_rx_tbl), ++ .rx_tbl_sec = sm8250_qmp_gen3x2_pcie_rx_tbl, ++ .rx_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_rx_tbl), ++ .pcs_tbl = sm8250_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_tbl), ++ .pcs_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_tbl, ++ .pcs_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8250_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8250_qmp_pcie_pcs_misc_tbl), ++ .pcs_misc_tbl_sec = sm8250_qmp_gen3x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num_sec = ARRAY_SIZE(sm8250_qmp_gen3x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc7180_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl), ++ .tx_tbl = qmp_v3_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v3_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v3_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v3_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v3_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v3_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v3_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v3_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v3_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v3_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc7180_usb3dpphy_cfg = { ++ .usb_cfg = &sc7180_usb3phy_cfg, ++ .dp_cfg = &sc7180_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v3_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_serdes_tbl), ++ .tx_tbl = qmp_v3_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_tx_tbl), ++ .rx_tbl = qmp_v3_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_rx_tbl), ++ .pcs_tbl = qmp_v3_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qmp_v3_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdm845_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdm845_ufsphy_serdes_tbl), ++ .tx_tbl = sdm845_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_tx_tbl), ++ .rx_tbl = sdm845_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdm845_ufsphy_rx_tbl), ++ .pcs_tbl = sdm845_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdm845_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sdm845_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg sm6115_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm6115_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm6115_ufsphy_serdes_tbl), ++ .tx_tbl = sm6115_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_tx_tbl), ++ .rx_tbl = sm6115_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm6115_ufsphy_rx_tbl), ++ .pcs_tbl = sm6115_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm6115_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm6115_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ ++ .is_dual_lane_phy = false, ++ .no_pcs_sw_reset = true, ++}; ++ ++static const struct qmp_phy_cfg msm8998_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_pcie_serdes_tbl), ++ .tx_tbl = msm8998_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_pcie_tx_tbl), ++ .rx_tbl = msm8998_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_pcie_rx_tbl), ++ .pcs_tbl = msm8998_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_pcie_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = ipq8074_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = pciephy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++}; ++ ++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = msm8998_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl), ++ .tx_tbl = msm8998_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl), ++ .rx_tbl = msm8998_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl), ++ .pcs_tbl = msm8998_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl), ++ .clk_list = msm8996_phy_clk_l, ++ .num_clks = ARRAY_SIZE(msm8996_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8150_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_ufsphy_serdes_tbl), ++ .tx_tbl = sm8150_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_tx_tbl), ++ .rx_tbl = sm8150_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_ufsphy_rx_tbl), ++ .pcs_tbl = sm8150_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8150_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_tx_tbl), ++ .rx_tbl = sm8150_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_rx_tbl), ++ .pcs_tbl = sm8150_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sc8180x_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sc8180x_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_serdes_tbl), ++ .tx_tbl = sc8180x_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_tx_tbl), ++ .rx_tbl = sc8180x_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_rx_tbl), ++ .pcs_tbl = sc8180x_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sc8180x_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sc8180x_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sc8180x_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v3_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v3_phy_clk_l), ++ .reset_list = sc7180_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(sc7180_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v3_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sc8180x_usb3dpphy_cfg = { ++ .usb_cfg = &sm8150_usb3phy_cfg, ++ .dp_cfg = &sc8180x_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8150_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8150_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8150_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8250_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_tx_tbl), ++ .rx_tbl = sm8250_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_rx_tbl), ++ .pcs_tbl = sm8250_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8250_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8250_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8250_dpphy_cfg = { ++ .type = PHY_TYPE_DP, ++ .nlanes = 1, ++ ++ .serdes_tbl = qmp_v4_dp_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl), ++ .tx_tbl = qmp_v4_dp_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qmp_v4_dp_tx_tbl), ++ ++ .serdes_tbl_rbr = qmp_v4_dp_serdes_tbl_rbr, ++ .serdes_tbl_rbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_rbr), ++ .serdes_tbl_hbr = qmp_v4_dp_serdes_tbl_hbr, ++ .serdes_tbl_hbr_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr), ++ .serdes_tbl_hbr2 = qmp_v4_dp_serdes_tbl_hbr2, ++ .serdes_tbl_hbr2_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr2), ++ .serdes_tbl_hbr3 = qmp_v4_dp_serdes_tbl_hbr3, ++ .serdes_tbl_hbr3_num = ARRAY_SIZE(qmp_v4_dp_serdes_tbl_hbr3), ++ ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++ ++ .dp_aux_init = qcom_qmp_v4_phy_dp_aux_init, ++ .configure_dp_tx = qcom_qmp_v4_phy_configure_dp_tx, ++ .configure_dp_phy = qcom_qmp_v4_phy_configure_dp_phy, ++ .calibrate_dp_phy = qcom_qmp_v4_dp_phy_calibrate, ++}; ++ ++static const struct qmp_phy_combo_cfg sm8250_usb3dpphy_cfg = { ++ .usb_cfg = &sm8250_usb3phy_cfg, ++ .dp_cfg = &sm8250_dpphy_cfg, ++}; ++ ++static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx55_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx55_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8250_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8250_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sdx55_qmp_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sdx55_qmp_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_serdes_tbl), ++ .tx_tbl = sdx55_qmp_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_tx_tbl), ++ .rx_tbl = sdx55_qmp_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_rx_tbl), ++ .pcs_tbl = sdx55_qmp_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_tbl), ++ .pcs_misc_tbl = sdx55_qmp_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sdx55_qmp_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = PCS_START | SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sdx65_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_tx_tbl), ++ .rx_tbl = sdx65_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sdx65_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_sdx55_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sdx55_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8350_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sdm845_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_serdes_tbl), ++ .tx_tbl = sm8350_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_tx_tbl), ++ .rx_tbl = sm8350_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_rx_tbl), ++ .pcs_tbl = sm8350_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_pcs_tbl), ++ .clk_list = qmp_v4_sm8250_usbphy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_sm8250_usbphy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qmp_v4_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ ++ .has_phy_dp_com_ctrl = true, ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8150_usb3_uniphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8150_usb3_uniphy_serdes_tbl), ++ .tx_tbl = sm8350_usb3_uniphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_tx_tbl), ++ .rx_tbl = sm8350_usb3_uniphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_rx_tbl), ++ .pcs_tbl = sm8350_usb3_uniphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_usb3_uniphy_pcs_tbl), ++ .clk_list = qmp_v4_phy_clk_l, ++ .num_clks = ARRAY_SIZE(qmp_v4_phy_clk_l), ++ .reset_list = msm8996_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(msm8996_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8350_usb3_uniphy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, ++ .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++}; ++ ++static const struct qmp_phy_cfg sm8450_ufsphy_cfg = { ++ .type = PHY_TYPE_UFS, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8350_ufsphy_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8350_ufsphy_serdes_tbl), ++ .tx_tbl = sm8350_ufsphy_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_tx_tbl), ++ .rx_tbl = sm8350_ufsphy_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8350_ufsphy_rx_tbl), ++ .pcs_tbl = sm8350_ufsphy_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8350_ufsphy_pcs_tbl), ++ .clk_list = sm8450_ufs_phy_clk_l, ++ .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8150_ufsphy_regs_layout, ++ ++ .start_ctrl = SERDES_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen3x1_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 1, ++ ++ .serdes_tbl = sm8450_qmp_gen3x1_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen3x1_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen3x1_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen3x1_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen3x1_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen3x1_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS, ++ ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg sm8450_qmp_gen4x2_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 2, ++ ++ .serdes_tbl = sm8450_qmp_gen4x2_pcie_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_serdes_tbl), ++ .tx_tbl = sm8450_qmp_gen4x2_pcie_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_tx_tbl), ++ .rx_tbl = sm8450_qmp_gen4x2_pcie_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_rx_tbl), ++ .pcs_tbl = sm8450_qmp_gen4x2_pcie_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_tbl), ++ .pcs_misc_tbl = sm8450_qmp_gen4x2_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(sm8450_qmp_gen4x2_pcie_pcs_misc_tbl), ++ .clk_list = sdm845_pciephy_clk_l, ++ .num_clks = ARRAY_SIZE(sdm845_pciephy_clk_l), ++ .reset_list = sdm845_pciephy_reset_l, ++ .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = sm8250_pcie_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .phy_status = PHYSTATUS_4_20, ++ ++ .is_dual_lane_phy = true, ++ .has_pwrdn_delay = true, ++ .pwrdn_delay_min = 995, /* us */ ++ .pwrdn_delay_max = 1005, /* us */ ++}; ++ ++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { ++ .type = PHY_TYPE_USB3, ++ .nlanes = 1, ++ ++ .serdes_tbl = qcm2290_usb3_serdes_tbl, ++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl), ++ .tx_tbl = qcm2290_usb3_tx_tbl, ++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl), ++ .rx_tbl = qcm2290_usb3_rx_tbl, ++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl), ++ .pcs_tbl = qcm2290_usb3_pcs_tbl, ++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl), ++ .clk_list = qcm2290_usb3phy_clk_l, ++ .num_clks = ARRAY_SIZE(qcm2290_usb3phy_clk_l), ++ .reset_list = qcm2290_usb3phy_reset_l, ++ .num_resets = ARRAY_SIZE(qcm2290_usb3phy_reset_l), ++ .vreg_list = qmp_phy_vreg_l, ++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), ++ .regs = qcm2290_usb3phy_regs_layout, ++ ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, ++ .phy_status = PHYSTATUS, ++ ++ .is_dual_lane_phy = true, ++}; ++ ++static void qcom_qmp_phy_configure_lane(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num, ++ u8 lane_mask) ++{ ++ int i; ++ const struct qmp_phy_init_tbl *t = tbl; ++ ++ if (!t) ++ return; ++ ++ for (i = 0; i < num; i++, t++) { ++ if (!(t->lane_mask & lane_mask)) ++ continue; ++ ++ if (t->in_layout) ++ writel(t->val, base + regs[t->offset]); ++ else ++ writel(t->val, base + t->offset); ++ } ++} ++ ++static void qcom_qmp_phy_configure(void __iomem *base, ++ const unsigned int *regs, ++ const struct qmp_phy_init_tbl tbl[], ++ int num) ++{ ++ qcom_qmp_phy_configure_lane(base, regs, tbl, num, 0xff); ++} ++ ++static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; ++ int serdes_tbl_num = cfg->serdes_tbl_num; ++ int ret; ++ ++ qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ if (cfg->serdes_tbl_sec) ++ qcom_qmp_phy_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, ++ cfg->serdes_tbl_num_sec); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ switch (dp_opts->link_rate) { ++ case 1620: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_rbr, ++ cfg->serdes_tbl_rbr_num); ++ break; ++ case 2700: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr, ++ cfg->serdes_tbl_hbr_num); ++ break; ++ case 5400: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr2, ++ cfg->serdes_tbl_hbr2_num); ++ break; ++ case 8100: ++ qcom_qmp_phy_configure(serdes, cfg->regs, ++ cfg->serdes_tbl_hbr3, ++ cfg->serdes_tbl_hbr3_num); ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ } ++ ++ ++ if (cfg->has_phy_com_ctrl) { ++ void __iomem *status; ++ unsigned int mask, val; ++ ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ ++ status = serdes + cfg->regs[QPHY_COM_PCS_READY_STATUS]; ++ mask = cfg->mask_com_pcs_ready; ++ ++ ret = readl_poll_timeout(status, val, (val & mask), 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, ++ "phy common block init timed-out\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(QSERDES_V3_COM_BIAS_EN | QSERDES_V3_COM_BIAS_EN_MUX | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_LANE_0_1_PWRDN | ++ DP_PHY_PD_CTL_LANE_2_3_PWRDN | DP_PHY_PD_CTL_PLL_PWRDN | ++ DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(QSERDES_V3_COM_BIAS_EN | ++ QSERDES_V3_COM_BIAS_EN_MUX | QSERDES_V3_COM_CLKBUF_R_EN | ++ QSERDES_V3_COM_CLKBUF_L_EN | QSERDES_V3_COM_EN_SYSCLK_TX_SEL | ++ QSERDES_V3_COM_CLKBUF_RX_DRIVE_L, ++ qphy->serdes + QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0x24, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xbb, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V3_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr3_hbr2[4][4] = { ++ { 0x00, 0x0c, 0x15, 0x1a }, ++ { 0x02, 0x0e, 0x16, 0xff }, ++ { 0x02, 0x11, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr3_hbr2[4][4] = { ++ { 0x02, 0x12, 0x16, 0x1a }, ++ { 0x09, 0x19, 0x1f, 0xff }, ++ { 0x10, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_pre_emphasis_hbr_rbr[4][4] = { ++ { 0x00, 0x0c, 0x14, 0x19 }, ++ { 0x00, 0x0b, 0x12, 0xff }, ++ { 0x00, 0x0b, 0xff, 0xff }, ++ { 0x04, 0xff, 0xff, 0xff } ++}; ++ ++static const u8 qmp_dp_v3_voltage_swing_hbr_rbr[4][4] = { ++ { 0x08, 0x0f, 0x16, 0x1f }, ++ { 0x11, 0x1e, 0x1f, 0xff }, ++ { 0x19, 0x1f, 0xff, 0xff }, ++ { 0x1f, 0xff, 0xff, 0xff } ++}; ++ ++static int qcom_qmp_phy_configure_dp_swing(struct qmp_phy *qphy, ++ unsigned int drv_lvl_reg, unsigned int emp_post_reg) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ unsigned int v_level = 0, p_level = 0; ++ u8 voltage_swing_cfg, pre_emphasis_cfg; ++ int i; ++ ++ for (i = 0; i < dp_opts->lanes; i++) { ++ v_level = max(v_level, dp_opts->voltage[i]); ++ p_level = max(p_level, dp_opts->pre[i]); ++ } ++ ++ if (dp_opts->link_rate <= 2700) { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr_rbr[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr_rbr[v_level][p_level]; ++ } else { ++ voltage_swing_cfg = qmp_dp_v3_voltage_swing_hbr3_hbr2[v_level][p_level]; ++ pre_emphasis_cfg = qmp_dp_v3_pre_emphasis_hbr3_hbr2[v_level][p_level]; ++ } ++ ++ /* TODO: Move check to config check */ ++ if (voltage_swing_cfg == 0xFF && pre_emphasis_cfg == 0xFF) ++ return -EINVAL; ++ ++ /* Enable MUX to use Cursor values from these registers */ ++ voltage_swing_cfg |= DP_PHY_TXn_TX_DRV_LVL_MUX_EN; ++ pre_emphasis_cfg |= DP_PHY_TXn_TX_EMP_POST1_LVL_MUX_EN; ++ ++ writel(voltage_swing_cfg, qphy->tx + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx + emp_post_reg); ++ writel(voltage_swing_cfg, qphy->tx2 + drv_lvl_reg); ++ writel(pre_emphasis_cfg, qphy->tx2 + emp_post_reg); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v3_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 bias_en, drvr_en; ++ ++ if (qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V3_TX_TX_DRV_LVL, ++ QSERDES_V3_TX_TX_EMP_POST1_LVL) < 0) ++ return; ++ ++ if (dp_opts->lanes == 1) { ++ bias_en = 0x3e; ++ drvr_en = 0x13; ++ } else { ++ bias_en = 0x3f; ++ drvr_en = 0x10; ++ } ++ ++ writel(drvr_en, qphy->tx + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr_en, qphy->tx2 + QSERDES_V3_TX_HIGHZ_DRVR_EN); ++ writel(bias_en, qphy->tx2 + QSERDES_V3_TX_TRANSCEIVER_BIAS_EN); ++} ++ ++static bool qcom_qmp_phy_configure_dp_mode(struct qmp_phy *qphy) ++{ ++ u32 val; ++ bool reverse = false; ++ ++ val = DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN; ++ ++ /* ++ * TODO: Assume orientation is CC1 for now and two lanes, need to ++ * use type-c connector to understand orientation and lanes. ++ * ++ * Otherwise val changes to be like below if this code understood ++ * the orientation of the type-c cable. ++ * ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC2) ++ * val |= DP_PHY_PD_CTL_LANE_0_1_PWRDN; ++ * if (lane_cnt == 4 || orientation == ORIENTATION_CC1) ++ * val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ * if (orientation == ORIENTATION_CC2) ++ * writel(0x4c, qphy->pcs + QSERDES_V3_DP_PHY_MODE); ++ */ ++ val |= DP_PHY_PD_CTL_LANE_2_3_PWRDN; ++ writel(val, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ writel(0x5c, qphy->pcs + QSERDES_DP_PHY_MODE); ++ ++ return reverse; ++} ++ ++static int qcom_qmp_v3_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ ++ qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V3_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V3_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x04, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V3_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V3_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ return readl_poll_timeout(qphy->pcs + QSERDES_V3_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000); ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v3_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static void qcom_qmp_v4_phy_dp_aux_init(struct qmp_phy *qphy) ++{ ++ writel(DP_PHY_PD_CTL_PWRDN | DP_PHY_PD_CTL_PSR_PWRDN | DP_PHY_PD_CTL_AUX_PWRDN | ++ DP_PHY_PD_CTL_PLL_PWRDN | DP_PHY_PD_CTL_DP_CLAMP_EN, ++ qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ ++ /* Turn on BIAS current for PHY/PLL */ ++ writel(0x17, qphy->serdes + QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN); ++ ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG0); ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ writel(0x00, qphy->pcs + QSERDES_DP_PHY_AUX_CFG3); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG4); ++ writel(0x26, qphy->pcs + QSERDES_DP_PHY_AUX_CFG5); ++ writel(0x0a, qphy->pcs + QSERDES_DP_PHY_AUX_CFG6); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG7); ++ writel(0xb7, qphy->pcs + QSERDES_DP_PHY_AUX_CFG8); ++ writel(0x03, qphy->pcs + QSERDES_DP_PHY_AUX_CFG9); ++ qphy->dp_aux_cfg = 0; ++ ++ writel(PHY_AUX_STOP_ERR_MASK | PHY_AUX_DEC_ERR_MASK | ++ PHY_AUX_SYNC_ERR_MASK | PHY_AUX_ALIGN_ERR_MASK | ++ PHY_AUX_REQ_ERR_MASK, ++ qphy->pcs + QSERDES_V4_DP_PHY_AUX_INTERRUPT_MASK); ++} ++ ++static void qcom_qmp_v4_phy_configure_dp_tx(struct qmp_phy *qphy) ++{ ++ /* Program default values before writing proper values */ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ qcom_qmp_phy_configure_dp_swing(qphy, ++ QSERDES_V4_TX_TX_DRV_LVL, ++ QSERDES_V4_TX_TX_EMP_POST1_LVL); ++} ++ ++static int qcom_qmp_v4_phy_configure_dp_phy(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_dp_clks *dp_clks = qphy->dp_clks; ++ const struct phy_configure_opts_dp *dp_opts = &qphy->dp_opts; ++ u32 phy_vco_div, status; ++ unsigned long pixel_freq; ++ u32 bias0_en, drvr0_en, bias1_en, drvr1_en; ++ bool reverse; ++ ++ writel(0x0f, qphy->pcs + QSERDES_V4_DP_PHY_CFG_1); ++ ++ reverse = qcom_qmp_phy_configure_dp_mode(qphy); ++ ++ writel(0x13, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ writel(0xa4, qphy->pcs + QSERDES_DP_PHY_AUX_CFG2); ++ ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX0_TX1_LANE_CTL); ++ writel(0x05, qphy->pcs + QSERDES_V4_DP_PHY_TX2_TX3_LANE_CTL); ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ phy_vco_div = 0x1; ++ pixel_freq = 1620000000UL / 2; ++ break; ++ case 2700: ++ phy_vco_div = 0x1; ++ pixel_freq = 2700000000UL / 2; ++ break; ++ case 5400: ++ phy_vco_div = 0x2; ++ pixel_freq = 5400000000UL / 4; ++ break; ++ case 8100: ++ phy_vco_div = 0x0; ++ pixel_freq = 8100000000UL / 6; ++ break; ++ default: ++ /* Other link rates aren't supported */ ++ return -EINVAL; ++ } ++ writel(phy_vco_div, qphy->pcs + QSERDES_V4_DP_PHY_VCO_DIV); ++ ++ clk_set_rate(dp_clks->dp_link_hw.clk, dp_opts->link_rate * 100000); ++ clk_set_rate(dp_clks->dp_pixel_hw.clk, pixel_freq); ++ ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x05, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x01, qphy->pcs + QSERDES_DP_PHY_CFG); ++ writel(0x09, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ writel(0x20, qphy->serdes + QSERDES_V4_COM_RESETSM_CNTRL); ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_C_READY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->serdes + QSERDES_V4_COM_CMN_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(0)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ /* ++ * At least for 7nm DP PHY this has to be done after enabling link ++ * clock. ++ */ ++ ++ if (dp_opts->lanes == 1) { ++ bias0_en = reverse ? 0x3e : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3e; ++ drvr0_en = reverse ? 0x13 : 0x10; ++ drvr1_en = reverse ? 0x10 : 0x13; ++ } else if (dp_opts->lanes == 2) { ++ bias0_en = reverse ? 0x3f : 0x15; ++ bias1_en = reverse ? 0x15 : 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } else { ++ bias0_en = 0x3f; ++ bias1_en = 0x3f; ++ drvr0_en = 0x10; ++ drvr1_en = 0x10; ++ } ++ ++ writel(drvr0_en, qphy->tx + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias0_en, qphy->tx + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ writel(drvr1_en, qphy->tx2 + QSERDES_V4_TX_HIGHZ_DRVR_EN); ++ writel(bias1_en, qphy->tx2 + QSERDES_V4_TX_TRANSCEIVER_BIAS_EN); ++ ++ writel(0x18, qphy->pcs + QSERDES_DP_PHY_CFG); ++ udelay(2000); ++ writel(0x19, qphy->pcs + QSERDES_DP_PHY_CFG); ++ ++ if (readl_poll_timeout(qphy->pcs + QSERDES_V4_DP_PHY_STATUS, ++ status, ++ ((status & BIT(1)) > 0), ++ 500, ++ 10000)) ++ return -ETIMEDOUT; ++ ++ writel(0x0a, qphy->tx + QSERDES_V4_TX_TX_POL_INV); ++ writel(0x0a, qphy->tx2 + QSERDES_V4_TX_TX_POL_INV); ++ ++ writel(0x27, qphy->tx + QSERDES_V4_TX_TX_DRV_LVL); ++ writel(0x27, qphy->tx2 + QSERDES_V4_TX_TX_DRV_LVL); ++ ++ writel(0x20, qphy->tx + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ writel(0x20, qphy->tx2 + QSERDES_V4_TX_TX_EMP_POST1_LVL); ++ ++ return 0; ++} ++ ++/* ++ * We need to calibrate the aux setting here as many times ++ * as the caller tries ++ */ ++static int qcom_qmp_v4_dp_phy_calibrate(struct qmp_phy *qphy) ++{ ++ static const u8 cfg1_settings[] = { 0x20, 0x13, 0x23, 0x1d }; ++ u8 val; ++ ++ qphy->dp_aux_cfg++; ++ qphy->dp_aux_cfg %= ARRAY_SIZE(cfg1_settings); ++ val = cfg1_settings[qphy->dp_aux_cfg]; ++ ++ writel(val, qphy->pcs + QSERDES_DP_PHY_AUX_CFG1); ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_configure(struct phy *phy, union phy_configure_opts *opts) ++{ ++ const struct phy_configure_opts_dp *dp_opts = &opts->dp; ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ memcpy(&qphy->dp_opts, dp_opts, sizeof(*dp_opts)); ++ if (qphy->dp_opts.set_voltages) { ++ cfg->configure_dp_tx(qphy); ++ qphy->dp_opts.set_voltages = 0; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_dp_phy_calibrate(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->calibrate_dp_phy) ++ return cfg->calibrate_dp_phy(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *dp_com = qmp->dp_com; ++ int ret, i; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (qmp->init_count++) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ /* turn on regulator supplies */ ++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); ++ if (ret) { ++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); ++ goto err_unlock; ++ } ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ ret = reset_control_assert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset assert failed\n", ++ cfg->reset_list[i]); ++ goto err_disable_regulators; ++ } ++ } ++ ++ for (i = cfg->num_resets - 1; i >= 0; i--) { ++ ret = reset_control_deassert(qmp->resets[i]); ++ if (ret) { ++ dev_err(qmp->dev, "%s reset deassert failed\n", ++ qphy->cfg->reset_list[i]); ++ goto err_assert_reset; ++ } ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ goto err_assert_reset; ++ ++ if (cfg->has_phy_dp_com_ctrl) { ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_POWER_DOWN_CTRL, ++ SW_PWRDN); ++ /* override hardware control for reset of qmp phy */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ /* Default type-c orientation, i.e CC1 */ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, 0x02); ++ ++ qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL, ++ USB3_MODE | DP_MODE); ++ ++ /* bring both QMP USB and QMP DP PHYs PCS block out of reset */ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL, ++ SW_DPPHY_RESET_MUX | SW_DPPHY_RESET | ++ SW_USB3PHY_RESET_MUX | SW_USB3PHY_RESET); ++ ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SWI_CTRL, 0x03); ++ qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); ++ } ++ ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } else { ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(pcs, ++ cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ else ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++ ++err_assert_reset: ++ while (++i < cfg->num_resets) ++ reset_control_assert(qmp->resets[i]); ++err_disable_regulators: ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++err_unlock: ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++{ ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *serdes = qphy->serdes; ++ int i = cfg->num_resets; ++ ++ mutex_lock(&qmp->phy_mutex); ++ if (--qmp->init_count) { ++ mutex_unlock(&qmp->phy_mutex); ++ return 0; ++ } ++ ++ reset_control_assert(qmp->ufs_reset); ++ if (cfg->has_phy_com_ctrl) { ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL], ++ SERDES_START | PCS_START); ++ qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], ++ SW_RESET); ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); ++ } ++ ++ while (--i >= 0) ++ reset_control_assert(qmp->resets[i]); ++ ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs); ++ ++ mutex_unlock(&qmp->phy_mutex); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_init(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret; ++ dev_vdbg(qmp->dev, "Initializing QMP phy\n"); ++ ++ if (cfg->no_pcs_sw_reset) { ++ /* ++ * Get UFS reset, which is delayed until now to avoid a ++ * circular dependency where UFS needs its PHY, but the PHY ++ * needs this UFS reset. ++ */ ++ if (!qmp->ufs_reset) { ++ qmp->ufs_reset = ++ devm_reset_control_get_exclusive(qmp->dev, ++ "ufsphy"); ++ ++ if (IS_ERR(qmp->ufs_reset)) { ++ ret = PTR_ERR(qmp->ufs_reset); ++ dev_err(qmp->dev, ++ "failed to get UFS reset: %d\n", ++ ret); ++ ++ qmp->ufs_reset = NULL; ++ return ret; ++ } ++ } ++ ++ ret = reset_control_assert(qmp->ufs_reset); ++ if (ret) ++ return ret; ++ } ++ ++ ret = qcom_qmp_phy_com_init(qphy); ++ if (ret) ++ return ret; ++ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->dp_aux_init(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_power_on(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ struct qcom_qmp *qmp = qphy->qmp; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *tx = qphy->tx; ++ void __iomem *rx = qphy->rx; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ void __iomem *status; ++ unsigned int mask, val, ready; ++ int ret; ++ ++ qcom_qmp_phy_serdes_init(qphy); ++ ++ if (cfg->has_lane_rst) { ++ ret = reset_control_deassert(qphy->lane_rst); ++ if (ret) { ++ dev_err(qmp->dev, "lane%d reset deassert failed\n", ++ qphy->index); ++ return ret; ++ } ++ } ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret); ++ goto err_reset_lane; ++ } ++ ++ /* Tx, Rx, and PCS configurations */ ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 1); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(tx, cfg->regs, cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 1); ++ ++ /* Configuration for other LANE for USB-DP combo PHY */ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl, cfg->tx_tbl_num, 2); ++ if (cfg->tx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->tx2, cfg->regs, ++ cfg->tx_tbl_sec, ++ cfg->tx_tbl_num_sec, 2); ++ } ++ ++ /* Configure special DP tx tunings */ ++ if (cfg->type == PHY_TYPE_DP) ++ cfg->configure_dp_tx(qphy); ++ ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 1); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); ++ ++ if (cfg->is_dual_lane_phy) { ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl, cfg->rx_tbl_num, 2); ++ if (cfg->rx_tbl_sec) ++ qcom_qmp_phy_configure_lane(qphy->rx2, cfg->regs, ++ cfg->rx_tbl_sec, ++ cfg->rx_tbl_num_sec, 2); ++ } ++ ++ /* Configure link rate, swing, etc. */ ++ if (cfg->type == PHY_TYPE_DP) { ++ cfg->configure_dp_phy(qphy); ++ } else { ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); ++ } ++ ++ ret = reset_control_deassert(qmp->ufs_reset); ++ if (ret) ++ goto err_disable_pipe_clk; ++ ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ cfg->pcs_misc_tbl_num); ++ if (cfg->pcs_misc_tbl_sec) ++ qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, ++ cfg->pcs_misc_tbl_num_sec); ++ ++ /* ++ * Pull out PHY from POWER DOWN state. ++ * This is active low enable signal to power-down PHY. ++ */ ++ if(cfg->type == PHY_TYPE_PCIE) ++ qphy_setbits(pcs, QPHY_POWER_DOWN_CONTROL, cfg->pwrdn_ctrl); ++ ++ if (cfg->has_pwrdn_delay) ++ usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); ++ ++ if (cfg->type != PHY_TYPE_DP) { ++ /* Pull PHY out of reset state */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ /* start SerDes and Phy-Coding-Sublayer */ ++ qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ if (cfg->type == PHY_TYPE_UFS) { ++ status = pcs + cfg->regs[QPHY_PCS_READY_STATUS]; ++ mask = PCS_READY; ++ ready = PCS_READY; ++ } else { ++ status = pcs + cfg->regs[QPHY_PCS_STATUS]; ++ mask = cfg->phy_status; ++ ready = 0; ++ } ++ ++ ret = readl_poll_timeout(status, val, (val & mask) == ready, 10, ++ PHY_INIT_COMPLETE_TIMEOUT); ++ if (ret) { ++ dev_err(qmp->dev, "phy initialization timed-out\n"); ++ goto err_disable_pipe_clk; ++ } ++ } ++ return 0; ++ ++err_disable_pipe_clk: ++ clk_disable_unprepare(qphy->pipe_clk); ++err_reset_lane: ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_power_off(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ ++ if (cfg->type == PHY_TYPE_DP) { ++ /* Assert DP PHY power down */ ++ writel(DP_PHY_PD_CTL_PSR_PWRDN, qphy->pcs + QSERDES_DP_PHY_PD_CTL); ++ } else { ++ /* PHY reset */ ++ if (!cfg->no_pcs_sw_reset) ++ qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); ++ ++ /* stop SerDes and Phy-Coding-Sublayer */ ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_START_CTRL], cfg->start_ctrl); ++ ++ /* Put PHY into POWER DOWN state: active low */ ++ if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) { ++ qphy_clrbits(qphy->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ cfg->pwrdn_ctrl); ++ } else { ++ qphy_clrbits(qphy->pcs, QPHY_POWER_DOWN_CONTROL, ++ cfg->pwrdn_ctrl); ++ } ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_exit(struct phy *phy) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ if (cfg->has_lane_rst) ++ reset_control_assert(qphy->lane_rst); ++ ++ qcom_qmp_phy_com_exit(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_enable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_init(phy); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_power_on(phy); ++ if (ret) ++ qcom_qmp_phy_exit(phy); ++ ++ return ret; ++} ++ ++static int qcom_qmp_phy_disable(struct phy *phy) ++{ ++ int ret; ++ ++ ret = qcom_qmp_phy_power_off(phy); ++ if (ret) ++ return ret; ++ return qcom_qmp_phy_exit(phy); ++} ++ ++static int qcom_qmp_phy_set_mode(struct phy *phy, ++ enum phy_mode mode, int submode) ++{ ++ struct qmp_phy *qphy = phy_get_drvdata(phy); ++ ++ qphy->mode = mode; ++ ++ return 0; ++} ++ ++static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ u32 intr_mask; ++ ++ if (qphy->mode == PHY_MODE_USB_HOST_SS || ++ qphy->mode == PHY_MODE_USB_DEVICE_SS) ++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN; ++ else ++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL; ++ ++ /* Clear any pending interrupts status */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL); ++ ++ /* Enable required PHY autonomous mode interrupts */ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask); ++ ++ /* Enable i/o clamp_n for autonomous mode */ ++ if (pcs_misc) ++ qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++} ++ ++static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++{ ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ void __iomem *pcs = qphy->pcs; ++ void __iomem *pcs_misc = qphy->pcs_misc; ++ ++ /* Disable i/o clamp_n on resume for normal mode */ ++ if (pcs_misc) ++ qphy_setbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); ++ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], ++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN); ++ ++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++ /* Writing 1 followed by 0 clears the interrupt */ ++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR); ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ ++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ qcom_qmp_phy_enable_autonomous_mode(qphy); ++ ++ clk_disable_unprepare(qphy->pipe_clk); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ ++ return 0; ++} ++ ++static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct qmp_phy *qphy = qmp->phys[0]; ++ const struct qmp_phy_cfg *cfg = qphy->cfg; ++ int ret = 0; ++ ++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qphy->mode); ++ ++ /* Supported only for USB3 PHY and luckily USB3 is the first phy */ ++ if (cfg->type != PHY_TYPE_USB3) ++ return 0; ++ ++ if (!qmp->init_count) { ++ dev_vdbg(dev, "PHY not initialized, bailing out\n"); ++ return 0; ++ } ++ ++ ret = clk_bulk_prepare_enable(cfg->num_clks, qmp->clks); ++ if (ret) ++ return ret; ++ ++ ret = clk_prepare_enable(qphy->pipe_clk); ++ if (ret) { ++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret); ++ clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); ++ return ret; ++ } ++ ++ qcom_qmp_phy_disable_autonomous_mode(qphy); ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_vregs; ++ int i; ++ ++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL); ++ if (!qmp->vregs) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->vregs[i].supply = cfg->vreg_list[i]; ++ ++ return devm_regulator_bulk_get(dev, num, qmp->vregs); ++} ++ ++static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int i; ++ ++ qmp->resets = devm_kcalloc(dev, cfg->num_resets, ++ sizeof(*qmp->resets), GFP_KERNEL); ++ if (!qmp->resets) ++ return -ENOMEM; ++ ++ for (i = 0; i < cfg->num_resets; i++) { ++ struct reset_control *rst; ++ const char *name = cfg->reset_list[i]; ++ ++ rst = devm_reset_control_get_exclusive(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ return PTR_ERR(rst); ++ } ++ qmp->resets[i] = rst; ++ } ++ ++ return 0; ++} ++ ++static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ int num = cfg->num_clks; ++ int i; ++ ++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); ++ if (!qmp->clks) ++ return -ENOMEM; ++ ++ for (i = 0; i < num; i++) ++ qmp->clks[i].id = cfg->clk_list[i]; ++ ++ return devm_clk_bulk_get(dev, num, qmp->clks); ++} ++ ++static void phy_clk_release_provider(void *res) ++{ ++ of_clk_del_provider(res); ++} ++ ++/* ++ * Register a fixed rate pipe clock. ++ * ++ * The _pipe_clksrc generated by PHY goes to the GCC that gate ++ * controls it. The _pipe_clk coming out of the GCC is requested ++ * by the PHY driver for its operations. ++ * We register the _pipe_clksrc here. The gcc driver takes care ++ * of assigning this _pipe_clksrc as parent to _pipe_clk. ++ * Below picture shows this relationship. ++ * ++ * +---------------+ ++ * | PHY block |<<---------------------------------------+ ++ * | | | ++ * | +-------+ | +-----+ | ++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+ ++ * clk | +-------+ | +-----+ ++ * +---------------+ ++ */ ++static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) ++{ ++ struct clk_fixed_rate *fixed; ++ struct clk_init_data init = { }; ++ int ret; ++ ++ ret = of_property_read_string(np, "clock-output-names", &init.name); ++ if (ret) { ++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np); ++ return ret; ++ } ++ ++ fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL); ++ if (!fixed) ++ return -ENOMEM; ++ ++ init.ops = &clk_fixed_rate_ops; ++ ++ /* controllers using QMP phys use 125MHz pipe clock interface */ ++ fixed->fixed_rate = 125000000; ++ fixed->hw.init = &init; ++ ++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++/* ++ * Display Port PLL driver block diagram for branch clocks ++ * ++ * +------------------------------+ ++ * | DP_VCO_CLK | ++ * | | ++ * | +-------------------+ | ++ * | | (DP PLL/VCO) | | ++ * | +---------+---------+ | ++ * | v | ++ * | +----------+-----------+ | ++ * | | hsclk_divsel_clk_src | | ++ * | +----------+-----------+ | ++ * +------------------------------+ ++ * | ++ * +---------<---------v------------>----------+ ++ * | | ++ * +--------v----------------+ | ++ * | dp_phy_pll_link_clk | | ++ * | link_clk | | ++ * +--------+----------------+ | ++ * | | ++ * | | ++ * v v ++ * Input to DISPCC block | ++ * for link clk, crypto clk | ++ * and interface clock | ++ * | ++ * | ++ * +--------<------------+-----------------+---<---+ ++ * | | | ++ * +----v---------+ +--------v-----+ +--------v------+ ++ * | vco_divided | | vco_divided | | vco_divided | ++ * | _clk_src | | _clk_src | | _clk_src | ++ * | | | | | | ++ * |divsel_six | | divsel_two | | divsel_four | ++ * +-------+------+ +-----+--------+ +--------+------+ ++ * | | | ++ * v---->----------v-------------<------v ++ * | ++ * +----------+-----------------+ ++ * | dp_phy_pll_vco_div_clk | ++ * +---------+------------------+ ++ * | ++ * v ++ * Input to DISPCC block ++ * for DP pixel clock ++ * ++ */ ++static int qcom_qmp_dp_pixel_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 1620000000UL / 2: ++ case 2700000000UL / 2: ++ /* 5.4 and 8.1 GHz are same link rate as 2.7GHz, i.e. div 4 and div 6 */ ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_pixel_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_pixel_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ return 1620000000UL / 2; ++ case 2700: ++ return 2700000000UL / 2; ++ case 5400: ++ return 5400000000UL / 4; ++ case 8100: ++ return 8100000000UL / 6; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_pixel_clk_ops = { ++ .determine_rate = qcom_qmp_dp_pixel_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_pixel_clk_recalc_rate, ++}; ++ ++static int qcom_qmp_dp_link_clk_determine_rate(struct clk_hw *hw, ++ struct clk_rate_request *req) ++{ ++ switch (req->rate) { ++ case 162000000: ++ case 270000000: ++ case 540000000: ++ case 810000000: ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static unsigned long ++qcom_qmp_dp_link_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) ++{ ++ const struct qmp_phy_dp_clks *dp_clks; ++ const struct qmp_phy *qphy; ++ const struct phy_configure_opts_dp *dp_opts; ++ ++ dp_clks = container_of(hw, struct qmp_phy_dp_clks, dp_link_hw); ++ qphy = dp_clks->qphy; ++ dp_opts = &qphy->dp_opts; ++ ++ switch (dp_opts->link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ return dp_opts->link_rate * 100000; ++ default: ++ return 0; ++ } ++} ++ ++static const struct clk_ops qcom_qmp_dp_link_clk_ops = { ++ .determine_rate = qcom_qmp_dp_link_clk_determine_rate, ++ .recalc_rate = qcom_qmp_dp_link_clk_recalc_rate, ++}; ++ ++static struct clk_hw * ++qcom_qmp_dp_clks_hw_get(struct of_phandle_args *clkspec, void *data) ++{ ++ struct qmp_phy_dp_clks *dp_clks = data; ++ unsigned int idx = clkspec->args[0]; ++ ++ if (idx >= 2) { ++ pr_err("%s: invalid index %u\n", __func__, idx); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (idx == 0) ++ return &dp_clks->dp_link_hw; ++ ++ return &dp_clks->dp_pixel_hw; ++} ++ ++static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, ++ struct device_node *np) ++{ ++ struct clk_init_data init = { }; ++ struct qmp_phy_dp_clks *dp_clks; ++ char name[64]; ++ int ret; ++ ++ dp_clks = devm_kzalloc(qmp->dev, sizeof(*dp_clks), GFP_KERNEL); ++ if (!dp_clks) ++ return -ENOMEM; ++ ++ dp_clks->qphy = qphy; ++ qphy->dp_clks = dp_clks; ++ ++ snprintf(name, sizeof(name), "%s::link_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_link_clk_ops; ++ init.name = name; ++ dp_clks->dp_link_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_link_hw); ++ if (ret) ++ return ret; ++ ++ snprintf(name, sizeof(name), "%s::vco_div_clk", dev_name(qmp->dev)); ++ init.ops = &qcom_qmp_dp_pixel_clk_ops; ++ init.name = name; ++ dp_clks->dp_pixel_hw.init = &init; ++ ret = devm_clk_hw_register(qmp->dev, &dp_clks->dp_pixel_hw); ++ if (ret) ++ return ret; ++ ++ ret = of_clk_add_hw_provider(np, qcom_qmp_dp_clks_hw_get, dp_clks); ++ if (ret) ++ return ret; ++ ++ /* ++ * Roll a devm action because the clock provider is the child node, but ++ * the child node is not actually a device. ++ */ ++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np); ++} ++ ++static const struct phy_ops qcom_qmp_phy_gen_ops = { ++ .init = qcom_qmp_phy_enable, ++ .exit = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_phy_dp_ops = { ++ .init = qcom_qmp_phy_init, ++ .configure = qcom_qmp_dp_phy_configure, ++ .power_on = qcom_qmp_phy_power_on, ++ .calibrate = qcom_qmp_dp_phy_calibrate, ++ .power_off = qcom_qmp_phy_power_off, ++ .exit = qcom_qmp_phy_exit, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static const struct phy_ops qcom_qmp_pcie_ufs_ops = { ++ .power_on = qcom_qmp_phy_enable, ++ .power_off = qcom_qmp_phy_disable, ++ .set_mode = qcom_qmp_phy_set_mode, ++ .owner = THIS_MODULE, ++}; ++ ++static void qcom_qmp_reset_control_put(void *data) ++{ ++ reset_control_put(data); ++} ++ ++static ++int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++ void __iomem *serdes, const struct qmp_phy_cfg *cfg) ++{ ++ struct qcom_qmp *qmp = dev_get_drvdata(dev); ++ struct phy *generic_phy; ++ struct qmp_phy *qphy; ++ const struct phy_ops *ops; ++ char prop_name[MAX_PROP_NAME]; ++ int ret; ++ ++ qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); ++ if (!qphy) ++ return -ENOMEM; ++ ++ qphy->cfg = cfg; ++ qphy->serdes = serdes; ++ /* ++ * Get memory resources for each phy lane: ++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. ++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 ++ * For single lane PHYs: pcs_misc (optional) -> 3. ++ */ ++ qphy->tx = of_iomap(np, 0); ++ if (!qphy->tx) ++ return -ENOMEM; ++ ++ qphy->rx = of_iomap(np, 1); ++ if (!qphy->rx) ++ return -ENOMEM; ++ ++ qphy->pcs = of_iomap(np, 2); ++ if (!qphy->pcs) ++ return -ENOMEM; ++ ++ /* ++ * If this is a dual-lane PHY, then there should be registers for the ++ * second lane. Some old device trees did not specify this, so fall ++ * back to old legacy behavior of assuming they can be reached at an ++ * offset from the first lane. ++ */ ++ if (cfg->is_dual_lane_phy) { ++ qphy->tx2 = of_iomap(np, 3); ++ qphy->rx2 = of_iomap(np, 4); ++ if (!qphy->tx2 || !qphy->rx2) { ++ dev_warn(dev, ++ "Underspecified device tree, falling back to legacy register regions\n"); ++ ++ /* In the old version, pcs_misc is at index 3. */ ++ qphy->pcs_misc = qphy->tx2; ++ qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; ++ qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 5); ++ } ++ ++ } else { ++ qphy->pcs_misc = of_iomap(np, 3); ++ } ++ ++ if (!qphy->pcs_misc) ++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ ++ /* ++ * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 ++ * based phys, so they essentially have pipe clock. So, ++ * we return error in case phy is USB3 or PIPE type. ++ * Otherwise, we initialize pipe clock to NULL for ++ * all phys that don't need this. ++ */ ++ snprintf(prop_name, sizeof(prop_name), "pipe%d", id); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ if (IS_ERR(qphy->pipe_clk)) { ++ if (cfg->type == PHY_TYPE_PCIE || ++ cfg->type == PHY_TYPE_USB3) { ++ ret = PTR_ERR(qphy->pipe_clk); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, ++ "failed to get lane%d pipe_clk, %d\n", ++ id, ret); ++ return ret; ++ } ++ qphy->pipe_clk = NULL; ++ } ++ ++ /* Get lane reset, if any */ ++ if (cfg->has_lane_rst) { ++ snprintf(prop_name, sizeof(prop_name), "lane%d", id); ++ qphy->lane_rst = of_reset_control_get_exclusive(np, prop_name); ++ if (IS_ERR(qphy->lane_rst)) { ++ dev_err(dev, "failed to get lane%d reset\n", id); ++ return PTR_ERR(qphy->lane_rst); ++ } ++ ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put, ++ qphy->lane_rst); ++ if (ret) ++ return ret; ++ } ++ ++ if (cfg->type == PHY_TYPE_UFS || cfg->type == PHY_TYPE_PCIE) ++ ops = &qcom_qmp_pcie_ufs_ops; ++ else if (cfg->type == PHY_TYPE_DP) ++ ops = &qcom_qmp_phy_dp_ops; ++ else ++ ops = &qcom_qmp_phy_gen_ops; ++ ++ generic_phy = devm_phy_create(dev, np, ops); ++ if (IS_ERR(generic_phy)) { ++ ret = PTR_ERR(generic_phy); ++ dev_err(dev, "failed to create qphy %d\n", ret); ++ return ret; ++ } ++ ++ qphy->phy = generic_phy; ++ qphy->index = id; ++ qphy->qmp = qmp; ++ qmp->phys[id] = qphy; ++ phy_set_drvdata(generic_phy, qphy); ++ ++ return 0; ++} ++ ++static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,ipq8074-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-pcie-phy", ++ .data = &msm8996_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-ufs-phy", ++ .data = &msm8996_ufs_cfg, ++ }, { ++ .compatible = "qcom,msm8996-qmp-usb3-phy", ++ .data = &msm8996_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-pcie-phy", ++ .data = &msm8998_pciephy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,ipq8074-qmp-pcie-phy", ++ .data = &ipq8074_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-pcie-phy", ++ .data = &ipq6018_pciephy_cfg, ++ }, { ++ .compatible = "qcom,ipq6018-qmp-usb3-phy", ++ .data = &ipq8074_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-phy", ++ .data = &sc7180_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sc8180x-qmp-pcie-phy", ++ .data = &sc8180x_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8280xp-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sdm845-qhp-pcie-phy", ++ .data = &sdm845_qhp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-pcie-phy", ++ .data = &sdm845_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-phy", ++ .data = &qmp_v3_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-usb3-uni-phy", ++ .data = &qmp_v3_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdm845-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,msm8998-qmp-usb3-phy", ++ .data = &msm8998_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm6115-qmp-ufs-phy", ++ .data = &sm6115_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm6350-qmp-ufs-phy", ++ .data = &sdm845_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-ufs-phy", ++ .data = &sm8150_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-phy", ++ .data = &sm8150_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8150-qmp-usb3-uni-phy", ++ .data = &sm8150_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-phy", ++ .data = &sm8250_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ /* It's a combo phy */ ++ }, { ++ .compatible = "qcom,sm8250-qmp-usb3-uni-phy", ++ .data = &sm8250_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x1-pcie-phy", ++ .data = &sm8250_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-gen3x2-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-ufs-phy", ++ .data = &sm8350_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8250-qmp-modem-pcie-phy", ++ .data = &sm8250_qmp_gen3x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-pcie-phy", ++ .data = &sdx55_qmp_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sdx55-qmp-usb3-uni-phy", ++ .data = &sdx55_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sdx65-qmp-usb3-uni-phy", ++ .data = &sdx65_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,sm8350-qmp-usb3-uni-phy", ++ .data = &sm8350_usb3_uniphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen3x1-pcie-phy", ++ .data = &sm8450_qmp_gen3x1_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-gen4x2-pcie-phy", ++ .data = &sm8450_qmp_gen4x2_pciephy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-ufs-phy", ++ .data = &sm8450_ufsphy_cfg, ++ }, { ++ .compatible = "qcom,sm8450-qmp-usb3-phy", ++ .data = &sm8350_usb3phy_cfg, ++ }, { ++ .compatible = "qcom,qcm2290-qmp-usb3-phy", ++ .data = &qcm2290_usb3phy_cfg, ++ }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++ ++static const struct of_device_id qcom_qmp_combo_phy_of_match_table[] = { ++ { ++ .compatible = "qcom,sc7180-qmp-usb3-dp-phy", ++ .data = &sc7180_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sm8250-qmp-usb3-dp-phy", ++ .data = &sm8250_usb3dpphy_cfg, ++ }, ++ { ++ .compatible = "qcom,sc8180x-qmp-usb3-dp-phy", ++ .data = &sc8180x_usb3dpphy_cfg, ++ }, ++ { } ++}; ++ ++static const struct dev_pm_ops qcom_qmp_phy_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_runtime_suspend, ++ qcom_qmp_phy_runtime_resume, NULL) ++}; ++ ++static int qcom_qmp_phy_probe(struct platform_device *pdev) ++{ ++ struct qcom_qmp *qmp; ++ struct device *dev = &pdev->dev; ++ struct device_node *child; ++ struct phy_provider *phy_provider; ++ void __iomem *serdes; ++ void __iomem *usb_serdes; ++ void __iomem *dp_serdes = NULL; ++ const struct qmp_phy_combo_cfg *combo_cfg = NULL; ++ const struct qmp_phy_cfg *cfg = NULL; ++ const struct qmp_phy_cfg *usb_cfg = NULL; ++ const struct qmp_phy_cfg *dp_cfg = NULL; ++ int num, id, expected_phys; ++ int ret; ++ ++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL); ++ if (!qmp) ++ return -ENOMEM; ++ ++ qmp->dev = dev; ++ dev_set_drvdata(dev, qmp); ++ ++ /* Get the specific init parameters of QMP phy */ ++ cfg = of_device_get_match_data(dev); ++ if (!cfg) { ++ const struct of_device_id *match; ++ ++ match = of_match_device(qcom_qmp_combo_phy_of_match_table, dev); ++ if (!match) ++ return -EINVAL; ++ ++ combo_cfg = match->data; ++ if (!combo_cfg) ++ return -EINVAL; ++ ++ usb_cfg = combo_cfg->usb_cfg; ++ cfg = usb_cfg; /* Setup clks and regulators */ ++ } ++ ++ /* per PHY serdes; usually located at base address */ ++ usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(serdes)) ++ return PTR_ERR(serdes); ++ ++ /* per PHY dp_com; if PHY has dp_com control block */ ++ if (combo_cfg || cfg->has_phy_dp_com_ctrl) { ++ qmp->dp_com = devm_platform_ioremap_resource(pdev, 1); ++ if (IS_ERR(qmp->dp_com)) ++ return PTR_ERR(qmp->dp_com); ++ } ++ ++ if (combo_cfg) { ++ /* Only two serdes for combo PHY */ ++ dp_serdes = devm_platform_ioremap_resource(pdev, 2); ++ if (IS_ERR(dp_serdes)) ++ return PTR_ERR(dp_serdes); ++ ++ dp_cfg = combo_cfg->dp_cfg; ++ expected_phys = 2; ++ } else { ++ expected_phys = cfg->nlanes; ++ } ++ ++ mutex_init(&qmp->phy_mutex); ++ ++ ret = qcom_qmp_phy_clk_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_reset_init(dev, cfg); ++ if (ret) ++ return ret; ++ ++ ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ if (ret) { ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "failed to get regulator supplies: %d\n", ++ ret); ++ return ret; ++ } ++ ++ num = of_get_available_child_count(dev->of_node); ++ /* do we have a rogue child node ? */ ++ if (num > expected_phys) ++ return -EINVAL; ++ ++ qmp->phys = devm_kcalloc(dev, num, sizeof(*qmp->phys), GFP_KERNEL); ++ if (!qmp->phys) ++ return -ENOMEM; ++ ++ pm_runtime_set_active(dev); ++ pm_runtime_enable(dev); ++ /* ++ * Prevent runtime pm from being ON by default. Users can enable ++ * it using power/control in sysfs. ++ */ ++ pm_runtime_forbid(dev); ++ ++ id = 0; ++ for_each_available_child_of_node(dev->of_node, child) { ++ if (of_node_name_eq(child, "dp-phy")) { ++ cfg = dp_cfg; ++ serdes = dp_serdes; ++ } else if (of_node_name_eq(child, "usb3-phy")) { ++ cfg = usb_cfg; ++ serdes = usb_serdes; ++ } ++ ++ /* Create per-lane phy */ ++ ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ if (ret) { ++ dev_err(dev, "failed to create lane%d phy, %d\n", ++ id, ret); ++ goto err_node_put; ++ } ++ ++ /* ++ * Register the pipe clock provided by phy. ++ * See function description to see details of this pipe clock. ++ */ ++ if (cfg->type == PHY_TYPE_USB3 || cfg->type == PHY_TYPE_PCIE) { ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; ++ } ++ } else if (cfg->type == PHY_TYPE_DP) { ++ ret = phy_dp_clks_register(qmp, qmp->phys[id], child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register DP clock source\n"); ++ goto err_node_put; ++ } ++ } ++ id++; ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (!IS_ERR(phy_provider)) ++ dev_info(dev, "Registered Qcom-QMP phy\n"); ++ else ++ pm_runtime_disable(dev); ++ ++ return PTR_ERR_OR_ZERO(phy_provider); ++ ++err_node_put: ++ pm_runtime_disable(dev); ++ of_node_put(child); ++ return ret; ++} ++ ++static struct platform_driver qcom_qmp_phy_driver = { ++ .probe = qcom_qmp_phy_probe, ++ .driver = { ++ .name = "qcom-qmp-phy", ++ .pm = &qcom_qmp_phy_pm_ops, ++ .of_match_table = qcom_qmp_phy_of_match_table, ++ }, ++}; ++ ++module_platform_driver(qcom_qmp_phy_driver); ++ ++MODULE_AUTHOR("Vivek Gautam "); ++MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_LICENSE("GPL v2"); +-- +2.35.1 + diff --git a/queue-5.15/phy-usb-s2-wol-wakeup_count-not-incremented-for-usb-.patch b/queue-5.15/phy-usb-s2-wol-wakeup_count-not-incremented-for-usb-.patch new file mode 100644 index 00000000000..2982edc581a --- /dev/null +++ b/queue-5.15/phy-usb-s2-wol-wakeup_count-not-incremented-for-usb-.patch @@ -0,0 +1,54 @@ +From 567e418e8a447a143efc86a8b7a151d0df46d7bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Oct 2022 14:30:14 -0700 +Subject: phy: usb: s2 WoL wakeup_count not incremented for USB->Eth devices + +From: Al Cooper + +[ Upstream commit f7fc5b7090372fc4dd7798c874635ca41b8ba733 ] + +The PHY's "wakeup_count" is not incrementing when waking from +WoL. The wakeup count can be found in sysfs at: +/sys/bus/platform/devices/rdb/*.usb-phy/power/wakeup_count. +The problem is that the system wakup event handler was being passed +the wrong "device" by the PHY driver. + +Fixes: f1c0db40a3ad ("phy: usb: Add "wake on" functionality") +Signed-off-by: Al Cooper +Signed-off-by: Justin Chen +Acked-by: Florian Fainelli +Link: https://lore.kernel.org/r/1665005418-15807-3-git-send-email-justinpopo6@gmail.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/broadcom/phy-brcm-usb.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/broadcom/phy-brcm-usb.c b/drivers/phy/broadcom/phy-brcm-usb.c +index 2cb3779fcdf8..c0c3ab9b2a15 100644 +--- a/drivers/phy/broadcom/phy-brcm-usb.c ++++ b/drivers/phy/broadcom/phy-brcm-usb.c +@@ -102,9 +102,9 @@ static int brcm_pm_notifier(struct notifier_block *notifier, + + static irqreturn_t brcm_usb_phy_wake_isr(int irq, void *dev_id) + { +- struct phy *gphy = dev_id; ++ struct device *dev = dev_id; + +- pm_wakeup_event(&gphy->dev, 0); ++ pm_wakeup_event(dev, 0); + + return IRQ_HANDLED; + } +@@ -451,7 +451,7 @@ static int brcm_usb_phy_dvr_init(struct platform_device *pdev, + if (priv->wake_irq >= 0) { + err = devm_request_irq(dev, priv->wake_irq, + brcm_usb_phy_wake_isr, 0, +- dev_name(dev), gphy); ++ dev_name(dev), dev); + if (err < 0) + return err; + device_set_wakeup_capable(dev, 1); +-- +2.35.1 + diff --git a/queue-5.15/pinctrl-k210-call-of_node_put.patch b/queue-5.15/pinctrl-k210-call-of_node_put.patch new file mode 100644 index 00000000000..3317bd20f3f --- /dev/null +++ b/queue-5.15/pinctrl-k210-call-of_node_put.patch @@ -0,0 +1,42 @@ +From 9e77f0f721a3aba07d9add82045fb99c25eca886 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 07:58:53 +0000 +Subject: pinctrl: k210: call of_node_put() + +From: ZhangPeng + +[ Upstream commit a8acc11643082a706de86a19f1f824712d971984 ] + +Since for_each_available_child_of_node() will increase the refcount of +node, we need to call of_node_put() manually when breaking out of the +iteration. + +Fixes: d4c34d09ab03 ("pinctrl: Add RISC-V Canaan Kendryte K210 FPIOA driver") +Signed-off-by: ZhangPeng +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20221122075853.2496680-1-zhangpeng362@huawei.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/pinctrl-k210.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c +index ecab6bf63dc6..ad4db99094a7 100644 +--- a/drivers/pinctrl/pinctrl-k210.c ++++ b/drivers/pinctrl/pinctrl-k210.c +@@ -862,8 +862,10 @@ static int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + for_each_available_child_of_node(np_config, np) { + ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(np); + goto err; ++ } + } + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/pinctrl-pinconf-generic-add-missing-of_node_put.patch b/queue-5.15/pinctrl-pinconf-generic-add-missing-of_node_put.patch new file mode 100644 index 00000000000..6805746767d --- /dev/null +++ b/queue-5.15/pinctrl-pinconf-generic-add-missing-of_node_put.patch @@ -0,0 +1,40 @@ +From 1655d916b2c502cce6443425bc0c130382bdd0e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 07:01:56 +0000 +Subject: pinctrl: pinconf-generic: add missing of_node_put() + +From: ZhangPeng + +[ Upstream commit 5ead93289815a075d43c415e35c8beafafb801c9 ] + +of_node_put() needs to be called when jumping out of the loop, since +for_each_available_child_of_node() will increase the refcount of node. + +Fixes: c7289500e29d ("pinctrl: pinconf-generic: scan also referenced phandle node") +Signed-off-by: ZhangPeng +Link: https://lore.kernel.org/r/20221125070156.3535855-1-zhangpeng362@huawei.com +Signed-off-by: Linus Walleij +Signed-off-by: Sasha Levin +--- + drivers/pinctrl/pinconf-generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c +index b1db28007986..e6fe1330eab9 100644 +--- a/drivers/pinctrl/pinconf-generic.c ++++ b/drivers/pinctrl/pinconf-generic.c +@@ -393,8 +393,10 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, + for_each_available_child_of_node(np_config, np) { + ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map, + &reserved_maps, num_maps, type); +- if (ret < 0) ++ if (ret < 0) { ++ of_node_put(np); + goto exit; ++ } + } + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/platform-chrome-cros_ec_typec-cleanup-switch-handle-.patch b/queue-5.15/platform-chrome-cros_ec_typec-cleanup-switch-handle-.patch new file mode 100644 index 00000000000..5a71838b6d4 --- /dev/null +++ b/queue-5.15/platform-chrome-cros_ec_typec-cleanup-switch-handle-.patch @@ -0,0 +1,44 @@ +From bec97cd7c6d60e4aaf22ef76ca76440980b163fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 21:48:34 +0000 +Subject: platform/chrome: cros_ec_typec: Cleanup switch handle return paths + +From: Prashant Malani + +[ Upstream commit 66fe238a9bcc158f75ddecf976d1ce7efe20f713 ] + +Some of the return paths for the cros_typec_get_switch_handles() +aren't necessary. Clean up the return paths to only undo the handle +get's which succeeded. + +Signed-off-by: Prashant Malani +Link: https://lore.kernel.org/r/20220711072333.2064341-9-pmalani@chromium.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 9a8aadcf0b45 ("platform/chrome: cros_ec_typec: zero out stale pointers") +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_ec_typec.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c +index aadb8d237aef..d63be2b3d10e 100644 +--- a/drivers/platform/chrome/cros_ec_typec.c ++++ b/drivers/platform/chrome/cros_ec_typec.c +@@ -156,12 +156,10 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port, + return 0; + + role_sw_err: +- usb_role_switch_put(port->role_sw); +-ori_sw_err: + typec_switch_put(port->ori_sw); +-mux_err: ++ori_sw_err: + typec_mux_put(port->mux); +- ++mux_err: + return -ENODEV; + } + +-- +2.35.1 + diff --git a/queue-5.15/platform-chrome-cros_ec_typec-zero-out-stale-pointer.patch b/queue-5.15/platform-chrome-cros_ec_typec-zero-out-stale-pointer.patch new file mode 100644 index 00000000000..3b378dbb89e --- /dev/null +++ b/queue-5.15/platform-chrome-cros_ec_typec-zero-out-stale-pointer.patch @@ -0,0 +1,45 @@ +From 3207d8f5bf04eddd4ca238f556869490972dfdbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 09:39:40 +0000 +Subject: platform/chrome: cros_ec_typec: zero out stale pointers + +From: Victor Ding + +[ Upstream commit 9a8aadcf0b459c1257b9477fd6402e1d5952ae07 ] + +`cros_typec_get_switch_handles` allocates four pointers when obtaining +type-c switch handles. These pointers are all freed if failing to obtain +any of them; therefore, pointers in `port` become stale. The stale +pointers eventually cause use-after-free or double free in later code +paths. Zeroing out all pointer fields after freeing to eliminate these +stale pointers. + +Fixes: f28adb41dab4 ("platform/chrome: cros_ec_typec: Register Type C switches") +Fixes: 1a8912caba02 ("platform/chrome: cros_ec_typec: Get retimer handle") +Signed-off-by: Victor Ding +Acked-by: Prashant Malani +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20221207093924.v2.1.I1864b6a7ee98824118b93677868d22d3750f439b@changeid +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_ec_typec.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c +index d63be2b3d10e..b94abb8f7706 100644 +--- a/drivers/platform/chrome/cros_ec_typec.c ++++ b/drivers/platform/chrome/cros_ec_typec.c +@@ -157,8 +157,10 @@ static int cros_typec_get_switch_handles(struct cros_typec_port *port, + + role_sw_err: + typec_switch_put(port->ori_sw); ++ port->ori_sw = NULL; + ori_sw_err: + typec_mux_put(port->mux); ++ port->mux = NULL; + mux_err: + return -ENODEV; + } +-- +2.35.1 + diff --git a/queue-5.15/platform-chrome-cros_usbpd_notify-fix-error-handling.patch b/queue-5.15/platform-chrome-cros_usbpd_notify-fix-error-handling.patch new file mode 100644 index 00000000000..9d9f8b4053e --- /dev/null +++ b/queue-5.15/platform-chrome-cros_usbpd_notify-fix-error-handling.patch @@ -0,0 +1,67 @@ +From 515c72201e2f4c37ae4ee573b42b0ea47c5c8da1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 08:08:23 +0000 +Subject: platform/chrome: cros_usbpd_notify: Fix error handling in + cros_usbpd_notify_init() + +From: Yuan Can + +[ Upstream commit 5a2d96623670155d94aca72c320c0ac27bdc6bd2 ] + +The following WARNING message was given when rmmod cros_usbpd_notify: + + Unexpected driver unregister! + WARNING: CPU: 0 PID: 253 at drivers/base/driver.c:270 driver_unregister+0x8a/0xb0 + Modules linked in: cros_usbpd_notify(-) + CPU: 0 PID: 253 Comm: rmmod Not tainted 6.1.0-rc3 #24 + ... + Call Trace: + + cros_usbpd_notify_exit+0x11/0x1e [cros_usbpd_notify] + __x64_sys_delete_module+0x3c7/0x570 + ? __ia32_sys_delete_module+0x570/0x570 + ? lock_is_held_type+0xe3/0x140 + ? syscall_enter_from_user_mode+0x17/0x50 + ? rcu_read_lock_sched_held+0xa0/0xd0 + ? syscall_enter_from_user_mode+0x1c/0x50 + do_syscall_64+0x37/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + RIP: 0033:0x7f333fe9b1b7 + +The reason is that the cros_usbpd_notify_init() does not check the return +value of platform_driver_register(), and the cros_usbpd_notify can +install successfully even if platform_driver_register() failed. + +Fix by checking the return value of platform_driver_register() and +unregister cros_usbpd_notify_plat_driver when it failed. + +Fixes: ec2daf6e33f9 ("platform: chrome: Add cros-usbpd-notify driver") +Signed-off-by: Yuan Can +Reviewed-by: Brian Norris +Link: https://lore.kernel.org/r/20221117080823.77549-1-yuancan@huawei.com +Signed-off-by: Prashant Malani +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_usbpd_notify.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/chrome/cros_usbpd_notify.c b/drivers/platform/chrome/cros_usbpd_notify.c +index 48a6617aa12f..de76de6f5090 100644 +--- a/drivers/platform/chrome/cros_usbpd_notify.c ++++ b/drivers/platform/chrome/cros_usbpd_notify.c +@@ -285,7 +285,11 @@ static int __init cros_usbpd_notify_init(void) + return ret; + + #ifdef CONFIG_ACPI +- platform_driver_register(&cros_usbpd_notify_acpi_driver); ++ ret = platform_driver_register(&cros_usbpd_notify_acpi_driver); ++ if (ret) { ++ platform_driver_unregister(&cros_usbpd_notify_plat_driver); ++ return ret; ++ } + #endif + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/platform-mellanox-mlxbf-pmc-fix-event-typo.patch b/queue-5.15/platform-mellanox-mlxbf-pmc-fix-event-typo.patch new file mode 100644 index 00000000000..22d15f812db --- /dev/null +++ b/queue-5.15/platform-mellanox-mlxbf-pmc-fix-event-typo.patch @@ -0,0 +1,38 @@ +From 1a9433ee78e5eaa21585a2d51bfa2ca06154462e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 09:35:19 -0500 +Subject: platform/mellanox: mlxbf-pmc: Fix event typo + +From: James Hurley + +[ Upstream commit b0b698b80c56b0712f0d4346d51bf0363ba03068 ] + +Had a duplicate event typo, so just fixed the 1 character typo. + +Fixes: 1a218d312e65 ("platform/mellanox: mlxbf-pmc: Add Mellanox BlueField PMC driver") +Signed-off-by: James Hurley +Reviewed-by: David Thompson +Reviewed-by: Shravan Kumar Ramani +Link: https://lore.kernel.org/r/aadacdbbd3186c55e74ea9456fe011b77938eb6c.1670535330.git.jahurley@nvidia.com +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/mellanox/mlxbf-pmc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c +index 65b4a819f1bd..c2c9b0d3244c 100644 +--- a/drivers/platform/mellanox/mlxbf-pmc.c ++++ b/drivers/platform/mellanox/mlxbf-pmc.c +@@ -358,7 +358,7 @@ static const struct mlxbf_pmc_events mlxbf_pmc_hnfnet_events[] = { + { 0x32, "DDN_DIAG_W_INGRESS" }, + { 0x33, "DDN_DIAG_C_INGRESS" }, + { 0x34, "DDN_DIAG_CORE_SENT" }, +- { 0x35, "NDN_DIAG_S_OUT_OF_CRED" }, ++ { 0x35, "NDN_DIAG_N_OUT_OF_CRED" }, + { 0x36, "NDN_DIAG_S_OUT_OF_CRED" }, + { 0x37, "NDN_DIAG_E_OUT_OF_CRED" }, + { 0x38, "NDN_DIAG_W_OUT_OF_CRED" }, +-- +2.35.1 + diff --git a/queue-5.15/platform-x86-huawei-wmi-fix-return-value-calculation.patch b/queue-5.15/platform-x86-huawei-wmi-fix-return-value-calculation.patch new file mode 100644 index 00000000000..a12bee3eb79 --- /dev/null +++ b/queue-5.15/platform-x86-huawei-wmi-fix-return-value-calculation.patch @@ -0,0 +1,74 @@ +From 59ee80436a8fc3e60f2d89a837ec6f9fc86f853b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Oct 2022 15:00:45 +0000 +Subject: platform/x86: huawei-wmi: fix return value calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Barnabás Pőcze + +[ Upstream commit 0b9a1dcdb6a2c841899389bf2dd7a3e0e2aa0e99 ] + +Previously, `huawei_wmi_input_setup()` returned the result of +logical or-ing the return values of two functions that return negative +errno-style error codes and one that returns `acpi_status`. If this +returned value was non-zero, then it was propagated from the platform +driver's probe function. That function should return a negative +errno-style error code, so the result of the logical or that +`huawei_wmi_input_setup()` returned was not appropriate. + +Fix that by checking each function separately and returning the +error code unmodified. + +Fixes: 1ac9abeb2e5b ("platform/x86: huawei-wmi: Move to platform driver") +Signed-off-by: Barnabás Pőcze +Link: https://lore.kernel.org/r/20221005150032.173198-2-pobrn@protonmail.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/huawei-wmi.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/x86/huawei-wmi.c b/drivers/platform/x86/huawei-wmi.c +index eac3e6b4ea11..935562c870c3 100644 +--- a/drivers/platform/x86/huawei-wmi.c ++++ b/drivers/platform/x86/huawei-wmi.c +@@ -760,6 +760,9 @@ static int huawei_wmi_input_setup(struct device *dev, + const char *guid, + struct input_dev **idev) + { ++ acpi_status status; ++ int err; ++ + *idev = devm_input_allocate_device(dev); + if (!*idev) + return -ENOMEM; +@@ -769,10 +772,19 @@ static int huawei_wmi_input_setup(struct device *dev, + (*idev)->id.bustype = BUS_HOST; + (*idev)->dev.parent = dev; + +- return sparse_keymap_setup(*idev, huawei_wmi_keymap, NULL) || +- input_register_device(*idev) || +- wmi_install_notify_handler(guid, huawei_wmi_input_notify, +- *idev); ++ err = sparse_keymap_setup(*idev, huawei_wmi_keymap, NULL); ++ if (err) ++ return err; ++ ++ err = input_register_device(*idev); ++ if (err) ++ return err; ++ ++ status = wmi_install_notify_handler(guid, huawei_wmi_input_notify, *idev); ++ if (ACPI_FAILURE(status)) ++ return -EIO; ++ ++ return 0; + } + + static void huawei_wmi_input_exit(struct device *dev, const char *guid) +-- +2.35.1 + diff --git a/queue-5.15/platform-x86-intel_scu_ipc-fix-possible-name-leak-in.patch b/queue-5.15/platform-x86-intel_scu_ipc-fix-possible-name-leak-in.patch new file mode 100644 index 00000000000..6795f3ac5ab --- /dev/null +++ b/queue-5.15/platform-x86-intel_scu_ipc-fix-possible-name-leak-in.patch @@ -0,0 +1,48 @@ +From 9f7c9cad3b97bf20777cb66eefcddb36ddd1f50e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 23:19:16 +0800 +Subject: platform/x86: intel_scu_ipc: fix possible name leak in + __intel_scu_ipc_register() + +From: Yang Yingliang + +[ Upstream commit 0b3d0cb7c0bed2fd6454f77ed75e7a662c6efd12 ] + +In some error paths before device_register(), the names allocated +by dev_set_name() are not freed. Move dev_set_name() front to +device_register(), so the name can be freed while calling +put_device(). + +Fixes: 54b34aa0a729 ("platform/x86: intel_scu_ipc: Split out SCU IPC functionality from the SCU driver") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221208151916.2404977-1-yangyingliang@huawei.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel_scu_ipc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c +index 7cc9089d1e14..e7a3e3402817 100644 +--- a/drivers/platform/x86/intel_scu_ipc.c ++++ b/drivers/platform/x86/intel_scu_ipc.c +@@ -583,7 +583,6 @@ __intel_scu_ipc_register(struct device *parent, + scu->dev.parent = parent; + scu->dev.class = &intel_scu_ipc_class; + scu->dev.release = intel_scu_ipc_release; +- dev_set_name(&scu->dev, "intel_scu_ipc"); + + if (!request_mem_region(scu_data->mem.start, resource_size(&scu_data->mem), + "intel_scu_ipc")) { +@@ -612,6 +611,7 @@ __intel_scu_ipc_register(struct device *parent, + * After this point intel_scu_ipc_release() takes care of + * releasing the SCU IPC resources once refcount drops to zero. + */ ++ dev_set_name(&scu->dev, "intel_scu_ipc"); + err = device_register(&scu->dev); + if (err) { + put_device(&scu->dev); +-- +2.35.1 + diff --git a/queue-5.15/platform-x86-mxm-wmi-fix-memleak-in-mxm_wmi_call_mx-.patch b/queue-5.15/platform-x86-mxm-wmi-fix-memleak-in-mxm_wmi_call_mx-.patch new file mode 100644 index 00000000000..7eb4d34df66 --- /dev/null +++ b/queue-5.15/platform-x86-mxm-wmi-fix-memleak-in-mxm_wmi_call_mx-.patch @@ -0,0 +1,62 @@ +From 0af5bb35292c2ae1b7c2c90ab9dd27a824974846 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 09:11:01 +0800 +Subject: platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]() + +From: Yu Liao + +[ Upstream commit 727cc0147f5066e359aca65cc6cc5e6d64cc15d8 ] + +The ACPI buffer memory (out.pointer) returned by wmi_evaluate_method() +is not freed after the call, so it leads to memory leak. + +The method results in ACPI buffer is not used, so just pass NULL to +wmi_evaluate_method() which fixes the memory leak. + +Fixes: 99b38b4acc0d ("platform/x86: add MXM WMI driver.") +Signed-off-by: Yu Liao +Link: https://lore.kernel.org/r/20221129011101.2042315-1-liaoyu15@huawei.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/mxm-wmi.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c +index 9a19fbd2f734..9a457956025a 100644 +--- a/drivers/platform/x86/mxm-wmi.c ++++ b/drivers/platform/x86/mxm-wmi.c +@@ -35,13 +35,11 @@ int mxm_wmi_call_mxds(int adapter) + .xarg = 1, + }; + struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; +- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + printk("calling mux switch %d\n", adapter); + +- status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, +- &output); ++ status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL); + + if (ACPI_FAILURE(status)) + return status; +@@ -60,13 +58,11 @@ int mxm_wmi_call_mxmx(int adapter) + .xarg = 1, + }; + struct acpi_buffer input = { (acpi_size)sizeof(args), &args }; +- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + printk("calling mux switch %d\n", adapter); + +- status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, +- &output); ++ status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL); + + if (ACPI_FAILURE(status)) + return status; +-- +2.35.1 + diff --git a/queue-5.15/pm-hibernate-fix-mistake-in-kerneldoc-comment.patch b/queue-5.15/pm-hibernate-fix-mistake-in-kerneldoc-comment.patch new file mode 100644 index 00000000000..e52c0217866 --- /dev/null +++ b/queue-5.15/pm-hibernate-fix-mistake-in-kerneldoc-comment.patch @@ -0,0 +1,45 @@ +From e2da91d08b210ac2adae97512d2078c80b2c64b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 10:28:39 +0800 +Subject: PM: hibernate: Fix mistake in kerneldoc comment + +From: xiongxin + +[ Upstream commit 6e5d7300cbe7c3541bc31f16db3e9266e6027b4b ] + +The actual maximum image size formula in hibernate_preallocate_memory() +is as follows: + +max_size = (count - (size + PAGES_FOR_IO)) / 2 + - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE); + +but the one in the kerneldoc comment of the function is different and +incorrect. + +Fixes: ddeb64870810 ("PM / Hibernate: Add sysfs knob to control size of memory for drivers") +Signed-off-by: xiongxin +[ rjw: Subject and changelog rewrite ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + kernel/power/snapshot.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c +index 330d49937692..475d630e650f 100644 +--- a/kernel/power/snapshot.c ++++ b/kernel/power/snapshot.c +@@ -1719,8 +1719,8 @@ static unsigned long minimum_image_size(unsigned long saveable) + * /sys/power/reserved_size, respectively). To make this happen, we compute the + * total number of available page frames and allocate at least + * +- * ([page frames total] + PAGES_FOR_IO + [metadata pages]) / 2 +- * + 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE) ++ * ([page frames total] - PAGES_FOR_IO - [metadata pages]) / 2 ++ * - 2 * DIV_ROUND_UP(reserved_size, PAGE_SIZE) + * + * of them, which corresponds to the maximum size of a hibernation image. + * +-- +2.35.1 + diff --git a/queue-5.15/pm-runtime-do-not-call-__rpm_callback-from-rpm_idle.patch b/queue-5.15/pm-runtime-do-not-call-__rpm_callback-from-rpm_idle.patch new file mode 100644 index 00000000000..08f3dbae592 --- /dev/null +++ b/queue-5.15/pm-runtime-do-not-call-__rpm_callback-from-rpm_idle.patch @@ -0,0 +1,54 @@ +From e4c343e28e8708225fca8d882662ac88c309c7f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 15:30:28 +0100 +Subject: PM: runtime: Do not call __rpm_callback() from rpm_idle() + +From: Rafael J. Wysocki + +[ Upstream commit bc80c2e438dcbfcf748452ec0f7ad5b79ff3ad88 ] + +Calling __rpm_callback() from rpm_idle() after adding device links +support to the former is a clear mistake. + +Not only it causes rpm_idle() to carry out unnecessary actions, but it +is also against the assumption regarding the stability of PM-runtime +status across __rpm_callback() invocations, because rpm_suspend() and +rpm_resume() may run in parallel with __rpm_callback() when it is called +by rpm_idle() and the device's PM-runtime status can be updated by any +of them. + +Fixes: 21d5c57b3726 ("PM / runtime: Use device links") +Link: https://lore.kernel.org/linux-pm/36aed941-a73e-d937-2721-4f0decd61ce0@quicinc.com +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Adrian Hunter +Signed-off-by: Sasha Levin +--- + drivers/base/power/runtime.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c +index 3179c9265471..c1142a7a4fe6 100644 +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -484,7 +484,17 @@ static int rpm_idle(struct device *dev, int rpmflags) + + dev->power.idle_notification = true; + +- retval = __rpm_callback(callback, dev); ++ if (dev->power.irq_safe) ++ spin_unlock(&dev->power.lock); ++ else ++ spin_unlock_irq(&dev->power.lock); ++ ++ retval = callback(dev); ++ ++ if (dev->power.irq_safe) ++ spin_lock(&dev->power.lock); ++ else ++ spin_lock_irq(&dev->power.lock); + + dev->power.idle_notification = false; + wake_up_all(&dev->power.wait_queue); +-- +2.35.1 + diff --git a/queue-5.15/pnp-fix-name-memory-leak-in-pnp_alloc_dev.patch b/queue-5.15/pnp-fix-name-memory-leak-in-pnp_alloc_dev.patch new file mode 100644 index 00000000000..4c68da9a427 --- /dev/null +++ b/queue-5.15/pnp-fix-name-memory-leak-in-pnp_alloc_dev.patch @@ -0,0 +1,46 @@ +From 15e9f75efb846d744b79ad5f01edc3004b9bb318 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 09:23:58 +0800 +Subject: PNP: fix name memory leak in pnp_alloc_dev() + +From: Yang Yingliang + +[ Upstream commit 110d7b0325c55ff3620073ba4201845f59e22ebf ] + +After commit 1fa5ae857bb1 ("driver core: get rid of struct device's +bus_id string array"), the name of device is allocated dynamically, +move dev_set_name() after pnp_add_id() to avoid memory leak. + +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Reviewed-by: Hanjun Guo +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/pnp/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c +index 4df5aa6a309c..6a60c5d83383 100644 +--- a/drivers/pnp/core.c ++++ b/drivers/pnp/core.c +@@ -148,14 +148,14 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, + dev->dev.coherent_dma_mask = dev->dma_mask; + dev->dev.release = &pnp_release_device; + +- dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); +- + dev_id = pnp_add_id(dev, pnpid); + if (!dev_id) { + kfree(dev); + return NULL; + } + ++ dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); ++ + return dev; + } + +-- +2.35.1 + diff --git a/queue-5.15/power-supply-ab8500-fix-error-handling-in-ab8500_cha.patch b/queue-5.15/power-supply-ab8500-fix-error-handling-in-ab8500_cha.patch new file mode 100644 index 00000000000..5c0cf1410fc --- /dev/null +++ b/queue-5.15/power-supply-ab8500-fix-error-handling-in-ab8500_cha.patch @@ -0,0 +1,47 @@ +From 02d014555cd2f22239bd8e4c5b02b3b2ab682426 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 03:19:32 +0000 +Subject: power: supply: ab8500: Fix error handling in ab8500_charger_init() + +From: Yuan Can + +[ Upstream commit c4d33381b134da188ccd1084aef21e2b8c3c422e ] + +The ab8500_charger_init() returns the platform_driver_register() directly +without checking its return value, if platform_driver_register() failed, +all ab8500_charger_component_drivers are not unregistered. + +Fix by unregister ab8500_charger_component_drivers when +platform_driver_register() failed. + +Fixes: 1c1f13a006ed ("power: supply: ab8500: Move to componentized binding") +Signed-off-by: Yuan Can +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/ab8500_charger.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c +index 15eadaf46f14..a4f766fc7c9d 100644 +--- a/drivers/power/supply/ab8500_charger.c ++++ b/drivers/power/supply/ab8500_charger.c +@@ -3726,7 +3726,14 @@ static int __init ab8500_charger_init(void) + if (ret) + return ret; + +- return platform_driver_register(&ab8500_charger_driver); ++ ret = platform_driver_register(&ab8500_charger_driver); ++ if (ret) { ++ platform_unregister_drivers(ab8500_charger_component_drivers, ++ ARRAY_SIZE(ab8500_charger_component_drivers)); ++ return ret; ++ } ++ ++ return 0; + } + + static void __exit ab8500_charger_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/power-supply-fix-null-pointer-dereferencing-in-power.patch b/queue-5.15/power-supply-fix-null-pointer-dereferencing-in-power.patch new file mode 100644 index 00000000000..e5644720cad --- /dev/null +++ b/queue-5.15/power-supply-fix-null-pointer-dereferencing-in-power.patch @@ -0,0 +1,44 @@ +From 9dd337d04e013a4b0326cd724a50517d7d3e4626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 15:51:53 +0800 +Subject: power: supply: fix null pointer dereferencing in + power_supply_get_battery_info + +From: ruanjinjie + +[ Upstream commit 104bb8a663451404a26331263ce5b96c34504049 ] + +when kmalloc() fail to allocate memory in kasprintf(), propname +will be NULL, strcmp() called by of_get_property() will cause +null pointer dereference. + +So return ENOMEM if kasprintf() return NULL pointer. + +Fixes: 3afb50d7125b ("power: supply: core: Add some helpers to use the battery OCV capacity table") +Signed-off-by: ruanjinjie +Reviewed-by: Baolin Wang +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/power_supply_core.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c +index c3af54421840..3f9c60c5b250 100644 +--- a/drivers/power/supply/power_supply_core.c ++++ b/drivers/power/supply/power_supply_core.c +@@ -696,6 +696,11 @@ int power_supply_get_battery_info(struct power_supply *psy, + int i, tab_len, size; + + propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index); ++ if (!propname) { ++ power_supply_put_battery_info(psy, info); ++ err = -ENOMEM; ++ goto out_put_node; ++ } + list = of_get_property(battery_np, propname, &size); + if (!list || !size) { + dev_err(&psy->dev, "failed to get %s\n", propname); +-- +2.35.1 + diff --git a/queue-5.15/power-supply-fix-residue-sysfs-file-in-error-handle-.patch b/queue-5.15/power-supply-fix-residue-sysfs-file-in-error-handle-.patch new file mode 100644 index 00000000000..a4e781e9e63 --- /dev/null +++ b/queue-5.15/power-supply-fix-residue-sysfs-file-in-error-handle-.patch @@ -0,0 +1,50 @@ +From 89c58c6bf34dae0e54fb087abc3f1ab19198fd62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 16:32:19 +0800 +Subject: power: supply: fix residue sysfs file in error handle route of + __power_supply_register() + +From: Zeng Heng + +[ Upstream commit 5b79480ce1978864ac3f06f2134dfa3b6691fe74 ] + +If device_add() succeeds, we should call device_del() when want to +get rid of it, so move it into proper jump symbol. + +Otherwise, when __power_supply_register() returns fail and goto +wakeup_init_failed to exit, there is still residue device file in sysfs. +When attempt to probe device again, sysfs would complain as below: + +sysfs: cannot create duplicate filename '/devices/platform/i2c/i2c-0/0-001c/power_supply/adp5061' +Call Trace: + dump_stack_lvl+0x68/0x85 + sysfs_warn_dup.cold+0x1c/0x29 + sysfs_create_dir_ns+0x1b1/0x1d0 + kobject_add_internal+0x143/0x390 + kobject_add+0x108/0x170 + +Fixes: 80c6463e2fa3 ("power_supply: Fix Oops from NULL pointer dereference from wakeup_source_activate") +Signed-off-by: Zeng Heng +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/power_supply_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c +index a6e9afa5a1cf..c3af54421840 100644 +--- a/drivers/power/supply/power_supply_core.c ++++ b/drivers/power/supply/power_supply_core.c +@@ -1220,8 +1220,8 @@ __power_supply_register(struct device *parent, + register_cooler_failed: + psy_unregister_thermal(psy); + register_thermal_failed: +- device_del(dev); + wakeup_init_failed: ++ device_del(dev); + device_add_failed: + check_supplies_failed: + dev_set_name_failed: +-- +2.35.1 + diff --git a/queue-5.15/power-supply-z2_battery-fix-possible-memleak-in-z2_b.patch b/queue-5.15/power-supply-z2_battery-fix-possible-memleak-in-z2_b.patch new file mode 100644 index 00000000000..211b5fdd6b7 --- /dev/null +++ b/queue-5.15/power-supply-z2_battery-fix-possible-memleak-in-z2_b.patch @@ -0,0 +1,44 @@ +From c40cf58a441cbe0d79bbbe4569f53e22ad6ef315 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 09:18:31 +0800 +Subject: power: supply: z2_battery: Fix possible memleak in z2_batt_probe() + +From: Zhang Qilong + +[ Upstream commit 955bee204f3dd307642c101b75e370662987e735 ] + +If devm_gpiod_get_optional() returns error, the charger should be +freed before z2_batt_probe returns according to the context. We +fix it by just gotoing to 'err' branch. + +Fixes: a3b4388ea19b ("power: supply: z2_battery: Convert to GPIO descriptors") +Signed-off-by: Zhang Qilong +Reviewed-by: Linus Walleij +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/z2_battery.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/power/supply/z2_battery.c b/drivers/power/supply/z2_battery.c +index 7ed4e4bb26ec..fd33cdf9cf12 100644 +--- a/drivers/power/supply/z2_battery.c ++++ b/drivers/power/supply/z2_battery.c +@@ -206,10 +206,12 @@ static int z2_batt_probe(struct i2c_client *client, + + charger->charge_gpiod = devm_gpiod_get_optional(&client->dev, + NULL, GPIOD_IN); +- if (IS_ERR(charger->charge_gpiod)) +- return dev_err_probe(&client->dev, ++ if (IS_ERR(charger->charge_gpiod)) { ++ ret = dev_err_probe(&client->dev, + PTR_ERR(charger->charge_gpiod), + "failed to get charge GPIO\n"); ++ goto err; ++ } + + if (charger->charge_gpiod) { + gpiod_set_consumer_name(charger->charge_gpiod, "BATT CHRG"); +-- +2.35.1 + diff --git a/queue-5.15/powerpc-52xx-fix-a-resource-leak-in-an-error-handlin.patch b/queue-5.15/powerpc-52xx-fix-a-resource-leak-in-an-error-handlin.patch new file mode 100644 index 00000000000..df4327953bf --- /dev/null +++ b/queue-5.15/powerpc-52xx-fix-a-resource-leak-in-an-error-handlin.patch @@ -0,0 +1,38 @@ +From b722204a858b69350f57a2b2212093670c8df7c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Jan 2022 08:16:04 +0100 +Subject: powerpc/52xx: Fix a resource leak in an error handling path + +From: Christophe JAILLET + +[ Upstream commit 5836947613ef33d311b4eff6a32d019580a214f5 ] + +The error handling path of mpc52xx_lpbfifo_probe() has a request_irq() +that is not balanced by a corresponding free_irq(). + +Add the missing call, as already done in the remove function. + +Fixes: 3c9059d79f5e ("powerpc/5200: add LocalPlus bus FIFO device driver") +Signed-off-by: Christophe JAILLET +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/dec1496d46ccd5311d0f6e9f9ca4238be11bf6a6.1643440531.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +index b91ebebd9ff2..e0049b7df212 100644 +--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c ++++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c +@@ -530,6 +530,7 @@ static int mpc52xx_lpbfifo_probe(struct platform_device *op) + err_bcom_rx_irq: + bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task); + err_bcom_rx: ++ free_irq(lpbfifo.irq, &lpbfifo); + err_irq: + iounmap(lpbfifo.regs); + lpbfifo.regs = NULL; +-- +2.35.1 + diff --git a/queue-5.15/powerpc-83xx-mpc832x_rdb-call-platform_device_put-in.patch b/queue-5.15/powerpc-83xx-mpc832x_rdb-call-platform_device_put-in.patch new file mode 100644 index 00000000000..710abed4677 --- /dev/null +++ b/queue-5.15/powerpc-83xx-mpc832x_rdb-call-platform_device_put-in.patch @@ -0,0 +1,39 @@ +From 6535f2e8345fabb9b6376bad521737fe3c2b7e21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 29 Oct 2022 19:16:26 +0800 +Subject: powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in + of_fsl_spi_probe() + +From: Yang Yingliang + +[ Upstream commit 4d0eea415216fe3791da2f65eb41399e70c7bedf ] + +If platform_device_add() is not called or failed, it can not call +platform_device_del() to clean up memory, it should call +platform_device_put() in error case. + +Fixes: 26f6cb999366 ("[POWERPC] fsl_soc: add support for fsl_spi") +Signed-off-by: Yang Yingliang +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221029111626.429971-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/83xx/mpc832x_rdb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c +index b6133a237a70..6e18d0703568 100644 +--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c ++++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c +@@ -106,7 +106,7 @@ static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, + + goto next; + unreg: +- platform_device_del(pdev); ++ platform_device_put(pdev); + err: + pr_err("%pOF: registration failed\n", np); + next: +-- +2.35.1 + diff --git a/queue-5.15/powerpc-dts-t208x-mark-mac1-and-mac2-as-10g.patch b/queue-5.15/powerpc-dts-t208x-mark-mac1-and-mac2-as-10g.patch new file mode 100644 index 00000000000..cd44e8b87e8 --- /dev/null +++ b/queue-5.15/powerpc-dts-t208x-mark-mac1-and-mac2-as-10g.patch @@ -0,0 +1,142 @@ +From ef27d82d516114e7ea78f98db542b2c38525df54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 16:22:39 -0400 +Subject: powerpc: dts: t208x: Mark MAC1 and MAC2 as 10G + +From: Sean Anderson + +[ Upstream commit 36926a7d70c2d462fca1ed85bfee000d17fd8662 ] + +On the T208X SoCs, MAC1 and MAC2 support XGMII. Add some new MAC dtsi +fragments, and mark the QMAN ports as 10G. + +Fixes: da414bb923d9 ("powerpc/mpc85xx: Add FSL QorIQ DPAA FMan support to the SoC device tree(s)") +Signed-off-by: Sean Anderson +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi | 44 +++++++++++++++++++ + .../boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi | 44 +++++++++++++++++++ + arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | 4 +- + 3 files changed, 90 insertions(+), 2 deletions(-) + create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi + create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi + +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi +new file mode 100644 +index 000000000000..437dab3fc017 +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later ++/* ++ * QorIQ FMan v3 10g port #2 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2022 Sean Anderson ++ * Copyright 2012 - 2015 Freescale Semiconductor Inc. ++ */ ++ ++fman@400000 { ++ fman0_rx_0x08: port@88000 { ++ cell-index = <0x8>; ++ compatible = "fsl,fman-v3-port-rx"; ++ reg = <0x88000 0x1000>; ++ fsl,fman-10g-port; ++ }; ++ ++ fman0_tx_0x28: port@a8000 { ++ cell-index = <0x28>; ++ compatible = "fsl,fman-v3-port-tx"; ++ reg = <0xa8000 0x1000>; ++ fsl,fman-10g-port; ++ }; ++ ++ ethernet@e0000 { ++ cell-index = <0>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe0000 0x1000>; ++ fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>; ++ ptp-timer = <&ptp_timer0>; ++ pcsphy-handle = <&pcsphy0>; ++ }; ++ ++ mdio@e1000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; ++ reg = <0xe1000 0x1000>; ++ fsl,erratum-a011043; /* must ignore read errors */ ++ ++ pcsphy0: ethernet-phy@0 { ++ reg = <0x0>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi +new file mode 100644 +index 000000000000..ad116b17850a +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi +@@ -0,0 +1,44 @@ ++// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later ++/* ++ * QorIQ FMan v3 10g port #3 device tree stub [ controller @ offset 0x400000 ] ++ * ++ * Copyright 2022 Sean Anderson ++ * Copyright 2012 - 2015 Freescale Semiconductor Inc. ++ */ ++ ++fman@400000 { ++ fman0_rx_0x09: port@89000 { ++ cell-index = <0x9>; ++ compatible = "fsl,fman-v3-port-rx"; ++ reg = <0x89000 0x1000>; ++ fsl,fman-10g-port; ++ }; ++ ++ fman0_tx_0x29: port@a9000 { ++ cell-index = <0x29>; ++ compatible = "fsl,fman-v3-port-tx"; ++ reg = <0xa9000 0x1000>; ++ fsl,fman-10g-port; ++ }; ++ ++ ethernet@e2000 { ++ cell-index = <1>; ++ compatible = "fsl,fman-memac"; ++ reg = <0xe2000 0x1000>; ++ fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>; ++ ptp-timer = <&ptp_timer0>; ++ pcsphy-handle = <&pcsphy1>; ++ }; ++ ++ mdio@e3000 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio"; ++ reg = <0xe3000 0x1000>; ++ fsl,erratum-a011043; /* must ignore read errors */ ++ ++ pcsphy1: ethernet-phy@0 { ++ reg = <0x0>; ++ }; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi +index ecbb447920bc..74e17e134387 100644 +--- a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi ++++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi +@@ -609,8 +609,8 @@ usb1: usb@211000 { + /include/ "qoriq-bman1.dtsi" + + /include/ "qoriq-fman3-0.dtsi" +-/include/ "qoriq-fman3-0-1g-0.dtsi" +-/include/ "qoriq-fman3-0-1g-1.dtsi" ++/include/ "qoriq-fman3-0-10g-2.dtsi" ++/include/ "qoriq-fman3-0-10g-3.dtsi" + /include/ "qoriq-fman3-0-1g-2.dtsi" + /include/ "qoriq-fman3-0-1g-3.dtsi" + /include/ "qoriq-fman3-0-1g-4.dtsi" +-- +2.35.1 + diff --git a/queue-5.15/powerpc-eeh-drop-redundant-spinlock-initialization.patch b/queue-5.15/powerpc-eeh-drop-redundant-spinlock-initialization.patch new file mode 100644 index 00000000000..792e06ebc19 --- /dev/null +++ b/queue-5.15/powerpc-eeh-drop-redundant-spinlock-initialization.patch @@ -0,0 +1,38 @@ +From 66490a3d9430a726cbb83ee20535632c77d2e687 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 11 May 2022 09:27:56 +0800 +Subject: powerpc/eeh: Drop redundant spinlock initialization + +From: Haowen Bai + +[ Upstream commit 3def164a5cedad9117859dd4610cae2cc59cb6d2 ] + +slot_errbuf_lock has declared and initialized by DEFINE_SPINLOCK, +so we don't need to spin_lock_init again, drop it. + +Signed-off-by: Haowen Bai +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/1652232476-9696-1-git-send-email-baihaowen@meizu.com +Stable-dep-of: 9aafbfa5f57a ("powerpc/pseries/eeh: use correct API for error log size") +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/eeh_pseries.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c +index 09fafcf2d3a0..08ce7e4ad9f0 100644 +--- a/arch/powerpc/platforms/pseries/eeh_pseries.c ++++ b/arch/powerpc/platforms/pseries/eeh_pseries.c +@@ -845,8 +845,7 @@ static int __init eeh_pseries_init(void) + return -EINVAL; + } + +- /* Initialize error log lock and size */ +- spin_lock_init(&slot_errbuf_lock); ++ /* Initialize error log size */ + eeh_error_buf_size = rtas_token("rtas-error-log-max"); + if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { + pr_info("%s: unknown EEH error log size\n", +-- +2.35.1 + diff --git a/queue-5.15/powerpc-hv-gpci-fix-hv_gpci-event-list.patch b/queue-5.15/powerpc-hv-gpci-fix-hv_gpci-event-list.patch new file mode 100644 index 00000000000..dd66d00da7b --- /dev/null +++ b/queue-5.15/powerpc-hv-gpci-fix-hv_gpci-event-list.patch @@ -0,0 +1,174 @@ +From 3b044ea127433534894fe0939ef699a97cdefd4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 23:15:13 +0530 +Subject: powerpc/hv-gpci: Fix hv_gpci event list + +From: Kajol Jain + +[ Upstream commit 03f7c1d2a49acd30e38789cd809d3300721e9b0e ] + +Based on getPerfCountInfo v1.018 documentation, some of the +hv_gpci events were deprecated for platform firmware that +supports counter_info_version 0x8 or above. + +Fix the hv_gpci event list by adding a new attribute group +called "hv_gpci_event_attrs_v6" and a "ENABLE_EVENTS_COUNTERINFO_V6" +macro to enable these events for platform firmware +that supports counter_info_version 0x6 or below. And assigning +the hv_gpci event list based on output counter info version +of underlying plaform. + +Fixes: 97bf2640184f ("powerpc/perf/hv-gpci: add the remaining gpci requests") +Signed-off-by: Kajol Jain +Reviewed-by: Madhavan Srinivasan +Reviewed-by: Athira Rajeev +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221130174513.87501-1-kjain@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/hv-gpci-requests.h | 4 ++++ + arch/powerpc/perf/hv-gpci.c | 33 +++++++++++++++++++++++++++- + arch/powerpc/perf/hv-gpci.h | 1 + + arch/powerpc/perf/req-gen/perf.h | 20 +++++++++++++++++ + 4 files changed, 57 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/perf/hv-gpci-requests.h b/arch/powerpc/perf/hv-gpci-requests.h +index 8965b4463d43..5e86371a20c7 100644 +--- a/arch/powerpc/perf/hv-gpci-requests.h ++++ b/arch/powerpc/perf/hv-gpci-requests.h +@@ -79,6 +79,7 @@ REQUEST(__field(0, 8, partition_id) + ) + #include I(REQUEST_END) + ++#ifdef ENABLE_EVENTS_COUNTERINFO_V6 + /* + * Not available for counter_info_version >= 0x8, use + * run_instruction_cycles_by_partition(0x100) instead. +@@ -92,6 +93,7 @@ REQUEST(__field(0, 8, partition_id) + __count(0x10, 8, cycles) + ) + #include I(REQUEST_END) ++#endif + + #define REQUEST_NAME system_performance_capabilities + #define REQUEST_NUM 0x40 +@@ -103,6 +105,7 @@ REQUEST(__field(0, 1, perf_collect_privileged) + ) + #include I(REQUEST_END) + ++#ifdef ENABLE_EVENTS_COUNTERINFO_V6 + #define REQUEST_NAME processor_bus_utilization_abc_links + #define REQUEST_NUM 0x50 + #define REQUEST_IDX_KIND "hw_chip_id=?" +@@ -194,6 +197,7 @@ REQUEST(__field(0, 4, phys_processor_idx) + __count(0x28, 8, instructions_completed) + ) + #include I(REQUEST_END) ++#endif + + /* Processor_core_power_mode (0x95) skipped, no counters */ + /* Affinity_domain_information_by_virtual_processor (0xA0) skipped, +diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c +index c756228a081f..28b770bbc10b 100644 +--- a/arch/powerpc/perf/hv-gpci.c ++++ b/arch/powerpc/perf/hv-gpci.c +@@ -72,7 +72,7 @@ static struct attribute_group format_group = { + + static struct attribute_group event_group = { + .name = "events", +- .attrs = hv_gpci_event_attrs, ++ /* .attrs is set in init */ + }; + + #define HV_CAPS_ATTR(_name, _format) \ +@@ -330,6 +330,7 @@ static int hv_gpci_init(void) + int r; + unsigned long hret; + struct hv_perf_caps caps; ++ struct hv_gpci_request_buffer *arg; + + hv_gpci_assert_offsets_correct(); + +@@ -353,6 +354,36 @@ static int hv_gpci_init(void) + /* sampling not supported */ + h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; + ++ arg = (void *)get_cpu_var(hv_gpci_reqb); ++ memset(arg, 0, HGPCI_REQ_BUFFER_SIZE); ++ ++ /* ++ * hcall H_GET_PERF_COUNTER_INFO populates the output ++ * counter_info_version value based on the system hypervisor. ++ * Pass the counter request 0x10 corresponds to request type ++ * 'Dispatch_timebase_by_processor', to get the supported ++ * counter_info_version. ++ */ ++ arg->params.counter_request = cpu_to_be32(0x10); ++ ++ r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, ++ virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE); ++ if (r) { ++ pr_devel("hcall failed, can't get supported counter_info_version: 0x%x\n", r); ++ arg->params.counter_info_version_out = 0x8; ++ } ++ ++ /* ++ * Use counter_info_version_out value to assign ++ * required hv-gpci event list. ++ */ ++ if (arg->params.counter_info_version_out >= 0x8) ++ event_group.attrs = hv_gpci_event_attrs; ++ else ++ event_group.attrs = hv_gpci_event_attrs_v6; ++ ++ put_cpu_var(hv_gpci_reqb); ++ + r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1); + if (r) + return r; +diff --git a/arch/powerpc/perf/hv-gpci.h b/arch/powerpc/perf/hv-gpci.h +index 4d108262bed7..c72020912dea 100644 +--- a/arch/powerpc/perf/hv-gpci.h ++++ b/arch/powerpc/perf/hv-gpci.h +@@ -26,6 +26,7 @@ enum { + #define REQUEST_FILE "../hv-gpci-requests.h" + #define NAME_LOWER hv_gpci + #define NAME_UPPER HV_GPCI ++#define ENABLE_EVENTS_COUNTERINFO_V6 + #include "req-gen/perf.h" + #undef REQUEST_FILE + #undef NAME_LOWER +diff --git a/arch/powerpc/perf/req-gen/perf.h b/arch/powerpc/perf/req-gen/perf.h +index fa9bc804e67a..6b2a59fefffa 100644 +--- a/arch/powerpc/perf/req-gen/perf.h ++++ b/arch/powerpc/perf/req-gen/perf.h +@@ -139,6 +139,26 @@ PMU_EVENT_ATTR_STRING( \ + #define REQUEST_(r_name, r_value, r_idx_1, r_fields) \ + r_fields + ++/* Generate event list for platforms with counter_info_version 0x6 or below */ ++static __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = { ++#include REQUEST_FILE ++ NULL ++}; ++ ++/* ++ * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci ++ * events were deprecated for platform firmware that supports ++ * counter_info_version 0x8 or above. ++ * Those deprecated events are still part of platform firmware that ++ * support counter_info_version 0x6 and below. As per the getPerfCountInfo ++ * v1.018 documentation there is no counter_info_version 0x7. ++ * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of ++ * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms ++ * that supports counter_info_version 0x8 or above. ++ */ ++#undef ENABLE_EVENTS_COUNTERINFO_V6 ++ ++/* Generate event list for platforms with counter_info_version 0x8 or above*/ + static __maybe_unused struct attribute *hv_gpci_event_attrs[] = { + #include REQUEST_FILE + NULL +-- +2.35.1 + diff --git a/queue-5.15/powerpc-perf-callchain-validate-kernel-stack-pointer.patch b/queue-5.15/powerpc-perf-callchain-validate-kernel-stack-pointer.patch new file mode 100644 index 00000000000..33273166500 --- /dev/null +++ b/queue-5.15/powerpc-perf-callchain-validate-kernel-stack-pointer.patch @@ -0,0 +1,46 @@ +From c70f93766260616d8224c6b178e0d48a3d8706f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Nov 2022 22:49:28 +1000 +Subject: powerpc/perf: callchain validate kernel stack pointer bounds + +From: Nicholas Piggin + +[ Upstream commit 32c5209214bd8d4f8c4e9d9b630ef4c671f58e79 ] + +The interrupt frame detection and loads from the hypothetical pt_regs +are not bounds-checked. The next-frame validation only bounds-checks +STACK_FRAME_OVERHEAD, which does not include the pt_regs. Add another +test for this. + +The user could set r1 to be equal to the address matching the first +interrupt frame - STACK_INT_FRAME_SIZE, which is in the previous page +due to the kernel redzone, and induce the kernel to load the marker from +there. Possibly this could cause a crash at least. If the user could +induce the previous page to contain a valid marker, then it might be +able to direct perf to read specific memory addresses in a way that +could be transmitted back to the user in the perf data. + +Fixes: 20002ded4d93 ("perf_counter: powerpc: Add callchain support") +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221127124942.1665522-4-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/perf/callchain.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c +index 082f6d0308a4..8718289c051d 100644 +--- a/arch/powerpc/perf/callchain.c ++++ b/arch/powerpc/perf/callchain.c +@@ -61,6 +61,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re + next_sp = fp[0]; + + if (next_sp == sp + STACK_INT_FRAME_SIZE && ++ validate_sp(sp, current, STACK_INT_FRAME_SIZE) && + fp[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) { + /* + * This looks like an interrupt frame for an +-- +2.35.1 + diff --git a/queue-5.15/powerpc-pseries-eeh-use-correct-api-for-error-log-si.patch b/queue-5.15/powerpc-pseries-eeh-use-correct-api-for-error-log-si.patch new file mode 100644 index 00000000000..e1b499d2d18 --- /dev/null +++ b/queue-5.15/powerpc-pseries-eeh-use-correct-api-for-error-log-si.patch @@ -0,0 +1,49 @@ +From 10fbfab0c75e2bdab769058ed9e2521ec7f00b4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 09:07:43 -0600 +Subject: powerpc/pseries/eeh: use correct API for error log size + +From: Nathan Lynch + +[ Upstream commit 9aafbfa5f57a4b75bafd3bed0191e8429c5fa618 ] + +rtas-error-log-max is not the name of an RTAS function, so rtas_token() +is not the appropriate API for retrieving its value. We already have +rtas_get_error_log_max() which returns a sensible value if the property +is absent for any reason, so use that instead. + +Fixes: 8d633291b4fc ("powerpc/eeh: pseries platform EEH error log retrieval") +Signed-off-by: Nathan Lynch +[mpe: Drop no-longer possible error handling as noticed by ajd] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221118150751.469393-6-nathanl@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/eeh_pseries.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c +index 08ce7e4ad9f0..f51fd4ac3f0b 100644 +--- a/arch/powerpc/platforms/pseries/eeh_pseries.c ++++ b/arch/powerpc/platforms/pseries/eeh_pseries.c +@@ -846,16 +846,7 @@ static int __init eeh_pseries_init(void) + } + + /* Initialize error log size */ +- eeh_error_buf_size = rtas_token("rtas-error-log-max"); +- if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { +- pr_info("%s: unknown EEH error log size\n", +- __func__); +- eeh_error_buf_size = 1024; +- } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { +- pr_info("%s: EEH error log size %d exceeds the maximal %d\n", +- __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); +- eeh_error_buf_size = RTAS_ERROR_LOG_MAX; +- } ++ eeh_error_buf_size = rtas_get_error_log_max(); + + /* Set EEH probe mode */ + eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG); +-- +2.35.1 + diff --git a/queue-5.15/powerpc-xive-add-missing-iounmap-in-error-path-in-xi.patch b/queue-5.15/powerpc-xive-add-missing-iounmap-in-error-path-in-xi.patch new file mode 100644 index 00000000000..3399919bdd3 --- /dev/null +++ b/queue-5.15/powerpc-xive-add-missing-iounmap-in-error-path-in-xi.patch @@ -0,0 +1,41 @@ +From 323a44a342bb4121eb89f06c9531b6cd98d54fb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 11:23:33 +0800 +Subject: powerpc/xive: add missing iounmap() in error path in + xive_spapr_populate_irq_data() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yang Yingliang + +[ Upstream commit 8b49670f3bb3f10cd4d5a6dca17f5a31b173ecdc ] + +If remapping 'data->trig_page' fails, the 'data->eoi_mmio' need be unmapped +before returning from xive_spapr_populate_irq_data(). + +Fixes: eac1e731b59e ("powerpc/xive: guest exploitation of the XIVE interrupt controller") +Signed-off-by: Yang Yingliang +Reviewed-by: Cédric Le Goater +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221017032333.1852406-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/sysdev/xive/spapr.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c +index 2bf78a30238b..43bd2579d942 100644 +--- a/arch/powerpc/sysdev/xive/spapr.c ++++ b/arch/powerpc/sysdev/xive/spapr.c +@@ -437,6 +437,7 @@ static int xive_spapr_populate_irq_data(u32 hw_irq, struct xive_irq_data *data) + + data->trig_mmio = ioremap(data->trig_page, 1u << data->esb_shift); + if (!data->trig_mmio) { ++ iounmap(data->eoi_mmio); + pr_err("Failed to map trigger page for irq 0x%x\n", hw_irq); + return -ENOMEM; + } +-- +2.35.1 + diff --git a/queue-5.15/powerpc-xmon-fix-wswitch-unreachable-warning-in-bpt_.patch b/queue-5.15/powerpc-xmon-fix-wswitch-unreachable-warning-in-bpt_.patch new file mode 100644 index 00000000000..d4380a25861 --- /dev/null +++ b/queue-5.15/powerpc-xmon-fix-wswitch-unreachable-warning-in-bpt_.patch @@ -0,0 +1,59 @@ +From ddaf01390955e85a6fed9770f17b37522424b246 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 15:15:04 +0100 +Subject: powerpc/xmon: Fix -Wswitch-unreachable warning in bpt_cmds +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gustavo A. R. Silva + +[ Upstream commit 1c4a4a4c8410be4a231a58b23e7a30923ff954ac ] + +When building with automatic stack variable initialization, GCC 12 +complains about variables defined outside of switch case statements. +Move the variable into the case that uses it, which silences the warning: + +arch/powerpc/xmon/xmon.c: In function ‘bpt_cmds’: +arch/powerpc/xmon/xmon.c:1529:13: warning: statement will never be executed [-Wswitch-unreachable] + 1529 | int mode; + | ^~~~ + +Fixes: 09b6c1129f89 ("powerpc/xmon: Fix compile error with PPC_8xx=y") +Signed-off-by: Gustavo A. R. Silva +Reviewed-by: Kees Cook +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/YySE6FHiOcbWWR+9@work +Signed-off-by: Sasha Levin +--- + arch/powerpc/xmon/xmon.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c +index 8b28ff9d98d1..3c085e1e5232 100644 +--- a/arch/powerpc/xmon/xmon.c ++++ b/arch/powerpc/xmon/xmon.c +@@ -1528,9 +1528,9 @@ bpt_cmds(void) + cmd = inchar(); + + switch (cmd) { +- static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; +- int mode; +- case 'd': /* bd - hardware data breakpoint */ ++ case 'd': { /* bd - hardware data breakpoint */ ++ static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n"; ++ int mode; + if (xmon_is_ro) { + printf(xmon_ro_msg); + break; +@@ -1563,6 +1563,7 @@ bpt_cmds(void) + + force_enable_xmon(); + break; ++ } + + case 'i': /* bi - hardware instr breakpoint */ + if (xmon_is_ro) { +-- +2.35.1 + diff --git a/queue-5.15/ppp-associate-skb-with-a-device-at-tx.patch b/queue-5.15/ppp-associate-skb-with-a-device-at-tx.patch new file mode 100644 index 00000000000..38e26eded93 --- /dev/null +++ b/queue-5.15/ppp-associate-skb-with-a-device-at-tx.patch @@ -0,0 +1,62 @@ +From 65d06fb7e82f9b1e46020f7e8fd482cc4afeeeda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 10:29:13 -0800 +Subject: ppp: associate skb with a device at tx + +From: Stanislav Fomichev + +[ Upstream commit 9f225444467b98579cf28d94f4ad053460dfdb84 ] + +Syzkaller triggered flow dissector warning with the following: + +r0 = openat$ppp(0xffffffffffffff9c, &(0x7f0000000000), 0xc0802, 0x0) +ioctl$PPPIOCNEWUNIT(r0, 0xc004743e, &(0x7f00000000c0)) +ioctl$PPPIOCSACTIVE(r0, 0x40107446, &(0x7f0000000240)={0x2, &(0x7f0000000180)=[{0x20, 0x0, 0x0, 0xfffff034}, {0x6}]}) +pwritev(r0, &(0x7f0000000040)=[{&(0x7f0000000140)='\x00!', 0x2}], 0x1, 0x0, 0x0) + +[ 9.485814] WARNING: CPU: 3 PID: 329 at net/core/flow_dissector.c:1016 __skb_flow_dissect+0x1ee0/0x1fa0 +[ 9.485929] skb_get_poff+0x53/0xa0 +[ 9.485937] bpf_skb_get_pay_offset+0xe/0x20 +[ 9.485944] ? ppp_send_frame+0xc2/0x5b0 +[ 9.485949] ? _raw_spin_unlock_irqrestore+0x40/0x60 +[ 9.485958] ? __ppp_xmit_process+0x7a/0xe0 +[ 9.485968] ? ppp_xmit_process+0x5b/0xb0 +[ 9.485974] ? ppp_write+0x12a/0x190 +[ 9.485981] ? do_iter_write+0x18e/0x2d0 +[ 9.485987] ? __import_iovec+0x30/0x130 +[ 9.485997] ? do_pwritev+0x1b6/0x240 +[ 9.486016] ? trace_hardirqs_on+0x47/0x50 +[ 9.486023] ? __x64_sys_pwritev+0x24/0x30 +[ 9.486026] ? do_syscall_64+0x3d/0x80 +[ 9.486031] ? entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Flow dissector tries to find skb net namespace either via device +or via socket. Neigher is set in ppp_send_frame, so let's manually +use ppp->dev. + +Cc: Paul Mackerras +Cc: linux-ppp@vger.kernel.org +Reported-by: syzbot+41cab52ab62ee99ed24a@syzkaller.appspotmail.com +Signed-off-by: Stanislav Fomichev +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 829d6ada1704..c1f11d1df4cd 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1742,6 +1742,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + int len; + unsigned char *cp; + ++ skb->dev = ppp->dev; ++ + if (proto < 0x8000) { + #ifdef CONFIG_PPP_FILTER + /* check if we should pass this packet */ +-- +2.35.1 + diff --git a/queue-5.15/proc-fixup-uptime-selftest.patch b/queue-5.15/proc-fixup-uptime-selftest.patch new file mode 100644 index 00000000000..8e265d0df11 --- /dev/null +++ b/queue-5.15/proc-fixup-uptime-selftest.patch @@ -0,0 +1,48 @@ +From fa077cce4cd00e91ef0f519c2ec6fef9ee48a1e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 21:08:09 +0300 +Subject: proc: fixup uptime selftest + +From: Alexey Dobriyan + +[ Upstream commit 5cc81d5c81af0dee54da9a67a3ebe4be076a13db ] + +syscall(3) returns -1 and sets errno on error, unlike "syscall" +instruction. + +Systems which have <= 32/64 CPUs are unaffected. Test won't bounce +to all CPUs before completing if there are more of them. + +Link: https://lkml.kernel.org/r/Y1bUiT7VRXlXPQa1@p183 +Fixes: 1f5bd0547654 ("proc: selftests: test /proc/uptime") +Signed-off-by: Alexey Dobriyan +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/proc/proc-uptime-002.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/proc/proc-uptime-002.c b/tools/testing/selftests/proc/proc-uptime-002.c +index e7ceabed7f51..7d0aa22bdc12 100644 +--- a/tools/testing/selftests/proc/proc-uptime-002.c ++++ b/tools/testing/selftests/proc/proc-uptime-002.c +@@ -17,6 +17,7 @@ + // while shifting across CPUs. + #undef NDEBUG + #include ++#include + #include + #include + #include +@@ -54,7 +55,7 @@ int main(void) + len += sizeof(unsigned long); + free(m); + m = malloc(len); +- } while (sys_sched_getaffinity(0, len, m) == -EINVAL); ++ } while (sys_sched_getaffinity(0, len, m) == -1 && errno == EINVAL); + + fd = open("/proc/uptime", O_RDONLY); + assert(fd >= 0); +-- +2.35.1 + diff --git a/queue-5.15/pstore-avoid-kcore-oops-by-vmap-ing-with-vm_ioremap.patch b/queue-5.15/pstore-avoid-kcore-oops-by-vmap-ing-with-vm_ioremap.patch new file mode 100644 index 00000000000..841d07700fd --- /dev/null +++ b/queue-5.15/pstore-avoid-kcore-oops-by-vmap-ing-with-vm_ioremap.patch @@ -0,0 +1,103 @@ +From a633504dc3fbea1932de8416bc47955b7307381f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 15:31:36 -0800 +Subject: pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP + +From: Stephen Boyd + +[ Upstream commit e6b842741b4f39007215fd7e545cb55aa3d358a2 ] + +An oops can be induced by running 'cat /proc/kcore > /dev/null' on +devices using pstore with the ram backend because kmap_atomic() assumes +lowmem pages are accessible with __va(). + + Unable to handle kernel paging request at virtual address ffffff807ff2b000 + Mem abort info: + ESR = 0x96000006 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x06: level 2 translation fault + Data abort info: + ISV = 0, ISS = 0x00000006 + CM = 0, WnR = 0 + swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000081d87000 + [ffffff807ff2b000] pgd=180000017fe18003, p4d=180000017fe18003, pud=180000017fe18003, pmd=0000000000000000 + Internal error: Oops: 96000006 [#1] PREEMPT SMP + Modules linked in: dm_integrity + CPU: 7 PID: 21179 Comm: perf Not tainted 5.15.67-10882-ge4eb2eb988cd #1 baa443fb8e8477896a370b31a821eb2009f9bfba + Hardware name: Google Lazor (rev3 - 8) (DT) + pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : __memcpy+0x110/0x260 + lr : vread+0x194/0x294 + sp : ffffffc013ee39d0 + x29: ffffffc013ee39f0 x28: 0000000000001000 x27: ffffff807ff2b000 + x26: 0000000000001000 x25: ffffffc0085a2000 x24: ffffff802d4b3000 + x23: ffffff80f8a60000 x22: ffffff802d4b3000 x21: ffffffc0085a2000 + x20: ffffff8080b7bc68 x19: 0000000000001000 x18: 0000000000000000 + x17: 0000000000000000 x16: 0000000000000000 x15: ffffffd3073f2e60 + x14: ffffffffad588000 x13: 0000000000000000 x12: 0000000000000001 + x11: 00000000000001a2 x10: 00680000fff2bf0b x9 : 03fffffff807ff2b + x8 : 0000000000000001 x7 : 0000000000000000 x6 : 0000000000000000 + x5 : ffffff802d4b4000 x4 : ffffff807ff2c000 x3 : ffffffc013ee3a78 + x2 : 0000000000001000 x1 : ffffff807ff2b000 x0 : ffffff802d4b3000 + Call trace: + __memcpy+0x110/0x260 + read_kcore+0x584/0x778 + proc_reg_read+0xb4/0xe4 + +During early boot, memblock reserves the pages for the ramoops reserved +memory node in DT that would otherwise be part of the direct lowmem +mapping. Pstore's ram backend reuses those reserved pages to change the +memory type (writeback or non-cached) by passing the pages to vmap() +(see pfn_to_page() usage in persistent_ram_vmap() for more details) with +specific flags. When read_kcore() starts iterating over the vmalloc +region, it runs over the virtual address that vmap() returned for +ramoops. In aligned_vread() the virtual address is passed to +vmalloc_to_page() which returns the page struct for the reserved lowmem +area. That lowmem page is passed to kmap_atomic(), which effectively +calls page_to_virt() that assumes a lowmem page struct must be directly +accessible with __va() and friends. These pages are mapped via vmap() +though, and the lowmem mapping was never made, so accessing them via the +lowmem virtual address oopses like above. + +Let's side-step this problem by passing VM_IOREMAP to vmap(). This will +tell vread() to not include the ramoops region in the kcore. Instead the +area will look like a bunch of zeros. The alternative is to teach kmap() +about vmalloc areas that intersect with lowmem. Presumably such a change +isn't a one-liner, and there isn't much interest in inspecting the +ramoops region in kcore files anyway, so the most expedient route is +taken for now. + +Cc: Brian Geffon +Cc: Mike Rapoport +Cc: Andrew Morton +Fixes: 404a6043385d ("staging: android: persistent_ram: handle reserving and mapping memory") +Signed-off-by: Stephen Boyd +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20221205233136.3420802-1-swboyd@chromium.org +Signed-off-by: Sasha Levin +--- + fs/pstore/ram_core.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c +index fe5305028c6e..155c7010b1f8 100644 +--- a/fs/pstore/ram_core.c ++++ b/fs/pstore/ram_core.c +@@ -439,7 +439,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, + phys_addr_t addr = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(addr >> PAGE_SHIFT); + } +- vaddr = vmap(pages, page_count, VM_MAP, prot); ++ /* ++ * VM_IOREMAP used here to bypass this region during vread() ++ * and kmap_atomic() (i.e. kcore) to avoid __va() failures. ++ */ ++ vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot); + kfree(pages); + + /* +-- +2.35.1 + diff --git a/queue-5.15/pstore-ram-fix-error-return-code-in-ramoops_probe.patch b/queue-5.15/pstore-ram-fix-error-return-code-in-ramoops_probe.patch new file mode 100644 index 00000000000..0b53ba04b8d --- /dev/null +++ b/queue-5.15/pstore-ram-fix-error-return-code-in-ramoops_probe.patch @@ -0,0 +1,45 @@ +From b8cb54da3ead478919cb0c0a0e9091ddb7c6edd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 16:22:54 +0800 +Subject: pstore/ram: Fix error return code in ramoops_probe() + +From: Wang Yufen + +[ Upstream commit e1fce564900f8734edf15b87f028c57e14f6e28d ] + +In the if (dev_of_node(dev) && !pdata) path, the "err" may be assigned a +value of 0, so the error return code -EINVAL may be incorrectly set +to 0. To fix set valid return code before calling to goto. + +Fixes: 35da60941e44 ("pstore/ram: add Device Tree bindings") +Signed-off-by: Wang Yufen +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/1669969374-46582-1-git-send-email-wangyufen@huawei.com +Signed-off-by: Sasha Levin +--- + fs/pstore/ram.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c +index fefe3d391d3a..74e4d93f3e08 100644 +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -735,6 +735,7 @@ static int ramoops_probe(struct platform_device *pdev) + /* Make sure we didn't get bogus platform data pointer. */ + if (!pdata) { + pr_err("NULL platform data\n"); ++ err = -EINVAL; + goto fail_out; + } + +@@ -742,6 +743,7 @@ static int ramoops_probe(struct platform_device *pdev) + !pdata->ftrace_size && !pdata->pmsg_size)) { + pr_err("The memory size and the record/console size must be " + "non-zero\n"); ++ err = -EINVAL; + goto fail_out; + } + +-- +2.35.1 + diff --git a/queue-5.15/pwm-mediatek-always-use-bus-clock-for-pwm-on-mt7622.patch b/queue-5.15/pwm-mediatek-always-use-bus-clock-for-pwm-on-mt7622.patch new file mode 100644 index 00000000000..e6b29a5f6ae --- /dev/null +++ b/queue-5.15/pwm-mediatek-always-use-bus-clock-for-pwm-on-mt7622.patch @@ -0,0 +1,49 @@ +From 4e462f10bb25ee242f26c8a676f3fc35b8b353d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 19:35:08 +0100 +Subject: pwm: mediatek: always use bus clock for PWM on MT7622 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Daniel Golle + +[ Upstream commit aa3c668f2f98856af96e13f44da6ca4f26f0b98c ] + +According to MT7622 Reference Manual for Development Board v1.0 the PWM +unit found in the MT7622 SoC also comes with the PWM_CK_26M_SEL register +at offset 0x210 just like other modern MediaTek ARM64 SoCs. +And also MT7622 sets that register to 0x00000001 on reset which is +described as 'Select 26M fix CLK as BCLK' in the datasheet. +Hence set has_ck_26m_sel to true also for MT7622 which results in the +driver writing 0 to the PWM_CK_26M_SEL register which is described as +'Select bus CLK as BCLK'. + +Fixes: 0c0ead76235db0 ("pwm: mediatek: Always use bus clock") +Signed-off-by: Daniel Golle +Reviewed-by: AngeloGioacchino Del Regno +Acked-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/Y1iF2slvSblf6bYK@makrotopia.org +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-mediatek.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c +index 0d4dd80e9f07..f8f9a7489129 100644 +--- a/drivers/pwm/pwm-mediatek.c ++++ b/drivers/pwm/pwm-mediatek.c +@@ -275,7 +275,7 @@ static const struct pwm_mediatek_of_data mt2712_pwm_data = { + static const struct pwm_mediatek_of_data mt7622_pwm_data = { + .num_pwms = 6, + .pwm45_fixup = false, +- .has_ck_26m_sel = false, ++ .has_ck_26m_sel = true, + }; + + static const struct pwm_mediatek_of_data mt7623_pwm_data = { +-- +2.35.1 + diff --git a/queue-5.15/pwm-mtk-disp-fix-the-parameters-calculated-by-the-en.patch b/queue-5.15/pwm-mtk-disp-fix-the-parameters-calculated-by-the-en.patch new file mode 100644 index 00000000000..6bf968189d5 --- /dev/null +++ b/queue-5.15/pwm-mtk-disp-fix-the-parameters-calculated-by-the-en.patch @@ -0,0 +1,56 @@ +From 412bd8018406f616ef168edc94b8764169b3d229 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 19:35:06 +0100 +Subject: pwm: mtk-disp: Fix the parameters calculated by the enabled flag of + disp_pwm +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: xinlei lee + +[ Upstream commit 0b5ef3429d8f78427558ab0dcbfd862098ba2a63 ] + +In the original mtk_disp_pwm_get_state() function wrongly uses bit 0 of +CON0 to judge if the PWM is enabled. +However that is indicated by a bit (at a machine dependent position) in +the DISP_PWM_EN register. Fix this accordingly. + +Fixes: 3f2b16734914 ("pwm: mtk-disp: Implement atomic API .get_state()") +Signed-off-by: xinlei lee +Reviewed-by: Uwe Kleine-König +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/1666172538-11652-1-git-send-email-xinlei.lee@mediatek.com +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-mtk-disp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/pwm/pwm-mtk-disp.c b/drivers/pwm/pwm-mtk-disp.c +index c605013e4114..3fbb4bae93a4 100644 +--- a/drivers/pwm/pwm-mtk-disp.c ++++ b/drivers/pwm/pwm-mtk-disp.c +@@ -178,7 +178,7 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + { + struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip); + u64 rate, period, high_width; +- u32 clk_div, con0, con1; ++ u32 clk_div, pwm_en, con0, con1; + int err; + + err = clk_prepare_enable(mdp->clk_main); +@@ -197,7 +197,8 @@ static void mtk_disp_pwm_get_state(struct pwm_chip *chip, + rate = clk_get_rate(mdp->clk_main); + con0 = readl(mdp->base + mdp->data->con0); + con1 = readl(mdp->base + mdp->data->con1); +- state->enabled = !!(con0 & BIT(0)); ++ pwm_en = readl(mdp->base + DISP_PWM_EN); ++ state->enabled = !!(pwm_en & mdp->data->enable_mask); + clk_div = FIELD_GET(PWM_CLKDIV_MASK, con0); + period = FIELD_GET(PWM_PERIOD_MASK, con1); + /* +-- +2.35.1 + diff --git a/queue-5.15/pwm-sifive-call-pwm_sifive_update_clock-while-mutex-.patch b/queue-5.15/pwm-sifive-call-pwm_sifive_update_clock-while-mutex-.patch new file mode 100644 index 00000000000..faa72cc553d --- /dev/null +++ b/queue-5.15/pwm-sifive-call-pwm_sifive_update_clock-while-mutex-.patch @@ -0,0 +1,50 @@ +From 5026d626932d5a408d5c69009bbc72c801777914 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 19:35:05 +0100 +Subject: pwm: sifive: Call pwm_sifive_update_clock() while mutex is held +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 45558b3abb87eeb2cedb8a59cb2699c120b5102a ] + +As was documented in commit 0f02f491b786 ("pwm: sifive: Reduce time the +controller lock is held") a caller of pwm_sifive_update_clock() must +hold the mutex. So fix pwm_sifive_clock_notifier() to grab the lock. + +While this necessity was only documented later, the race exists since +the driver was introduced. + +Fixes: 9e37a53eb051 ("pwm: sifive: Add a driver for SiFive SoC PWM") +Reported-by: Emil Renner Berthing +Reviewed-by: Emil Renner Berthing +Link: https://lore.kernel.org/r/20221018061656.1428111-1-u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-sifive.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/pwm/pwm-sifive.c b/drivers/pwm/pwm-sifive.c +index 58347fcd4812..07e9fc58354f 100644 +--- a/drivers/pwm/pwm-sifive.c ++++ b/drivers/pwm/pwm-sifive.c +@@ -217,8 +217,11 @@ static int pwm_sifive_clock_notifier(struct notifier_block *nb, + struct pwm_sifive_ddata *ddata = + container_of(nb, struct pwm_sifive_ddata, notifier); + +- if (event == POST_RATE_CHANGE) ++ if (event == POST_RATE_CHANGE) { ++ mutex_lock(&ddata->lock); + pwm_sifive_update_clock(ddata, ndata->new_rate); ++ mutex_unlock(&ddata->lock); ++ } + + return NOTIFY_OK; + } +-- +2.35.1 + diff --git a/queue-5.15/pwm-tegra-improve-required-rate-calculation.patch b/queue-5.15/pwm-tegra-improve-required-rate-calculation.patch new file mode 100644 index 00000000000..5df67c0e9a1 --- /dev/null +++ b/queue-5.15/pwm-tegra-improve-required-rate-calculation.patch @@ -0,0 +1,52 @@ +From e170338b4bc8ef5d0e0737eb3400eff2411a1644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 28 Oct 2022 13:33:55 +0100 +Subject: pwm: tegra: Improve required rate calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jon Hunter + +[ Upstream commit f271946117dde2ca8741b8138b347b2d68e6ad56 ] + +For the case where dev_pm_opp_set_rate() is called to set the PWM clock +rate, the requested rate is calculated as ... + + required_clk_rate = (NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH; + +The above calculation may lead to rounding errors because the +NSEC_PER_SEC is divided by 'period_ns' before applying the +PWM_DUTY_WIDTH multiplication factor. For example, if the period is +45334ns, the above calculation yields a rate of 5646848Hz instead of +5646976Hz. Fix this by applying the multiplication factor before +dividing and using the DIV_ROUND_UP macro which yields the expected +result of 5646976Hz. + +Fixes: 1d7796bdb63a ("pwm: tegra: Support dynamic clock frequency configuration") +Signed-off-by: Jon Hunter +Reviewed-by: Uwe Kleine-König +Signed-off-by: Thierry Reding +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-tegra.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c +index 11a10b575ace..2735a97906fd 100644 +--- a/drivers/pwm/pwm-tegra.c ++++ b/drivers/pwm/pwm-tegra.c +@@ -142,8 +142,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + * source clock rate as required_clk_rate, PWM controller will + * be able to configure the requested period. + */ +- required_clk_rate = +- (NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH; ++ required_clk_rate = DIV_ROUND_UP_ULL(NSEC_PER_SEC << PWM_DUTY_WIDTH, ++ period_ns); + + err = clk_set_rate(pc->clk, required_clk_rate); + if (err < 0) +-- +2.35.1 + diff --git a/queue-5.15/qed-gcc13-use-u16-for-fid-to-be-big-enough.patch b/queue-5.15/qed-gcc13-use-u16-for-fid-to-be-big-enough.patch new file mode 100644 index 00000000000..3404f892f32 --- /dev/null +++ b/queue-5.15/qed-gcc13-use-u16-for-fid-to-be-big-enough.patch @@ -0,0 +1,53 @@ +From 855c6c70ec26a36cf729a9a1a4b46a49d1307094 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 12:43:54 +0100 +Subject: qed (gcc13): use u16 for fid to be big enough + +From: Jiri Slaby (SUSE) + +[ Upstream commit 7d84118229bf7f7290438c85caa8e49de52d50c1 ] + +gcc 13 correctly reports overflow in qed_grc_dump_addr_range(): +In file included from drivers/net/ethernet/qlogic/qed/qed.h:23, + from drivers/net/ethernet/qlogic/qed/qed_debug.c:10: +drivers/net/ethernet/qlogic/qed/qed_debug.c: In function 'qed_grc_dump_addr_range': +include/linux/qed/qed_if.h:1217:9: error: overflow in conversion from 'int' to 'u8' {aka 'unsigned char'} changes value from '(int)vf_id << 8 | 128' to '128' [-Werror=overflow] + +We do: + u8 fid; + ... + fid = vf_id << 8 | 128; + +Since fid is 16bit (and the stored value above too), fid should be u16, +not u8. Fix that. + +Cc: Martin Liska +Cc: Ariel Elior +Cc: Manish Chopra +Signed-off-by: Jiri Slaby (SUSE) +Link: https://lore.kernel.org/r/20221031114354.10398-1-jirislaby@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qed/qed_debug.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c +index 6ab3e60d4928..4b4077cf2d26 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c +@@ -1796,9 +1796,10 @@ static u32 qed_grc_dump_addr_range(struct qed_hwfn *p_hwfn, + u8 split_id) + { + struct dbg_tools_data *dev_data = &p_hwfn->dbg_info; +- u8 port_id = 0, pf_id = 0, vf_id = 0, fid = 0; ++ u8 port_id = 0, pf_id = 0, vf_id = 0; + bool read_using_dmae = false; + u32 thresh; ++ u16 fid; + + if (!dump) + return len; +-- +2.35.1 + diff --git a/queue-5.15/r6040-fix-kmemleak-in-probe-and-remove.patch b/queue-5.15/r6040-fix-kmemleak-in-probe-and-remove.patch new file mode 100644 index 00000000000..ae728da7e92 --- /dev/null +++ b/queue-5.15/r6040-fix-kmemleak-in-probe-and-remove.patch @@ -0,0 +1,96 @@ +From 4f5145bc554c60ae0da0f8cc48dda01f3f0a54a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 20:56:14 +0800 +Subject: r6040: Fix kmemleak in probe and remove + +From: Li Zetao + +[ Upstream commit 7e43039a49c2da45edc1d9d7c9ede4003ab45a5f ] + +There is a memory leaks reported by kmemleak: + + unreferenced object 0xffff888116111000 (size 2048): + comm "modprobe", pid 817, jiffies 4294759745 (age 76.502s) + hex dump (first 32 bytes): + 00 c4 0a 04 81 88 ff ff 08 10 11 16 81 88 ff ff ................ + 08 10 11 16 81 88 ff ff 00 00 00 00 00 00 00 00 ................ + backtrace: + [] kmalloc_trace+0x22/0x60 + [] phy_device_create+0x4e/0x90 + [] get_phy_device+0xd2/0x220 + [] mdiobus_scan+0xa4/0x2e0 + [] __mdiobus_register+0x482/0x8b0 + [] r6040_init_one+0x714/0xd2c [r6040] + ... + +The problem occurs in probe process as follows: + r6040_init_one: + mdiobus_register + mdiobus_scan <- alloc and register phy_device, + the reference count of phy_device is 3 + r6040_mii_probe + phy_connect <- connect to the first phy_device, + so the reference count of the first + phy_device is 4, others are 3 + register_netdev <- fault inject succeeded, goto error handling path + + // error handling path + err_out_mdio_unregister: + mdiobus_unregister(lp->mii_bus); + err_out_mdio: + mdiobus_free(lp->mii_bus); <- the reference count of the first + phy_device is 1, it is not released + and other phy_devices are released + // similarly, the remove process also has the same problem + +The root cause is traced to the phy_device is not disconnected when +removes one r6040 device in r6040_remove_one() or on error handling path +after r6040_mii probed successfully. In r6040_mii_probe(), a net ethernet +device is connected to the first PHY device of mii_bus, in order to +notify the connected driver when the link status changes, which is the +default behavior of the PHY infrastructure to handle everything. +Therefore the phy_device should be disconnected when removes one r6040 +device or on error handling path. + +Fix it by adding phy_disconnect() when removes one r6040 device or on +error handling path after r6040_mii probed successfully. + +Fixes: 3831861b4ad8 ("r6040: implement phylib") +Signed-off-by: Li Zetao +Reviewed-by: Leon Romanovsky +Link: https://lore.kernel.org/r/20221213125614.927754-1-lizetao1@huawei.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/rdc/r6040.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/rdc/r6040.c b/drivers/net/ethernet/rdc/r6040.c +index 01ef5efd7bc2..5a8a6977ec9a 100644 +--- a/drivers/net/ethernet/rdc/r6040.c ++++ b/drivers/net/ethernet/rdc/r6040.c +@@ -1159,10 +1159,12 @@ static int r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Failed to register net device\n"); +- goto err_out_mdio_unregister; ++ goto err_out_phy_disconnect; + } + return 0; + ++err_out_phy_disconnect: ++ phy_disconnect(dev->phydev); + err_out_mdio_unregister: + mdiobus_unregister(lp->mii_bus); + err_out_mdio: +@@ -1186,6 +1188,7 @@ static void r6040_remove_one(struct pci_dev *pdev) + struct r6040_private *lp = netdev_priv(dev); + + unregister_netdev(dev); ++ phy_disconnect(dev->phydev); + mdiobus_unregister(lp->mii_bus); + mdiobus_free(lp->mii_bus); + netif_napi_del(&lp->napi); +-- +2.35.1 + diff --git a/queue-5.15/rapidio-devices-fix-missing-put_device-in-mport_cdev.patch b/queue-5.15/rapidio-devices-fix-missing-put_device-in-mport_cdev.patch new file mode 100644 index 00000000000..583c196c35d --- /dev/null +++ b/queue-5.15/rapidio-devices-fix-missing-put_device-in-mport_cdev.patch @@ -0,0 +1,44 @@ +From 8841eae2afebb12268598377e811b9f59468257b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 3 Dec 2022 08:57:21 +0000 +Subject: rapidio: devices: fix missing put_device in mport_cdev_open + +From: Cai Xinchen + +[ Upstream commit d5b6e6eba3af11cb2a2791fa36a2524990fcde1a ] + +When kfifo_alloc fails, the refcount of chdev->dev is left incremental. +We should use put_device(&chdev->dev) to decrease the ref count of +chdev->dev to avoid refcount leak. + +Link: https://lkml.kernel.org/r/20221203085721.13146-1-caixinchen1@huawei.com +Fixes: e8de370188d0 ("rapidio: add mport char device driver") +Signed-off-by: Cai Xinchen +Cc: Alexandre Bounine +Cc: Dan Carpenter +Cc: Jakob Koschel +Cc: John Hubbard +Cc: Matt Porter +Cc: Wang Weiyang +Cc: Yang Yingliang +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + drivers/rapidio/devices/rio_mport_cdev.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c +index b8c09eaa23b5..5ac2dc1e2abd 100644 +--- a/drivers/rapidio/devices/rio_mport_cdev.c ++++ b/drivers/rapidio/devices/rio_mport_cdev.c +@@ -1911,6 +1911,7 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + sizeof(struct rio_event) * MPORT_EVENT_DEPTH, + GFP_KERNEL); + if (ret < 0) { ++ put_device(&chdev->dev); + dev_err(&chdev->dev, DRV_NAME ": kfifo_alloc failed\n"); + ret = -ENOMEM; + goto err_fifo; +-- +2.35.1 + diff --git a/queue-5.15/rapidio-fix-possible-name-leaks-when-rio_add_device-.patch b/queue-5.15/rapidio-fix-possible-name-leaks-when-rio_add_device-.patch new file mode 100644 index 00000000000..424aff7dfee --- /dev/null +++ b/queue-5.15/rapidio-fix-possible-name-leaks-when-rio_add_device-.patch @@ -0,0 +1,76 @@ +From 0fea007f02b279994882a5f5331e97897949dd69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 23:26:35 +0800 +Subject: rapidio: fix possible name leaks when rio_add_device() fails + +From: Yang Yingliang + +[ Upstream commit f9574cd48679926e2a569e1957a5a1bcc8a719ac ] + +Patch series "rapidio: fix three possible memory leaks". + +This patchset fixes three name leaks in error handling. + - patch #1 fixes two name leaks while rio_add_device() fails. + - patch #2 fixes a name leak while rio_register_mport() fails. + +This patch (of 2): + +If rio_add_device() returns error, the name allocated by dev_set_name() +need be freed. It should use put_device() to give up the reference in the +error path, so that the name can be freed in kobject_cleanup(), and the +'rdev' can be freed in rio_release_dev(). + +Link: https://lkml.kernel.org/r/20221114152636.2939035-1-yangyingliang@huawei.com +Link: https://lkml.kernel.org/r/20221114152636.2939035-2-yangyingliang@huawei.com +Fixes: e8de370188d0 ("rapidio: add mport char device driver") +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Cc: Alexandre Bounine +Cc: Matt Porter +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + drivers/rapidio/devices/rio_mport_cdev.c | 7 +++++-- + drivers/rapidio/rio-scan.c | 8 ++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c +index 94331d999d27..48cd9b7f3b89 100644 +--- a/drivers/rapidio/devices/rio_mport_cdev.c ++++ b/drivers/rapidio/devices/rio_mport_cdev.c +@@ -1803,8 +1803,11 @@ static int rio_mport_add_riodev(struct mport_cdev_priv *priv, + rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE], + 0, 0xffff); + err = rio_add_device(rdev); +- if (err) +- goto cleanup; ++ if (err) { ++ put_device(&rdev->dev); ++ return err; ++ } ++ + rio_dev_get(rdev); + + return 0; +diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c +index 19b0c33f4a62..fdcf742b2adb 100644 +--- a/drivers/rapidio/rio-scan.c ++++ b/drivers/rapidio/rio-scan.c +@@ -454,8 +454,12 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, + 0, 0xffff); + + ret = rio_add_device(rdev); +- if (ret) +- goto cleanup; ++ if (ret) { ++ if (rswitch) ++ kfree(rswitch->route_table); ++ put_device(&rdev->dev); ++ return NULL; ++ } + + rio_dev_get(rdev); + +-- +2.35.1 + diff --git a/queue-5.15/rapidio-fix-possible-uaf-when-kfifo_alloc-fails.patch b/queue-5.15/rapidio-fix-possible-uaf-when-kfifo_alloc-fails.patch new file mode 100644 index 00000000000..1b1baf359aa --- /dev/null +++ b/queue-5.15/rapidio-fix-possible-uaf-when-kfifo_alloc-fails.patch @@ -0,0 +1,58 @@ +From a266e1311d2dfc362c8df90bd1cfec880c98638b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 17:51:47 +0800 +Subject: rapidio: fix possible UAF when kfifo_alloc() fails + +From: Wang Weiyang + +[ Upstream commit 02d7d89f816951e0862147d751b1150d67aaebdd ] + +If kfifo_alloc() fails in mport_cdev_open(), goto err_fifo and just free +priv. But priv is still in the chdev->file_list, then list traversal +may cause UAF. This fixes the following smatch warning: + +drivers/rapidio/devices/rio_mport_cdev.c:1930 mport_cdev_open() warn: '&priv->list' not removed from list + +Link: https://lkml.kernel.org/r/20221123095147.52408-1-wangweiyang2@huawei.com +Fixes: e8de370188d0 ("rapidio: add mport char device driver") +Signed-off-by: Wang Weiyang +Cc: Alexandre Bounine +Cc: Dan Carpenter +Cc: Jakob Koschel +Cc: John Hubbard +Cc: Matt Porter +Cc: Yang Yingliang +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + drivers/rapidio/devices/rio_mport_cdev.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c +index 48cd9b7f3b89..b8c09eaa23b5 100644 +--- a/drivers/rapidio/devices/rio_mport_cdev.c ++++ b/drivers/rapidio/devices/rio_mport_cdev.c +@@ -1903,10 +1903,6 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + + priv->md = chdev; + +- mutex_lock(&chdev->file_mutex); +- list_add_tail(&priv->list, &chdev->file_list); +- mutex_unlock(&chdev->file_mutex); +- + INIT_LIST_HEAD(&priv->db_filters); + INIT_LIST_HEAD(&priv->pw_filters); + spin_lock_init(&priv->fifo_lock); +@@ -1925,6 +1921,9 @@ static int mport_cdev_open(struct inode *inode, struct file *filp) + spin_lock_init(&priv->req_lock); + mutex_init(&priv->dma_lock); + #endif ++ mutex_lock(&chdev->file_mutex); ++ list_add_tail(&priv->list, &chdev->file_list); ++ mutex_unlock(&chdev->file_mutex); + + filp->private_data = priv; + goto out; +-- +2.35.1 + diff --git a/queue-5.15/rapidio-rio-fix-possible-name-leak-in-rio_register_m.patch b/queue-5.15/rapidio-rio-fix-possible-name-leak-in-rio_register_m.patch new file mode 100644 index 00000000000..e02f6ddaa9a --- /dev/null +++ b/queue-5.15/rapidio-rio-fix-possible-name-leak-in-rio_register_m.patch @@ -0,0 +1,51 @@ +From f15583ba9aad6eb2a50c21b58ea9d3127d3c9a54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 23:26:36 +0800 +Subject: rapidio: rio: fix possible name leak in rio_register_mport() + +From: Yang Yingliang + +[ Upstream commit e92a216d16bde65d21a3227e0fb2aa0794576525 ] + +If device_register() returns error, the name allocated by dev_set_name() +need be freed. It should use put_device() to give up the reference in the +error path, so that the name can be freed in kobject_cleanup(), and +list_del() is called to delete the port from rio_mports. + +Link: https://lkml.kernel.org/r/20221114152636.2939035-3-yangyingliang@huawei.com +Fixes: 2aaf308b95b2 ("rapidio: rework device hierarchy and introduce mport class of devices") +Signed-off-by: Yang Yingliang +Cc: Alexandre Bounine +Cc: Matt Porter +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + drivers/rapidio/rio.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c +index e74cf09eeff0..9544b8ee0c96 100644 +--- a/drivers/rapidio/rio.c ++++ b/drivers/rapidio/rio.c +@@ -2186,11 +2186,16 @@ int rio_register_mport(struct rio_mport *port) + atomic_set(&port->state, RIO_DEVICE_RUNNING); + + res = device_register(&port->dev); +- if (res) ++ if (res) { + dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n", + port->id, res); +- else ++ mutex_lock(&rio_mport_list_lock); ++ list_del(&port->node); ++ mutex_unlock(&rio_mport_list_lock); ++ put_device(&port->dev); ++ } else { + dev_dbg(&port->dev, "RIO: registered mport%d\n", port->id); ++ } + + return res; + } +-- +2.35.1 + diff --git a/queue-5.15/rcu-fix-__this_cpu_read-lockdep-warning-in-rcu_force.patch b/queue-5.15/rcu-fix-__this_cpu_read-lockdep-warning-in-rcu_force.patch new file mode 100644 index 00000000000..4c354d90427 --- /dev/null +++ b/queue-5.15/rcu-fix-__this_cpu_read-lockdep-warning-in-rcu_force.patch @@ -0,0 +1,60 @@ +From b27cb0c3865a1519e06776d3c8dbc203a26efabe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 12:41:48 +0800 +Subject: rcu: Fix __this_cpu_read() lockdep warning in + rcu_force_quiescent_state() + +From: Zqiang + +[ Upstream commit ceb1c8c9b8aa9199da46a0f29d2d5f08d9b44c15 ] + +Running rcutorture with non-zero fqs_duration module parameter in a +kernel built with CONFIG_PREEMPTION=y results in the following splat: + +BUG: using __this_cpu_read() in preemptible [00000000] +code: rcu_torture_fqs/398 +caller is __this_cpu_preempt_check+0x13/0x20 +CPU: 3 PID: 398 Comm: rcu_torture_fqs Not tainted 6.0.0-rc1-yoctodev-standard+ +Call Trace: + +dump_stack_lvl+0x5b/0x86 +dump_stack+0x10/0x16 +check_preemption_disabled+0xe5/0xf0 +__this_cpu_preempt_check+0x13/0x20 +rcu_force_quiescent_state.part.0+0x1c/0x170 +rcu_force_quiescent_state+0x1e/0x30 +rcu_torture_fqs+0xca/0x160 +? rcu_torture_boost+0x430/0x430 +kthread+0x192/0x1d0 +? kthread_complete_and_exit+0x30/0x30 +ret_from_fork+0x22/0x30 + + +The problem is that rcu_force_quiescent_state() uses __this_cpu_read() +in preemptible code instead of the proper raw_cpu_read(). This commit +therefore changes __this_cpu_read() to raw_cpu_read(). + +Signed-off-by: Zqiang +Reviewed-by: Joel Fernandes (Google) +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + kernel/rcu/tree.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index 63f7ce228cc3..cf101da389b0 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -2674,7 +2674,7 @@ void rcu_force_quiescent_state(void) + struct rcu_node *rnp_old = NULL; + + /* Funnel through hierarchy to reduce memory contention. */ +- rnp = __this_cpu_read(rcu_data.mynode); ++ rnp = raw_cpu_read(rcu_data.mynode); + for (; rnp != NULL; rnp = rnp->parent) { + ret = (READ_ONCE(rcu_state.gp_flags) & RCU_GP_FLAG_FQS) || + !raw_spin_trylock(&rnp->fqslock); +-- +2.35.1 + diff --git a/queue-5.15/rdma-core-fix-order-of-nldev_exit-call.patch b/queue-5.15/rdma-core-fix-order-of-nldev_exit-call.patch new file mode 100644 index 00000000000..681fa2f0db0 --- /dev/null +++ b/queue-5.15/rdma-core-fix-order-of-nldev_exit-call.patch @@ -0,0 +1,38 @@ +From f0cf1ccd82bc4a1602515ad7248a6dc180ab2e91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 10:37:13 +0300 +Subject: RDMA/core: Fix order of nldev_exit call + +From: Leon Romanovsky + +[ Upstream commit 4508d32ccced24c972bc4592104513e1ff8439b5 ] + +Create symmetrical exit flow by calling to nldev_exit() after +call to rdma_nl_unregister(RDMA_NL_LS). + +Fixes: 6c80b41abe22 ("RDMA/netlink: Add nldev initialization flows") +Signed-off-by: Leon Romanovsky +Link: https://lore.kernel.org/r/64e676774a53a406f4cde265d5a4cfd6b8e97df9.1666683334.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c +index 1519379b116e..ab2106a09f9c 100644 +--- a/drivers/infiniband/core/device.c ++++ b/drivers/infiniband/core/device.c +@@ -2848,8 +2848,8 @@ static int __init ib_core_init(void) + static void __exit ib_core_cleanup(void) + { + roce_gid_mgmt_cleanup(); +- nldev_exit(); + rdma_nl_unregister(RDMA_NL_LS); ++ nldev_exit(); + unregister_pernet_device(&rdma_dev_net_ops); + unregister_blocking_lsm_notifier(&ibdev_lsm_nb); + ib_sa_cleanup(); +-- +2.35.1 + diff --git a/queue-5.15/rdma-core-make-sure-ib_port-is-valid-when-access-sys.patch b/queue-5.15/rdma-core-make-sure-ib_port-is-valid-when-access-sys.patch new file mode 100644 index 00000000000..28c802b1177 --- /dev/null +++ b/queue-5.15/rdma-core-make-sure-ib_port-is-valid-when-access-sys.patch @@ -0,0 +1,130 @@ +From 4c6788e6ac951f3b2611198edaf2889f6a4cef2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 10:51:35 +0200 +Subject: RDMA/core: Make sure "ib_port" is valid when access sysfs node + +From: Mark Zhang + +[ Upstream commit 5e15ff29b156bbbdeadae230c8ecd5ecd8ca2477 ] + +The "ib_port" structure must be set before adding the sysfs kobject, +and reset after removing it, otherwise it may crash when accessing +the sysfs node: + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000050 + Mem abort info: + ESR = 0x96000006 + Exception class = DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + Data abort info: + ISV = 0, ISS = 0x00000006 + CM = 0, WnR = 0 + user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000e85f5ba5 + [0000000000000050] pgd=0000000848fd9003, pud=000000085b387003, pmd=0000000000000000 + Internal error: Oops: 96000006 [#2] PREEMPT SMP + Modules linked in: ib_umad(O) mlx5_ib(O) nfnetlink_cttimeout(E) nfnetlink(E) act_gact(E) cls_flower(E) sch_ingress(E) openvswitch(E) nsh(E) nf_nat_ipv6(E) nf_nat_ipv4(E) nf_conncount(E) nf_nat(E) nf_conntrack(E) nf_defrag_ipv6(E) nf_defrag_ipv4(E) mst_pciconf(O) ipmi_devintf(E) ipmi_msghandler(E) ipmb_dev_int(OE) mlx5_core(O) mlxfw(O) mlxdevm(O) auxiliary(O) ib_uverbs(O) ib_core(O) mlx_compat(O) psample(E) sbsa_gwdt(E) uio_pdrv_genirq(E) uio(E) mlxbf_pmc(OE) mlxbf_gige(OE) mlxbf_tmfifo(OE) gpio_mlxbf2(OE) pwr_mlxbf(OE) mlx_trio(OE) i2c_mlxbf(OE) mlx_bootctl(OE) bluefield_edac(OE) knem(O) ip_tables(E) ipv6(E) crc_ccitt(E) [last unloaded: mst_pci] + Process grep (pid: 3372, stack limit = 0x0000000022055c92) + CPU: 5 PID: 3372 Comm: grep Tainted: G D OE 4.19.161-mlnx.47.gadcd9e3 #1 + Hardware name: https://www.mellanox.com BlueField SoC/BlueField SoC, BIOS BlueField:3.9.2-15-ga2403ab Sep 8 2022 + pstate: 40000005 (nZcv daif -PAN -UAO) + pc : hw_stat_port_show+0x4c/0x80 [ib_core] + lr : port_attr_show+0x40/0x58 [ib_core] + sp : ffff000029f43b50 + x29: ffff000029f43b50 x28: 0000000019375000 + x27: ffff8007b821a540 x26: ffff000029f43e30 + x25: 0000000000008000 x24: ffff000000eaa958 + x23: 0000000000001000 x22: ffff8007a4ce3000 + x21: ffff8007baff8000 x20: ffff8007b9066ac0 + x19: ffff8007bae97578 x18: 0000000000000000 + x17: 0000000000000000 x16: 0000000000000000 + x15: 0000000000000000 x14: 0000000000000000 + x13: 0000000000000000 x12: 0000000000000000 + x11: 0000000000000000 x10: 0000000000000000 + x9 : 0000000000000000 x8 : ffff8007a4ce4000 + x7 : 0000000000000000 x6 : 000000000000003f + x5 : ffff000000e6a280 x4 : ffff8007a4ce3000 + x3 : 0000000000000000 x2 : aaaaaaaaaaaaaaab + x1 : ffff8007b9066a10 x0 : ffff8007baff8000 + Call trace: + hw_stat_port_show+0x4c/0x80 [ib_core] + port_attr_show+0x40/0x58 [ib_core] + sysfs_kf_seq_show+0x8c/0x150 + kernfs_seq_show+0x44/0x50 + seq_read+0x1b4/0x45c + kernfs_fop_read+0x148/0x1d8 + __vfs_read+0x58/0x180 + vfs_read+0x94/0x154 + ksys_read+0x68/0xd8 + __arm64_sys_read+0x28/0x34 + el0_svc_common+0x88/0x18c + el0_svc_handler+0x78/0x94 + el0_svc+0x8/0xe8 + Code: f2955562 aa1603e4 aa1503e0 f9405683 (f9402861) + +Fixes: d8a5883814b9 ("RDMA/core: Replace the ib_port_data hw_stats pointers with a ib_port pointer") +Signed-off-by: Mark Zhang +Reviewed-by: Michael Guralnik +Link: https://lore.kernel.org/r/88867e705c42c1cd2011e45201c25eecdb9fef94.1667810736.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/sysfs.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c +index 8d709986b88c..253ccaf343f6 100644 +--- a/drivers/infiniband/core/sysfs.c ++++ b/drivers/infiniband/core/sysfs.c +@@ -1198,6 +1198,9 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + p->port_num = port_num; + kobject_init(&p->kobj, &port_type); + ++ if (device->port_data && is_full_dev) ++ device->port_data[port_num].sysfs = p; ++ + cur_group = p->groups_list; + ret = alloc_port_table_group("gids", &p->groups[0], p->attrs_list, + attr->gid_tbl_len, show_port_gid); +@@ -1243,9 +1246,6 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + } + + list_add_tail(&p->kobj.entry, &coredev->port_list); +- if (device->port_data && is_full_dev) +- device->port_data[port_num].sysfs = p; +- + return p; + + err_groups: +@@ -1253,6 +1253,8 @@ static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num, + err_del: + kobject_del(&p->kobj); + err_put: ++ if (device->port_data && is_full_dev) ++ device->port_data[port_num].sysfs = NULL; + kobject_put(&p->kobj); + return ERR_PTR(ret); + } +@@ -1261,14 +1263,17 @@ static void destroy_port(struct ib_core_device *coredev, struct ib_port *port) + { + bool is_full_dev = &port->ibdev->coredev == coredev; + +- if (port->ibdev->port_data && +- port->ibdev->port_data[port->port_num].sysfs == port) +- port->ibdev->port_data[port->port_num].sysfs = NULL; + list_del(&port->kobj.entry); + if (is_full_dev) + sysfs_remove_groups(&port->kobj, port->ibdev->ops.port_groups); ++ + sysfs_remove_groups(&port->kobj, port->groups_list); + kobject_del(&port->kobj); ++ ++ if (port->ibdev->port_data && ++ port->ibdev->port_data[port->port_num].sysfs == port) ++ port->ibdev->port_data[port->port_num].sysfs = NULL; ++ + kobject_put(&port->kobj); + } + +-- +2.35.1 + diff --git a/queue-5.15/rdma-hfi-decrease-pci-device-reference-count-in-erro.patch b/queue-5.15/rdma-hfi-decrease-pci-device-reference-count-in-erro.patch new file mode 100644 index 00000000000..21b79c9a144 --- /dev/null +++ b/queue-5.15/rdma-hfi-decrease-pci-device-reference-count-in-erro.patch @@ -0,0 +1,42 @@ +From 7fd5b25edbca71a2528bf60f02c419d49c18deb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 21:15:46 +0800 +Subject: RDMA/hfi: Decrease PCI device reference count in error path + +From: Xiongfeng Wang + +[ Upstream commit 9b51d072da1d27e1193e84708201c48e385ad912 ] + +pci_get_device() will increase the reference count for the returned +pci_dev, and also decrease the reference count for the input parameter +*from* if it is not NULL. + +If we break out the loop in node_affinity_init() with 'dev' not NULL, we +need to call pci_dev_put() to decrease the reference count. Add missing +pci_dev_put() in error path. + +Fixes: c513de490f80 ("IB/hfi1: Invalid NUMA node information can cause a divide by zero") +Signed-off-by: Xiongfeng Wang +Link: https://lore.kernel.org/r/20221117131546.113280-1-wangxiongfeng2@huawei.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hfi1/affinity.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c +index 98c813ba4304..4c403d9e90cb 100644 +--- a/drivers/infiniband/hw/hfi1/affinity.c ++++ b/drivers/infiniband/hw/hfi1/affinity.c +@@ -178,6 +178,8 @@ int node_affinity_init(void) + for (node = 0; node < node_affinity.num_possible_nodes; node++) + hfi1_per_node_cntr[node] = 1; + ++ pci_dev_put(dev); ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/rdma-hfi1-fix-error-return-code-in-parse_platform_co.patch b/queue-5.15/rdma-hfi1-fix-error-return-code-in-parse_platform_co.patch new file mode 100644 index 00000000000..ae087d6b6a5 --- /dev/null +++ b/queue-5.15/rdma-hfi1-fix-error-return-code-in-parse_platform_co.patch @@ -0,0 +1,78 @@ +From a2227b017806f5c93f7c9cdffc9142f3539bb71d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 12:00:37 +0800 +Subject: RDMA/hfi1: Fix error return code in parse_platform_config() + +From: Wang Yufen + +[ Upstream commit 725349f8ba1e78a146c6ff8f3ee5e2712e517106 ] + +In the previous iteration of the while loop, the "ret" may have been +assigned a value of 0, so the error return code -EINVAL may have been +incorrectly set to 0. To fix set valid return code before calling to +goto. + +Fixes: 97167e813415 ("staging/rdma/hfi1: Tune for unknown channel if configuration file is absent") +Signed-off-by: Wang Yufen +Link: https://lore.kernel.org/r/1669953638-11747-1-git-send-email-wangyufen@huawei.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hfi1/firmware.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/infiniband/hw/hfi1/firmware.c b/drivers/infiniband/hw/hfi1/firmware.c +index 31e63e245ea9..ddf3217893f8 100644 +--- a/drivers/infiniband/hw/hfi1/firmware.c ++++ b/drivers/infiniband/hw/hfi1/firmware.c +@@ -1744,6 +1744,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + + if (!dd->platform_config.data) { + dd_dev_err(dd, "%s: Missing config file\n", __func__); ++ ret = -EINVAL; + goto bail; + } + ptr = (u32 *)dd->platform_config.data; +@@ -1752,6 +1753,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + ptr++; + if (magic_num != PLATFORM_CONFIG_MAGIC_NUM) { + dd_dev_err(dd, "%s: Bad config file\n", __func__); ++ ret = -EINVAL; + goto bail; + } + +@@ -1775,6 +1777,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + if (file_length > dd->platform_config.size) { + dd_dev_info(dd, "%s:File claims to be larger than read size\n", + __func__); ++ ret = -EINVAL; + goto bail; + } else if (file_length < dd->platform_config.size) { + dd_dev_info(dd, +@@ -1795,6 +1798,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + dd_dev_err(dd, "%s: Failed validation at offset %ld\n", + __func__, (ptr - (u32 *) + dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; + } + +@@ -1838,6 +1842,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + __func__, table_type, + (ptr - (u32 *) + dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; /* We don't trust this file now */ + } + pcfgcache->config_tables[table_type].table = ptr; +@@ -1857,6 +1862,7 @@ int parse_platform_config(struct hfi1_devdata *dd) + __func__, table_type, + (ptr - + (u32 *)dd->platform_config.data)); ++ ret = -EINVAL; + goto bail; /* We don't trust this file now */ + } + pcfgcache->config_tables[table_type].table_metadata = +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-ah-attr-queried-by-query_qp.patch b/queue-5.15/rdma-hns-fix-ah-attr-queried-by-query_qp.patch new file mode 100644 index 00000000000..333d43ddfa6 --- /dev/null +++ b/queue-5.15/rdma-hns-fix-ah-attr-queried-by-query_qp.patch @@ -0,0 +1,52 @@ +From 69475aaa1ed1b87af38632997f070d5fc7d31d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 18:29:07 +0800 +Subject: RDMA/hns: Fix AH attr queried by query_qp + +From: Chengchang Tang + +[ Upstream commit bc34c04f7b97c3794dec5a6d6d27ffd5f0e4f5c8 ] + +The queried AH attr is invalid. This patch fix it. + +This problem is found by rdma-core test test_mr_rereg_pd + +ERROR: test_mr_rereg_pd (tests.test_mr.MRTest) +Test that cover rereg MR's PD with this flow: +---------------------------------------------------------------------- +Traceback (most recent call last): + File "./tests/test_mr.py", line 157, in test_mr_rereg_pd + self.restate_qps() + File "./tests/test_mr.py", line 113, in restate_qps + self.server.qp.to_rts(self.server_qp_attr) + File "qp.pyx", line 1137, in pyverbs.qp.QP.to_rts + File "qp.pyx", line 1123, in pyverbs.qp.QP.to_rtr +pyverbs.pyverbs_error.PyverbsRDMAError: Failed to modify QP state to RTR. +Errno: 22, Invalid argument + +Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC") +Link: https://lore.kernel.org/r/20221126102911.2921820-3-xuhaoyue1@hisilicon.com +Signed-off-by: Chengchang Tang +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 94f3a0a87dfd..155ae202b1ec 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -5129,6 +5129,8 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, + + rdma_ah_set_sl(&qp_attr->ah_attr, + hr_reg_read(&context, QPC_SL)); ++ rdma_ah_set_port_num(&qp_attr->ah_attr, hr_qp->port + 1); ++ rdma_ah_set_ah_flags(&qp_attr->ah_attr, IB_AH_GRH); + grh->flow_label = hr_reg_read(&context, QPC_FL); + grh->sgid_index = hr_reg_read(&context, QPC_GMV_IDX); + grh->hop_limit = hr_reg_read(&context, QPC_HOPLIMIT); +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-error-code-of-cmd.patch b/queue-5.15/rdma-hns-fix-error-code-of-cmd.patch new file mode 100644 index 00000000000..e4565db97e6 --- /dev/null +++ b/queue-5.15/rdma-hns-fix-error-code-of-cmd.patch @@ -0,0 +1,86 @@ +From f80378cf7ddb80d71b0fef925165f33af51c9097 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 18:29:10 +0800 +Subject: RDMA/hns: Fix error code of CMD + +From: Chengchang Tang + +[ Upstream commit 667d6164b84884c64de3fc18670cd5a98b0b10cf ] + +The error code is fixed to EIO when CMD fails to excute. This patch +converts the error status reported by firmware to linux errno. + +Fixes: a04ff739f2a9 ("RDMA/hns: Add command queue support for hip08 RoCE driver") +Link: https://lore.kernel.org/r/20221126102911.2921820-6-xuhaoyue1@hisilicon.com +Signed-off-by: Chengchang Tang +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 26 +++++++++++++++++++++- + drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 5 +++++ + 2 files changed, 30 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 16f39321b319..79d92b789984 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -1257,6 +1257,30 @@ static void update_cmdq_status(struct hns_roce_dev *hr_dev) + hr_dev->cmd.state = HNS_ROCE_CMDQ_STATE_FATAL_ERR; + } + ++static int hns_roce_cmd_err_convert_errno(u16 desc_ret) ++{ ++ struct hns_roce_cmd_errcode errcode_table[] = { ++ {CMD_EXEC_SUCCESS, 0}, ++ {CMD_NO_AUTH, -EPERM}, ++ {CMD_NOT_EXIST, -EOPNOTSUPP}, ++ {CMD_CRQ_FULL, -EXFULL}, ++ {CMD_NEXT_ERR, -ENOSR}, ++ {CMD_NOT_EXEC, -ENOTBLK}, ++ {CMD_PARA_ERR, -EINVAL}, ++ {CMD_RESULT_ERR, -ERANGE}, ++ {CMD_TIMEOUT, -ETIME}, ++ {CMD_HILINK_ERR, -ENOLINK}, ++ {CMD_INFO_ILLEGAL, -ENXIO}, ++ {CMD_INVALID, -EBADR}, ++ }; ++ u16 i; ++ ++ for (i = 0; i < ARRAY_SIZE(errcode_table); i++) ++ if (desc_ret == errcode_table[i].return_status) ++ return errcode_table[i].errno; ++ return -EIO; ++} ++ + static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, + struct hns_roce_cmq_desc *desc, int num) + { +@@ -1301,7 +1325,7 @@ static int __hns_roce_cmq_send(struct hns_roce_dev *hr_dev, + dev_err_ratelimited(hr_dev->dev, + "Cmdq IO error, opcode = %x, return = %x\n", + desc->opcode, desc_ret); +- ret = -EIO; ++ ret = hns_roce_cmd_err_convert_errno(desc_ret); + } + } else { + /* FW/HW reset or incorrect number of desc */ +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +index 2f4a0019a716..67f5b6fcfa1b 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +@@ -276,6 +276,11 @@ enum hns_roce_cmd_return_status { + CMD_OTHER_ERR = 0xff + }; + ++struct hns_roce_cmd_errcode { ++ enum hns_roce_cmd_return_status return_status; ++ int errno; ++}; ++ + enum hns_roce_sgid_type { + GID_TYPE_FLAG_ROCE_V1 = 0, + GID_TYPE_FLAG_ROCE_V2_IPV4, +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-ext_sge-num-error-when-post-send.patch b/queue-5.15/rdma-hns-fix-ext_sge-num-error-when-post-send.patch new file mode 100644 index 00000000000..8798c7d5031 --- /dev/null +++ b/queue-5.15/rdma-hns-fix-ext_sge-num-error-when-post-send.patch @@ -0,0 +1,69 @@ +From fff83da88e4f284779e7980cde1179ea251d017f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 21:38:46 +0800 +Subject: RDMA/hns: Fix ext_sge num error when post send + +From: Luoyouming + +[ Upstream commit 8eaa6f7d569b4a22bfc1b0a3fdfeeb401feb65a4 ] + +In the HNS ROCE driver, The sge is divided into standard sge and extended +sge. There are 2 standard sge in RC/XRC, and the UD standard sge is 0. +In the scenario of RC SQ inline, if the data does not exceed 32bytes, the +standard sge will be used. If it exceeds, only the extended sge will be +used to fill the data. + +Currently, when filling the extended sge, max_gs is directly used as the +number of the extended sge, which did not subtract the number of standard +sge. There is a logical error. The new algorithm subtracts the number of +standard sge from max_gs to get the actual number of extended sge. + +Fixes: 30b707886aeb ("RDMA/hns: Support inline data in extented sge space for RC") +Link: https://lore.kernel.org/r/20221108133847.2304539-2-xuhaoyue1@hisilicon.com +Signed-off-by: Luoyouming +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 5875ccf86f66..94f3a0a87dfd 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -151,20 +151,29 @@ static void set_atomic_seg(const struct ib_send_wr *wr, + hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SGE_NUM, valid_num_sge); + } + ++static unsigned int get_std_sge_num(struct hns_roce_qp *qp) ++{ ++ if (qp->ibqp.qp_type == IB_QPT_GSI || qp->ibqp.qp_type == IB_QPT_UD) ++ return 0; ++ ++ return HNS_ROCE_SGE_IN_WQE; ++} ++ + static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + const struct ib_send_wr *wr, + unsigned int *sge_idx, u32 msg_len) + { + struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev; +- unsigned int ext_sge_sz = qp->sq.max_gs * HNS_ROCE_SGE_SIZE; + unsigned int left_len_in_pg; + unsigned int idx = *sge_idx; ++ unsigned int std_sge_num; + unsigned int i = 0; + unsigned int len; + void *addr; + void *dseg; + +- if (msg_len > ext_sge_sz) { ++ std_sge_num = get_std_sge_num(qp); ++ if (msg_len > (qp->sq.max_gs - std_sge_num) * HNS_ROCE_SGE_SIZE) { + ibdev_err(ibdev, + "no enough extended sge space for inline data.\n"); + return -EINVAL; +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-memory-leak-in-hns_roce_alloc_mr.patch b/queue-5.15/rdma-hns-fix-memory-leak-in-hns_roce_alloc_mr.patch new file mode 100644 index 00000000000..0bba57ec652 --- /dev/null +++ b/queue-5.15/rdma-hns-fix-memory-leak-in-hns_roce_alloc_mr.patch @@ -0,0 +1,41 @@ +From 4d3a04a9edbd9f54f1fc3748911663fb6aaaf182 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 15:08:34 +0800 +Subject: RDMA/hns: fix memory leak in hns_roce_alloc_mr() + +From: Zhengchao Shao + +[ Upstream commit a115aa00b18f7b8982b8f458149632caf64a862a ] + +When hns_roce_mr_enable() failed in hns_roce_alloc_mr(), mr_key is not +released. Compiled test only. + +Fixes: 9b2cf76c9f05 ("RDMA/hns: Optimize PBL buffer allocation process") +Signed-off-by: Zhengchao Shao +Link: https://lore.kernel.org/r/20221119070834.48502-1-shaozhengchao@huawei.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_mr.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 20360df25771..a593c142cd6b 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -415,10 +415,10 @@ struct ib_mr *hns_roce_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, + + return &mr->ibmr; + +-err_key: +- free_mr_key(hr_dev, mr); + err_pbl: + free_mr_pbl(hr_dev, mr); ++err_key: ++ free_mr_key(hr_dev, mr); + err_free: + kfree(mr); + return ERR_PTR(ret); +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-page-size-cap-from-firmware.patch b/queue-5.15/rdma-hns-fix-page-size-cap-from-firmware.patch new file mode 100644 index 00000000000..89554fec50f --- /dev/null +++ b/queue-5.15/rdma-hns-fix-page-size-cap-from-firmware.patch @@ -0,0 +1,39 @@ +From f12a5455d1853c6d763e57f2dae70ac49554a387 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 18:29:09 +0800 +Subject: RDMA/hns: Fix page size cap from firmware + +From: Chengchang Tang + +[ Upstream commit 99dc5a0712883d5d13b620d25b3759d429577bc8 ] + +Add verification to make sure the roce page size cap is supported by the +system page size. + +Fixes: ba6bb7e97421 ("RDMA/hns: Add interfaces to get pf capabilities from firmware") +Link: https://lore.kernel.org/r/20221126102911.2921820-5-xuhaoyue1@hisilicon.com +Signed-off-by: Chengchang Tang +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index b9557be812b7..16f39321b319 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -2371,6 +2371,9 @@ static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev) + V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M, + V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S); + ++ if (!(caps->page_size_cap & PAGE_SIZE)) ++ caps->page_size_cap = HNS_ROCE_V2_PAGE_SIZE_SUPPORTED; ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-fix-pbl-page-mtr-find.patch b/queue-5.15/rdma-hns-fix-pbl-page-mtr-find.patch new file mode 100644 index 00000000000..2a7623baafa --- /dev/null +++ b/queue-5.15/rdma-hns-fix-pbl-page-mtr-find.patch @@ -0,0 +1,41 @@ +From c0284becffb047ae8ba9d124791abbb8a6665183 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 18:29:08 +0800 +Subject: RDMA/hns: Fix PBL page MTR find + +From: Chengchang Tang + +[ Upstream commit 9fb39ef2ff3e18f1740625ba04093dfbef086d2b ] + +Now, The address of the first two pages in the MR will be searched, which +use to speed up the lookup of the pbl table for hardware. An exception +will occur when there is only one page in this MR. This patch fix the +number of page to search. + +Fixes: 9b2cf76c9f05 ("RDMA/hns: Optimize PBL buffer allocation process") +Link: https://lore.kernel.org/r/20221126102911.2921820-4-xuhaoyue1@hisilicon.com +Signed-off-by: Chengchang Tang +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 155ae202b1ec..b9557be812b7 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -3024,7 +3024,8 @@ static int set_mtpt_pbl(struct hns_roce_dev *hr_dev, + int i, count; + + count = hns_roce_mtr_find(hr_dev, &mr->pbl_mtr, 0, pages, +- ARRAY_SIZE(pages), &pbl_ba); ++ min_t(int, ARRAY_SIZE(pages), mr->npages), ++ &pbl_ba); + if (count < 1) { + ibdev_err(ibdev, "failed to find PBL mtr, count = %d.\n", + count); +-- +2.35.1 + diff --git a/queue-5.15/rdma-hns-repacing-dseg_len-by-macros-in-fill_ext_sge.patch b/queue-5.15/rdma-hns-repacing-dseg_len-by-macros-in-fill_ext_sge.patch new file mode 100644 index 00000000000..18272e7ea0d --- /dev/null +++ b/queue-5.15/rdma-hns-repacing-dseg_len-by-macros-in-fill_ext_sge.patch @@ -0,0 +1,57 @@ +From b1494482127ddc632314cece4cfc9207cf609d67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 20:33:13 +0800 +Subject: RDMA/hns: Repacing 'dseg_len' by macros in fill_ext_sge_inl_data() + +From: Luoyouming + +[ Upstream commit 3b1f864c904915b3baebffb31ea05ee704b0df3c ] + +The sge size is known to be constant, so it's unnecessary to use sizeof to +calculate. + +Link: https://lore.kernel.org/r/20220922123315.3732205-11-xuhaoyue1@hisilicon.com +Signed-off-by: Luoyouming +Signed-off-by: Haoyue Xu +Signed-off-by: Jason Gunthorpe +Stable-dep-of: 8eaa6f7d569b ("RDMA/hns: Fix ext_sge num error when post send") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +index 1421896abaf0..5875ccf86f66 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c ++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +@@ -156,8 +156,7 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + unsigned int *sge_idx, u32 msg_len) + { + struct ib_device *ibdev = &(to_hr_dev(qp->ibqp.device))->ib_dev; +- unsigned int dseg_len = sizeof(struct hns_roce_v2_wqe_data_seg); +- unsigned int ext_sge_sz = qp->sq.max_gs * dseg_len; ++ unsigned int ext_sge_sz = qp->sq.max_gs * HNS_ROCE_SGE_SIZE; + unsigned int left_len_in_pg; + unsigned int idx = *sge_idx; + unsigned int i = 0; +@@ -185,7 +184,7 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + if (len <= left_len_in_pg) { + memcpy(dseg, addr, len); + +- idx += len / dseg_len; ++ idx += len / HNS_ROCE_SGE_SIZE; + + i++; + if (i >= wr->num_sge) +@@ -200,7 +199,7 @@ static int fill_ext_sge_inl_data(struct hns_roce_qp *qp, + + len -= left_len_in_pg; + addr += left_len_in_pg; +- idx += left_len_in_pg / dseg_len; ++ idx += left_len_in_pg / HNS_ROCE_SGE_SIZE; + dseg = hns_roce_get_extend_sge(qp, + idx & (qp->sge.sge_cnt - 1)); + left_len_in_pg = 1 << HNS_HW_PAGE_SHIFT; +-- +2.35.1 + diff --git a/queue-5.15/rdma-irdma-report-the-correct-link-speed.patch b/queue-5.15/rdma-irdma-report-the-correct-link-speed.patch new file mode 100644 index 00000000000..a9831f4723b --- /dev/null +++ b/queue-5.15/rdma-irdma-report-the-correct-link-speed.patch @@ -0,0 +1,80 @@ +From 0e35824ee1df9806f1d816f3a29ebbba288c59e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 18:49:57 -0500 +Subject: RDMA/irdma: Report the correct link speed + +From: Shiraz Saleem + +[ Upstream commit 4eace75e0853273755b878ffa9cce6de84df975a ] + +The active link speed is currently hard-coded in irdma_query_port due +to which the port rate in ibstatus does reflect the active link speed. + +Call ib_get_eth_speed in irdma_query_port to get the active link speed. + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Reported-by: Kamal Heib +Signed-off-by: Shiraz Saleem +Link: https://lore.kernel.org/r/20221104234957.1135-1-shiraz.saleem@intel.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 35 +++-------------------------- + 1 file changed, 3 insertions(+), 32 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 911902d2b93e..c5971a840b87 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -60,36 +60,6 @@ static int irdma_query_device(struct ib_device *ibdev, + return 0; + } + +-/** +- * irdma_get_eth_speed_and_width - Get IB port speed and width from netdev speed +- * @link_speed: netdev phy link speed +- * @active_speed: IB port speed +- * @active_width: IB port width +- */ +-static void irdma_get_eth_speed_and_width(u32 link_speed, u16 *active_speed, +- u8 *active_width) +-{ +- if (link_speed <= SPEED_1000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_SDR; +- } else if (link_speed <= SPEED_10000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_FDR10; +- } else if (link_speed <= SPEED_20000) { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_DDR; +- } else if (link_speed <= SPEED_25000) { +- *active_width = IB_WIDTH_1X; +- *active_speed = IB_SPEED_EDR; +- } else if (link_speed <= SPEED_40000) { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_FDR10; +- } else { +- *active_width = IB_WIDTH_4X; +- *active_speed = IB_SPEED_EDR; +- } +-} +- + /** + * irdma_query_port - get port attributes + * @ibdev: device pointer from stack +@@ -117,8 +87,9 @@ static int irdma_query_port(struct ib_device *ibdev, u32 port, + props->state = IB_PORT_DOWN; + props->phys_state = IB_PORT_PHYS_STATE_DISABLED; + } +- irdma_get_eth_speed_and_width(SPEED_100000, &props->active_speed, +- &props->active_width); ++ ++ ib_get_eth_speed(ibdev, port, &props->active_speed, ++ &props->active_width); + + if (rdma_protocol_roce(ibdev, 1)) { + props->gid_tbl_len = 32; +-- +2.35.1 + diff --git a/queue-5.15/rdma-nldev-add-checks-for-nla_nest_start-in-fill_sta.patch b/queue-5.15/rdma-nldev-add-checks-for-nla_nest_start-in-fill_sta.patch new file mode 100644 index 00000000000..9240819c19e --- /dev/null +++ b/queue-5.15/rdma-nldev-add-checks-for-nla_nest_start-in-fill_sta.patch @@ -0,0 +1,38 @@ +From ffaf8865219f09db22c3dcb22fbc27ae06fc05c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Nov 2022 04:34:10 +0000 +Subject: RDMA/nldev: Add checks for nla_nest_start() in + fill_stat_counter_qps() + +From: Yuan Can + +[ Upstream commit ea5ef136e215fdef35f14010bc51fcd6686e6922 ] + +As the nla_nest_start() may fail with NULL returned, the return value needs +to be checked. + +Fixes: c4ffee7c9bdb ("RDMA/netlink: Implement counter dumpit calback") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221126043410.85632-1-yuancan@huawei.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/nldev.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c +index 6f3799698634..cefe12964f3e 100644 +--- a/drivers/infiniband/core/nldev.c ++++ b/drivers/infiniband/core/nldev.c +@@ -892,6 +892,8 @@ static int fill_stat_counter_qps(struct sk_buff *msg, + int ret = 0; + + table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP); ++ if (!table_attr) ++ return -EMSGSIZE; + + rt = &counter->device->res[RDMA_RESTRACK_QP]; + xa_lock(&rt->xa); +-- +2.35.1 + diff --git a/queue-5.15/rdma-nldev-fix-failure-to-send-large-messages.patch b/queue-5.15/rdma-nldev-fix-failure-to-send-large-messages.patch new file mode 100644 index 00000000000..2496cf4c66c --- /dev/null +++ b/queue-5.15/rdma-nldev-fix-failure-to-send-large-messages.patch @@ -0,0 +1,38 @@ +From 58491c547d7c94456fce92ffab2eed6574b4aa66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Nov 2022 13:52:46 +0200 +Subject: RDMA/nldev: Fix failure to send large messages + +From: Mark Zhang + +[ Upstream commit fc8f93ad3e5485d45c992233c96acd902992dfc4 ] + +Return "-EMSGSIZE" instead of "-EINVAL" when filling a QP entry, so that +new SKBs will be allocated if there's not enough room in current SKB. + +Fixes: 65959522f806 ("RDMA: Add support to dump resource tracker in RAW format") +Signed-off-by: Mark Zhang +Reviewed-by: Patrisious Haddad +Link: https://lore.kernel.org/r/b5e9c62f6b8369acab5648b661bf539cbceeffdc.1669636336.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/nldev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c +index cefe12964f3e..7ad3ba7d5a0a 100644 +--- a/drivers/infiniband/core/nldev.c ++++ b/drivers/infiniband/core/nldev.c +@@ -511,7 +511,7 @@ static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin, + + /* In create_qp() port is not set yet */ + if (qp->port && nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, qp->port)) +- return -EINVAL; ++ return -EMSGSIZE; + + ret = nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LQPN, qp->qp_num); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/rdma-nldev-return-eagain-if-the-cm_id-isn-t-from-exp.patch b/queue-5.15/rdma-nldev-return-eagain-if-the-cm_id-isn-t-from-exp.patch new file mode 100644 index 00000000000..27cb9bc82ba --- /dev/null +++ b/queue-5.15/rdma-nldev-return-eagain-if-the-cm_id-isn-t-from-exp.patch @@ -0,0 +1,51 @@ +From f3df5fc30b30042cbb0a67c0a34b1cb78f7391e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 10:51:36 +0200 +Subject: RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port + +From: Mark Zhang + +[ Upstream commit ecacb3751f254572af0009b9501e2cdc83a30b6a ] + +When filling a cm_id entry, return "-EAGAIN" instead of 0 if the cm_id +doesn'the have the same port as requested, otherwise an incomplete entry +may be returned, which causes "rdam res show cm_id" to return an error. + +For example on a machine with two rdma devices with "rping -C 1 -v -s" +running background, the "rdma" command fails: + $ rdma -V + rdma utility, iproute2-5.19.0 + $ rdma res show cm_id + link mlx5_0/- cm-idn 0 state LISTEN ps TCP pid 28056 comm rping src-addr 0.0.0.0:7174 + error: Protocol not available + +While with this fix it succeeds: + $ rdma res show cm_id + link mlx5_0/- cm-idn 0 state LISTEN ps TCP pid 26395 comm rping src-addr 0.0.0.0:7174 + link mlx5_1/- cm-idn 0 state LISTEN ps TCP pid 26395 comm rping src-addr 0.0.0.0:7174 + +Fixes: 00313983cda6 ("RDMA/nldev: provide detailed CM_ID information") +Signed-off-by: Mark Zhang +Link: https://lore.kernel.org/r/a08e898cdac5e28428eb749a99d9d981571b8ea7.1667810736.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/nldev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c +index cd89e59cbe33..6f3799698634 100644 +--- a/drivers/infiniband/core/nldev.c ++++ b/drivers/infiniband/core/nldev.c +@@ -550,7 +550,7 @@ static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin, + struct rdma_cm_id *cm_id = &id_priv->id; + + if (port && port != cm_id->port_num) +- return 0; ++ return -EAGAIN; + + if (cm_id->port_num && + nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, cm_id->port_num)) +-- +2.35.1 + diff --git a/queue-5.15/rdma-restrack-release-mr-restrack-when-delete.patch b/queue-5.15/rdma-restrack-release-mr-restrack-when-delete.patch new file mode 100644 index 00000000000..a04b92132b3 --- /dev/null +++ b/queue-5.15/rdma-restrack-release-mr-restrack-when-delete.patch @@ -0,0 +1,38 @@ +From 6deeb98b0f3dd5c7e1d5fa2ca24d146231a57834 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 10:51:34 +0200 +Subject: RDMA/restrack: Release MR restrack when delete + +From: Mark Zhang + +[ Upstream commit dac153f2802db1ad46207283cb9b2aae3d707a45 ] + +The MR restrack also needs to be released when delete it, otherwise it +cause memory leak as the task struct won't be released. + +Fixes: 13ef5539def7 ("RDMA/restrack: Count references to the verbs objects") +Signed-off-by: Mark Zhang +Reviewed-by: Michael Guralnik +Link: https://lore.kernel.org/r/703db18e8d4ef628691fb93980a709be673e62e3.1667810736.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/restrack.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c +index 1f935d9f6178..01a499a8b88d 100644 +--- a/drivers/infiniband/core/restrack.c ++++ b/drivers/infiniband/core/restrack.c +@@ -343,8 +343,6 @@ void rdma_restrack_del(struct rdma_restrack_entry *res) + rt = &dev->res[res->type]; + + old = xa_erase(&rt->xa, res->id); +- if (res->type == RDMA_RESTRACK_MR) +- return; + WARN_ON(old != res); + + out: +-- +2.35.1 + diff --git a/queue-5.15/rdma-rxe-fix-null-ptr-deref-in-rxe_qp_do_cleanup-whe.patch b/queue-5.15/rdma-rxe-fix-null-ptr-deref-in-rxe_qp_do_cleanup-whe.patch new file mode 100644 index 00000000000..5407a396c5c --- /dev/null +++ b/queue-5.15/rdma-rxe-fix-null-ptr-deref-in-rxe_qp_do_cleanup-whe.patch @@ -0,0 +1,78 @@ +From d8c494e5c22abd8543a4e983fbf95880849330b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 23:14:37 +0800 +Subject: RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket + create failed + +From: Zhang Xiaoxu + +[ Upstream commit f67376d801499f4fa0838c18c1efcad8840e550d ] + +There is a null-ptr-deref when mount.cifs over rdma: + + BUG: KASAN: null-ptr-deref in rxe_qp_do_cleanup+0x2f3/0x360 [rdma_rxe] + Read of size 8 at addr 0000000000000018 by task mount.cifs/3046 + + CPU: 2 PID: 3046 Comm: mount.cifs Not tainted 6.1.0-rc5+ #62 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc3 + Call Trace: + + dump_stack_lvl+0x34/0x44 + kasan_report+0xad/0x130 + rxe_qp_do_cleanup+0x2f3/0x360 [rdma_rxe] + execute_in_process_context+0x25/0x90 + __rxe_cleanup+0x101/0x1d0 [rdma_rxe] + rxe_create_qp+0x16a/0x180 [rdma_rxe] + create_qp.part.0+0x27d/0x340 + ib_create_qp_kernel+0x73/0x160 + rdma_create_qp+0x100/0x230 + _smbd_get_connection+0x752/0x20f0 + smbd_get_connection+0x21/0x40 + cifs_get_tcp_session+0x8ef/0xda0 + mount_get_conns+0x60/0x750 + cifs_mount+0x103/0xd00 + cifs_smb3_do_mount+0x1dd/0xcb0 + smb3_get_tree+0x1d5/0x300 + vfs_get_tree+0x41/0xf0 + path_mount+0x9b3/0xdd0 + __x64_sys_mount+0x190/0x1d0 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +The root cause of the issue is the socket create failed in +rxe_qp_init_req(). + +So move the reset rxe_qp_do_cleanup() after the NULL ptr check. + +Fixes: 8700e3e7c485 ("Soft RoCE driver") +Link: https://lore.kernel.org/r/20221122151437.1057671-1-zhangxiaoxu5@huawei.com +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_qp.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index 57ebf4871608..d7a968356a9b 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -830,12 +830,12 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + qp->resp.mr = NULL; + } + +- if (qp_type(qp) == IB_QPT_RC) +- sk_dst_reset(qp->sk->sk); +- + free_rd_atomic_resources(qp); + + if (qp->sk) { ++ if (qp_type(qp) == IB_QPT_RC) ++ sk_dst_reset(qp->sk->sk); ++ + kernel_sock_shutdown(qp->sk, SHUT_RDWR); + sock_release(qp->sk); + } +-- +2.35.1 + diff --git a/queue-5.15/rdma-siw-fix-immediate-work-request-flush-to-complet.patch b/queue-5.15/rdma-siw-fix-immediate-work-request-flush-to-complet.patch new file mode 100644 index 00000000000..7de3bb6f656 --- /dev/null +++ b/queue-5.15/rdma-siw-fix-immediate-work-request-flush-to-complet.patch @@ -0,0 +1,137 @@ +From 149336ddaff0d3938ebf511ef7fb15a52beb8770 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 15:50:57 +0100 +Subject: RDMA/siw: Fix immediate work request flush to completion queue + +From: Bernard Metzler + +[ Upstream commit bdf1da5df9da680589a7f74448dd0a94dd3e1446 ] + +Correctly set send queue element opcode during immediate work request +flushing in post sendqueue operation, if the QP is in ERROR state. +An undefined ocode value results in out-of-bounds access to an array +for mapping the opcode between siw internal and RDMA core representation +in work completion generation. It resulted in a KASAN BUG report +of type 'global-out-of-bounds' during NFSoRDMA testing. + +This patch further fixes a potential case of a malicious user which may +write undefined values for completion queue elements status or opcode, +if the CQ is memory mapped to user land. It avoids the same out-of-bounds +access to arrays for status and opcode mapping as described above. + +Fixes: 303ae1cdfdf7 ("rdma/siw: application interface") +Fixes: b0fff7317bb4 ("rdma/siw: completion queue methods") +Reported-by: Olga Kornievskaia +Reviewed-by: Tom Talpey +Signed-off-by: Bernard Metzler +Link: https://lore.kernel.org/r/20221107145057.895747-1-bmt@zurich.ibm.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_cq.c | 24 ++++++++++++++-- + drivers/infiniband/sw/siw/siw_verbs.c | 40 ++++++++++++++++++++++++--- + 2 files changed, 58 insertions(+), 6 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_cq.c b/drivers/infiniband/sw/siw/siw_cq.c +index d68e37859e73..acc7bcd538b5 100644 +--- a/drivers/infiniband/sw/siw/siw_cq.c ++++ b/drivers/infiniband/sw/siw/siw_cq.c +@@ -56,8 +56,6 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) + if (READ_ONCE(cqe->flags) & SIW_WQE_VALID) { + memset(wc, 0, sizeof(*wc)); + wc->wr_id = cqe->id; +- wc->status = map_cqe_status[cqe->status].ib; +- wc->opcode = map_wc_opcode[cqe->opcode]; + wc->byte_len = cqe->bytes; + + /* +@@ -71,10 +69,32 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) + wc->wc_flags = IB_WC_WITH_INVALIDATE; + } + wc->qp = cqe->base_qp; ++ wc->opcode = map_wc_opcode[cqe->opcode]; ++ wc->status = map_cqe_status[cqe->status].ib; + siw_dbg_cq(cq, + "idx %u, type %d, flags %2x, id 0x%pK\n", + cq->cq_get % cq->num_cqe, cqe->opcode, + cqe->flags, (void *)(uintptr_t)cqe->id); ++ } else { ++ /* ++ * A malicious user may set invalid opcode or ++ * status in the user mmapped CQE array. ++ * Sanity check and correct values in that case ++ * to avoid out-of-bounds access to global arrays ++ * for opcode and status mapping. ++ */ ++ u8 opcode = cqe->opcode; ++ u16 status = cqe->status; ++ ++ if (opcode >= SIW_NUM_OPCODES) { ++ opcode = 0; ++ status = IB_WC_GENERAL_ERR; ++ } else if (status >= SIW_NUM_WC_STATUS) { ++ status = IB_WC_GENERAL_ERR; ++ } ++ wc->opcode = map_wc_opcode[opcode]; ++ wc->status = map_cqe_status[status].ib; ++ + } + WRITE_ONCE(cqe->flags, 0); + cq->cq_get++; +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index ff33659acffa..9c7fbda9e068 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -674,13 +674,45 @@ static int siw_copy_inline_sgl(const struct ib_send_wr *core_wr, + static int siw_sq_flush_wr(struct siw_qp *qp, const struct ib_send_wr *wr, + const struct ib_send_wr **bad_wr) + { +- struct siw_sqe sqe = {}; + int rv = 0; + + while (wr) { +- sqe.id = wr->wr_id; +- sqe.opcode = wr->opcode; +- rv = siw_sqe_complete(qp, &sqe, 0, SIW_WC_WR_FLUSH_ERR); ++ struct siw_sqe sqe = {}; ++ ++ switch (wr->opcode) { ++ case IB_WR_RDMA_WRITE: ++ sqe.opcode = SIW_OP_WRITE; ++ break; ++ case IB_WR_RDMA_READ: ++ sqe.opcode = SIW_OP_READ; ++ break; ++ case IB_WR_RDMA_READ_WITH_INV: ++ sqe.opcode = SIW_OP_READ_LOCAL_INV; ++ break; ++ case IB_WR_SEND: ++ sqe.opcode = SIW_OP_SEND; ++ break; ++ case IB_WR_SEND_WITH_IMM: ++ sqe.opcode = SIW_OP_SEND_WITH_IMM; ++ break; ++ case IB_WR_SEND_WITH_INV: ++ sqe.opcode = SIW_OP_SEND_REMOTE_INV; ++ break; ++ case IB_WR_LOCAL_INV: ++ sqe.opcode = SIW_OP_INVAL_STAG; ++ break; ++ case IB_WR_REG_MR: ++ sqe.opcode = SIW_OP_REG_MR; ++ break; ++ default: ++ rv = -EINVAL; ++ break; ++ } ++ if (!rv) { ++ sqe.id = wr->wr_id; ++ rv = siw_sqe_complete(qp, &sqe, 0, ++ SIW_WC_WR_FLUSH_ERR); ++ } + if (rv) { + if (bad_wr) + *bad_wr = wr; +-- +2.35.1 + diff --git a/queue-5.15/rdma-siw-fix-pointer-cast-warning.patch b/queue-5.15/rdma-siw-fix-pointer-cast-warning.patch new file mode 100644 index 00000000000..d277904c032 --- /dev/null +++ b/queue-5.15/rdma-siw-fix-pointer-cast-warning.patch @@ -0,0 +1,47 @@ +From bc5d4c0eb10e80d2f1dcbaca1a29c0463f943472 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Dec 2022 18:03:43 +0100 +Subject: RDMA/siw: Fix pointer cast warning + +From: Arnd Bergmann + +[ Upstream commit 5244ca88671a1981ceec09c5c8809f003e6a62aa ] + +The previous build fix left a remaining issue in configurations with +64-bit dma_addr_t on 32-bit architectures: + +drivers/infiniband/sw/siw/siw_qp_tx.c: In function 'siw_get_pblpage': +drivers/infiniband/sw/siw/siw_qp_tx.c:32:37: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] + 32 | return virt_to_page((void *)paddr); + | ^ + +Use the same double cast here that the driver uses elsewhere to convert +between dma_addr_t and void*. + +Fixes: 0d1b756acf60 ("RDMA/siw: Pass a pointer to virt_to_page()") +Link: https://lore.kernel.org/r/20221215170347.2612403-1-arnd@kernel.org +Signed-off-by: Arnd Bergmann +Acked-by: Bernard Metzler +Reviewed-by: Linus Walleij +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_qp_tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c +index 7d47b521070b..05052b49107f 100644 +--- a/drivers/infiniband/sw/siw/siw_qp_tx.c ++++ b/drivers/infiniband/sw/siw/siw_qp_tx.c +@@ -29,7 +29,7 @@ static struct page *siw_get_pblpage(struct siw_mem *mem, u64 addr, int *idx) + dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx); + + if (paddr) +- return virt_to_page((void *)paddr); ++ return virt_to_page((void *)(uintptr_t)paddr); + + return NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/rdma-siw-set-defined-status-for-work-completion-with.patch b/queue-5.15/rdma-siw-set-defined-status-for-work-completion-with.patch new file mode 100644 index 00000000000..90bc69ac23e --- /dev/null +++ b/queue-5.15/rdma-siw-set-defined-status-for-work-completion-with.patch @@ -0,0 +1,52 @@ +From 4c8029fcc642320aab250fb2388a8685b85a4c96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 18:07:47 +0100 +Subject: RDMA/siw: Set defined status for work completion with undefined + status + +From: Bernard Metzler + +[ Upstream commit 60da2d11fcbc043304910e4d2ca82f9bab953e63 ] + +A malicious user may write undefined values into memory mapped completion +queue elements status or opcode. Undefined status or opcode values will +result in out-of-bounds access to an array mapping siw internal +representation of opcode and status to RDMA core representation when +reaping CQ elements. While siw detects those undefined values, it did not +correctly set completion status to a defined value, thus defeating the +whole purpose of the check. + +This bug leads to the following Smatch static checker warning: + + drivers/infiniband/sw/siw/siw_cq.c:96 siw_reap_cqe() + error: buffer overflow 'map_cqe_status' 10 <= 21 + +Fixes: bdf1da5df9da ("RDMA/siw: Fix immediate work request flush to completion queue") +Link: https://lore.kernel.org/r/20221115170747.1263298-1-bmt@zurich.ibm.com +Reported-by: Dan Carpenter +Signed-off-by: Bernard Metzler +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_cq.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_cq.c b/drivers/infiniband/sw/siw/siw_cq.c +index acc7bcd538b5..403029de6b92 100644 +--- a/drivers/infiniband/sw/siw/siw_cq.c ++++ b/drivers/infiniband/sw/siw/siw_cq.c +@@ -88,9 +88,9 @@ int siw_reap_cqe(struct siw_cq *cq, struct ib_wc *wc) + + if (opcode >= SIW_NUM_OPCODES) { + opcode = 0; +- status = IB_WC_GENERAL_ERR; ++ status = SIW_WC_GENERAL_ERR; + } else if (status >= SIW_NUM_WC_STATUS) { +- status = IB_WC_GENERAL_ERR; ++ status = SIW_WC_GENERAL_ERR; + } + wc->opcode = map_wc_opcode[opcode]; + wc->status = map_cqe_status[status].ib; +-- +2.35.1 + diff --git a/queue-5.15/rdma-srp-fix-error-return-code-in-srp_parse_options.patch b/queue-5.15/rdma-srp-fix-error-return-code-in-srp_parse_options.patch new file mode 100644 index 00000000000..c2fb813d44b --- /dev/null +++ b/queue-5.15/rdma-srp-fix-error-return-code-in-srp_parse_options.patch @@ -0,0 +1,241 @@ +From a25775b6df98a4ca61945faeb3ca7a32d0692231 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 12:00:38 +0800 +Subject: RDMA/srp: Fix error return code in srp_parse_options() + +From: Wang Yufen + +[ Upstream commit ed461b30b22c8fa85c25189c14cb89f29595cd14 ] + +In the previous iteration of the while loop, the "ret" may have been +assigned a value of 0, so the error return code -EINVAL may have been +incorrectly set to 0. To fix set valid return code before calling to +goto. Also investigate each case separately as Andy suggessted. + +Fixes: e711f968c49c ("IB/srp: replace custom implementation of hex2bin()") +Fixes: 2a174df0c602 ("IB/srp: Use kstrtoull() instead of simple_strtoull()") +Fixes: 19f313438c77 ("IB/srp: Add RDMA/CM support") +Signed-off-by: Wang Yufen +Link: https://lore.kernel.org/r/1669953638-11747-2-git-send-email-wangyufen@huawei.com +Reviewed-by: Bart Van Assche +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 96 ++++++++++++++++++++++++----- + 1 file changed, 82 insertions(+), 14 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index 2f4991cea98c..a6117a7d0ab1 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -3397,7 +3397,8 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_PKEY: +- if (match_hex(args, &token)) { ++ ret = match_hex(args, &token); ++ if (ret) { + pr_warn("bad P_Key parameter '%s'\n", p); + goto out; + } +@@ -3457,7 +3458,8 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_MAX_SECT: +- if (match_int(args, &token)) { ++ ret = match_int(args, &token); ++ if (ret) { + pr_warn("bad max sect parameter '%s'\n", p); + goto out; + } +@@ -3465,8 +3467,15 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_QUEUE_SIZE: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for queue_size parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad queue_size parameter '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->scsi_host->can_queue = token; +@@ -3477,25 +3486,40 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_MAX_CMD_PER_LUN: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max cmd_per_lun parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad max cmd_per_lun parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->scsi_host->cmd_per_lun = token; + break; + + case SRP_OPT_TARGET_CAN_QUEUE: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max target_can_queue parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad max target_can_queue parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->target_can_queue = token; + break; + + case SRP_OPT_IO_CLASS: +- if (match_hex(args, &token)) { ++ ret = match_hex(args, &token); ++ if (ret) { + pr_warn("bad IO class parameter '%s'\n", p); + goto out; + } +@@ -3504,6 +3528,7 @@ static int srp_parse_options(struct net *net, const char *buf, + pr_warn("unknown IO class parameter value %x specified (use %x or %x).\n", + token, SRP_REV10_IB_IO_CLASS, + SRP_REV16A_IB_IO_CLASS); ++ ret = -EINVAL; + goto out; + } + target->io_class = token; +@@ -3526,16 +3551,24 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_CMD_SG_ENTRIES: +- if (match_int(args, &token) || token < 1 || token > 255) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max cmd_sg_entries parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1 || token > 255) { + pr_warn("bad max cmd_sg_entries parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->cmd_sg_cnt = token; + break; + + case SRP_OPT_ALLOW_EXT_SG: +- if (match_int(args, &token)) { ++ ret = match_int(args, &token); ++ if (ret) { + pr_warn("bad allow_ext_sg parameter '%s'\n", p); + goto out; + } +@@ -3543,43 +3576,77 @@ static int srp_parse_options(struct net *net, const char *buf, + break; + + case SRP_OPT_SG_TABLESIZE: +- if (match_int(args, &token) || token < 1 || +- token > SG_MAX_SEGMENTS) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max sg_tablesize parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1 || token > SG_MAX_SEGMENTS) { + pr_warn("bad max sg_tablesize parameter '%s'\n", + p); ++ ret = -EINVAL; + goto out; + } + target->sg_tablesize = token; + break; + + case SRP_OPT_COMP_VECTOR: +- if (match_int(args, &token) || token < 0) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for comp_vector parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 0) { + pr_warn("bad comp_vector parameter '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->comp_vector = token; + break; + + case SRP_OPT_TL_RETRY_COUNT: +- if (match_int(args, &token) || token < 2 || token > 7) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for tl_retry_count parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 2 || token > 7) { + pr_warn("bad tl_retry_count parameter '%s' (must be a number between 2 and 7)\n", + p); ++ ret = -EINVAL; + goto out; + } + target->tl_retry_count = token; + break; + + case SRP_OPT_MAX_IT_IU_SIZE: +- if (match_int(args, &token) || token < 0) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for max it_iu_size parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 0) { + pr_warn("bad maximum initiator to target IU size '%s'\n", p); ++ ret = -EINVAL; + goto out; + } + target->max_it_iu_size = token; + break; + + case SRP_OPT_CH_COUNT: +- if (match_int(args, &token) || token < 1) { ++ ret = match_int(args, &token); ++ if (ret) { ++ pr_warn("match_int() failed for channel count parameter '%s', Error %d\n", ++ p, ret); ++ goto out; ++ } ++ if (token < 1) { + pr_warn("bad channel count %s\n", p); ++ ret = -EINVAL; + goto out; + } + target->ch_count = token; +@@ -3588,6 +3655,7 @@ static int srp_parse_options(struct net *net, const char *buf, + default: + pr_warn("unknown parameter or missing value '%s' in target creation request\n", + p); ++ ret = -EINVAL; + goto out; + } + } +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-module-refcount-leak-in-set_suppl.patch b/queue-5.15/regulator-core-fix-module-refcount-leak-in-set_suppl.patch new file mode 100644 index 00000000000..48417864b1e --- /dev/null +++ b/queue-5.15/regulator-core-fix-module-refcount-leak-in-set_suppl.patch @@ -0,0 +1,36 @@ +From a8172993c5a1d96d6f1e4beed0dc94dbdb91bc1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 20:27:05 +0800 +Subject: regulator: core: fix module refcount leak in set_supply() + +From: Yang Yingliang + +[ Upstream commit da46ee19cbd8344d6860816b4827a7ce95764867 ] + +If create_regulator() fails in set_supply(), the module refcount +needs be put to keep refcount balanced. + +Fixes: e2c09ae7a74d ("regulator: core: Increase refcount for regulator supply's module") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221201122706.4055992-2-yangyingliang@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 65900895a0b2..ab93debb817c 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1577,6 +1577,7 @@ static int set_supply(struct regulator_dev *rdev, + + rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); + if (rdev->supply == NULL) { ++ module_put(supply_rdev->owner); + err = -ENOMEM; + return err; + } +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-resource-leak-in-regulator_regist.patch b/queue-5.15/regulator-core-fix-resource-leak-in-regulator_regist.patch new file mode 100644 index 00000000000..725dfa01d04 --- /dev/null +++ b/queue-5.15/regulator-core-fix-resource-leak-in-regulator_regist.patch @@ -0,0 +1,71 @@ +From b69f18c59d76ae7bed1edc9cf1404cf6468c5c46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 10:51:11 +0800 +Subject: regulator: core: fix resource leak in regulator_register() + +From: Yang Yingliang + +[ Upstream commit ba62319a42c50e6254e98b3f316464fac8e77968 ] + +I got some resource leak reports while doing fault injection test: + + OF: ERROR: memory leak, expected refcount 1 instead of 100, + of_node_get()/of_node_put() unbalanced - destroy cset entry: + attach overlay node /i2c/pmic@64/regulators/buck1 + +unreferenced object 0xffff88810deea000 (size 512): + comm "490-i2c-rt5190a", pid 253, jiffies 4294859840 (age 5061.046s) + hex dump (first 32 bytes): + 00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N.......... + ff ff ff ff ff ff ff ff a0 1e 00 a1 ff ff ff ff ................ + backtrace: + [<00000000d78541e2>] kmalloc_trace+0x21/0x110 + [<00000000b343d153>] device_private_init+0x32/0xd0 + [<00000000be1f0c70>] device_add+0xb2d/0x1030 + [<00000000e3e6344d>] regulator_register+0xaf2/0x12a0 + [<00000000e2f5e754>] devm_regulator_register+0x57/0xb0 + [<000000008b898197>] rt5190a_probe+0x52a/0x861 [rt5190a_regulator] + +unreferenced object 0xffff88810b617b80 (size 32): + comm "490-i2c-rt5190a", pid 253, jiffies 4294859904 (age 5060.983s) + hex dump (first 32 bytes): + 72 65 67 75 6c 61 74 6f 72 2e 32 38 36 38 2d 53 regulator.2868-S + 55 50 50 4c 59 00 ff ff 29 00 00 00 2b 00 00 00 UPPLY...)...+... + backtrace: + [<000000009da9280d>] __kmalloc_node_track_caller+0x44/0x1b0 + [<0000000025c6a4e5>] kstrdup+0x3a/0x70 + [<00000000790efb69>] create_regulator+0xc0/0x4e0 + [<0000000005ed203a>] regulator_resolve_supply+0x2d4/0x440 + [<0000000045796214>] regulator_register+0x10b3/0x12a0 + [<00000000e2f5e754>] devm_regulator_register+0x57/0xb0 + [<000000008b898197>] rt5190a_probe+0x52a/0x861 [rt5190a_regulator] + +After calling regulator_resolve_supply(), the 'rdev->supply' is set +by set_supply(), after this set, in the error path, the resources +need be released, so call regulator_put() to avoid the leaks. + +Fixes: aea6cb99703e ("regulator: resolve supply after creating regulator") +Fixes: 8a866d527ac0 ("regulator: core: Resolve supply name earlier to prevent double-init") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221202025111.496402-1-yangyingliang@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index ab93debb817c..1a5aeb4868aa 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -5548,6 +5548,7 @@ regulator_register(const struct regulator_desc *regulator_desc, + regulator_remove_coupling(rdev); + mutex_unlock(®ulator_list_mutex); + wash: ++ regulator_put(rdev->supply); + kfree(rdev->coupling_desc.coupled_rdevs); + mutex_lock(®ulator_list_mutex); + regulator_ena_gpio_free(rdev); +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-unbalanced-of-node-refcount-in-re.patch b/queue-5.15/regulator-core-fix-unbalanced-of-node-refcount-in-re.patch new file mode 100644 index 00000000000..399b96df7cd --- /dev/null +++ b/queue-5.15/regulator-core-fix-unbalanced-of-node-refcount-in-re.patch @@ -0,0 +1,43 @@ +From 8cb8bda62a1c7ef611830994422c68a34bb324a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 17:15:08 +0800 +Subject: regulator: core: fix unbalanced of node refcount in + regulator_dev_lookup() + +From: Yang Yingliang + +[ Upstream commit f2b41b748c19962b82709d9f23c6b2b0ce9d2f91 ] + +I got the the following report: + + OF: ERROR: memory leak, expected refcount 1 instead of 2, + of_node_get()/of_node_put() unbalanced - destroy cset entry: + attach overlay node /i2c/pmic@62/regulators/exten + +In of_get_regulator(), the node is returned from of_parse_phandle() +with refcount incremented, after using it, of_node_put() need be called. + +Fixes: 69511a452e6d ("regulator: map consumer regulator based on device tree") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221115091508.900752-1-yangyingliang@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 221ae807b379..7bf85e0cce47 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1880,6 +1880,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, + node = of_get_regulator(dev, supply); + if (node) { + r = of_find_regulator_by_node(node); ++ of_node_put(node); + if (r) + return r; + +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-fix-use_count-leakage-when-handling-b.patch b/queue-5.15/regulator-core-fix-use_count-leakage-when-handling-b.patch new file mode 100644 index 00000000000..38dd1c3e7d7 --- /dev/null +++ b/queue-5.15/regulator-core-fix-use_count-leakage-when-handling-b.patch @@ -0,0 +1,62 @@ +From 18a49fb25b1189b8e2a0f5ef04ae9acb572331f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 11:38:06 +0800 +Subject: regulator: core: fix use_count leakage when handling boot-on +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rui Zhang + +[ Upstream commit 0591b14ce0398125439c759f889647369aa616a0 ] + +I found a use_count leakage towards supply regulator of rdev with +boot-on option. + +┌───────────────────┐ ┌───────────────────┐ +│ regulator_dev A │ │ regulator_dev B │ +│ (boot-on) │ │ (boot-on) │ +│ use_count=0 │◀──supply──│ use_count=1 │ +│ │ │ │ +└───────────────────┘ └───────────────────┘ + +In case of rdev(A) configured with `regulator-boot-on', the use_count +of supplying regulator(B) will increment inside +regulator_enable(rdev->supply). + +Thus, B will acts like always-on, and further balanced +regulator_enable/disable cannot actually disable it anymore. + +However, B was also configured with `regulator-boot-on', we wish it +could be disabled afterwards. + +Signed-off-by: Rui Zhang +Link: https://lore.kernel.org/r/20221201033806.2567812-1-zr.zhang@vivo.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 1a5aeb4868aa..eababed938a0 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1531,7 +1531,13 @@ static int set_machine_constraints(struct regulator_dev *rdev) + if (rdev->supply_name && !rdev->supply) + return -EPROBE_DEFER; + +- if (rdev->supply) { ++ /* If supplying regulator has already been enabled, ++ * it's not intended to have use_count increment ++ * when rdev is only boot-on. ++ */ ++ if (rdev->supply && ++ (rdev->constraints->always_on || ++ !regulator_is_enabled(rdev->supply))) { + ret = regulator_enable(rdev->supply); + if (ret < 0) { + _regulator_put(rdev->supply); +-- +2.35.1 + diff --git a/queue-5.15/regulator-core-use-kfree_const-to-free-space-conditi.patch b/queue-5.15/regulator-core-use-kfree_const-to-free-space-conditi.patch new file mode 100644 index 00000000000..017dce8adce --- /dev/null +++ b/queue-5.15/regulator-core-use-kfree_const-to-free-space-conditi.patch @@ -0,0 +1,38 @@ +From dbdc4d886ab2868a13fa1de9076d9a0027080029 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 11:46:16 +0800 +Subject: regulator: core: use kfree_const() to free space conditionally + +From: Wang ShaoBo + +[ Upstream commit dc8d006d15b623c1d80b90b45d6dcb6e890dad09 ] + +Use kfree_const() to free supply_name conditionally in create_regulator() +as supply_name may be allocated from kmalloc() or directly from .rodata +section. + +Fixes: 87fe29b61f95 ("regulator: push allocations in create_regulator() outside of lock") +Signed-off-by: Wang ShaoBo +Link: https://lore.kernel.org/r/20221123034616.3609537-1-bobo.shaobowang@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 7bf85e0cce47..65900895a0b2 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -1750,7 +1750,7 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, + + regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); + if (regulator == NULL) { +- kfree(supply_name); ++ kfree_const(supply_name); + return NULL; + } + +-- +2.35.1 + diff --git a/queue-5.15/regulator-qcom-labibb-fix-missing-of_node_put-in-qco.patch b/queue-5.15/regulator-qcom-labibb-fix-missing-of_node_put-in-qco.patch new file mode 100644 index 00000000000..b601446774d --- /dev/null +++ b/queue-5.15/regulator-qcom-labibb-fix-missing-of_node_put-in-qco.patch @@ -0,0 +1,37 @@ +From 7bb55546943ac18109ef74dd79983d58bdf17b69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 3 Dec 2022 06:21:09 +0000 +Subject: regulator: qcom-labibb: Fix missing of_node_put() in + qcom_labibb_regulator_probe() + +From: Yuan Can + +[ Upstream commit cf34ac6aa2b12fb0c3aacfdcae8acd7904b949ec ] + +The reg_node needs to be released through of_node_put() in the error +handling path when of_irq_get_byname() failed. + +Fixes: 390af53e0411 ("regulator: qcom-labibb: Implement short-circuit and over-current IRQs") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221203062109.115043-1-yuancan@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/qcom-labibb-regulator.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/regulator/qcom-labibb-regulator.c b/drivers/regulator/qcom-labibb-regulator.c +index 639b71eb41ff..bcf7140f3bc9 100644 +--- a/drivers/regulator/qcom-labibb-regulator.c ++++ b/drivers/regulator/qcom-labibb-regulator.c +@@ -822,6 +822,7 @@ static int qcom_labibb_regulator_probe(struct platform_device *pdev) + if (irq == 0) + irq = -EINVAL; + ++ of_node_put(reg_node); + return dev_err_probe(vreg->dev, irq, + "Short-circuit irq not found.\n"); + } +-- +2.35.1 + diff --git a/queue-5.15/regulator-qcom-rpmh-fix-pmr735a-s3-regulator-spec.patch b/queue-5.15/regulator-qcom-rpmh-fix-pmr735a-s3-regulator-spec.patch new file mode 100644 index 00000000000..3a9c271b6c3 --- /dev/null +++ b/queue-5.15/regulator-qcom-rpmh-fix-pmr735a-s3-regulator-spec.patch @@ -0,0 +1,36 @@ +From 90afacb54c8be2bb1d7cbe090764aad0a3972423 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 22:07:05 +0100 +Subject: regulator: qcom-rpmh: Fix PMR735a S3 regulator spec + +From: Konrad Dybcio + +[ Upstream commit dd801b2265c81bf0c8b0b4b8f7c1e7bfed078403 ] + +PMR735a has a wider range than previously defined. Fix it. + +Fixes: c4e5aa3dbee5 ("regulator: qcom-rpmh: Add PM7325/PMR735A regulator support") +Signed-off-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20221110210706.80301-1-konrad.dybcio@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/qcom-rpmh-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c +index 7f458d510483..27efdbbd90d9 100644 +--- a/drivers/regulator/qcom-rpmh-regulator.c ++++ b/drivers/regulator/qcom-rpmh-regulator.c +@@ -1108,7 +1108,7 @@ static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { + static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), +- RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"), ++ RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps515, "vdd-s3"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), +-- +2.35.1 + diff --git a/queue-5.15/relay-fix-type-mismatch-when-allocating-memory-in-re.patch b/queue-5.15/relay-fix-type-mismatch-when-allocating-memory-in-re.patch new file mode 100644 index 00000000000..21650c2a127 --- /dev/null +++ b/queue-5.15/relay-fix-type-mismatch-when-allocating-memory-in-re.patch @@ -0,0 +1,49 @@ +From a6676c29409bf2ce1ccc2252d582285e0f4739db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 09:23:38 +0000 +Subject: relay: fix type mismatch when allocating memory in relay_create_buf() + +From: Gavrilov Ilia + +[ Upstream commit 4d8586e04602fe42f0a782d2005956f8b6302678 ] + +The 'padding' field of the 'rchan_buf' structure is an array of 'size_t' +elements, but the memory is allocated for an array of 'size_t *' elements. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Link: https://lkml.kernel.org/r/20221129092002.3538384-1-Ilia.Gavrilov@infotecs.ru +Fixes: b86ff981a825 ("[PATCH] relay: migrate from relayfs to a generic relay API") +Signed-off-by: Ilia.Gavrilov +Cc: Colin Ian King +Cc: Jens Axboe +Cc: wuchi +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/relay.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/kernel/relay.c b/kernel/relay.c +index d1a67fbb819d..6825b8403877 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -151,13 +151,13 @@ static struct rchan_buf *relay_create_buf(struct rchan *chan) + { + struct rchan_buf *buf; + +- if (chan->n_subbufs > KMALLOC_MAX_SIZE / sizeof(size_t *)) ++ if (chan->n_subbufs > KMALLOC_MAX_SIZE / sizeof(size_t)) + return NULL; + + buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); + if (!buf) + return NULL; +- buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t *), ++ buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t), + GFP_KERNEL); + if (!buf->padding) + goto free_buf; +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-qcom-q6v5-fix-missing-clk_disable_unprepa.patch b/queue-5.15/remoteproc-qcom-q6v5-fix-missing-clk_disable_unprepa.patch new file mode 100644 index 00000000000..d0d4cd06159 --- /dev/null +++ b/queue-5.15/remoteproc-qcom-q6v5-fix-missing-clk_disable_unprepa.patch @@ -0,0 +1,46 @@ +From d64e694d6f6c0c8cd3622fc8a3ea3754bcdf922f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Dec 2022 16:27:57 +0800 +Subject: remoteproc: qcom: q6v5: Fix missing clk_disable_unprepare() in + q6v5_wcss_qcs404_power_on() + +From: Shang XiaoJing + +[ Upstream commit 7ff5d60f18bba5cbaf17b2926aa9da44d5beca01 ] + +q6v5_wcss_qcs404_power_on() have no fail path for readl_poll_timeout(). +Add fail path for readl_poll_timeout(). + +Fixes: 0af65b9b915e ("remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404") +Signed-off-by: Shang XiaoJing +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221204082757.18850-1-shangxiaojing@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_wcss.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c +index 9e67e323a55a..cfd34ffcbb12 100644 +--- a/drivers/remoteproc/qcom_q6v5_wcss.c ++++ b/drivers/remoteproc/qcom_q6v5_wcss.c +@@ -351,7 +351,7 @@ static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss) + if (ret) { + dev_err(wcss->dev, + "xo cbcr enabling timed out (rc:%d)\n", ret); +- return ret; ++ goto disable_xo_cbcr_clk; + } + + writel(0, wcss->reg_base + Q6SS_CGC_OVERRIDE); +@@ -417,6 +417,7 @@ static int q6v5_wcss_qcs404_power_on(struct q6v5_wcss *wcss) + val = readl(wcss->reg_base + Q6SS_SLEEP_CBCR); + val &= ~Q6SS_CLK_ENABLE; + writel(val, wcss->reg_base + Q6SS_SLEEP_CBCR); ++disable_xo_cbcr_clk: + val = readl(wcss->reg_base + Q6SS_XO_CBCR); + val &= ~Q6SS_CLK_ENABLE; + writel(val, wcss->reg_base + Q6SS_XO_CBCR); +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-qcom-q6v5-fix-potential-null-ptr-deref-in.patch b/queue-5.15/remoteproc-qcom-q6v5-fix-potential-null-ptr-deref-in.patch new file mode 100644 index 00000000000..a4c1644a1ae --- /dev/null +++ b/queue-5.15/remoteproc-qcom-q6v5-fix-potential-null-ptr-deref-in.patch @@ -0,0 +1,41 @@ +From 9e1360c9c3689b70abe057d352bb99b9998dd33b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 10:16:41 +0800 +Subject: remoteproc: qcom: q6v5: Fix potential null-ptr-deref in + q6v5_wcss_init_mmio() + +From: Shang XiaoJing + +[ Upstream commit f360e2b275efbb745ba0af8b47d9ef44221be586 ] + +q6v5_wcss_init_mmio() will call platform_get_resource_byname() that may +fail and return NULL. devm_ioremap() will use res->start as input, which +may causes null-ptr-deref. Check the ret value of +platform_get_resource_byname() to avoid the null-ptr-deref. + +Fixes: 0af65b9b915e ("remoteproc: qcom: wcss: Add non pas wcss Q6 support for QCS404") +Signed-off-by: Shang XiaoJing +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221125021641.29392-1-shangxiaojing@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_wcss.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c +index 20d50ec7eff1..9e67e323a55a 100644 +--- a/drivers/remoteproc/qcom_q6v5_wcss.c ++++ b/drivers/remoteproc/qcom_q6v5_wcss.c +@@ -827,6 +827,9 @@ static int q6v5_wcss_init_mmio(struct q6v5_wcss *wcss, + int ret; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qdsp6"); ++ if (!res) ++ return -EINVAL; ++ + wcss->reg_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!wcss->reg_base) +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-qcom_q6v5_pas-detach-power-domains-on-rem.patch b/queue-5.15/remoteproc-qcom_q6v5_pas-detach-power-domains-on-rem.patch new file mode 100644 index 00000000000..d206bef1d44 --- /dev/null +++ b/queue-5.15/remoteproc-qcom_q6v5_pas-detach-power-domains-on-rem.patch @@ -0,0 +1,79 @@ +From f6ff80e39967395be56159e306f4ea6a2bc83f76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 10:08:16 +0100 +Subject: remoteproc: qcom_q6v5_pas: detach power domains on remove + +From: Luca Weiss + +[ Upstream commit 34d01df00b84127be04c914fc9f8e8be1fcdf851 ] + +We need to detach from the power domains also on remove, not just on +probe fail so a subsequent probe works as expected. + +Otherwise the following error appears on re-probe: + +[ 29.452005] sysfs: cannot create duplicate filename '/devices/genpd:0:3000000.remoteproc' +[ 29.477121] CPU: 1 PID: 483 Comm: sh Tainted: G W 6.1.0-rc4-00075-g71a113770bda #78 +[ 29.510319] Hardware name: Fairphone 4 (DT) +[ 29.538335] Call trace: +[ 29.564470] dump_backtrace.part.0+0xe0/0xf0 +[ 29.592602] show_stack+0x18/0x30 +[ 29.619616] dump_stack_lvl+0x64/0x80 +[ 29.646834] dump_stack+0x18/0x34 +[ 29.673541] sysfs_warn_dup+0x60/0x7c +[ 29.700592] sysfs_create_dir_ns+0xec/0x110 +[ 29.728057] kobject_add_internal+0xb8/0x374 +[ 29.755530] kobject_add+0x9c/0x104 +[ 29.782072] device_add+0xbc/0x8a0 +[ 29.808445] device_register+0x20/0x30 +[ 29.835175] genpd_dev_pm_attach_by_id+0xa4/0x190 +[ 29.862851] genpd_dev_pm_attach_by_name+0x3c/0xb0 +[ 29.890472] dev_pm_domain_attach_by_name+0x20/0x30 +[ 29.918212] adsp_probe+0x278/0x580 +[ 29.944384] platform_probe+0x68/0xc0 +[ 29.970603] really_probe+0xbc/0x2dc +[ 29.996662] __driver_probe_device+0x78/0xe0 +[ 30.023491] device_driver_attach+0x48/0xac +[ 30.050215] bind_store+0xb8/0x114 +[ 30.075957] drv_attr_store+0x24/0x3c +[ 30.101874] sysfs_kf_write+0x44/0x54 +[ 30.127751] kernfs_fop_write_iter+0x120/0x1f0 +[ 30.154448] vfs_write+0x1ac/0x380 +[ 30.179937] ksys_write+0x70/0x104 +[ 30.205274] __arm64_sys_write+0x1c/0x2c +[ 30.231060] invoke_syscall+0x48/0x114 +[ 30.256594] el0_svc_common.constprop.0+0x44/0xec +[ 30.283183] do_el0_svc+0x2c/0xd0 +[ 30.308320] el0_svc+0x2c/0x84 +[ 30.333059] el0t_64_sync_handler+0xf4/0x120 +[ 30.359001] el0t_64_sync+0x18c/0x190 +[ 30.384385] kobject_add_internal failed for genpd:0:3000000.remoteproc with -EEXIST, don't try to register things with the same name in the same directory. +[ 30.406029] remoteproc remoteproc0: releasing 3000000.remoteproc +[ 30.416064] qcom_q6v5_pas: probe of 3000000.remoteproc failed with error -17 + +Fixes: 17ee2fb4e856 ("remoteproc: qcom: pas: Vote for active/proxy power domains") +Reviewed-by: Sibi Sankar +Reviewed-by: Mukesh Ojha +Signed-off-by: Luca Weiss +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221118090816.100012-2-luca.weiss@fairphone.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 533b48522326..8b82fd598dfa 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -514,6 +514,7 @@ static int adsp_remove(struct platform_device *pdev) + qcom_remove_sysmon_subdev(adsp->sysmon); + qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); ++ adsp_pds_detach(adsp, adsp->proxy_pds, adsp->proxy_pd_count); + device_init_wakeup(adsp->dev, false); + rproc_free(adsp->rproc); + +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-qcom_q6v5_pas-disable-wakeup-on-probe-fai.patch b/queue-5.15/remoteproc-qcom_q6v5_pas-disable-wakeup-on-probe-fai.patch new file mode 100644 index 00000000000..2d23536f236 --- /dev/null +++ b/queue-5.15/remoteproc-qcom_q6v5_pas-disable-wakeup-on-probe-fai.patch @@ -0,0 +1,58 @@ +From b51739f10f3c08f3edde0f6b8856310e89251990 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 10:08:15 +0100 +Subject: remoteproc: qcom_q6v5_pas: disable wakeup on probe fail or remove + +From: Luca Weiss + +[ Upstream commit 9a70551996e699fda262e8d54bbd41739d7aad6d ] + +Leaving wakeup enabled during probe fail (-EPROBE_DEFER) or remove makes +the subsequent probe fail. + +[ 3.749454] remoteproc remoteproc0: releasing 3000000.remoteproc +[ 3.752949] qcom_q6v5_pas: probe of 3000000.remoteproc failed with error -17 +[ 3.878935] remoteproc remoteproc0: releasing 4080000.remoteproc +[ 3.887602] qcom_q6v5_pas: probe of 4080000.remoteproc failed with error -17 +[ 4.319552] remoteproc remoteproc0: releasing 8300000.remoteproc +[ 4.332716] qcom_q6v5_pas: probe of 8300000.remoteproc failed with error -17 + +Fix this by disabling wakeup in both cases so the driver can properly +probe on the next try. + +Fixes: a781e5aa5911 ("remoteproc: core: Prevent system suspend during remoteproc recovery") +Fixes: dc86c129b4fb ("remoteproc: qcom: pas: Mark devices as wakeup capable") +Reviewed-by: Mukesh Ojha +Signed-off-by: Luca Weiss +Reviewed-by: Caleb Connolly +Reviewed-by: Sibi Sankar +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221118090816.100012-1-luca.weiss@fairphone.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 78d90d856e40..533b48522326 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -498,6 +498,7 @@ static int adsp_probe(struct platform_device *pdev) + detach_active_pds: + adsp_pds_detach(adsp, adsp->active_pds, adsp->active_pd_count); + free_rproc: ++ device_init_wakeup(adsp->dev, false); + rproc_free(rproc); + + return ret; +@@ -513,6 +514,7 @@ static int adsp_remove(struct platform_device *pdev) + qcom_remove_sysmon_subdev(adsp->sysmon); + qcom_remove_smd_subdev(adsp->rproc, &adsp->smd_subdev); + qcom_remove_ssr_subdev(adsp->rproc, &adsp->ssr_subdev); ++ device_init_wakeup(adsp->dev, false); + rproc_free(adsp->rproc); + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-qcom_q6v5_pas-fix-missing-of_node_put-in-.patch b/queue-5.15/remoteproc-qcom_q6v5_pas-fix-missing-of_node_put-in-.patch new file mode 100644 index 00000000000..1f6dc29d694 --- /dev/null +++ b/queue-5.15/remoteproc-qcom_q6v5_pas-fix-missing-of_node_put-in-.patch @@ -0,0 +1,37 @@ +From 164883b5857947a904fad884a2aa5c6cdc1fa57c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 3 Dec 2022 07:06:39 +0000 +Subject: remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in + adsp_alloc_memory_region() + +From: Yuan Can + +[ Upstream commit 38e7d9c19276832ebb0277f415b9214bf7baeb37 ] + +The pointer node is returned by of_parse_phandle() with refcount +incremented. We should use of_node_put() on it when done. + +Fixes: b9e718e950c3 ("remoteproc: Introduce Qualcomm ADSP PIL") +Signed-off-by: Yuan Can +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221203070639.15128-1-yuancan@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_q6v5_pas.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c +index 8b82fd598dfa..fbcbc00f2e64 100644 +--- a/drivers/remoteproc/qcom_q6v5_pas.c ++++ b/drivers/remoteproc/qcom_q6v5_pas.c +@@ -386,6 +386,7 @@ static int adsp_alloc_memory_region(struct qcom_adsp *adsp) + } + + ret = of_address_to_resource(node, 0, &r); ++ of_node_put(node); + if (ret) + return ret; + +-- +2.35.1 + diff --git a/queue-5.15/remoteproc-sysmon-fix-memory-leak-in-qcom_add_sysmon.patch b/queue-5.15/remoteproc-sysmon-fix-memory-leak-in-qcom_add_sysmon.patch new file mode 100644 index 00000000000..a15fa655402 --- /dev/null +++ b/queue-5.15/remoteproc-sysmon-fix-memory-leak-in-qcom_add_sysmon.patch @@ -0,0 +1,48 @@ +From 73a291b30b9a9a8854d7fba2c675b5235bbd5f6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 18:56:50 +0800 +Subject: remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev() + +From: Gaosheng Cui + +[ Upstream commit e01ce676aaef3b13d02343d7e70f9637d93a3367 ] + +The kfree() should be called when of_irq_get_byname() fails or +devm_request_threaded_irq() fails in qcom_add_sysmon_subdev(), +otherwise there will be a memory leak, so add kfree() to fix it. + +Fixes: 027045a6e2b7 ("remoteproc: qcom: Add shutdown-ack irq") +Signed-off-by: Gaosheng Cui +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221129105650.1539187-1-cuigaosheng1@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/qcom_sysmon.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/remoteproc/qcom_sysmon.c b/drivers/remoteproc/qcom_sysmon.c +index a9f04dd83ab6..fbfaf2637a91 100644 +--- a/drivers/remoteproc/qcom_sysmon.c ++++ b/drivers/remoteproc/qcom_sysmon.c +@@ -650,7 +650,9 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + if (sysmon->shutdown_irq != -ENODATA) { + dev_err(sysmon->dev, + "failed to retrieve shutdown-ack IRQ\n"); +- return ERR_PTR(sysmon->shutdown_irq); ++ ret = sysmon->shutdown_irq; ++ kfree(sysmon); ++ return ERR_PTR(ret); + } + } else { + ret = devm_request_threaded_irq(sysmon->dev, +@@ -661,6 +663,7 @@ struct qcom_sysmon *qcom_add_sysmon_subdev(struct rproc *rproc, + if (ret) { + dev_err(sysmon->dev, + "failed to acquire shutdown-ack IRQ\n"); ++ kfree(sysmon); + return ERR_PTR(ret); + } + } +-- +2.35.1 + diff --git a/queue-5.15/revert-drm-amd-display-limit-max-dsc-target-bpp-for-.patch b/queue-5.15/revert-drm-amd-display-limit-max-dsc-target-bpp-for-.patch new file mode 100644 index 00000000000..fc78c792bbc --- /dev/null +++ b/queue-5.15/revert-drm-amd-display-limit-max-dsc-target-bpp-for-.patch @@ -0,0 +1,79 @@ +From d24e2f1cf271b33f264776cfab4dba93e3fe97da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2022 15:04:36 -0400 +Subject: Revert "drm/amd/display: Limit max DSC target bpp for specific + monitors" + +From: Hamza Mahfooz + +[ Upstream commit 6803dfd3a69ccb318772463a86e40929fd4fbac7 ] + +This reverts commit 55eea8ef98641f6e1e1c202bd3a49a57c1dd4059. + +This quirk is now handled in the DRM core, so we can drop all of +the internal code that was added to handle it. + +Reviewed-by: Harry Wentland +Signed-off-by: Hamza Mahfooz +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 35 ------------------- + 1 file changed, 35 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +index d793eec69d61..6fee12c91ef5 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +@@ -40,39 +40,6 @@ + + #include "dm_helpers.h" + +-struct monitor_patch_info { +- unsigned int manufacturer_id; +- unsigned int product_id; +- void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param); +- unsigned int patch_param; +-}; +-static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param); +- +-static const struct monitor_patch_info monitor_patch_table[] = { +-{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15}, +-{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15}, +-}; +- +-static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param) +-{ +- if (edid_caps) +- edid_caps->panel_patch.max_dsc_target_bpp_limit = param; +-} +- +-static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps) +-{ +- int i, ret = 0; +- +- for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++) +- if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id) +- && (edid_caps->product_id == monitor_patch_table[i].product_id)) { +- monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param); +- ret++; +- } +- +- return ret; +-} +- + /* dm_helpers_parse_edid_caps + * + * Parse edid caps +@@ -158,8 +125,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( + kfree(sads); + kfree(sadb); + +- amdgpu_dm_patch_edid_caps(edid_caps); +- + return result; + } + +-- +2.35.1 + diff --git a/queue-5.15/risc-v-align-the-shadow-stack.patch b/queue-5.15/risc-v-align-the-shadow-stack.patch new file mode 100644 index 00000000000..9cf76c5a1d6 --- /dev/null +++ b/queue-5.15/risc-v-align-the-shadow-stack.patch @@ -0,0 +1,38 @@ +From 101b213bc49b15b924f8c92b5c96b4884b38a776 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 18:35:14 -0800 +Subject: RISC-V: Align the shadow stack + +From: Palmer Dabbelt + +[ Upstream commit b003b3b77d65133a0011ae3b7b255347438c12f6 ] + +The standard RISC-V ABIs all require 16-byte stack alignment. We're +only calling that one function on the shadow stack so I doubt it'd +result in a real issue, but might as well keep this lined up. + +Fixes: 31da94c25aea ("riscv: add VMAP_STACK overflow detection") +Reviewed-by: Jisheng Zhang +Link: https://lore.kernel.org/r/20221130023515.20217-1-palmer@rivosinc.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/kernel/traps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c +index 2f4cd85fb651..4102c97309cc 100644 +--- a/arch/riscv/kernel/traps.c ++++ b/arch/riscv/kernel/traps.c +@@ -211,7 +211,7 @@ static DEFINE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], + * shadow stack, handled_ kernel_ stack_ overflow(in kernel/entry.S) is used + * to get per-cpu overflow stack(get_overflow_stack). + */ +-long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)]; ++long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE/sizeof(long)] __aligned(16); + asmlinkage unsigned long get_overflow_stack(void) + { + return (unsigned long)this_cpu_ptr(overflow_stack) + +-- +2.35.1 + diff --git a/queue-5.15/riscv-bpf-emit-fixed-length-instructions-for-bpf_pse.patch b/queue-5.15/riscv-bpf-emit-fixed-length-instructions-for-bpf_pse.patch new file mode 100644 index 00000000000..206a2bf9d4d --- /dev/null +++ b/queue-5.15/riscv-bpf-emit-fixed-length-instructions-for-bpf_pse.patch @@ -0,0 +1,81 @@ +From d266508d8b821d76e1d738a9e505ad4123c2f794 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Dec 2022 17:14:10 +0800 +Subject: riscv, bpf: Emit fixed-length instructions for BPF_PSEUDO_FUNC +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pu Lehui + +[ Upstream commit b54b6003612a376e7be32cbc5c1af3754bbbbb3d ] + +For BPF_PSEUDO_FUNC instruction, verifier will refill imm with +correct addresses of bpf_calls and then run last pass of JIT. +Since the emit_imm of RV64 is variable-length, which will emit +appropriate length instructions accorroding to the imm, it may +broke ctx->offset, and lead to unpredictable problem, such as +inaccurate jump. So let's fix it with fixed-length instructions. + +Fixes: 69c087ba6225 ("bpf: Add bpf_for_each_map_elem() helper") +Suggested-by: Björn Töpel +Signed-off-by: Pu Lehui +Signed-off-by: Daniel Borkmann +Reviewed-by: Björn Töpel +Acked-by: Björn Töpel +Link: https://lore.kernel.org/bpf/20221206091410.1584784-1-pulehui@huaweicloud.com +Signed-off-by: Sasha Levin +--- + arch/riscv/net/bpf_jit_comp64.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c +index 3af4131c22c7..2e3f1a626a3a 100644 +--- a/arch/riscv/net/bpf_jit_comp64.c ++++ b/arch/riscv/net/bpf_jit_comp64.c +@@ -120,6 +120,25 @@ static bool in_auipc_jalr_range(s64 val) + val < ((1L << 31) - (1L << 11)); + } + ++/* Emit fixed-length instructions for address */ ++static int emit_addr(u8 rd, u64 addr, bool extra_pass, struct rv_jit_context *ctx) ++{ ++ u64 ip = (u64)(ctx->insns + ctx->ninsns); ++ s64 off = addr - ip; ++ s64 upper = (off + (1 << 11)) >> 12; ++ s64 lower = off & 0xfff; ++ ++ if (extra_pass && !in_auipc_jalr_range(off)) { ++ pr_err("bpf-jit: target offset 0x%llx is out of range\n", off); ++ return -ERANGE; ++ } ++ ++ emit(rv_auipc(rd, upper), ctx); ++ emit(rv_addi(rd, rd, lower), ctx); ++ return 0; ++} ++ ++/* Emit variable-length instructions for 32-bit and 64-bit imm */ + static void emit_imm(u8 rd, s64 val, struct rv_jit_context *ctx) + { + /* Note that the immediate from the add is sign-extended, +@@ -887,7 +906,15 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, + u64 imm64; + + imm64 = (u64)insn1.imm << 32 | (u32)imm; +- emit_imm(rd, imm64, ctx); ++ if (bpf_pseudo_func(insn)) { ++ /* fixed-length insns for extra jit pass */ ++ ret = emit_addr(rd, imm64, extra_pass, ctx); ++ if (ret) ++ return ret; ++ } else { ++ emit_imm(rd, imm64, ctx); ++ } ++ + return 1; + } + +-- +2.35.1 + diff --git a/queue-5.15/riscv-mm-add-arch-hook-arch_clear_hugepage_flags.patch b/queue-5.15/riscv-mm-add-arch-hook-arch_clear_hugepage_flags.patch new file mode 100644 index 00000000000..8d3b133550a --- /dev/null +++ b/queue-5.15/riscv-mm-add-arch-hook-arch_clear_hugepage_flags.patch @@ -0,0 +1,46 @@ +From f4c713a810eb9b32fb352b217085abd13ff96c68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 09:47:25 +0000 +Subject: riscv/mm: add arch hook arch_clear_hugepage_flags + +From: Tong Tiangen + +[ Upstream commit d8bf77a1dc3079692f54be3087a5fd16d90027b0 ] + +With the PG_arch_1 we keep track if the page's data cache is clean, +architecture rely on this property to treat new pages as dirty with +respect to the data cache and perform the flushing before mapping the pages +into userspace. + +This patch adds a new architecture hook, arch_clear_hugepage_flags,so that +architectures which rely on the page flags being in a particular state for +fresh allocations can adjust the flags accordingly when a page is freed +into the pool. + +Fixes: 9e953cda5cdf ("riscv: Introduce huge page support for 32/64bit kernel") +Signed-off-by: Tong Tiangen +Link: https://lore.kernel.org/r/20221024094725.3054311-3-tongtiangen@huawei.com +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + arch/riscv/include/asm/hugetlb.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h +index a5c2ca1d1cd8..ec19d6afc896 100644 +--- a/arch/riscv/include/asm/hugetlb.h ++++ b/arch/riscv/include/asm/hugetlb.h +@@ -5,4 +5,10 @@ + #include + #include + ++static inline void arch_clear_hugepage_flags(struct page *page) ++{ ++ clear_bit(PG_dcache_clean, &page->flags); ++} ++#define arch_clear_hugepage_flags arch_clear_hugepage_flags ++ + #endif /* _ASM_RISCV_HUGETLB_H */ +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-call-cmos_wake_setup-from-cmos_do_probe.patch b/queue-5.15/rtc-cmos-call-cmos_wake_setup-from-cmos_do_probe.patch new file mode 100644 index 00000000000..1d0f9a114ff --- /dev/null +++ b/queue-5.15/rtc-cmos-call-cmos_wake_setup-from-cmos_do_probe.patch @@ -0,0 +1,147 @@ +From a84fedb7e0adf0d7bc3f8afdaaf9e8e77a98493c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 13:07:08 +0100 +Subject: rtc: cmos: Call cmos_wake_setup() from cmos_do_probe() + +From: Rafael J. Wysocki + +[ Upstream commit 508ccdfb86b21da37ad091003a4d4567709d5dfb ] + +Notice that cmos_wake_setup() is the only user of acpi_rtc_info and it +can operate on the cmos_rtc variable directly, so it need not set the +platform_data pointer before cmos_do_probe() is called. Instead, it +can be called by cmos_do_probe() in the case when the platform_data +pointer is not set to implement the default behavior (which is to use +the FADT information as long as ACPI support is enabled). + +Modify the code accordingly. + +While at it, drop a comment that doesn't really match the code it is +supposed to be describing. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Zhang Rui +Tested-by: Zhang Rui +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/4803444.31r3eYUQgx@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 47 ++++++++++++++++++++---------------------- + 1 file changed, 22 insertions(+), 25 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 58cc2bae2f8a..a84262265d6d 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -744,6 +744,8 @@ static irqreturn_t cmos_interrupt(int irq, void *p) + return IRQ_NONE; + } + ++static void cmos_wake_setup(struct device *dev); ++ + #ifdef CONFIG_PNP + #define INITSECTION + +@@ -827,19 +829,27 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + if (info->address_space) + address_space = info->address_space; + +- if (info->rtc_day_alarm && info->rtc_day_alarm < 128) +- cmos_rtc.day_alrm = info->rtc_day_alarm; +- if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) +- cmos_rtc.mon_alrm = info->rtc_mon_alarm; +- if (info->rtc_century && info->rtc_century < 128) +- cmos_rtc.century = info->rtc_century; ++ cmos_rtc.day_alrm = info->rtc_day_alarm; ++ cmos_rtc.mon_alrm = info->rtc_mon_alarm; ++ cmos_rtc.century = info->rtc_century; + + if (info->wake_on && info->wake_off) { + cmos_rtc.wake_on = info->wake_on; + cmos_rtc.wake_off = info->wake_off; + } ++ } else { ++ cmos_wake_setup(dev); + } + ++ if (cmos_rtc.day_alrm >= 128) ++ cmos_rtc.day_alrm = 0; ++ ++ if (cmos_rtc.mon_alrm >= 128) ++ cmos_rtc.mon_alrm = 0; ++ ++ if (cmos_rtc.century >= 128) ++ cmos_rtc.century = 0; ++ + cmos_rtc.dev = dev; + dev_set_drvdata(dev, &cmos_rtc); + +@@ -1275,13 +1285,6 @@ static void use_acpi_alarm_quirks(void) + static inline void use_acpi_alarm_quirks(void) { } + #endif + +-/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find +- * its device node and pass extra config data. This helps its driver use +- * capabilities that the now-obsolete mc146818 didn't have, and informs it +- * that this board's RTC is wakeup-capable (per ACPI spec). +- */ +-static struct cmos_rtc_board_info acpi_rtc_info; +- + static void cmos_wake_setup(struct device *dev) + { + if (acpi_disabled) +@@ -1289,26 +1292,23 @@ static void cmos_wake_setup(struct device *dev) + + use_acpi_alarm_quirks(); + +- acpi_rtc_info.wake_on = rtc_wake_on; +- acpi_rtc_info.wake_off = rtc_wake_off; ++ cmos_rtc.wake_on = rtc_wake_on; ++ cmos_rtc.wake_off = rtc_wake_off; + +- /* workaround bug in some ACPI tables */ ++ /* ACPI tables bug workaround. */ + if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { + dev_dbg(dev, "bogus FADT month_alarm (%d)\n", + acpi_gbl_FADT.month_alarm); + acpi_gbl_FADT.month_alarm = 0; + } + +- acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; +- acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; +- acpi_rtc_info.rtc_century = acpi_gbl_FADT.century; ++ cmos_rtc.day_alrm = acpi_gbl_FADT.day_alarm; ++ cmos_rtc.mon_alrm = acpi_gbl_FADT.month_alarm; ++ cmos_rtc.century = acpi_gbl_FADT.century; + +- /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ + if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) + dev_info(dev, "RTC can wake from S4\n"); + +- dev->platform_data = &acpi_rtc_info; +- + /* RTC always wakes from S1/S2/S3, and often S4/STD */ + device_init_wakeup(dev, 1); + } +@@ -1359,8 +1359,6 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + { + int irq, ret; + +- cmos_wake_setup(&pnp->dev); +- + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { + irq = 0; + #ifdef CONFIG_X86 +@@ -1468,7 +1466,6 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + int irq, ret; + + cmos_of_init(pdev); +- cmos_wake_setup(&pdev->dev); + + if (RTC_IOMAPPED) + resource = platform_get_resource(pdev, IORESOURCE_IO, 0); +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-call-rtc_wake_setup-from-cmos_do_probe.patch b/queue-5.15/rtc-cmos-call-rtc_wake_setup-from-cmos_do_probe.patch new file mode 100644 index 00000000000..d2846f2022a --- /dev/null +++ b/queue-5.15/rtc-cmos-call-rtc_wake_setup-from-cmos_do_probe.patch @@ -0,0 +1,103 @@ +From 2edc0d02e1d4ed7b29b7d5f51bff2e032dd7ac5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 13:09:07 +0100 +Subject: rtc: cmos: Call rtc_wake_setup() from cmos_do_probe() + +From: Rafael J. Wysocki + +[ Upstream commit 375bbba09692fe4c5218eddee8e312dd733fa846 ] + +To reduce code duplication, move the invocation of rtc_wake_setup() +into cmos_do_probe() and simplify the callers of the latter. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Zhang Rui +Tested-by: Zhang Rui +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/2143522.irdbgypaU6@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index a84262265d6d..583116994a37 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -744,6 +744,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p) + return IRQ_NONE; + } + ++static inline void rtc_wake_setup(struct device *dev); + static void cmos_wake_setup(struct device *dev); + + #ifdef CONFIG_PNP +@@ -938,6 +939,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + nvmem_cfg.size = address_space - NVRAM_OFFSET; + devm_rtc_nvmem_register(cmos_rtc.rtc, &nvmem_cfg); + ++ /* ++ * Everything has gone well so far, so by default register a handler for ++ * the ACPI RTC fixed event. ++ */ ++ if (!info) ++ rtc_wake_setup(dev); ++ + dev_info(dev, "%s%s, %d bytes nvram%s\n", + !is_valid_irq(rtc_irq) ? "no alarms" : + cmos_rtc.mon_alrm ? "alarms up to one year" : +@@ -1357,7 +1365,7 @@ static void rtc_wake_setup(struct device *dev) + + static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + { +- int irq, ret; ++ int irq; + + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { + irq = 0; +@@ -1373,13 +1381,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + irq = pnp_irq(pnp, 0); + } + +- ret = cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); +- if (ret) +- return ret; +- +- rtc_wake_setup(&pnp->dev); +- +- return 0; ++ return cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); + } + + static void cmos_pnp_remove(struct pnp_dev *pnp) +@@ -1463,7 +1465,7 @@ static inline void cmos_of_init(struct platform_device *pdev) {} + static int __init cmos_platform_probe(struct platform_device *pdev) + { + struct resource *resource; +- int irq, ret; ++ int irq; + + cmos_of_init(pdev); + +@@ -1475,13 +1477,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + if (irq < 0) + irq = -1; + +- ret = cmos_do_probe(&pdev->dev, resource, irq); +- if (ret) +- return ret; +- +- rtc_wake_setup(&pdev->dev); +- +- return 0; ++ return cmos_do_probe(&pdev->dev, resource, irq); + } + + static int cmos_platform_remove(struct platform_device *pdev) +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-disable-acpi-rtc-event-on-removal.patch b/queue-5.15/rtc-cmos-disable-acpi-rtc-event-on-removal.patch new file mode 100644 index 00000000000..6fa27186697 --- /dev/null +++ b/queue-5.15/rtc-cmos-disable-acpi-rtc-event-on-removal.patch @@ -0,0 +1,68 @@ +From b164fb92a4a7e0f692860a11e25fdd6a97e67e99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 13:15:36 +0100 +Subject: rtc: cmos: Disable ACPI RTC event on removal + +From: Rafael J. Wysocki + +[ Upstream commit 83ebb7b3036d151ee39a4a752018665648fc3bd4 ] + +Make cmos_do_remove() drop the ACPI RTC fixed event handler so as to +prevent it from operating on stale data in case the event triggers +after driver removal. + +Fixes: 311ee9c151ad ("rtc: cmos: allow using ACPI for RTC alarm instead of HPET") +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Zhang Rui +Tested-by: Zhang Rui +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/2224609.iZASKD2KPV@kreacher +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 039486bfedf4..00e2ca7374ec 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -798,6 +798,14 @@ static void acpi_rtc_event_setup(struct device *dev) + acpi_disable_event(ACPI_EVENT_RTC, 0); + } + ++static void acpi_rtc_event_cleanup(void) ++{ ++ if (acpi_disabled) ++ return; ++ ++ acpi_remove_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler); ++} ++ + static void rtc_wake_on(struct device *dev) + { + acpi_clear_event(ACPI_EVENT_RTC); +@@ -884,6 +892,10 @@ static inline void acpi_rtc_event_setup(struct device *dev) + { + } + ++static inline void acpi_rtc_event_cleanup(void) ++{ ++} ++ + static inline void acpi_cmos_wake_setup(struct device *dev) + { + } +@@ -1138,6 +1150,9 @@ static void cmos_do_remove(struct device *dev) + hpet_unregister_irq_handler(cmos_interrupt); + } + ++ if (!dev_get_platdata(dev)) ++ acpi_rtc_event_cleanup(); ++ + cmos->rtc = NULL; + + ports = cmos->iomem; +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-eliminate-forward-declarations-of-some-func.patch b/queue-5.15/rtc-cmos-eliminate-forward-declarations-of-some-func.patch new file mode 100644 index 00000000000..56c96715902 --- /dev/null +++ b/queue-5.15/rtc-cmos-eliminate-forward-declarations-of-some-func.patch @@ -0,0 +1,362 @@ +From 81c132b04f90391b422d297f3f689be1bf29b201 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 13:09:32 +0100 +Subject: rtc: cmos: Eliminate forward declarations of some functions + +From: Rafael J. Wysocki + +[ Upstream commit dca4d3b71c8a09a16951add656711fbd6f5bfbb0 ] + +Reorder the ACPI-related code before cmos_do_probe() so as to eliminate +excessive forward declarations of some functions. + +While at it, for consistency, add the inline modifier to the +definitions of empty stub static funtions and remove it from the +corresponding definitions of functions with non-empty bodies. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Zhang Rui +Tested-by: Zhang Rui +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/13157911.uLZWGnKmhe@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 304 ++++++++++++++++++++--------------------- + 1 file changed, 149 insertions(+), 155 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 583116994a37..2a21d8281aa6 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -744,8 +744,155 @@ static irqreturn_t cmos_interrupt(int irq, void *p) + return IRQ_NONE; + } + +-static inline void rtc_wake_setup(struct device *dev); +-static void cmos_wake_setup(struct device *dev); ++#ifdef CONFIG_ACPI ++ ++#include ++ ++static u32 rtc_handler(void *context) ++{ ++ struct device *dev = context; ++ struct cmos_rtc *cmos = dev_get_drvdata(dev); ++ unsigned char rtc_control = 0; ++ unsigned char rtc_intr; ++ unsigned long flags; ++ ++ ++ /* ++ * Always update rtc irq when ACPI is used as RTC Alarm. ++ * Or else, ACPI SCI is enabled during suspend/resume only, ++ * update rtc irq in that case. ++ */ ++ if (cmos_use_acpi_alarm()) ++ cmos_interrupt(0, (void *)cmos->rtc); ++ else { ++ /* Fix me: can we use cmos_interrupt() here as well? */ ++ spin_lock_irqsave(&rtc_lock, flags); ++ if (cmos_rtc.suspend_ctrl) ++ rtc_control = CMOS_READ(RTC_CONTROL); ++ if (rtc_control & RTC_AIE) { ++ cmos_rtc.suspend_ctrl &= ~RTC_AIE; ++ CMOS_WRITE(rtc_control, RTC_CONTROL); ++ rtc_intr = CMOS_READ(RTC_INTR_FLAGS); ++ rtc_update_irq(cmos->rtc, 1, rtc_intr); ++ } ++ spin_unlock_irqrestore(&rtc_lock, flags); ++ } ++ ++ pm_wakeup_hard_event(dev); ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++ return ACPI_INTERRUPT_HANDLED; ++} ++ ++static void rtc_wake_setup(struct device *dev) ++{ ++ if (acpi_disabled) ++ return; ++ ++ acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); ++ /* ++ * After the RTC handler is installed, the Fixed_RTC event should ++ * be disabled. Only when the RTC alarm is set will it be enabled. ++ */ ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++} ++ ++static void rtc_wake_on(struct device *dev) ++{ ++ acpi_clear_event(ACPI_EVENT_RTC); ++ acpi_enable_event(ACPI_EVENT_RTC, 0); ++} ++ ++static void rtc_wake_off(struct device *dev) ++{ ++ acpi_disable_event(ACPI_EVENT_RTC, 0); ++} ++ ++#ifdef CONFIG_X86 ++/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */ ++static void use_acpi_alarm_quirks(void) ++{ ++ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) ++ return; ++ ++ if (!is_hpet_enabled()) ++ return; ++ ++ if (dmi_get_bios_year() < 2015) ++ return; ++ ++ use_acpi_alarm = true; ++} ++#else ++static inline void use_acpi_alarm_quirks(void) { } ++#endif ++ ++static void cmos_wake_setup(struct device *dev) ++{ ++ if (acpi_disabled) ++ return; ++ ++ use_acpi_alarm_quirks(); ++ ++ cmos_rtc.wake_on = rtc_wake_on; ++ cmos_rtc.wake_off = rtc_wake_off; ++ ++ /* ACPI tables bug workaround. */ ++ if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { ++ dev_dbg(dev, "bogus FADT month_alarm (%d)\n", ++ acpi_gbl_FADT.month_alarm); ++ acpi_gbl_FADT.month_alarm = 0; ++ } ++ ++ cmos_rtc.day_alrm = acpi_gbl_FADT.day_alarm; ++ cmos_rtc.mon_alrm = acpi_gbl_FADT.month_alarm; ++ cmos_rtc.century = acpi_gbl_FADT.century; ++ ++ if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) ++ dev_info(dev, "RTC can wake from S4\n"); ++ ++ /* RTC always wakes from S1/S2/S3, and often S4/STD */ ++ device_init_wakeup(dev, 1); ++} ++ ++static void cmos_check_acpi_rtc_status(struct device *dev, ++ unsigned char *rtc_control) ++{ ++ struct cmos_rtc *cmos = dev_get_drvdata(dev); ++ acpi_event_status rtc_status; ++ acpi_status status; ++ ++ if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC) ++ return; ++ ++ status = acpi_get_event_status(ACPI_EVENT_RTC, &rtc_status); ++ if (ACPI_FAILURE(status)) { ++ dev_err(dev, "Could not get RTC status\n"); ++ } else if (rtc_status & ACPI_EVENT_FLAG_SET) { ++ unsigned char mask; ++ *rtc_control &= ~RTC_AIE; ++ CMOS_WRITE(*rtc_control, RTC_CONTROL); ++ mask = CMOS_READ(RTC_INTR_FLAGS); ++ rtc_update_irq(cmos->rtc, 1, mask); ++ } ++} ++ ++#else /* !CONFIG_ACPI */ ++ ++static inline void rtc_wake_setup(struct device *dev) ++{ ++} ++ ++static inline void cmos_wake_setup(struct device *dev) ++{ ++} ++ ++static inline void cmos_check_acpi_rtc_status(struct device *dev, ++ unsigned char *rtc_control) ++{ ++} ++#endif /* CONFIG_ACPI */ + + #ifdef CONFIG_PNP + #define INITSECTION +@@ -1140,9 +1287,6 @@ static void cmos_check_wkalrm(struct device *dev) + } + } + +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control); +- + static int __maybe_unused cmos_resume(struct device *dev) + { + struct cmos_rtc *cmos = dev_get_drvdata(dev); +@@ -1209,156 +1353,6 @@ static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume); + * predate even PNPBIOS should set up platform_bus devices. + */ + +-#ifdef CONFIG_ACPI +- +-#include +- +-static u32 rtc_handler(void *context) +-{ +- struct device *dev = context; +- struct cmos_rtc *cmos = dev_get_drvdata(dev); +- unsigned char rtc_control = 0; +- unsigned char rtc_intr; +- unsigned long flags; +- +- +- /* +- * Always update rtc irq when ACPI is used as RTC Alarm. +- * Or else, ACPI SCI is enabled during suspend/resume only, +- * update rtc irq in that case. +- */ +- if (cmos_use_acpi_alarm()) +- cmos_interrupt(0, (void *)cmos->rtc); +- else { +- /* Fix me: can we use cmos_interrupt() here as well? */ +- spin_lock_irqsave(&rtc_lock, flags); +- if (cmos_rtc.suspend_ctrl) +- rtc_control = CMOS_READ(RTC_CONTROL); +- if (rtc_control & RTC_AIE) { +- cmos_rtc.suspend_ctrl &= ~RTC_AIE; +- CMOS_WRITE(rtc_control, RTC_CONTROL); +- rtc_intr = CMOS_READ(RTC_INTR_FLAGS); +- rtc_update_irq(cmos->rtc, 1, rtc_intr); +- } +- spin_unlock_irqrestore(&rtc_lock, flags); +- } +- +- pm_wakeup_hard_event(dev); +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_disable_event(ACPI_EVENT_RTC, 0); +- return ACPI_INTERRUPT_HANDLED; +-} +- +-static inline void rtc_wake_setup(struct device *dev) +-{ +- if (acpi_disabled) +- return; +- +- acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); +- /* +- * After the RTC handler is installed, the Fixed_RTC event should +- * be disabled. Only when the RTC alarm is set will it be enabled. +- */ +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_disable_event(ACPI_EVENT_RTC, 0); +-} +- +-static void rtc_wake_on(struct device *dev) +-{ +- acpi_clear_event(ACPI_EVENT_RTC); +- acpi_enable_event(ACPI_EVENT_RTC, 0); +-} +- +-static void rtc_wake_off(struct device *dev) +-{ +- acpi_disable_event(ACPI_EVENT_RTC, 0); +-} +- +-#ifdef CONFIG_X86 +-/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */ +-static void use_acpi_alarm_quirks(void) +-{ +- if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) +- return; +- +- if (!is_hpet_enabled()) +- return; +- +- if (dmi_get_bios_year() < 2015) +- return; +- +- use_acpi_alarm = true; +-} +-#else +-static inline void use_acpi_alarm_quirks(void) { } +-#endif +- +-static void cmos_wake_setup(struct device *dev) +-{ +- if (acpi_disabled) +- return; +- +- use_acpi_alarm_quirks(); +- +- cmos_rtc.wake_on = rtc_wake_on; +- cmos_rtc.wake_off = rtc_wake_off; +- +- /* ACPI tables bug workaround. */ +- if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { +- dev_dbg(dev, "bogus FADT month_alarm (%d)\n", +- acpi_gbl_FADT.month_alarm); +- acpi_gbl_FADT.month_alarm = 0; +- } +- +- cmos_rtc.day_alrm = acpi_gbl_FADT.day_alarm; +- cmos_rtc.mon_alrm = acpi_gbl_FADT.month_alarm; +- cmos_rtc.century = acpi_gbl_FADT.century; +- +- if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) +- dev_info(dev, "RTC can wake from S4\n"); +- +- /* RTC always wakes from S1/S2/S3, and often S4/STD */ +- device_init_wakeup(dev, 1); +-} +- +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control) +-{ +- struct cmos_rtc *cmos = dev_get_drvdata(dev); +- acpi_event_status rtc_status; +- acpi_status status; +- +- if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC) +- return; +- +- status = acpi_get_event_status(ACPI_EVENT_RTC, &rtc_status); +- if (ACPI_FAILURE(status)) { +- dev_err(dev, "Could not get RTC status\n"); +- } else if (rtc_status & ACPI_EVENT_FLAG_SET) { +- unsigned char mask; +- *rtc_control &= ~RTC_AIE; +- CMOS_WRITE(*rtc_control, RTC_CONTROL); +- mask = CMOS_READ(RTC_INTR_FLAGS); +- rtc_update_irq(cmos->rtc, 1, mask); +- } +-} +- +-#else +- +-static void cmos_wake_setup(struct device *dev) +-{ +-} +- +-static void cmos_check_acpi_rtc_status(struct device *dev, +- unsigned char *rtc_control) +-{ +-} +- +-static void rtc_wake_setup(struct device *dev) +-{ +-} +-#endif +- + #ifdef CONFIG_PNP + + #include +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-fix-build-on-non-acpi-platforms.patch b/queue-5.15/rtc-cmos-fix-build-on-non-acpi-platforms.patch new file mode 100644 index 00000000000..f22127136ae --- /dev/null +++ b/queue-5.15/rtc-cmos-fix-build-on-non-acpi-platforms.patch @@ -0,0 +1,38 @@ +From f2a84ae06c34e27dd9943f58d69e5f1f98d1ff4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 22:35:11 +0200 +Subject: rtc: cmos: fix build on non-ACPI platforms + +From: Alexandre Belloni + +[ Upstream commit db4e955ae333567dea02822624106c0b96a2f84f ] + +Now that rtc_wake_setup is called outside of cmos_wake_setup, it also need +to be defined on non-ACPI platforms. + +Reported-by: kernel test robot +Link: https://lore.kernel.org/r/20221018203512.2532407-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 01fb31f8e534..58cc2bae2f8a 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -1346,6 +1346,9 @@ static void cmos_check_acpi_rtc_status(struct device *dev, + { + } + ++static void rtc_wake_setup(struct device *dev) ++{ ++} + #endif + + #ifdef CONFIG_PNP +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-fix-event-handler-registration-ordering-iss.patch b/queue-5.15/rtc-cmos-fix-event-handler-registration-ordering-iss.patch new file mode 100644 index 00000000000..5f5bffae45b --- /dev/null +++ b/queue-5.15/rtc-cmos-fix-event-handler-registration-ordering-iss.patch @@ -0,0 +1,124 @@ +From 65294bba25b36c858437fac0ec7cff65c303a2c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Oct 2022 20:07:01 +0200 +Subject: rtc: cmos: Fix event handler registration ordering issue + +From: Rafael J. Wysocki + +[ Upstream commit 4919d3eb2ec0ee364f7e3cf2d99646c1b224fae8 ] + +Because acpi_install_fixed_event_handler() enables the event +automatically on success, it is incorrect to call it before the +handler routine passed to it is ready to handle events. + +Unfortunately, the rtc-cmos driver does exactly the incorrect thing +by calling cmos_wake_setup(), which passes rtc_handler() to +acpi_install_fixed_event_handler(), before cmos_do_probe(), because +rtc_handler() uses dev_get_drvdata() to get to the cmos object +pointer and the driver data pointer is only populated in +cmos_do_probe(). + +This leads to a NULL pointer dereference in rtc_handler() on boot +if the RTC fixed event happens to be active at the init time. + +To address this issue, change the initialization ordering of the +driver so that cmos_wake_setup() is always called after a successful +cmos_do_probe() call. + +While at it, change cmos_pnp_probe() to call cmos_do_probe() after +the initial if () statement used for computing the IRQ argument to +be passed to cmos_do_probe() which is cleaner than calling it in +each branch of that if () (local variable "irq" can be of type int, +because it is passed to that function as an argument of type int). + +Note that commit 6492fed7d8c9 ("rtc: rtc-cmos: Do not check +ACPI_FADT_LOW_POWER_S0") caused this issue to affect a larger number +of systems, because previously it only affected systems with +ACPI_FADT_LOW_POWER_S0 set, but it is present regardless of that +commit. + +Fixes: 6492fed7d8c9 ("rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0") +Fixes: a474aaedac99 ("rtc-cmos: move wake setup from ACPI glue into RTC driver") +Link: https://lore.kernel.org/linux-acpi/20221010141630.zfzi7mk7zvnmclzy@techsingularity.net/ +Reported-by: Mel Gorman +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Bjorn Helgaas +Tested-by: Mel Gorman +Link: https://lore.kernel.org/r/5629262.DvuYhMxLoT@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index bdb1df843c78..610413b4e9ca 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -1352,10 +1352,10 @@ static void cmos_check_acpi_rtc_status(struct device *dev, + + static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + { +- cmos_wake_setup(&pnp->dev); ++ int irq, ret; + + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { +- unsigned int irq = 0; ++ irq = 0; + #ifdef CONFIG_X86 + /* Some machines contain a PNP entry for the RTC, but + * don't define the IRQ. It should always be safe to +@@ -1364,13 +1364,17 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + if (nr_legacy_irqs()) + irq = RTC_IRQ; + #endif +- return cmos_do_probe(&pnp->dev, +- pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); + } else { +- return cmos_do_probe(&pnp->dev, +- pnp_get_resource(pnp, IORESOURCE_IO, 0), +- pnp_irq(pnp, 0)); ++ irq = pnp_irq(pnp, 0); + } ++ ++ ret = cmos_do_probe(&pnp->dev, pnp_get_resource(pnp, IORESOURCE_IO, 0), irq); ++ if (ret) ++ return ret; ++ ++ cmos_wake_setup(&pnp->dev); ++ ++ return 0; + } + + static void cmos_pnp_remove(struct pnp_dev *pnp) +@@ -1454,10 +1458,9 @@ static inline void cmos_of_init(struct platform_device *pdev) {} + static int __init cmos_platform_probe(struct platform_device *pdev) + { + struct resource *resource; +- int irq; ++ int irq, ret; + + cmos_of_init(pdev); +- cmos_wake_setup(&pdev->dev); + + if (RTC_IOMAPPED) + resource = platform_get_resource(pdev, IORESOURCE_IO, 0); +@@ -1467,7 +1470,13 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + if (irq < 0) + irq = -1; + +- return cmos_do_probe(&pdev->dev, resource, irq); ++ ret = cmos_do_probe(&pdev->dev, resource, irq); ++ if (ret) ++ return ret; ++ ++ cmos_wake_setup(&pdev->dev); ++ ++ return 0; + } + + static int cmos_platform_remove(struct platform_device *pdev) +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-fix-wake-alarm-breakage.patch b/queue-5.15/rtc-cmos-fix-wake-alarm-breakage.patch new file mode 100644 index 00000000000..9515fb27191 --- /dev/null +++ b/queue-5.15/rtc-cmos-fix-wake-alarm-breakage.patch @@ -0,0 +1,92 @@ +From 9f8a2c23c1264c8fd5ef85c2eeb61f09e83e6a00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 18:09:31 +0200 +Subject: rtc: cmos: Fix wake alarm breakage + +From: Rafael J. Wysocki + +[ Upstream commit 0782b66ed2fbb035dda76111df0954515e417b24 ] + +Commit 4919d3eb2ec0 ("rtc: cmos: Fix event handler registration +ordering issue") overlooked the fact that cmos_do_probe() depended +on the preparations carried out by cmos_wake_setup() and the wake +alarm stopped working after the ordering of them had been changed. + +Address this by partially reverting commit 4919d3eb2ec0 so that +cmos_wake_setup() is called before cmos_do_probe() again and moving +the rtc_wake_setup() invocation from cmos_wake_setup() directly to the +callers of cmos_do_probe() where it will happen after a successful +completion of the latter. + +Fixes: 4919d3eb2ec0 ("rtc: cmos: Fix event handler registration ordering issue") +Reported-by: Zhang Rui +Reported-by: Todd Brandt +Signed-off-by: Rafael J. Wysocki +Link: https://lore.kernel.org/r/5887691.lOV4Wx5bFT@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 610413b4e9ca..01fb31f8e534 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -1233,6 +1233,9 @@ static u32 rtc_handler(void *context) + + static inline void rtc_wake_setup(struct device *dev) + { ++ if (acpi_disabled) ++ return; ++ + acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, dev); + /* + * After the RTC handler is installed, the Fixed_RTC event should +@@ -1286,7 +1289,6 @@ static void cmos_wake_setup(struct device *dev) + + use_acpi_alarm_quirks(); + +- rtc_wake_setup(dev); + acpi_rtc_info.wake_on = rtc_wake_on; + acpi_rtc_info.wake_off = rtc_wake_off; + +@@ -1354,6 +1356,8 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + { + int irq, ret; + ++ cmos_wake_setup(&pnp->dev); ++ + if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) { + irq = 0; + #ifdef CONFIG_X86 +@@ -1372,7 +1376,7 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) + if (ret) + return ret; + +- cmos_wake_setup(&pnp->dev); ++ rtc_wake_setup(&pnp->dev); + + return 0; + } +@@ -1461,6 +1465,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + int irq, ret; + + cmos_of_init(pdev); ++ cmos_wake_setup(&pdev->dev); + + if (RTC_IOMAPPED) + resource = platform_get_resource(pdev, IORESOURCE_IO, 0); +@@ -1474,7 +1479,7 @@ static int __init cmos_platform_probe(struct platform_device *pdev) + if (ret) + return ret; + +- cmos_wake_setup(&pdev->dev); ++ rtc_wake_setup(&pdev->dev); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/rtc-cmos-rename-acpi-related-functions.patch b/queue-5.15/rtc-cmos-rename-acpi-related-functions.patch new file mode 100644 index 00000000000..7681f3b36c5 --- /dev/null +++ b/queue-5.15/rtc-cmos-rename-acpi-related-functions.patch @@ -0,0 +1,87 @@ +From 72790daa7ff5723a89f93f89257de2287b65fd7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 13:12:00 +0100 +Subject: rtc: cmos: Rename ACPI-related functions + +From: Rafael J. Wysocki + +[ Upstream commit d13e9ad9f5146f066a5c5a1cc993d09e4fb21ead ] + +The names of rtc_wake_setup() and cmos_wake_setup() don't indicate +that these functions are ACPI-related, which is the case, and the +former doesn't really reflect the role of the function. + +Rename them to acpi_rtc_event_setup() and acpi_cmos_wake_setup(), +respectively, to address this shortcoming. + +No intentional functional impact. + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Zhang Rui +Tested-by: Zhang Rui +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/3225614.44csPzL39Z@kreacher +Signed-off-by: Alexandre Belloni +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 2a21d8281aa6..039486bfedf4 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -784,7 +784,7 @@ static u32 rtc_handler(void *context) + return ACPI_INTERRUPT_HANDLED; + } + +-static void rtc_wake_setup(struct device *dev) ++static void acpi_rtc_event_setup(struct device *dev) + { + if (acpi_disabled) + return; +@@ -828,7 +828,7 @@ static void use_acpi_alarm_quirks(void) + static inline void use_acpi_alarm_quirks(void) { } + #endif + +-static void cmos_wake_setup(struct device *dev) ++static void acpi_cmos_wake_setup(struct device *dev) + { + if (acpi_disabled) + return; +@@ -880,11 +880,11 @@ static void cmos_check_acpi_rtc_status(struct device *dev, + + #else /* !CONFIG_ACPI */ + +-static inline void rtc_wake_setup(struct device *dev) ++static inline void acpi_rtc_event_setup(struct device *dev) + { + } + +-static inline void cmos_wake_setup(struct device *dev) ++static inline void acpi_cmos_wake_setup(struct device *dev) + { + } + +@@ -986,7 +986,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + cmos_rtc.wake_off = info->wake_off; + } + } else { +- cmos_wake_setup(dev); ++ acpi_cmos_wake_setup(dev); + } + + if (cmos_rtc.day_alrm >= 128) +@@ -1091,7 +1091,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) + * the ACPI RTC fixed event. + */ + if (!info) +- rtc_wake_setup(dev); ++ acpi_rtc_event_setup(dev); + + dev_info(dev, "%s%s, %d bytes nvram%s\n", + !is_valid_irq(rtc_irq) ? "no alarms" : +-- +2.35.1 + diff --git a/queue-5.15/rtc-mxc_v2-add-missing-clk_disable_unprepare.patch b/queue-5.15/rtc-mxc_v2-add-missing-clk_disable_unprepare.patch new file mode 100644 index 00000000000..55e75ef047f --- /dev/null +++ b/queue-5.15/rtc-mxc_v2-add-missing-clk_disable_unprepare.patch @@ -0,0 +1,40 @@ +From 6dad8e1b2efe1d3e91a03b3a49c2ae8d60f02e28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 16:50:46 +0800 +Subject: rtc: mxc_v2: Add missing clk_disable_unprepare() + +From: GUO Zihua + +[ Upstream commit 55d5a86618d3b1a768bce01882b74cbbd2651975 ] + +The call to clk_disable_unprepare() is left out in the error handling of +devm_rtc_allocate_device. Add it back. + +Fixes: 5490a1e018a4 ("rtc: mxc_v2: fix possible race condition") +Signed-off-by: GUO Zihua +Link: https://lore.kernel.org/r/20221122085046.21689-1-guozihua@huawei.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-mxc_v2.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c +index 5e0383401629..f6d2ad91ff7a 100644 +--- a/drivers/rtc/rtc-mxc_v2.c ++++ b/drivers/rtc/rtc-mxc_v2.c +@@ -336,8 +336,10 @@ static int mxc_rtc_probe(struct platform_device *pdev) + } + + pdata->rtc = devm_rtc_allocate_device(&pdev->dev); +- if (IS_ERR(pdata->rtc)) ++ if (IS_ERR(pdata->rtc)) { ++ clk_disable_unprepare(pdata->clk); + return PTR_ERR(pdata->rtc); ++ } + + pdata->rtc->ops = &mxc_rtc_ops; + pdata->rtc->range_max = U32_MAX; +-- +2.35.1 + diff --git a/queue-5.15/rtc-pcf85063-fix-pcf85063_clkout_control.patch b/queue-5.15/rtc-pcf85063-fix-pcf85063_clkout_control.patch new file mode 100644 index 00000000000..683a3c2c55e --- /dev/null +++ b/queue-5.15/rtc-pcf85063-fix-pcf85063_clkout_control.patch @@ -0,0 +1,37 @@ +From 31aa39204e0275f1f5e1a3bc1701949c13a8f6fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Dec 2022 23:35:53 +0100 +Subject: rtc: pcf85063: fix pcf85063_clkout_control + +From: Alexandre Belloni + +[ Upstream commit c2d12e85336f6d4172fb2bab5935027c446d7343 ] + +pcf85063_clkout_control reads the wrong register but then update the +correct one. + +Reported-by: Janne Terho +Fixes: 8c229ab6048b ("rtc: pcf85063: Add pcf85063 clkout control to common clock framework") +Link: https://lore.kernel.org/r/20221211223553.59955-1-alexandre.belloni@bootlin.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-pcf85063.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c +index 3e2837722667..bf2e370907b7 100644 +--- a/drivers/rtc/rtc-pcf85063.c ++++ b/drivers/rtc/rtc-pcf85063.c +@@ -422,7 +422,7 @@ static int pcf85063_clkout_control(struct clk_hw *hw, bool enable) + unsigned int buf; + int ret; + +- ret = regmap_read(pcf85063->regmap, PCF85063_REG_OFFSET, &buf); ++ ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &buf); + if (ret < 0) + return ret; + buf &= PCF85063_REG_CLKO_F_MASK; +-- +2.35.1 + diff --git a/queue-5.15/rtc-pcf85063-fix-reading-alarm.patch b/queue-5.15/rtc-pcf85063-fix-reading-alarm.patch new file mode 100644 index 00000000000..723368b05b2 --- /dev/null +++ b/queue-5.15/rtc-pcf85063-fix-reading-alarm.patch @@ -0,0 +1,46 @@ +From 1198144261fe83072b31ec033fb855bd87e6dbde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 09:41:41 +0200 +Subject: rtc: pcf85063: Fix reading alarm + +From: Alexander Stein + +[ Upstream commit a6ceee26fd5ed9b5bd37322b1ca88e4548cee4a3 ] + +If the alarms are disabled the topmost bit (AEN_*) is set in the alarm +registers. This is also interpreted in BCD number leading to this warning: +rtc rtc0: invalid alarm value: 2022-09-21T80:80:80 + +Fix this by masking alarm enabling and reserved bits. + +Fixes: 05cb3a56ee8c ("rtc: pcf85063: add alarm support") +Signed-off-by: Alexander Stein +Link: https://lore.kernel.org/r/20220921074141.3903104-1-alexander.stein@ew.tq-group.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-pcf85063.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c +index 14da4ab30104..3e2837722667 100644 +--- a/drivers/rtc/rtc-pcf85063.c ++++ b/drivers/rtc/rtc-pcf85063.c +@@ -167,10 +167,10 @@ static int pcf85063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) + if (ret) + return ret; + +- alrm->time.tm_sec = bcd2bin(buf[0]); +- alrm->time.tm_min = bcd2bin(buf[1]); +- alrm->time.tm_hour = bcd2bin(buf[2]); +- alrm->time.tm_mday = bcd2bin(buf[3]); ++ alrm->time.tm_sec = bcd2bin(buf[0] & 0x7f); ++ alrm->time.tm_min = bcd2bin(buf[1] & 0x7f); ++ alrm->time.tm_hour = bcd2bin(buf[2] & 0x3f); ++ alrm->time.tm_mday = bcd2bin(buf[3] & 0x3f); + + ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val); + if (ret) +-- +2.35.1 + diff --git a/queue-5.15/rtc-pic32-move-devm_rtc_allocate_device-earlier-in-p.patch b/queue-5.15/rtc-pic32-move-devm_rtc_allocate_device-earlier-in-p.patch new file mode 100644 index 00000000000..7fea0985c2d --- /dev/null +++ b/queue-5.15/rtc-pic32-move-devm_rtc_allocate_device-earlier-in-p.patch @@ -0,0 +1,52 @@ +From a35335c29e0aef837fab4508ebf41f8bbca82114 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 09:59:53 +0800 +Subject: rtc: pic32: Move devm_rtc_allocate_device earlier in + pic32_rtc_probe() + +From: Gaosheng Cui + +[ Upstream commit 90cd5c88830140c9fade92a8027e0fb2c6e4cc49 ] + +The pic32_rtc_enable(pdata, 0) and clk_disable_unprepare(pdata->clk) +should be called in the error handling of devm_rtc_allocate_device(), +so we should move devm_rtc_allocate_device earlier in pic32_rtc_probe() +to fix it. + +Fixes: 6515e23b9fde ("rtc: pic32: convert to devm_rtc_allocate_device") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221123015953.1998521-1-cuigaosheng1@huawei.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-pic32.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c +index 7fb9145c43bd..fa351ac20158 100644 +--- a/drivers/rtc/rtc-pic32.c ++++ b/drivers/rtc/rtc-pic32.c +@@ -324,16 +324,16 @@ static int pic32_rtc_probe(struct platform_device *pdev) + + spin_lock_init(&pdata->alarm_lock); + ++ pdata->rtc = devm_rtc_allocate_device(&pdev->dev); ++ if (IS_ERR(pdata->rtc)) ++ return PTR_ERR(pdata->rtc); ++ + clk_prepare_enable(pdata->clk); + + pic32_rtc_enable(pdata, 1); + + device_init_wakeup(&pdev->dev, 1); + +- pdata->rtc = devm_rtc_allocate_device(&pdev->dev); +- if (IS_ERR(pdata->rtc)) +- return PTR_ERR(pdata->rtc); +- + pdata->rtc->ops = &pic32_rtcops; + pdata->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + pdata->rtc->range_max = RTC_TIMESTAMP_END_2099; +-- +2.35.1 + diff --git a/queue-5.15/rtc-rtc-cmos-do-not-check-acpi_fadt_low_power_s0.patch b/queue-5.15/rtc-rtc-cmos-do-not-check-acpi_fadt_low_power_s0.patch new file mode 100644 index 00000000000..7c6481f9374 --- /dev/null +++ b/queue-5.15/rtc-rtc-cmos-do-not-check-acpi_fadt_low_power_s0.patch @@ -0,0 +1,58 @@ +From f1c3a2fc0c318ae1a6960edd55da71429043117a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Aug 2022 20:23:59 +0200 +Subject: rtc: rtc-cmos: Do not check ACPI_FADT_LOW_POWER_S0 + +From: Rafael J. Wysocki + +[ Upstream commit 6492fed7d8c95f53b0b804ef541324d924d95d41 ] + +The ACPI_FADT_LOW_POWER_S0 flag merely means that it is better to +use low-power S0 idle on the given platform than S3 (provided that +the latter is supported) and it doesn't preclude using either of +them (which of them will be used depends on the choices made by user +space). + +For this reason, there is no benefit from checking that flag in +use_acpi_alarm_quirks(). + +First off, it cannot be a bug to do S3 with use_acpi_alarm set, +because S3 can be used on systems with ACPI_FADT_LOW_POWER_S0 and it +must work if really supported, so the ACPI_FADT_LOW_POWER_S0 check is +not needed to protect the S3-capable systems from failing. + +Second, suspend-to-idle can be carried out on a system with +ACPI_FADT_LOW_POWER_S0 unset and it is expected to work, so if setting +use_acpi_alarm is needed to handle that case correctly, it should be +set regardless of the ACPI_FADT_LOW_POWER_S0 value. + +Accordingly, drop the ACPI_FADT_LOW_POWER_S0 check from +use_acpi_alarm_quirks(). + +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Mario Limonciello +Signed-off-by: Alexandre Belloni +Link: https://lore.kernel.org/r/12054246.O9o76ZdvQC@kreacher +Stable-dep-of: 83ebb7b3036d ("rtc: cmos: Disable ACPI RTC event on removal") +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-cmos.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index 7c006c2b125f..bdb1df843c78 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -1260,9 +1260,6 @@ static void use_acpi_alarm_quirks(void) + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return; + +- if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)) +- return; +- + if (!is_hpet_enabled()) + return; + +-- +2.35.1 + diff --git a/queue-5.15/rtc-snvs-allow-a-time-difference-on-clock-register-r.patch b/queue-5.15/rtc-snvs-allow-a-time-difference-on-clock-register-r.patch new file mode 100644 index 00000000000..1be2c1eacf4 --- /dev/null +++ b/queue-5.15/rtc-snvs-allow-a-time-difference-on-clock-register-r.patch @@ -0,0 +1,92 @@ +From 01d428df094de9a650bb740e16ae40daa8040318 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 6 Nov 2022 12:59:15 +0100 +Subject: rtc: snvs: Allow a time difference on clock register read + +From: Stefan Eichenberger + +[ Upstream commit 0462681e207ccc44778a77b3297af728b1cf5b9f ] + +On an iMX6ULL the following message appears when a wakealarm is set: + +echo 0 > /sys/class/rtc/rtc1/wakealarm +rtc rtc1: Timeout trying to get valid LPSRT Counter read + +This does not always happen but is reproducible quite often (7 out of 10 +times). The problem appears because the iMX6ULL is not able to read the +registers within one 32kHz clock cycle which is the base clock of the +RTC. Therefore, this patch allows a difference of up to 320 cycles +(10ms). 10ms was chosen to be big enough even on systems with less cpu +power (e.g. iMX6ULL). According to the reference manual a difference is +fine: +- If the two consecutive reads are similar, the value is correct. +The values have to be similar, not equal. + +Fixes: cd7f3a249dbe ("rtc: snvs: Add timeouts to avoid kernel lockups") +Reviewed-by: Francesco Dolcini +Signed-off-by: Stefan Eichenberger +Signed-off-by: Francesco Dolcini +Link: https://lore.kernel.org/r/20221106115915.7930-1-francesco@dolcini.it +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-snvs.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c +index bd929b0e7d7d..d82acf1af1fa 100644 +--- a/drivers/rtc/rtc-snvs.c ++++ b/drivers/rtc/rtc-snvs.c +@@ -32,6 +32,14 @@ + #define SNVS_LPPGDR_INIT 0x41736166 + #define CNTR_TO_SECS_SH 15 + ++/* The maximum RTC clock cycles that are allowed to pass between two ++ * consecutive clock counter register reads. If the values are corrupted a ++ * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles ++ * we end at 10ms which should be enough for most cases. If it once takes ++ * longer than expected we do a retry. ++ */ ++#define MAX_RTC_READ_DIFF_CYCLES 320 ++ + struct snvs_rtc_data { + struct rtc_device *rtc; + struct regmap *regmap; +@@ -56,6 +64,7 @@ static u64 rtc_read_lpsrt(struct snvs_rtc_data *data) + static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + { + u64 read1, read2; ++ s64 diff; + unsigned int timeout = 100; + + /* As expected, the registers might update between the read of the LSB +@@ -66,7 +75,8 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + do { + read2 = read1; + read1 = rtc_read_lpsrt(data); +- } while (read1 != read2 && --timeout); ++ diff = read1 - read2; ++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); + if (!timeout) + dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); + +@@ -78,13 +88,15 @@ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) + static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb) + { + u32 count1, count2; ++ s32 diff; + unsigned int timeout = 100; + + regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); + do { + count2 = count1; + regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); +- } while (count1 != count2 && --timeout); ++ diff = count1 - count2; ++ } while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout); + if (!timeout) { + dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n"); + return -ETIMEDOUT; +-- +2.35.1 + diff --git a/queue-5.15/rtc-st-lpc-add-missing-clk_disable_unprepare-in-st_r.patch b/queue-5.15/rtc-st-lpc-add-missing-clk_disable_unprepare-in-st_r.patch new file mode 100644 index 00000000000..bee83e99b9b --- /dev/null +++ b/queue-5.15/rtc-st-lpc-add-missing-clk_disable_unprepare-in-st_r.patch @@ -0,0 +1,36 @@ +From b8420952d73a41d66527bb5a112fab0efdda5915 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 09:48:05 +0800 +Subject: rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe() + +From: Gaosheng Cui + +[ Upstream commit 5fb733d7bd6949e90028efdce8bd528c6ab7cf1e ] + +The clk_disable_unprepare() should be called in the error handling +of clk_get_rate(), fix it. + +Fixes: b5b2bdfc2893 ("rtc: st: Add new driver for ST's LPC RTC") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221123014805.1993052-1-cuigaosheng1@huawei.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Sasha Levin +--- + drivers/rtc/rtc-st-lpc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c +index bdb20f63254e..0f8e4231098e 100644 +--- a/drivers/rtc/rtc-st-lpc.c ++++ b/drivers/rtc/rtc-st-lpc.c +@@ -238,6 +238,7 @@ static int st_rtc_probe(struct platform_device *pdev) + + rtc->clkrate = clk_get_rate(rtc->clk); + if (!rtc->clkrate) { ++ clk_disable_unprepare(rtc->clk); + dev_err(&pdev->dev, "Unable to fetch clock rate\n"); + return -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.15/rxrpc-fix-ack.buffersize-to-be-0-when-generating-an-.patch b/queue-5.15/rxrpc-fix-ack.buffersize-to-be-0-when-generating-an-.patch new file mode 100644 index 00000000000..b11ac3d13a2 --- /dev/null +++ b/queue-5.15/rxrpc-fix-ack.buffersize-to-be-0-when-generating-an-.patch @@ -0,0 +1,37 @@ +From f85c44a8b0ff517e63b38a9f61afb8d61d5a7a6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 19:17:29 +0100 +Subject: rxrpc: Fix ack.bufferSize to be 0 when generating an ack + +From: David Howells + +[ Upstream commit 8889a711f9b4dcf4dd1330fa493081beebd118c9 ] + +ack.bufferSize should be set to 0 when generating an ack. + +Fixes: 8d94aa381dab ("rxrpc: Calls shouldn't hold socket refs") +Reported-by: Jeffrey Altman +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Signed-off-by: Sasha Levin +--- + net/rxrpc/output.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c +index 9683617db704..08c117bc083e 100644 +--- a/net/rxrpc/output.c ++++ b/net/rxrpc/output.c +@@ -93,7 +93,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, + *_hard_ack = hard_ack; + *_top = top; + +- pkt->ack.bufferSpace = htons(8); ++ pkt->ack.bufferSpace = htons(0); + pkt->ack.maxSkew = htons(0); + pkt->ack.firstPacket = htonl(hard_ack + 1); + pkt->ack.previousPacket = htonl(call->ackr_highest_seq); +-- +2.35.1 + diff --git a/queue-5.15/rxrpc-fix-missing-unlock-in-rxrpc_do_sendmsg.patch b/queue-5.15/rxrpc-fix-missing-unlock-in-rxrpc_do_sendmsg.patch new file mode 100644 index 00000000000..514a51279f9 --- /dev/null +++ b/queue-5.15/rxrpc-fix-missing-unlock-in-rxrpc_do_sendmsg.patch @@ -0,0 +1,47 @@ +From 8d0799a437c3fade96867bd1459b2ef405c8818c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Dec 2022 16:19:47 +0000 +Subject: rxrpc: Fix missing unlock in rxrpc_do_sendmsg() + +From: David Howells + +[ Upstream commit 4feb2c44629e6f9b459b41a5a60491069d346a95 ] + +One of the error paths in rxrpc_do_sendmsg() doesn't unlock the call mutex +before returning. Fix it to do this. + +Note that this still doesn't get rid of the checker warning: + + ../net/rxrpc/sendmsg.c:617:5: warning: context imbalance in 'rxrpc_do_sendmsg' - wrong count at exit + +I think the interplay between the socket lock and the call's user_mutex may +be too complicated for checker to analyse, especially as +rxrpc_new_client_call_for_sendmsg(), which it calls, returns with the +call's user_mutex if successful but unconditionally drops the socket lock. + +Fixes: e754eba685aa ("rxrpc: Provide a cmsg to specify the amount of Tx data for a call") +Signed-off-by: David Howells +cc: Marc Dionne +cc: linux-afs@lists.infradead.org +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rxrpc/sendmsg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c +index 3c3a626459de..d4e4e94f4f98 100644 +--- a/net/rxrpc/sendmsg.c ++++ b/net/rxrpc/sendmsg.c +@@ -716,7 +716,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) + if (call->tx_total_len != -1 || + call->tx_pending || + call->tx_top != 0) +- goto error_put; ++ goto out_put_unlock; + call->tx_total_len = p.call.tx_total_len; + } + } +-- +2.35.1 + diff --git a/queue-5.15/s390-ctcm-fix-return-type-of-ctc-mp-m_tx.patch b/queue-5.15/s390-ctcm-fix-return-type-of-ctc-mp-m_tx.patch new file mode 100644 index 00000000000..c532d1c73d4 --- /dev/null +++ b/queue-5.15/s390-ctcm-fix-return-type-of-ctc-mp-m_tx.patch @@ -0,0 +1,76 @@ +From 814a7ed8d996889896b1e1e0a95752ccc6211b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 10:01:28 -0700 +Subject: s390/ctcm: Fix return type of ctc{mp,}m_tx() + +From: Nathan Chancellor + +[ Upstream commit aa5bf80c3c067b82b4362cd6e8e2194623bcaca6 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/s390/net/ctcm_main.c:1064:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = ctcm_tx, + ^~~~~~~ + drivers/s390/net/ctcm_main.c:1072:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = ctcmpc_tx, + ^~~~~~~~~ + +->ndo_start_xmit() in 'struct net_device_ops' expects a return type of +'netdev_tx_t', not 'int'. Adjust the return type of ctc{mp,}m_tx() to +match the prototype's to resolve the warning and potential CFI failure, +should s390 select ARCH_SUPPORTS_CFI_CLANG in the future. + +Additionally, while in the area, remove a comment block that is no +longer relevant. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reviewed-by: Alexandra Winter +Reviewed-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/ctcm_main.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c +index fd705429708e..f91b6cfd7ed0 100644 +--- a/drivers/s390/net/ctcm_main.c ++++ b/drivers/s390/net/ctcm_main.c +@@ -825,16 +825,9 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) + /** + * Start transmission of a packet. + * Called from generic network device layer. +- * +- * skb Pointer to buffer containing the packet. +- * dev Pointer to interface struct. +- * +- * returns 0 if packet consumed, !0 if packet rejected. +- * Note: If we return !0, then the packet is free'd by +- * the generic network layer. + */ + /* first merge version - leaving both functions separated */ +-static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t ctcm_tx(struct sk_buff *skb, struct net_device *dev) + { + struct ctcm_priv *priv = dev->ml_priv; + +@@ -877,7 +870,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) + } + + /* unmerged MPC variant of ctcm_tx */ +-static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) + { + int len = 0; + struct ctcm_priv *priv = dev->ml_priv; +-- +2.35.1 + diff --git a/queue-5.15/s390-lcs-fix-return-type-of-lcs_start_xmit.patch b/queue-5.15/s390-lcs-fix-return-type-of-lcs_start_xmit.patch new file mode 100644 index 00000000000..e31af7ad211 --- /dev/null +++ b/queue-5.15/s390-lcs-fix-return-type-of-lcs_start_xmit.patch @@ -0,0 +1,68 @@ +From bbfa2ddff38182b69492b19b11d257020945364c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 10:01:30 -0700 +Subject: s390/lcs: Fix return type of lcs_start_xmit() + +From: Nathan Chancellor + +[ Upstream commit bb16db8393658e0978c3f0d30ae069e878264fa3 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/s390/net/lcs.c:2090:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = lcs_start_xmit, + ^~~~~~~~~~~~~~ + drivers/s390/net/lcs.c:2097:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = lcs_start_xmit, + ^~~~~~~~~~~~~~ + +->ndo_start_xmit() in 'struct net_device_ops' expects a return type of +'netdev_tx_t', not 'int'. Adjust the return type of lcs_start_xmit() to +match the prototype's to resolve the warning and potential CFI failure, +should s390 select ARCH_SUPPORTS_CFI_CLANG in the future. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reviewed-by: Alexandra Winter +Reviewed-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/lcs.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c +index 06a322bdced6..7e743f4717a9 100644 +--- a/drivers/s390/net/lcs.c ++++ b/drivers/s390/net/lcs.c +@@ -1518,9 +1518,8 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer) + /** + * Packet transmit function called by network stack + */ +-static int +-__lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, +- struct net_device *dev) ++static netdev_tx_t __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, ++ struct net_device *dev) + { + struct lcs_header *header; + int rc = NETDEV_TX_OK; +@@ -1581,8 +1580,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, + return rc; + } + +-static int +-lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t lcs_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct lcs_card *card; + int rc; +-- +2.35.1 + diff --git a/queue-5.15/s390-netiucv-fix-return-type-of-netiucv_tx.patch b/queue-5.15/s390-netiucv-fix-return-type-of-netiucv_tx.patch new file mode 100644 index 00000000000..b97d0b1bf5a --- /dev/null +++ b/queue-5.15/s390-netiucv-fix-return-type-of-netiucv_tx.patch @@ -0,0 +1,63 @@ +From a9148c237ac565c0eec2e853164df5cf899fda94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Nov 2022 10:01:29 -0700 +Subject: s390/netiucv: Fix return type of netiucv_tx() + +From: Nathan Chancellor + +[ Upstream commit 88d86d18d7cf7e9137c95f9d212bb9fff8a1b4be ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function +pointer prototype to make sure the call target is valid to help mitigate +ROP attacks. If they are not identical, there is a failure at run time, +which manifests as either a kernel panic or thread getting killed. A +proposed warning in clang aims to catch these at compile time, which +reveals: + + drivers/s390/net/netiucv.c:1854:21: error: incompatible function pointer types initializing 'netdev_tx_t (*)(struct sk_buff *, struct net_device *)' (aka 'enum netdev_tx (*)(struct sk_buff *, struct net_device *)') with an expression of type 'int (struct sk_buff *, struct net_device *)' [-Werror,-Wincompatible-function-pointer-types-strict] + .ndo_start_xmit = netiucv_tx, + ^~~~~~~~~~ + +->ndo_start_xmit() in 'struct net_device_ops' expects a return type of +'netdev_tx_t', not 'int'. Adjust the return type of netiucv_tx() to +match the prototype's to resolve the warning and potential CFI failure, +should s390 select ARCH_SUPPORTS_CFI_CLANG in the future. + +Additionally, while in the area, remove a comment block that is no +longer relevant. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reviewed-by: Alexandra Winter +Reviewed-by: Kees Cook +Signed-off-by: Nathan Chancellor +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/s390/net/netiucv.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c +index 5a0c2f07a3a2..ce5f0ffd6cc8 100644 +--- a/drivers/s390/net/netiucv.c ++++ b/drivers/s390/net/netiucv.c +@@ -1252,15 +1252,8 @@ static int netiucv_close(struct net_device *dev) + /** + * Start transmission of a packet. + * Called from generic network device layer. +- * +- * @param skb Pointer to buffer containing the packet. +- * @param dev Pointer to interface struct. +- * +- * @return 0 if packet consumed, !0 if packet rejected. +- * Note: If we return !0, then the packet is free'd by +- * the generic network layer. + */ +-static int netiucv_tx(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t netiucv_tx(struct sk_buff *skb, struct net_device *dev) + { + struct netiucv_priv *privptr = netdev_priv(dev); + int rc; +-- +2.35.1 + diff --git a/queue-5.15/samples-vfio-mdev-fix-missing-pci_disable_device-in-.patch b/queue-5.15/samples-vfio-mdev-fix-missing-pci_disable_device-in-.patch new file mode 100644 index 00000000000..ff07225e084 --- /dev/null +++ b/queue-5.15/samples-vfio-mdev-fix-missing-pci_disable_device-in-.patch @@ -0,0 +1,59 @@ +From fc701bf815c33b7f9020308682c54562726565e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 09:33:41 +0800 +Subject: samples: vfio-mdev: Fix missing pci_disable_device() in + mdpy_fb_probe() + +From: Shang XiaoJing + +[ Upstream commit d1f0f50fbbbbca1e3e8157e51934613bf88f6d44 ] + +Add missing pci_disable_device() in fail path of mdpy_fb_probe(). +Besides, fix missing release functions in mdpy_fb_remove(). + +Fixes: cacade1946a4 ("sample: vfio mdev display - guest driver") +Signed-off-by: Shang XiaoJing +Link: https://lore.kernel.org/r/20221208013341.3999-1-shangxiaojing@huawei.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + samples/vfio-mdev/mdpy-fb.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c +index 9ec93d90e8a5..4eb7aa11cfbb 100644 +--- a/samples/vfio-mdev/mdpy-fb.c ++++ b/samples/vfio-mdev/mdpy-fb.c +@@ -109,7 +109,7 @@ static int mdpy_fb_probe(struct pci_dev *pdev, + + ret = pci_request_regions(pdev, "mdpy-fb"); + if (ret < 0) +- return ret; ++ goto err_disable_dev; + + pci_read_config_dword(pdev, MDPY_FORMAT_OFFSET, &format); + pci_read_config_dword(pdev, MDPY_WIDTH_OFFSET, &width); +@@ -191,6 +191,9 @@ static int mdpy_fb_probe(struct pci_dev *pdev, + err_release_regions: + pci_release_regions(pdev); + ++err_disable_dev: ++ pci_disable_device(pdev); ++ + return ret; + } + +@@ -199,7 +202,10 @@ static void mdpy_fb_remove(struct pci_dev *pdev) + struct fb_info *info = pci_get_drvdata(pdev); + + unregister_framebuffer(info); ++ iounmap(info->screen_base); + framebuffer_release(info); ++ pci_release_regions(pdev); ++ pci_disable_device(pdev); + } + + static struct pci_device_id mdpy_fb_pci_table[] = { +-- +2.35.1 + diff --git a/queue-5.15/sched-core-introduce-sched_asym_cpucap_active.patch b/queue-5.15/sched-core-introduce-sched_asym_cpucap_active.patch new file mode 100644 index 00000000000..c947e7a8434 --- /dev/null +++ b/queue-5.15/sched-core-introduce-sched_asym_cpucap_active.patch @@ -0,0 +1,142 @@ +From 07ff45b3f4122eabed0fe33809a699ce0dc0782a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 13:13:03 +0200 +Subject: sched/core: Introduce sched_asym_cpucap_active() + +From: Dietmar Eggemann + +[ Upstream commit 740cf8a760b73e8375bfb4bedcbe9746183350f9 ] + +Create an inline helper for conditional code to be only executed on +asymmetric CPU capacity systems. This makes these (currently ~10 and +future) conditions a lot more readable. + +Signed-off-by: Dietmar Eggemann +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/20220729111305.1275158-2-dietmar.eggemann@arm.com +Stable-dep-of: a2e7f03ed28f ("sched/uclamp: Make asym_fits_capacity() use util_fits_cpu()") +Signed-off-by: Sasha Levin +--- + kernel/sched/cpudeadline.c | 2 +- + kernel/sched/deadline.c | 4 ++-- + kernel/sched/fair.c | 8 ++++---- + kernel/sched/rt.c | 4 ++-- + kernel/sched/sched.h | 5 +++++ + 5 files changed, 14 insertions(+), 9 deletions(-) + +diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c +index ceb03d76c0cc..221ca1050573 100644 +--- a/kernel/sched/cpudeadline.c ++++ b/kernel/sched/cpudeadline.c +@@ -124,7 +124,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p, + unsigned long cap, max_cap = 0; + int cpu, max_cpu = -1; + +- if (!static_branch_unlikely(&sched_asym_cpucapacity)) ++ if (!sched_asym_cpucap_active()) + return 1; + + /* Ensure the capacity of the CPUs fits the task. */ +diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c +index 147b757d162b..2a2f32eaffcc 100644 +--- a/kernel/sched/deadline.c ++++ b/kernel/sched/deadline.c +@@ -112,7 +112,7 @@ static inline unsigned long __dl_bw_capacity(int i) + */ + static inline unsigned long dl_bw_capacity(int i) + { +- if (!static_branch_unlikely(&sched_asym_cpucapacity) && ++ if (!sched_asym_cpucap_active() && + capacity_orig_of(i) == SCHED_CAPACITY_SCALE) { + return dl_bw_cpus(i) << SCHED_CAPACITY_SHIFT; + } else { +@@ -1703,7 +1703,7 @@ select_task_rq_dl(struct task_struct *p, int cpu, int flags) + * Take the capacity of the CPU into account to + * ensure it fits the requirement of the task. + */ +- if (static_branch_unlikely(&sched_asym_cpucapacity)) ++ if (sched_asym_cpucap_active()) + select_rq |= !dl_task_fits_capacity(p, cpu); + + if (select_rq) { +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index d706c1a8453a..619fc7bd65e2 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4253,7 +4253,7 @@ static inline int task_fits_cpu(struct task_struct *p, int cpu) + + static inline void update_misfit_status(struct task_struct *p, struct rq *rq) + { +- if (!static_branch_unlikely(&sched_asym_cpucapacity)) ++ if (!sched_asym_cpucap_active()) + return; + + if (!p || p->nr_cpus_allowed == 1) { +@@ -6528,7 +6528,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + + static inline bool asym_fits_capacity(unsigned long task_util, int cpu) + { +- if (static_branch_unlikely(&sched_asym_cpucapacity)) ++ if (sched_asym_cpucap_active()) + return fits_capacity(task_util, capacity_of(cpu)); + + return true; +@@ -6548,7 +6548,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + * On asymmetric system, update task utilization because we will check + * that the task fits with cpu's capacity. + */ +- if (static_branch_unlikely(&sched_asym_cpucapacity)) { ++ if (sched_asym_cpucap_active()) { + sync_entity_load_avg(&p->se); + task_util = uclamp_task_util(p); + } +@@ -6602,7 +6602,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + * For asymmetric CPU capacity systems, our domain of interest is + * sd_asym_cpucapacity rather than sd_llc. + */ +- if (static_branch_unlikely(&sched_asym_cpucapacity)) { ++ if (sched_asym_cpucap_active()) { + sd = rcu_dereference(per_cpu(sd_asym_cpucapacity, target)); + /* + * On an asymmetric CPU capacity system where an exclusive +diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c +index f75dcd3537b8..add67f811e00 100644 +--- a/kernel/sched/rt.c ++++ b/kernel/sched/rt.c +@@ -473,7 +473,7 @@ static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu) + unsigned int cpu_cap; + + /* Only heterogeneous systems can benefit from this check */ +- if (!static_branch_unlikely(&sched_asym_cpucapacity)) ++ if (!sched_asym_cpucap_active()) + return true; + + min_cap = uclamp_eff_value(p, UCLAMP_MIN); +@@ -1736,7 +1736,7 @@ static int find_lowest_rq(struct task_struct *task) + * If we're on asym system ensure we consider the different capacities + * of the CPUs when searching for the lowest_mask. + */ +- if (static_branch_unlikely(&sched_asym_cpucapacity)) { ++ if (sched_asym_cpucap_active()) { + + ret = cpupri_find_fitness(&task_rq(task)->rd->cpupri, + task, lowest_mask, +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 4a98bb9fd881..fffb45bdddcc 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -1788,6 +1788,11 @@ DECLARE_PER_CPU(struct sched_domain __rcu *, sd_asym_packing); + DECLARE_PER_CPU(struct sched_domain __rcu *, sd_asym_cpucapacity); + extern struct static_key_false sched_asym_cpucapacity; + ++static __always_inline bool sched_asym_cpucap_active(void) ++{ ++ return static_branch_unlikely(&sched_asym_cpucapacity); ++} ++ + struct sched_group_capacity { + atomic_t ref; + /* +-- +2.35.1 + diff --git a/queue-5.15/sched-fair-cleanup-task_util-and-capacity-type.patch b/queue-5.15/sched-fair-cleanup-task_util-and-capacity-type.patch new file mode 100644 index 00000000000..f4391b039f1 --- /dev/null +++ b/queue-5.15/sched-fair-cleanup-task_util-and-capacity-type.patch @@ -0,0 +1,47 @@ +From c7e131402b15130783fba2a9f29d1d5b63c9b9f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Dec 2021 09:57:55 +0000 +Subject: sched/fair: Cleanup task_util and capacity type + +From: Vincent Donnefort + +[ Upstream commit ef8df9798d469b7c45c66664550e93469749f1e8 ] + +task_util and capacity are comparable unsigned long values. There is no +need for an intermidiate implicit signed cast. + +Signed-off-by: Vincent Donnefort +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20211207095755.859972-1-vincent.donnefort@arm.com +Stable-dep-of: 48d5e9daa8b7 ("sched/uclamp: Fix relationship between uclamp and migration margin") +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index a853e4e9e3c3..999fcb460dfd 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4120,7 +4120,8 @@ static inline void util_est_update(struct cfs_rq *cfs_rq, + trace_sched_util_est_se_tp(&p->se); + } + +-static inline int task_fits_capacity(struct task_struct *p, long capacity) ++static inline int task_fits_capacity(struct task_struct *p, ++ unsigned long capacity) + { + return fits_capacity(uclamp_task_util(p), capacity); + } +@@ -6398,7 +6399,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + return best_cpu; + } + +-static inline bool asym_fits_capacity(int task_util, int cpu) ++static inline bool asym_fits_capacity(unsigned long task_util, int cpu) + { + if (static_branch_unlikely(&sched_asym_cpucapacity)) + return fits_capacity(task_util, capacity_of(cpu)); +-- +2.35.1 + diff --git a/queue-5.15/sched-fair-removed-useless-update-of-p-recent_used_c.patch b/queue-5.15/sched-fair-removed-useless-update-of-p-recent_used_c.patch new file mode 100644 index 00000000000..6a1e173cbbe --- /dev/null +++ b/queue-5.15/sched-fair-removed-useless-update-of-p-recent_used_c.patch @@ -0,0 +1,42 @@ +From 552c62e65a61a2e32463c17af4c303dfd669b560 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Sep 2021 12:35:44 +0200 +Subject: sched/fair: Removed useless update of p->recent_used_cpu + +From: Vincent Guittot + +[ Upstream commit a7ba894821b6ade7bb420455f87020b2838d6180 ] + +Since commit 89aafd67f28c ("sched/fair: Use prev instead of new target as recent_used_cpu"), +p->recent_used_cpu is unconditionnaly set with prev. + +Fixes: 89aafd67f28c ("sched/fair: Use prev instead of new target as recent_used_cpu") +Signed-off-by: Vincent Guittot +Signed-off-by: Peter Zijlstra (Intel) +Acked-by: Mel Gorman +Link: https://lkml.kernel.org/r/20210928103544.27489-1-vincent.guittot@linaro.org +Stable-dep-of: a2e7f03ed28f ("sched/uclamp: Make asym_fits_capacity() use util_fits_cpu()") +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 9e2c6e38342c..d706c1a8453a 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6595,11 +6595,6 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && + cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) && + asym_fits_capacity(task_util, recent_used_cpu)) { +- /* +- * Replace recent_used_cpu with prev as it is a potential +- * candidate for the next wake: +- */ +- p->recent_used_cpu = prev; + return recent_used_cpu; + } + +-- +2.35.1 + diff --git a/queue-5.15/sched-sugov-ignore-busy-filter-when-rq-is-capped-by-.patch b/queue-5.15/sched-sugov-ignore-busy-filter-when-rq-is-capped-by-.patch new file mode 100644 index 00000000000..41c58d44066 --- /dev/null +++ b/queue-5.15/sched-sugov-ignore-busy-filter-when-rq-is-capped-by-.patch @@ -0,0 +1,262 @@ +From f4e13af71a0b8d8031bf04897306e52bf021dd19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Dec 2021 22:53:19 +0000 +Subject: sched/sugov: Ignore 'busy' filter when rq is capped by uclamp_max + +From: Qais Yousef + +[ Upstream commit 7a17e1db1265471f7718af100cfc5e41280d53a7 ] + +sugov_update_single_{freq, perf}() contains a 'busy' filter that ensures +we don't bring the frqeuency down if there's no idle time (CPU is busy). + +The problem is that with uclamp_max we will have scenarios where a busy +task is capped to run at a lower frequency and this filter prevents +applying the capping when this task starts running. + +We handle this by skipping the filter when uclamp is enabled and the rq +is being capped by uclamp_max. + +We introduce a new function uclamp_rq_is_capped() to help detecting when +this capping is taking effect. Some code shuffling was required to allow +using cpu_util_{cfs, rt}() in this new function. + +On 2 Core SMT2 Intel laptop I see: + +Without this patch: + + uclampset -M 0 sysbench --test=cpu --threads = 4 run + +produces a score of ~3200 consistently. Which is the highest possible. + +Compiling the kernel also results in frequency running at max 3.1GHz all +the time - running uclampset -M 400 to cap it has no effect without this +patch. + +With this patch: + + uclampset -M 0 sysbench --test=cpu --threads = 4 run + +produces a score of ~1100 with some outliers in ~1700. Uclamp max +aggregates the performance requirements, so having high values sometimes +is expected if some other task happens to require that frequency starts +running at the same time. + +When compiling the kernel with uclampset -M 400 I can see the +frequencies mostly in the ~2GHz region. Helpful to conserve power and +prevent heating when not plugged in. + +Fixes: 982d9cdc22c9 ("sched/cpufreq, sched/uclamp: Add clamps for FAIR and RT tasks") +Signed-off-by: Qais Yousef +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20211216225320.2957053-2-qais.yousef@arm.com +Stable-dep-of: b48e16a69792 ("sched/uclamp: Make task_fits_capacity() use util_fits_cpu()") +Signed-off-by: Sasha Levin +--- + kernel/sched/cpufreq_schedutil.c | 10 ++- + kernel/sched/sched.h | 139 +++++++++++++++++-------------- + 2 files changed, 86 insertions(+), 63 deletions(-) + +diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c +index 7f6bb37d3a2f..93dcea233c65 100644 +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -349,8 +349,11 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time, + /* + * Do not reduce the frequency if the CPU has not been idle + * recently, as the reduction is likely to be premature then. ++ * ++ * Except when the rq is capped by uclamp_max. + */ +- if (sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) { ++ if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) && ++ sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) { + next_f = sg_policy->next_freq; + + /* Restore cached freq as next_freq has changed */ +@@ -396,8 +399,11 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time, + /* + * Do not reduce the target performance level if the CPU has not been + * idle recently, as the reduction is likely to be premature then. ++ * ++ * Except when the rq is capped by uclamp_max. + */ +- if (sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util) ++ if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) && ++ sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util) + sg_cpu->util = prev_util; + + cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl), +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 7a3fcd70aa86..435bd7e43359 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2847,6 +2847,67 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) + static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} + #endif /* CONFIG_CPU_FREQ */ + ++#ifdef arch_scale_freq_capacity ++# ifndef arch_scale_freq_invariant ++# define arch_scale_freq_invariant() true ++# endif ++#else ++# define arch_scale_freq_invariant() false ++#endif ++ ++#ifdef CONFIG_SMP ++static inline unsigned long capacity_orig_of(int cpu) ++{ ++ return cpu_rq(cpu)->cpu_capacity_orig; ++} ++ ++/** ++ * enum cpu_util_type - CPU utilization type ++ * @FREQUENCY_UTIL: Utilization used to select frequency ++ * @ENERGY_UTIL: Utilization used during energy calculation ++ * ++ * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time ++ * need to be aggregated differently depending on the usage made of them. This ++ * enum is used within effective_cpu_util() to differentiate the types of ++ * utilization expected by the callers, and adjust the aggregation accordingly. ++ */ ++enum cpu_util_type { ++ FREQUENCY_UTIL, ++ ENERGY_UTIL, ++}; ++ ++unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, ++ unsigned long max, enum cpu_util_type type, ++ struct task_struct *p); ++ ++static inline unsigned long cpu_bw_dl(struct rq *rq) ++{ ++ return (rq->dl.running_bw * SCHED_CAPACITY_SCALE) >> BW_SHIFT; ++} ++ ++static inline unsigned long cpu_util_dl(struct rq *rq) ++{ ++ return READ_ONCE(rq->avg_dl.util_avg); ++} ++ ++static inline unsigned long cpu_util_cfs(struct rq *rq) ++{ ++ unsigned long util = READ_ONCE(rq->cfs.avg.util_avg); ++ ++ if (sched_feat(UTIL_EST)) { ++ util = max_t(unsigned long, util, ++ READ_ONCE(rq->cfs.avg.util_est.enqueued)); ++ } ++ ++ return util; ++} ++ ++static inline unsigned long cpu_util_rt(struct rq *rq) ++{ ++ return READ_ONCE(rq->avg_rt.util_avg); ++} ++#endif ++ + #ifdef CONFIG_UCLAMP_TASK + unsigned long uclamp_eff_value(struct task_struct *p, enum uclamp_id clamp_id); + +@@ -2903,6 +2964,21 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, + return clamp(util, min_util, max_util); + } + ++/* Is the rq being capped/throttled by uclamp_max? */ ++static inline bool uclamp_rq_is_capped(struct rq *rq) ++{ ++ unsigned long rq_util; ++ unsigned long max_util; ++ ++ if (!static_branch_likely(&sched_uclamp_used)) ++ return false; ++ ++ rq_util = cpu_util_cfs(cpu_of(rq)) + cpu_util_rt(rq); ++ max_util = READ_ONCE(rq->uclamp[UCLAMP_MAX].value); ++ ++ return max_util != SCHED_CAPACITY_SCALE && rq_util >= max_util; ++} ++ + /* + * When uclamp is compiled in, the aggregation at rq level is 'turned off' + * by default in the fast path and only gets turned on once userspace performs +@@ -2923,73 +2999,14 @@ unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, + return util; + } + ++static inline bool uclamp_rq_is_capped(struct rq *rq) { return false; } ++ + static inline bool uclamp_is_used(void) + { + return false; + } + #endif /* CONFIG_UCLAMP_TASK */ + +-#ifdef arch_scale_freq_capacity +-# ifndef arch_scale_freq_invariant +-# define arch_scale_freq_invariant() true +-# endif +-#else +-# define arch_scale_freq_invariant() false +-#endif +- +-#ifdef CONFIG_SMP +-static inline unsigned long capacity_orig_of(int cpu) +-{ +- return cpu_rq(cpu)->cpu_capacity_orig; +-} +- +-/** +- * enum cpu_util_type - CPU utilization type +- * @FREQUENCY_UTIL: Utilization used to select frequency +- * @ENERGY_UTIL: Utilization used during energy calculation +- * +- * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time +- * need to be aggregated differently depending on the usage made of them. This +- * enum is used within effective_cpu_util() to differentiate the types of +- * utilization expected by the callers, and adjust the aggregation accordingly. +- */ +-enum cpu_util_type { +- FREQUENCY_UTIL, +- ENERGY_UTIL, +-}; +- +-unsigned long effective_cpu_util(int cpu, unsigned long util_cfs, +- unsigned long max, enum cpu_util_type type, +- struct task_struct *p); +- +-static inline unsigned long cpu_bw_dl(struct rq *rq) +-{ +- return (rq->dl.running_bw * SCHED_CAPACITY_SCALE) >> BW_SHIFT; +-} +- +-static inline unsigned long cpu_util_dl(struct rq *rq) +-{ +- return READ_ONCE(rq->avg_dl.util_avg); +-} +- +-static inline unsigned long cpu_util_cfs(struct rq *rq) +-{ +- unsigned long util = READ_ONCE(rq->cfs.avg.util_avg); +- +- if (sched_feat(UTIL_EST)) { +- util = max_t(unsigned long, util, +- READ_ONCE(rq->cfs.avg.util_est.enqueued)); +- } +- +- return util; +-} +- +-static inline unsigned long cpu_util_rt(struct rq *rq) +-{ +- return READ_ONCE(rq->avg_rt.util_avg); +-} +-#endif +- + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ + static inline unsigned long cpu_util_irq(struct rq *rq) + { +-- +2.35.1 + diff --git a/queue-5.15/sched-uclamp-fix-relationship-between-uclamp-and-mig.patch b/queue-5.15/sched-uclamp-fix-relationship-between-uclamp-and-mig.patch new file mode 100644 index 00000000000..5794f2154e7 --- /dev/null +++ b/queue-5.15/sched-uclamp-fix-relationship-between-uclamp-and-mig.patch @@ -0,0 +1,200 @@ +From ff920b3de13e7cec61d7513030ac0d4a4de627a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 15:36:01 +0100 +Subject: sched/uclamp: Fix relationship between uclamp and migration margin + +From: Qais Yousef + +[ Upstream commit 48d5e9daa8b767e75ed9421665b037a49ce4bc04 ] + +fits_capacity() verifies that a util is within 20% margin of the +capacity of a CPU, which is an attempt to speed up upmigration. + +But when uclamp is used, this 20% margin is problematic because for +example if a task is boosted to 1024, then it will not fit on any CPU +according to fits_capacity() logic. + +Or if a task is boosted to capacity_orig_of(medium_cpu). The task will +end up on big instead on the desired medium CPU. + +Similar corner cases exist for uclamp and usage of capacity_of(). +Slightest irq pressure on biggest CPU for example will make a 1024 +boosted task look like it can't fit. + +What we really want is for uclamp comparisons to ignore the migration +margin and capacity pressure, yet retain them for when checking the +_actual_ util signal. + +For example, task p: + + p->util_avg = 300 + p->uclamp[UCLAMP_MIN] = 1024 + +Will fit a big CPU. But + + p->util_avg = 900 + p->uclamp[UCLAMP_MIN] = 1024 + +will not, this should trigger overutilized state because the big CPU is +now *actually* being saturated. + +Similar reasoning applies to capping tasks with UCLAMP_MAX. For example: + + p->util_avg = 1024 + p->uclamp[UCLAMP_MAX] = capacity_orig_of(medium_cpu) + +Should fit the task on medium cpus without triggering overutilized +state. + +Inlined comments expand more on desired behavior in more scenarios. + +Introduce new util_fits_cpu() function which encapsulates the new logic. +The new function is not used anywhere yet, but will be used to update +various users of fits_capacity() in later patches. + +Fixes: af24bde8df202 ("sched/uclamp: Add uclamp support to energy_compute()") +Signed-off-by: Qais Yousef +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20220804143609.515789-2-qais.yousef@arm.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 123 insertions(+) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 999fcb460dfd..951138dbf564 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4120,6 +4120,129 @@ static inline void util_est_update(struct cfs_rq *cfs_rq, + trace_sched_util_est_se_tp(&p->se); + } + ++static inline int util_fits_cpu(unsigned long util, ++ unsigned long uclamp_min, ++ unsigned long uclamp_max, ++ int cpu) ++{ ++ unsigned long capacity_orig, capacity_orig_thermal; ++ unsigned long capacity = capacity_of(cpu); ++ bool fits, uclamp_max_fits; ++ ++ /* ++ * Check if the real util fits without any uclamp boost/cap applied. ++ */ ++ fits = fits_capacity(util, capacity); ++ ++ if (!uclamp_is_used()) ++ return fits; ++ ++ /* ++ * We must use capacity_orig_of() for comparing against uclamp_min and ++ * uclamp_max. We only care about capacity pressure (by using ++ * capacity_of()) for comparing against the real util. ++ * ++ * If a task is boosted to 1024 for example, we don't want a tiny ++ * pressure to skew the check whether it fits a CPU or not. ++ * ++ * Similarly if a task is capped to capacity_orig_of(little_cpu), it ++ * should fit a little cpu even if there's some pressure. ++ * ++ * Only exception is for thermal pressure since it has a direct impact ++ * on available OPP of the system. ++ * ++ * We honour it for uclamp_min only as a drop in performance level ++ * could result in not getting the requested minimum performance level. ++ * ++ * For uclamp_max, we can tolerate a drop in performance level as the ++ * goal is to cap the task. So it's okay if it's getting less. ++ * ++ * In case of capacity inversion, which is not handled yet, we should ++ * honour the inverted capacity for both uclamp_min and uclamp_max all ++ * the time. ++ */ ++ capacity_orig = capacity_orig_of(cpu); ++ capacity_orig_thermal = capacity_orig - arch_scale_thermal_pressure(cpu); ++ ++ /* ++ * We want to force a task to fit a cpu as implied by uclamp_max. ++ * But we do have some corner cases to cater for.. ++ * ++ * ++ * C=z ++ * | ___ ++ * | C=y | | ++ * |_ _ _ _ _ _ _ _ _ ___ _ _ _ | _ | _ _ _ _ _ uclamp_max ++ * | C=x | | | | ++ * | ___ | | | | ++ * | | | | | | | (util somewhere in this region) ++ * | | | | | | | ++ * | | | | | | | ++ * +---------------------------------------- ++ * cpu0 cpu1 cpu2 ++ * ++ * In the above example if a task is capped to a specific performance ++ * point, y, then when: ++ * ++ * * util = 80% of x then it does not fit on cpu0 and should migrate ++ * to cpu1 ++ * * util = 80% of y then it is forced to fit on cpu1 to honour ++ * uclamp_max request. ++ * ++ * which is what we're enforcing here. A task always fits if ++ * uclamp_max <= capacity_orig. But when uclamp_max > capacity_orig, ++ * the normal upmigration rules should withhold still. ++ * ++ * Only exception is when we are on max capacity, then we need to be ++ * careful not to block overutilized state. This is so because: ++ * ++ * 1. There's no concept of capping at max_capacity! We can't go ++ * beyond this performance level anyway. ++ * 2. The system is being saturated when we're operating near ++ * max capacity, it doesn't make sense to block overutilized. ++ */ ++ uclamp_max_fits = (capacity_orig == SCHED_CAPACITY_SCALE) && (uclamp_max == SCHED_CAPACITY_SCALE); ++ uclamp_max_fits = !uclamp_max_fits && (uclamp_max <= capacity_orig); ++ fits = fits || uclamp_max_fits; ++ ++ /* ++ * ++ * C=z ++ * | ___ (region a, capped, util >= uclamp_max) ++ * | C=y | | ++ * |_ _ _ _ _ _ _ _ _ ___ _ _ _ | _ | _ _ _ _ _ uclamp_max ++ * | C=x | | | | ++ * | ___ | | | | (region b, uclamp_min <= util <= uclamp_max) ++ * |_ _ _|_ _|_ _ _ _| _ | _ _ _| _ | _ _ _ _ _ uclamp_min ++ * | | | | | | | ++ * | | | | | | | (region c, boosted, util < uclamp_min) ++ * +---------------------------------------- ++ * cpu0 cpu1 cpu2 ++ * ++ * a) If util > uclamp_max, then we're capped, we don't care about ++ * actual fitness value here. We only care if uclamp_max fits ++ * capacity without taking margin/pressure into account. ++ * See comment above. ++ * ++ * b) If uclamp_min <= util <= uclamp_max, then the normal ++ * fits_capacity() rules apply. Except we need to ensure that we ++ * enforce we remain within uclamp_max, see comment above. ++ * ++ * c) If util < uclamp_min, then we are boosted. Same as (b) but we ++ * need to take into account the boosted value fits the CPU without ++ * taking margin/pressure into account. ++ * ++ * Cases (a) and (b) are handled in the 'fits' variable already. We ++ * just need to consider an extra check for case (c) after ensuring we ++ * handle the case uclamp_min > uclamp_max. ++ */ ++ uclamp_min = min(uclamp_min, uclamp_max); ++ if (util < uclamp_min && capacity_orig != SCHED_CAPACITY_SCALE) ++ fits = fits && (uclamp_min <= capacity_orig_thermal); ++ ++ return fits; ++} ++ + static inline int task_fits_capacity(struct task_struct *p, + unsigned long capacity) + { +-- +2.35.1 + diff --git a/queue-5.15/sched-uclamp-make-asym_fits_capacity-use-util_fits_c.patch b/queue-5.15/sched-uclamp-make-asym_fits_capacity-use-util_fits_c.patch new file mode 100644 index 00000000000..b01919da40e --- /dev/null +++ b/queue-5.15/sched-uclamp-make-asym_fits_capacity-use-util_fits_c.patch @@ -0,0 +1,104 @@ +From 6102aff993e8b11655ba4a0fab175e960da75d34 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 15:36:05 +0100 +Subject: sched/uclamp: Make asym_fits_capacity() use util_fits_cpu() + +From: Qais Yousef + +[ Upstream commit a2e7f03ed28fce26c78b985f87913b6ce3accf9d ] + +Use the new util_fits_cpu() to ensure migration margin and capacity +pressure are taken into account correctly when uclamp is being used +otherwise we will fail to consider CPUs as fitting in scenarios where +they should. + +s/asym_fits_capacity/asym_fits_cpu/ to better reflect what it does now. + +Fixes: b4c9c9f15649 ("sched/fair: Prefer prev cpu in asymmetric wakeup path") +Signed-off-by: Qais Yousef +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20220804143609.515789-6-qais.yousef@arm.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 619fc7bd65e2..6648683cd964 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6526,10 +6526,13 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + return best_cpu; + } + +-static inline bool asym_fits_capacity(unsigned long task_util, int cpu) ++static inline bool asym_fits_cpu(unsigned long util, ++ unsigned long util_min, ++ unsigned long util_max, ++ int cpu) + { + if (sched_asym_cpucap_active()) +- return fits_capacity(task_util, capacity_of(cpu)); ++ return util_fits_cpu(util, util_min, util_max, cpu); + + return true; + } +@@ -6541,7 +6544,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + { + bool has_idle_core = false; + struct sched_domain *sd; +- unsigned long task_util; ++ unsigned long task_util, util_min, util_max; + int i, recent_used_cpu; + + /* +@@ -6550,7 +6553,9 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + */ + if (sched_asym_cpucap_active()) { + sync_entity_load_avg(&p->se); +- task_util = uclamp_task_util(p); ++ task_util = task_util_est(p); ++ util_min = uclamp_eff_value(p, UCLAMP_MIN); ++ util_max = uclamp_eff_value(p, UCLAMP_MAX); + } + + /* +@@ -6559,7 +6564,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + lockdep_assert_irqs_disabled(); + + if ((available_idle_cpu(target) || sched_idle_cpu(target)) && +- asym_fits_capacity(task_util, target)) ++ asym_fits_cpu(task_util, util_min, util_max, target)) + return target; + + /* +@@ -6567,7 +6572,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + */ + if (prev != target && cpus_share_cache(prev, target) && + (available_idle_cpu(prev) || sched_idle_cpu(prev)) && +- asym_fits_capacity(task_util, prev)) ++ asym_fits_cpu(task_util, util_min, util_max, prev)) + return prev; + + /* +@@ -6582,7 +6587,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + in_task() && + prev == smp_processor_id() && + this_rq()->nr_running <= 1 && +- asym_fits_capacity(task_util, prev)) { ++ asym_fits_cpu(task_util, util_min, util_max, prev)) { + return prev; + } + +@@ -6594,7 +6599,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target) + cpus_share_cache(recent_used_cpu, target) && + (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) && + cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) && +- asym_fits_capacity(task_util, recent_used_cpu)) { ++ asym_fits_cpu(task_util, util_min, util_max, recent_used_cpu)) { + return recent_used_cpu; + } + +-- +2.35.1 + diff --git a/queue-5.15/sched-uclamp-make-select_idle_capacity-use-util_fits.patch b/queue-5.15/sched-uclamp-make-select_idle_capacity-use-util_fits.patch new file mode 100644 index 00000000000..9f6b4aa38ae --- /dev/null +++ b/queue-5.15/sched-uclamp-make-select_idle_capacity-use-util_fits.patch @@ -0,0 +1,57 @@ +From d36ad82334e31142ad9ac27f5a980f9eb7ad9139 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 15:36:04 +0100 +Subject: sched/uclamp: Make select_idle_capacity() use util_fits_cpu() + +From: Qais Yousef + +[ Upstream commit b759caa1d9f667b94727b2ad12589cbc4ce13a82 ] + +Use the new util_fits_cpu() to ensure migration margin and capacity +pressure are taken into account correctly when uclamp is being used +otherwise we will fail to consider CPUs as fitting in scenarios where +they should. + +Fixes: b4c9c9f15649 ("sched/fair: Prefer prev cpu in asymmetric wakeup path") +Signed-off-by: Qais Yousef +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20220804143609.515789-5-qais.yousef@arm.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index a4c71dfae95e..9e2c6e38342c 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6498,21 +6498,23 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool + static int + select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target) + { +- unsigned long task_util, best_cap = 0; ++ unsigned long task_util, util_min, util_max, best_cap = 0; + int cpu, best_cpu = -1; + struct cpumask *cpus; + + cpus = this_cpu_cpumask_var_ptr(select_idle_mask); + cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr); + +- task_util = uclamp_task_util(p); ++ task_util = task_util_est(p); ++ util_min = uclamp_eff_value(p, UCLAMP_MIN); ++ util_max = uclamp_eff_value(p, UCLAMP_MAX); + + for_each_cpu_wrap(cpu, cpus, target) { + unsigned long cpu_cap = capacity_of(cpu); + + if (!available_idle_cpu(cpu) && !sched_idle_cpu(cpu)) + continue; +- if (fits_capacity(task_util, cpu_cap)) ++ if (util_fits_cpu(task_util, util_min, util_max, cpu)) + return cpu; + + if (cpu_cap > best_cap) { +-- +2.35.1 + diff --git a/queue-5.15/sched-uclamp-make-task_fits_capacity-use-util_fits_c.patch b/queue-5.15/sched-uclamp-make-task_fits_capacity-use-util_fits_c.patch new file mode 100644 index 00000000000..947bb7282d8 --- /dev/null +++ b/queue-5.15/sched-uclamp-make-task_fits_capacity-use-util_fits_c.patch @@ -0,0 +1,113 @@ +From a81f98cc5002f72a7e9bb193e108a108e58eee89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 15:36:02 +0100 +Subject: sched/uclamp: Make task_fits_capacity() use util_fits_cpu() + +From: Qais Yousef + +[ Upstream commit b48e16a69792b5dc4a09d6807369d11b2970cc36 ] + +So that the new uclamp rules in regard to migration margin and capacity +pressure are taken into account correctly. + +Fixes: a7008c07a568 ("sched/fair: Make task_fits_capacity() consider uclamp restrictions") +Co-developed-by: Vincent Guittot +Signed-off-by: Qais Yousef +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lore.kernel.org/r/20220804143609.515789-3-qais.yousef@arm.com +Signed-off-by: Sasha Levin +--- + kernel/sched/fair.c | 26 ++++++++++++++++---------- + kernel/sched/sched.h | 9 +++++++++ + 2 files changed, 25 insertions(+), 10 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 951138dbf564..a4c71dfae95e 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4243,10 +4243,12 @@ static inline int util_fits_cpu(unsigned long util, + return fits; + } + +-static inline int task_fits_capacity(struct task_struct *p, +- unsigned long capacity) ++static inline int task_fits_cpu(struct task_struct *p, int cpu) + { +- return fits_capacity(uclamp_task_util(p), capacity); ++ unsigned long uclamp_min = uclamp_eff_value(p, UCLAMP_MIN); ++ unsigned long uclamp_max = uclamp_eff_value(p, UCLAMP_MAX); ++ unsigned long util = task_util_est(p); ++ return util_fits_cpu(util, uclamp_min, uclamp_max, cpu); + } + + static inline void update_misfit_status(struct task_struct *p, struct rq *rq) +@@ -4259,7 +4261,7 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq) + return; + } + +- if (task_fits_capacity(p, capacity_of(cpu_of(rq)))) { ++ if (task_fits_cpu(p, cpu_of(rq))) { + rq->misfit_task_load = 0; + return; + } +@@ -8157,7 +8159,7 @@ static int detach_tasks(struct lb_env *env) + + case migrate_misfit: + /* This is not a misfit task */ +- if (task_fits_capacity(p, capacity_of(env->src_cpu))) ++ if (task_fits_cpu(p, env->src_cpu)) + goto next; + + env->imbalance = 0; +@@ -9042,6 +9044,10 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd, + + memset(sgs, 0, sizeof(*sgs)); + ++ /* Assume that task can't fit any CPU of the group */ ++ if (sd->flags & SD_ASYM_CPUCAPACITY) ++ sgs->group_misfit_task_load = 1; ++ + for_each_cpu(i, sched_group_span(group)) { + struct rq *rq = cpu_rq(i); + unsigned int local; +@@ -9061,12 +9067,12 @@ static inline void update_sg_wakeup_stats(struct sched_domain *sd, + if (!nr_running && idle_cpu_without(i, p)) + sgs->idle_cpus++; + +- } ++ /* Check if task fits in the CPU */ ++ if (sd->flags & SD_ASYM_CPUCAPACITY && ++ sgs->group_misfit_task_load && ++ task_fits_cpu(p, i)) ++ sgs->group_misfit_task_load = 0; + +- /* Check if task fits in the group */ +- if (sd->flags & SD_ASYM_CPUCAPACITY && +- !task_fits_capacity(p, group->sgc->max_capacity)) { +- sgs->group_misfit_task_load = 1; + } + + sgs->group_capacity = group->sgc->capacity; +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index 435bd7e43359..4a98bb9fd881 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2992,6 +2992,15 @@ static inline bool uclamp_is_used(void) + return static_branch_likely(&sched_uclamp_used); + } + #else /* CONFIG_UCLAMP_TASK */ ++static inline unsigned long uclamp_eff_value(struct task_struct *p, ++ enum uclamp_id clamp_id) ++{ ++ if (clamp_id == UCLAMP_MIN) ++ return 0; ++ ++ return SCHED_CAPACITY_SCALE; ++} ++ + static inline + unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, + struct task_struct *p) +-- +2.35.1 + diff --git a/queue-5.15/scsi-core-fix-a-race-between-scsi_done-and-scsi_time.patch b/queue-5.15/scsi-core-fix-a-race-between-scsi_done-and-scsi_time.patch new file mode 100644 index 00000000000..e87e3b2a421 --- /dev/null +++ b/queue-5.15/scsi-core-fix-a-race-between-scsi_done-and-scsi_time.patch @@ -0,0 +1,64 @@ +From b43e94377de042b8b735cf1802daaf7155854a01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 13:29:49 -0700 +Subject: scsi: core: Fix a race between scsi_done() and scsi_timeout() + +From: Bart Van Assche + +[ Upstream commit 978b7922d3dca672b41bb4b8ce6c06ab77112741 ] + +If there is a race between scsi_done() and scsi_timeout() and if +scsi_timeout() loses the race, scsi_timeout() should not reset the request +timer. Hence change the return value for this case from BLK_EH_RESET_TIMER +into BLK_EH_DONE. + +Although the block layer holds a reference on a request (req->ref) while +calling a timeout handler, restarting the timer (blk_add_timer()) while a +request is being completed is racy. + +Reviewed-by: Mike Christie +Cc: Keith Busch +Cc: Christoph Hellwig +Cc: Ming Lei +Cc: John Garry +Cc: Hannes Reinecke +Reported-by: Adrian Hunter +Fixes: 15f73f5b3e59 ("blk-mq: move failure injection out of blk_mq_complete_request") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20221018202958.1902564-2-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_error.c | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c +index bb5a6e0fa49a..dd9f5778f687 100644 +--- a/drivers/scsi/scsi_error.c ++++ b/drivers/scsi/scsi_error.c +@@ -343,19 +343,11 @@ enum blk_eh_timer_return scsi_times_out(struct request *req) + + if (rtn == BLK_EH_DONE) { + /* +- * Set the command to complete first in order to prevent a real +- * completion from releasing the command while error handling +- * is using it. If the command was already completed, then the +- * lower level driver beat the timeout handler, and it is safe +- * to return without escalating error recovery. +- * +- * If timeout handling lost the race to a real completion, the +- * block layer may ignore that due to a fake timeout injection, +- * so return RESET_TIMER to allow error handling another shot +- * at this command. ++ * If scsi_done() has already set SCMD_STATE_COMPLETE, do not ++ * modify *scmd. + */ + if (test_and_set_bit(SCMD_STATE_COMPLETE, &scmd->state)) +- return BLK_EH_RESET_TIMER; ++ return BLK_EH_DONE; + if (scsi_abort_command(scmd) != SUCCESS) { + set_host_byte(scmd, DID_TIME_OUT); + scsi_eh_scmd_add(scmd); +-- +2.35.1 + diff --git a/queue-5.15/scsi-efct-fix-possible-memleak-in-efct_device_init.patch b/queue-5.15/scsi-efct-fix-possible-memleak-in-efct_device_init.patch new file mode 100644 index 00000000000..890f0fc781c --- /dev/null +++ b/queue-5.15/scsi-efct-fix-possible-memleak-in-efct_device_init.patch @@ -0,0 +1,48 @@ +From 42e7c570fdc37e2f3301b90f8097107be99eade0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 15:40:46 +0800 +Subject: scsi: efct: Fix possible memleak in efct_device_init() + +From: Chen Zhongjin + +[ Upstream commit bb0cd225dd37df1f4a22e36dad59ff33178ecdfc ] + +In efct_device_init(), when efct_scsi_reg_fc_transport() fails, +efct_scsi_tgt_driver_exit() is not called to release memory for +efct_scsi_tgt_driver_init() and causes memleak: + +unreferenced object 0xffff8881020ce000 (size 2048): + comm "modprobe", pid 465, jiffies 4294928222 (age 55.872s) + backtrace: + [<0000000021a1ef1b>] kmalloc_trace+0x27/0x110 + [<000000004c3ed51c>] target_register_template+0x4fd/0x7b0 [target_core_mod] + [<00000000f3393296>] efct_scsi_tgt_driver_init+0x18/0x50 [efct] + [<00000000115de533>] 0xffffffffc0d90011 + [<00000000d608f646>] do_one_initcall+0xd0/0x4e0 + [<0000000067828cf1>] do_init_module+0x1cc/0x6a0 + ... + +Fixes: 4df84e846624 ("scsi: elx: efct: Driver initialization routines") +Signed-off-by: Chen Zhongjin +Link: https://lore.kernel.org/r/20221111074046.57061-1-chenzhongjin@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/elx/efct/efct_driver.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/elx/efct/efct_driver.c b/drivers/scsi/elx/efct/efct_driver.c +index eab68fd9337a..37e1ab96ee5b 100644 +--- a/drivers/scsi/elx/efct/efct_driver.c ++++ b/drivers/scsi/elx/efct/efct_driver.c +@@ -42,6 +42,7 @@ efct_device_init(void) + + rc = efct_scsi_reg_fc_transport(); + if (rc) { ++ efct_scsi_tgt_driver_exit(); + pr_err("failed to register to FC host\n"); + return rc; + } +-- +2.35.1 + diff --git a/queue-5.15/scsi-elx-libefc-fix-second-parameter-type-in-state-c.patch b/queue-5.15/scsi-elx-libefc-fix-second-parameter-type-in-state-c.patch new file mode 100644 index 00000000000..33f923212a5 --- /dev/null +++ b/queue-5.15/scsi-elx-libefc-fix-second-parameter-type-in-state-c.patch @@ -0,0 +1,81 @@ +From f9d457ab600aa876f00f561b50d38b8f248d3a30 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 09:19:06 -0700 +Subject: scsi: elx: libefc: Fix second parameter type in state callbacks + +From: Nathan Chancellor + +[ Upstream commit 3d75e766b58a7410d4e835c534e1b4664a8f62d0 ] + +With clang's kernel control flow integrity (kCFI, CONFIG_CFI_CLANG), +indirect call targets are validated against the expected function pointer +prototype to make sure the call target is valid to help mitigate ROP +attacks. If they are not identical, there is a failure at run time, which +manifests as either a kernel panic or thread getting killed. A proposed +warning in clang aims to catch these at compile time, which reveals: + + drivers/scsi/elx/libefc/efc_node.c:811:22: error: incompatible function pointer types assigning to 'void (*)(struct efc_sm_ctx *, u32, void *)' (aka 'void (*)(struct efc_sm_ctx *, unsigned int, void *)') from 'void (*)(struct efc_sm_ctx *, enum efc_sm_event, void *)' [-Werror,-Wincompatible-function-pointer-types-strict] + ctx->current_state = state; + ^ ~~~~~ + drivers/scsi/elx/libefc/efc_node.c:878:21: error: incompatible function pointer types assigning to 'void (*)(struct efc_sm_ctx *, u32, void *)' (aka 'void (*)(struct efc_sm_ctx *, unsigned int, void *)') from 'void (*)(struct efc_sm_ctx *, enum efc_sm_event, void *)' [-Werror,-Wincompatible-function-pointer-types-strict] + node->nodedb_state = state; + ^ ~~~~~ + drivers/scsi/elx/libefc/efc_node.c:905:6: error: incompatible function pointer types assigning to 'void (*)(struct efc_sm_ctx *, enum efc_sm_event, void *)' from 'void (*)(struct efc_sm_ctx *, u32, void *)' (aka 'void (*)(struct efc_sm_ctx *, unsigned int, void *)') [-Werror,-Wincompatible-function-pointer-types-strict] + pf = node->nodedb_state; + ^ ~~~~~~~~~~~~~~~~~~ + + drivers/scsi/elx/libefc/efc_device.c:455:22: error: incompatible function pointer types assigning to 'void (*)(struct efc_sm_ctx *, u32, void *)' (aka 'void (*)(struct efc_sm_ctx *, unsigned int, void *)') from 'void (struct efc_sm_ctx *, enum efc_sm_event, void *)' [-Werror,-Wincompatible-function-pointer-types-strict] + node->nodedb_state = __efc_d_init; + ^ ~~~~~~~~~~~~ + + drivers/scsi/elx/libefc/efc_sm.c:41:22: error: incompatible function pointer types assigning to 'void (*)(struct efc_sm_ctx *, u32, void *)' (aka 'void (*)(struct efc_sm_ctx *, unsigned int, void *)') from 'void (*)(struct efc_sm_ctx *, enum efc_sm_event, void *)' [-Werror,-Wincompatible-function-pointer-types-strict] + ctx->current_state = state; + ^ ~~~~~ + +The type of the second parameter in the prototypes of ->current_state() and +->nodedb_state() ('u32') does not match the implementations, which have a +second parameter type of 'enum efc_sm_event'. Update the prototypes to have +the correct second parameter type, clearing up all the warnings and CFI +failures. + +Link: https://github.com/ClangBuiltLinux/linux/issues/1750 +Reported-by: Sami Tolvanen +Signed-off-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20221102161906.2781508-1-nathan@kernel.org +Reviewed-by: Kees Cook +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/elx/libefc/efclib.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/elx/libefc/efclib.h b/drivers/scsi/elx/libefc/efclib.h +index ee291cabf7e0..b14e516be7d5 100644 +--- a/drivers/scsi/elx/libefc/efclib.h ++++ b/drivers/scsi/elx/libefc/efclib.h +@@ -58,10 +58,12 @@ enum efc_node_send_ls_acc { + #define EFC_LINK_STATUS_UP 0 + #define EFC_LINK_STATUS_DOWN 1 + ++enum efc_sm_event; ++ + /* State machine context header */ + struct efc_sm_ctx { + void (*current_state)(struct efc_sm_ctx *ctx, +- u32 evt, void *arg); ++ enum efc_sm_event evt, void *arg); + + const char *description; + void *app; +@@ -364,7 +366,7 @@ struct efc_node { + int prev_evt; + + void (*nodedb_state)(struct efc_sm_ctx *ctx, +- u32 evt, void *arg); ++ enum efc_sm_event evt, void *arg); + struct timer_list gidpt_delay_timer; + u64 time_last_gidpt_msec; + +-- +2.35.1 + diff --git a/queue-5.15/scsi-fcoe-fix-possible-name-leak-when-device_registe.patch b/queue-5.15/scsi-fcoe-fix-possible-name-leak-when-device_registe.patch new file mode 100644 index 00000000000..9442acccd1f --- /dev/null +++ b/queue-5.15/scsi-fcoe-fix-possible-name-leak-when-device_registe.patch @@ -0,0 +1,78 @@ +From e583b0af1096f331b5099676f90115501d8bc9c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 17:43:10 +0800 +Subject: scsi: fcoe: Fix possible name leak when device_register() fails + +From: Yang Yingliang + +[ Upstream commit 47b6a122c7b69a876c7ee2fc064a26b09627de9d ] + +If device_register() returns an error, the name allocated by dev_set_name() +needs to be freed. As the comment of device_register() says, one should use +put_device() to give up the reference in the error path. Fix this by +calling put_device(), then the name can be freed in kobject_cleanup(). + +The 'fcf' is freed in fcoe_fcf_device_release(), so the kfree() in the +error path can be removed. + +The 'ctlr' is freed in fcoe_ctlr_device_release(), so don't use the error +label, just return NULL after calling put_device(). + +Fixes: 9a74e884ee71 ("[SCSI] libfcoe: Add fcoe_sysfs") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221112094310.3633291-1-yangyingliang@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/fcoe/fcoe_sysfs.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c +index af658aa38fed..6260aa5ea6af 100644 +--- a/drivers/scsi/fcoe/fcoe_sysfs.c ++++ b/drivers/scsi/fcoe/fcoe_sysfs.c +@@ -830,14 +830,15 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent, + + dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id); + error = device_register(&ctlr->dev); +- if (error) +- goto out_del_q2; ++ if (error) { ++ destroy_workqueue(ctlr->devloss_work_q); ++ destroy_workqueue(ctlr->work_q); ++ put_device(&ctlr->dev); ++ return NULL; ++ } + + return ctlr; + +-out_del_q2: +- destroy_workqueue(ctlr->devloss_work_q); +- ctlr->devloss_work_q = NULL; + out_del_q: + destroy_workqueue(ctlr->work_q); + ctlr->work_q = NULL; +@@ -1036,16 +1037,16 @@ struct fcoe_fcf_device *fcoe_fcf_device_add(struct fcoe_ctlr_device *ctlr, + fcf->selected = new_fcf->selected; + + error = device_register(&fcf->dev); +- if (error) +- goto out_del; ++ if (error) { ++ put_device(&fcf->dev); ++ goto out; ++ } + + fcf->state = FCOE_FCF_STATE_CONNECTED; + list_add_tail(&fcf->peers, &ctlr->fcfs); + + return fcf; + +-out_del: +- kfree(fcf); + out: + return NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/scsi-fcoe-fix-transport-not-deattached-when-fcoe_if_.patch b/queue-5.15/scsi-fcoe-fix-transport-not-deattached-when-fcoe_if_.patch new file mode 100644 index 00000000000..df9e1fdb072 --- /dev/null +++ b/queue-5.15/scsi-fcoe-fix-transport-not-deattached-when-fcoe_if_.patch @@ -0,0 +1,46 @@ +From 0637980f7bad9ab1187ca0ffafab22477104bef5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 17:24:42 +0800 +Subject: scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails + +From: Chen Zhongjin + +[ Upstream commit 4155658cee394b22b24c6d64e49247bf26d95b92 ] + +fcoe_init() calls fcoe_transport_attach(&fcoe_sw_transport), but when +fcoe_if_init() fails, &fcoe_sw_transport is not detached and leaves freed +&fcoe_sw_transport on fcoe_transports list. This causes panic when +reinserting module. + + BUG: unable to handle page fault for address: fffffbfff82e2213 + RIP: 0010:fcoe_transport_attach+0xe1/0x230 [libfcoe] + Call Trace: + + do_one_initcall+0xd0/0x4e0 + load_module+0x5eee/0x7210 + ... + +Fixes: 78a582463c1e ("[SCSI] fcoe: convert fcoe.ko to become an fcoe transport provider driver") +Signed-off-by: Chen Zhongjin +Link: https://lore.kernel.org/r/20221115092442.133088-1-chenzhongjin@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/fcoe/fcoe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c +index 5ae6c207d3ac..76dbdae0e987 100644 +--- a/drivers/scsi/fcoe/fcoe.c ++++ b/drivers/scsi/fcoe/fcoe.c +@@ -2501,6 +2501,7 @@ static int __init fcoe_init(void) + + out_free: + mutex_unlock(&fcoe_config_mutex); ++ fcoe_transport_detach(&fcoe_sw_transport); + out_destroy: + destroy_workqueue(fcoe_wq); + return rc; +-- +2.35.1 + diff --git a/queue-5.15/scsi-hpsa-fix-error-handling-in-hpsa_add_sas_host.patch b/queue-5.15/scsi-hpsa-fix-error-handling-in-hpsa_add_sas_host.patch new file mode 100644 index 00000000000..8e423c64198 --- /dev/null +++ b/queue-5.15/scsi-hpsa-fix-error-handling-in-hpsa_add_sas_host.patch @@ -0,0 +1,54 @@ +From c6c5c4cec6e52370129800d63dfe83072063c2f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 23:11:29 +0800 +Subject: scsi: hpsa: Fix error handling in hpsa_add_sas_host() + +From: Yang Yingliang + +[ Upstream commit 4ef174a3ad9b5d73c1b6573e244ebba2b0d86eac ] + +hpsa_sas_port_add_phy() does: + ... + sas_phy_add() -> may return error here + sas_port_add_phy() + ... + +Whereas hpsa_free_sas_phy() does: + ... + sas_port_delete_phy() + sas_phy_delete() + ... + +If hpsa_sas_port_add_phy() returns an error, hpsa_free_sas_phy() can not be +called to free the memory because the port and the phy have not been added +yet. + +Replace hpsa_free_sas_phy() with sas_phy_free() and kfree() to avoid kernel +crash in this case. + +Fixes: d04e62b9d63a ("hpsa: add in sas transport class") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221110151129.394389-1-yangyingliang@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hpsa.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 74d563950c64..a4a00944b290 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -9788,7 +9788,8 @@ static int hpsa_add_sas_host(struct ctlr_info *h) + return 0; + + free_sas_phy: +- hpsa_free_sas_phy(hpsa_sas_phy); ++ sas_phy_free(hpsa_sas_phy->phy); ++ kfree(hpsa_sas_phy); + free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); + free_sas_node: +-- +2.35.1 + diff --git a/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_add_sas_d.patch b/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_add_sas_d.patch new file mode 100644 index 00000000000..4a4bc0ce939 --- /dev/null +++ b/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_add_sas_d.patch @@ -0,0 +1,43 @@ +From b8c003bcbe95a8ecdfe25d9980a96ad3424f6919 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 12:30:12 +0800 +Subject: scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device() + +From: Yang Yingliang + +[ Upstream commit fda34a5d304d0b98cc967e8763b52221b66dc202 ] + +If hpsa_sas_port_add_rphy() returns an error, the 'rphy' allocated in +sas_end_device_alloc() needs to be freed. Address this by calling +sas_rphy_free() in the error path. + +Fixes: d04e62b9d63a ("hpsa: add in sas transport class") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221111043012.1074466-1-yangyingliang@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hpsa.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index a4a00944b290..cf7988de7b90 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -9825,10 +9825,12 @@ static int hpsa_add_sas_device(struct hpsa_sas_node *hpsa_sas_node, + + rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy); + if (rc) +- goto free_sas_port; ++ goto free_sas_rphy; + + return 0; + ++free_sas_rphy: ++ sas_rphy_free(rphy); + free_sas_port: + hpsa_free_sas_port(hpsa_sas_port); + device->sas_port = NULL; +-- +2.35.1 + diff --git a/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_init_one.patch b/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_init_one.patch new file mode 100644 index 00000000000..e9be8f40ba1 --- /dev/null +++ b/queue-5.15/scsi-hpsa-fix-possible-memory-leak-in-hpsa_init_one.patch @@ -0,0 +1,42 @@ +From 7da835af37f4ed21c4de6e61d7787baae80c144a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 01:57:51 +0000 +Subject: scsi: hpsa: Fix possible memory leak in hpsa_init_one() + +From: Yuan Can + +[ Upstream commit 9c9ff300e0de07475796495d86f449340d454a0c ] + +The hpda_alloc_ctlr_info() allocates h and its field reply_map. However, in +hpsa_init_one(), if alloc_percpu() failed, the hpsa_init_one() jumps to +clean1 directly, which frees h and leaks the h->reply_map. + +Fix by calling hpda_free_ctlr_info() to release h->replay_map and h instead +free h directly. + +Fixes: 8b834bff1b73 ("scsi: hpsa: fix selection of reply queue") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221122015751.87284-1-yuancan@huawei.com +Reviewed-by: Ming Lei +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/hpsa.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 3faa87fa296a..74d563950c64 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -8927,7 +8927,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + destroy_workqueue(h->monitor_ctlr_wq); + h->monitor_ctlr_wq = NULL; + } +- kfree(h); ++ hpda_free_ctlr_info(h); + return rc; + } + +-- +2.35.1 + diff --git a/queue-5.15/scsi-ipr-fix-warning-in-ipr_init.patch b/queue-5.15/scsi-ipr-fix-warning-in-ipr_init.patch new file mode 100644 index 00000000000..c4ebd094782 --- /dev/null +++ b/queue-5.15/scsi-ipr-fix-warning-in-ipr_init.patch @@ -0,0 +1,73 @@ +From 74a4485c28937e3f2d1b81599c216062086c4ddd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Nov 2022 14:45:13 +0800 +Subject: scsi: ipr: Fix WARNING in ipr_init() + +From: Shang XiaoJing + +[ Upstream commit e6f108bffc3708ddcff72324f7d40dfcd0204894 ] + +ipr_init() will not call unregister_reboot_notifier() when +pci_register_driver() fails, which causes a WARNING. Call +unregister_reboot_notifier() when pci_register_driver() fails. + +notifier callback ipr_halt [ipr] already registered +WARNING: CPU: 3 PID: 299 at kernel/notifier.c:29 +notifier_chain_register+0x16d/0x230 +Modules linked in: ipr(+) xhci_pci_renesas xhci_hcd ehci_hcd usbcore +led_class gpu_sched drm_buddy video wmi drm_ttm_helper ttm +drm_display_helper drm_kms_helper drm drm_panel_orientation_quirks +agpgart cfbft +CPU: 3 PID: 299 Comm: modprobe Tainted: G W +6.1.0-rc1-00190-g39508d23b672-dirty #332 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 +RIP: 0010:notifier_chain_register+0x16d/0x230 +Call Trace: + + __blocking_notifier_chain_register+0x73/0xb0 + ipr_init+0x30/0x1000 [ipr] + do_one_initcall+0xdb/0x480 + do_init_module+0x1cf/0x680 + load_module+0x6a50/0x70a0 + __do_sys_finit_module+0x12f/0x1c0 + do_syscall_64+0x3f/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Fixes: f72919ec2bbb ("[SCSI] ipr: implement shutdown changes and remove obsolete write cache parameter") +Signed-off-by: Shang XiaoJing +Link: https://lore.kernel.org/r/20221113064513.14028-1-shangxiaojing@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ipr.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c +index 56b8a2d6ffe4..04fb7fc01226 100644 +--- a/drivers/scsi/ipr.c ++++ b/drivers/scsi/ipr.c +@@ -10869,11 +10869,19 @@ static struct notifier_block ipr_notifier = { + **/ + static int __init ipr_init(void) + { ++ int rc; ++ + ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n", + IPR_DRIVER_VERSION, IPR_DRIVER_DATE); + + register_reboot_notifier(&ipr_notifier); +- return pci_register_driver(&ipr_driver); ++ rc = pci_register_driver(&ipr_driver); ++ if (rc) { ++ unregister_reboot_notifier(&ipr_notifier); ++ return rc; ++ } ++ ++ return 0; + } + + /** +-- +2.35.1 + diff --git a/queue-5.15/scsi-lpfc-fix-hard-lockup-when-reading-the-rx_monito.patch b/queue-5.15/scsi-lpfc-fix-hard-lockup-when-reading-the-rx_monito.patch new file mode 100644 index 00000000000..476f315a33e --- /dev/null +++ b/queue-5.15/scsi-lpfc-fix-hard-lockup-when-reading-the-rx_monito.patch @@ -0,0 +1,77 @@ +From 22bde018d7e1f7faefb74dc634e26ad172a910d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Oct 2022 09:43:20 -0700 +Subject: scsi: lpfc: Fix hard lockup when reading the rx_monitor from debugfs + +From: Justin Tee + +[ Upstream commit c44e50f4a0ec00c2298f31f91bc2c3e9bbd81c7e ] + +During I/O and simultaneous cat of /sys/kernel/debug/lpfc/fnX/rx_monitor, a +hard lockup similar to the call trace below may occur. + +The spin_lock_bh in lpfc_rx_monitor_report is not protecting from timer +interrupts as expected, so change the strength of the spin lock to _irq. + +Kernel panic - not syncing: Hard LOCKUP +CPU: 3 PID: 110402 Comm: cat Kdump: loaded + +exception RIP: native_queued_spin_lock_slowpath+91 + +[IRQ stack] + native_queued_spin_lock_slowpath at ffffffffb814e30b + _raw_spin_lock at ffffffffb89a667a + lpfc_rx_monitor_record at ffffffffc0a73a36 [lpfc] + lpfc_cmf_timer at ffffffffc0abbc67 [lpfc] + __hrtimer_run_queues at ffffffffb8184250 + hrtimer_interrupt at ffffffffb8184ab0 + smp_apic_timer_interrupt at ffffffffb8a026ba + apic_timer_interrupt at ffffffffb8a01c4f +[End of IRQ stack] + + apic_timer_interrupt at ffffffffb8a01c4f + lpfc_rx_monitor_report at ffffffffc0a73c80 [lpfc] + lpfc_rx_monitor_read at ffffffffc0addde1 [lpfc] + full_proxy_read at ffffffffb83e7fc3 + vfs_read at ffffffffb833fe71 + ksys_read at ffffffffb83402af + do_syscall_64 at ffffffffb800430b + entry_SYSCALL_64_after_hwframe at ffffffffb8a000ad + +Signed-off-by: Justin Tee +Link: https://lore.kernel.org/r/20221017164323.14536-2-justintee8345@gmail.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_sli.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index d6e761adf1f1..df3b190fccd1 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -7992,10 +7992,10 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, + "IO_cnt", "Info", "BWutil(ms)"); + } + +- /* Needs to be _bh because record is called from timer interrupt ++ /* Needs to be _irq because record is called from timer interrupt + * context + */ +- spin_lock_bh(ring_lock); ++ spin_lock_irq(ring_lock); + while (*head_idx != *tail_idx) { + entry = &ring[*head_idx]; + +@@ -8039,7 +8039,7 @@ u32 lpfc_rx_monitor_report(struct lpfc_hba *phba, + if (cnt >= max_read_entries) + break; + } +- spin_unlock_bh(ring_lock); ++ spin_unlock_irq(ring_lock); + + return cnt; + } +-- +2.35.1 + diff --git a/queue-5.15/scsi-mpt3sas-fix-possible-resource-leaks-in-mpt3sas_.patch b/queue-5.15/scsi-mpt3sas-fix-possible-resource-leaks-in-mpt3sas_.patch new file mode 100644 index 00000000000..7c3b3ad7258 --- /dev/null +++ b/queue-5.15/scsi-mpt3sas-fix-possible-resource-leaks-in-mpt3sas_.patch @@ -0,0 +1,67 @@ +From 4256f363aa8dda8bad9549fef3e34fd7f8f80837 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 11:24:03 +0800 +Subject: scsi: mpt3sas: Fix possible resource leaks in + mpt3sas_transport_port_add() + +From: Yang Yingliang + +[ Upstream commit 78316e9dfc24906dd474630928ed1d3c562b568e ] + +In mpt3sas_transport_port_add(), if sas_rphy_add() returns error, +sas_rphy_free() needs be called to free the resource allocated in +sas_end_device_alloc(). Otherwise a kernel crash will happen: + +Unable to handle kernel NULL pointer dereference at virtual address 0000000000000108 +CPU: 45 PID: 37020 Comm: bash Kdump: loaded Tainted: G W 6.1.0-rc1+ #189 +pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : device_del+0x54/0x3d0 +lr : device_del+0x37c/0x3d0 +Call trace: + device_del+0x54/0x3d0 + attribute_container_class_device_del+0x28/0x38 + transport_remove_classdev+0x6c/0x80 + attribute_container_device_trigger+0x108/0x110 + transport_remove_device+0x28/0x38 + sas_rphy_remove+0x50/0x78 [scsi_transport_sas] + sas_port_delete+0x30/0x148 [scsi_transport_sas] + do_sas_phy_delete+0x78/0x80 [scsi_transport_sas] + device_for_each_child+0x68/0xb0 + sas_remove_children+0x30/0x50 [scsi_transport_sas] + sas_rphy_remove+0x38/0x78 [scsi_transport_sas] + sas_port_delete+0x30/0x148 [scsi_transport_sas] + do_sas_phy_delete+0x78/0x80 [scsi_transport_sas] + device_for_each_child+0x68/0xb0 + sas_remove_children+0x30/0x50 [scsi_transport_sas] + sas_remove_host+0x20/0x38 [scsi_transport_sas] + scsih_remove+0xd8/0x420 [mpt3sas] + +Because transport_add_device() is not called when sas_rphy_add() fails, the +device is not added. When sas_rphy_remove() is subsequently called to +remove the device in the remove() path, a NULL pointer dereference happens. + +Fixes: f92363d12359 ("[SCSI] mpt3sas: add new driver supporting 12GB SAS") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221109032403.1636422-1-yangyingliang@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/mpt3sas/mpt3sas_transport.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c +index 0681daee6c14..e5ecd6ada6cd 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c +@@ -829,6 +829,8 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, + if ((sas_rphy_add(rphy))) { + ioc_err(ioc, "failure at %s:%d/%s()!\n", + __FILE__, __LINE__, __func__); ++ sas_rphy_free(rphy); ++ rphy = NULL; + } + + if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { +-- +2.35.1 + diff --git a/queue-5.15/scsi-qla2xxx-fix-set-but-not-used-variable-warnings.patch b/queue-5.15/scsi-qla2xxx-fix-set-but-not-used-variable-warnings.patch new file mode 100644 index 00000000000..9ec4babdf41 --- /dev/null +++ b/queue-5.15/scsi-qla2xxx-fix-set-but-not-used-variable-warnings.patch @@ -0,0 +1,146 @@ +From 77cb5fab9693ef29cb2bbc70d9c317932a257e6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 15:48:18 -0700 +Subject: scsi: qla2xxx: Fix set-but-not-used variable warnings +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bart Van Assche + +[ Upstream commit 4fb2169d66b837a2986f569f5d5b81f79e6e4a4c ] + +Fix the following two compiler warnings: + +drivers/scsi/qla2xxx/qla_init.c: In function ‘qla24xx_async_abort_cmd’: +drivers/scsi/qla2xxx/qla_init.c:171:17: warning: variable ‘bail’ set but not used [-Wunused-but-set-variable] + 171 | uint8_t bail; + | ^~~~ +drivers/scsi/qla2xxx/qla_init.c: In function ‘qla2x00_async_tm_cmd’: +drivers/scsi/qla2xxx/qla_init.c:2023:17: warning: variable ‘bail’ set but not used [-Wunused-but-set-variable] + 2023 | uint8_t bail; + | ^~~~ + +Cc: Arun Easi +Cc: Giridhar Malavali +Fixes: feafb7b1714c ("[SCSI] qla2xxx: Fix vport delete issues") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20221031224818.2607882-1-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/qla2xxx/qla_def.h | 22 +++++++++++----------- + drivers/scsi/qla2xxx/qla_init.c | 6 ++---- + drivers/scsi/qla2xxx/qla_inline.h | 4 +--- + drivers/scsi/qla2xxx/qla_os.c | 4 +--- + 4 files changed, 15 insertions(+), 21 deletions(-) + +diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h +index 51c7ce5f9792..307ffdfe048b 100644 +--- a/drivers/scsi/qla2xxx/qla_def.h ++++ b/drivers/scsi/qla2xxx/qla_def.h +@@ -5117,17 +5117,17 @@ struct secure_flash_update_block_pk { + (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || \ + test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) + +-#define QLA_VHA_MARK_BUSY(__vha, __bail) do { \ +- atomic_inc(&__vha->vref_count); \ +- mb(); \ +- if (__vha->flags.delete_progress) { \ +- atomic_dec(&__vha->vref_count); \ +- wake_up(&__vha->vref_waitq); \ +- __bail = 1; \ +- } else { \ +- __bail = 0; \ +- } \ +-} while (0) ++static inline bool qla_vha_mark_busy(scsi_qla_host_t *vha) ++{ ++ atomic_inc(&vha->vref_count); ++ mb(); ++ if (vha->flags.delete_progress) { ++ atomic_dec(&vha->vref_count); ++ wake_up(&vha->vref_waitq); ++ return true; ++ } ++ return false; ++} + + #define QLA_VHA_MARK_NOT_BUSY(__vha) do { \ + atomic_dec(&__vha->vref_count); \ +diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c +index b81797a3ab61..46b3b31a41bd 100644 +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -168,7 +168,6 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) + struct srb_iocb *abt_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; +- uint8_t bail; + + /* ref: INIT for ABTS command */ + sp = qla2xxx_get_qpair_sp(cmd_sp->vha, cmd_sp->qpair, cmd_sp->fcport, +@@ -176,7 +175,7 @@ int qla24xx_async_abort_cmd(srb_t *cmd_sp, bool wait) + if (!sp) + return QLA_MEMORY_ALLOC_FAILED; + +- QLA_VHA_MARK_BUSY(vha, bail); ++ qla_vha_mark_busy(vha); + abt_iocb = &sp->u.iocb_cmd; + sp->type = SRB_ABT_CMD; + sp->name = "abort"; +@@ -2022,14 +2021,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, + struct srb_iocb *tm_iocb; + srb_t *sp; + int rval = QLA_FUNCTION_FAILED; +- uint8_t bail; + + /* ref: INIT */ + sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); + if (!sp) + goto done; + +- QLA_VHA_MARK_BUSY(vha, bail); ++ qla_vha_mark_busy(vha); + sp->type = SRB_TM_CMD; + sp->name = "tmf"; + qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), +diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h +index db17f7f410cd..5185dc5daf80 100644 +--- a/drivers/scsi/qla2xxx/qla_inline.h ++++ b/drivers/scsi/qla2xxx/qla_inline.h +@@ -225,11 +225,9 @@ static inline srb_t * + qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag) + { + srb_t *sp = NULL; +- uint8_t bail; + struct qla_qpair *qpair; + +- QLA_VHA_MARK_BUSY(vha, bail); +- if (unlikely(bail)) ++ if (unlikely(qla_vha_mark_busy(vha))) + return NULL; + + qpair = vha->hw->base_qpair; +diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c +index 00e97f0a07eb..05d827227d0b 100644 +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -5043,13 +5043,11 @@ struct qla_work_evt * + qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type) + { + struct qla_work_evt *e; +- uint8_t bail; + + if (test_bit(UNLOADING, &vha->dpc_flags)) + return NULL; + +- QLA_VHA_MARK_BUSY(vha, bail); +- if (bail) ++ if (qla_vha_mark_busy(vha)) + return NULL; + + e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC); +-- +2.35.1 + diff --git a/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_report_zones.patch b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_report_zones.patch new file mode 100644 index 00000000000..fdddc203133 --- /dev/null +++ b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_report_zones.patch @@ -0,0 +1,41 @@ +From 077b5e6a04569caf0e04842bb7ecab89ddda46ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 23:06:12 -0800 +Subject: scsi: scsi_debug: Fix a warning in resp_report_zones() + +From: Harshit Mogalapalli + +[ Upstream commit 07f2ca139d9a7a1ba71c4c03997c8de161db2346 ] + +As 'alloc_len' is user controlled data, if user tries to allocate memory +larger than(>=) MAX_ORDER, then kcalloc() will fail, it creates a stack +trace and messes up dmesg with a warning. + +Add __GFP_NOWARN in order to avoid too large allocation warning. This is +detected by static analysis using smatch. + +Fixes: 7db0e0c8190a ("scsi: scsi_debug: Fix buffer size of REPORT ZONES command") +Signed-off-by: Harshit Mogalapalli +Link: https://lore.kernel.org/r/20221112070612.2121535-1-harshit.m.mogalapalli@oracle.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 6ca3205a0bf5..5624bb6a64a3 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -4367,7 +4367,7 @@ static int resp_report_zones(struct scsi_cmnd *scp, + rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD), + max_zones); + +- arr = kzalloc(alloc_len, GFP_ATOMIC); ++ arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +-- +2.35.1 + diff --git a/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_verify.patch b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_verify.patch new file mode 100644 index 00000000000..4e38b6ce291 --- /dev/null +++ b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_verify.patch @@ -0,0 +1,41 @@ +From 36774be9888c2a3789464ab08fdc0561226de143 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 23:00:31 -0800 +Subject: scsi: scsi_debug: Fix a warning in resp_verify() + +From: Harshit Mogalapalli + +[ Upstream commit ed0f17b748b20271cb568c7ca0b23b120316a47d ] + +As 'vnum' is controlled by user, so if user tries to allocate memory larger +than(>=) MAX_ORDER, then kcalloc() will fail, it creates a stack trace and +messes up dmesg with a warning. + +Add __GFP_NOWARN in order to avoid too large allocation warning. This is +detected by static analysis using smatch. + +Fixes: c3e2fe9222d4 ("scsi: scsi_debug: Implement VERIFY(10), add VERIFY(16)") +Signed-off-by: Harshit Mogalapalli +Link: https://lore.kernel.org/r/20221112070031.2121068-1-harshit.m.mogalapalli@oracle.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index b44fd9b80934..6ca3205a0bf5 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -4296,7 +4296,7 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) + if (ret) + return ret; + +- arr = kcalloc(lb_size, vnum, GFP_ATOMIC); ++ arr = kcalloc(lb_size, vnum, GFP_ATOMIC | __GFP_NOWARN); + if (!arr) { + mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC, + INSUFF_RES_ASCQ); +-- +2.35.1 + diff --git a/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_write_scat.patch b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_write_scat.patch new file mode 100644 index 00000000000..ef937cdbb8b --- /dev/null +++ b/queue-5.15/scsi-scsi_debug-fix-a-warning-in-resp_write_scat.patch @@ -0,0 +1,66 @@ +From f76d491463a8de6e4a543a0d0325a5fffe5b18f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 02:05:25 -0800 +Subject: scsi: scsi_debug: Fix a warning in resp_write_scat() + +From: Harshit Mogalapalli + +[ Upstream commit 216e179724c1d9f57a8ababf8bd7aaabef67f01b ] + +As 'lbdof_blen' is coming from user, if the size in kzalloc() is >= +MAX_ORDER then we hit a warning. + +Call trace: + +sg_ioctl + sg_ioctl_common + scsi_ioctl + sg_scsi_ioctl + blk_execute_rq + blk_mq_sched_insert_request + blk_mq_run_hw_queue + __blk_mq_delay_run_hw_queue + __blk_mq_run_hw_queue + blk_mq_sched_dispatch_requests + __blk_mq_sched_dispatch_requests + blk_mq_dispatch_rq_list + scsi_queue_rq + scsi_dispatch_cmd + scsi_debug_queuecommand + schedule_resp + resp_write_scat + +If you try to allocate a memory larger than(>=) MAX_ORDER, then kmalloc() +will definitely fail. It creates a stack trace and messes up dmesg. The +user controls the size here so if they specify a too large size it will +fail. + +Add __GFP_NOWARN in order to avoid too large allocation warning. This is +detected by static analysis using smatch. + +Fixes: 481b5e5c7949 ("scsi: scsi_debug: add resp_write_scat function") +Signed-off-by: Harshit Mogalapalli +Link: https://lore.kernel.org/r/20221111100526.1790533-1-harshit.m.mogalapalli@oracle.com +Acked-by: Douglas Gilbert +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 0b16061d8da8..b44fd9b80934 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -3640,7 +3640,7 @@ static int resp_write_scat(struct scsi_cmnd *scp, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + return illegal_condition_result; + } +- lrdp = kzalloc(lbdof_blen, GFP_ATOMIC); ++ lrdp = kzalloc(lbdof_blen, GFP_ATOMIC | __GFP_NOWARN); + if (lrdp == NULL) + return SCSI_MLQUEUE_HOST_BUSY; + if (sdebug_verbose) +-- +2.35.1 + diff --git a/queue-5.15/scsi-scsi_debug-fix-possible-name-leak-in-sdebug_add.patch b/queue-5.15/scsi-scsi_debug-fix-possible-name-leak-in-sdebug_add.patch new file mode 100644 index 00000000000..91645a54bbe --- /dev/null +++ b/queue-5.15/scsi-scsi_debug-fix-possible-name-leak-in-sdebug_add.patch @@ -0,0 +1,49 @@ +From f2e09a1a4a555883542cfcbcc4104fea63827c65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 12 Nov 2022 21:10:10 +0800 +Subject: scsi: scsi_debug: Fix possible name leak in sdebug_add_host_helper() + +From: Yang Yingliang + +[ Upstream commit e6d773f93a49e0eda88a903a2a6542ca83380eb1 ] + +Afer commit 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id +string array"), the name of device is allocated dynamically, it needs be +freed when device_register() returns error. + +As comment of device_register() says, one should use put_device() to give +up the reference in the error path. Fix this by calling put_device(), then +the name can be freed in kobject_cleanup(), and sdbg_host is freed in +sdebug_release_adapter(). + +When the device release is not set, it means the device is not initialized. +We can not call put_device() in this case. Use kfree() to free memory. + +Fixes: 1fa5ae857bb1 ("driver core: get rid of struct device's bus_id string array") +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221112131010.3757845-1-yangyingliang@huawei.com +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/scsi_debug.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 5624bb6a64a3..591df0a91057 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -7156,7 +7156,10 @@ static int sdebug_add_host_helper(int per_host_idx) + kfree(sdbg_devinfo->zstate); + kfree(sdbg_devinfo); + } +- kfree(sdbg_host); ++ if (sdbg_host->dev.release) ++ put_device(&sdbg_host->dev); ++ else ++ kfree(sdbg_host); + pr_warn("%s: failed, errno=%d\n", __func__, -error); + return error; + } +-- +2.35.1 + diff --git a/queue-5.15/scsi-snic-fix-possible-uaf-in-snic_tgt_create.patch b/queue-5.15/scsi-snic-fix-possible-uaf-in-snic_tgt_create.patch new file mode 100644 index 00000000000..0c431d1a716 --- /dev/null +++ b/queue-5.15/scsi-snic-fix-possible-uaf-in-snic_tgt_create.patch @@ -0,0 +1,47 @@ +From 45f2b18ae1efc4f5d615bc6113091c6ea932cae6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 11:51:00 +0800 +Subject: scsi: snic: Fix possible UAF in snic_tgt_create() + +From: Gaosheng Cui + +[ Upstream commit e118df492320176af94deec000ae034cc92be754 ] + +Smatch reports a warning as follows: + +drivers/scsi/snic/snic_disc.c:307 snic_tgt_create() warn: + '&tgt->list' not removed from list + +If device_add() fails in snic_tgt_create(), tgt will be freed, but +tgt->list will not be removed from snic->disc.tgt_list, then list traversal +may cause UAF. + +Remove from snic->disc.tgt_list before free(). + +Fixes: c8806b6c9e82 ("snic: driver for Cisco SCSI HBA") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221117035100.2944812-1-cuigaosheng1@huawei.com +Acked-by: Narsimhulu Musini +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/snic/snic_disc.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c +index e9ccfb97773f..7cf871323b2c 100644 +--- a/drivers/scsi/snic/snic_disc.c ++++ b/drivers/scsi/snic/snic_disc.c +@@ -318,6 +318,9 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid) + ret); + + put_device(&snic->shost->shost_gendev); ++ spin_lock_irqsave(snic->shost->host_lock, flags); ++ list_del(&tgt->list); ++ spin_unlock_irqrestore(snic->shost->host_lock, flags); + kfree(tgt); + tgt = NULL; + +-- +2.35.1 + diff --git a/queue-5.15/scsi-ufs-reduce-the-start-stop-unit-timeout.patch b/queue-5.15/scsi-ufs-reduce-the-start-stop-unit-timeout.patch new file mode 100644 index 00000000000..6fc8dde9c34 --- /dev/null +++ b/queue-5.15/scsi-ufs-reduce-the-start-stop-unit-timeout.patch @@ -0,0 +1,55 @@ +From 4f2daec641f2e8f48deebc9202a07bf5e006c75e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 13:29:54 -0700 +Subject: scsi: ufs: Reduce the START STOP UNIT timeout + +From: Bart Van Assche + +[ Upstream commit dcd5b7637c6d442d957f73780a03047413ed3a10 ] + +Reduce the START STOP UNIT command timeout to one second since on Android +devices a kernel panic is triggered if an attempt to suspend the system +takes more than 20 seconds. One second should be enough for the START STOP +UNIT command since this command completes in less than a millisecond for +the UFS devices I have access to. + +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20221018202958.1902564-7-bvanassche@acm.org +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/ufs/ufshcd.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index dae1a85f1512..a428b8145dcc 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -8476,8 +8476,6 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + struct scsi_device *sdp; + unsigned long flags; + int ret, retries; +- unsigned long deadline; +- int32_t remaining; + + spin_lock_irqsave(hba->host->host_lock, flags); + sdp = hba->sdev_ufs_device; +@@ -8510,14 +8508,9 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, + * callbacks hence set the RQF_PM flag so that it doesn't resume the + * already suspended childs. + */ +- deadline = jiffies + 10 * HZ; + for (retries = 3; retries > 0; --retries) { +- ret = -ETIMEDOUT; +- remaining = deadline - jiffies; +- if (remaining <= 0) +- break; + ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr, +- remaining / HZ, 0, 0, RQF_PM, NULL); ++ HZ, 0, 0, RQF_PM, NULL); + if (!scsi_status_is_check_condition(ret) || + !scsi_sense_valid(&sshdr) || + sshdr.sense_key != UNIT_ATTENTION) +-- +2.35.1 + diff --git a/queue-5.15/sctp-sysctl-make-extra-pointers-netns-aware.patch b/queue-5.15/sctp-sysctl-make-extra-pointers-netns-aware.patch new file mode 100644 index 00000000000..138e11c8147 --- /dev/null +++ b/queue-5.15/sctp-sysctl-make-extra-pointers-netns-aware.patch @@ -0,0 +1,166 @@ +From 0579970e6429f95374dc90bdef4ad1631cc35014 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 13:48:54 +0800 +Subject: sctp: sysctl: make extra pointers netns aware + +From: Firo Yang + +[ Upstream commit da05cecc4939c0410d56c29e252998b192756318 ] + +Recently, a customer reported that from their container whose +net namespace is different to the host's init_net, they can't set +the container's net.sctp.rto_max to any value smaller than +init_net.sctp.rto_min. + +For instance, +Host: +sudo sysctl net.sctp.rto_min +net.sctp.rto_min = 1000 + +Container: +echo 100 > /mnt/proc-net/sctp/rto_min +echo 400 > /mnt/proc-net/sctp/rto_max +echo: write error: Invalid argument + +This is caused by the check made from this'commit 4f3fdf3bc59c +("sctp: add check rto_min and rto_max in sysctl")' +When validating the input value, it's always referring the boundary +value set for the init_net namespace. + +Having container's rto_max smaller than host's init_net.sctp.rto_min +does make sense. Consider that the rto between two containers on the +same host is very likely smaller than it for two hosts. + +So to fix this problem, as suggested by Marcelo, this patch makes the +extra pointers of rto_min, rto_max, pf_retrans, and ps_retrans point +to the corresponding variables from the newly created net namespace while +the new net namespace is being registered in sctp_sysctl_net_register. + +Fixes: 4f3fdf3bc59c ("sctp: add check rto_min and rto_max in sysctl") +Reviewed-by: Marcelo Ricardo Leitner +Reviewed-by: Jakub Kicinski +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: Firo Yang +Link: https://lore.kernel.org/r/20221209054854.23889-1-firo.yang@suse.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sysctl.c | 73 ++++++++++++++++++++++++++++------------------- + 1 file changed, 44 insertions(+), 29 deletions(-) + +diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c +index b46a416787ec..43ebf090029d 100644 +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -84,17 +84,18 @@ static struct ctl_table sctp_table[] = { + { /* sentinel */ } + }; + ++/* The following index defines are used in sctp_sysctl_net_register(). ++ * If you add new items to the sctp_net_table, please ensure that ++ * the index values of these defines hold the same meaning indicated by ++ * their macro names when they appear in sctp_net_table. ++ */ ++#define SCTP_RTO_MIN_IDX 0 ++#define SCTP_RTO_MAX_IDX 1 ++#define SCTP_PF_RETRANS_IDX 2 ++#define SCTP_PS_RETRANS_IDX 3 ++ + static struct ctl_table sctp_net_table[] = { +- { +- .procname = "rto_initial", +- .data = &init_net.sctp.rto_initial, +- .maxlen = sizeof(unsigned int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ONE, +- .extra2 = &timer_max +- }, +- { ++ [SCTP_RTO_MIN_IDX] = { + .procname = "rto_min", + .data = &init_net.sctp.rto_min, + .maxlen = sizeof(unsigned int), +@@ -103,7 +104,7 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = SYSCTL_ONE, + .extra2 = &init_net.sctp.rto_max + }, +- { ++ [SCTP_RTO_MAX_IDX] = { + .procname = "rto_max", + .data = &init_net.sctp.rto_max, + .maxlen = sizeof(unsigned int), +@@ -112,6 +113,33 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = &init_net.sctp.rto_min, + .extra2 = &timer_max + }, ++ [SCTP_PF_RETRANS_IDX] = { ++ .procname = "pf_retrans", ++ .data = &init_net.sctp.pf_retrans, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = &init_net.sctp.ps_retrans, ++ }, ++ [SCTP_PS_RETRANS_IDX] = { ++ .procname = "ps_retrans", ++ .data = &init_net.sctp.ps_retrans, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &init_net.sctp.pf_retrans, ++ .extra2 = &ps_retrans_max, ++ }, ++ { ++ .procname = "rto_initial", ++ .data = &init_net.sctp.rto_initial, ++ .maxlen = sizeof(unsigned int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = &timer_max ++ }, + { + .procname = "rto_alpha_exp_divisor", + .data = &init_net.sctp.rto_alpha, +@@ -207,24 +235,6 @@ static struct ctl_table sctp_net_table[] = { + .extra1 = SYSCTL_ONE, + .extra2 = SYSCTL_INT_MAX, + }, +- { +- .procname = "pf_retrans", +- .data = &init_net.sctp.pf_retrans, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = SYSCTL_ZERO, +- .extra2 = &init_net.sctp.ps_retrans, +- }, +- { +- .procname = "ps_retrans", +- .data = &init_net.sctp.ps_retrans, +- .maxlen = sizeof(int), +- .mode = 0644, +- .proc_handler = proc_dointvec_minmax, +- .extra1 = &init_net.sctp.pf_retrans, +- .extra2 = &ps_retrans_max, +- }, + { + .procname = "sndbuf_policy", + .data = &init_net.sctp.sndbuf_policy, +@@ -586,6 +596,11 @@ int sctp_sysctl_net_register(struct net *net) + for (i = 0; table[i].data; i++) + table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; + ++ table[SCTP_RTO_MIN_IDX].extra2 = &net->sctp.rto_max; ++ table[SCTP_RTO_MAX_IDX].extra1 = &net->sctp.rto_min; ++ table[SCTP_PF_RETRANS_IDX].extra2 = &net->sctp.ps_retrans; ++ table[SCTP_PS_RETRANS_IDX].extra1 = &net->sctp.pf_retrans; ++ + net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); + if (net->sctp.sysctl_header == NULL) { + kfree(table); +-- +2.35.1 + diff --git a/queue-5.15/seccomp-move-copy_seccomp-to-no-failure-path.patch b/queue-5.15/seccomp-move-copy_seccomp-to-no-failure-path.patch new file mode 100644 index 00000000000..ad3113b0d9b --- /dev/null +++ b/queue-5.15/seccomp-move-copy_seccomp-to-no-failure-path.patch @@ -0,0 +1,172 @@ +From e5c103fe29a2f2aa137fb50eae10c5242d0636b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 08:45:32 -0700 +Subject: seccomp: Move copy_seccomp() to no failure path. + +From: Kuniyuki Iwashima + +[ Upstream commit a1140cb215fa13dcec06d12ba0c3ee105633b7c4 ] + +Our syzbot instance reported memory leaks in do_seccomp() [0], similar +to the report [1]. It shows that we miss freeing struct seccomp_filter +and some objects included in it. + +We can reproduce the issue with the program below [2] which calls one +seccomp() and two clone() syscalls. + +The first clone()d child exits earlier than its parent and sends a +signal to kill it during the second clone(), more precisely before the +fatal_signal_pending() test in copy_process(). When the parent receives +the signal, it has to destroy the embryonic process and return -EINTR to +user space. In the failure path, we have to call seccomp_filter_release() +to decrement the filter's refcount. + +Initially, we called it in free_task() called from the failure path, but +the commit 3a15fb6ed92c ("seccomp: release filter after task is fully +dead") moved it to release_task() to notify user space as early as possible +that the filter is no longer used. + +To keep the change and current seccomp refcount semantics, let's move +copy_seccomp() just after the signal check and add a WARN_ON_ONCE() in +free_task() for future debugging. + +[0]: +unreferenced object 0xffff8880063add00 (size 256): + comm "repro_seccomp", pid 230, jiffies 4294687090 (age 9.914s) + hex dump (first 32 bytes): + 01 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................ + ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ + backtrace: + do_seccomp (./include/linux/slab.h:600 ./include/linux/slab.h:733 kernel/seccomp.c:666 kernel/seccomp.c:708 kernel/seccomp.c:1871 kernel/seccomp.c:1991) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) +unreferenced object 0xffffc90000035000 (size 4096): + comm "repro_seccomp", pid 230, jiffies 4294687090 (age 9.915s) + hex dump (first 32 bytes): + 01 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + __vmalloc_node_range (mm/vmalloc.c:3226) + __vmalloc_node (mm/vmalloc.c:3261 (discriminator 4)) + bpf_prog_alloc_no_stats (kernel/bpf/core.c:91) + bpf_prog_alloc (kernel/bpf/core.c:129) + bpf_prog_create_from_user (net/core/filter.c:1414) + do_seccomp (kernel/seccomp.c:671 kernel/seccomp.c:708 kernel/seccomp.c:1871 kernel/seccomp.c:1991) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) +unreferenced object 0xffff888003fa1000 (size 1024): + comm "repro_seccomp", pid 230, jiffies 4294687090 (age 9.915s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + bpf_prog_alloc_no_stats (./include/linux/slab.h:600 ./include/linux/slab.h:733 kernel/bpf/core.c:95) + bpf_prog_alloc (kernel/bpf/core.c:129) + bpf_prog_create_from_user (net/core/filter.c:1414) + do_seccomp (kernel/seccomp.c:671 kernel/seccomp.c:708 kernel/seccomp.c:1871 kernel/seccomp.c:1991) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) +unreferenced object 0xffff888006360240 (size 16): + comm "repro_seccomp", pid 230, jiffies 4294687090 (age 9.915s) + hex dump (first 16 bytes): + 01 00 37 00 76 65 72 6c e0 83 01 06 80 88 ff ff ..7.verl........ + backtrace: + bpf_prog_store_orig_filter (net/core/filter.c:1137) + bpf_prog_create_from_user (net/core/filter.c:1428) + do_seccomp (kernel/seccomp.c:671 kernel/seccomp.c:708 kernel/seccomp.c:1871 kernel/seccomp.c:1991) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) +unreferenced object 0xffff8880060183e0 (size 8): + comm "repro_seccomp", pid 230, jiffies 4294687090 (age 9.915s) + hex dump (first 8 bytes): + 06 00 00 00 00 00 ff 7f ........ + backtrace: + kmemdup (mm/util.c:129) + bpf_prog_store_orig_filter (net/core/filter.c:1144) + bpf_prog_create_from_user (net/core/filter.c:1428) + do_seccomp (kernel/seccomp.c:671 kernel/seccomp.c:708 kernel/seccomp.c:1871 kernel/seccomp.c:1991) + do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) + +[1]: https://syzkaller.appspot.com/bug?id=2809bb0ac77ad9aa3f4afe42d6a610aba594a987 + +[2]: + +void main(void) +{ + struct sock_filter filter[] = { + BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), + }; + struct sock_fprog fprog = { + .len = sizeof(filter) / sizeof(filter[0]), + .filter = filter, + }; + long i, pid; + + syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &fprog); + + for (i = 0; i < 2; i++) { + pid = syscall(__NR_clone, CLONE_NEWNET | SIGKILL, NULL, NULL, 0); + if (pid == 0) + return; + } +} + +Fixes: 3a15fb6ed92c ("seccomp: release filter after task is fully dead") +Reported-by: syzbot+ab17848fe269b573eb71@syzkaller.appspotmail.com +Reported-by: Ayushman Dutta +Suggested-by: Kees Cook +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Christian Brauner (Microsoft) +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20220823154532.82913-1-kuniyu@amazon.com +Signed-off-by: Sasha Levin +--- + kernel/fork.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/kernel/fork.c b/kernel/fork.c +index 908ba3c93893..3fb7e9e6a7b9 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -446,6 +446,9 @@ void put_task_stack(struct task_struct *tsk) + + void free_task(struct task_struct *tsk) + { ++#ifdef CONFIG_SECCOMP ++ WARN_ON_ONCE(tsk->seccomp.filter); ++#endif + release_user_cpus_ptr(tsk); + scs_release(tsk); + +@@ -2345,12 +2348,6 @@ static __latent_entropy struct task_struct *copy_process( + + spin_lock(¤t->sighand->siglock); + +- /* +- * Copy seccomp details explicitly here, in case they were changed +- * before holding sighand lock. +- */ +- copy_seccomp(p); +- + rseq_fork(p, clone_flags); + + /* Don't start children in a dying pid namespace */ +@@ -2365,6 +2362,14 @@ static __latent_entropy struct task_struct *copy_process( + goto bad_fork_cancel_cgroup; + } + ++ /* No more failure paths after this point. */ ++ ++ /* ++ * Copy seccomp details explicitly here, in case they were changed ++ * before holding sighand lock. ++ */ ++ copy_seccomp(p); ++ + init_task_pid_links(p); + if (likely(p->pid)) { + ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace); +-- +2.35.1 + diff --git a/queue-5.15/selftests-bpf-add-test-for-unstable-ct-lookup-api.patch b/queue-5.15/selftests-bpf-add-test-for-unstable-ct-lookup-api.patch new file mode 100644 index 00000000000..97f9b892af5 --- /dev/null +++ b/queue-5.15/selftests-bpf-add-test-for-unstable-ct-lookup-api.patch @@ -0,0 +1,209 @@ +From 08a41000ce4f41bfa13789d967d03661b33ce531 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jan 2022 22:09:50 +0530 +Subject: selftests/bpf: Add test for unstable CT lookup API + +From: Kumar Kartikeya Dwivedi + +[ Upstream commit 87091063df5d4845d1db0761a9ed5510c4756a96 ] + +This tests that we return errors as documented, and also that the kfunc +calls work from both XDP and TC hooks. + +Signed-off-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20220114163953.1455836-8-memxor@gmail.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: a8dfde09c901 ("selftests/bpf: Select CONFIG_FUNCTION_ERROR_INJECTION") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/config | 4 + + .../testing/selftests/bpf/prog_tests/bpf_nf.c | 48 ++++++++ + .../testing/selftests/bpf/progs/test_bpf_nf.c | 109 ++++++++++++++++++ + 3 files changed, 161 insertions(+) + create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_nf.c + create mode 100644 tools/testing/selftests/bpf/progs/test_bpf_nf.c + +diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config +index 5192305159ec..4a2a47fcd6ef 100644 +--- a/tools/testing/selftests/bpf/config ++++ b/tools/testing/selftests/bpf/config +@@ -46,3 +46,7 @@ CONFIG_IMA_READ_POLICY=y + CONFIG_BLK_DEV_LOOP=y + CONFIG_FUNCTION_TRACER=y + CONFIG_DYNAMIC_FTRACE=y ++CONFIG_NETFILTER=y ++CONFIG_NF_DEFRAG_IPV4=y ++CONFIG_NF_DEFRAG_IPV6=y ++CONFIG_NF_CONNTRACK=y +diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_nf.c b/tools/testing/selftests/bpf/prog_tests/bpf_nf.c +new file mode 100644 +index 000000000000..e3166a81e989 +--- /dev/null ++++ b/tools/testing/selftests/bpf/prog_tests/bpf_nf.c +@@ -0,0 +1,48 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++#include "test_bpf_nf.skel.h" ++ ++enum { ++ TEST_XDP, ++ TEST_TC_BPF, ++}; ++ ++void test_bpf_nf_ct(int mode) ++{ ++ struct test_bpf_nf *skel; ++ int prog_fd, err, retval; ++ ++ skel = test_bpf_nf__open_and_load(); ++ if (!ASSERT_OK_PTR(skel, "test_bpf_nf__open_and_load")) ++ return; ++ ++ if (mode == TEST_XDP) ++ prog_fd = bpf_program__fd(skel->progs.nf_xdp_ct_test); ++ else ++ prog_fd = bpf_program__fd(skel->progs.nf_skb_ct_test); ++ ++ err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4), NULL, NULL, ++ (__u32 *)&retval, NULL); ++ if (!ASSERT_OK(err, "bpf_prog_test_run")) ++ goto end; ++ ++ ASSERT_EQ(skel->bss->test_einval_bpf_tuple, -EINVAL, "Test EINVAL for NULL bpf_tuple"); ++ ASSERT_EQ(skel->bss->test_einval_reserved, -EINVAL, "Test EINVAL for reserved not set to 0"); ++ ASSERT_EQ(skel->bss->test_einval_netns_id, -EINVAL, "Test EINVAL for netns_id < -1"); ++ ASSERT_EQ(skel->bss->test_einval_len_opts, -EINVAL, "Test EINVAL for len__opts != NF_BPF_CT_OPTS_SZ"); ++ ASSERT_EQ(skel->bss->test_eproto_l4proto, -EPROTO, "Test EPROTO for l4proto != TCP or UDP"); ++ ASSERT_EQ(skel->bss->test_enonet_netns_id, -ENONET, "Test ENONET for bad but valid netns_id"); ++ ASSERT_EQ(skel->bss->test_enoent_lookup, -ENOENT, "Test ENOENT for failed lookup"); ++ ASSERT_EQ(skel->bss->test_eafnosupport, -EAFNOSUPPORT, "Test EAFNOSUPPORT for invalid len__tuple"); ++end: ++ test_bpf_nf__destroy(skel); ++} ++ ++void test_bpf_nf(void) ++{ ++ if (test__start_subtest("xdp-ct")) ++ test_bpf_nf_ct(TEST_XDP); ++ if (test__start_subtest("tc-bpf-ct")) ++ test_bpf_nf_ct(TEST_TC_BPF); ++} +diff --git a/tools/testing/selftests/bpf/progs/test_bpf_nf.c b/tools/testing/selftests/bpf/progs/test_bpf_nf.c +new file mode 100644 +index 000000000000..6f131c993c0b +--- /dev/null ++++ b/tools/testing/selftests/bpf/progs/test_bpf_nf.c +@@ -0,0 +1,109 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include ++#include ++ ++#define EAFNOSUPPORT 97 ++#define EPROTO 71 ++#define ENONET 64 ++#define EINVAL 22 ++#define ENOENT 2 ++ ++int test_einval_bpf_tuple = 0; ++int test_einval_reserved = 0; ++int test_einval_netns_id = 0; ++int test_einval_len_opts = 0; ++int test_eproto_l4proto = 0; ++int test_enonet_netns_id = 0; ++int test_enoent_lookup = 0; ++int test_eafnosupport = 0; ++ ++struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *, struct bpf_sock_tuple *, u32, ++ struct bpf_ct_opts *, u32) __ksym; ++struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32, ++ struct bpf_ct_opts *, u32) __ksym; ++void bpf_ct_release(struct nf_conn *) __ksym; ++ ++static __always_inline void ++nf_ct_test(struct nf_conn *(*func)(void *, struct bpf_sock_tuple *, u32, ++ struct bpf_ct_opts *, u32), ++ void *ctx) ++{ ++ struct bpf_ct_opts opts_def = { .l4proto = IPPROTO_TCP, .netns_id = -1 }; ++ struct bpf_sock_tuple bpf_tuple; ++ struct nf_conn *ct; ++ ++ __builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4)); ++ ++ ct = func(ctx, NULL, 0, &opts_def, sizeof(opts_def)); ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_einval_bpf_tuple = opts_def.error; ++ ++ opts_def.reserved[0] = 1; ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); ++ opts_def.reserved[0] = 0; ++ opts_def.l4proto = IPPROTO_TCP; ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_einval_reserved = opts_def.error; ++ ++ opts_def.netns_id = -2; ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); ++ opts_def.netns_id = -1; ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_einval_netns_id = opts_def.error; ++ ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def) - 1); ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_einval_len_opts = opts_def.error; ++ ++ opts_def.l4proto = IPPROTO_ICMP; ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); ++ opts_def.l4proto = IPPROTO_TCP; ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_eproto_l4proto = opts_def.error; ++ ++ opts_def.netns_id = 0xf00f; ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); ++ opts_def.netns_id = -1; ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_enonet_netns_id = opts_def.error; ++ ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def, sizeof(opts_def)); ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_enoent_lookup = opts_def.error; ++ ++ ct = func(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4) - 1, &opts_def, sizeof(opts_def)); ++ if (ct) ++ bpf_ct_release(ct); ++ else ++ test_eafnosupport = opts_def.error; ++} ++ ++SEC("xdp") ++int nf_xdp_ct_test(struct xdp_md *ctx) ++{ ++ nf_ct_test((void *)bpf_xdp_ct_lookup, ctx); ++ return 0; ++} ++ ++SEC("tc") ++int nf_skb_ct_test(struct __sk_buff *ctx) ++{ ++ nf_ct_test((void *)bpf_skb_ct_lookup, ctx); ++ return 0; ++} ++ ++char _license[] SEC("license") = "GPL"; +-- +2.35.1 + diff --git a/queue-5.15/selftests-devlink-fix-the-fd-redirect-in-dummy_repor.patch b/queue-5.15/selftests-devlink-fix-the-fd-redirect-in-dummy_repor.patch new file mode 100644 index 00000000000..730301c997d --- /dev/null +++ b/queue-5.15/selftests-devlink-fix-the-fd-redirect-in-dummy_repor.patch @@ -0,0 +1,45 @@ +From cea653ff392eba581dde7db5b770cfe09ac6ef58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Dec 2022 18:01:01 -0800 +Subject: selftests: devlink: fix the fd redirect in dummy_reporter_test + +From: Jakub Kicinski + +[ Upstream commit 2fc60e2ff972d3dca836bff0b08cbe503c4ca1ce ] + +$number + > bash means redirect FD $number, e.g. commonly +used 2> redirects stderr (fd 2). The test uses 8192> to +write the number 8192 to a file, this results in: + + ./devlink.sh: line 499: 8192: Bad file descriptor + +Oddly the test also papers over this issue by checking +for failure (expecting an error rather than success) +so it passes, anyway. + +Fixes: ff18176ad806 ("selftests: Add a test of large binary to devlink health test") +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/netdevsim/devlink.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +index 9de1d123f4f5..a08c02abde12 100755 +--- a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh ++++ b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +@@ -496,8 +496,8 @@ dummy_reporter_test() + + check_reporter_info dummy healthy 3 3 10 true + +- echo 8192> $DEBUGFS_DIR/health/binary_len +- check_fail $? "Failed set dummy reporter binary len to 8192" ++ echo 8192 > $DEBUGFS_DIR/health/binary_len ++ check_err $? "Failed set dummy reporter binary len to 8192" + + local dump=$(devlink health dump show $DL_HANDLE reporter dummy -j) + check_err $? "Failed show dump of dummy reporter" +-- +2.35.1 + diff --git a/queue-5.15/selftests-efivarfs-add-checking-of-the-test-return-v.patch b/queue-5.15/selftests-efivarfs-add-checking-of-the-test-return-v.patch new file mode 100644 index 00000000000..1fda7dafc07 --- /dev/null +++ b/queue-5.15/selftests-efivarfs-add-checking-of-the-test-return-v.patch @@ -0,0 +1,39 @@ +From f8f26dc81fabfd00a0019cc133467d7243b5cd93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:26:26 +0800 +Subject: selftests/efivarfs: Add checking of the test return value + +From: Zhao Gongyi + +[ Upstream commit c93924267fe6f2b44af1849f714ae9cd8117a9cd ] + +Add checking of the test return value, otherwise it will report success +forever for test_create_read(). + +Fixes: dff6d2ae56d0 ("selftests/efivarfs: clean up test files from test_create*()") +Signed-off-by: Zhao Gongyi +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/efivarfs/efivarfs.sh | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/tools/testing/selftests/efivarfs/efivarfs.sh b/tools/testing/selftests/efivarfs/efivarfs.sh +index a90f394f9aa9..d374878cc0ba 100755 +--- a/tools/testing/selftests/efivarfs/efivarfs.sh ++++ b/tools/testing/selftests/efivarfs/efivarfs.sh +@@ -87,6 +87,11 @@ test_create_read() + { + local file=$efivarfs_mount/$FUNCNAME-$test_guid + ./create-read $file ++ if [ $? -ne 0 ]; then ++ echo "create and read $file failed" ++ file_cleanup $file ++ exit 1 ++ fi + file_cleanup $file + } + +-- +2.35.1 + diff --git a/queue-5.15/selftests-ftrace-event_triggers-wait-longer-for-test.patch b/queue-5.15/selftests-ftrace-event_triggers-wait-longer-for-test.patch new file mode 100644 index 00000000000..132267ecc99 --- /dev/null +++ b/queue-5.15/selftests-ftrace-event_triggers-wait-longer-for-test.patch @@ -0,0 +1,57 @@ +From be8d3517c562897b4c267885c54ef182f52ecace Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 10:09:31 +0800 +Subject: selftests/ftrace: event_triggers: wait longer for test_event_enable + +From: Yipeng Zou + +[ Upstream commit a1d6cd88c8973cfb08ee85722488b1d6d5d16327 ] + +In some platform, the schedule event may came slowly, delay 100ms can't +cover it. + +I was notice that on my board which running in low cpu_freq,and this +selftests allways gose fail. + +So maybe we can check more times here to wait longer. + +Fixes: 43bb45da82f9 ("selftests: ftrace: Add a selftest to test event enable/disable func trigger") +Signed-off-by: Yipeng Zou +Acked-by: Masami Hiramatsu (Google) +Acked-by: Steven Rostedt (Google) +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + .../ftrace/test.d/ftrace/func_event_triggers.tc | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +index 3145b0f1835c..27a68bbe778b 100644 +--- a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc ++++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc +@@ -38,11 +38,18 @@ cnt_trace() { + + test_event_enabled() { + val=$1 ++ check_times=10 # wait for 10 * SLEEP_TIME at most + +- e=`cat $EVENT_ENABLE` +- if [ "$e" != $val ]; then +- fail "Expected $val but found $e" +- fi ++ while [ $check_times -ne 0 ]; do ++ e=`cat $EVENT_ENABLE` ++ if [ "$e" == $val ]; then ++ return 0 ++ fi ++ sleep $SLEEP_TIME ++ check_times=$((check_times - 1)) ++ done ++ ++ fail "Expected $val but found $e" + } + + run_enable_disable() { +-- +2.35.1 + diff --git a/queue-5.15/selftests-powerpc-fix-resource-leaks.patch b/queue-5.15/selftests-powerpc-fix-resource-leaks.patch new file mode 100644 index 00000000000..da15638fc24 --- /dev/null +++ b/queue-5.15/selftests-powerpc-fix-resource-leaks.patch @@ -0,0 +1,51 @@ +From 758d3ed6193d80966f48338b802bcda7e22d637a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 12:44:27 +0400 +Subject: selftests/powerpc: Fix resource leaks + +From: Miaoqian Lin + +[ Upstream commit 8f4ab7da904ab7027ccd43ddb4f0094e932a5877 ] + +In check_all_cpu_dscr_defaults, opendir() opens the directory stream. +Add missing closedir() in the error path to release it. + +In check_cpu_dscr_default, open() creates an open file descriptor. +Add missing close() in the error path to release it. + +Fixes: ebd5858c904b ("selftests/powerpc: Add test for all DSCR sysfs interfaces") +Signed-off-by: Miaoqian Lin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20221205084429.570654-1-linmq006@gmail.com +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c +index fbbdffdb2e5d..f20d1c166d1e 100644 +--- a/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c ++++ b/tools/testing/selftests/powerpc/dscr/dscr_sysfs_test.c +@@ -24,6 +24,7 @@ static int check_cpu_dscr_default(char *file, unsigned long val) + rc = read(fd, buf, sizeof(buf)); + if (rc == -1) { + perror("read() failed"); ++ close(fd); + return 1; + } + close(fd); +@@ -65,8 +66,10 @@ static int check_all_cpu_dscr_defaults(unsigned long val) + if (access(file, F_OK)) + continue; + +- if (check_cpu_dscr_default(file, val)) ++ if (check_cpu_dscr_default(file, val)) { ++ closedir(sysfs); + return 1; ++ } + } + closedir(sysfs); + return 0; +-- +2.35.1 + diff --git a/queue-5.15/serial-8250_bcm7271-fix-error-handling-in-brcmuart_i.patch b/queue-5.15/serial-8250_bcm7271-fix-error-handling-in-brcmuart_i.patch new file mode 100644 index 00000000000..6ad3c9d9961 --- /dev/null +++ b/queue-5.15/serial-8250_bcm7271-fix-error-handling-in-brcmuart_i.patch @@ -0,0 +1,64 @@ +From fec833ce3eeab8c80108289ffb0233cf6af77d72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 07:21:10 +0000 +Subject: serial: 8250_bcm7271: Fix error handling in brcmuart_init() + +From: Yuan Can + +[ Upstream commit 6a3ff858915fa8ca36c7eb02c87c9181ae2fc333 ] + +A problem about 8250_bcm7271 create debugfs failed is triggered with the +following log given: + + [ 324.516635] debugfs: Directory 'bcm7271-uart' with parent '/' already present! + +The reason is that brcmuart_init() returns platform_driver_register() +directly without checking its return value, if platform_driver_register() +failed, it returns without destroy the newly created debugfs, resulting +the debugfs of 8250_bcm7271 can never be created later. + + brcmuart_init() + debugfs_create_dir() # create debugfs directory + platform_driver_register() + driver_register() + bus_add_driver() + priv = kzalloc(...) # OOM happened + # return without destroy debugfs directory + +Fix by removing debugfs when platform_driver_register() returns error. + +Fixes: 41a469482de2 ("serial: 8250: Add new 8250-core based Broadcom STB driver") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221109072110.117291-2-yuancan@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/8250/8250_bcm7271.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c +index 711cf30e835a..60b3ac1a0317 100644 +--- a/drivers/tty/serial/8250/8250_bcm7271.c ++++ b/drivers/tty/serial/8250/8250_bcm7271.c +@@ -1214,9 +1214,17 @@ static struct platform_driver brcmuart_platform_driver = { + + static int __init brcmuart_init(void) + { ++ int ret; ++ + brcmuart_debugfs_root = debugfs_create_dir( + brcmuart_platform_driver.driver.name, NULL); +- return platform_driver_register(&brcmuart_platform_driver); ++ ret = platform_driver_register(&brcmuart_platform_driver); ++ if (ret) { ++ debugfs_remove_recursive(brcmuart_debugfs_root); ++ return ret; ++ } ++ ++ return 0; + } + module_init(brcmuart_init); + +-- +2.35.1 + diff --git a/queue-5.15/serial-altera_uart-fix-locking-in-polling-mode.patch b/queue-5.15/serial-altera_uart-fix-locking-in-polling-mode.patch new file mode 100644 index 00000000000..7867f09e4c1 --- /dev/null +++ b/queue-5.15/serial-altera_uart-fix-locking-in-polling-mode.patch @@ -0,0 +1,51 @@ +From 7298351e45aa4f02d8e8b0e252cae48741f0fa48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 15:04:26 -0500 +Subject: serial: altera_uart: fix locking in polling mode + +From: Gabriel Somlo + +[ Upstream commit 1307c5d33cce8a41dd77c2571e4df65a5b627feb ] + +Since altera_uart_interrupt() may also be called from +a poll timer in "serving_softirq" context, use +spin_[lock_irqsave|unlock_irqrestore] variants, which +are appropriate for both softirq and hardware interrupt +contexts. + +Fixes: 2f8b9c15cd88 ("altera_uart: Add support for polling mode (IRQ-less)") +Signed-off-by: Gabriel Somlo +Link: https://lore.kernel.org/r/20221122200426.888349-1-gsomlo@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/altera_uart.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c +index 6e08fa11ceea..91799c420e25 100644 +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -278,16 +278,17 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) + { + struct uart_port *port = data; + struct altera_uart *pp = container_of(port, struct altera_uart, port); ++ unsigned long flags; + unsigned int isr; + + isr = altera_uart_readl(port, ALTERA_UART_STATUS_REG) & pp->imr; + +- spin_lock(&port->lock); ++ spin_lock_irqsave(&port->lock, flags); + if (isr & ALTERA_UART_STATUS_RRDY_MSK) + altera_uart_rx_chars(port); + if (isr & ALTERA_UART_STATUS_TRDY_MSK) + altera_uart_tx_chars(port); +- spin_unlock(&port->lock); ++ spin_unlock_irqrestore(&port->lock, flags); + + return IRQ_RETVAL(isr); + } +-- +2.35.1 + diff --git a/queue-5.15/serial-amba-pl011-avoid-sbsa-uart-accessing-dmacr-re.patch b/queue-5.15/serial-amba-pl011-avoid-sbsa-uart-accessing-dmacr-re.patch new file mode 100644 index 00000000000..0d403ee3ce9 --- /dev/null +++ b/queue-5.15/serial-amba-pl011-avoid-sbsa-uart-accessing-dmacr-re.patch @@ -0,0 +1,93 @@ +From 2b3d76c97be49fdba735652eb922e51eab590f35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 18:32:37 +0800 +Subject: serial: amba-pl011: avoid SBSA UART accessing DMACR register + +From: Jiamei Xie + +[ Upstream commit 94cdb9f33698478b0e7062586633c42c6158a786 ] + +Chapter "B Generic UART" in "ARM Server Base System Architecture" [1] +documentation describes a generic UART interface. Such generic UART +does not support DMA. In current code, sbsa_uart_pops and +amba_pl011_pops share the same stop_rx operation, which will invoke +pl011_dma_rx_stop, leading to an access of the DMACR register. This +commit adds a using_rx_dma check in pl011_dma_rx_stop to avoid the +access to DMACR register for SBSA UARTs which does not support DMA. + +When the kernel enables DMA engine with "CONFIG_DMA_ENGINE=y", Linux +SBSA PL011 driver will access PL011 DMACR register in some functions. +For most real SBSA Pl011 hardware implementations, the DMACR write +behaviour will be ignored. So these DMACR operations will not cause +obvious problems. But for some virtual SBSA PL011 hardware, like Xen +virtual SBSA PL011 (vpl011) device, the behaviour might be different. +Xen vpl011 emulation will inject a data abort to guest, when guest is +accessing an unimplemented UART register. As Xen VPL011 is SBSA +compatible, it will not implement DMACR register. So when Linux SBSA +PL011 driver access DMACR register, it will get an unhandled data abort +fault and the application will get a segmentation fault: +Unhandled fault at 0xffffffc00944d048 +Mem abort info: + ESR = 0x96000000 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x00: ttbr address size fault +Data abort info: + ISV = 0, ISS = 0x00000000 + CM = 0, WnR = 0 +swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000020e2e000 +[ffffffc00944d048] pgd=100000003ffff803, p4d=100000003ffff803, pud=100000003ffff803, pmd=100000003fffa803, pte=006800009c090f13 +Internal error: ttbr address size fault: 96000000 [#1] PREEMPT SMP +... +Call trace: + pl011_stop_rx+0x70/0x80 + tty_port_shutdown+0x7c/0xb4 + tty_port_close+0x60/0xcc + uart_close+0x34/0x8c + tty_release+0x144/0x4c0 + __fput+0x78/0x220 + ____fput+0x1c/0x30 + task_work_run+0x88/0xc0 + do_notify_resume+0x8d0/0x123c + el0_svc+0xa8/0xc0 + el0t_64_sync_handler+0xa4/0x130 + el0t_64_sync+0x1a0/0x1a4 +Code: b9000083 b901f001 794038a0 8b000042 (b9000041) +---[ end trace 83dd93df15c3216f ]--- +note: bootlogd[132] exited with preempt_count 1 +/etc/rcS.d/S07bootlogd: line 47: 132 Segmentation fault start-stop-daemon + +This has been discussed in the Xen community, and we think it should fix +this in Linux. See [2] for more information. + +[1] https://developer.arm.com/documentation/den0094/c/?lang=en +[2] https://lists.xenproject.org/archives/html/xen-devel/2022-11/msg00543.html + +Fixes: 0dd1e247fd39 (drivers: PL011: add support for the ARM SBSA generic UART) +Signed-off-by: Jiamei Xie +Reviewed-by: Andre Przywara +Link: https://lore.kernel.org/r/20221117103237.86856-1-jiamei.xie@arm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/amba-pl011.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index 300a8bbb4b80..ca105e9baa42 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1050,6 +1050,9 @@ static void pl011_dma_rx_callback(void *data) + */ + static inline void pl011_dma_rx_stop(struct uart_amba_port *uap) + { ++ if (!uap->using_rx_dma) ++ return; ++ + /* FIXME. Just disable the DMA enable */ + uap->dmacr &= ~UART011_RXDMAE; + pl011_write(uap->dmacr, uap, REG_DMACR); +-- +2.35.1 + diff --git a/queue-5.15/serial-pch-fix-pci-device-refcount-leak-in-pch_reque.patch b/queue-5.15/serial-pch-fix-pci-device-refcount-leak-in-pch_reque.patch new file mode 100644 index 00000000000..0d2ace7ae18 --- /dev/null +++ b/queue-5.15/serial-pch-fix-pci-device-refcount-leak-in-pch_reque.patch @@ -0,0 +1,58 @@ +From ea3b90d7c25c63ab9e67bd6be5bde028f9e9a11e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:45:59 +0800 +Subject: serial: pch: Fix PCI device refcount leak in pch_request_dma() + +From: Xiongfeng Wang + +[ Upstream commit 8be3a7bf773700534a6e8f87f6ed2ed111254be5 ] + +As comment of pci_get_slot() says, it returns a pci_device with its +refcount increased. The caller must decrement the reference count by +calling pci_dev_put(). + +Since 'dma_dev' is only used to filter the channel in filter(), we can +call pci_dev_put() before exiting from pch_request_dma(). Add the +missing pci_dev_put() for the normal and error path. + +Fixes: 3c6a483275f4 ("Serial: EG20T: add PCH_UART driver") +Signed-off-by: Xiongfeng Wang +Link: https://lore.kernel.org/r/20221122114559.27692-1-wangxiongfeng2@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/pch_uart.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c +index 1e65933f6cce..52cab2038da8 100644 +--- a/drivers/tty/serial/pch_uart.c ++++ b/drivers/tty/serial/pch_uart.c +@@ -707,6 +707,7 @@ static void pch_request_dma(struct uart_port *port) + if (!chan) { + dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n", + __func__); ++ pci_dev_put(dma_dev); + return; + } + priv->chan_tx = chan; +@@ -723,6 +724,7 @@ static void pch_request_dma(struct uart_port *port) + __func__); + dma_release_channel(priv->chan_tx); + priv->chan_tx = NULL; ++ pci_dev_put(dma_dev); + return; + } + +@@ -730,6 +732,8 @@ static void pch_request_dma(struct uart_port *port) + priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize, + &priv->rx_buf_dma, GFP_KERNEL); + priv->chan_rx = chan; ++ ++ pci_dev_put(dma_dev); + } + + static void pch_dma_rx_complete(void *arg) +-- +2.35.1 + diff --git a/queue-5.15/serial-pl011-do-not-clear-rx-fifo-rx-interrupt-in-un.patch b/queue-5.15/serial-pl011-do-not-clear-rx-fifo-rx-interrupt-in-un.patch new file mode 100644 index 00000000000..6495c085780 --- /dev/null +++ b/queue-5.15/serial-pl011-do-not-clear-rx-fifo-rx-interrupt-in-un.patch @@ -0,0 +1,52 @@ +From 1782c02c3cfcd522f5c4f45c52c94fc788fcf25a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 10:01:08 +0800 +Subject: serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: delisun + +[ Upstream commit 032d5a71ed378ffc6a2d41a187d8488a4f9fe415 ] + +Clearing the RX FIFO will cause data loss. +Copy the pl011_enabl_interrupts implementation, and remove the clear +interrupt and FIFO part of the code. + +Fixes: 211565b10099 ("serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle") +Signed-off-by: delisun +Reviewed-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20221110020108.7700-1-delisun@pateo.com.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/amba-pl011.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index ca105e9baa42..7c8515f83f0a 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1836,8 +1836,17 @@ static void pl011_enable_interrupts(struct uart_amba_port *uap) + static void pl011_unthrottle_rx(struct uart_port *port) + { + struct uart_amba_port *uap = container_of(port, struct uart_amba_port, port); ++ unsigned long flags; + +- pl011_enable_interrupts(uap); ++ spin_lock_irqsave(&uap->port.lock, flags); ++ ++ uap->im = UART011_RTIM; ++ if (!pl011_dma_rx_running(uap)) ++ uap->im |= UART011_RXIM; ++ ++ pl011_write(uap->im, uap, REG_IMSC); ++ ++ spin_unlock_irqrestore(&uap->port.lock, flags); + } + + static int pl011_startup(struct uart_port *port) +-- +2.35.1 + diff --git a/queue-5.15/serial-stm32-move-dma_request_chan-before-clk_prepar.patch b/queue-5.15/serial-stm32-move-dma_request_chan-before-clk_prepar.patch new file mode 100644 index 00000000000..b9f21f1da1e --- /dev/null +++ b/queue-5.15/serial-stm32-move-dma_request_chan-before-clk_prepar.patch @@ -0,0 +1,117 @@ +From 91f169be5f40713e5884bef17e6059a7a2b1216e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 18 Nov 2022 18:06:02 +0100 +Subject: serial: stm32: move dma_request_chan() before clk_prepare_enable() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Valentin Caron + +[ Upstream commit 0d114e9ff940ebad8e88267013bf96c605a6b336 ] + +If dma_request_chan() returns a PROBE_DEFER error, clk_disable_unprepare() +will be called and USART clock will be disabled. But early console can be +still active on the same USART. + +While moving dma_request_chan() before clk_prepare_enable(), the clock +won't be taken in case of a DMA PROBE_DEFER error, and so it doesn't need +to be disabled. Then USART is still clocked for early console. + +Fixes: a7770a4bfcf4 ("serial: stm32: defer probe for dma devices") +Reported-by: Uwe Kleine-König +Signed-off-by: Valentin Caron +Link: https://lore.kernel.org/r/20221118170602.1057863-1-valentin.caron@foss.st.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/stm32-usart.c | 47 ++++++++++++++++---------------- + 1 file changed, 23 insertions(+), 24 deletions(-) + +diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c +index ce7ff7a0207f..5c60960e185d 100644 +--- a/drivers/tty/serial/stm32-usart.c ++++ b/drivers/tty/serial/stm32-usart.c +@@ -1363,22 +1363,10 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + if (!stm32port->info) + return -EINVAL; + +- ret = stm32_usart_init_port(stm32port, pdev); +- if (ret) +- return ret; +- +- if (stm32port->wakeup_src) { +- device_set_wakeup_capable(&pdev->dev, true); +- ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); +- if (ret) +- goto err_deinit_port; +- } +- + stm32port->rx_ch = dma_request_chan(&pdev->dev, "rx"); +- if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) { +- ret = -EPROBE_DEFER; +- goto err_wakeirq; +- } ++ if (PTR_ERR(stm32port->rx_ch) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ + /* Fall back in interrupt mode for any non-deferral error */ + if (IS_ERR(stm32port->rx_ch)) + stm32port->rx_ch = NULL; +@@ -1392,6 +1380,17 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + if (IS_ERR(stm32port->tx_ch)) + stm32port->tx_ch = NULL; + ++ ret = stm32_usart_init_port(stm32port, pdev); ++ if (ret) ++ goto err_dma_tx; ++ ++ if (stm32port->wakeup_src) { ++ device_set_wakeup_capable(&pdev->dev, true); ++ ret = dev_pm_set_wake_irq(&pdev->dev, stm32port->port.irq); ++ if (ret) ++ goto err_deinit_port; ++ } ++ + if (stm32port->rx_ch && stm32_usart_of_dma_rx_probe(stm32port, pdev)) { + /* Fall back in interrupt mode */ + dma_release_channel(stm32port->rx_ch); +@@ -1428,19 +1427,11 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + +- if (stm32port->tx_ch) { ++ if (stm32port->tx_ch) + stm32_usart_of_dma_tx_remove(stm32port, pdev); +- dma_release_channel(stm32port->tx_ch); +- } +- + if (stm32port->rx_ch) + stm32_usart_of_dma_rx_remove(stm32port, pdev); + +-err_dma_rx: +- if (stm32port->rx_ch) +- dma_release_channel(stm32port->rx_ch); +- +-err_wakeirq: + if (stm32port->wakeup_src) + dev_pm_clear_wake_irq(&pdev->dev); + +@@ -1450,6 +1441,14 @@ static int stm32_usart_serial_probe(struct platform_device *pdev) + + stm32_usart_deinit_port(stm32port); + ++err_dma_tx: ++ if (stm32port->tx_ch) ++ dma_release_channel(stm32port->tx_ch); ++ ++err_dma_rx: ++ if (stm32port->rx_ch) ++ dma_release_channel(stm32port->rx_ch); ++ + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/serial-sunsab-fix-error-handling-in-sunsab_init.patch b/queue-5.15/serial-sunsab-fix-error-handling-in-sunsab_init.patch new file mode 100644 index 00000000000..721563792bd --- /dev/null +++ b/queue-5.15/serial-sunsab-fix-error-handling-in-sunsab_init.patch @@ -0,0 +1,46 @@ +From 35c9524429bdd0801de67c4d410e90a699c55c75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 06:12:12 +0000 +Subject: serial: sunsab: Fix error handling in sunsab_init() + +From: Yuan Can + +[ Upstream commit 1a6ec673fb627c26e2267ca0a03849f91dbd9b40 ] + +The sunsab_init() returns the platform_driver_register() directly without +checking its return value, if platform_driver_register() failed, the +allocated sunsab_ports is leaked. +Fix by free sunsab_ports and set it to NULL when platform_driver_register() +failed. + +Fixes: c4d37215a824 ("[SERIAL] sunsab: Convert to of_driver framework.") +Signed-off-by: Yuan Can +Link: https://lore.kernel.org/r/20221123061212.52593-1-yuancan@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/sunsab.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c +index 92e572634009..ac7cb80e4d6b 100644 +--- a/drivers/tty/serial/sunsab.c ++++ b/drivers/tty/serial/sunsab.c +@@ -1137,7 +1137,13 @@ static int __init sunsab_init(void) + } + } + +- return platform_driver_register(&sab_driver); ++ err = platform_driver_register(&sab_driver); ++ if (err) { ++ kfree(sunsab_ports); ++ sunsab_ports = NULL; ++ } ++ ++ return err; + } + + static void __exit sunsab_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/serial-tegra-read-dma-status-before-terminating.patch b/queue-5.15/serial-tegra-read-dma-status-before-terminating.patch new file mode 100644 index 00000000000..163eae93236 --- /dev/null +++ b/queue-5.15/serial-tegra-read-dma-status-before-terminating.patch @@ -0,0 +1,60 @@ +From b42edab3b327c3c8d00278fdd8b5ac7f52324bef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 20:28:06 +0530 +Subject: serial: tegra: Read DMA status before terminating +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kartik + +[ Upstream commit 109a951a9f1fd8a34ebd1896cbbd5d5cede880a7 ] + +Read the DMA status before terminating the DMA, as doing so deletes +the DMA desc. + +Also, to get the correct transfer status information, pause the DMA +using dmaengine_pause() before reading the DMA status. + +Fixes: e9ea096dd225 ("serial: tegra: add serial driver") +Reviewed-by: Jon Hunter +Reviewed-by: Ilpo Järvinen +Acked-by: Thierry Reding +Signed-off-by: Akhil R +Signed-off-by: Kartik +Link: https://lore.kernel.org/r/1666105086-17326-1-git-send-email-kkartik@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/serial-tegra.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c +index d4dba298de7a..79187ff9ac13 100644 +--- a/drivers/tty/serial/serial-tegra.c ++++ b/drivers/tty/serial/serial-tegra.c +@@ -619,8 +619,9 @@ static void tegra_uart_stop_tx(struct uart_port *u) + if (tup->tx_in_progress != TEGRA_UART_TX_DMA) + return; + +- dmaengine_terminate_all(tup->tx_dma_chan); ++ dmaengine_pause(tup->tx_dma_chan); + dmaengine_tx_status(tup->tx_dma_chan, tup->tx_cookie, &state); ++ dmaengine_terminate_all(tup->tx_dma_chan); + count = tup->tx_bytes_requested - state.residue; + async_tx_ack(tup->tx_dma_desc); + uart_xmit_advance(&tup->uport, count); +@@ -763,8 +764,9 @@ static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup) + return; + } + +- dmaengine_terminate_all(tup->rx_dma_chan); ++ dmaengine_pause(tup->rx_dma_chan); + dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state); ++ dmaengine_terminate_all(tup->rx_dma_chan); + + tegra_uart_rx_buffer_push(tup, state.residue); + tup->rx_dma_active = false; +-- +2.35.1 + diff --git a/queue-5.15/series b/queue-5.15/series index 4980741188e..6a432349be5 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -1 +1,687 @@ drm-amd-display-manually-adjust-strobe-for-dcn303.patch +usb-musb-remove-extra-check-in-musb_gadget_vbus_draw.patch +arm64-dts-qcom-ipq6018-cp01-c1-use-blspi1-pins.patch +arm64-dts-qcom-sm8250-sony-xperia-edo-fix-touchscree.patch +arm64-dts-qcom-msm8996-add-msm8996-pro-support.patch +arm64-dts-qcom-msm8996-fix-supported-hw-in-cpufreq-o.patch +arm64-dts-qcom-msm8996-fix-gpu-opp-table.patch +arm-dts-qcom-apq8064-fix-coresight-compatible.patch +arm64-dts-qcom-sdm630-fix-uart1-pin-bias.patch +arm64-dts-qcom-sdm845-cheza-fix-ap-suspend-pin-bias.patch +arm64-dts-qcom-msm8916-drop-mss-fallback-compatible.patch +objtool-kcsan-add-volatile-read-write-instrumentatio.patch +arm-dts-stm32-drop-stm32mp15xc.dtsi-from-avenger96.patch +arm-dts-stm32-fix-av96-wlan-regulator-gpio-property.patch +drivers-soc-ti-knav_qmss_queue-mark-knav_acc_firmwar.patch +arm64-dts-qcom-pm660-use-unique-adc5_vcoin-address-i.patch +arm64-dts-qcom-sm8250-correct-lpass-pin-pull-down.patch +soc-qcom-llcc-make-irq-truly-optional.patch +arm64-dts-qcom-correct-qmp-phy-child-node-name.patch +arm64-dts-qcom-sm8150-fix-ufs-phy-registers.patch +arm64-dts-qcom-sm8250-fix-ufs-phy-registers.patch +arm64-dts-qcom-sm8350-fix-ufs-phy-registers.patch +arm64-dts-qcom-sm8250-drop-bogus-dp-phy-clock.patch +soc-qcom-apr-make-code-more-reuseable.patch +soc-qcom-apr-add-check-for-idr_alloc-and-of_property.patch +arm64-dts-qcom-sm6125-fix-sdhci-cqe-reg-names.patch +arm-dts-spear600-fix-clcd-interrupt.patch +soc-ti-knav_qmss_queue-use-pm_runtime_resume_and_get.patch +soc-ti-knav_qmss_queue-fix-pm-disable-depth-imbalanc.patch +soc-ti-smartreflex-fix-pm-disable-depth-imbalance-in.patch +arm64-treat-esr_elx-as-a-64-bit-register.patch +arm64-mm-kfence-only-handle-translation-faults.patch +perf-arm_dsu-fix-hotplug-callback-leak-in-dsu_pmu_in.patch +perf-arm_dmc620-fix-hotplug-callback-leak-in-dmc620_.patch +perf-smmuv3-fix-hotplug-callback-leak-in-arm_smmu_pm.patch +arm64-dts-ti-k3-am65-main-drop-dma-coherent-in-crypt.patch +arm64-dts-ti-k3-j721e-main-drop-dma-coherent-in-cryp.patch +arm-dts-nuvoton-remove-bogus-unit-addresses-from-fix.patch +arm64-dts-mt6779-fix-devicetree-build-warnings.patch +arm64-dts-mt2712e-fix-unit_address_vs_reg-warning-fo.patch +arm64-dts-mt2712e-fix-unit-address-for-pinctrl-node.patch +arm64-dts-mt2712-evb-fix-vproc-fixed-regulators-unit.patch +arm64-dts-mt2712-evb-fix-usb-vbus-regulators-unit-na.patch +arm64-dts-mediatek-pumpkin-common-fix-devicetree-war.patch +arm64-dts-mediatek-mt6797-fix-26m-oscillator-unit-na.patch +arm-dts-dove-fix-assigned-addresses-for-every-pcie-r.patch +arm-dts-armada-370-fix-assigned-addresses-for-every-.patch +arm-dts-armada-xp-fix-assigned-addresses-for-every-p.patch +arm-dts-armada-375-fix-assigned-addresses-for-every-.patch +arm-dts-armada-38x-fix-assigned-addresses-for-every-.patch +arm-dts-armada-39x-fix-assigned-addresses-for-every-.patch +arm-dts-turris-omnia-add-ethernet-aliases.patch +arm-dts-turris-omnia-add-switch-port-6-node.patch +arm-dts-armada-38x-fix-compatible-string-for-gpios.patch +arm-dts-armada-39x-fix-compatible-string-for-gpios.patch +arm64-dts-armada-3720-turris-mox-add-missing-interru.patch +seccomp-move-copy_seccomp-to-no-failure-path.patch +pstore-ram-fix-error-return-code-in-ramoops_probe.patch +arm-mmp-fix-timer_read-delay.patch +pstore-avoid-kcore-oops-by-vmap-ing-with-vm_ioremap.patch +tpm-tpm_ftpm_tee-fix-error-handling-in-ftpm_mod_init.patch +tpm-tpm_crb-fix-error-message-in-__crb_relinquish_lo.patch +ovl-store-lower-path-in-ovl_inode.patch +ovl-use-ovl_copy_-real-upper-attr-wrappers.patch +ovl-remove-privs-in-ovl_copyfile.patch +ovl-remove-privs-in-ovl_fallocate.patch +sched-fair-cleanup-task_util-and-capacity-type.patch +sched-uclamp-fix-relationship-between-uclamp-and-mig.patch +sched-sugov-ignore-busy-filter-when-rq-is-capped-by-.patch +sched-uclamp-make-task_fits_capacity-use-util_fits_c.patch +sched-uclamp-make-select_idle_capacity-use-util_fits.patch +sched-fair-removed-useless-update-of-p-recent_used_c.patch +sched-core-introduce-sched_asym_cpucap_active.patch +sched-uclamp-make-asym_fits_capacity-use-util_fits_c.patch +cpuidle-dt-return-the-correct-numbers-of-parsed-idle.patch +alpha-fix-tif_notify_signal-handling.patch +alpha-fix-syscall-entry-in-audut_syscall-case.patch +x86-sgx-reduce-delay-and-interference-of-enclave-rel.patch +pm-hibernate-fix-mistake-in-kerneldoc-comment.patch +fs-don-t-audit-the-capability-check-in-simple_xattr_.patch +cpufreq-qcom-hw-fix-memory-leak-in-qcom_cpufreq_hw_r.patch +selftests-ftrace-event_triggers-wait-longer-for-test.patch +perf-fix-possible-memleak-in-pmu_dev_alloc.patch +lib-debugobjects-fix-stat-count-and-optimize-debug_o.patch +platform-x86-huawei-wmi-fix-return-value-calculation.patch +timerqueue-use-rb_entry_safe-in-timerqueue_getnext.patch +proc-fixup-uptime-selftest.patch +lib-fonts-fix-undefined-behavior-in-bit-shift-for-ge.patch +ocfs2-fix-memory-leak-in-ocfs2_stack_glue_init.patch +mips-vpe-mt-fix-possible-memory-leak-while-module-ex.patch +mips-vpe-cmp-fix-possible-memory-leak-while-module-e.patch +selftests-efivarfs-add-checking-of-the-test-return-v.patch +pnp-fix-name-memory-leak-in-pnp_alloc_dev.patch +perf-x86-intel-uncore-fix-reference-count-leak-in-sa.patch +perf-x86-intel-uncore-fix-reference-count-leak-in-hs.patch +perf-x86-intel-uncore-fix-reference-count-leak-in-sn.patch +perf-x86-intel-uncore-fix-reference-count-leak-in-__.patch +platform-chrome-cros_usbpd_notify-fix-error-handling.patch +thermal-core-fix-some-possible-name-leaks-in-error-p.patch +irqchip-gic-pm-use-pm_runtime_resume_and_get-in-gic_.patch +irqchip-wpcm450-fix-memory-leak-in-wpcm450_aic_of_in.patch +edac-i10nm-fix-refcount-leak-in-pci_get_dev_wrapper.patch +sunrpc-return-true-false-not-1-0-from-bool-functions.patch +nfsd-finish-converting-the-nfsv2-getacl-result-encod.patch +nfsd-don-t-call-nfsd_file_put-from-client-states-seq.patch +genirq-irqdesc-don-t-try-to-remove-non-existing-sysf.patch +cpufreq-amd_freq_sensitivity-add-missing-pci_dev_put.patch +libfs-add-define_simple_attribute_signed-for-signed-.patch +lib-notifier-error-inject-fix-error-when-writing-err.patch +debugfs-fix-error-when-writing-negative-value-to-ato.patch +rapidio-fix-possible-name-leaks-when-rio_add_device-.patch +rapidio-rio-fix-possible-name-leak-in-rio_register_m.patch +clocksource-drivers-sh_cmt-access-registers-accordin.patch +mips-ralink-mt7621-define-mt7621_sysc_base-with-__io.patch +mips-ralink-mt7621-soc-queries-and-tests-as-function.patch +mips-ralink-mt7621-do-not-use-kzalloc-too-early.patch +futex-move-to-kernel-futex.patch +futex-resend-potentially-swallowed-owner-death-notif.patch +cpu-hotplug-make-target_store-a-nop-when-target-stat.patch +cpu-hotplug-do-not-bail-out-in-dying-starting-sectio.patch +clocksource-drivers-timer-ti-dm-fix-missing-clk_disa.patch +acpica-fix-use-after-free-in-acpi_ut_copy_ipackage_t.patch +uprobes-x86-allow-to-probe-a-nop-instruction-with-0x.patch +x86-xen-fix-memory-leak-in-xen_smp_intr_init-_pv.patch +x86-xen-fix-memory-leak-in-xen_init_lock_cpu.patch +xen-privcmd-fix-a-possible-warning-in-privcmd_ioctl_.patch +pm-runtime-do-not-call-__rpm_callback-from-rpm_idle.patch +platform-chrome-cros_ec_typec-cleanup-switch-handle-.patch +platform-chrome-cros_ec_typec-zero-out-stale-pointer.patch +platform-x86-mxm-wmi-fix-memleak-in-mxm_wmi_call_mx-.patch +platform-x86-intel_scu_ipc-fix-possible-name-leak-in.patch +mips-bcm63xx-add-check-for-null-for-clk-in-clk_enabl.patch +mips-octeon-warn-only-once-if-deprecated-link-status.patch +lockd-set-other-missing-fields-when-unlocking-files.patch +fs-sysv-fix-sysv_nblocks-returns-wrong-value.patch +rapidio-fix-possible-uaf-when-kfifo_alloc-fails.patch +eventfd-change-int-to-__u64-in-eventfd_signal-ifndef.patch +relay-fix-type-mismatch-when-allocating-memory-in-re.patch +hfs-fix-oob-write-in-hfs_asc2mac.patch +rapidio-devices-fix-missing-put_device-in-mport_cdev.patch +platform-mellanox-mlxbf-pmc-fix-event-typo.patch +wifi-ath9k-hif_usb-fix-memory-leak-of-urbs-in-ath9k_.patch +wifi-ath9k-hif_usb-fix-use-after-free-in-ath9k_hif_u.patch +wifi-rtl8xxxu-fix-reading-the-vendor-of-combo-chips.patch +drm-bridge-adv7533-remove-dynamic-lane-switching-fro.patch +libbpf-fix-use-after-free-in-btf_dump_name_dups.patch +libbpf-fix-null-pointer-dereference-in-find_prog_by_.patch +ata-libata-move-ata_-port-link-dev-_dbg-to-standard-.patch +ata-add-use-ata_taskfile-error-status-fields.patch +ata-libata-fix-ncq-autosense-logic.patch +ipmi-kcs-poll-obf-briefly-to-reduce-obe-latency.patch +drm-amdgpu-powerplay-psm-fix-memory-leak-in-power-st.patch +powerpc-dts-t208x-mark-mac1-and-mac2-as-10g.patch +media-v4l2-ctrls-fix-off-by-one-error-in-integer-men.patch +media-coda-jpeg-add-check-for-kmalloc.patch +media-adv748x-afe-select-input-port-when-initializin.patch +media-i2c-ad5820-fix-error-path.patch +venus-pm_helpers-fix-error-check-in-vcodec_domains_g.patch +soreuseport-fix-socket-selection-for-so_incoming_cpu.patch +media-exynos4-is-don-t-rely-on-the-v4l2_async_subdev.patch +libbpf-btf-dedup-identical-struct-test-needs-check-f.patch +can-kvaser_usb-do-not-increase-tx-statistics-when-se.patch +can-kvaser_usb-kvaser_usb_leaf-get-capabilities-from.patch +can-kvaser_usb-kvaser_usb_leaf-rename-leaf-usbcan-_c.patch +can-kvaser_usb-kvaser_usb_leaf-handle-cmd_error_even.patch +can-kvaser_usb_leaf-set-warning-state-even-without-b.patch +can-kvaser_usb-make-use-of-units.h-in-assignment-of-.patch +can-kvaser_usb_leaf-fix-improved-state-not-being-rep.patch +can-kvaser_usb_leaf-fix-wrong-can-state-after-stoppi.patch +can-kvaser_usb_leaf-fix-bogus-restart-events.patch +can-kvaser_usb-add-struct-kvaser_usb_busparams.patch +can-kvaser_usb-compare-requested-bittiming-parameter.patch +drm-rockchip-lvds-fix-pm-usage-counter-unbalance-in-.patch +clk-renesas-r9a06g032-repair-grave-increment-error.patch +spi-update-reference-to-struct-spi_controller.patch +drm-panel-panel-sitronix-st7701-remove-panel-on-dsi-.patch +ima-handle-estale-returned-by-ima_filter_rule_match.patch +drm-msm-hdmi-drop-unused-gpio-support.patch +drm-msm-hdmi-use-devres-helper-for-runtime-pm-manage.patch +bpf-fix-slot-type-check-in-check_stack_write_var_off.patch +media-vivid-fix-compose-size-exceed-boundary.patch +media-platform-exynos4-is-fix-return-value-check-in-.patch +bpf-propagate-precision-in-alu-alu64-operations.patch +bpf-check-the-other-end-of-slot_type-for-stack_spill.patch +bpf-propagate-precision-across-all-frames-not-just-t.patch +clk-qcom-gcc-sm8250-use-retention-mode-for-usb-gdscs.patch +mtd-fix-device-name-leak-when-register-device-failed.patch +input-joystick-fix-kconfig-warning-for-joystick_adc.patch +wifi-rsi-fix-handling-of-802.3-eapol-frames-sent-via.patch +media-camss-clean-up-received-buffers-on-failed-star.patch +net-proc-provide-proc_fs-n-fallback-for-proc_create_.patch +rxrpc-fix-ack.buffersize-to-be-0-when-generating-an-.patch +bfq-fix-waker_bfqq-inconsistency-crash.patch +drm-radeon-add-the-missed-acpi_put_table-to-fix-memo.patch +drm-mediatek-modify-dpi-power-on-off-sequence.patch +asoc-pxa-fix-null-pointer-dereference-in-filter.patch +libbpf-fix-uninitialized-warning-in-btf_dump_dump_ty.patch +nvmet-only-allocate-a-single-slab-for-bvecs.patch +regulator-core-fix-unbalanced-of-node-refcount-in-re.patch +amdgpu-pm-prevent-array-underflow-in-vega20_odn_edit.patch +nvme-return-err-on-nvme_init_non_mdts_limits-fail.patch +regulator-qcom-rpmh-fix-pmr735a-s3-regulator-spec.patch +drm-fourcc-add-packed-10bit-yuv-4-2-0-format.patch +drm-fourcc-fix-vsub-hsub-for-q410-and-q401.patch +integrity-fix-memory-leakage-in-keyring-allocation-e.patch +ima-fix-misuse-of-dereference-of-pointer-in-template.patch +block-clear-slave_dir-when-dropping-the-main-slave_d.patch +wifi-ath10k-fix-return-value-in-ath10k_pci_init.patch +drm-msm-a6xx-fix-speed-bin-detection-vs-probe-defer.patch +mtd-lpddr2_nvm-fix-possible-null-ptr-deref.patch +input-elants_i2c-properly-handle-the-reset-gpio-when.patch +media-vidtv-fix-use-after-free-in-vidtv_bridge_dvb_i.patch +media-solo6x10-fix-possible-memory-leak-in-solo_sysf.patch +media-platform-exynos4-is-fix-error-handling-in-fimc.patch +media-videobuf-dma-contig-use-dma_mmap_coherent.patch +inet-add-read_once-sk-sk_bound_dev_if-in-inet_csk_bi.patch +mtd-spi-nor-hide-jedec_id-sysfs-attribute-if-not-pre.patch +mtd-spi-nor-fix-the-number-of-bytes-for-the-dummy-cy.patch +bpf-move-skb-len-0-checks-into-__bpf_redirect.patch +hid-hid-sensor-custom-set-fixed-size-for-custom-attr.patch +pinctrl-k210-call-of_node_put.patch +alsa-pcm-fix-undefined-behavior-in-bit-shift-for-snd.patch +alsa-seq-fix-undefined-behavior-in-bit-shift-for-snd.patch +regulator-core-use-kfree_const-to-free-space-conditi.patch +clk-rockchip-fix-memory-leak-in-rockchip_clk_registe.patch +drm-amdgpu-fix-pci-device-refcount-leak.patch +bonding-fix-link-recovery-in-mode-2-when-updelay-is-.patch +mtd-maps-pxa2xx-flash-fix-memory-leak-in-probe.patch +drbd-remove-call-to-memset-before-free-device-resour.patch +drbd-destroy-workqueue-when-drbd-device-was-freed.patch +asoc-qcom-add-checks-for-devm_kcalloc.patch +media-vimc-fix-wrong-function-called-when-vimc_init-.patch +media-imon-fix-a-race-condition-in-send_packet.patch +clk-imx8mn-rename-vpu_pll-to-m7_alt_pll.patch +clk-imx-replace-osc_hdmi-with-dummy.patch +clk-imx8mn-fix-imx8mn_sai2_sels-clocks-list.patch +clk-imx8mn-fix-imx8mn_enet_phy_sels-clocks-list.patch +pinctrl-pinconf-generic-add-missing-of_node_put.patch +media-dvb-core-fix-ignored-return-value-in-dvb_regis.patch +media-dvb-usb-az6027-fix-null-ptr-deref-in-az6027_i2.patch +media-s5p-mfc-add-variant-data-for-mfc-v7-hardware-f.patch +drm-tegra-add-missing-clk_disable_unprepare-in-tegra.patch +asoc-dt-bindings-wcd9335-fix-reset-line-polarity-in-.patch +asoc-mediatek-mtk-btcvsd-add-checks-for-write-and-re.patch +nfsv4.2-clear-fattr4_word2_security_label-when-done-.patch +nfsv4.2-fix-a-memory-stomp-in-decode_attr_security_l.patch +nfsv4.2-fix-initialisation-of-struct-nfs4_label.patch +nfsv4-fix-a-credential-leak-in-_nfs4_discover_trunki.patch +nfsv4-fix-a-deadlock-between-nfs4_open_recover_helpe.patch +nfs-fix-an-oops-in-nfs_d_automount.patch +alsa-asihpi-fix-missing-pci_disable_device.patch +wifi-iwlwifi-mvm-fix-double-free-on-tx-path.patch +asoc-mediatek-mt8173-fix-debugfs-registration-for-co.patch +asoc-mediatek-mt8173-enable-irq-when-pdata-is-ready.patch +drm-amd-pm-smu11-baco-is-supported-when-it-s-in-baco.patch +drm-radeon-fix-pci-device-refcount-leak-in-radeon_at.patch +drm-amdgpu-fix-pci-device-refcount-leak-in-amdgpu_at.patch +drm-amdkfd-fix-memory-leakage.patch +asoc-pcm512x-fix-pm-disable-depth-imbalance-in-pcm51.patch +netfilter-conntrack-set-icmpv6-redirects-as-related.patch +input-wistron_btns-disable-on-uml.patch +bpf-sockmap-fix-repeated-calls-to-sock_put-when-msg-.patch +bpf-sockmap-fix-missing-bpf_f_ingress-flag-when-usin.patch +bpf-sockmap-fix-data-loss-caused-by-using-apply_byte.patch +bonding-uninitialized-variable-in-bond_miimon_inspec.patch +spi-spidev-mask-spi_cs_high-in-spi_ioc_rd_mode.patch +wifi-mac80211-fix-memory-leak-in-ieee80211_if_add.patch +wifi-cfg80211-fix-not-unregister-reg_pdev-when-load_.patch +mt76-stop-the-radar-detector-after-leaving-dfs-chann.patch +wifi-mt76-mt7921-fix-reporting-of-tx-aggr-histogram.patch +wifi-mt76-fix-coverity-overrun-call-in-mt76_get_txpo.patch +regulator-core-fix-module-refcount-leak-in-set_suppl.patch +clk-qcom-lpass-sc7180-fix-pm_runtime-usage.patch +clk-qcom-clk-krait-fix-wrong-div2-functions.patch +hsr-add-a-rcu-read-lock-to-hsr_forward_skb.patch +hsr-avoid-double-remove-of-a-node.patch +hsr-disable-netpoll.patch +hsr-synchronize-sending-frames-to-have-always-increm.patch +hsr-synchronize-sequence-number-updates.patch +configfs-fix-possible-memory-leak-in-configfs_create.patch +regulator-core-fix-resource-leak-in-regulator_regist.patch +hwmon-jc42-convert-register-access-and-caching-to-re.patch +hwmon-jc42-restore-the-min-max-critical-temperatures.patch +bpf-sockmap-fix-race-in-sock_map_free.patch +alsa-pcm-set-missing-stop_operating-flag-at-undoing-.patch +media-saa7164-fix-missing-pci_disable_device.patch +alsa-mts64-fix-possible-null-ptr-defer-in-snd_mts64_.patch +xprtrdma-fix-regbuf-data-not-freed-in-rpcrdma_req_cr.patch +sunrpc-fix-missing-release-socket-in-rpc_sockname.patch +nfsv4.x-fail-client-initialisation-if-state-manager-.patch +riscv-bpf-emit-fixed-length-instructions-for-bpf_pse.patch +mmc-alcor-fix-return-value-check-of-mmc_add_host.patch +mmc-moxart-fix-return-value-check-of-mmc_add_host.patch +mmc-mxcmmc-fix-return-value-check-of-mmc_add_host.patch +mmc-pxamci-fix-return-value-check-of-mmc_add_host.patch +mmc-rtsx_pci-fix-return-value-check-of-mmc_add_host.patch +mmc-rtsx_usb_sdmmc-fix-return-value-check-of-mmc_add.patch +mmc-toshsd-fix-return-value-check-of-mmc_add_host.patch +mmc-vub300-fix-return-value-check-of-mmc_add_host.patch +mmc-wmt-sdmmc-fix-return-value-check-of-mmc_add_host.patch +mmc-atmel-mci-fix-return-value-check-of-mmc_add_host.patch +mmc-omap_hsmmc-fix-return-value-check-of-mmc_add_hos.patch +mmc-meson-gx-fix-return-value-check-of-mmc_add_host.patch +mmc-via-sdmmc-fix-return-value-check-of-mmc_add_host.patch +mmc-wbsd-fix-return-value-check-of-mmc_add_host.patch +mmc-mmci-fix-return-value-check-of-mmc_add_host.patch +mmc-renesas_sdhi-alway-populate-scc-pointer.patch +memstick-ms_block-add-error-handling-support-for-add.patch +memstick-ms_block-add-check-for-alloc_ordered_workqu.patch +mmc-core-normalize-the-error-handling-branch-in-sd_r.patch +regulator-qcom-labibb-fix-missing-of_node_put-in-qco.patch +media-c8sectpfe-add-of_node_put-when-breaking-out-of.patch +media-coda-add-check-for-dcoda_iram_alloc.patch +media-coda-add-check-for-kmalloc.patch +clk-samsung-fix-memory-leak-in-_samsung_clk_register.patch +spi-spi-gpio-don-t-set-mosi-as-an-input-if-not-3wire.patch +wifi-rtl8xxxu-add-__packed-to-struct-rtl8723bu_c2h.patch +wifi-rtl8xxxu-fix-the-channel-width-reporting.patch +wifi-brcmfmac-fix-error-return-code-in-brcmf_sdio_do.patch +blktrace-fix-output-non-blktrace-event-when-blk_clas.patch +bpf-do-not-zero-extend-kfunc-return-values.patch +clk-socfpga-fix-memory-leak-in-socfpga_gate_init.patch +net-vmw_vsock-vmci-check-memcpy_from_msg.patch +net-defxx-fix-missing-err-handling-in-dfx_init.patch +net-stmmac-selftests-fix-potential-memleak-in-stmmac.patch +net-stmmac-fix-possible-memory-leak-in-stmmac_dvr_pr.patch +drivers-net-qlcnic-fix-potential-memory-leak-in-qlcn.patch +of-overlay-fix-null-pointer-dereferencing-in-find_du.patch +ethernet-s2io-don-t-call-dev_kfree_skb-under-spin_lo.patch +net-farsync-fix-kmemleak-when-rmmods-farsync.patch +net-tunnel-wait-until-all-sk_user_data-reader-finish.patch +net-apple-mace-don-t-call-dev_kfree_skb-under-spin_l.patch +net-apple-bmac-don-t-call-dev_kfree_skb-under-spin_l.patch +net-emaclite-don-t-call-dev_kfree_skb-under-spin_loc.patch +net-ethernet-dnet-don-t-call-dev_kfree_skb-under-spi.patch +hamradio-don-t-call-dev_kfree_skb-under-spin_lock_ir.patch +net-amd-lance-don-t-call-dev_kfree_skb-under-spin_lo.patch +af_unix-call-proto_unregister-in-the-error-path-in-a.patch +net-amd-xgbe-fix-logic-around-active-and-passive-cab.patch +net-amd-xgbe-check-only-the-minimum-speed-for-active.patch +can-tcan4x5x-remove-invalid-write-in-clear_interrupt.patch +can-m_can-call-the-ram-init-directly-from-m_can_chip.patch +can-tcan4x5x-fix-use-of-register-error-status-mask.patch +net-lan9303-fix-read-error-execution-path.patch +ntb_netdev-use-dev_kfree_skb_any-in-interrupt-contex.patch +sctp-sysctl-make-extra-pointers-netns-aware.patch +bluetooth-mgmt-fix-error-report-for-add_ext_adv_para.patch +bluetooth-btintel-fix-missing-free-skb-in-btintel_se.patch +bluetooth-btusb-don-t-call-kfree_skb-under-spin_lock.patch +bluetooth-hci_qca-don-t-call-kfree_skb-under-spin_lo.patch +bluetooth-hci_ll-don-t-call-kfree_skb-under-spin_loc.patch +bluetooth-hci_h5-don-t-call-kfree_skb-under-spin_loc.patch +bluetooth-hci_bcsp-don-t-call-kfree_skb-under-spin_l.patch +bluetooth-hci_core-don-t-call-kfree_skb-under-spin_l.patch +bluetooth-rfcomm-don-t-call-kfree_skb-under-spin_loc.patch +stmmac-fix-potential-division-by-0.patch +i40e-fix-the-inability-to-attach-xdp-program-on-down.patch +net-dsa-tag_8021q-avoid-leaking-ctx-on-dsa_tag_8021q.patch +apparmor-fix-a-memleak-in-multi_transaction_new.patch +apparmor-fix-lockdep-warning-when-removing-a-namespa.patch +apparmor-fix-abi-check-to-include-v8-abi.patch +crypto-hisilicon-qm-fix-missing-destroy-qp_idr.patch +crypto-sun8i-ss-use-dma_addr-instead-u32.patch +crypto-nitrox-avoid-double-free-on-error-path-in-nit.patch +scsi-core-fix-a-race-between-scsi_done-and-scsi_time.patch +apparmor-use-pointer-to-struct-aa_label-for-lbs_cred.patch +pci-dwc-fix-n_fts-array-overrun.patch +rdma-core-fix-order-of-nldev_exit-call.patch +pci-pci-epf-test-register-notifier-if-only-core_init.patch +f2fs-fix-the-race-condition-of-resize-flag-between-r.patch +crypto-rockchip-do-not-do-custom-power-management.patch +crypto-rockchip-do-not-store-mode-globally.patch +crypto-rockchip-add-fallback-for-cipher.patch +crypto-rockchip-add-fallback-for-ahash.patch +crypto-rockchip-better-handle-cipher-key.patch +crypto-rockchip-remove-non-aligned-handling.patch +crypto-rockchip-rework-by-using-crypto_engine.patch +apparmor-fix-memleak-in-alloc_ns.patch +f2fs-fix-to-invalidate-dcc-f2fs_issue_discard-in-err.patch +f2fs-fix-normal-discard-process.patch +f2fs-fix-to-destroy-sbi-post_read_wq-in-error-path-o.patch +rdma-irdma-report-the-correct-link-speed.patch +scsi-qla2xxx-fix-set-but-not-used-variable-warnings.patch +rdma-siw-fix-immediate-work-request-flush-to-complet.patch +ib-mad-don-t-call-to-function-that-might-sleep-while.patch +pci-vmd-disable-msi-remapping-after-suspend.patch +rdma-restrack-release-mr-restrack-when-delete.patch +rdma-core-make-sure-ib_port-is-valid-when-access-sys.patch +rdma-nldev-return-eagain-if-the-cm_id-isn-t-from-exp.patch +rdma-siw-set-defined-status-for-work-completion-with.patch +scsi-scsi_debug-fix-a-warning-in-resp_write_scat.patch +crypto-ccree-remove-debugfs-when-platform_driver_reg.patch +crypto-cryptd-use-request-context-instead-of-stack-f.patch +crypto-hisilicon-qm-add-missing-pci_dev_put-in-q_num.patch +rdma-hns-repacing-dseg_len-by-macros-in-fill_ext_sge.patch +rdma-hns-fix-ext_sge-num-error-when-post-send.patch +pci-check-for-alloc-failure-in-pci_request_irq.patch +rdma-hfi-decrease-pci-device-reference-count-in-erro.patch +crypto-ccree-make-cc_debugfs_global_fini-available-f.patch +rdma-hns-fix-memory-leak-in-hns_roce_alloc_mr.patch +rdma-rxe-fix-null-ptr-deref-in-rxe_qp_do_cleanup-whe.patch +dt-bindings-imx6q-pcie-fix-clock-names-for-imx6sx-an.patch +dt-bindings-visconti-pcie-fix-interrupts-array-max-c.patch +scsi-hpsa-fix-possible-memory-leak-in-hpsa_init_one.patch +crypto-tcrypt-fix-multibuffer-skcipher-speed-test-me.patch +padata-always-leave-bhs-disabled-when-running-parall.patch +padata-fix-list-iterator-in-padata_do_serial.patch +scsi-mpt3sas-fix-possible-resource-leaks-in-mpt3sas_.patch +scsi-hpsa-fix-error-handling-in-hpsa_add_sas_host.patch +scsi-hpsa-fix-possible-memory-leak-in-hpsa_add_sas_d.patch +scsi-efct-fix-possible-memleak-in-efct_device_init.patch +scsi-scsi_debug-fix-a-warning-in-resp_verify.patch +scsi-scsi_debug-fix-a-warning-in-resp_report_zones.patch +scsi-fcoe-fix-possible-name-leak-when-device_registe.patch +scsi-scsi_debug-fix-possible-name-leak-in-sdebug_add.patch +scsi-ipr-fix-warning-in-ipr_init.patch +scsi-fcoe-fix-transport-not-deattached-when-fcoe_if_.patch +scsi-snic-fix-possible-uaf-in-snic_tgt_create.patch +rdma-nldev-add-checks-for-nla_nest_start-in-fill_sta.patch +f2fs-avoid-victim-selection-from-previous-victim-sec.patch +rdma-nldev-fix-failure-to-send-large-messages.patch +crypto-amlogic-remove-kcalloc-without-check.patch +crypto-omap-sham-use-pm_runtime_resume_and_get-in-om.patch +riscv-mm-add-arch-hook-arch_clear_hugepage_flags.patch +rdma-hfi1-fix-error-return-code-in-parse_platform_co.patch +rdma-srp-fix-error-return-code-in-srp_parse_options.patch +pci-mt7621-rename-mt7621_pci_-to-mt7621_pcie_.patch +pci-mt7621-add-sentinel-to-quirks-table.patch +orangefs-fix-sysfs-not-cleanup-when-dev-init-failed.patch +rdma-hns-fix-ah-attr-queried-by-query_qp.patch +rdma-hns-fix-pbl-page-mtr-find.patch +rdma-hns-fix-page-size-cap-from-firmware.patch +rdma-hns-fix-error-code-of-cmd.patch +crypto-img-hash-fix-variable-dereferenced-before-che.patch +hwrng-amd-fix-pci-device-refcount-leak.patch +hwrng-geode-fix-pci-device-refcount-leak.patch +ib-ipoib-fix-queue-count-inconsistency-for-pkey-chil.patch +risc-v-align-the-shadow-stack.patch +drivers-dio-fix-possible-memory-leak-in-dio_init.patch +serial-tegra-read-dma-status-before-terminating.patch +serial-8250_bcm7271-fix-error-handling-in-brcmuart_i.patch +class-fix-possible-memory-leak-in-__class_register.patch +vfio-platform-do-not-pass-return-buffer-to-acpi-_rst.patch +uio-uio_dmem_genirq-fix-missing-unlock-in-irq-config.patch +uio-uio_dmem_genirq-fix-deadlock-between-irq-config-.patch +usb-fotg210-udc-fix-ages-old-endianness-issues.patch +staging-vme_user-fix-possible-uaf-in-tsi148_dma_list.patch +usb-typec-check-for-ops-exit-instead-of-ops-enter-in.patch +usb-typec-tcpci-fix-of-node-refcount-leak-in-tcpci_r.patch +usb-typec-tipd-cleanup-resources-if-devm_tps6598_psy.patch +usb-typec-tipd-fix-spurious-fwnode_handle_put-in-err.patch +extcon-usbc-tusb320-add-support-for-mode-setting-and.patch +extcon-usbc-tusb320-add-support-for-tusb320l.patch +usb-typec-factor-out-non-pd-fwnode-properties.patch +extcon-usbc-tusb320-factor-out-extcon-into-dedicated.patch +extcon-usbc-tusb320-add-usb-type-c-support.patch +extcon-usbc-tusb320-update-state-on-probe-even-if-no.patch +serial-amba-pl011-avoid-sbsa-uart-accessing-dmacr-re.patch +serial-pl011-do-not-clear-rx-fifo-rx-interrupt-in-un.patch +serial-stm32-move-dma_request_chan-before-clk_prepar.patch +serial-pch-fix-pci-device-refcount-leak-in-pch_reque.patch +tty-serial-clean-up-stop-tx-part-in-altera_uart_tx_c.patch +tty-serial-altera_uart_-r-t-x_chars-need-only-uart_p.patch +serial-altera_uart-fix-locking-in-polling-mode.patch +serial-sunsab-fix-error-handling-in-sunsab_init.patch +test_firmware-fix-memory-leak-in-test_firmware_init.patch +misc-ocxl-fix-possible-name-leak-in-ocxl_file_regist.patch +ocxl-fix-pci-device-refcount-leak-when-calling-get_f.patch +misc-tifm-fix-possible-memory-leak-in-tifm_7xx1_swit.patch +misc-sgi-gru-fix-use-after-free-error-in-gru_set_con.patch +firmware-raspberrypi-fix-possible-memory-leak-in-rpi.patch +cxl-fix-possible-null-ptr-deref-in-cxl_guest_init_af.patch +cxl-fix-possible-null-ptr-deref-in-cxl_pci_init_afu-.patch +iio-temperature-ltc2983-make-bulk-write-buffer-dma-s.patch +iio-adis-handle-devices-that-cannot-unmask-the-drdy-.patch +iio-adis-stylistic-changes.patch +iio-imu-adis-move-exports-into-iio_adislib-namespace.patch +iio-adis-add-__adis_enable_irq-implementation.patch +counter-stm32-lptimer-cnt-fix-the-check-on-arr-and-c.patch +coresight-trbe-remove-cpuhp-instance-node-before-rem.patch +usb-roles-fix-of-node-refcount-leak-in-usb_role_swit.patch +usb-gadget-f_hid-fix-f_hidg-lifetime-vs-cdev.patch +usb-gadget-f_hid-fix-refcount-leak-on-error-path.patch +drivers-mcb-fix-resource-leak-in-mcb_probe.patch +mcb-mcb-parse-fix-error-handing-in-chameleon_parse_g.patch +chardev-fix-error-handling-in-cdev_device_add.patch +i2c-pxa-pci-fix-missing-pci_disable_device-on-error-.patch +staging-rtl8192u-fix-use-after-free-in-ieee80211_rx.patch +staging-rtl8192e-fix-potential-use-after-free-in-rtl.patch +vme-fix-error-not-catched-in-fake_init.patch +gpiolib-get-rid-of-redundant-else.patch +gpiolib-cdev-fix-null-pointer-dereferences.patch +gpiolib-make-struct-comments-into-real-kernel-docs.patch +gpiolib-protect-the-gpio-device-against-being-droppe.patch +i2c-mux-reg-check-return-value-after-calling-platfor.patch +i2c-ismt-fix-an-out-of-bounds-bug-in-ismt_access.patch +usb-storage-add-check-for-kcalloc.patch +tracing-hist-fix-issue-of-losting-command-info-in-er.patch +ksmbd-fix-resource-leak-in-ksmbd_session_rpc_open.patch +samples-vfio-mdev-fix-missing-pci_disable_device-in-.patch +thermal-drivers-imx8mm_thermal-validate-temperature-.patch +thermal-drivers-qcom-temp-alarm-fix-inaccurate-warni.patch +thermal-drivers-qcom-lmh-fix-irq-handler-return-valu.patch +fbdev-ssd1307fb-drop-optional-dependency.patch +fbdev-pm2fb-fix-missing-pci_disable_device.patch +fbdev-via-fix-error-in-via_core_init.patch +fbdev-vermilion-decrease-reference-count-in-error-pa.patch +fbdev-ep93xx-fb-add-missing-clk_disable_unprepare-in.patch +fbdev-geode-don-t-build-on-uml.patch +fbdev-uvesafb-don-t-build-on-uml.patch +fbdev-uvesafb-fixes-an-error-handling-path-in-uvesaf.patch +hsi-omap_ssi_core-fix-unbalanced-pm_runtime_disable.patch +hsi-omap_ssi_core-fix-possible-memory-leak-in-ssi_pr.patch +power-supply-fix-residue-sysfs-file-in-error-handle-.patch +perf-trace-return-error-if-a-system-call-doesn-t-exi.patch +perf-trace-use-macro-raw_syscall_args_num-to-replace.patch +perf-trace-handle-failure-when-trace-point-folder-is.patch +perf-symbol-correction-while-adjusting-symbol.patch +power-supply-z2_battery-fix-possible-memleak-in-z2_b.patch +hsi-omap_ssi_core-fix-error-handling-in-ssi_init.patch +power-supply-ab8500-fix-error-handling-in-ab8500_cha.patch +power-supply-fix-null-pointer-dereferencing-in-power.patch +perf-stat-refactor-__run_perf_stat-common-code.patch +perf-stat-do-not-delay-the-workload-with-delay.patch +rdma-siw-fix-pointer-cast-warning.patch +fs-ntfs3-avoid-ubsan-error-on-true_sectors_per_clst.patch +overflow-implement-size_t-saturating-arithmetic-help.patch +fs-ntfs3-harden-against-integer-overflows.patch +iommu-sun50i-fix-reset-release.patch +iommu-sun50i-consider-all-fault-sources-for-reset.patch +iommu-sun50i-fix-r-w-permission-check.patch +iommu-sun50i-fix-flush-size.patch +iommu-rockchip-fix-permission-bits-in-page-table-ent.patch +phy-usb-s2-wol-wakeup_count-not-incremented-for-usb-.patch +include-uapi-linux-swab-fix-potentially-missing-__al.patch +pwm-tegra-improve-required-rate-calculation.patch +fs-ntfs3-fix-slab-out-of-bounds-read-in-ntfs_trim_fs.patch +dmaengine-idxd-fix-crc_val-field-for-completion-reco.patch +rtc-rtc-cmos-do-not-check-acpi_fadt_low_power_s0.patch +rtc-cmos-fix-event-handler-registration-ordering-iss.patch +rtc-cmos-fix-wake-alarm-breakage.patch +rtc-cmos-fix-build-on-non-acpi-platforms.patch +rtc-cmos-call-cmos_wake_setup-from-cmos_do_probe.patch +rtc-cmos-call-rtc_wake_setup-from-cmos_do_probe.patch +rtc-cmos-eliminate-forward-declarations-of-some-func.patch +rtc-cmos-rename-acpi-related-functions.patch +rtc-cmos-disable-acpi-rtc-event-on-removal.patch +rtc-snvs-allow-a-time-difference-on-clock-register-r.patch +rtc-pcf85063-fix-reading-alarm.patch +iommu-amd-fix-pci-device-refcount-leak-in-ppr_notifi.patch +iommu-fsl_pamu-fix-resource-leak-in-fsl_pamu_probe.patch +macintosh-fix-possible-memory-leak-in-macio_add_one_.patch +macintosh-macio-adb-check-the-return-value-of-iorema.patch +powerpc-52xx-fix-a-resource-leak-in-an-error-handlin.patch +cxl-fix-refcount-leak-in-cxl_calc_capp_routing.patch +powerpc-xmon-fix-wswitch-unreachable-warning-in-bpt_.patch +powerpc-xive-add-missing-iounmap-in-error-path-in-xi.patch +phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch +phy-qcom-qmp-combo-fix-runtime-suspend.patch +powerpc-perf-callchain-validate-kernel-stack-pointer.patch +powerpc-83xx-mpc832x_rdb-call-platform_device_put-in.patch +powerpc-hv-gpci-fix-hv_gpci-event-list.patch +selftests-powerpc-fix-resource-leaks.patch +iommu-sun50i-remove-iommu_domain_identity.patch +pwm-sifive-call-pwm_sifive_update_clock-while-mutex-.patch +pwm-mtk-disp-fix-the-parameters-calculated-by-the-en.patch +pwm-mediatek-always-use-bus-clock-for-pwm-on-mt7622.patch +remoteproc-sysmon-fix-memory-leak-in-qcom_add_sysmon.patch +remoteproc-qcom-q6v5-fix-potential-null-ptr-deref-in.patch +remoteproc-qcom_q6v5_pas-disable-wakeup-on-probe-fai.patch +remoteproc-qcom_q6v5_pas-detach-power-domains-on-rem.patch +remoteproc-qcom_q6v5_pas-fix-missing-of_node_put-in-.patch +remoteproc-qcom-q6v5-fix-missing-clk_disable_unprepa.patch +powerpc-eeh-drop-redundant-spinlock-initialization.patch +powerpc-pseries-eeh-use-correct-api-for-error-log-si.patch +mfd-bd957x-fix-kconfig-dependency-on-regmap_irq.patch +mfd-qcom_rpm-fix-an-error-handling-path-in-qcom_rpm_.patch +mfd-pm8008-remove-driver-data-structure-pm8008_data.patch +mfd-pm8008-fix-return-value-check-in-pm8008_probe.patch +netfilter-flowtable-really-fix-nat-ipv6-offload.patch +rtc-st-lpc-add-missing-clk_disable_unprepare-in-st_r.patch +rtc-pic32-move-devm_rtc_allocate_device-earlier-in-p.patch +rtc-pcf85063-fix-pcf85063_clkout_control.patch +nfsd-under-nfsv4.1-fix-double-svc_xprt_put-on-rpc_cr.patch +net-macsec-fix-net-device-access-prior-to-holding-a-.patch +misdn-hfcsusb-don-t-call-dev_kfree_skb-kfree_skb-und.patch +misdn-hfcpci-don-t-call-dev_kfree_skb-kfree_skb-unde.patch +misdn-hfcmulti-don-t-call-dev_kfree_skb-kfree_skb-un.patch +block-bfq-fix-possible-uaf-for-bfqq-bic.patch +selftests-bpf-add-test-for-unstable-ct-lookup-api.patch +net-enetc-avoid-buffer-leaks-on-xdp_do_redirect-fail.patch +nfc-pn533-clear-nfc_target-before-being-used.patch +unix-fix-race-in-sock_seqpacket-s-unix_dgram_sendmsg.patch +r6040-fix-kmemleak-in-probe-and-remove.patch +blk-iocost-simplify-ioc_name.patch +igc-enhance-qbv-scheduling-by-using-first-flag-bit.patch +igc-use-strict-cycles-for-qbv-scheduling.patch +igc-add-checking-for-basetime-less-than-zero.patch +igc-allow-basetime-0-enrollment-for-qbv.patch +igc-recalculate-qbv-end_time-by-considering-cycle-ti.patch +igc-lift-taprio-schedule-restriction.patch +igc-set-qbv-start_time-and-end_time-to-end_time-if-n.patch +rtc-mxc_v2-add-missing-clk_disable_unprepare.patch +selftests-devlink-fix-the-fd-redirect-in-dummy_repor.patch +openvswitch-fix-flow-lookup-to-use-unmasked-key.patch +soc-mediatek-pm-domains-fix-the-power-glitch-issue.patch +arm64-dts-mt8183-fix-mali-gpu-clock.patch +skbuff-account-for-tail-adjustment-during-pull-opera.patch +mailbox-mpfs-read-the-system-controller-s-status.patch +mailbox-arm_mhuv2-fix-return-value-check-in-mhuv2_pr.patch +mailbox-zynq-ipi-fix-error-handling-while-device_reg.patch +net_sched-reject-tcf_em_simple-case-for-complex-emat.patch +rxrpc-fix-missing-unlock-in-rxrpc_do_sendmsg.patch +myri10ge-fix-an-error-handling-path-in-myri10ge_prob.patch +net-stream-purge-sk_error_queue-in-sk_stream_kill_qu.patch +hid-amd_sfh-add-missing-check-for-dma_alloc_coherent.patch +rcu-fix-__this_cpu_read-lockdep-warning-in-rcu_force.patch +arm64-make-is_ttbrx_addr-noinstr-safe.patch +video-hyperv_fb-avoid-taking-busy-spinlock-on-panic-.patch +x86-hyperv-remove-unregister-syscore-call-from-hyper.patch +binfmt_misc-fix-shift-out-of-bounds-in-check_special.patch +fs-jfs-fix-shift-out-of-bounds-in-dballocag.patch +udf-avoid-double-brelse-in-udf_rename.patch +jfs-fix-fortify-moan-in-symlink.patch +fs-jfs-fix-shift-out-of-bounds-in-dbdiscardag.patch +acpica-fix-error-code-path-in-acpi_ds_call_control_m.patch +nilfs2-fix-shift-out-of-bounds-overflow-in-nilfs_sb2.patch +nilfs2-fix-shift-out-of-bounds-due-to-too-large-expo.patch +acct-fix-potential-integer-overflow-in-encode_comp_t.patch +hfs-fix-oob-read-in-__hfs_brec_find.patch +drm-etnaviv-add-missing-quirks-for-gc300.patch +media-imx-jpeg-disable-useless-interrupt-to-avoid-ke.patch +brcmfmac-return-error-when-getting-invalid-max_flowr.patch +wifi-ath9k-verify-the-expected-usb_endpoints-are-pre.patch +wifi-ar5523-fix-use-after-free-on-ar5523_cmd-timed-o.patch +asoc-codecs-rt298-add-quirk-for-kbl-r-rvp-platform.patch +ipmi-fix-memleak-when-unload-ipmi-driver.patch +drm-amd-display-prevent-memory-leak.patch +revert-drm-amd-display-limit-max-dsc-target-bpp-for-.patch +qed-gcc13-use-u16-for-fid-to-be-big-enough.patch +bpf-make-sure-skb-len-0-when-redirecting-to-a-tunnel.patch +net-ethernet-ti-fix-return-type-of-netcp_ndo_start_x.patch +hamradio-baycom_epp-fix-return-type-of-baycom_send_p.patch +wifi-brcmfmac-fix-potential-shift-out-of-bounds-in-b.patch +igb-do-not-free-q_vector-unless-new-one-was-allocate.patch +drm-amdgpu-fix-type-of-second-parameter-in-trans_msg.patch +drm-amdgpu-fix-type-of-second-parameter-in-odn_edit_.patch +s390-ctcm-fix-return-type-of-ctc-mp-m_tx.patch +s390-netiucv-fix-return-type-of-netiucv_tx.patch +s390-lcs-fix-return-type-of-lcs_start_xmit.patch +drm-msm-use-drm_mode_copy.patch +drm-rockchip-use-drm_mode_copy.patch +drm-sti-use-drm_mode_copy.patch +drm-mediatek-fix-return-type-of-mtk_hdmi_bridge_mode.patch +drivers-md-md-bitmap-check-the-return-value-of-md_bi.patch +md-raid1-stop-mdx_raid1-thread-when-raid1-array-run-.patch +drm-amd-display-fix-array-index-out-of-bound-error-i.patch +net-add-atomic_long_t-to-net_device_stats-fields.patch +ipv6-sit-use-dev_stats_inc-to-avoid-data-races.patch +mrp-introduce-active-flags-to-prevent-uaf-when-appli.patch +ppp-associate-skb-with-a-device-at-tx.patch +bpf-prevent-decl_tag-from-being-referenced-in-func_p.patch +ethtool-avoiding-integer-overflow-in-ethtool_phys_id.patch +media-dvb-frontends-fix-leak-of-memory-fw.patch +media-dvbdev-adopts-refcnt-to-avoid-uaf.patch +media-dvb-usb-fix-memory-leak-in-dvb_usb_adapter_ini.patch +blk-mq-fix-possible-memleak-when-register-hctx-faile.patch +drm-amd-display-use-the-largest-vready_offset-in-pip.patch +libbpf-avoid-enum-forward-declarations-in-public-api.patch +regulator-core-fix-use_count-leakage-when-handling-b.patch +net-dpaa2-publish-mac-stringset-to-ethtool-s-even-if.patch +wifi-mt76-do-not-run-mt76u_status_worker-if-the-devi.patch +mmc-f-sdh30-add-quirks-for-broken-timeout-clock-capa.patch +mmc-renesas_sdhi-better-reset-from-hs400-mode.patch +media-si470x-fix-use-after-free-in-si470x_int_in_cal.patch +clk-st-fix-memory-leak-in-st_of_quadfs_setup.patch +crypto-hisilicon-hpre-fix-resource-leak-in-remove-pr.patch +scsi-lpfc-fix-hard-lockup-when-reading-the-rx_monito.patch +scsi-ufs-reduce-the-start-stop-unit-timeout.patch +scsi-elx-libefc-fix-second-parameter-type-in-state-c.patch +hugetlbfs-fix-null-ptr-deref-in-hugetlbfs_parse_para.patch +drm-fsl-dcu-fix-return-type-of-fsl_dcu_drm_connector.patch +drm-sti-fix-return-type-of-sti_-dvo-hda-hdmi-_connec.patch +orangefs-fix-kmemleak-in-orangefs_prepare_debugfs_he.patch +orangefs-fix-kmemleak-in-orangefs_-kernel-client-_de.patch +tools-include-add-_ret_ip_-and-math-definitions-to-k.patch +kvm-selftests-fix-build-regression-by-using-accessor.patch diff --git a/queue-5.15/skbuff-account-for-tail-adjustment-during-pull-opera.patch b/queue-5.15/skbuff-account-for-tail-adjustment-during-pull-opera.patch new file mode 100644 index 00000000000..974aed182aa --- /dev/null +++ b/queue-5.15/skbuff-account-for-tail-adjustment-during-pull-opera.patch @@ -0,0 +1,66 @@ +From facaa68f97da8d6be83443964d00f1207fe5aac5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Dec 2022 23:11:58 -0700 +Subject: skbuff: Account for tail adjustment during pull operations + +From: Subash Abhinov Kasiviswanathan + +[ Upstream commit 2d7afdcbc9d32423f177ee12b7c93783aea338fb ] + +Extending the tail can have some unexpected side effects if a program uses +a helper like BPF_FUNC_skb_pull_data to read partial content beyond the +head skb headlen when all the skbs in the gso frag_list are linear with no +head_frag - + + kernel BUG at net/core/skbuff.c:4219! + pc : skb_segment+0xcf4/0xd2c + lr : skb_segment+0x63c/0xd2c + Call trace: + skb_segment+0xcf4/0xd2c + __udp_gso_segment+0xa4/0x544 + udp4_ufo_fragment+0x184/0x1c0 + inet_gso_segment+0x16c/0x3a4 + skb_mac_gso_segment+0xd4/0x1b0 + __skb_gso_segment+0xcc/0x12c + udp_rcv_segment+0x54/0x16c + udp_queue_rcv_skb+0x78/0x144 + udp_unicast_rcv_skb+0x8c/0xa4 + __udp4_lib_rcv+0x490/0x68c + udp_rcv+0x20/0x30 + ip_protocol_deliver_rcu+0x1b0/0x33c + ip_local_deliver+0xd8/0x1f0 + ip_rcv+0x98/0x1a4 + deliver_ptype_list_skb+0x98/0x1ec + __netif_receive_skb_core+0x978/0xc60 + +Fix this by marking these skbs as GSO_DODGY so segmentation can handle +the tail updates accordingly. + +Fixes: 3dcbdb134f32 ("net: gso: Fix skb_segment splat when splitting gso_size mangled skb having linear-headed frag_list") +Signed-off-by: Sean Tranchetti +Signed-off-by: Subash Abhinov Kasiviswanathan +Reviewed-by: Alexander Duyck +Link: https://lore.kernel.org/r/1671084718-24796-1-git-send-email-quic_subashab@quicinc.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/skbuff.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/core/skbuff.c b/net/core/skbuff.c +index 6706bd3c8e9c..058ec2f17da6 100644 +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -2263,6 +2263,9 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta) + insp = list; + } else { + /* Eaten partially. */ ++ if (skb_is_gso(skb) && !list->head_frag && ++ skb_headlen(list)) ++ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + + if (skb_shared(list)) { + /* Sucks! We need to fork list. :-( */ +-- +2.35.1 + diff --git a/queue-5.15/soc-mediatek-pm-domains-fix-the-power-glitch-issue.patch b/queue-5.15/soc-mediatek-pm-domains-fix-the-power-glitch-issue.patch new file mode 100644 index 00000000000..18160f11094 --- /dev/null +++ b/queue-5.15/soc-mediatek-pm-domains-fix-the-power-glitch-issue.patch @@ -0,0 +1,44 @@ +From 125d7a0da448177604f2cf7638004a7805508d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Oct 2022 18:20:29 +0800 +Subject: soc: mediatek: pm-domains: Fix the power glitch issue + +From: Chun-Jie Chen + +[ Upstream commit dba8eb83af9dd757ef645b52200775e86883d858 ] + +Power reset maybe generate unexpected signal. In order to avoid +the glitch issue, we need to enable isolation first to guarantee the +stable signal when power reset is triggered. + +Fixes: 59b644b01cf4 ("soc: mediatek: Add MediaTek SCPSYS power domains") +Signed-off-by: Chun-Jie Chen +Signed-off-by: Allen-KH Cheng +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Miles Chen +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20221014102029.1162-1-allen-kh.cheng@mediatek.com +Signed-off-by: Matthias Brugger +Signed-off-by: Sasha Levin +--- + drivers/soc/mediatek/mtk-pm-domains.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c +index afd2fd74802d..52ecde8e446c 100644 +--- a/drivers/soc/mediatek/mtk-pm-domains.c ++++ b/drivers/soc/mediatek/mtk-pm-domains.c +@@ -272,9 +272,9 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) + clk_bulk_disable_unprepare(pd->num_subsys_clks, pd->subsys_clks); + + /* subsys power off */ +- regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT); + regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT); ++ regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT); + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT); + regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT); + +-- +2.35.1 + diff --git a/queue-5.15/soc-qcom-apr-add-check-for-idr_alloc-and-of_property.patch b/queue-5.15/soc-qcom-apr-add-check-for-idr_alloc-and-of_property.patch new file mode 100644 index 00000000000..a2d05a42be7 --- /dev/null +++ b/queue-5.15/soc-qcom-apr-add-check-for-idr_alloc-and-of_property.patch @@ -0,0 +1,64 @@ +From f2dda3611ab2a285b6b767f694bcdef1ea60530f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Nov 2022 09:44:03 +0800 +Subject: soc: qcom: apr: Add check for idr_alloc and + of_property_read_string_index + +From: Jiasheng Jiang + +[ Upstream commit 6d7860f5750d73da2fa1a1f6c9405058a593fa32 ] + +As idr_alloc() and of_property_read_string_index() can return negative +numbers, it should be better to check the return value and deal with +the exception. +Therefore, it should be better to use goto statement to stop and return +error. + +Fixes: 6adba21eb434 ("soc: qcom: Add APR bus driver") +Signed-off-by: Jiasheng Jiang +Reviewed-by: Bjorn Andersson +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221107014403.3606-1-jiasheng@iscas.ac.cn +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/apr.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c +index 5687653fabd5..173427bbf916 100644 +--- a/drivers/soc/qcom/apr.c ++++ b/drivers/soc/qcom/apr.c +@@ -310,11 +310,19 @@ static int apr_add_device(struct device *dev, struct device_node *np, + adev->dev.driver = NULL; + + spin_lock(&apr->svcs_lock); +- idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); ++ ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); + spin_unlock(&apr->svcs_lock); ++ if (ret < 0) { ++ dev_err(dev, "idr_alloc failed: %d\n", ret); ++ goto out; ++ } + +- of_property_read_string_index(np, "qcom,protection-domain", +- 1, &adev->service_path); ++ ret = of_property_read_string_index(np, "qcom,protection-domain", ++ 1, &adev->service_path); ++ if (ret < 0) { ++ dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); ++ goto out; ++ } + + dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); + +@@ -324,6 +332,7 @@ static int apr_add_device(struct device *dev, struct device_node *np, + put_device(&adev->dev); + } + ++out: + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.15/soc-qcom-apr-make-code-more-reuseable.patch b/queue-5.15/soc-qcom-apr-make-code-more-reuseable.patch new file mode 100644 index 00000000000..dc2d88d1255 --- /dev/null +++ b/queue-5.15/soc-qcom-apr-make-code-more-reuseable.patch @@ -0,0 +1,413 @@ +From 5376129d5521fb7cc06094e45ce42c58f9245bf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Sep 2021 14:55:40 +0100 +Subject: soc: qcom: apr: make code more reuseable + +From: Srinivas Kandagatla + +[ Upstream commit 99139b80c1b3d73026ed8be2de42c52e2976ab64 ] + +APR and other packet routers like GPR are pretty much same and +interact with other drivers in similar way. + +Ex: GPR ports can be considered as APR services, only difference +is they are allocated dynamically. + +Other difference is packet layout, which should not matter +with the apis abstracted. Apart from this the rest of the +functionality is pretty much identical across APR and GPR. + +Make the apr code more reusable by abstracting it service level, +rather than device level so that we do not need to write +new drivers for other new packet routers like GPR. + +This patch is in preparation to add GPR support to this driver. + +Signed-off-by: Srinivas Kandagatla +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20210927135559.738-4-srinivas.kandagatla@linaro.org +Stable-dep-of: 6d7860f5750d ("soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index") +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/apr.c | 129 +++++++++++++++++++++-------------- + include/linux/soc/qcom/apr.h | 12 +++- + 2 files changed, 90 insertions(+), 51 deletions(-) + +diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c +index 2e455d9e3d94..5687653fabd5 100644 +--- a/drivers/soc/qcom/apr.c ++++ b/drivers/soc/qcom/apr.c +@@ -15,13 +15,18 @@ + #include + #include + +-struct apr { ++enum { ++ PR_TYPE_APR = 0, ++}; ++ ++struct packet_router { + struct rpmsg_endpoint *ch; + struct device *dev; + spinlock_t svcs_lock; + spinlock_t rx_lock; + struct idr svcs_idr; + int dest_domain_id; ++ int type; + struct pdr_handle *pdr; + struct workqueue_struct *rxwq; + struct work_struct rx_work; +@@ -44,21 +49,21 @@ struct apr_rx_buf { + */ + int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt) + { +- struct apr *apr = dev_get_drvdata(adev->dev.parent); ++ struct packet_router *apr = dev_get_drvdata(adev->dev.parent); + struct apr_hdr *hdr; + unsigned long flags; + int ret; + +- spin_lock_irqsave(&adev->lock, flags); ++ spin_lock_irqsave(&adev->svc.lock, flags); + + hdr = &pkt->hdr; + hdr->src_domain = APR_DOMAIN_APPS; +- hdr->src_svc = adev->svc_id; ++ hdr->src_svc = adev->svc.id; + hdr->dest_domain = adev->domain_id; +- hdr->dest_svc = adev->svc_id; ++ hdr->dest_svc = adev->svc.id; + + ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); +- spin_unlock_irqrestore(&adev->lock, flags); ++ spin_unlock_irqrestore(&adev->svc.lock, flags); + + return ret ? ret : hdr->pkt_size; + } +@@ -74,7 +79,7 @@ static void apr_dev_release(struct device *dev) + static int apr_callback(struct rpmsg_device *rpdev, void *buf, + int len, void *priv, u32 addr) + { +- struct apr *apr = dev_get_drvdata(&rpdev->dev); ++ struct packet_router *apr = dev_get_drvdata(&rpdev->dev); + struct apr_rx_buf *abuf; + unsigned long flags; + +@@ -100,11 +105,11 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, + return 0; + } + +- +-static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) ++static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf) + { + uint16_t hdr_size, msg_type, ver, svc_id; +- struct apr_device *svc = NULL; ++ struct pkt_router_svc *svc; ++ struct apr_device *adev; + struct apr_driver *adrv = NULL; + struct apr_resp_pkt resp; + struct apr_hdr *hdr; +@@ -145,12 +150,15 @@ static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) + svc_id = hdr->dest_svc; + spin_lock_irqsave(&apr->svcs_lock, flags); + svc = idr_find(&apr->svcs_idr, svc_id); +- if (svc && svc->dev.driver) +- adrv = to_apr_driver(svc->dev.driver); ++ if (svc && svc->dev->driver) { ++ adev = svc_to_apr_device(svc); ++ adrv = to_apr_driver(adev->dev.driver); ++ } + spin_unlock_irqrestore(&apr->svcs_lock, flags); + +- if (!adrv) { +- dev_err(apr->dev, "APR: service is not registered\n"); ++ if (!adrv || !adev) { ++ dev_err(apr->dev, "APR: service is not registered (%d)\n", ++ svc_id); + return -EINVAL; + } + +@@ -164,20 +172,26 @@ static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) + if (resp.payload_size > 0) + resp.payload = buf + hdr_size; + +- adrv->callback(svc, &resp); ++ adrv->callback(adev, &resp); + + return 0; + } + + static void apr_rxwq(struct work_struct *work) + { +- struct apr *apr = container_of(work, struct apr, rx_work); ++ struct packet_router *apr = container_of(work, struct packet_router, rx_work); + struct apr_rx_buf *abuf, *b; + unsigned long flags; + + if (!list_empty(&apr->rx_list)) { + list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { +- apr_do_rx_callback(apr, abuf); ++ switch (apr->type) { ++ case PR_TYPE_APR: ++ apr_do_rx_callback(apr, abuf); ++ break; ++ default: ++ break; ++ } + spin_lock_irqsave(&apr->rx_lock, flags); + list_del(&abuf->node); + spin_unlock_irqrestore(&apr->rx_lock, flags); +@@ -201,7 +215,7 @@ static int apr_device_match(struct device *dev, struct device_driver *drv) + + while (id->domain_id != 0 || id->svc_id != 0) { + if (id->domain_id == adev->domain_id && +- id->svc_id == adev->svc_id) ++ id->svc_id == adev->svc.id) + return 1; + id++; + } +@@ -221,14 +235,14 @@ static void apr_device_remove(struct device *dev) + { + struct apr_device *adev = to_apr_device(dev); + struct apr_driver *adrv; +- struct apr *apr = dev_get_drvdata(adev->dev.parent); ++ struct packet_router *apr = dev_get_drvdata(adev->dev.parent); + + if (dev->driver) { + adrv = to_apr_driver(dev->driver); + if (adrv->remove) + adrv->remove(adev); + spin_lock(&apr->svcs_lock); +- idr_remove(&apr->svcs_idr, adev->svc_id); ++ idr_remove(&apr->svcs_idr, adev->svc.id); + spin_unlock(&apr->svcs_lock); + } + } +@@ -255,28 +269,39 @@ struct bus_type aprbus = { + EXPORT_SYMBOL_GPL(aprbus); + + static int apr_add_device(struct device *dev, struct device_node *np, +- const struct apr_device_id *id) ++ u32 svc_id, u32 domain_id) + { +- struct apr *apr = dev_get_drvdata(dev); ++ struct packet_router *apr = dev_get_drvdata(dev); + struct apr_device *adev = NULL; ++ struct pkt_router_svc *svc; + int ret; + + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + +- spin_lock_init(&adev->lock); ++ adev->svc_id = svc_id; ++ svc = &adev->svc; ++ ++ svc->id = svc_id; ++ svc->pr = apr; ++ svc->priv = adev; ++ svc->dev = dev; ++ spin_lock_init(&svc->lock); ++ ++ adev->domain_id = domain_id; + +- adev->svc_id = id->svc_id; +- adev->domain_id = id->domain_id; +- adev->version = id->svc_version; + if (np) + snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); +- else +- strscpy(adev->name, id->name, APR_NAME_SIZE); + +- dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, +- id->domain_id, id->svc_id); ++ switch (apr->type) { ++ case PR_TYPE_APR: ++ dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, ++ domain_id, svc_id); ++ break; ++ default: ++ break; ++ } + + adev->dev.bus = &aprbus; + adev->dev.parent = dev; +@@ -285,8 +310,7 @@ static int apr_add_device(struct device *dev, struct device_node *np, + adev->dev.driver = NULL; + + spin_lock(&apr->svcs_lock); +- idr_alloc(&apr->svcs_idr, adev, id->svc_id, +- id->svc_id + 1, GFP_ATOMIC); ++ idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); + spin_unlock(&apr->svcs_lock); + + of_property_read_string_index(np, "qcom,protection-domain", +@@ -306,7 +330,7 @@ static int apr_add_device(struct device *dev, struct device_node *np, + static int of_apr_add_pd_lookups(struct device *dev) + { + const char *service_name, *service_path; +- struct apr *apr = dev_get_drvdata(dev); ++ struct packet_router *apr = dev_get_drvdata(dev); + struct device_node *node; + struct pdr_service *pds; + int ret; +@@ -338,13 +362,14 @@ static int of_apr_add_pd_lookups(struct device *dev) + + static void of_register_apr_devices(struct device *dev, const char *svc_path) + { +- struct apr *apr = dev_get_drvdata(dev); ++ struct packet_router *apr = dev_get_drvdata(dev); + struct device_node *node; + const char *service_path; + int ret; + + for_each_child_of_node(dev->of_node, node) { +- struct apr_device_id id = { {0} }; ++ u32 svc_id; ++ u32 domain_id; + + /* + * This function is called with svc_path NULL during +@@ -374,13 +399,13 @@ static void of_register_apr_devices(struct device *dev, const char *svc_path) + continue; + } + +- if (of_property_read_u32(node, "reg", &id.svc_id)) ++ if (of_property_read_u32(node, "reg", &svc_id)) + continue; + +- id.domain_id = apr->dest_domain_id; ++ domain_id = apr->dest_domain_id; + +- if (apr_add_device(dev, node, &id)) +- dev_err(dev, "Failed to add apr %d svc\n", id.svc_id); ++ if (apr_add_device(dev, node, svc_id, domain_id)) ++ dev_err(dev, "Failed to add apr %d svc\n", svc_id); + } + } + +@@ -400,7 +425,7 @@ static int apr_remove_device(struct device *dev, void *svc_path) + + static void apr_pd_status(int state, char *svc_path, void *priv) + { +- struct apr *apr = (struct apr *)priv; ++ struct packet_router *apr = (struct packet_router *)priv; + + switch (state) { + case SERVREG_SERVICE_STATE_UP: +@@ -415,16 +440,20 @@ static void apr_pd_status(int state, char *svc_path, void *priv) + static int apr_probe(struct rpmsg_device *rpdev) + { + struct device *dev = &rpdev->dev; +- struct apr *apr; ++ struct packet_router *apr; + int ret; + + apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); + if (!apr) + return -ENOMEM; + +- ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id); ++ ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); ++ if (ret) /* try deprecated apr-domain property */ ++ ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", ++ &apr->dest_domain_id); ++ apr->type = PR_TYPE_APR; + if (ret) { +- dev_err(dev, "APR Domain ID not specified in DT\n"); ++ dev_err(dev, "Domain ID not specified in DT\n"); + return ret; + } + +@@ -467,7 +496,7 @@ static int apr_probe(struct rpmsg_device *rpdev) + + static void apr_remove(struct rpmsg_device *rpdev) + { +- struct apr *apr = dev_get_drvdata(&rpdev->dev); ++ struct packet_router *apr = dev_get_drvdata(&rpdev->dev); + + pdr_handle_release(apr->pdr); + device_for_each_child(&rpdev->dev, NULL, apr_remove_device); +@@ -504,20 +533,20 @@ void apr_driver_unregister(struct apr_driver *drv) + } + EXPORT_SYMBOL_GPL(apr_driver_unregister); + +-static const struct of_device_id apr_of_match[] = { ++static const struct of_device_id pkt_router_of_match[] = { + { .compatible = "qcom,apr"}, + { .compatible = "qcom,apr-v2"}, + {} + }; +-MODULE_DEVICE_TABLE(of, apr_of_match); ++MODULE_DEVICE_TABLE(of, pkt_router_of_match); + +-static struct rpmsg_driver apr_driver = { ++static struct rpmsg_driver packet_router_driver = { + .probe = apr_probe, + .remove = apr_remove, + .callback = apr_callback, + .drv = { + .name = "qcom,apr", +- .of_match_table = apr_of_match, ++ .of_match_table = pkt_router_of_match, + }, + }; + +@@ -527,7 +556,7 @@ static int __init apr_init(void) + + ret = bus_register(&aprbus); + if (!ret) +- ret = register_rpmsg_driver(&apr_driver); ++ ret = register_rpmsg_driver(&packet_router_driver); + else + bus_unregister(&aprbus); + +@@ -537,7 +566,7 @@ static int __init apr_init(void) + static void __exit apr_exit(void) + { + bus_unregister(&aprbus); +- unregister_rpmsg_driver(&apr_driver); ++ unregister_rpmsg_driver(&packet_router_driver); + } + + subsys_initcall(apr_init); +diff --git a/include/linux/soc/qcom/apr.h b/include/linux/soc/qcom/apr.h +index 137f9f2ac4c3..7bca213a3f83 100644 +--- a/include/linux/soc/qcom/apr.h ++++ b/include/linux/soc/qcom/apr.h +@@ -79,6 +79,15 @@ struct apr_resp_pkt { + #define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF) + #define APR_SVC_MINOR_VERSION(v) (v & 0xFF) + ++struct packet_router; ++struct pkt_router_svc { ++ struct device *dev; ++ struct packet_router *pr; ++ spinlock_t lock; ++ int id; ++ void *priv; ++}; ++ + struct apr_device { + struct device dev; + uint16_t svc_id; +@@ -86,11 +95,12 @@ struct apr_device { + uint32_t version; + char name[APR_NAME_SIZE]; + const char *service_path; +- spinlock_t lock; ++ struct pkt_router_svc svc; + struct list_head node; + }; + + #define to_apr_device(d) container_of(d, struct apr_device, dev) ++#define svc_to_apr_device(d) container_of(d, struct apr_device, svc) + + struct apr_driver { + int (*probe)(struct apr_device *sl); +-- +2.35.1 + diff --git a/queue-5.15/soc-qcom-llcc-make-irq-truly-optional.patch b/queue-5.15/soc-qcom-llcc-make-irq-truly-optional.patch new file mode 100644 index 00000000000..a424fc8bb27 --- /dev/null +++ b/queue-5.15/soc-qcom-llcc-make-irq-truly-optional.patch @@ -0,0 +1,40 @@ +From 3e5bd29d50ff7864dbd70d59873df9dc88c6f85e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 16:30:41 +0100 +Subject: soc: qcom: llcc: make irq truly optional + +From: Luca Weiss + +[ Upstream commit c882c899ead3545102a4d71b5fbe73b9e4bc2657 ] + +The function platform_get_irq prints an error message into the kernel +log when the irq isn't found. + +Since the interrupt is actually optional and not provided by some SoCs, +use platform_get_irq_optional which does not print an error message. + +Fixes: c081f3060fab ("soc: qcom: Add support to register LLCC EDAC driver") +Signed-off-by: Luca Weiss +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20221104153041.412020-1-luca.weiss@fairphone.com +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/llcc-qcom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c +index cabd8870316d..47d41804fdf6 100644 +--- a/drivers/soc/qcom/llcc-qcom.c ++++ b/drivers/soc/qcom/llcc-qcom.c +@@ -607,7 +607,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) + if (ret) + goto err; + +- drv_data->ecc_irq = platform_get_irq(pdev, 0); ++ drv_data->ecc_irq = platform_get_irq_optional(pdev, 0); + if (drv_data->ecc_irq >= 0) { + llcc_edac = platform_device_register_data(&pdev->dev, + "qcom_llcc_edac", -1, drv_data, +-- +2.35.1 + diff --git a/queue-5.15/soc-ti-knav_qmss_queue-fix-pm-disable-depth-imbalanc.patch b/queue-5.15/soc-ti-knav_qmss_queue-fix-pm-disable-depth-imbalanc.patch new file mode 100644 index 00000000000..2e5f0896ce9 --- /dev/null +++ b/queue-5.15/soc-ti-knav_qmss_queue-fix-pm-disable-depth-imbalanc.patch @@ -0,0 +1,38 @@ +From 312d7260c7723543f32137d4cd755af317565588 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 16:03:21 +0800 +Subject: soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in + knav_queue_probe + +From: Zhang Qilong + +[ Upstream commit e961c0f19450fd4a26bd043dd2979990bf12caf6 ] + +The pm_runtime_enable will increase power disable depth. Thus +a pairing decrement is needed on the error handling path to +keep it balanced according to context. + +Fixes: 41f93af900a2 ("soc: ti: add Keystone Navigator QMSS driver") +Signed-off-by: Zhang Qilong +Signed-off-by: Nishanth Menon +Link: https://lore.kernel.org/r/20221108080322.52268-2-zhangqilong3@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/knav_qmss_queue.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c +index de11f2b8db0f..52389859395c 100644 +--- a/drivers/soc/ti/knav_qmss_queue.c ++++ b/drivers/soc/ti/knav_qmss_queue.c +@@ -1787,6 +1787,7 @@ static int knav_queue_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) { ++ pm_runtime_disable(&pdev->dev); + dev_err(dev, "Failed to enable QMSS\n"); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/soc-ti-knav_qmss_queue-use-pm_runtime_resume_and_get.patch b/queue-5.15/soc-ti-knav_qmss_queue-use-pm_runtime_resume_and_get.patch new file mode 100644 index 00000000000..79d5d398638 --- /dev/null +++ b/queue-5.15/soc-ti-knav_qmss_queue-use-pm_runtime_resume_and_get.patch @@ -0,0 +1,41 @@ +From 9d6b44c945d8914b1886d2eeb95b211793b2aeb2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Apr 2022 06:29:55 +0000 +Subject: soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of + pm_runtime_get_sync + +From: Minghao Chi + +[ Upstream commit 12eeb74925da70eb39d90abead9de9793be3d4c8 ] + +Using pm_runtime_resume_and_get is more appropriate for simplifying +code. + +Reported-by: Zeal Robot +Signed-off-by: Minghao Chi +Signed-off-by: Nishanth Menon +Link: https://lore.kernel.org/r/20220418062955.2557949-1-chi.minghao@zte.com.cn +Stable-dep-of: e961c0f19450 ("soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe") +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/knav_qmss_queue.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c +index 920eca809084..de11f2b8db0f 100644 +--- a/drivers/soc/ti/knav_qmss_queue.c ++++ b/drivers/soc/ti/knav_qmss_queue.c +@@ -1785,9 +1785,8 @@ static int knav_queue_probe(struct platform_device *pdev) + INIT_LIST_HEAD(&kdev->pdsps); + + pm_runtime_enable(&pdev->dev); +- ret = pm_runtime_get_sync(&pdev->dev); ++ ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) { +- pm_runtime_put_noidle(&pdev->dev); + dev_err(dev, "Failed to enable QMSS\n"); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/soc-ti-smartreflex-fix-pm-disable-depth-imbalance-in.patch b/queue-5.15/soc-ti-smartreflex-fix-pm-disable-depth-imbalance-in.patch new file mode 100644 index 00000000000..7e35a9b3309 --- /dev/null +++ b/queue-5.15/soc-ti-smartreflex-fix-pm-disable-depth-imbalance-in.patch @@ -0,0 +1,37 @@ +From 2adcdb00cfade49ec016d577cf789a7f3ee53851 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 8 Nov 2022 16:03:22 +0800 +Subject: soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe + +From: Zhang Qilong + +[ Upstream commit 69460e68eb662064ab4188d4e129ff31c1f23ed9 ] + +The pm_runtime_enable will increase power disable depth. Thus +a pairing decrement is needed on the error handling path to +keep it balanced according to context. + +Fixes: 984aa6dbf4ca ("OMAP3: PM: Adding smartreflex driver support.") +Signed-off-by: Zhang Qilong +Signed-off-by: Nishanth Menon +Link: https://lore.kernel.org/r/20221108080322.52268-3-zhangqilong3@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/soc/ti/smartreflex.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c +index b5b2fa538d5c..4d15587324d4 100644 +--- a/drivers/soc/ti/smartreflex.c ++++ b/drivers/soc/ti/smartreflex.c +@@ -931,6 +931,7 @@ static int omap_sr_probe(struct platform_device *pdev) + err_debugfs: + debugfs_remove_recursive(sr_info->dbg_dir); + err_list_del: ++ pm_runtime_disable(&pdev->dev); + list_del(&sr_info->node); + clk_unprepare(sr_info->fck); + +-- +2.35.1 + diff --git a/queue-5.15/soreuseport-fix-socket-selection-for-so_incoming_cpu.patch b/queue-5.15/soreuseport-fix-socket-selection-for-so_incoming_cpu.patch new file mode 100644 index 00000000000..30d6b2b34d6 --- /dev/null +++ b/queue-5.15/soreuseport-fix-socket-selection-for-so_incoming_cpu.patch @@ -0,0 +1,301 @@ +From d57203a138514f357d5934ab468ec16bde6aba66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Oct 2022 13:44:34 -0700 +Subject: soreuseport: Fix socket selection for SO_INCOMING_CPU. + +From: Kuniyuki Iwashima + +[ Upstream commit b261eda84ec136240a9ca753389853a3a1bccca2 ] + +Kazuho Oku reported that setsockopt(SO_INCOMING_CPU) does not work +with setsockopt(SO_REUSEPORT) since v4.6. + +With the combination of SO_REUSEPORT and SO_INCOMING_CPU, we could +build a highly efficient server application. + +setsockopt(SO_INCOMING_CPU) associates a CPU with a TCP listener +or UDP socket, and then incoming packets processed on the CPU will +likely be distributed to the socket. Technically, a socket could +even receive packets handled on another CPU if no sockets in the +reuseport group have the same CPU receiving the flow. + +The logic exists in compute_score() so that a socket will get a higher +score if it has the same CPU with the flow. However, the score gets +ignored after the blamed two commits, which introduced a faster socket +selection algorithm for SO_REUSEPORT. + +This patch introduces a counter of sockets with SO_INCOMING_CPU in +a reuseport group to check if we should iterate all sockets to find +a proper one. We increment the counter when + + * calling listen() if the socket has SO_INCOMING_CPU and SO_REUSEPORT + + * enabling SO_INCOMING_CPU if the socket is in a reuseport group + +Also, we decrement it when + + * detaching a socket out of the group to apply SO_INCOMING_CPU to + migrated TCP requests + + * disabling SO_INCOMING_CPU if the socket is in a reuseport group + +When the counter reaches 0, we can get back to the O(1) selection +algorithm. + +The overall changes are negligible for the non-SO_INCOMING_CPU case, +and the only notable thing is that we have to update sk_incomnig_cpu +under reuseport_lock. Otherwise, the race prevents transitioning to +the O(n) algorithm and results in the wrong socket selection. + + cpu1 (setsockopt) cpu2 (listen) ++-----------------+ +-------------+ + +lock_sock(sk1) lock_sock(sk2) + +reuseport_update_incoming_cpu(sk1, val) +. +| /* set CPU as 0 */ +|- WRITE_ONCE(sk1->incoming_cpu, val) +| +| spin_lock_bh(&reuseport_lock) +| reuseport_grow(sk2, reuse) +| . +| |- more_socks_size = reuse->max_socks * 2U; +| |- if (more_socks_size > U16_MAX && +| | reuse->num_closed_socks) +| | . +| | |- RCU_INIT_POINTER(sk1->sk_reuseport_cb, NULL); +| | `- __reuseport_detach_closed_sock(sk1, reuse) +| | . +| | `- reuseport_put_incoming_cpu(sk1, reuse) +| | . +| | | /* Read shutdown()ed sk1's sk_incoming_cpu +| | | * without lock_sock(). +| | | */ +| | `- if (sk1->sk_incoming_cpu >= 0) +| | . +| | | /* decrement not-yet-incremented +| | | * count, which is never incremented. +| | | */ +| | `- __reuseport_put_incoming_cpu(reuse); +| | +| `- spin_lock_bh(&reuseport_lock) +| +|- spin_lock_bh(&reuseport_lock) +| +|- reuse = rcu_dereference_protected(sk1->sk_reuseport_cb, ...) +|- if (!reuse) +| . +| | /* Cannot increment reuse->incoming_cpu. */ +| `- goto out; +| +`- spin_unlock_bh(&reuseport_lock) + +Fixes: e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection") +Fixes: c125e80b8868 ("soreuseport: fast reuseport TCP socket selection") +Reported-by: Kazuho Oku +Signed-off-by: Kuniyuki Iwashima +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + include/net/sock_reuseport.h | 2 + + net/core/sock.c | 2 +- + net/core/sock_reuseport.c | 94 ++++++++++++++++++++++++++++++++++-- + 3 files changed, 92 insertions(+), 6 deletions(-) + +diff --git a/include/net/sock_reuseport.h b/include/net/sock_reuseport.h +index efc9085c6892..6ec140b0a61b 100644 +--- a/include/net/sock_reuseport.h ++++ b/include/net/sock_reuseport.h +@@ -16,6 +16,7 @@ struct sock_reuseport { + u16 max_socks; /* length of socks */ + u16 num_socks; /* elements in socks */ + u16 num_closed_socks; /* closed elements in socks */ ++ u16 incoming_cpu; + /* The last synq overflow event timestamp of this + * reuse->socks[] group. + */ +@@ -58,5 +59,6 @@ static inline bool reuseport_has_conns(struct sock *sk) + } + + void reuseport_has_conns_set(struct sock *sk); ++void reuseport_update_incoming_cpu(struct sock *sk, int val); + + #endif /* _SOCK_REUSEPORT_H */ +diff --git a/net/core/sock.c b/net/core/sock.c +index 9bcffe1d5332..b7ac53e72d1a 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1302,7 +1302,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, + break; + } + case SO_INCOMING_CPU: +- WRITE_ONCE(sk->sk_incoming_cpu, val); ++ reuseport_update_incoming_cpu(sk, val); + break; + + case SO_CNX_ADVICE: +diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c +index fb90e1e00773..5a165286e4d8 100644 +--- a/net/core/sock_reuseport.c ++++ b/net/core/sock_reuseport.c +@@ -37,6 +37,70 @@ void reuseport_has_conns_set(struct sock *sk) + } + EXPORT_SYMBOL(reuseport_has_conns_set); + ++static void __reuseport_get_incoming_cpu(struct sock_reuseport *reuse) ++{ ++ /* Paired with READ_ONCE() in reuseport_select_sock_by_hash(). */ ++ WRITE_ONCE(reuse->incoming_cpu, reuse->incoming_cpu + 1); ++} ++ ++static void __reuseport_put_incoming_cpu(struct sock_reuseport *reuse) ++{ ++ /* Paired with READ_ONCE() in reuseport_select_sock_by_hash(). */ ++ WRITE_ONCE(reuse->incoming_cpu, reuse->incoming_cpu - 1); ++} ++ ++static void reuseport_get_incoming_cpu(struct sock *sk, struct sock_reuseport *reuse) ++{ ++ if (sk->sk_incoming_cpu >= 0) ++ __reuseport_get_incoming_cpu(reuse); ++} ++ ++static void reuseport_put_incoming_cpu(struct sock *sk, struct sock_reuseport *reuse) ++{ ++ if (sk->sk_incoming_cpu >= 0) ++ __reuseport_put_incoming_cpu(reuse); ++} ++ ++void reuseport_update_incoming_cpu(struct sock *sk, int val) ++{ ++ struct sock_reuseport *reuse; ++ int old_sk_incoming_cpu; ++ ++ if (unlikely(!rcu_access_pointer(sk->sk_reuseport_cb))) { ++ /* Paired with REAE_ONCE() in sk_incoming_cpu_update() ++ * and compute_score(). ++ */ ++ WRITE_ONCE(sk->sk_incoming_cpu, val); ++ return; ++ } ++ ++ spin_lock_bh(&reuseport_lock); ++ ++ /* This must be done under reuseport_lock to avoid a race with ++ * reuseport_grow(), which accesses sk->sk_incoming_cpu without ++ * lock_sock() when detaching a shutdown()ed sk. ++ * ++ * Paired with READ_ONCE() in reuseport_select_sock_by_hash(). ++ */ ++ old_sk_incoming_cpu = sk->sk_incoming_cpu; ++ WRITE_ONCE(sk->sk_incoming_cpu, val); ++ ++ reuse = rcu_dereference_protected(sk->sk_reuseport_cb, ++ lockdep_is_held(&reuseport_lock)); ++ ++ /* reuseport_grow() has detached a closed sk. */ ++ if (!reuse) ++ goto out; ++ ++ if (old_sk_incoming_cpu < 0 && val >= 0) ++ __reuseport_get_incoming_cpu(reuse); ++ else if (old_sk_incoming_cpu >= 0 && val < 0) ++ __reuseport_put_incoming_cpu(reuse); ++ ++out: ++ spin_unlock_bh(&reuseport_lock); ++} ++ + static int reuseport_sock_index(struct sock *sk, + const struct sock_reuseport *reuse, + bool closed) +@@ -64,6 +128,7 @@ static void __reuseport_add_sock(struct sock *sk, + /* paired with smp_rmb() in reuseport_(select|migrate)_sock() */ + smp_wmb(); + reuse->num_socks++; ++ reuseport_get_incoming_cpu(sk, reuse); + } + + static bool __reuseport_detach_sock(struct sock *sk, +@@ -76,6 +141,7 @@ static bool __reuseport_detach_sock(struct sock *sk, + + reuse->socks[i] = reuse->socks[reuse->num_socks - 1]; + reuse->num_socks--; ++ reuseport_put_incoming_cpu(sk, reuse); + + return true; + } +@@ -86,6 +152,7 @@ static void __reuseport_add_closed_sock(struct sock *sk, + reuse->socks[reuse->max_socks - reuse->num_closed_socks - 1] = sk; + /* paired with READ_ONCE() in inet_csk_bind_conflict() */ + WRITE_ONCE(reuse->num_closed_socks, reuse->num_closed_socks + 1); ++ reuseport_get_incoming_cpu(sk, reuse); + } + + static bool __reuseport_detach_closed_sock(struct sock *sk, +@@ -99,6 +166,7 @@ static bool __reuseport_detach_closed_sock(struct sock *sk, + reuse->socks[i] = reuse->socks[reuse->max_socks - reuse->num_closed_socks]; + /* paired with READ_ONCE() in inet_csk_bind_conflict() */ + WRITE_ONCE(reuse->num_closed_socks, reuse->num_closed_socks - 1); ++ reuseport_put_incoming_cpu(sk, reuse); + + return true; + } +@@ -166,6 +234,7 @@ int reuseport_alloc(struct sock *sk, bool bind_inany) + reuse->bind_inany = bind_inany; + reuse->socks[0] = sk; + reuse->num_socks = 1; ++ reuseport_get_incoming_cpu(sk, reuse); + rcu_assign_pointer(sk->sk_reuseport_cb, reuse); + + out: +@@ -209,6 +278,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) + more_reuse->reuseport_id = reuse->reuseport_id; + more_reuse->bind_inany = reuse->bind_inany; + more_reuse->has_conns = reuse->has_conns; ++ more_reuse->incoming_cpu = reuse->incoming_cpu; + + memcpy(more_reuse->socks, reuse->socks, + reuse->num_socks * sizeof(struct sock *)); +@@ -458,18 +528,32 @@ static struct sock *run_bpf_filter(struct sock_reuseport *reuse, u16 socks, + static struct sock *reuseport_select_sock_by_hash(struct sock_reuseport *reuse, + u32 hash, u16 num_socks) + { ++ struct sock *first_valid_sk = NULL; + int i, j; + + i = j = reciprocal_scale(hash, num_socks); +- while (reuse->socks[i]->sk_state == TCP_ESTABLISHED) { ++ do { ++ struct sock *sk = reuse->socks[i]; ++ ++ if (sk->sk_state != TCP_ESTABLISHED) { ++ /* Paired with WRITE_ONCE() in __reuseport_(get|put)_incoming_cpu(). */ ++ if (!READ_ONCE(reuse->incoming_cpu)) ++ return sk; ++ ++ /* Paired with WRITE_ONCE() in reuseport_update_incoming_cpu(). */ ++ if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) ++ return sk; ++ ++ if (!first_valid_sk) ++ first_valid_sk = sk; ++ } ++ + i++; + if (i >= num_socks) + i = 0; +- if (i == j) +- return NULL; +- } ++ } while (i != j); + +- return reuse->socks[i]; ++ return first_valid_sk; + } + + /** +-- +2.35.1 + diff --git a/queue-5.15/spi-spi-gpio-don-t-set-mosi-as-an-input-if-not-3wire.patch b/queue-5.15/spi-spi-gpio-don-t-set-mosi-as-an-input-if-not-3wire.patch new file mode 100644 index 00000000000..121f748f6ce --- /dev/null +++ b/queue-5.15/spi-spi-gpio-don-t-set-mosi-as-an-input-if-not-3wire.patch @@ -0,0 +1,64 @@ +From 3861b046130ed4e7a0b7c11175919b2fc0f11e5b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 15:08:53 -0800 +Subject: spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode + +From: Kris Bahnsen + +[ Upstream commit 3a6f994f848a69deb2bf3cd9d130dd0c09730e55 ] + +The addition of 3WIRE support would affect MOSI direction even +when still in standard (4 wire) mode. This can lead to MOSI being +at an invalid logic level when a device driver sets an SPI +message with a NULL tx_buf. + +spi.h states that if tx_buf is NULL then "zeros will be shifted +out ... " If MOSI is tristated then the data shifted out is subject +to pull resistors, keepers, or in the absence of those, noise. + +This issue came to light when using spi-gpio connected to an +ADS7843 touchscreen controller. MOSI pulled high when clocking +MISO data in caused the SPI device to interpret this as a command +which would put the device in an unexpected and non-functional +state. + +Fixes: 4b859db2c606 ("spi: spi-gpio: add SPI_3WIRE support") +Fixes: 5132b3d28371 ("spi: gpio: Support 3WIRE high-impedance turn-around") +Signed-off-by: Kris Bahnsen +Link: https://lore.kernel.org/r/20221207230853.6174-1-kris@embeddedTS.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-gpio.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 0584f4d2fde2..3ffdab6caac2 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -244,9 +244,19 @@ static int spi_gpio_set_direction(struct spi_device *spi, bool output) + if (output) + return gpiod_direction_output(spi_gpio->mosi, 1); + +- ret = gpiod_direction_input(spi_gpio->mosi); +- if (ret) +- return ret; ++ /* ++ * Only change MOSI to an input if using 3WIRE mode. ++ * Otherwise, MOSI could be left floating if there is ++ * no pull resistor connected to the I/O pin, or could ++ * be left logic high if there is a pull-up. Transmitting ++ * logic high when only clocking MISO data in can put some ++ * SPI devices in to a bad state. ++ */ ++ if (spi->mode & SPI_3WIRE) { ++ ret = gpiod_direction_input(spi_gpio->mosi); ++ if (ret) ++ return ret; ++ } + /* + * Send a turnaround high impedance cycle when switching + * from output to input. Theoretically there should be +-- +2.35.1 + diff --git a/queue-5.15/spi-spidev-mask-spi_cs_high-in-spi_ioc_rd_mode.patch b/queue-5.15/spi-spidev-mask-spi_cs_high-in-spi_ioc_rd_mode.patch new file mode 100644 index 00000000000..091cf404a1d --- /dev/null +++ b/queue-5.15/spi-spidev-mask-spi_cs_high-in-spi_ioc_rd_mode.patch @@ -0,0 +1,83 @@ +From 104bb94ae62100f7c68b40afba68d46b3e57625c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 17:29:27 +0100 +Subject: spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE + +From: Alexander Sverdlin + +[ Upstream commit 7dbfa445ff7393d1c4c066c1727c9e0af1251958 ] + +Commit f3186dd87669 ("spi: Optionally use GPIO descriptors for CS GPIOs") +has changed the user-space interface so that bogus SPI_CS_HIGH started +to appear in the mask returned by SPI_IOC_RD_MODE even for active-low CS +pins. Commit 138c9c32f090 +("spi: spidev: Fix CS polarity if GPIO descriptors are used") fixed only +SPI_IOC_WR_MODE part of the problem. Let's fix SPI_IOC_RD_MODE +symmetrically. + +Test case: + + #include + #include + #include + + int main(int argc, char **argv) + { + char modew = SPI_CPHA; + char moder; + int f = open("/dev/spidev0.0", O_RDWR); + + if (f < 0) + return 1; + + ioctl(f, SPI_IOC_WR_MODE, &modew); + ioctl(f, SPI_IOC_RD_MODE, &moder); + + return moder == modew ? 0 : 2; + } + +Fixes: f3186dd87669 ("spi: Optionally use GPIO descriptors for CS GPIOs") +Signed-off-by: Alexander Sverdlin +Link: https://lore.kernel.org/r/20221130162927.539512-1-alexander.sverdlin@siemens.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spidev.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c +index 1bd73e322b7b..d233e2424ad1 100644 +--- a/drivers/spi/spidev.c ++++ b/drivers/spi/spidev.c +@@ -376,12 +376,23 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) + switch (cmd) { + /* read requests */ + case SPI_IOC_RD_MODE: +- retval = put_user(spi->mode & SPI_MODE_MASK, +- (__u8 __user *)arg); +- break; + case SPI_IOC_RD_MODE32: +- retval = put_user(spi->mode & SPI_MODE_MASK, +- (__u32 __user *)arg); ++ tmp = spi->mode; ++ ++ { ++ struct spi_controller *ctlr = spi->controller; ++ ++ if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && ++ ctlr->cs_gpiods[spi->chip_select]) ++ tmp &= ~SPI_CS_HIGH; ++ } ++ ++ if (cmd == SPI_IOC_RD_MODE) ++ retval = put_user(tmp & SPI_MODE_MASK, ++ (__u8 __user *)arg); ++ else ++ retval = put_user(tmp & SPI_MODE_MASK, ++ (__u32 __user *)arg); + break; + case SPI_IOC_RD_LSB_FIRST: + retval = put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0, +-- +2.35.1 + diff --git a/queue-5.15/spi-update-reference-to-struct-spi_controller.patch b/queue-5.15/spi-update-reference-to-struct-spi_controller.patch new file mode 100644 index 00000000000..06818efed57 --- /dev/null +++ b/queue-5.15/spi-update-reference-to-struct-spi_controller.patch @@ -0,0 +1,42 @@ +From 4ec63add1bfab6cb3296a86129159042b4a75bfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Nov 2022 18:32:51 +0100 +Subject: spi: Update reference to struct spi_controller +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jonathan Neuschäfer + +[ Upstream commit bf585ccee22faf469d82727cf375868105b362f7 ] + +struct spi_master has been renamed to struct spi_controller. Update the +reference in spi.rst to make it clickable again. + +Fixes: 8caab75fd2c2 ("spi: Generalize SPI "master" to "controller"") +Signed-off-by: Jonathan Neuschäfer +Link: https://lore.kernel.org/r/20221101173252.1069294-1-j.neuschaefer@gmx.net +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + Documentation/driver-api/spi.rst | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Documentation/driver-api/spi.rst b/Documentation/driver-api/spi.rst +index f64cb666498a..f28887045049 100644 +--- a/Documentation/driver-api/spi.rst ++++ b/Documentation/driver-api/spi.rst +@@ -25,8 +25,8 @@ hardware, which may be as simple as a set of GPIO pins or as complex as + a pair of FIFOs connected to dual DMA engines on the other side of the + SPI shift register (maximizing throughput). Such drivers bridge between + whatever bus they sit on (often the platform bus) and SPI, and expose +-the SPI side of their device as a :c:type:`struct spi_master +-`. SPI devices are children of that master, ++the SPI side of their device as a :c:type:`struct spi_controller ++`. SPI devices are children of that master, + represented as a :c:type:`struct spi_device ` and + manufactured from :c:type:`struct spi_board_info + ` descriptors which are usually provided by +-- +2.35.1 + diff --git a/queue-5.15/staging-rtl8192e-fix-potential-use-after-free-in-rtl.patch b/queue-5.15/staging-rtl8192e-fix-potential-use-after-free-in-rtl.patch new file mode 100644 index 00000000000..3c945087691 --- /dev/null +++ b/queue-5.15/staging-rtl8192e-fix-potential-use-after-free-in-rtl.patch @@ -0,0 +1,41 @@ +From 2ff4499a1b8ed40b3e19d1579c0c47d8f4df171d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 16:12:53 +0800 +Subject: staging: rtl8192e: Fix potential use-after-free in + rtllib_rx_Monitor() + +From: YueHaibing + +[ Upstream commit d30f4436f364b4ad915ca2c09be07cd0f93ceb44 ] + +The skb is delivered to netif_rx() in rtllib_monitor_rx(), which may free it, +after calling this, dereferencing skb may trigger use-after-free. +Found by Smatch. + +Fixes: 94a799425eee ("From: wlanfae [PATCH 1/8] rtl8192e: Import new version of driver from realtek") +Signed-off-by: YueHaibing +Link: https://lore.kernel.org/r/20221123081253.22296-1-yuehaibing@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/rtl8192e/rtllib_rx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c +index e3d0a361d370..98e90670560b 100644 +--- a/drivers/staging/rtl8192e/rtllib_rx.c ++++ b/drivers/staging/rtl8192e/rtllib_rx.c +@@ -1489,9 +1489,9 @@ static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb, + hdrlen += 4; + } + +- rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); + ieee->stats.rx_packets++; + ieee->stats.rx_bytes += skb->len; ++ rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); + + return 1; + } +-- +2.35.1 + diff --git a/queue-5.15/staging-rtl8192u-fix-use-after-free-in-ieee80211_rx.patch b/queue-5.15/staging-rtl8192u-fix-use-after-free-in-ieee80211_rx.patch new file mode 100644 index 00000000000..a73dc15808b --- /dev/null +++ b/queue-5.15/staging-rtl8192u-fix-use-after-free-in-ieee80211_rx.patch @@ -0,0 +1,41 @@ +From 73f5d36faa9e75e7e519bc98cc0ea8f668d969b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 09:43:14 +0300 +Subject: staging: rtl8192u: Fix use after free in ieee80211_rx() + +From: Dan Carpenter + +[ Upstream commit bcc5e2dcf09089b337b76fc1a589f6ff95ca19ac ] + +We cannot dereference the "skb" pointer after calling +ieee80211_monitor_rx(), because it is a use after free. + +Fixes: 8fc8598e61f6 ("Staging: Added Realtek rtl8192u driver to staging") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/Y33BArx3k/aw6yv/@kili +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +index b58e75932ecd..3686b3c599ce 100644 +--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c ++++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +@@ -951,9 +951,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, + #endif + + if (ieee->iw_mode == IW_MODE_MONITOR) { ++ unsigned int len = skb->len; ++ + ieee80211_monitor_rx(ieee, skb, rx_stats); + stats->rx_packets++; +- stats->rx_bytes += skb->len; ++ stats->rx_bytes += len; + return 1; + } + +-- +2.35.1 + diff --git a/queue-5.15/staging-vme_user-fix-possible-uaf-in-tsi148_dma_list.patch b/queue-5.15/staging-vme_user-fix-possible-uaf-in-tsi148_dma_list.patch new file mode 100644 index 00000000000..0d7019069e2 --- /dev/null +++ b/queue-5.15/staging-vme_user-fix-possible-uaf-in-tsi148_dma_list.patch @@ -0,0 +1,44 @@ +From 513b20adfe62632f473f7e9509b6381645b91987 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 11:59:14 +0800 +Subject: staging: vme_user: Fix possible UAF in tsi148_dma_list_add + +From: Gaosheng Cui + +[ Upstream commit 357057ee55d3c99a5de5abe8150f7bca04f8e53b ] + +Smatch report warning as follows: + +drivers/staging/vme_user/vme_tsi148.c:1757 tsi148_dma_list_add() warn: + '&entry->list' not removed from list + +In tsi148_dma_list_add(), the error path "goto err_dma" will not +remove entry->list from list->entries, but entry will be freed, +then list traversal may cause UAF. + +Fix by removeing it from list->entries before free(). + +Fixes: b2383c90a9d6 ("vme: tsi148: fix first DMA item mapping") +Signed-off-by: Gaosheng Cui +Link: https://lore.kernel.org/r/20221117035914.2954454-1-cuigaosheng1@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/vme/bridges/vme_tsi148.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c +index be9051b02f24..5b4c766d15e6 100644 +--- a/drivers/vme/bridges/vme_tsi148.c ++++ b/drivers/vme/bridges/vme_tsi148.c +@@ -1765,6 +1765,7 @@ static int tsi148_dma_list_add(struct vme_dma_list *list, + return 0; + + err_dma: ++ list_del(&entry->list); + err_dest: + err_source: + err_align: +-- +2.35.1 + diff --git a/queue-5.15/stmmac-fix-potential-division-by-0.patch b/queue-5.15/stmmac-fix-potential-division-by-0.patch new file mode 100644 index 00000000000..fb10544291b --- /dev/null +++ b/queue-5.15/stmmac-fix-potential-division-by-0.patch @@ -0,0 +1,89 @@ +From 6b62f0dc4d8ac88a8669b9331fc26f7e1e0e7e5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Dec 2022 23:37:22 +0100 +Subject: stmmac: fix potential division by 0 + +From: Piergiorgio Beruto + +[ Upstream commit ede5a389852d3640a28e7187fb32b7f204380901 ] + +When the MAC is connected to a 10 Mb/s PHY and the PTP clock is derived +from the MAC reference clock (default), the clk_ptp_rate becomes too +small and the calculated sub second increment becomes 0 when computed by +the stmmac_config_sub_second_increment() function within +stmmac_init_tstamp_counter(). + +Therefore, the subsequent div_u64 in stmmac_init_tstamp_counter() +operation triggers a divide by 0 exception as shown below. + +[ 95.062067] socfpga-dwmac ff700000.ethernet eth0: Register MEM_TYPE_PAGE_POOL RxQ-0 +[ 95.076440] socfpga-dwmac ff700000.ethernet eth0: PHY [stmmac-0:08] driver [NCN26000] (irq=49) +[ 95.095964] dwmac1000: Master AXI performs any burst length +[ 95.101588] socfpga-dwmac ff700000.ethernet eth0: No Safety Features support found +[ 95.109428] Division by zero in kernel. +[ 95.113447] CPU: 0 PID: 239 Comm: ifconfig Not tainted 6.1.0-rc7-centurion3-1.0.3.0-01574-gb624218205b7-dirty #77 +[ 95.123686] Hardware name: Altera SOCFPGA +[ 95.127695] unwind_backtrace from show_stack+0x10/0x14 +[ 95.132938] show_stack from dump_stack_lvl+0x40/0x4c +[ 95.137992] dump_stack_lvl from Ldiv0+0x8/0x10 +[ 95.142527] Ldiv0 from __aeabi_uidivmod+0x8/0x18 +[ 95.147232] __aeabi_uidivmod from div_u64_rem+0x1c/0x40 +[ 95.152552] div_u64_rem from stmmac_init_tstamp_counter+0xd0/0x164 +[ 95.158826] stmmac_init_tstamp_counter from stmmac_hw_setup+0x430/0xf00 +[ 95.165533] stmmac_hw_setup from __stmmac_open+0x214/0x2d4 +[ 95.171117] __stmmac_open from stmmac_open+0x30/0x44 +[ 95.176182] stmmac_open from __dev_open+0x11c/0x134 +[ 95.181172] __dev_open from __dev_change_flags+0x168/0x17c +[ 95.186750] __dev_change_flags from dev_change_flags+0x14/0x50 +[ 95.192662] dev_change_flags from devinet_ioctl+0x2b4/0x604 +[ 95.198321] devinet_ioctl from inet_ioctl+0x1ec/0x214 +[ 95.203462] inet_ioctl from sock_ioctl+0x14c/0x3c4 +[ 95.208354] sock_ioctl from vfs_ioctl+0x20/0x38 +[ 95.212984] vfs_ioctl from sys_ioctl+0x250/0x844 +[ 95.217691] sys_ioctl from ret_fast_syscall+0x0/0x4c +[ 95.222743] Exception stack(0xd0ee1fa8 to 0xd0ee1ff0) +[ 95.227790] 1fa0: 00574c4f be9aeca4 00000003 00008914 be9aeca4 be9aec50 +[ 95.235945] 1fc0: 00574c4f be9aeca4 0059f078 00000036 be9aee8c be9aef7a 00000015 00000000 +[ 95.244096] 1fe0: 005a01f0 be9aec38 004d7484 b6e67d74 + +Signed-off-by: Piergiorgio Beruto +Fixes: 91a2559c1dc5 ("net: stmmac: Fix sub-second increment") +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/de4c64ccac9084952c56a06a8171d738604c4770.1670678513.git.piergiorgio.beruto@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 3 ++- + drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +index d68ef72dcdde..4538e4fd8189 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +@@ -47,7 +47,8 @@ static void config_sub_second_increment(void __iomem *ioaddr, + if (!(value & PTP_TCR_TSCTRLSSR)) + data = (data * 1000) / 465; + +- data &= PTP_SSIR_SSINC_MASK; ++ if (data > PTP_SSIR_SSINC_MAX) ++ data = PTP_SSIR_SSINC_MAX; + + reg_value = data; + if (gmac4) +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +index 53172a439810..bf619295d079 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h +@@ -64,7 +64,7 @@ + #define PTP_TCR_TSENMACADDR BIT(18) + + /* SSIR defines */ +-#define PTP_SSIR_SSINC_MASK 0xff ++#define PTP_SSIR_SSINC_MAX 0xff + #define GMAC4_PTP_SSIR_SSINC_SHIFT 16 + + /* Auxiliary Control defines */ +-- +2.35.1 + diff --git a/queue-5.15/sunrpc-fix-missing-release-socket-in-rpc_sockname.patch b/queue-5.15/sunrpc-fix-missing-release-socket-in-rpc_sockname.patch new file mode 100644 index 00000000000..034387713f9 --- /dev/null +++ b/queue-5.15/sunrpc-fix-missing-release-socket-in-rpc_sockname.patch @@ -0,0 +1,37 @@ +From 598022ec53b2fd5311c7f24aac3b3a0cc1b75608 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 17:23:42 +0800 +Subject: SUNRPC: Fix missing release socket in rpc_sockname() + +From: Wang ShaoBo + +[ Upstream commit 50fa355bc0d75911fe9d5072a5ba52cdb803aff7 ] + +socket dynamically created is not released when getting an unintended +address family type in rpc_sockname(), direct to out_release for calling +sock_release(). + +Fixes: 2e738fdce22f ("SUNRPC: Add API to acquire source address") +Signed-off-by: Wang ShaoBo +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/clnt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c +index ca2a494d727b..bbeb80e1133d 100644 +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -1375,7 +1375,7 @@ static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, + break; + default: + err = -EAFNOSUPPORT; +- goto out; ++ goto out_release; + } + if (err < 0) { + dprintk("RPC: can't bind UDP socket (%d)\n", err); +-- +2.35.1 + diff --git a/queue-5.15/sunrpc-return-true-false-not-1-0-from-bool-functions.patch b/queue-5.15/sunrpc-return-true-false-not-1-0-from-bool-functions.patch new file mode 100644 index 00000000000..73c72d1abac --- /dev/null +++ b/queue-5.15/sunrpc-return-true-false-not-1-0-from-bool-functions.patch @@ -0,0 +1,97 @@ +From aa6ffadb36a5d94667364b693a9b32517d38aab6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Mar 2022 10:48:59 +0800 +Subject: SUNRPC: Return true/false (not 1/0) from bool functions + +From: Haowen Bai + +[ Upstream commit 5f7b839d47dbc74cf4a07beeab5191f93678673e ] + +Return boolean values ("true" or "false") instead of 1 or 0 from bool +functions. This fixes the following warnings from coccicheck: + +./fs/nfsd/nfs2acl.c:289:9-10: WARNING: return of 0/1 in function +'nfsaclsvc_encode_accessres' with return type bool +./fs/nfsd/nfs2acl.c:252:9-10: WARNING: return of 0/1 in function +'nfsaclsvc_encode_getaclres' with return type bool + +Signed-off-by: Haowen Bai +Signed-off-by: Chuck Lever +Stable-dep-of: ea5021e911d3 ("NFSD: Finish converting the NFSv2 GETACL result encoder") +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs2acl.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c +index 4b43929c1f25..ec7776b0e868 100644 +--- a/fs/nfsd/nfs2acl.c ++++ b/fs/nfsd/nfs2acl.c +@@ -249,34 +249,34 @@ static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) + int w; + + if (!svcxdr_encode_stat(xdr, resp->status)) +- return 0; ++ return false; + + if (dentry == NULL || d_really_is_negative(dentry)) +- return 1; ++ return true; + inode = d_inode(dentry); + + if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat)) +- return 0; ++ return false; + if (xdr_stream_encode_u32(xdr, resp->mask) < 0) +- return 0; ++ return false; + + rqstp->rq_res.page_len = w = nfsacl_size( + (resp->mask & NFS_ACL) ? resp->acl_access : NULL, + (resp->mask & NFS_DFACL) ? resp->acl_default : NULL); + while (w > 0) { + if (!*(rqstp->rq_next_page++)) +- return 1; ++ return true; + w -= PAGE_SIZE; + } + + if (!nfs_stream_encode_acl(xdr, inode, resp->acl_access, + resp->mask & NFS_ACL, 0)) +- return 0; ++ return false; + if (!nfs_stream_encode_acl(xdr, inode, resp->acl_default, + resp->mask & NFS_DFACL, NFS_ACL_DEFAULT)) +- return 0; ++ return false; + +- return 1; ++ return true; + } + + /* ACCESS */ +@@ -286,17 +286,17 @@ static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, __be32 *p) + struct nfsd3_accessres *resp = rqstp->rq_resp; + + if (!svcxdr_encode_stat(xdr, resp->status)) +- return 0; ++ return false; + switch (resp->status) { + case nfs_ok: + if (!svcxdr_encode_fattr(rqstp, xdr, &resp->fh, &resp->stat)) +- return 0; ++ return false; + if (xdr_stream_encode_u32(xdr, resp->access) < 0) +- return 0; ++ return false; + break; + } + +- return 1; ++ return true; + } + + /* +-- +2.35.1 + diff --git a/queue-5.15/test_firmware-fix-memory-leak-in-test_firmware_init.patch b/queue-5.15/test_firmware-fix-memory-leak-in-test_firmware_init.patch new file mode 100644 index 00000000000..7fe5a7b09d6 --- /dev/null +++ b/queue-5.15/test_firmware-fix-memory-leak-in-test_firmware_init.patch @@ -0,0 +1,54 @@ +From dc31390e03601e4effd9568e68787a4690508f5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Nov 2022 11:57:21 +0800 +Subject: test_firmware: fix memory leak in test_firmware_init() + +From: Zhengchao Shao + +[ Upstream commit 7610615e8cdb3f6f5bbd9d8e7a5d8a63e3cabf2e ] + +When misc_register() failed in test_firmware_init(), the memory pointed +by test_fw_config->name is not released. The memory leak information is +as follows: +unreferenced object 0xffff88810a34cb00 (size 32): + comm "insmod", pid 7952, jiffies 4294948236 (age 49.060s) + hex dump (first 32 bytes): + 74 65 73 74 2d 66 69 72 6d 77 61 72 65 2e 62 69 test-firmware.bi + 6e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 n............... + backtrace: + [] __kmalloc_node_track_caller+0x4b/0xc0 + [] kstrndup+0x46/0xc0 + [] __test_firmware_config_init+0x29/0x380 [test_firmware] + [] 0xffffffffa040f068 + [] do_one_initcall+0x141/0x780 + [] do_init_module+0x1c3/0x630 + [] load_module+0x623e/0x76a0 + [] __do_sys_finit_module+0x181/0x240 + [] do_syscall_64+0x39/0xb0 + [] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Fixes: c92316bf8e94 ("test_firmware: add batched firmware tests") +Signed-off-by: Zhengchao Shao +Acked-by: Luis Chamberlain +Link: https://lore.kernel.org/r/20221119035721.18268-1-shaozhengchao@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/test_firmware.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/test_firmware.c b/lib/test_firmware.c +index 1bccd6cd5f48..e68be7aba7d1 100644 +--- a/lib/test_firmware.c ++++ b/lib/test_firmware.c +@@ -1111,6 +1111,7 @@ static int __init test_firmware_init(void) + + rc = misc_register(&test_fw_misc_device); + if (rc) { ++ __test_firmware_config_free(); + kfree(test_fw_config); + pr_err("could not register misc device: %d\n", rc); + return rc; +-- +2.35.1 + diff --git a/queue-5.15/thermal-core-fix-some-possible-name-leaks-in-error-p.patch b/queue-5.15/thermal-core-fix-some-possible-name-leaks-in-error-p.patch new file mode 100644 index 00000000000..b41a104e4d7 --- /dev/null +++ b/queue-5.15/thermal-core-fix-some-possible-name-leaks-in-error-p.patch @@ -0,0 +1,75 @@ +From b0c368ddd03febb3ebcbe6f60841e75fec67ad03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Nov 2022 17:19:45 +0800 +Subject: thermal: core: fix some possible name leaks in error paths + +From: Yang Yingliang + +[ Upstream commit 4748f9687caaeefab8578285b97b2f30789fc4b4 ] + +In some error paths before device_register(), the names allocated +by dev_set_name() are not freed. Move dev_set_name() front to +device_register(), so the name can be freed while calling +put_device(). + +Fixes: 1dd7128b839f ("thermal/core: Fix null pointer dereference in thermal_release()") +Signed-off-by: Yang Yingliang +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/thermal/thermal_core.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 867c8aa92b3a..38082fdc4fde 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -905,10 +905,6 @@ __thermal_cooling_device_register(struct device_node *np, + cdev->id = ret; + id = ret; + +- ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); +- if (ret) +- goto out_ida_remove; +- + cdev->type = kstrdup(type ? type : "", GFP_KERNEL); + if (!cdev->type) { + ret = -ENOMEM; +@@ -923,6 +919,11 @@ __thermal_cooling_device_register(struct device_node *np, + cdev->device.class = &thermal_class; + cdev->devdata = devdata; + thermal_cooling_device_setup_sysfs(cdev); ++ ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id); ++ if (ret) { ++ thermal_cooling_device_destroy_sysfs(cdev); ++ goto out_kfree_type; ++ } + ret = device_register(&cdev->device); + if (ret) + goto out_kfree_type; +@@ -1235,10 +1236,6 @@ thermal_zone_device_register(const char *type, int trips, int mask, + tz->id = id; + strlcpy(tz->type, type, sizeof(tz->type)); + +- result = dev_set_name(&tz->device, "thermal_zone%d", tz->id); +- if (result) +- goto remove_id; +- + if (!ops->critical) + ops->critical = thermal_zone_device_critical; + +@@ -1260,6 +1257,11 @@ thermal_zone_device_register(const char *type, int trips, int mask, + /* A new thermal zone needs to be updated anyway. */ + atomic_set(&tz->need_update, 1); + ++ result = dev_set_name(&tz->device, "thermal_zone%d", tz->id); ++ if (result) { ++ thermal_zone_destroy_device_groups(tz); ++ goto remove_id; ++ } + result = device_register(&tz->device); + if (result) + goto release_device; +-- +2.35.1 + diff --git a/queue-5.15/thermal-drivers-imx8mm_thermal-validate-temperature-.patch b/queue-5.15/thermal-drivers-imx8mm_thermal-validate-temperature-.patch new file mode 100644 index 00000000000..ce0d68a9b16 --- /dev/null +++ b/queue-5.15/thermal-drivers-imx8mm_thermal-validate-temperature-.patch @@ -0,0 +1,45 @@ +From 000f7d1612861a2bce7d59048eb8eab45b2eab8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Oct 2022 09:35:07 +0200 +Subject: thermal/drivers/imx8mm_thermal: Validate temperature range + +From: Marcus Folkesson + +[ Upstream commit d37edc7370273306d8747097fafa62436c1cfe16 ] + +Check against the upper temperature limit (125 degrees C) before +consider the temperature valid. + +Fixes: 5eed800a6811 ("thermal: imx8mm: Add support for i.MX8MM thermal monitoring unit") +Signed-off-by: Marcus Folkesson +Reviewed-by: Jacky Bai +Link: https://lore.kernel.org/r/20221014073507.1594844-1-marcus.folkesson@gmail.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/imx8mm_thermal.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c +index af666bd9e8d4..c5cd873c6e01 100644 +--- a/drivers/thermal/imx8mm_thermal.c ++++ b/drivers/thermal/imx8mm_thermal.c +@@ -65,8 +65,14 @@ static int imx8mm_tmu_get_temp(void *data, int *temp) + u32 val; + + val = readl_relaxed(tmu->base + TRITSR) & TRITSR_TEMP0_VAL_MASK; ++ ++ /* ++ * Do not validate against the V bit (bit 31) due to errata ++ * ERR051272: TMU: Bit 31 of registers TMU_TSCR/TMU_TRITSR/TMU_TRATSR invalid ++ */ ++ + *temp = val * 1000; +- if (*temp < VER1_TEMP_LOW_LIMIT) ++ if (*temp < VER1_TEMP_LOW_LIMIT || *temp > VER2_TEMP_HIGH_LIMIT) + return -EAGAIN; + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/thermal-drivers-qcom-lmh-fix-irq-handler-return-valu.patch b/queue-5.15/thermal-drivers-qcom-lmh-fix-irq-handler-return-valu.patch new file mode 100644 index 00000000000..d400723fd4e --- /dev/null +++ b/queue-5.15/thermal-drivers-qcom-lmh-fix-irq-handler-return-valu.patch @@ -0,0 +1,39 @@ +From d593e821ed01dc4bf080e687a8007d02e0710710 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Mar 2022 11:03:22 -0700 +Subject: thermal/drivers/qcom/lmh: Fix irq handler return value + +From: Bjorn Andersson + +[ Upstream commit 46a891e45be97c6781ac34f5ec777d69370e252b ] + +After enough invocations the LMh irq is eventually reported as bad, because the +handler doesn't return IRQ_HANDLED, fix this. + +Fixes: 53bca371cdf7 ("thermal/drivers/qcom: Add support for LMh driver") +Reported-by: Daniel Lezcano +Signed-off-by: Bjorn Andersson +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220316180322.88132-1-bjorn.andersson@linaro.org +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/qcom/lmh.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/thermal/qcom/lmh.c b/drivers/thermal/qcom/lmh.c +index eafa7526eb8b..cc94d8b005d4 100644 +--- a/drivers/thermal/qcom/lmh.c ++++ b/drivers/thermal/qcom/lmh.c +@@ -43,7 +43,7 @@ static irqreturn_t lmh_handle_irq(int hw_irq, void *data) + if (irq) + generic_handle_irq(irq); + +- return 0; ++ return IRQ_HANDLED; + } + + static void lmh_enable_interrupt(struct irq_data *d) +-- +2.35.1 + diff --git a/queue-5.15/thermal-drivers-qcom-temp-alarm-fix-inaccurate-warni.patch b/queue-5.15/thermal-drivers-qcom-temp-alarm-fix-inaccurate-warni.patch new file mode 100644 index 00000000000..2a96767505b --- /dev/null +++ b/queue-5.15/thermal-drivers-qcom-temp-alarm-fix-inaccurate-warni.patch @@ -0,0 +1,41 @@ +From 592e18fc1cdf2b39a5b64888fcf32bd2e3c0251c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Oct 2022 16:52:37 +0200 +Subject: thermal/drivers/qcom/temp-alarm: Fix inaccurate warning for gen2 + +From: Luca Weiss + +[ Upstream commit 8763f8acbf8aef22a2321d4c978cd078aa3b8f64 ] + +On gen2 chips the stage2 threshold is not 140 degC but 125 degC. + +Make the warning message clearer by using this variable and also by +including the temperature that was checked for. + +Fixes: aa92b3310c55 ("thermal/drivers/qcom-spmi-temp-alarm: Add support for GEN2 rev 1 PMIC peripherals") +Signed-off-by: Luca Weiss +Reviewed-by: Amit Kucheria +Link: https://lore.kernel.org/r/20221020145237.942146-1-luca.weiss@fairphone.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/qcom/qcom-spmi-temp-alarm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +index 7419e196dbb0..1037de19873a 100644 +--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c ++++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +@@ -251,7 +251,8 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip, + disable_s2_shutdown = true; + else + dev_warn(chip->dev, +- "No ADC is configured and critical temperature is above the maximum stage 2 threshold of 140 C! Configuring stage 2 shutdown at 140 C.\n"); ++ "No ADC is configured and critical temperature %d mC is above the maximum stage 2 threshold of %ld mC! Configuring stage 2 shutdown at %ld mC.\n", ++ temp, stage2_threshold_max, stage2_threshold_max); + } + + skip: +-- +2.35.1 + diff --git a/queue-5.15/timerqueue-use-rb_entry_safe-in-timerqueue_getnext.patch b/queue-5.15/timerqueue-use-rb_entry_safe-in-timerqueue_getnext.patch new file mode 100644 index 00000000000..e35083a90a5 --- /dev/null +++ b/queue-5.15/timerqueue-use-rb_entry_safe-in-timerqueue_getnext.patch @@ -0,0 +1,44 @@ +From fbd438168d5934e91a81e77a2e993014f09b64c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 19:54:23 +0000 +Subject: timerqueue: Use rb_entry_safe() in timerqueue_getnext() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Barnabás Pőcze + +[ Upstream commit 2f117484329b233455ee278f2d9b0a4356835060 ] + +When `timerqueue_getnext()` is called on an empty timer queue, it will +use `rb_entry()` on a NULL pointer, which is invalid. Fix that by using +`rb_entry_safe()` which handles NULL pointers. + +This has not caused any issues so far because the offset of the `rb_node` +member in `timerqueue_node` is 0, so `rb_entry()` is essentially a no-op. + +Fixes: 511885d7061e ("lib/timerqueue: Rely on rbtree semantics for next timer") +Signed-off-by: Barnabás Pőcze +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20221114195421.342929-1-pobrn@protonmail.com +Signed-off-by: Sasha Levin +--- + include/linux/timerqueue.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h +index 93884086f392..adc80e29168e 100644 +--- a/include/linux/timerqueue.h ++++ b/include/linux/timerqueue.h +@@ -35,7 +35,7 @@ struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) + { + struct rb_node *leftmost = rb_first_cached(&head->rb_root); + +- return rb_entry(leftmost, struct timerqueue_node, node); ++ return rb_entry_safe(leftmost, struct timerqueue_node, node); + } + + static inline void timerqueue_init(struct timerqueue_node *node) +-- +2.35.1 + diff --git a/queue-5.15/tools-include-add-_ret_ip_-and-math-definitions-to-k.patch b/queue-5.15/tools-include-add-_ret_ip_-and-math-definitions-to-k.patch new file mode 100644 index 00000000000..96d95de57ef --- /dev/null +++ b/queue-5.15/tools-include-add-_ret_ip_-and-math-definitions-to-k.patch @@ -0,0 +1,52 @@ +From 0e1ce55af94f446aeb901a46561d822c662f4107 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Dec 2022 18:09:57 -0600 +Subject: tools/include: Add _RET_IP_ and math definitions to kernel.h + +From: Karolina Drobnik + +commit 5cf67a6051ea2558fd7c3d39c5a808db73073e9d upstream. + +Add max_t, min_t and clamp functions, together with _RET_IP_ +definition, so they can be used in testing. + +Signed-off-by: Karolina Drobnik +Signed-off-by: Mike Rapoport +Link: https://lore.kernel.org/r/230fea382cb1e1659cdd52a55201854d38a0a149.1643796665.git.karolinadrobnik@gmail.com +[tyhicks: Backport around contextual differences due to the lack of v5.16 commit + d6e6a27d960f ("tools: Fix math.h breakage"). That commit fixed a commit + that was merged in v5.16-rc1 and, therefore, doesn't need to go back to + the stable branches.] +Signed-off-by: Tyler Hicks (Microsoft) +Signed-off-by: Sasha Levin +--- + tools/include/linux/kernel.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h +index a7e54a08fb54..c2e109860fbc 100644 +--- a/tools/include/linux/kernel.h ++++ b/tools/include/linux/kernel.h +@@ -14,6 +14,8 @@ + #define UINT_MAX (~0U) + #endif + ++#define _RET_IP_ ((unsigned long)__builtin_return_address(0)) ++ + #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) + + #define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1) +@@ -52,6 +54,10 @@ + _min1 < _min2 ? _min1 : _min2; }) + #endif + ++#define max_t(type, x, y) max((type)x, (type)y) ++#define min_t(type, x, y) min((type)x, (type)y) ++#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi) ++ + #ifndef roundup + #define roundup(x, y) ( \ + { \ +-- +2.35.1 + diff --git a/queue-5.15/tpm-tpm_crb-fix-error-message-in-__crb_relinquish_lo.patch b/queue-5.15/tpm-tpm_crb-fix-error-message-in-__crb_relinquish_lo.patch new file mode 100644 index 00000000000..6795a2d87a4 --- /dev/null +++ b/queue-5.15/tpm-tpm_crb-fix-error-message-in-__crb_relinquish_lo.patch @@ -0,0 +1,38 @@ +From 08acc4ee8a40ee56c1446f8fc9193200a07e3217 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 11:38:53 -0800 +Subject: tpm/tpm_crb: Fix error message in __crb_relinquish_locality() + +From: Michael Kelley + +[ Upstream commit f5264068071964b56dc02c9dab3d11574aaca6ff ] + +The error message in __crb_relinquish_locality() mentions requestAccess +instead of Relinquish. Fix it. + +Fixes: 888d867df441 ("tpm: cmd_ready command can be issued only after granting locality") +Signed-off-by: Michael Kelley +Acked-by: Tomas Winkler +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + drivers/char/tpm/tpm_crb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c +index 18606651d1aa..65f8f179a27f 100644 +--- a/drivers/char/tpm/tpm_crb.c ++++ b/drivers/char/tpm/tpm_crb.c +@@ -252,7 +252,7 @@ static int __crb_relinquish_locality(struct device *dev, + iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl); + if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value, + TPM2_TIMEOUT_C)) { +- dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n"); ++ dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n"); + return -ETIME; + } + +-- +2.35.1 + diff --git a/queue-5.15/tpm-tpm_ftpm_tee-fix-error-handling-in-ftpm_mod_init.patch b/queue-5.15/tpm-tpm_ftpm_tee-fix-error-handling-in-ftpm_mod_init.patch new file mode 100644 index 00000000000..0f82b0452b6 --- /dev/null +++ b/queue-5.15/tpm-tpm_ftpm_tee-fix-error-handling-in-ftpm_mod_init.patch @@ -0,0 +1,47 @@ +From bda035fb6a4ed463a14c0c2facc1b46750122656 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 03:19:26 +0000 +Subject: tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init() + +From: Yuan Can + +[ Upstream commit 2b7d07f7acaac2c7750e420dcf4414588ede6d03 ] + +The ftpm_mod_init() returns the driver_register() directly without checking +its return value, if driver_register() failed, the ftpm_tee_plat_driver is +not unregistered. + +Fix by unregister ftpm_tee_plat_driver when driver_register() failed. + +Fixes: 9f1944c23c8c ("tpm_ftpm_tee: register driver on TEE bus") +Signed-off-by: Yuan Can +Reviewed-by: Maxim Uvarov +Acked-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + drivers/char/tpm/tpm_ftpm_tee.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c +index 6e3235565a4d..d9daaafdd295 100644 +--- a/drivers/char/tpm/tpm_ftpm_tee.c ++++ b/drivers/char/tpm/tpm_ftpm_tee.c +@@ -397,7 +397,13 @@ static int __init ftpm_mod_init(void) + if (rc) + return rc; + +- return driver_register(&ftpm_tee_driver.driver); ++ rc = driver_register(&ftpm_tee_driver.driver); ++ if (rc) { ++ platform_driver_unregister(&ftpm_tee_plat_driver); ++ return rc; ++ } ++ ++ return 0; + } + + static void __exit ftpm_mod_exit(void) +-- +2.35.1 + diff --git a/queue-5.15/tracing-hist-fix-issue-of-losting-command-info-in-er.patch b/queue-5.15/tracing-hist-fix-issue-of-losting-command-info-in-er.patch new file mode 100644 index 00000000000..79b704d66d8 --- /dev/null +++ b/queue-5.15/tracing-hist-fix-issue-of-losting-command-info-in-er.patch @@ -0,0 +1,93 @@ +From 8a7d69a7f895ed9a37de094c211c1ff15d7a6185 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 21:53:26 +0800 +Subject: tracing/hist: Fix issue of losting command info in error_log + +From: Zheng Yejian + +[ Upstream commit 608c6ed3337850c767ab0dd6c583477922233e29 ] + +When input some constructed invalid 'trigger' command, command info +in 'error_log' are lost [1]. + +The root cause is that there is a path that event_hist_trigger_parse() +is recursely called once and 'last_cmd' which save origin command is +cleared, then later calling of hist_err() will no longer record origin +command info: + + event_hist_trigger_parse() { + last_cmd_set() // <1> 'last_cmd' save origin command here at first + create_actions() { + onmatch_create() { + action_create() { + trace_action_create() { + trace_action_create_field_var() { + create_field_var_hist() { + event_hist_trigger_parse() { // <2> recursely called once + hist_err_clear() // <3> 'last_cmd' is cleared here + } + hist_err() // <4> No longer find origin command!!! + +Since 'glob' is empty string while running into the recurse call, we +can trickly check it and bypass the call of hist_err_clear() to solve it. + +[1] + # cd /sys/kernel/tracing + # echo "my_synth_event int v1; int v2; int v3;" >> synthetic_events + # echo 'hist:keys=pid' >> events/sched/sched_waking/trigger + # echo "hist:keys=next_pid:onmatch(sched.sched_waking).my_synth_event(\ +pid,pid1)" >> events/sched/sched_switch/trigger + # cat error_log +[ 8.405018] hist:sched:sched_switch: error: Couldn't find synthetic event + Command: +hist:keys=next_pid:onmatch(sched.sched_waking).my_synth_event(pid,pid1) + ^ +[ 8.816902] hist:sched:sched_switch: error: Couldn't find field + Command: +hist:keys=next_pid:onmatch(sched.sched_waking).my_synth_event(pid,pid1) + ^ +[ 8.816902] hist:sched:sched_switch: error: Couldn't parse field variable + Command: +hist:keys=next_pid:onmatch(sched.sched_waking).my_synth_event(pid,pid1) + ^ +[ 8.999880] : error: Couldn't find field + Command: + ^ +[ 8.999880] : error: Couldn't parse field variable + Command: + ^ +[ 8.999880] : error: Couldn't find field + Command: + ^ +[ 8.999880] : error: Couldn't create histogram for field + Command: + ^ + +Link: https://lore.kernel.org/linux-trace-kernel/20221207135326.3483216-1-zhengyejian1@huawei.com + +Cc: +Cc: +Fixes: f404da6e1d46 ("tracing: Add 'last error' error facility for hist triggers") +Signed-off-by: Zheng Yejian +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_events_hist.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 31e3e0bbd129..6397285883fa 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -5954,7 +5954,7 @@ static int event_hist_trigger_func(struct event_command *cmd_ops, + /* Just return zero, not the number of registered triggers */ + ret = 0; + out: +- if (ret == 0) ++ if (ret == 0 && glob[0]) + hist_err_clear(); + + return ret; +-- +2.35.1 + diff --git a/queue-5.15/tty-serial-altera_uart_-r-t-x_chars-need-only-uart_p.patch b/queue-5.15/tty-serial-altera_uart_-r-t-x_chars-need-only-uart_p.patch new file mode 100644 index 00000000000..d752c52458e --- /dev/null +++ b/queue-5.15/tty-serial-altera_uart_-r-t-x_chars-need-only-uart_p.patch @@ -0,0 +1,71 @@ +From 838167c47ee499978bfc90d04414c0efda4b636e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 07:20:43 +0200 +Subject: tty: serial: altera_uart_{r,t}x_chars() need only uart_port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jiri Slaby + +[ Upstream commit 3af44d9bb0539d5fa27d6159d696fda5f3747bff ] + +Both altera_uart_{r,t}x_chars() need only uart_port, not altera_uart. So +pass the former from altera_uart_interrupt() directly. + +Apart it maybe saves a dereference, this makes the transition of +altera_uart_tx_chars() easier to follow in the next patch. + +Cc: Tobias Klauser +Reviewed-by: Ilpo Järvinen +Acked-by: Tobias Klauser +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20220920052049.20507-4-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 1307c5d33cce ("serial: altera_uart: fix locking in polling mode") +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/altera_uart.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c +index 0e194556d76e..6e08fa11ceea 100644 +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -199,9 +199,8 @@ static void altera_uart_set_termios(struct uart_port *port, + */ + } + +-static void altera_uart_rx_chars(struct altera_uart *pp) ++static void altera_uart_rx_chars(struct uart_port *port) + { +- struct uart_port *port = &pp->port; + unsigned char ch, flag; + unsigned short status; + +@@ -246,9 +245,8 @@ static void altera_uart_rx_chars(struct altera_uart *pp) + tty_flip_buffer_push(&port->state->port); + } + +-static void altera_uart_tx_chars(struct altera_uart *pp) ++static void altera_uart_tx_chars(struct uart_port *port) + { +- struct uart_port *port = &pp->port; + struct circ_buf *xmit = &port->state->xmit; + + if (port->x_char) { +@@ -286,9 +284,9 @@ static irqreturn_t altera_uart_interrupt(int irq, void *data) + + spin_lock(&port->lock); + if (isr & ALTERA_UART_STATUS_RRDY_MSK) +- altera_uart_rx_chars(pp); ++ altera_uart_rx_chars(port); + if (isr & ALTERA_UART_STATUS_TRDY_MSK) +- altera_uart_tx_chars(pp); ++ altera_uart_tx_chars(port); + spin_unlock(&port->lock); + + return IRQ_RETVAL(isr); +-- +2.35.1 + diff --git a/queue-5.15/tty-serial-clean-up-stop-tx-part-in-altera_uart_tx_c.patch b/queue-5.15/tty-serial-clean-up-stop-tx-part-in-altera_uart_tx_c.patch new file mode 100644 index 00000000000..78904897434 --- /dev/null +++ b/queue-5.15/tty-serial-clean-up-stop-tx-part-in-altera_uart_tx_c.patch @@ -0,0 +1,48 @@ +From e678661f5fbc72e2715e8498bde4555d791a014e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 07:20:42 +0200 +Subject: tty: serial: clean up stop-tx part in altera_uart_tx_chars() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jiri Slaby + +[ Upstream commit d9c128117da41cf4cb0e80ae565b5d3ac79dffac ] + +The "stop TX" path in altera_uart_tx_chars() is open-coded, so: +* use uart_circ_empty() to check if the buffer is empty, and +* when true, call altera_uart_stop_tx(). + +Cc: Tobias Klauser +Reviewed-by: Ilpo Järvinen +Acked-by: Tobias Klauser +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20220920052049.20507-3-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 1307c5d33cce ("serial: altera_uart: fix locking in polling mode") +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/altera_uart.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c +index 7c5f4e966b59..0e194556d76e 100644 +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -272,10 +272,8 @@ static void altera_uart_tx_chars(struct altera_uart *pp) + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); + +- if (xmit->head == xmit->tail) { +- pp->imr &= ~ALTERA_UART_CONTROL_TRDY_MSK; +- altera_uart_update_ctrl_reg(pp); +- } ++ if (uart_circ_empty(xmit)) ++ altera_uart_stop_tx(port); + } + + static irqreturn_t altera_uart_interrupt(int irq, void *data) +-- +2.35.1 + diff --git a/queue-5.15/udf-avoid-double-brelse-in-udf_rename.patch b/queue-5.15/udf-avoid-double-brelse-in-udf_rename.patch new file mode 100644 index 00000000000..83586aa43d1 --- /dev/null +++ b/queue-5.15/udf-avoid-double-brelse-in-udf_rename.patch @@ -0,0 +1,93 @@ +From 40dc1497884e101331fa26a272fa13cb1686a007 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Oct 2022 18:57:41 +0900 +Subject: udf: Avoid double brelse() in udf_rename() + +From: Shigeru Yoshida + +[ Upstream commit c791730f2554a9ebb8f18df9368dc27d4ebc38c2 ] + +syzbot reported a warning like below [1]: + +VFS: brelse: Trying to free free buffer +WARNING: CPU: 2 PID: 7301 at fs/buffer.c:1145 __brelse+0x67/0xa0 +... +Call Trace: + + invalidate_bh_lru+0x99/0x150 + smp_call_function_many_cond+0xe2a/0x10c0 + ? generic_remap_file_range_prep+0x50/0x50 + ? __brelse+0xa0/0xa0 + ? __mutex_lock+0x21c/0x12d0 + ? smp_call_on_cpu+0x250/0x250 + ? rcu_read_lock_sched_held+0xb/0x60 + ? lock_release+0x587/0x810 + ? __brelse+0xa0/0xa0 + ? generic_remap_file_range_prep+0x50/0x50 + on_each_cpu_cond_mask+0x3c/0x80 + blkdev_flush_mapping+0x13a/0x2f0 + blkdev_put_whole+0xd3/0xf0 + blkdev_put+0x222/0x760 + deactivate_locked_super+0x96/0x160 + deactivate_super+0xda/0x100 + cleanup_mnt+0x222/0x3d0 + task_work_run+0x149/0x240 + ? task_work_cancel+0x30/0x30 + do_exit+0xb29/0x2a40 + ? reacquire_held_locks+0x4a0/0x4a0 + ? do_raw_spin_lock+0x12a/0x2b0 + ? mm_update_next_owner+0x7c0/0x7c0 + ? rwlock_bug.part.0+0x90/0x90 + ? zap_other_threads+0x234/0x2d0 + do_group_exit+0xd0/0x2a0 + __x64_sys_exit_group+0x3a/0x50 + do_syscall_64+0x34/0xb0 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +The cause of the issue is that brelse() is called on both ofibh.sbh +and ofibh.ebh by udf_find_entry() when it returns NULL. However, +brelse() is called by udf_rename(), too. So, b_count on buffer_head +becomes unbalanced. + +This patch fixes the issue by not calling brelse() by udf_rename() +when udf_find_entry() returns NULL. + +Link: https://syzkaller.appspot.com/bug?id=8297f45698159c6bca8a1f87dc983667c1a1c851 [1] +Reported-by: syzbot+7902cd7684bc35306224@syzkaller.appspotmail.com +Signed-off-by: Shigeru Yoshida +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20221023095741.271430-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + fs/udf/namei.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/fs/udf/namei.c b/fs/udf/namei.c +index 865e658535b1..0e30a50060d9 100644 +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -1091,8 +1091,9 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + return -EINVAL; + + ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); +- if (IS_ERR(ofi)) { +- retval = PTR_ERR(ofi); ++ if (!ofi || IS_ERR(ofi)) { ++ if (IS_ERR(ofi)) ++ retval = PTR_ERR(ofi); + goto end_rename; + } + +@@ -1101,8 +1102,7 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + + brelse(ofibh.sbh); + tloc = lelb_to_cpu(ocfi.icb.extLocation); +- if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) +- != old_inode->i_ino) ++ if (udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) + goto end_rename; + + nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi); +-- +2.35.1 + diff --git a/queue-5.15/uio-uio_dmem_genirq-fix-deadlock-between-irq-config-.patch b/queue-5.15/uio-uio_dmem_genirq-fix-deadlock-between-irq-config-.patch new file mode 100644 index 00000000000..24c8f70ce84 --- /dev/null +++ b/queue-5.15/uio-uio_dmem_genirq-fix-deadlock-between-irq-config-.patch @@ -0,0 +1,64 @@ +From a260c82f6a50c74727e9bf510903b6034a0e610a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 19:40:58 -0300 +Subject: uio: uio_dmem_genirq: Fix deadlock between irq config and handling + +From: Rafael Mendonca + +[ Upstream commit 118b918018175d9fcd8db667f905012e986cc2c9 ] + +This fixes a concurrency issue addressed in commit 34cb27528398 ("UIO: Fix +concurrency issue"): + + "In a SMP case there was a race condition issue between + Uio_pdrv_genirq_irqcontrol() running on one CPU and irq handler on + another CPU. Fix it by spin_locking shared resources access inside irq + handler." + +The implementation of "uio_dmem_genirq" was based on "uio_pdrv_genirq" and +it is used in a similar manner to the "uio_pdrv_genirq" driver with respect +to interrupt configuration and handling. At the time "uio_dmem_genirq" was +merged, both had the same implementation of the 'uio_info' handlers +irqcontrol() and handler(), thus, both had the same concurrency issue +mentioned by the above commit. However, the above patch was only applied to +the "uio_pdrv_genirq" driver. + +Split out from commit 34cb27528398 ("UIO: Fix concurrency issue"). + +Fixes: 0a0c3b5a24bd ("Add new uio device for dynamic memory allocation") +Signed-off-by: Rafael Mendonca +Link: https://lore.kernel.org/r/20220930224100.816175-3-rafaelmendsr@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/uio/uio_dmem_genirq.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c +index bfaedc324104..28be820b546e 100644 +--- a/drivers/uio/uio_dmem_genirq.c ++++ b/drivers/uio/uio_dmem_genirq.c +@@ -110,8 +110,10 @@ static irqreturn_t uio_dmem_genirq_handler(int irq, struct uio_info *dev_info) + * remember the state so we can allow user space to enable it later. + */ + ++ spin_lock(&priv->lock); + if (!test_and_set_bit(0, &priv->flags)) + disable_irq_nosync(irq); ++ spin_unlock(&priv->lock); + + return IRQ_HANDLED; + } +@@ -125,7 +127,8 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) + * in the interrupt controller, but keep track of the + * state to prevent per-irq depth damage. + * +- * Serialize this operation to support multiple tasks. ++ * Serialize this operation to support multiple tasks and concurrency ++ * with irq handler on SMP systems. + */ + + spin_lock_irqsave(&priv->lock, flags); +-- +2.35.1 + diff --git a/queue-5.15/uio-uio_dmem_genirq-fix-missing-unlock-in-irq-config.patch b/queue-5.15/uio-uio_dmem_genirq-fix-missing-unlock-in-irq-config.patch new file mode 100644 index 00000000000..a92263c3cb3 --- /dev/null +++ b/queue-5.15/uio-uio_dmem_genirq-fix-missing-unlock-in-irq-config.patch @@ -0,0 +1,127 @@ +From 940bf8d4086780b43eaace5b6122583a597bb268 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 19:40:57 -0300 +Subject: uio: uio_dmem_genirq: Fix missing unlock in irq configuration + +From: Rafael Mendonca + +[ Upstream commit 9de255c461d1b3f0242b3ad1450c3323a3e00b34 ] + +Commit b74351287d4b ("uio: fix a sleep-in-atomic-context bug in +uio_dmem_genirq_irqcontrol()") started calling disable_irq() without +holding the spinlock because it can sleep. However, that fix introduced +another bug: if interrupt is already disabled and a new disable request +comes in, then the spinlock is not unlocked: + +root@localhost:~# printf '\x00\x00\x00\x00' > /dev/uio0 +root@localhost:~# printf '\x00\x00\x00\x00' > /dev/uio0 +root@localhost:~# [ 14.851538] BUG: scheduling while atomic: bash/223/0x00000002 +[ 14.851991] Modules linked in: uio_dmem_genirq uio myfpga(OE) bochs drm_vram_helper drm_ttm_helper ttm drm_kms_helper drm snd_pcm ppdev joydev psmouse snd_timer snd e1000fb_sys_fops syscopyarea parport sysfillrect soundcore sysimgblt input_leds pcspkr i2c_piix4 serio_raw floppy evbug qemu_fw_cfg mac_hid pata_acpi ip_tables x_tables autofs4 [last unloaded: parport_pc] +[ 14.854206] CPU: 0 PID: 223 Comm: bash Tainted: G OE 6.0.0-rc7 #21 +[ 14.854786] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +[ 14.855664] Call Trace: +[ 14.855861] +[ 14.856025] dump_stack_lvl+0x4d/0x67 +[ 14.856325] dump_stack+0x14/0x1a +[ 14.856583] __schedule_bug.cold+0x4b/0x5c +[ 14.856915] __schedule+0xe81/0x13d0 +[ 14.857199] ? idr_find+0x13/0x20 +[ 14.857456] ? get_work_pool+0x2d/0x50 +[ 14.857756] ? __flush_work+0x233/0x280 +[ 14.858068] ? __schedule+0xa95/0x13d0 +[ 14.858307] ? idr_find+0x13/0x20 +[ 14.858519] ? get_work_pool+0x2d/0x50 +[ 14.858798] schedule+0x6c/0x100 +[ 14.859009] schedule_hrtimeout_range_clock+0xff/0x110 +[ 14.859335] ? tty_write_room+0x1f/0x30 +[ 14.859598] ? n_tty_poll+0x1ec/0x220 +[ 14.859830] ? tty_ldisc_deref+0x1a/0x20 +[ 14.860090] schedule_hrtimeout_range+0x17/0x20 +[ 14.860373] do_select+0x596/0x840 +[ 14.860627] ? __kernel_text_address+0x16/0x50 +[ 14.860954] ? poll_freewait+0xb0/0xb0 +[ 14.861235] ? poll_freewait+0xb0/0xb0 +[ 14.861517] ? rpm_resume+0x49d/0x780 +[ 14.861798] ? common_interrupt+0x59/0xa0 +[ 14.862127] ? asm_common_interrupt+0x2b/0x40 +[ 14.862511] ? __uart_start.isra.0+0x61/0x70 +[ 14.862902] ? __check_object_size+0x61/0x280 +[ 14.863255] core_sys_select+0x1c6/0x400 +[ 14.863575] ? vfs_write+0x1c9/0x3d0 +[ 14.863853] ? vfs_write+0x1c9/0x3d0 +[ 14.864121] ? _copy_from_user+0x45/0x70 +[ 14.864526] do_pselect.constprop.0+0xb3/0xf0 +[ 14.864893] ? do_syscall_64+0x6d/0x90 +[ 14.865228] ? do_syscall_64+0x6d/0x90 +[ 14.865556] __x64_sys_pselect6+0x76/0xa0 +[ 14.865906] do_syscall_64+0x60/0x90 +[ 14.866214] ? syscall_exit_to_user_mode+0x2a/0x50 +[ 14.866640] ? do_syscall_64+0x6d/0x90 +[ 14.866972] ? do_syscall_64+0x6d/0x90 +[ 14.867286] ? do_syscall_64+0x6d/0x90 +[ 14.867626] entry_SYSCALL_64_after_hwframe+0x63/0xcd +[...] stripped +[ 14.872959] + +('myfpga' is a simple 'uio_dmem_genirq' driver I wrote to test this) + +The implementation of "uio_dmem_genirq" was based on "uio_pdrv_genirq" and +it is used in a similar manner to the "uio_pdrv_genirq" driver with respect +to interrupt configuration and handling. At the time "uio_dmem_genirq" was +introduced, both had the same implementation of the 'uio_info' handlers +irqcontrol() and handler(). Then commit 34cb27528398 ("UIO: Fix concurrency +issue"), which was only applied to "uio_pdrv_genirq", ended up making them +a little different. That commit, among other things, changed disable_irq() +to disable_irq_nosync() in the implementation of irqcontrol(). The +motivation there was to avoid a deadlock between irqcontrol() and +handler(), since it added a spinlock in the irq handler, and disable_irq() +waits for the completion of the irq handler. + +By changing disable_irq() to disable_irq_nosync() in irqcontrol(), we also +avoid the sleeping-while-atomic bug that commit b74351287d4b ("uio: fix a +sleep-in-atomic-context bug in uio_dmem_genirq_irqcontrol()") was trying to +fix. Thus, this fixes the missing unlock in irqcontrol() by importing the +implementation of irqcontrol() handler from the "uio_pdrv_genirq" driver. +In the end, it reverts commit b74351287d4b ("uio: fix a +sleep-in-atomic-context bug in uio_dmem_genirq_irqcontrol()") and change +disable_irq() to disable_irq_nosync(). + +It is worth noting that this still does not address the concurrency issue +fixed by commit 34cb27528398 ("UIO: Fix concurrency issue"). It will be +addressed separately in the next commits. + +Split out from commit 34cb27528398 ("UIO: Fix concurrency issue"). + +Fixes: b74351287d4b ("uio: fix a sleep-in-atomic-context bug in uio_dmem_genirq_irqcontrol()") +Signed-off-by: Rafael Mendonca +Link: https://lore.kernel.org/r/20220930224100.816175-2-rafaelmendsr@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/uio/uio_dmem_genirq.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c +index 6b5cfa5b0673..bfaedc324104 100644 +--- a/drivers/uio/uio_dmem_genirq.c ++++ b/drivers/uio/uio_dmem_genirq.c +@@ -132,13 +132,11 @@ static int uio_dmem_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) + if (irq_on) { + if (test_and_clear_bit(0, &priv->flags)) + enable_irq(dev_info->irq); +- spin_unlock_irqrestore(&priv->lock, flags); + } else { +- if (!test_and_set_bit(0, &priv->flags)) { +- spin_unlock_irqrestore(&priv->lock, flags); +- disable_irq(dev_info->irq); +- } ++ if (!test_and_set_bit(0, &priv->flags)) ++ disable_irq_nosync(dev_info->irq); + } ++ spin_unlock_irqrestore(&priv->lock, flags); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.15/unix-fix-race-in-sock_seqpacket-s-unix_dgram_sendmsg.patch b/queue-5.15/unix-fix-race-in-sock_seqpacket-s-unix_dgram_sendmsg.patch new file mode 100644 index 00000000000..3f30ac96a15 --- /dev/null +++ b/queue-5.15/unix-fix-race-in-sock_seqpacket-s-unix_dgram_sendmsg.patch @@ -0,0 +1,86 @@ +From 7f63a953adf1a3a6668e80b36146036101272382 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 00:05:53 +0300 +Subject: unix: Fix race in SOCK_SEQPACKET's unix_dgram_sendmsg() + +From: Kirill Tkhai + +[ Upstream commit 3ff8bff704f4de125dca2262e5b5b963a3da1d87 ] + +There is a race resulting in alive SOCK_SEQPACKET socket +may change its state from TCP_ESTABLISHED to TCP_CLOSE: + +unix_release_sock(peer) unix_dgram_sendmsg(sk) + sock_orphan(peer) + sock_set_flag(peer, SOCK_DEAD) + sock_alloc_send_pskb() + if !(sk->sk_shutdown & SEND_SHUTDOWN) + OK + if sock_flag(peer, SOCK_DEAD) + sk->sk_state = TCP_CLOSE + sk->sk_shutdown = SHUTDOWN_MASK + +After that socket sk remains almost normal: it is able to connect, listen, accept +and recvmsg, while it can't sendmsg. + +Since this is the only possibility for alive SOCK_SEQPACKET to change +the state in such way, we should better fix this strange and potentially +danger corner case. + +Note, that we will return EPIPE here like this is normally done in sock_alloc_send_pskb(). +Originally used ECONNREFUSED looks strange, since it's strange to return +a specific retval in dependence of race in kernel, when user can't affect on this. + +Also, move TCP_CLOSE assignment for SOCK_DGRAM sockets under state lock +to fix race with unix_dgram_connect(): + +unix_dgram_connect(other) unix_dgram_sendmsg(sk) + unix_peer(sk) = NULL + unix_state_unlock(sk) + unix_state_double_lock(sk, other) + sk->sk_state = TCP_ESTABLISHED + unix_peer(sk) = other + unix_state_double_unlock(sk, other) + sk->sk_state = TCP_CLOSED + +This patch fixes both of these races. + +Fixes: 83301b5367a9 ("af_unix: Set TCP_ESTABLISHED for datagram sockets too") +Signed-off-by: Kirill Tkhai +Link: https://lore.kernel.org/r/135fda25-22d5-837a-782b-ceee50e19844@ya.ru +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 545823c1d5ed..0a59a00cb581 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1865,13 +1865,20 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, + unix_state_lock(sk); + + err = 0; +- if (unix_peer(sk) == other) { ++ if (sk->sk_type == SOCK_SEQPACKET) { ++ /* We are here only when racing with unix_release_sock() ++ * is clearing @other. Never change state to TCP_CLOSE ++ * unlike SOCK_DGRAM wants. ++ */ ++ unix_state_unlock(sk); ++ err = -EPIPE; ++ } else if (unix_peer(sk) == other) { + unix_peer(sk) = NULL; + unix_dgram_peer_wake_disconnect_wakeup(sk, other); + ++ sk->sk_state = TCP_CLOSE; + unix_state_unlock(sk); + +- sk->sk_state = TCP_CLOSE; + unix_dgram_disconnected(sk, other); + sock_put(other); + err = -ECONNREFUSED; +-- +2.35.1 + diff --git a/queue-5.15/uprobes-x86-allow-to-probe-a-nop-instruction-with-0x.patch b/queue-5.15/uprobes-x86-allow-to-probe-a-nop-instruction-with-0x.patch new file mode 100644 index 00000000000..892d54244b2 --- /dev/null +++ b/queue-5.15/uprobes-x86-allow-to-probe-a-nop-instruction-with-0x.patch @@ -0,0 +1,53 @@ +From 7daab246ea90ffd1087d6e57cd71fabac7b8cecb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Dec 2022 18:39:33 +0100 +Subject: uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix + +From: Oleg Nesterov + +[ Upstream commit cefa72129e45313655d53a065b8055aaeb01a0c9 ] + +Intel ICC -hotpatch inserts 2-byte "0x66 0x90" NOP at the start of each +function to reserve extra space for hot-patching, and currently it is not +possible to probe these functions because branch_setup_xol_ops() wrongly +rejects NOP with REP prefix as it treats them like word-sized branch +instructions. + +Fixes: 250bbd12c2fe ("uprobes/x86: Refuse to attach uprobe to "word-sized" branch insns") +Reported-by: Seiji Nishikawa +Suggested-by: Denys Vlasenko +Signed-off-by: Oleg Nesterov +Signed-off-by: Thomas Gleixner +Acked-by: Masami Hiramatsu (Google) +Link: https://lore.kernel.org/r/20221204173933.GA31544@redhat.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/uprobes.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c +index b63cf8f7745e..6c07f6daaa22 100644 +--- a/arch/x86/kernel/uprobes.c ++++ b/arch/x86/kernel/uprobes.c +@@ -722,8 +722,9 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) + switch (opc1) { + case 0xeb: /* jmp 8 */ + case 0xe9: /* jmp 32 */ +- case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */ + break; ++ case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */ ++ goto setup; + + case 0xe8: /* call relative */ + branch_clear_offset(auprobe, insn); +@@ -753,6 +754,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) + return -ENOTSUPP; + } + ++setup: + auprobe->branch.opc1 = opc1; + auprobe->branch.ilen = insn->length; + auprobe->branch.offs = insn->immediate.value; +-- +2.35.1 + diff --git a/queue-5.15/usb-fotg210-udc-fix-ages-old-endianness-issues.patch b/queue-5.15/usb-fotg210-udc-fix-ages-old-endianness-issues.patch new file mode 100644 index 00000000000..07886170295 --- /dev/null +++ b/queue-5.15/usb-fotg210-udc-fix-ages-old-endianness-issues.patch @@ -0,0 +1,71 @@ +From 52e562e5ff48e1f1076b3f9ca44fcee1a9bf96b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 11 Nov 2022 10:03:17 +0100 +Subject: usb: fotg210-udc: Fix ages old endianness issues + +From: Linus Walleij + +[ Upstream commit 46ed6026ca2181c917c8334a82e3eaf40a6234dd ] + +The code in the FOTG210 driver isn't entirely endianness-agnostic +as reported by the kernel robot sparse testing. This came to +the surface while moving the files around. + +The driver is only used on little-endian systems, so this causes +no real-world regression, but it is nice to be strict and have +some compile coverage also on big endian machines, so fix it +up with the right LE accessors. + +Fixes: b84a8dee23fd ("usb: gadget: add Faraday fotg210_udc driver") +Reported-by: kernel test robot +Link: https://lore.kernel.org/linux-usb/202211110910.0dJ7nZCn-lkp@intel.com/ +Signed-off-by: Linus Walleij +Link: https://lore.kernel.org/r/20221111090317.94228-1-linus.walleij@linaro.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/udc/fotg210-udc.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c +index fdca28e72a3b..d0e051beb3af 100644 +--- a/drivers/usb/gadget/udc/fotg210-udc.c ++++ b/drivers/usb/gadget/udc/fotg210-udc.c +@@ -629,10 +629,10 @@ static void fotg210_request_error(struct fotg210_udc *fotg210) + static void fotg210_set_address(struct fotg210_udc *fotg210, + struct usb_ctrlrequest *ctrl) + { +- if (ctrl->wValue >= 0x0100) { ++ if (le16_to_cpu(ctrl->wValue) >= 0x0100) { + fotg210_request_error(fotg210); + } else { +- fotg210_set_dev_addr(fotg210, ctrl->wValue); ++ fotg210_set_dev_addr(fotg210, le16_to_cpu(ctrl->wValue)); + fotg210_set_cxdone(fotg210); + } + } +@@ -713,17 +713,17 @@ static void fotg210_get_status(struct fotg210_udc *fotg210, + + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_DEVICE: +- fotg210->ep0_data = 1 << USB_DEVICE_SELF_POWERED; ++ fotg210->ep0_data = cpu_to_le16(1 << USB_DEVICE_SELF_POWERED); + break; + case USB_RECIP_INTERFACE: +- fotg210->ep0_data = 0; ++ fotg210->ep0_data = cpu_to_le16(0); + break; + case USB_RECIP_ENDPOINT: + epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK; + if (epnum) + fotg210->ep0_data = +- fotg210_is_epnstall(fotg210->ep[epnum]) +- << USB_ENDPOINT_HALT; ++ cpu_to_le16(fotg210_is_epnstall(fotg210->ep[epnum]) ++ << USB_ENDPOINT_HALT); + else + fotg210_request_error(fotg210); + break; +-- +2.35.1 + diff --git a/queue-5.15/usb-gadget-f_hid-fix-f_hidg-lifetime-vs-cdev.patch b/queue-5.15/usb-gadget-f_hid-fix-f_hidg-lifetime-vs-cdev.patch new file mode 100644 index 00000000000..e5db1ef231e --- /dev/null +++ b/queue-5.15/usb-gadget-f_hid-fix-f_hidg-lifetime-vs-cdev.patch @@ -0,0 +1,164 @@ +From 61636cf379071b6f8c17306e7443e82c8a200a68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 12:35:21 +0000 +Subject: usb: gadget: f_hid: fix f_hidg lifetime vs cdev + +From: John Keeping + +[ Upstream commit 89ff3dfac604614287ad5aad9370c3f984ea3f4b ] + +The embedded struct cdev does not have its lifetime correctly tied to +the enclosing struct f_hidg, so there is a use-after-free if /dev/hidgN +is held open while the gadget is deleted. + +This can readily be replicated with libusbgx's example programs (for +conciseness - operating directly via configfs is equivalent): + + gadget-hid + exec 3<> /dev/hidg0 + gadget-vid-pid-remove + exec 3<&- + +Pull the existing device up in to struct f_hidg and make use of the +cdev_device_{add,del}() helpers. This changes the lifetime of the +device object to match struct f_hidg, but note that it is still added +and deleted at the same time. + +Fixes: 71adf1189469 ("USB: gadget: add HID gadget driver") +Tested-by: Lee Jones +Reviewed-by: Andrzej Pietrasiewicz +Reviewed-by: Lee Jones +Signed-off-by: John Keeping +Link: https://lore.kernel.org/r/20221122123523.3068034-2-john@metanate.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/f_hid.c | 52 ++++++++++++++++------------- + 1 file changed, 28 insertions(+), 24 deletions(-) + +diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c +index ca0a7d9eaa34..8b8bbeaa27cb 100644 +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -71,7 +71,7 @@ struct f_hidg { + wait_queue_head_t write_queue; + struct usb_request *req; + +- int minor; ++ struct device dev; + struct cdev cdev; + struct usb_function func; + +@@ -84,6 +84,14 @@ static inline struct f_hidg *func_to_hidg(struct usb_function *f) + return container_of(f, struct f_hidg, func); + } + ++static void hidg_release(struct device *dev) ++{ ++ struct f_hidg *hidg = container_of(dev, struct f_hidg, dev); ++ ++ kfree(hidg->set_report_buf); ++ kfree(hidg); ++} ++ + /*-------------------------------------------------------------------------*/ + /* Static descriptors */ + +@@ -904,9 +912,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) + struct usb_ep *ep; + struct f_hidg *hidg = func_to_hidg(f); + struct usb_string *us; +- struct device *device; + int status; +- dev_t dev; + + /* maybe allocate device-global string IDs, and patch descriptors */ + us = usb_gstrings_attach(c->cdev, ct_func_strings, +@@ -999,21 +1005,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) + + /* create char device */ + cdev_init(&hidg->cdev, &f_hidg_fops); +- dev = MKDEV(major, hidg->minor); +- status = cdev_add(&hidg->cdev, dev, 1); ++ status = cdev_device_add(&hidg->cdev, &hidg->dev); + if (status) + goto fail_free_descs; + +- device = device_create(hidg_class, NULL, dev, NULL, +- "%s%d", "hidg", hidg->minor); +- if (IS_ERR(device)) { +- status = PTR_ERR(device); +- goto del; +- } +- + return 0; +-del: +- cdev_del(&hidg->cdev); + fail_free_descs: + usb_free_all_descriptors(f); + fail: +@@ -1244,9 +1240,7 @@ static void hidg_free(struct usb_function *f) + + hidg = func_to_hidg(f); + opts = container_of(f->fi, struct f_hid_opts, func_inst); +- kfree(hidg->report_desc); +- kfree(hidg->set_report_buf); +- kfree(hidg); ++ put_device(&hidg->dev); + mutex_lock(&opts->lock); + --opts->refcnt; + mutex_unlock(&opts->lock); +@@ -1256,8 +1250,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) + { + struct f_hidg *hidg = func_to_hidg(f); + +- device_destroy(hidg_class, MKDEV(major, hidg->minor)); +- cdev_del(&hidg->cdev); ++ cdev_device_del(&hidg->cdev, &hidg->dev); + + usb_free_all_descriptors(f); + } +@@ -1266,6 +1259,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) + { + struct f_hidg *hidg; + struct f_hid_opts *opts; ++ int ret; + + /* allocate and initialize one new instance */ + hidg = kzalloc(sizeof(*hidg), GFP_KERNEL); +@@ -1277,17 +1271,27 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) + mutex_lock(&opts->lock); + ++opts->refcnt; + +- hidg->minor = opts->minor; ++ device_initialize(&hidg->dev); ++ hidg->dev.release = hidg_release; ++ hidg->dev.class = hidg_class; ++ hidg->dev.devt = MKDEV(major, opts->minor); ++ ret = dev_set_name(&hidg->dev, "hidg%d", opts->minor); ++ if (ret) { ++ --opts->refcnt; ++ mutex_unlock(&opts->lock); ++ return ERR_PTR(ret); ++ } ++ + hidg->bInterfaceSubClass = opts->subclass; + hidg->bInterfaceProtocol = opts->protocol; + hidg->report_length = opts->report_length; + hidg->report_desc_length = opts->report_desc_length; + if (opts->report_desc) { +- hidg->report_desc = kmemdup(opts->report_desc, +- opts->report_desc_length, +- GFP_KERNEL); ++ hidg->report_desc = devm_kmemdup(&hidg->dev, opts->report_desc, ++ opts->report_desc_length, ++ GFP_KERNEL); + if (!hidg->report_desc) { +- kfree(hidg); ++ put_device(&hidg->dev); + mutex_unlock(&opts->lock); + return ERR_PTR(-ENOMEM); + } +-- +2.35.1 + diff --git a/queue-5.15/usb-gadget-f_hid-fix-refcount-leak-on-error-path.patch b/queue-5.15/usb-gadget-f_hid-fix-refcount-leak-on-error-path.patch new file mode 100644 index 00000000000..0f89c737b58 --- /dev/null +++ b/queue-5.15/usb-gadget-f_hid-fix-refcount-leak-on-error-path.patch @@ -0,0 +1,40 @@ +From 98ca6b6723a95464fafb93c7d1ad81f494ba2eb9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 12:35:22 +0000 +Subject: usb: gadget: f_hid: fix refcount leak on error path + +From: John Keeping + +[ Upstream commit 70a3288a7586526315105c699b687d78cd32559a ] + +When failing to allocate report_desc, opts->refcnt has already been +incremented so it needs to be decremented to avoid leaving the options +structure permanently locked. + +Fixes: 21a9476a7ba8 ("usb: gadget: hid: add configfs support") +Tested-by: Lee Jones +Reviewed-by: Andrzej Pietrasiewicz +Reviewed-by: Lee Jones +Signed-off-by: John Keeping +Link: https://lore.kernel.org/r/20221122123523.3068034-3-john@metanate.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/f_hid.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c +index 8b8bbeaa27cb..6be6009f911e 100644 +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -1292,6 +1292,7 @@ static struct usb_function *hidg_alloc(struct usb_function_instance *fi) + GFP_KERNEL); + if (!hidg->report_desc) { + put_device(&hidg->dev); ++ --opts->refcnt; + mutex_unlock(&opts->lock); + return ERR_PTR(-ENOMEM); + } +-- +2.35.1 + diff --git a/queue-5.15/usb-musb-remove-extra-check-in-musb_gadget_vbus_draw.patch b/queue-5.15/usb-musb-remove-extra-check-in-musb_gadget_vbus_draw.patch new file mode 100644 index 00000000000..2cd089f2307 --- /dev/null +++ b/queue-5.15/usb-musb-remove-extra-check-in-musb_gadget_vbus_draw.patch @@ -0,0 +1,47 @@ +From 52717286c2a08e82fa051f0ef727cfd52884dcfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 20:21:15 +0200 +Subject: usb: musb: remove extra check in musb_gadget_vbus_draw + +From: Ivaylo Dimitrov + +[ Upstream commit ecec4b20d29c3d6922dafe7d2555254a454272d2 ] + +The checks for musb->xceiv and musb->xceiv->set_power duplicate those in +usb_phy_set_power(), so there is no need of them. Moreover, not calling +usb_phy_set_power() results in usb_phy_set_charger_current() not being +called, so current USB config max current is not propagated through USB +charger framework and charger drivers may try to draw more current than +allowed or possible. + +Fix that by removing those extra checks and calling usb_phy_set_power() +directly. + +Tested on Motorola Droid4 and Nokia N900 + +Fixes: a9081a008f84 ("usb: phy: Add USB charger support") +Cc: stable +Signed-off-by: Ivaylo Dimitrov +Link: https://lore.kernel.org/r/1669400475-4762-1-git-send-email-ivo.g.dimitrov.75@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/musb/musb_gadget.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index dc67fff8e941..22c3df49ba8a 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -1628,8 +1628,6 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) + { + struct musb *musb = gadget_to_musb(gadget); + +- if (!musb->xceiv->set_power) +- return -EOPNOTSUPP; + return usb_phy_set_power(musb->xceiv, mA); + } + +-- +2.35.1 + diff --git a/queue-5.15/usb-roles-fix-of-node-refcount-leak-in-usb_role_swit.patch b/queue-5.15/usb-roles-fix-of-node-refcount-leak-in-usb_role_swit.patch new file mode 100644 index 00000000000..f182f01ff89 --- /dev/null +++ b/queue-5.15/usb-roles-fix-of-node-refcount-leak-in-usb_role_swit.patch @@ -0,0 +1,51 @@ +From 2a8a629911e93183d010d3911f5d93c26bc2b649 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Nov 2022 19:12:26 +0800 +Subject: usb: roles: fix of node refcount leak in usb_role_switch_is_parent() + +From: Yang Yingliang + +[ Upstream commit 1ab30c610630da5391a373cddb8a065bf4c4bc01 ] + +I got the following report while doing device(mt6370-tcpc) load +test with CONFIG_OF_UNITTEST and CONFIG_OF_DYNAMIC enabled: + + OF: ERROR: memory leak, expected refcount 1 instead of 2, + of_node_get()/of_node_put() unbalanced - destroy cset entry: + attach overlay node /i2c/pmic@34 + +The 'parent' returned by fwnode_get_parent() with refcount incremented. +it needs be put after using. + +Fixes: 6fadd72943b8 ("usb: roles: get usb-role-switch from parent") +Reviewed-by: Heikki Krogerus +Signed-off-by: Yang Yingliang +Link: https://lore.kernel.org/r/20221122111226.251588-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/roles/class.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c +index dfaed7eee94f..32e6d19f7011 100644 +--- a/drivers/usb/roles/class.c ++++ b/drivers/usb/roles/class.c +@@ -106,10 +106,13 @@ usb_role_switch_is_parent(struct fwnode_handle *fwnode) + struct fwnode_handle *parent = fwnode_get_parent(fwnode); + struct device *dev; + +- if (!parent || !fwnode_property_present(parent, "usb-role-switch")) ++ if (!fwnode_property_present(parent, "usb-role-switch")) { ++ fwnode_handle_put(parent); + return NULL; ++ } + + dev = class_find_device_by_fwnode(role_class, parent); ++ fwnode_handle_put(parent); + return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER); + } + +-- +2.35.1 + diff --git a/queue-5.15/usb-storage-add-check-for-kcalloc.patch b/queue-5.15/usb-storage-add-check-for-kcalloc.patch new file mode 100644 index 00000000000..31905041561 --- /dev/null +++ b/queue-5.15/usb-storage-add-check-for-kcalloc.patch @@ -0,0 +1,39 @@ +From 52dc012d9d521f50dd75c2873b0fc87755e3b0a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Dec 2022 19:00:58 +0800 +Subject: usb: storage: Add check for kcalloc + +From: Jiasheng Jiang + +[ Upstream commit c35ca10f53c51eeb610d3f8fbc6dd6d511b58a58 ] + +As kcalloc may return NULL pointer, the return value should +be checked and return error if fails as same as the ones in +alauda_read_map. + +Fixes: e80b0fade09e ("[PATCH] USB Storage: add alauda support") +Acked-by: Alan Stern +Signed-off-by: Jiasheng Jiang +Link: https://lore.kernel.org/r/20221208110058.12983-1-jiasheng@iscas.ac.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/storage/alauda.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c +index 20b857e97e60..7e4ce0e7e05a 100644 +--- a/drivers/usb/storage/alauda.c ++++ b/drivers/usb/storage/alauda.c +@@ -438,6 +438,8 @@ static int alauda_init_media(struct us_data *us) + + MEDIA_INFO(us).blockshift + MEDIA_INFO(us).pageshift); + MEDIA_INFO(us).pba_to_lba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); + MEDIA_INFO(us).lba_to_pba = kcalloc(num_zones, sizeof(u16*), GFP_NOIO); ++ if (MEDIA_INFO(us).pba_to_lba == NULL || MEDIA_INFO(us).lba_to_pba == NULL) ++ return USB_STOR_TRANSPORT_ERROR; + + if (alauda_reset_media(us) != USB_STOR_XFER_GOOD) + return USB_STOR_TRANSPORT_ERROR; +-- +2.35.1 + diff --git a/queue-5.15/usb-typec-check-for-ops-exit-instead-of-ops-enter-in.patch b/queue-5.15/usb-typec-check-for-ops-exit-instead-of-ops-enter-in.patch new file mode 100644 index 00000000000..a63a50b4cb3 --- /dev/null +++ b/queue-5.15/usb-typec-check-for-ops-exit-instead-of-ops-enter-in.patch @@ -0,0 +1,39 @@ +From ecdd5be7fddfda52185518bb34426ab8adb3592f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 17:59:24 +0100 +Subject: usb: typec: Check for ops->exit instead of ops->enter in altmode_exit + +From: Sven Peter + +[ Upstream commit b6ddd180e3d9f92c1e482b3cdeec7dda086b1341 ] + +typec_altmode_exit checks if ops->enter is not NULL but then calls +ops->exit a few lines below. Fix that and check for the function +pointer it's about to call instead. + +Fixes: 8a37d87d72f0 ("usb: typec: Bus type for alternate modes") +Signed-off-by: Sven Peter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20221114165924.33487-1-sven@svenpeter.dev +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/typec/bus.c b/drivers/usb/typec/bus.c +index 78e0e78954f2..0aefb9e14f22 100644 +--- a/drivers/usb/typec/bus.c ++++ b/drivers/usb/typec/bus.c +@@ -134,7 +134,7 @@ int typec_altmode_exit(struct typec_altmode *adev) + if (!adev || !adev->active) + return 0; + +- if (!pdev->ops || !pdev->ops->enter) ++ if (!pdev->ops || !pdev->ops->exit) + return -EOPNOTSUPP; + + /* Moving to USB Safe State */ +-- +2.35.1 + diff --git a/queue-5.15/usb-typec-factor-out-non-pd-fwnode-properties.patch b/queue-5.15/usb-typec-factor-out-non-pd-fwnode-properties.patch new file mode 100644 index 00000000000..e043a77a4f4 --- /dev/null +++ b/queue-5.15/usb-typec-factor-out-non-pd-fwnode-properties.patch @@ -0,0 +1,150 @@ +From 6d3caddd3abfcedab14f48ffe0f7fa6ff0f1f663 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 13 Feb 2022 23:01:16 -0600 +Subject: usb: typec: Factor out non-PD fwnode properties + +From: Samuel Holland + +[ Upstream commit 2e7dfb0e9cacad0f1adbc4b97f0b96ba35027f24 ] + +Basic programmable non-PD Type-C port controllers do not need the full +TCPM library, but they share the same devicetree binding and the same +typec_capability structure. Factor out a helper for parsing those +properties which map to fields in struct typec_capability, so the code +can be shared between TCPM and basic non-TCPM drivers. + +Reviewed-by: Heikki Krogerus +Signed-off-by: Samuel Holland +Link: https://lore.kernel.org/r/20220214050118.61015-4-samuel@sholland.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 581c848b610d ("extcon: usbc-tusb320: Update state on probe even if no IRQ pending") +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/class.c | 43 +++++++++++++++++++++++++++++++++++ + drivers/usb/typec/tcpm/tcpm.c | 24 +------------------ + include/linux/usb/typec.h | 3 +++ + 3 files changed, 47 insertions(+), 23 deletions(-) + +diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c +index ff6c14d7b1a8..339752fef65e 100644 +--- a/drivers/usb/typec/class.c ++++ b/drivers/usb/typec/class.c +@@ -1895,6 +1895,49 @@ void *typec_get_drvdata(struct typec_port *port) + } + EXPORT_SYMBOL_GPL(typec_get_drvdata); + ++int typec_get_fw_cap(struct typec_capability *cap, ++ struct fwnode_handle *fwnode) ++{ ++ const char *cap_str; ++ int ret; ++ ++ cap->fwnode = fwnode; ++ ++ ret = fwnode_property_read_string(fwnode, "power-role", &cap_str); ++ if (ret < 0) ++ return ret; ++ ++ ret = typec_find_port_power_role(cap_str); ++ if (ret < 0) ++ return ret; ++ cap->type = ret; ++ ++ /* USB data support is optional */ ++ ret = fwnode_property_read_string(fwnode, "data-role", &cap_str); ++ if (ret == 0) { ++ ret = typec_find_port_data_role(cap_str); ++ if (ret < 0) ++ return ret; ++ cap->data = ret; ++ } ++ ++ /* Get the preferred power role for a DRP */ ++ if (cap->type == TYPEC_PORT_DRP) { ++ cap->prefer_role = TYPEC_NO_PREFERRED_ROLE; ++ ++ ret = fwnode_property_read_string(fwnode, "try-power-role", &cap_str); ++ if (ret == 0) { ++ ret = typec_find_power_role(cap_str); ++ if (ret < 0) ++ return ret; ++ cap->prefer_role = ret; ++ } ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(typec_get_fw_cap); ++ + /** + * typec_port_register_altmode - Register USB Type-C Port Alternate Mode + * @port: USB Type-C Port that supports the alternate mode +diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c +index 33aadc0a29ea..984a13a9efc2 100644 +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -5928,7 +5928,6 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, + struct fwnode_handle *fwnode) + { + const char *opmode_str; +- const char *cap_str; + int ret; + u32 mw, frs_current; + +@@ -5944,23 +5943,10 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, + */ + fw_devlink_purge_absent_suppliers(fwnode); + +- /* USB data support is optional */ +- ret = fwnode_property_read_string(fwnode, "data-role", &cap_str); +- if (ret == 0) { +- ret = typec_find_port_data_role(cap_str); +- if (ret < 0) +- return ret; +- port->typec_caps.data = ret; +- } +- +- ret = fwnode_property_read_string(fwnode, "power-role", &cap_str); ++ ret = typec_get_fw_cap(&port->typec_caps, fwnode); + if (ret < 0) + return ret; + +- ret = typec_find_port_power_role(cap_str); +- if (ret < 0) +- return ret; +- port->typec_caps.type = ret; + port->port_type = port->typec_caps.type; + port->pd_supported = !fwnode_property_read_bool(fwnode, "pd-disable"); + +@@ -5997,14 +5983,6 @@ static int tcpm_fw_get_caps(struct tcpm_port *port, + if (port->port_type == TYPEC_PORT_SRC) + return 0; + +- /* Get the preferred power role for DRP */ +- ret = fwnode_property_read_string(fwnode, "try-power-role", &cap_str); +- if (ret < 0) +- return ret; +- +- port->typec_caps.prefer_role = typec_find_power_role(cap_str); +- if (port->typec_caps.prefer_role < 0) +- return -EINVAL; + sink: + port->self_powered = fwnode_property_read_bool(fwnode, "self-powered"); + +diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h +index e2e44bb1dad8..c1e5910809ad 100644 +--- a/include/linux/usb/typec.h ++++ b/include/linux/usb/typec.h +@@ -295,6 +295,9 @@ int typec_set_mode(struct typec_port *port, int mode); + + void *typec_get_drvdata(struct typec_port *port); + ++int typec_get_fw_cap(struct typec_capability *cap, ++ struct fwnode_handle *fwnode); ++ + int typec_find_pwr_opmode(const char *name); + int typec_find_orientation(const char *name); + int typec_find_port_power_role(const char *name); +-- +2.35.1 + diff --git a/queue-5.15/usb-typec-tcpci-fix-of-node-refcount-leak-in-tcpci_r.patch b/queue-5.15/usb-typec-tcpci-fix-of-node-refcount-leak-in-tcpci_r.patch new file mode 100644 index 00000000000..011e124b0d5 --- /dev/null +++ b/queue-5.15/usb-typec-tcpci-fix-of-node-refcount-leak-in-tcpci_r.patch @@ -0,0 +1,60 @@ +From 2039768432c8b544f7efee1b51c3ae83b70f6812 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Nov 2022 14:24:16 +0800 +Subject: usb: typec: tcpci: fix of node refcount leak in tcpci_register_port() + +From: Yang Yingliang + +[ Upstream commit 0384e87e3fec735e47f1c133c796f32ef7a72a9b ] + +I got the following report while doing device(mt6370-tcpc) load +test with CONFIG_OF_UNITTEST and CONFIG_OF_DYNAMIC enabled: + + OF: ERROR: memory leak, expected refcount 1 instead of 2, + of_node_get()/of_node_put() unbalanced - destroy cset entry: + attach overlay node /i2c/pmic@34/tcpc/connector + +The 'fwnode' set in tcpci_parse_config() which is called +in tcpci_register_port(), its node refcount is increased +in device_get_named_child_node(). It needs be put while +exiting, so call fwnode_handle_put() in the error path of +tcpci_register_port() and in tcpci_unregister_port() to +avoid leak. + +Fixes: 5e85a04c8c0d ("usb: typec: add fwnode to tcpc") +Signed-off-by: Yang Yingliang +Acked-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20221121062416.1026192-1-yangyingliang@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/tcpm/tcpci.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c +index 64e248117c41..5340a3a3a81b 100644 +--- a/drivers/usb/typec/tcpm/tcpci.c ++++ b/drivers/usb/typec/tcpm/tcpci.c +@@ -817,8 +817,10 @@ struct tcpci *tcpci_register_port(struct device *dev, struct tcpci_data *data) + return ERR_PTR(err); + + tcpci->port = tcpm_register_port(tcpci->dev, &tcpci->tcpc); +- if (IS_ERR(tcpci->port)) ++ if (IS_ERR(tcpci->port)) { ++ fwnode_handle_put(tcpci->tcpc.fwnode); + return ERR_CAST(tcpci->port); ++ } + + return tcpci; + } +@@ -827,6 +829,7 @@ EXPORT_SYMBOL_GPL(tcpci_register_port); + void tcpci_unregister_port(struct tcpci *tcpci) + { + tcpm_unregister_port(tcpci->port); ++ fwnode_handle_put(tcpci->tcpc.fwnode); + } + EXPORT_SYMBOL_GPL(tcpci_unregister_port); + +-- +2.35.1 + diff --git a/queue-5.15/usb-typec-tipd-cleanup-resources-if-devm_tps6598_psy.patch b/queue-5.15/usb-typec-tipd-cleanup-resources-if-devm_tps6598_psy.patch new file mode 100644 index 00000000000..f156f3970c3 --- /dev/null +++ b/queue-5.15/usb-typec-tipd-cleanup-resources-if-devm_tps6598_psy.patch @@ -0,0 +1,39 @@ +From 2aba93585e27b9ebb9a702235821b1475c744d4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 18:44:46 +0100 +Subject: usb: typec: tipd: Cleanup resources if devm_tps6598_psy_register + fails + +From: Sven Peter + +[ Upstream commit 19c220e9ab00f50edefb9667e3101e84a5112df2 ] + +We can't just return if devm_tps6598_psy_register fails since previous +resources are not devres managed and have yet to be cleaned up. + +Fixes: 10eb0b6ac63a ("usb: typec: tps6598x: Export some power supply properties") +Signed-off-by: Sven Peter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20221114174449.34634-1-sven@svenpeter.dev +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/tipd/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +index 23a8b9b0b1fe..dd35b3ee2c5a 100644 +--- a/drivers/usb/typec/tipd/core.c ++++ b/drivers/usb/typec/tipd/core.c +@@ -684,7 +684,7 @@ static int tps6598x_probe(struct i2c_client *client) + + ret = devm_tps6598_psy_register(tps); + if (ret) +- return ret; ++ goto err_role_put; + + tps->port = typec_register_port(&client->dev, &typec_cap); + if (IS_ERR(tps->port)) { +-- +2.35.1 + diff --git a/queue-5.15/usb-typec-tipd-fix-spurious-fwnode_handle_put-in-err.patch b/queue-5.15/usb-typec-tipd-fix-spurious-fwnode_handle_put-in-err.patch new file mode 100644 index 00000000000..1d3554ad5a0 --- /dev/null +++ b/queue-5.15/usb-typec-tipd-fix-spurious-fwnode_handle_put-in-err.patch @@ -0,0 +1,47 @@ +From db987468a3a571331cf7d42056c6d04a77a8dec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 14 Nov 2022 18:44:47 +0100 +Subject: usb: typec: tipd: Fix spurious fwnode_handle_put in error path + +From: Sven Peter + +[ Upstream commit 782c70edc4852a5d39be12377a85501546236212 ] + +The err_role_put error path always calls fwnode_handle_put to release +the fwnode. This path can be reached after probe itself has already +released that fwnode though. Fix that by moving fwnode_handle_put in the +happy path to the very end. + +Fixes: 18a6c866bb19 ("usb: typec: tps6598x: Add USB role switching logic") +Signed-off-by: Sven Peter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20221114174449.34634-2-sven@svenpeter.dev +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/tipd/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c +index dd35b3ee2c5a..2f32c3fceef8 100644 +--- a/drivers/usb/typec/tipd/core.c ++++ b/drivers/usb/typec/tipd/core.c +@@ -691,7 +691,6 @@ static int tps6598x_probe(struct i2c_client *client) + ret = PTR_ERR(tps->port); + goto err_role_put; + } +- fwnode_handle_put(fwnode); + + if (status & TPS_STATUS_PLUG_PRESENT) { + ret = tps6598x_connect(tps, status); +@@ -710,6 +709,7 @@ static int tps6598x_probe(struct i2c_client *client) + } + + i2c_set_clientdata(client, tps); ++ fwnode_handle_put(fwnode); + + return 0; + +-- +2.35.1 + diff --git a/queue-5.15/venus-pm_helpers-fix-error-check-in-vcodec_domains_g.patch b/queue-5.15/venus-pm_helpers-fix-error-check-in-vcodec_domains_g.patch new file mode 100644 index 00000000000..cc5e40bd45a --- /dev/null +++ b/queue-5.15/venus-pm_helpers-fix-error-check-in-vcodec_domains_g.patch @@ -0,0 +1,38 @@ +From 201fe1e9f93138f60e262eefbabf15324c342699 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 14:37:00 +0800 +Subject: venus: pm_helpers: Fix error check in vcodec_domains_get() + +From: Tang Bin + +[ Upstream commit 0f6e8d8c94a82e85e1b9b62a7671990740dc6f70 ] + +In the function vcodec_domains_get(), dev_pm_domain_attach_by_name() +may return NULL in some cases, so IS_ERR() doesn't meet the +requirements. Thus fix it. + +Fixes: 7482a983dea3 ("media: venus: redesign clocks and pm domains control") +Signed-off-by: Tang Bin +Signed-off-by: Sasha Levin +--- + drivers/media/platform/qcom/venus/pm_helpers.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c +index 03fc82cb3fea..055513a7301f 100644 +--- a/drivers/media/platform/qcom/venus/pm_helpers.c ++++ b/drivers/media/platform/qcom/venus/pm_helpers.c +@@ -869,8 +869,8 @@ static int vcodec_domains_get(struct venus_core *core) + for (i = 0; i < res->vcodec_pmdomains_num; i++) { + pd = dev_pm_domain_attach_by_name(dev, + res->vcodec_pmdomains[i]); +- if (IS_ERR(pd)) +- return PTR_ERR(pd); ++ if (IS_ERR_OR_NULL(pd)) ++ return PTR_ERR(pd) ? : -ENODATA; + core->pmdomains[i] = pd; + } + +-- +2.35.1 + diff --git a/queue-5.15/vfio-platform-do-not-pass-return-buffer-to-acpi-_rst.patch b/queue-5.15/vfio-platform-do-not-pass-return-buffer-to-acpi-_rst.patch new file mode 100644 index 00000000000..263e2c86df3 --- /dev/null +++ b/queue-5.15/vfio-platform-do-not-pass-return-buffer-to-acpi-_rst.patch @@ -0,0 +1,43 @@ +From 8c0681198cd7745211ab749d9571147d1dfdf13f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Oct 2022 12:28:25 -0300 +Subject: vfio: platform: Do not pass return buffer to ACPI _RST method + +From: Rafael Mendonca + +[ Upstream commit e67e070632a665c932d534b8b800477bb3111449 ] + +The ACPI _RST method has no return value, there's no need to pass a return +buffer to acpi_evaluate_object(). + +Fixes: d30daa33ec1d ("vfio: platform: call _RST method when using ACPI") +Signed-off-by: Rafael Mendonca +Reviewed-by: Eric Auger +Link: https://lore.kernel.org/r/20221018152825.891032-1-rafaelmendsr@gmail.com +Signed-off-by: Alex Williamson +Signed-off-by: Sasha Levin +--- + drivers/vfio/platform/vfio_platform_common.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c +index 6af7ce7d619c..701bd99a8719 100644 +--- a/drivers/vfio/platform/vfio_platform_common.c ++++ b/drivers/vfio/platform/vfio_platform_common.c +@@ -72,12 +72,11 @@ static int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev, + const char **extra_dbg) + { + #ifdef CONFIG_ACPI +- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct device *dev = vdev->device; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_status acpi_ret; + +- acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, &buffer); ++ acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, NULL); + if (ACPI_FAILURE(acpi_ret)) { + if (extra_dbg) + *extra_dbg = acpi_format_exception(acpi_ret); +-- +2.35.1 + diff --git a/queue-5.15/video-hyperv_fb-avoid-taking-busy-spinlock-on-panic-.patch b/queue-5.15/video-hyperv_fb-avoid-taking-busy-spinlock-on-panic-.patch new file mode 100644 index 00000000000..c63411cf823 --- /dev/null +++ b/queue-5.15/video-hyperv_fb-avoid-taking-busy-spinlock-on-panic-.patch @@ -0,0 +1,106 @@ +From 47fb477dc91442936c54b416ab3cf7035dc44435 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 19:17:29 -0300 +Subject: video: hyperv_fb: Avoid taking busy spinlock on panic path + +From: Guilherme G. Piccoli + +[ Upstream commit 1d044ca035dc22df0d3b39e56f2881071d9118bd ] + +The Hyper-V framebuffer code registers a panic notifier in order +to try updating its fbdev if the kernel crashed. The notifier +callback is straightforward, but it calls the vmbus_sendpacket() +routine eventually, and such function takes a spinlock for the +ring buffer operations. + +Panic path runs in atomic context, with local interrupts and +preemption disabled, and all secondary CPUs shutdown. That said, +taking a spinlock might cause a lockup if a secondary CPU was +disabled with such lock taken. Fix it here by checking if the +ring buffer spinlock is busy on Hyper-V framebuffer panic notifier; +if so, bail-out avoiding the potential lockup scenario. + +Cc: Andrea Parri (Microsoft) +Cc: Dexuan Cui +Cc: Haiyang Zhang +Cc: "K. Y. Srinivasan" +Cc: Michael Kelley +Cc: Stephen Hemminger +Cc: Tianyu Lan +Cc: Wei Liu +Tested-by: Fabio A M Martins +Signed-off-by: Guilherme G. Piccoli +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20220819221731.480795-10-gpiccoli@igalia.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + drivers/hv/ring_buffer.c | 13 +++++++++++++ + drivers/video/fbdev/hyperv_fb.c | 8 +++++++- + include/linux/hyperv.h | 2 ++ + 3 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c +index f4091143213b..1475ea77351e 100644 +--- a/drivers/hv/ring_buffer.c ++++ b/drivers/hv/ring_buffer.c +@@ -249,6 +249,19 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info) + ring_info->pkt_buffer_size = 0; + } + ++/* ++ * Check if the ring buffer spinlock is available to take or not; used on ++ * atomic contexts, like panic path (see the Hyper-V framebuffer driver). ++ */ ++ ++bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel) ++{ ++ struct hv_ring_buffer_info *rinfo = &channel->outbound; ++ ++ return spin_is_locked(&rinfo->ring_lock); ++} ++EXPORT_SYMBOL_GPL(hv_ringbuffer_spinlock_busy); ++ + /* Write to the ring buffer. */ + int hv_ringbuffer_write(struct vmbus_channel *channel, + const struct kvec *kv_list, u32 kv_count, +diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c +index 58c304a3b7c4..de865e197c8d 100644 +--- a/drivers/video/fbdev/hyperv_fb.c ++++ b/drivers/video/fbdev/hyperv_fb.c +@@ -799,12 +799,18 @@ static void hvfb_ondemand_refresh_throttle(struct hvfb_par *par, + static int hvfb_on_panic(struct notifier_block *nb, + unsigned long e, void *p) + { ++ struct hv_device *hdev; + struct hvfb_par *par; + struct fb_info *info; + + par = container_of(nb, struct hvfb_par, hvfb_panic_nb); +- par->synchronous_fb = true; + info = par->info; ++ hdev = device_to_hv_device(info->device); ++ ++ if (hv_ringbuffer_spinlock_busy(hdev->channel)) ++ return NOTIFY_DONE; ++ ++ par->synchronous_fb = true; + if (par->need_docopy) + hvfb_docopy(par, 0, dio_fb_size); + synthvid_update(info, 0, 0, INT_MAX, INT_MAX); +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index ddc8713ce57b..8499fc9220e0 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1307,6 +1307,8 @@ struct hv_ring_buffer_debug_info { + int hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, + struct hv_ring_buffer_debug_info *debug_info); + ++bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel); ++ + /* Vmbus interface */ + #define vmbus_driver_register(driver) \ + __vmbus_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) +-- +2.35.1 + diff --git a/queue-5.15/vme-fix-error-not-catched-in-fake_init.patch b/queue-5.15/vme-fix-error-not-catched-in-fake_init.patch new file mode 100644 index 00000000000..f794214acd5 --- /dev/null +++ b/queue-5.15/vme-fix-error-not-catched-in-fake_init.patch @@ -0,0 +1,49 @@ +From 97603b39173fba96ad925a1f12e4d46a4387df29 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 16:48:05 +0800 +Subject: vme: Fix error not catched in fake_init() + +From: Chen Zhongjin + +[ Upstream commit 7bef797d707f1744f71156b21d41e3b8c946631f ] + +In fake_init(), __root_device_register() is possible to fail but it's +ignored, which can cause unregistering vme_root fail when exit. + + general protection fault, + probably for non-canonical address 0xdffffc000000008c + KASAN: null-ptr-deref in range [0x0000000000000460-0x0000000000000467] + RIP: 0010:root_device_unregister+0x26/0x60 + Call Trace: + + __x64_sys_delete_module+0x34f/0x540 + do_syscall_64+0x38/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Return error when __root_device_register() fails. + +Fixes: 658bcdae9c67 ("vme: Adding Fake VME driver") +Signed-off-by: Chen Zhongjin +Link: https://lore.kernel.org/r/20221205084805.147436-1-chenzhongjin@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/vme/bridges/vme_fake.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/vme/bridges/vme_fake.c b/drivers/vme/bridges/vme_fake.c +index 6a1bc284f297..eae78366eb02 100644 +--- a/drivers/vme/bridges/vme_fake.c ++++ b/drivers/vme/bridges/vme_fake.c +@@ -1073,6 +1073,8 @@ static int __init fake_init(void) + + /* We need a fake parent device */ + vme_root = __root_device_register("vme", THIS_MODULE); ++ if (IS_ERR(vme_root)) ++ return PTR_ERR(vme_root); + + /* If we want to support more than one bridge at some point, we need to + * dynamically allocate this so we get one per device. +-- +2.35.1 + diff --git a/queue-5.15/wifi-ar5523-fix-use-after-free-on-ar5523_cmd-timed-o.patch b/queue-5.15/wifi-ar5523-fix-use-after-free-on-ar5523_cmd-timed-o.patch new file mode 100644 index 00000000000..2cb4e373e4d --- /dev/null +++ b/queue-5.15/wifi-ar5523-fix-use-after-free-on-ar5523_cmd-timed-o.patch @@ -0,0 +1,110 @@ +From 2e803ca3b224eab930f72b7fb16587d5439714c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Oct 2022 03:32:23 +0900 +Subject: wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out + +From: Shigeru Yoshida + +[ Upstream commit b6702a942a069c2a975478d719e98d83cdae1797 ] + +syzkaller reported use-after-free with the stack trace like below [1]: + +[ 38.960489][ C3] ================================================================== +[ 38.963216][ C3] BUG: KASAN: use-after-free in ar5523_cmd_tx_cb+0x220/0x240 +[ 38.964950][ C3] Read of size 8 at addr ffff888048e03450 by task swapper/3/0 +[ 38.966363][ C3] +[ 38.967053][ C3] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 6.0.0-09039-ga6afa4199d3d-dirty #18 +[ 38.968464][ C3] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-1.fc36 04/01/2014 +[ 38.969959][ C3] Call Trace: +[ 38.970841][ C3] +[ 38.971663][ C3] dump_stack_lvl+0xfc/0x174 +[ 38.972620][ C3] print_report.cold+0x2c3/0x752 +[ 38.973626][ C3] ? ar5523_cmd_tx_cb+0x220/0x240 +[ 38.974644][ C3] kasan_report+0xb1/0x1d0 +[ 38.975720][ C3] ? ar5523_cmd_tx_cb+0x220/0x240 +[ 38.976831][ C3] ar5523_cmd_tx_cb+0x220/0x240 +[ 38.978412][ C3] __usb_hcd_giveback_urb+0x353/0x5b0 +[ 38.979755][ C3] usb_hcd_giveback_urb+0x385/0x430 +[ 38.981266][ C3] dummy_timer+0x140c/0x34e0 +[ 38.982925][ C3] ? notifier_call_chain+0xb5/0x1e0 +[ 38.984761][ C3] ? rcu_read_lock_sched_held+0xb/0x60 +[ 38.986242][ C3] ? lock_release+0x51c/0x790 +[ 38.987323][ C3] ? _raw_read_unlock_irqrestore+0x37/0x70 +[ 38.988483][ C3] ? __wake_up_common_lock+0xde/0x130 +[ 38.989621][ C3] ? reacquire_held_locks+0x4a0/0x4a0 +[ 38.990777][ C3] ? lock_acquire+0x472/0x550 +[ 38.991919][ C3] ? rcu_read_lock_sched_held+0xb/0x60 +[ 38.993138][ C3] ? lock_acquire+0x472/0x550 +[ 38.994890][ C3] ? dummy_urb_enqueue+0x860/0x860 +[ 38.996266][ C3] ? do_raw_spin_unlock+0x16f/0x230 +[ 38.997670][ C3] ? dummy_urb_enqueue+0x860/0x860 +[ 38.999116][ C3] call_timer_fn+0x1a0/0x6a0 +[ 39.000668][ C3] ? add_timer_on+0x4a0/0x4a0 +[ 39.002137][ C3] ? reacquire_held_locks+0x4a0/0x4a0 +[ 39.003809][ C3] ? __next_timer_interrupt+0x226/0x2a0 +[ 39.005509][ C3] __run_timers.part.0+0x69a/0xac0 +[ 39.007025][ C3] ? dummy_urb_enqueue+0x860/0x860 +[ 39.008716][ C3] ? call_timer_fn+0x6a0/0x6a0 +[ 39.010254][ C3] ? cpuacct_percpu_seq_show+0x10/0x10 +[ 39.011795][ C3] ? kvm_sched_clock_read+0x14/0x40 +[ 39.013277][ C3] ? sched_clock_cpu+0x69/0x2b0 +[ 39.014724][ C3] run_timer_softirq+0xb6/0x1d0 +[ 39.016196][ C3] __do_softirq+0x1d2/0x9be +[ 39.017616][ C3] __irq_exit_rcu+0xeb/0x190 +[ 39.019004][ C3] irq_exit_rcu+0x5/0x20 +[ 39.020361][ C3] sysvec_apic_timer_interrupt+0x8f/0xb0 +[ 39.021965][ C3] +[ 39.023237][ C3] + +In ar5523_probe(), ar5523_host_available() calls ar5523_cmd() as below +(there are other functions which finally call ar5523_cmd()): + +ar5523_probe() +-> ar5523_host_available() + -> ar5523_cmd_read() + -> ar5523_cmd() + +If ar5523_cmd() timed out, then ar5523_host_available() failed and +ar5523_probe() freed the device structure. So, ar5523_cmd_tx_cb() +might touch the freed structure. + +This patch fixes this issue by canceling in-flight tx cmd if submitted +urb timed out. + +Link: https://syzkaller.appspot.com/bug?id=9e12b2d54300842b71bdd18b54971385ff0d0d3a [1] +Reported-by: syzbot+95001b1fd6dfcc716c29@syzkaller.appspotmail.com +Signed-off-by: Shigeru Yoshida +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221009183223.420015-1-syoshida@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ar5523/ar5523.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c +index 1baec4b412c8..efe38b2c1df7 100644 +--- a/drivers/net/wireless/ath/ar5523/ar5523.c ++++ b/drivers/net/wireless/ath/ar5523/ar5523.c +@@ -241,6 +241,11 @@ static void ar5523_cmd_tx_cb(struct urb *urb) + } + } + ++static void ar5523_cancel_tx_cmd(struct ar5523 *ar) ++{ ++ usb_kill_urb(ar->tx_cmd.urb_tx); ++} ++ + static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, + int ilen, void *odata, int olen, int flags) + { +@@ -280,6 +285,7 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, + } + + if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { ++ ar5523_cancel_tx_cmd(ar); + cmd->odata = NULL; + ar5523_err(ar, "timeout waiting for command %02x reply\n", + code); +-- +2.35.1 + diff --git a/queue-5.15/wifi-ath10k-fix-return-value-in-ath10k_pci_init.patch b/queue-5.15/wifi-ath10k-fix-return-value-in-ath10k_pci_init.patch new file mode 100644 index 00000000000..7abbfe153c2 --- /dev/null +++ b/queue-5.15/wifi-ath10k-fix-return-value-in-ath10k_pci_init.patch @@ -0,0 +1,63 @@ +From 147669c3eaa0dda8508ad7b500a4c5768b224419 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Nov 2022 14:19:26 +0800 +Subject: wifi: ath10k: Fix return value in ath10k_pci_init() + +From: Xiu Jianfeng + +[ Upstream commit 2af7749047d8d6ad43feff69f555a13a6a6c2831 ] + +This driver is attempting to register to support two different buses. +if either of these is successful then ath10k_pci_init() should return 0 +so that hardware attached to the successful bus can be probed and +supported. only if both of these are unsuccessful should ath10k_pci_init() +return an errno. + +Fixes: 0b523ced9a3c ("ath10k: add basic skeleton to support ahb") +Signed-off-by: Xiu Jianfeng +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221110061926.18163-1-xiujianfeng@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/pci.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c +index 4d4e2f91e15c..85a30c301dad 100644 +--- a/drivers/net/wireless/ath/ath10k/pci.c ++++ b/drivers/net/wireless/ath/ath10k/pci.c +@@ -3793,18 +3793,22 @@ static struct pci_driver ath10k_pci_driver = { + + static int __init ath10k_pci_init(void) + { +- int ret; ++ int ret1, ret2; + +- ret = pci_register_driver(&ath10k_pci_driver); +- if (ret) ++ ret1 = pci_register_driver(&ath10k_pci_driver); ++ if (ret1) + printk(KERN_ERR "failed to register ath10k pci driver: %d\n", +- ret); ++ ret1); + +- ret = ath10k_ahb_init(); +- if (ret) +- printk(KERN_ERR "ahb init failed: %d\n", ret); ++ ret2 = ath10k_ahb_init(); ++ if (ret2) ++ printk(KERN_ERR "ahb init failed: %d\n", ret2); + +- return ret; ++ if (ret1 && ret2) ++ return ret1; ++ ++ /* registered to at least one bus */ ++ return 0; + } + module_init(ath10k_pci_init); + +-- +2.35.1 + diff --git a/queue-5.15/wifi-ath9k-hif_usb-fix-memory-leak-of-urbs-in-ath9k_.patch b/queue-5.15/wifi-ath9k-hif_usb-fix-memory-leak-of-urbs-in-ath9k_.patch new file mode 100644 index 00000000000..1a40f2cf49b --- /dev/null +++ b/queue-5.15/wifi-ath9k-hif_usb-fix-memory-leak-of-urbs-in-ath9k_.patch @@ -0,0 +1,61 @@ +From 9785f8d425f4848b8d1bc333a17ad03972799f08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 18:13:59 +0300 +Subject: wifi: ath9k: hif_usb: fix memory leak of urbs in + ath9k_hif_usb_dealloc_tx_urbs() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Fedor Pchelkin + +[ Upstream commit c2a94de38c74e86f49124ac14f093d6a5c377a90 ] + +Syzkaller reports a long-known leak of urbs in +ath9k_hif_usb_dealloc_tx_urbs(). + +The cause of the leak is that usb_get_urb() is called but usb_free_urb() +(or usb_put_urb()) is not called inside usb_kill_urb() as urb->dev or +urb->ep fields have not been initialized and usb_kill_urb() returns +immediately. + +The patch removes trying to kill urbs located in hif_dev->tx.tx_buf +because hif_dev->tx.tx_buf is not supposed to contain urbs which are in +pending state (the pending urbs are stored in hif_dev->tx.tx_pending). +The tx.tx_lock is acquired so there should not be any changes in the list. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 03fb92a432ea ("ath9k: hif_usb: fix race condition between usb_get_urb() and usb_kill_anchored_urbs()") +Signed-off-by: Fedor Pchelkin +Signed-off-by: Alexey Khoroshilov +Acked-by: Toke Høiland-Jørgensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220725151359.283704-1-pchelkin@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index f06eec99de68..e66518d86882 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -781,14 +781,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) + spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + list_for_each_entry_safe(tx_buf, tx_buf_tmp, + &hif_dev->tx.tx_buf, list) { +- usb_get_urb(tx_buf->urb); +- spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); +- usb_kill_urb(tx_buf->urb); + list_del(&tx_buf->list); + usb_free_urb(tx_buf->urb); + kfree(tx_buf->buf); + kfree(tx_buf); +- spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); + } + spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); + +-- +2.35.1 + diff --git a/queue-5.15/wifi-ath9k-hif_usb-fix-use-after-free-in-ath9k_hif_u.patch b/queue-5.15/wifi-ath9k-hif_usb-fix-use-after-free-in-ath9k_hif_u.patch new file mode 100644 index 00000000000..2ba210170cd --- /dev/null +++ b/queue-5.15/wifi-ath9k-hif_usb-fix-use-after-free-in-ath9k_hif_u.patch @@ -0,0 +1,118 @@ +From 97dbb58948ddd90ee78612b723cb97917b63c621 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Oct 2022 14:49:17 +0300 +Subject: wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Fedor Pchelkin + +[ Upstream commit dd95f2239fc846795fc926787c3ae0ca701c9840 ] + +It is possible that skb is freed in ath9k_htc_rx_msg(), then +usb_submit_urb() fails and we try to free skb again. It causes +use-after-free bug. Moreover, if alloc_skb() fails, urb->context becomes +NULL but rx_buf is not freed and there can be a memory leak. + +The patch removes unnecessary nskb and makes skb processing more clear: it +is supposed that ath9k_htc_rx_msg() either frees old skb or passes its +managing to another callback function. + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Fixes: 3deff76095c4 ("ath9k_htc: Increase URB count for REG_IN pipe") +Signed-off-by: Fedor Pchelkin +Signed-off-by: Alexey Khoroshilov +Acked-by: Toke Høiland-Jørgensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221008114917.21404-1-pchelkin@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 28 +++++++++++++----------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index e66518d86882..e5d5b0761881 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -709,14 +709,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + struct rx_buf *rx_buf = (struct rx_buf *)urb->context; + struct hif_device_usb *hif_dev = rx_buf->hif_dev; + struct sk_buff *skb = rx_buf->skb; +- struct sk_buff *nskb; + int ret; + + if (!skb) + return; + + if (!hif_dev) +- goto free; ++ goto free_skb; + + switch (urb->status) { + case 0: +@@ -725,7 +724,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + case -ECONNRESET: + case -ENODEV: + case -ESHUTDOWN: +- goto free; ++ goto free_skb; + default: + skb_reset_tail_pointer(skb); + skb_trim(skb, 0); +@@ -736,25 +735,27 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + if (likely(urb->actual_length != 0)) { + skb_put(skb, urb->actual_length); + +- /* Process the command first */ ++ /* ++ * Process the command first. ++ * skb is either freed here or passed to be ++ * managed to another callback function. ++ */ + ath9k_htc_rx_msg(hif_dev->htc_handle, skb, + skb->len, USB_REG_IN_PIPE); + +- +- nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); +- if (!nskb) { ++ skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); ++ if (!skb) { + dev_err(&hif_dev->udev->dev, + "ath9k_htc: REG_IN memory allocation failure\n"); +- urb->context = NULL; +- return; ++ goto free_rx_buf; + } + +- rx_buf->skb = nskb; ++ rx_buf->skb = skb; + + usb_fill_int_urb(urb, hif_dev->udev, + usb_rcvintpipe(hif_dev->udev, + USB_REG_IN_PIPE), +- nskb->data, MAX_REG_IN_BUF_SIZE, ++ skb->data, MAX_REG_IN_BUF_SIZE, + ath9k_hif_usb_reg_in_cb, rx_buf, 1); + } + +@@ -763,12 +764,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + usb_unanchor_urb(urb); +- goto free; ++ goto free_skb; + } + + return; +-free: ++free_skb: + kfree_skb(skb); ++free_rx_buf: + kfree(rx_buf); + urb->context = NULL; + } +-- +2.35.1 + diff --git a/queue-5.15/wifi-ath9k-verify-the-expected-usb_endpoints-are-pre.patch b/queue-5.15/wifi-ath9k-verify-the-expected-usb_endpoints-are-pre.patch new file mode 100644 index 00000000000..1b3e016abd1 --- /dev/null +++ b/queue-5.15/wifi-ath9k-verify-the-expected-usb_endpoints-are-pre.patch @@ -0,0 +1,80 @@ +From 4262e0385e82e71147acf6f661781be28ed0049a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Oct 2022 00:15:32 +0300 +Subject: wifi: ath9k: verify the expected usb_endpoints are present +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Fedor Pchelkin + +[ Upstream commit 16ef02bad239f11f322df8425d302be62f0443ce ] + +The bug arises when a USB device claims to be an ATH9K but doesn't +have the expected endpoints. (In this case there was an interrupt +endpoint where the driver expected a bulk endpoint.) The kernel +needs to be able to handle such devices without getting an internal error. + +usb 1-1: BOGUS urb xfer, pipe 3 != type 1 +WARNING: CPU: 3 PID: 500 at drivers/usb/core/urb.c:493 usb_submit_urb+0xce2/0x1430 drivers/usb/core/urb.c:493 +Modules linked in: +CPU: 3 PID: 500 Comm: kworker/3:2 Not tainted 5.10.135-syzkaller #0 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 +Workqueue: events request_firmware_work_func +RIP: 0010:usb_submit_urb+0xce2/0x1430 drivers/usb/core/urb.c:493 +Call Trace: + ath9k_hif_usb_alloc_rx_urbs drivers/net/wireless/ath/ath9k/hif_usb.c:908 [inline] + ath9k_hif_usb_alloc_urbs+0x75e/0x1010 drivers/net/wireless/ath/ath9k/hif_usb.c:1019 + ath9k_hif_usb_dev_init drivers/net/wireless/ath/ath9k/hif_usb.c:1109 [inline] + ath9k_hif_usb_firmware_cb+0x142/0x530 drivers/net/wireless/ath/ath9k/hif_usb.c:1242 + request_firmware_work_func+0x12e/0x240 drivers/base/firmware_loader/main.c:1097 + process_one_work+0x9af/0x1600 kernel/workqueue.c:2279 + worker_thread+0x61d/0x12f0 kernel/workqueue.c:2425 + kthread+0x3b4/0x4a0 kernel/kthread.c:313 + ret_from_fork+0x22/0x30 arch/x86/entry/entry_64.S:299 + +Found by Linux Verification Center (linuxtesting.org) with Syzkaller. + +Suggested-by: Alan Stern +Signed-off-by: Fedor Pchelkin +Signed-off-by: Alexey Khoroshilov +Acked-by: Toke Høiland-Jørgensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221008211532.74583-1-pchelkin@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index e5d5b0761881..f938ac1a4abd 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1328,10 +1328,24 @@ static int send_eject_command(struct usb_interface *interface) + static int ath9k_hif_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) + { ++ struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out; + struct usb_device *udev = interface_to_usbdev(interface); ++ struct usb_host_interface *alt; + struct hif_device_usb *hif_dev; + int ret = 0; + ++ /* Verify the expected endpoints are present */ ++ alt = interface->cur_altsetting; ++ if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 || ++ usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE || ++ usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE || ++ usb_endpoint_num(int_in) != USB_REG_IN_PIPE || ++ usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) { ++ dev_err(&udev->dev, ++ "ath9k_htc: Device endpoint numbers are not the expected ones\n"); ++ return -ENODEV; ++ } ++ + if (id->driver_info == STORAGE_DEVICE) + return send_eject_command(interface); + +-- +2.35.1 + diff --git a/queue-5.15/wifi-brcmfmac-fix-error-return-code-in-brcmf_sdio_do.patch b/queue-5.15/wifi-brcmfmac-fix-error-return-code-in-brcmf_sdio_do.patch new file mode 100644 index 00000000000..5d103ab49a8 --- /dev/null +++ b/queue-5.15/wifi-brcmfmac-fix-error-return-code-in-brcmf_sdio_do.patch @@ -0,0 +1,53 @@ +From 5d534849923d21058cf53db3f1a4f078665a9f68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Dec 2022 13:35:42 +0800 +Subject: wifi: brcmfmac: Fix error return code in + brcmf_sdio_download_firmware() + +From: Wang Yufen + +[ Upstream commit c2f2924bc7f9ea75ef8d95863e710168f8196256 ] + +Fix to return a negative error code instead of 0 when +brcmf_chip_set_active() fails. In addition, change the return +value for brcmf_pcie_exit_download_state() to keep consistent. + +Fixes: d380ebc9b6fb ("brcmfmac: rename chip download functions") +Signed-off-by: Wang Yufen +Reviewed-by: Arend van Spriel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1669959342-27144-1-git-send-email-wangyufen@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 +- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +index 3ff4997e1c97..358021a33b8a 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -626,7 +626,7 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo, + } + + if (!brcmf_chip_set_active(devinfo->ci, resetintr)) +- return -EINVAL; ++ return -EIO; + return 0; + } + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +index f7961b22e051..5006aa831751 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -3411,6 +3411,7 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, + /* Take arm out of reset */ + if (!brcmf_chip_set_active(bus->ci, rstvec)) { + brcmf_err("error getting out of ARM core reset\n"); ++ bcmerror = -EIO; + goto err; + } + +-- +2.35.1 + diff --git a/queue-5.15/wifi-brcmfmac-fix-potential-shift-out-of-bounds-in-b.patch b/queue-5.15/wifi-brcmfmac-fix-potential-shift-out-of-bounds-in-b.patch new file mode 100644 index 00000000000..a4f8c6077a7 --- /dev/null +++ b/queue-5.15/wifi-brcmfmac-fix-potential-shift-out-of-bounds-in-b.patch @@ -0,0 +1,149 @@ +From b78bd8912e59fc9d71f3f822232d76c2c8839f97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Oct 2022 16:13:29 +0900 +Subject: wifi: brcmfmac: Fix potential shift-out-of-bounds in + brcmf_fw_alloc_request() + +From: Minsuk Kang + +[ Upstream commit 81d17f6f3331f03c8eafdacea68ab773426c1e3c ] + +This patch fixes a shift-out-of-bounds in brcmfmac that occurs in +BIT(chiprev) when a 'chiprev' provided by the device is too large. +It should also not be equal to or greater than BITS_PER_TYPE(u32) +as we do bitwise AND with a u32 variable and BIT(chiprev). The patch +adds a check that makes the function return NULL if that is the case. +Note that the NULL case is later handled by the bus-specific caller, +brcmf_usb_probe_cb() or brcmf_usb_reset_resume(), for example. + +Found by a modified version of syzkaller. + +UBSAN: shift-out-of-bounds in drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +shift exponent 151055786 is too large for 64-bit type 'long unsigned int' +CPU: 0 PID: 1885 Comm: kworker/0:2 Tainted: G O 5.14.0+ #132 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 +Workqueue: usb_hub_wq hub_event +Call Trace: + dump_stack_lvl+0x57/0x7d + ubsan_epilogue+0x5/0x40 + __ubsan_handle_shift_out_of_bounds.cold+0x53/0xdb + ? lock_chain_count+0x20/0x20 + brcmf_fw_alloc_request.cold+0x19/0x3ea + ? brcmf_fw_get_firmwares+0x250/0x250 + ? brcmf_usb_ioctl_resp_wait+0x1a7/0x1f0 + brcmf_usb_get_fwname+0x114/0x1a0 + ? brcmf_usb_reset_resume+0x120/0x120 + ? number+0x6c4/0x9a0 + brcmf_c_process_clm_blob+0x168/0x590 + ? put_dec+0x90/0x90 + ? enable_ptr_key_workfn+0x20/0x20 + ? brcmf_common_pd_remove+0x50/0x50 + ? rcu_read_lock_sched_held+0xa1/0xd0 + brcmf_c_preinit_dcmds+0x673/0xc40 + ? brcmf_c_set_joinpref_default+0x100/0x100 + ? rcu_read_lock_sched_held+0xa1/0xd0 + ? rcu_read_lock_bh_held+0xb0/0xb0 + ? lock_acquire+0x19d/0x4e0 + ? find_held_lock+0x2d/0x110 + ? brcmf_usb_deq+0x1cc/0x260 + ? mark_held_locks+0x9f/0xe0 + ? lockdep_hardirqs_on_prepare+0x273/0x3e0 + ? _raw_spin_unlock_irqrestore+0x47/0x50 + ? trace_hardirqs_on+0x1c/0x120 + ? brcmf_usb_deq+0x1a7/0x260 + ? brcmf_usb_rx_fill_all+0x5a/0xf0 + brcmf_attach+0x246/0xd40 + ? wiphy_new_nm+0x1476/0x1d50 + ? kmemdup+0x30/0x40 + brcmf_usb_probe+0x12de/0x1690 + ? brcmf_usbdev_qinit.constprop.0+0x470/0x470 + usb_probe_interface+0x25f/0x710 + really_probe+0x1be/0xa90 + __driver_probe_device+0x2ab/0x460 + ? usb_match_id.part.0+0x88/0xc0 + driver_probe_device+0x49/0x120 + __device_attach_driver+0x18a/0x250 + ? driver_allows_async_probing+0x120/0x120 + bus_for_each_drv+0x123/0x1a0 + ? bus_rescan_devices+0x20/0x20 + ? lockdep_hardirqs_on_prepare+0x273/0x3e0 + ? trace_hardirqs_on+0x1c/0x120 + __device_attach+0x207/0x330 + ? device_bind_driver+0xb0/0xb0 + ? kobject_uevent_env+0x230/0x12c0 + bus_probe_device+0x1a2/0x260 + device_add+0xa61/0x1ce0 + ? __mutex_unlock_slowpath+0xe7/0x660 + ? __fw_devlink_link_to_suppliers+0x550/0x550 + usb_set_configuration+0x984/0x1770 + ? kernfs_create_link+0x175/0x230 + usb_generic_driver_probe+0x69/0x90 + usb_probe_device+0x9c/0x220 + really_probe+0x1be/0xa90 + __driver_probe_device+0x2ab/0x460 + driver_probe_device+0x49/0x120 + __device_attach_driver+0x18a/0x250 + ? driver_allows_async_probing+0x120/0x120 + bus_for_each_drv+0x123/0x1a0 + ? bus_rescan_devices+0x20/0x20 + ? lockdep_hardirqs_on_prepare+0x273/0x3e0 + ? trace_hardirqs_on+0x1c/0x120 + __device_attach+0x207/0x330 + ? device_bind_driver+0xb0/0xb0 + ? kobject_uevent_env+0x230/0x12c0 + bus_probe_device+0x1a2/0x260 + device_add+0xa61/0x1ce0 + ? __fw_devlink_link_to_suppliers+0x550/0x550 + usb_new_device.cold+0x463/0xf66 + ? hub_disconnect+0x400/0x400 + ? _raw_spin_unlock_irq+0x24/0x30 + hub_event+0x10d5/0x3330 + ? hub_port_debounce+0x280/0x280 + ? __lock_acquire+0x1671/0x5790 + ? wq_calc_node_cpumask+0x170/0x2a0 + ? lock_release+0x640/0x640 + ? rcu_read_lock_sched_held+0xa1/0xd0 + ? rcu_read_lock_bh_held+0xb0/0xb0 + ? lockdep_hardirqs_on_prepare+0x273/0x3e0 + process_one_work+0x873/0x13e0 + ? lock_release+0x640/0x640 + ? pwq_dec_nr_in_flight+0x320/0x320 + ? rwlock_bug.part.0+0x90/0x90 + worker_thread+0x8b/0xd10 + ? __kthread_parkme+0xd9/0x1d0 + ? process_one_work+0x13e0/0x13e0 + kthread+0x379/0x450 + ? _raw_spin_unlock_irq+0x24/0x30 + ? set_kthread_struct+0x100/0x100 + ret_from_fork+0x1f/0x30 + +Reported-by: Dokyung Song +Reported-by: Jisoo Jang +Reported-by: Minsuk Kang +Signed-off-by: Minsuk Kang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221024071329.504277-1-linuxlovemin@yonsei.ac.kr +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +index dcbe55b56e43..c54d8722e755 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +@@ -746,6 +746,11 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev, + u32 i, j; + char end = '\0'; + ++ if (chiprev >= BITS_PER_TYPE(u32)) { ++ brcmf_err("Invalid chip revision %u\n", chiprev); ++ return NULL; ++ } ++ + for (i = 0; i < table_size; i++) { + if (mapping_table[i].chipid == chip && + mapping_table[i].revmask & BIT(chiprev)) +-- +2.35.1 + diff --git a/queue-5.15/wifi-cfg80211-fix-not-unregister-reg_pdev-when-load_.patch b/queue-5.15/wifi-cfg80211-fix-not-unregister-reg_pdev-when-load_.patch new file mode 100644 index 00000000000..cce56e3e799 --- /dev/null +++ b/queue-5.15/wifi-cfg80211-fix-not-unregister-reg_pdev-when-load_.patch @@ -0,0 +1,57 @@ +From 60933e6931f756032aaba6373ddd953694c7f69b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 9 Nov 2022 17:02:37 +0800 +Subject: wifi: cfg80211: Fix not unregister reg_pdev when + load_builtin_regdb_keys() fails + +From: Chen Zhongjin + +[ Upstream commit 833a9fd28c9b7ccb39a334721379e992dc1c0c89 ] + +In regulatory_init_db(), when it's going to return a error, reg_pdev +should be unregistered. When load_builtin_regdb_keys() fails it doesn't +do it and makes cfg80211 can't be reload with report: + +sysfs: cannot create duplicate filename '/devices/platform/regulatory.0' + ... + + dump_stack_lvl+0x79/0x9b + sysfs_warn_dup.cold+0x1c/0x29 + sysfs_create_dir_ns+0x22d/0x290 + kobject_add_internal+0x247/0x800 + kobject_add+0x135/0x1b0 + device_add+0x389/0x1be0 + platform_device_add+0x28f/0x790 + platform_device_register_full+0x376/0x4b0 + regulatory_init+0x9a/0x4b2 [cfg80211] + cfg80211_init+0x84/0x113 [cfg80211] + ... + +Fixes: 90a53e4432b1 ("cfg80211: implement regdb signature checking") +Signed-off-by: Chen Zhongjin +Link: https://lore.kernel.org/r/20221109090237.214127-1-chenzhongjin@huawei.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/reg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index 7b19a2087db9..d0fbe822e793 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -4247,8 +4247,10 @@ static int __init regulatory_init_db(void) + return -EINVAL; + + err = load_builtin_regdb_keys(); +- if (err) ++ if (err) { ++ platform_device_unregister(reg_pdev); + return err; ++ } + + /* We always try to get an update for the static regdomain */ + err = regulatory_hint_core(cfg80211_world_regdom->alpha2); +-- +2.35.1 + diff --git a/queue-5.15/wifi-iwlwifi-mvm-fix-double-free-on-tx-path.patch b/queue-5.15/wifi-iwlwifi-mvm-fix-double-free-on-tx-path.patch new file mode 100644 index 00000000000..72a5cd08838 --- /dev/null +++ b/queue-5.15/wifi-iwlwifi-mvm-fix-double-free-on-tx-path.patch @@ -0,0 +1,215 @@ +From 0058e69afe83c852c46f78ac68203fcc1704ccff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 23:02:06 +0200 +Subject: wifi: iwlwifi: mvm: fix double free on tx path. + +From: Ben Greear + +[ Upstream commit 0473cbae2137b963bd0eaa74336131cb1d3bc6c3 ] + +We see kernel crashes and lockups and KASAN errors related to ax210 +firmware crashes. One of the KASAN dumps pointed at the tx path, +and it appears there is indeed a way to double-free an skb. + +If iwl_mvm_tx_skb_sta returns non-zero, then the 'skb' sent into the +method will be freed. But, in case where we build TSO skb buffer, +the skb may also be freed in error case. So, return 0 in that particular +error case and do cleanup manually. + +BUG: KASAN: use-after-free in __list_del_entry_valid+0x12/0x90 +iwlwifi 0000:06:00.0: 0x00000000 | tsf hi +Read of size 8 at addr ffff88813cfa4ba0 by task btserver/9650 + +CPU: 4 PID: 9650 Comm: btserver Tainted: G W 5.19.8+ #5 +iwlwifi 0000:06:00.0: 0x00000000 | time gp1 +Hardware name: Default string Default string/SKYBAY, BIOS 5.12 02/19/2019 +Call Trace: + + dump_stack_lvl+0x55/0x6d + print_report.cold.12+0xf2/0x684 +iwlwifi 0000:06:00.0: 0x1D0915A8 | time gp2 + ? __list_del_entry_valid+0x12/0x90 + kasan_report+0x8b/0x180 +iwlwifi 0000:06:00.0: 0x00000001 | uCode revision type + ? __list_del_entry_valid+0x12/0x90 + __list_del_entry_valid+0x12/0x90 +iwlwifi 0000:06:00.0: 0x00000048 | uCode version major + tcp_update_skb_after_send+0x5d/0x170 + __tcp_transmit_skb+0xb61/0x15c0 +iwlwifi 0000:06:00.0: 0xDAA05125 | uCode version minor + ? __tcp_select_window+0x490/0x490 +iwlwifi 0000:06:00.0: 0x00000420 | hw version + ? trace_kmalloc_node+0x29/0xd0 + ? __kmalloc_node_track_caller+0x12a/0x260 + ? memset+0x1f/0x40 + ? __build_skb_around+0x125/0x150 + ? __alloc_skb+0x1d4/0x220 + ? skb_zerocopy_clone+0x55/0x230 +iwlwifi 0000:06:00.0: 0x00489002 | board version + ? kmalloc_reserve+0x80/0x80 + ? rcu_read_lock_bh_held+0x60/0xb0 + tcp_write_xmit+0x3f1/0x24d0 +iwlwifi 0000:06:00.0: 0x034E001C | hcmd + ? __check_object_size+0x180/0x350 +iwlwifi 0000:06:00.0: 0x24020000 | isr0 + tcp_sendmsg_locked+0x8a9/0x1520 +iwlwifi 0000:06:00.0: 0x01400000 | isr1 + ? tcp_sendpage+0x50/0x50 +iwlwifi 0000:06:00.0: 0x48F0000A | isr2 + ? lock_release+0xb9/0x400 + ? tcp_sendmsg+0x14/0x40 +iwlwifi 0000:06:00.0: 0x00C3080C | isr3 + ? lock_downgrade+0x390/0x390 + ? do_raw_spin_lock+0x114/0x1d0 +iwlwifi 0000:06:00.0: 0x00200000 | isr4 + ? rwlock_bug.part.2+0x50/0x50 +iwlwifi 0000:06:00.0: 0x034A001C | last cmd Id + ? rwlock_bug.part.2+0x50/0x50 + ? lockdep_hardirqs_on_prepare+0xe/0x200 +iwlwifi 0000:06:00.0: 0x0000C2F0 | wait_event + ? __local_bh_enable_ip+0x87/0xe0 + ? inet_send_prepare+0x220/0x220 +iwlwifi 0000:06:00.0: 0x000000C4 | l2p_control + tcp_sendmsg+0x22/0x40 + sock_sendmsg+0x5f/0x70 +iwlwifi 0000:06:00.0: 0x00010034 | l2p_duration + __sys_sendto+0x19d/0x250 +iwlwifi 0000:06:00.0: 0x00000007 | l2p_mhvalid + ? __ia32_sys_getpeername+0x40/0x40 +iwlwifi 0000:06:00.0: 0x00000000 | l2p_addr_match + ? rcu_read_lock_held_common+0x12/0x50 + ? rcu_read_lock_sched_held+0x5a/0xd0 + ? rcu_read_lock_bh_held+0xb0/0xb0 + ? rcu_read_lock_sched_held+0x5a/0xd0 + ? rcu_read_lock_sched_held+0x5a/0xd0 + ? lock_release+0xb9/0x400 + ? lock_downgrade+0x390/0x390 + ? ktime_get+0x64/0x130 + ? ktime_get+0x8d/0x130 + ? rcu_read_lock_held_common+0x12/0x50 + ? rcu_read_lock_sched_held+0x5a/0xd0 + ? rcu_read_lock_held_common+0x12/0x50 + ? rcu_read_lock_sched_held+0x5a/0xd0 + ? rcu_read_lock_bh_held+0xb0/0xb0 + ? rcu_read_lock_bh_held+0xb0/0xb0 + __x64_sys_sendto+0x6f/0x80 + do_syscall_64+0x34/0xb0 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 +RIP: 0033:0x7f1d126e4531 +Code: 00 00 00 00 0f 1f 44 00 00 f3 0f 1e fa 48 8d 05 35 80 0c 00 41 89 ca 8b 00 85 c0 75 1c 45 31 c9 45 31 c0 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 67 c3 66 0f 1f 44 00 00 55 48 83 ec 20 48 89 +RSP: 002b:00007ffe21a679d8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 000000000000ffdc RCX: 00007f1d126e4531 +RDX: 0000000000010000 RSI: 000000000374acf0 RDI: 0000000000000014 +RBP: 00007ffe21a67ac0 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000010 +R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000 + + +Allocated by task 9650: + kasan_save_stack+0x1c/0x40 + __kasan_slab_alloc+0x6d/0x90 + kmem_cache_alloc_node+0xf3/0x2b0 + __alloc_skb+0x191/0x220 + tcp_stream_alloc_skb+0x3f/0x330 + tcp_sendmsg_locked+0x67c/0x1520 + tcp_sendmsg+0x22/0x40 + sock_sendmsg+0x5f/0x70 + __sys_sendto+0x19d/0x250 + __x64_sys_sendto+0x6f/0x80 + do_syscall_64+0x34/0xb0 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +Freed by task 9650: + kasan_save_stack+0x1c/0x40 + kasan_set_track+0x21/0x30 + kasan_set_free_info+0x20/0x30 + __kasan_slab_free+0x102/0x170 + kmem_cache_free+0xc8/0x3e0 + iwl_mvm_mac_itxq_xmit+0x124/0x270 [iwlmvm] + ieee80211_queue_skb+0x874/0xd10 [mac80211] + ieee80211_xmit_fast+0xf80/0x1180 [mac80211] + __ieee80211_subif_start_xmit+0x287/0x680 [mac80211] + ieee80211_subif_start_xmit+0xcd/0x730 [mac80211] + dev_hard_start_xmit+0xf6/0x420 + __dev_queue_xmit+0x165b/0x1b50 + ip_finish_output2+0x66e/0xfb0 + __ip_finish_output+0x487/0x6d0 + ip_output+0x11c/0x350 + __ip_queue_xmit+0x36b/0x9d0 + __tcp_transmit_skb+0xb35/0x15c0 + tcp_write_xmit+0x3f1/0x24d0 + tcp_sendmsg_locked+0x8a9/0x1520 + tcp_sendmsg+0x22/0x40 + sock_sendmsg+0x5f/0x70 + __sys_sendto+0x19d/0x250 + __x64_sys_sendto+0x6f/0x80 + do_syscall_64+0x34/0xb0 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +The buggy address belongs to the object at ffff88813cfa4b40 + which belongs to the cache skbuff_fclone_cache of size 472 +The buggy address is located 96 bytes inside of + 472-byte region [ffff88813cfa4b40, ffff88813cfa4d18) + +The buggy address belongs to the physical page: +page:ffffea0004f3e900 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff88813cfa6c40 pfn:0x13cfa4 +head:ffffea0004f3e900 order:2 compound_mapcount:0 compound_pincount:0 +flags: 0x5fff8000010200(slab|head|node=0|zone=2|lastcpupid=0x3fff) +raw: 005fff8000010200 ffffea0004656b08 ffffea0008e8cf08 ffff8881081a5240 +raw: ffff88813cfa6c40 0000000000170015 00000001ffffffff 0000000000000000 +page dumped because: kasan: bad access detected + +Memory state around the buggy address: + ffff88813cfa4a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc + ffff88813cfa4b00: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb +>ffff88813cfa4b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ^ + ffff88813cfa4c00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb + ffff88813cfa4c80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +================================================================== + +Fixes: 08f7d8b69aaf ("iwlwifi: mvm: bring back mvm GSO code") +Link: https://lore.kernel.org/linux-wireless/20220928193057.16132-1-greearb@candelatech.com/ +Tested-by: Amol Jawale +Signed-off-by: Ben Greear +Link: https://lore.kernel.org/r/20221123225313.21b1ee31d666.I3b3ba184433dd2a544d91eeeda29b467021824ae@changeid +Signed-off-by: Gregory Greenman +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +index b5368cb57ca8..e354918c2480 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +@@ -1150,6 +1150,7 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, + struct sk_buff_head mpdus_skbs; + unsigned int payload_len; + int ret; ++ struct sk_buff *orig_skb = skb; + + if (WARN_ON_ONCE(!mvmsta)) + return -1; +@@ -1182,8 +1183,17 @@ int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb, + + ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta); + if (ret) { ++ /* Free skbs created as part of TSO logic that have not yet been dequeued */ + __skb_queue_purge(&mpdus_skbs); +- return ret; ++ /* skb here is not necessarily same as skb that entered this method, ++ * so free it explicitly. ++ */ ++ if (skb == orig_skb) ++ ieee80211_free_txskb(mvm->hw, skb); ++ else ++ kfree_skb(skb); ++ /* there was error, but we consumed skb one way or another, so return 0 */ ++ return 0; + } + } + +-- +2.35.1 + diff --git a/queue-5.15/wifi-mac80211-fix-memory-leak-in-ieee80211_if_add.patch b/queue-5.15/wifi-mac80211-fix-memory-leak-in-ieee80211_if_add.patch new file mode 100644 index 00000000000..a9a63d05dc1 --- /dev/null +++ b/queue-5.15/wifi-mac80211-fix-memory-leak-in-ieee80211_if_add.patch @@ -0,0 +1,36 @@ +From dfbaefc040e3f6c2362c46ca8e4732540969311e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 14:45:00 +0800 +Subject: wifi: mac80211: fix memory leak in ieee80211_if_add() + +From: Zhengchao Shao + +[ Upstream commit 13e5afd3d773c6fc6ca2b89027befaaaa1ea7293 ] + +When register_netdevice() failed in ieee80211_if_add(), ndev->tstats +isn't released. Fix it. + +Fixes: 5a490510ba5f ("mac80211: use per-CPU TX/RX statistics") +Signed-off-by: Zhengchao Shao +Link: https://lore.kernel.org/r/20221117064500.319983-1-shaozhengchao@huawei.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/iface.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c +index 041859b5b71d..a3347f245782 100644 +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -2059,6 +2059,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, + + ret = cfg80211_register_netdevice(ndev); + if (ret) { ++ ieee80211_if_free(ndev); + free_netdev(ndev); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.15/wifi-mt76-do-not-run-mt76u_status_worker-if-the-devi.patch b/queue-5.15/wifi-mt76-do-not-run-mt76u_status_worker-if-the-devi.patch new file mode 100644 index 00000000000..8219e90699d --- /dev/null +++ b/queue-5.15/wifi-mt76-do-not-run-mt76u_status_worker-if-the-devi.patch @@ -0,0 +1,107 @@ +From 1b79ba2adac726994a7b771d0b74ab61c9ed805a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 21:07:37 +0200 +Subject: wifi: mt76: do not run mt76u_status_worker if the device is not + running + +From: Lorenzo Bianconi + +[ Upstream commit bd5dac7ced5a7c9faa4dc468ac9560c3256df845 ] + +Fix the following NULL pointer dereference avoiding to run +mt76u_status_worker thread if the device is not running yet. + +KASAN: null-ptr-deref in range +[0x0000000000000000-0x0000000000000007] +CPU: 0 PID: 98 Comm: kworker/u2:2 Not tainted 5.14.0+ #78 Hardware +name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +rel-1.12.1-0-ga5cab58e9a3f-prebuilt.qemu.org 04/01/2014 +Workqueue: mt76 mt76u_tx_status_data +RIP: 0010:mt76x02_mac_fill_tx_status.isra.0+0x82c/0x9e0 +Code: c5 48 b8 00 00 00 00 00 fc ff df 80 3c 02 00 0f 85 94 01 00 00 +48 b8 00 00 00 00 00 fc ff df 4d 8b 34 24 4c 89 f2 48 c1 ea 03 <0f> +b6 +04 02 84 c0 74 08 3c 03 0f 8e 89 01 00 00 41 8b 16 41 0f b7 +RSP: 0018:ffffc900005af988 EFLAGS: 00010246 +RAX: dffffc0000000000 RBX: ffffc900005afae8 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: ffffffff832fc661 RDI: ffffc900005afc2a +RBP: ffffc900005afae0 R08: 0000000000000001 R09: fffff520000b5f3c +R10: 0000000000000003 R11: fffff520000b5f3b R12: ffff88810b6132d8 +R13: 000000000000ffff R14: 0000000000000000 R15: ffffc900005afc28 +FS: 0000000000000000(0000) GS:ffff88811aa00000(0000) +knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fa0eda6a000 CR3: 0000000118f17000 CR4: 0000000000750ef0 +PKRU: 55555554 +Call Trace: + mt76x02_send_tx_status+0x1d2/0xeb0 + mt76x02_tx_status_data+0x8e/0xd0 + mt76u_tx_status_data+0xe1/0x240 + process_one_work+0x92b/0x1460 + worker_thread+0x95/0xe00 + kthread+0x3a1/0x480 + ret_from_fork+0x1f/0x30 +Modules linked in: +--[ end trace 8df5d20fc5040f65 ]-- +RIP: 0010:mt76x02_mac_fill_tx_status.isra.0+0x82c/0x9e0 +Code: c5 48 b8 00 00 00 00 00 fc ff df 80 3c 02 00 0f 85 94 01 00 00 +48 b8 00 00 00 00 00 fc ff df 4d 8b 34 24 4c 89 f2 48 c1 ea 03 <0f> +b6 +04 02 84 c0 74 08 3c 03 0f 8e 89 01 00 00 41 8b 16 41 0f b7 +RSP: 0018:ffffc900005af988 EFLAGS: 00010246 +RAX: dffffc0000000000 RBX: ffffc900005afae8 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: ffffffff832fc661 RDI: ffffc900005afc2a +RBP: ffffc900005afae0 R08: 0000000000000001 R09: fffff520000b5f3c +R10: 0000000000000003 R11: fffff520000b5f3b R12: ffff88810b6132d8 +R13: 000000000000ffff R14: 0000000000000000 R15: ffffc900005afc28 +FS: 0000000000000000(0000) GS:ffff88811aa00000(0000) +knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fa0eda6a000 CR3: 0000000118f17000 CR4: 0000000000750ef0 +PKRU: 55555554 + +Moreover move stat_work schedule out of the for loop. + +Reported-by: Dokyung Song +Co-developed-by: Deren Wu +Signed-off-by: Deren Wu +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/usb.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c +index 1e9f60bb811a..b47343e321b8 100644 +--- a/drivers/net/wireless/mediatek/mt76/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/usb.c +@@ -814,6 +814,9 @@ static void mt76u_status_worker(struct mt76_worker *w) + struct mt76_queue *q; + int i; + ++ if (!test_bit(MT76_STATE_RUNNING, &dev->phy.state)) ++ return; ++ + for (i = 0; i < IEEE80211_NUM_ACS; i++) { + q = dev->phy.q_tx[i]; + if (!q) +@@ -833,11 +836,11 @@ static void mt76u_status_worker(struct mt76_worker *w) + wake_up(&dev->tx_wait); + + mt76_worker_schedule(&dev->tx_worker); +- +- if (dev->drv->tx_status_data && +- !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) +- queue_work(dev->wq, &dev->usb.stat_work); + } ++ ++ if (dev->drv->tx_status_data && ++ !test_and_set_bit(MT76_READING_STATS, &dev->phy.state)) ++ queue_work(dev->wq, &dev->usb.stat_work); + } + + static void mt76u_tx_status_data(struct work_struct *work) +-- +2.35.1 + diff --git a/queue-5.15/wifi-mt76-fix-coverity-overrun-call-in-mt76_get_txpo.patch b/queue-5.15/wifi-mt76-fix-coverity-overrun-call-in-mt76_get_txpo.patch new file mode 100644 index 00000000000..e9a5cf96e87 --- /dev/null +++ b/queue-5.15/wifi-mt76-fix-coverity-overrun-call-in-mt76_get_txpo.patch @@ -0,0 +1,44 @@ +From 1102e063073145520baf737edebdf1be2b6e83c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Nov 2022 10:35:37 +0800 +Subject: wifi: mt76: fix coverity overrun-call in mt76_get_txpower() + +From: Deren Wu + +[ Upstream commit 03dd0d49de7db680a856fa566963bb8421f46368 ] + +Make sure the nss is valid for nss_delta array. Return zero +if the index is invalid. + +Coverity message: +Event overrun-call: Overrunning callee's array of size 4 by passing +argument "n_chains" (which evaluates to 15) in call to +"mt76_tx_power_nss_delta". +int delta = mt76_tx_power_nss_delta(n_chains); + +Fixes: 07cda406308b ("mt76: fix rounding issues on converting per-chain and combined txpower") +Signed-off-by: Deren Wu +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index d1f00706d41e..4e4af6e17b50 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -1021,8 +1021,9 @@ static inline bool mt76_is_skb_pktid(u8 pktid) + static inline u8 mt76_tx_power_nss_delta(u8 nss) + { + static const u8 nss_delta[4] = { 0, 6, 9, 12 }; ++ u8 idx = nss - 1; + +- return nss_delta[nss - 1]; ++ return (idx < ARRAY_SIZE(nss_delta)) ? nss_delta[idx] : 0; + } + + static inline bool mt76_testmode_enabled(struct mt76_phy *phy) +-- +2.35.1 + diff --git a/queue-5.15/wifi-mt76-mt7921-fix-reporting-of-tx-aggr-histogram.patch b/queue-5.15/wifi-mt76-mt7921-fix-reporting-of-tx-aggr-histogram.patch new file mode 100644 index 00000000000..7d6f0fff933 --- /dev/null +++ b/queue-5.15/wifi-mt76-mt7921-fix-reporting-of-tx-aggr-histogram.patch @@ -0,0 +1,36 @@ +From 35399897f6f2596c009f3038bffa4f45b01a995e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 13:46:50 +0100 +Subject: wifi: mt76: mt7921: fix reporting of TX AGGR histogram + +From: Lorenzo Bianconi + +[ Upstream commit 028b4f22b37b88821fd87b56ce47b180583c774e ] + +Similar to mt7915, fix stats clash between bins [4-7] in 802.11 tx +aggregation histogram. + +Fixes: 163f4d22c118d ("mt76: mt7921: add MAC support") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +index 426e7a32bdc8..6cf0c9b1b8b9 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +@@ -1476,7 +1476,7 @@ mt7921_mac_update_mib_stats(struct mt7921_phy *phy) + mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0), + MT_MIB_RTS_FAIL_COUNT_MASK); + +- for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { ++ for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) { + u32 val, val2; + + val = mt76_rr(dev, MT_TX_AGG_CNT(0, i)); +-- +2.35.1 + diff --git a/queue-5.15/wifi-rsi-fix-handling-of-802.3-eapol-frames-sent-via.patch b/queue-5.15/wifi-rsi-fix-handling-of-802.3-eapol-frames-sent-via.patch new file mode 100644 index 00000000000..0065ed5acc3 --- /dev/null +++ b/queue-5.15/wifi-rsi-fix-handling-of-802.3-eapol-frames-sent-via.patch @@ -0,0 +1,92 @@ +From e4adb3d0f82f046598a5418224554757ed56a485 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Nov 2022 17:33:39 +0100 +Subject: wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port + +From: Marek Vasut + +[ Upstream commit b8f6efccbb9dc0ff5dee7e20d69a4747298ee603 ] + +When using wpa_supplicant v2.10, this driver is no longer able to +associate with any AP and fails in the EAPOL 4-way handshake while +sending the 2/4 message to the AP. The problem is not present in +wpa_supplicant v2.9 or older. The problem stems from HostAP commit +144314eaa ("wpa_supplicant: Send EAPOL frames over nl80211 where available") +which changes the way EAPOL frames are sent, from them being send +at L2 frames to them being sent via nl80211 control port. + +An EAPOL frame sent as L2 frame is passed to the WiFi driver with +skb->protocol ETH_P_PAE, while EAPOL frame sent via nl80211 control +port has skb->protocol set to ETH_P_802_3 . The later happens in +ieee80211_tx_control_port(), where the EAPOL frame is encapsulated +into 802.3 frame. + +The rsi_91x driver handles ETH_P_PAE EAPOL frames as high-priority +frames and sends them via highest-priority transmit queue, while +the ETH_P_802_3 frames are sent as regular frames. The EAPOL 4-way +handshake frames must be sent as highest-priority, otherwise the +4-way handshake times out. + +Therefore, to fix this problem, inspect the skb control flags and +if flag IEEE80211_TX_CTRL_PORT_CTRL_PROTO is set, assume this is +an EAPOL frame and transmit the frame via high-priority queue just +like other ETH_P_PAE frames. + +Fixes: 0eb42586cf87 ("rsi: data packet descriptor enhancements") +Signed-off-by: Marek Vasut +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221104163339.227432-1-marex@denx.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/rsi/rsi_91x_core.c | 4 +++- + drivers/net/wireless/rsi/rsi_91x_hal.c | 6 +++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c +index 6bfaab48b507..6b64a103f39f 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_core.c ++++ b/drivers/net/wireless/rsi/rsi_91x_core.c +@@ -465,7 +465,9 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb) + tid, 0); + } + } +- if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { ++ ++ if (IEEE80211_SKB_CB(skb)->control.flags & ++ IEEE80211_TX_CTRL_PORT_CTRL_PROTO) { + q_num = MGMT_SOFT_Q; + skb->priority = q_num; + } +diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c +index dca81a4bbdd7..30d2eccbcadd 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_hal.c ++++ b/drivers/net/wireless/rsi/rsi_91x_hal.c +@@ -162,12 +162,16 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + u8 header_size; + u8 vap_id = 0; + u8 dword_align_bytes; ++ bool tx_eapol; + u16 seq_num; + + info = IEEE80211_SKB_CB(skb); + vif = info->control.vif; + tx_params = (struct skb_info *)info->driver_data; + ++ tx_eapol = IEEE80211_SKB_CB(skb)->control.flags & ++ IEEE80211_TX_CTRL_PORT_CTRL_PROTO; ++ + header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc); + if (header_size > skb_headroom(skb)) { + rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__); +@@ -231,7 +235,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + } + } + +- if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { ++ if (tx_eapol) { + rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n"); + + data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE); +-- +2.35.1 + diff --git a/queue-5.15/wifi-rtl8xxxu-add-__packed-to-struct-rtl8723bu_c2h.patch b/queue-5.15/wifi-rtl8xxxu-add-__packed-to-struct-rtl8723bu_c2h.patch new file mode 100644 index 00000000000..af97db50ae1 --- /dev/null +++ b/queue-5.15/wifi-rtl8xxxu-add-__packed-to-struct-rtl8723bu_c2h.patch @@ -0,0 +1,41 @@ +From 3e12c5304fb09595246cf4123efec3d1fc3f980d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 16:13:57 +0200 +Subject: wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h + +From: Bitterblue Smith + +[ Upstream commit dd469a754afdb782ba3033cee102147493dc39f4 ] + +This struct is used to access a sequence of bytes received from the +wifi chip. It must not have any padding bytes between the members. + +This doesn't change anything on my system, possibly because currently +none of the members need more than byte alignment. + +Fixes: b2b43b7837ba ("rtl8xxxu: Initial functionality to handle C2H events for 8723bu") +Signed-off-by: Bitterblue Smith +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/1a270918-da22-ff5f-29fc-7855f740c5ba@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +index 7ddce3c3f0c4..cd3ff9847ced 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1190,7 +1190,7 @@ struct rtl8723bu_c2h { + u8 bw; + } __packed ra_report; + }; +-}; ++} __packed; + + struct rtl8xxxu_fileops; + +-- +2.35.1 + diff --git a/queue-5.15/wifi-rtl8xxxu-fix-reading-the-vendor-of-combo-chips.patch b/queue-5.15/wifi-rtl8xxxu-fix-reading-the-vendor-of-combo-chips.patch new file mode 100644 index 00000000000..332c40410a0 --- /dev/null +++ b/queue-5.15/wifi-rtl8xxxu-fix-reading-the-vendor-of-combo-chips.patch @@ -0,0 +1,83 @@ +From e6ab3a541fa333d4aaa34fa490c5eb2aeeaf187e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Oct 2022 13:56:09 +0300 +Subject: wifi: rtl8xxxu: Fix reading the vendor of combo chips + +From: Bitterblue Smith + +[ Upstream commit 6f103aeb5e985ac08f3a4a049a2c17294f40cff9 ] + +The wifi + bluetooth combo chips (RTL8723AU and RTL8723BU) read the +chip vendor from the wrong register because the val32 variable gets +overwritten. Add one more variable to avoid this. + +This had no real effect on RTL8723BU. It may have had an effect on +RTL8723AU. + +Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") +Signed-off-by: Bitterblue Smith +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/24af8024-2f07-552b-93d8-38823d8e3cb0@gmail.com +Signed-off-by: Sasha Levin +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index e74c885a04e5..2a4ecbb0fce6 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -1607,18 +1607,18 @@ static void rtl8xxxu_print_chipinfo(struct rtl8xxxu_priv *priv) + static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + { + struct device *dev = &priv->udev->dev; +- u32 val32, bonding; ++ u32 val32, bonding, sys_cfg; + u16 val16; + +- val32 = rtl8xxxu_read32(priv, REG_SYS_CFG); +- priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >> ++ sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); ++ priv->chip_cut = (sys_cfg & SYS_CFG_CHIP_VERSION_MASK) >> + SYS_CFG_CHIP_VERSION_SHIFT; +- if (val32 & SYS_CFG_TRP_VAUX_EN) { ++ if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -ENOTSUPP; + } + +- if (val32 & SYS_CFG_BT_FUNC) { ++ if (sys_cfg & SYS_CFG_BT_FUNC) { + if (priv->chip_cut >= 3) { + sprintf(priv->chip_name, "8723BU"); + priv->rtl_chip = RTL8723B; +@@ -1640,7 +1640,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + if (val32 & MULTI_GPS_FUNC_EN) + priv->has_gps = 1; + priv->is_multi_func = 1; +- } else if (val32 & SYS_CFG_TYPE_ID) { ++ } else if (sys_cfg & SYS_CFG_TYPE_ID) { + bonding = rtl8xxxu_read32(priv, REG_HPON_FSM); + bonding &= HPON_FSM_BONDING_MASK; + if (priv->fops->tx_desc_size == +@@ -1688,7 +1688,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + case RTL8188E: + case RTL8192E: + case RTL8723B: +- switch (val32 & SYS_CFG_VENDOR_EXT_MASK) { ++ switch (sys_cfg & SYS_CFG_VENDOR_EXT_MASK) { + case SYS_CFG_VENDOR_ID_TSMC: + sprintf(priv->chip_vendor, "TSMC"); + break; +@@ -1705,7 +1705,7 @@ static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv) + } + break; + default: +- if (val32 & SYS_CFG_VENDOR_ID) { ++ if (sys_cfg & SYS_CFG_VENDOR_ID) { + sprintf(priv->chip_vendor, "UMC"); + priv->vendor_umc = 1; + } else { +-- +2.35.1 + diff --git a/queue-5.15/wifi-rtl8xxxu-fix-the-channel-width-reporting.patch b/queue-5.15/wifi-rtl8xxxu-fix-the-channel-width-reporting.patch new file mode 100644 index 00000000000..b53172a88a5 --- /dev/null +++ b/queue-5.15/wifi-rtl8xxxu-fix-the-channel-width-reporting.patch @@ -0,0 +1,62 @@ +From e8a3d4b2d05a3caaf9ea52c013e2785962361b42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Dec 2022 16:15:08 +0200 +Subject: wifi: rtl8xxxu: Fix the channel width reporting + +From: Bitterblue Smith + +[ Upstream commit 76c16af2cb10282274596e21add2c9f0b95c941b ] + +The gen 2 chips RTL8192EU and RTL8188FU periodically send the driver +reports about the TX rate, and the driver passes these reports to +sta_statistics. The reports from RTL8192EU may or may not include the +channel width. The reports from RTL8188FU do not include it. + +Only access the c2h->ra_report.bw field if the report (skb) is big +enough. + +The other problem fixed here is that the code was actually never +changing the channel width initially reported by +rtl8xxxu_bss_info_changed because the value of RATE_INFO_BW_20 is 0. + +Fixes: 0985d3a410ac ("rtl8xxxu: Feed current txrate information for mac80211") +Signed-off-by: Bitterblue Smith +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/5b41f1ae-72e7-6b7a-2459-b736399a1c40@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 2a4ecbb0fce6..7370d92a3bda 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5517,7 +5517,6 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) + rarpt->txrate.flags = 0; + rate = c2h->ra_report.rate; + sgi = c2h->ra_report.sgi; +- bw = c2h->ra_report.bw; + + if (rate < DESC_RATE_MCS0) { + rarpt->txrate.legacy = +@@ -5534,8 +5533,13 @@ static void rtl8xxxu_c2hcmd_callback(struct work_struct *work) + RATE_INFO_FLAGS_SHORT_GI; + } + +- if (bw == RATE_INFO_BW_20) +- rarpt->txrate.bw |= RATE_INFO_BW_20; ++ if (skb->len >= offsetofend(typeof(*c2h), ra_report.bw)) { ++ if (c2h->ra_report.bw == RTL8XXXU_CHANNEL_WIDTH_40) ++ bw = RATE_INFO_BW_40; ++ else ++ bw = RATE_INFO_BW_20; ++ rarpt->txrate.bw = bw; ++ } + } + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); + rarpt->bit_rate = bit_rate; +-- +2.35.1 + diff --git a/queue-5.15/x86-hyperv-remove-unregister-syscore-call-from-hyper.patch b/queue-5.15/x86-hyperv-remove-unregister-syscore-call-from-hyper.patch new file mode 100644 index 00000000000..f5d832a3c72 --- /dev/null +++ b/queue-5.15/x86-hyperv-remove-unregister-syscore-call-from-hyper.patch @@ -0,0 +1,48 @@ +From d4d49f63d349390741e776a412fff1a4dd215fae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 22:14:51 -0800 +Subject: x86/hyperv: Remove unregister syscore call from Hyper-V cleanup + +From: Gaurav Kohli + +[ Upstream commit 32c97d980e2eef25465d453f2956a9ca68926a3c ] + +Hyper-V cleanup code comes under panic path where preemption and irq +is already disabled. So calling of unregister_syscore_ops might schedule +out the thread even for the case where mutex lock is free. +hyperv_cleanup + unregister_syscore_ops + mutex_lock(&syscore_ops_lock) + might_sleep +Here might_sleep might schedule out this thread, where voluntary preemption +config is on and this thread will never comes back. And also this was added +earlier to maintain the symmetry which is not required as this can comes +during crash shutdown path only. + +To prevent the same, removing unregister_syscore_ops function call. + +Signed-off-by: Gaurav Kohli +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/1669443291-2575-1-git-send-email-gauravkohli@linux.microsoft.com +Signed-off-by: Wei Liu +Signed-off-by: Sasha Levin +--- + arch/x86/hyperv/hv_init.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c +index 762f10cdfb7a..95f98af74fdc 100644 +--- a/arch/x86/hyperv/hv_init.c ++++ b/arch/x86/hyperv/hv_init.c +@@ -469,8 +469,6 @@ void hyperv_cleanup(void) + { + union hv_x64_msr_hypercall_contents hypercall_msr; + +- unregister_syscore_ops(&hv_syscore_ops); +- + /* Reset our OS id */ + wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0); + +-- +2.35.1 + diff --git a/queue-5.15/x86-sgx-reduce-delay-and-interference-of-enclave-rel.patch b/queue-5.15/x86-sgx-reduce-delay-and-interference-of-enclave-rel.patch new file mode 100644 index 00000000000..202e63c98c7 --- /dev/null +++ b/queue-5.15/x86-sgx-reduce-delay-and-interference-of-enclave-rel.patch @@ -0,0 +1,142 @@ +From 9c3fd3efb9c3b5f41a11720ed4f16a2710c4d594 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 31 Oct 2022 10:29:58 -0700 +Subject: x86/sgx: Reduce delay and interference of enclave release + +From: Reinette Chatre + +[ Upstream commit 7b72c823ddf8aaaec4e9fb28e6fbe4d511e7dad1 ] + +commit 8795359e35bc ("x86/sgx: Silence softlockup detection when +releasing large enclaves") introduced a cond_resched() during enclave +release where the EREMOVE instruction is applied to every 4k enclave +page. Giving other tasks an opportunity to run while tearing down a +large enclave placates the soft lockup detector but Iqbal found +that the fix causes a 25% performance degradation of a workload +run using Gramine. + +Gramine maintains a 1:1 mapping between processes and SGX enclaves. +That means if a workload in an enclave creates a subprocess then +Gramine creates a duplicate enclave for that subprocess to run in. +The consequence is that the release of the enclave used to run +the subprocess can impact the performance of the workload that is +run in the original enclave, especially in large enclaves when +SGX2 is not in use. + +The workload run by Iqbal behaves as follows: +Create enclave (enclave "A") +/* Initialize workload in enclave "A" */ +Create enclave (enclave "B") +/* Run subprocess in enclave "B" and send result to enclave "A" */ +Release enclave (enclave "B") +/* Run workload in enclave "A" */ +Release enclave (enclave "A") + +The performance impact of releasing enclave "B" in the above scenario +is amplified when there is a lot of SGX memory and the enclave size +matches the SGX memory. When there is 128GB SGX memory and an enclave +size of 128GB, from the time enclave "B" starts the 128GB SGX memory +is oversubscribed with a combined demand for 256GB from the two +enclaves. + +Before commit 8795359e35bc ("x86/sgx: Silence softlockup detection when +releasing large enclaves") enclave release was done in a tight loop +without giving other tasks a chance to run. Even though the system +experienced soft lockups the workload (run in enclave "A") obtained +good performance numbers because when the workload started running +there was no interference. + +Commit 8795359e35bc ("x86/sgx: Silence softlockup detection when +releasing large enclaves") gave other tasks opportunity to run while an +enclave is released. The impact of this in this scenario is that while +enclave "B" is released and needing to access each page that belongs +to it in order to run the SGX EREMOVE instruction on it, enclave "A" +is attempting to run the workload needing to access the enclave +pages that belong to it. This causes a lot of swapping due to the +demand for the oversubscribed SGX memory. Longer latencies are +experienced by the workload in enclave "A" while enclave "B" is +released. + +Improve the performance of enclave release while still avoiding the +soft lockup detector with two enhancements: +- Only call cond_resched() after XA_CHECK_SCHED iterations. +- Use the xarray advanced API to keep the xarray locked for + XA_CHECK_SCHED iterations instead of locking and unlocking + at every iteration. + +This batching solution is copied from sgx_encl_may_map() that +also iterates through all enclave pages using this technique. + +With this enhancement the workload experiences a 5% +performance degradation when compared to a kernel without +commit 8795359e35bc ("x86/sgx: Silence softlockup detection when +releasing large enclaves"), an improvement to the reported 25% +degradation, while still placating the soft lockup detector. + +Scenarios with poor performance are still possible even with these +enhancements. For example, short workloads creating sub processes +while running in large enclaves. Further performance improvements +are pursued in user space through avoiding to create duplicate enclaves +for certain sub processes, and using SGX2 that will do lazy allocation +of pages as needed so enclaves created for sub processes start quickly +and release quickly. + +Fixes: 8795359e35bc ("x86/sgx: Silence softlockup detection when releasing large enclaves") +Reported-by: Md Iqbal Hossain +Signed-off-by: Reinette Chatre +Signed-off-by: Dave Hansen +Tested-by: Md Iqbal Hossain +Link: https://lore.kernel.org/all/00efa80dd9e35dc85753e1c5edb0344ac07bb1f0.1667236485.git.reinette.chatre%40intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/sgx/encl.c | 23 +++++++++++++++++++---- + 1 file changed, 19 insertions(+), 4 deletions(-) + +diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c +index 19876ebfb504..fa5777af8da1 100644 +--- a/arch/x86/kernel/cpu/sgx/encl.c ++++ b/arch/x86/kernel/cpu/sgx/encl.c +@@ -533,11 +533,15 @@ const struct vm_operations_struct sgx_vm_ops = { + void sgx_encl_release(struct kref *ref) + { + struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount); ++ unsigned long max_page_index = PFN_DOWN(encl->base + encl->size - 1); + struct sgx_va_page *va_page; + struct sgx_encl_page *entry; +- unsigned long index; ++ unsigned long count = 0; ++ ++ XA_STATE(xas, &encl->page_array, PFN_DOWN(encl->base)); + +- xa_for_each(&encl->page_array, index, entry) { ++ xas_lock(&xas); ++ xas_for_each(&xas, entry, max_page_index) { + if (entry->epc_page) { + /* + * The page and its radix tree entry cannot be freed +@@ -552,9 +556,20 @@ void sgx_encl_release(struct kref *ref) + } + + kfree(entry); +- /* Invoke scheduler to prevent soft lockups. */ +- cond_resched(); ++ /* ++ * Invoke scheduler on every XA_CHECK_SCHED iteration ++ * to prevent soft lockups. ++ */ ++ if (!(++count % XA_CHECK_SCHED)) { ++ xas_pause(&xas); ++ xas_unlock(&xas); ++ ++ cond_resched(); ++ ++ xas_lock(&xas); ++ } + } ++ xas_unlock(&xas); + + xa_destroy(&encl->page_array); + +-- +2.35.1 + diff --git a/queue-5.15/x86-xen-fix-memory-leak-in-xen_init_lock_cpu.patch b/queue-5.15/x86-xen-fix-memory-leak-in-xen_init_lock_cpu.patch new file mode 100644 index 00000000000..b15ff221118 --- /dev/null +++ b/queue-5.15/x86-xen-fix-memory-leak-in-xen_init_lock_cpu.patch @@ -0,0 +1,64 @@ +From becd886ace7ae072141c7a0bc4ca4a46991e60de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 23:58:58 +0800 +Subject: x86/xen: Fix memory leak in xen_init_lock_cpu() + +From: Xiu Jianfeng + +[ Upstream commit ca84ce153d887b1dc8b118029976cc9faf2a9b40 ] + +In xen_init_lock_cpu(), the @name has allocated new string by kasprintf(), +if bind_ipi_to_irqhandler() fails, it should be freed, otherwise may lead +to a memory leak issue, fix it. + +Fixes: 2d9e1e2f58b5 ("xen: implement Xen-specific spinlocks") +Signed-off-by: Xiu Jianfeng +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/r/20221123155858.11382-3-xiujianfeng@huawei.com +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + arch/x86/xen/spinlock.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c +index 043c73dfd2c9..5c6fc16e4b92 100644 +--- a/arch/x86/xen/spinlock.c ++++ b/arch/x86/xen/spinlock.c +@@ -75,6 +75,7 @@ void xen_init_lock_cpu(int cpu) + cpu, per_cpu(lock_kicker_irq, cpu)); + + name = kasprintf(GFP_KERNEL, "spinlock%d", cpu); ++ per_cpu(irq_name, cpu) = name; + irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR, + cpu, + dummy_handler, +@@ -85,7 +86,6 @@ void xen_init_lock_cpu(int cpu) + if (irq >= 0) { + disable_irq(irq); /* make sure it's never delivered */ + per_cpu(lock_kicker_irq, cpu) = irq; +- per_cpu(irq_name, cpu) = name; + } + + printk("cpu %d spinlock event irq %d\n", cpu, irq); +@@ -98,6 +98,8 @@ void xen_uninit_lock_cpu(int cpu) + if (!xen_pvspin) + return; + ++ kfree(per_cpu(irq_name, cpu)); ++ per_cpu(irq_name, cpu) = NULL; + /* + * When booting the kernel with 'mitigations=auto,nosmt', the secondary + * CPUs are not activated, and lock_kicker_irq is not initialized. +@@ -108,8 +110,6 @@ void xen_uninit_lock_cpu(int cpu) + + unbind_from_irqhandler(irq, NULL); + per_cpu(lock_kicker_irq, cpu) = -1; +- kfree(per_cpu(irq_name, cpu)); +- per_cpu(irq_name, cpu) = NULL; + } + + PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen); +-- +2.35.1 + diff --git a/queue-5.15/x86-xen-fix-memory-leak-in-xen_smp_intr_init-_pv.patch b/queue-5.15/x86-xen-fix-memory-leak-in-xen_smp_intr_init-_pv.patch new file mode 100644 index 00000000000..0bc67b39dce --- /dev/null +++ b/queue-5.15/x86-xen-fix-memory-leak-in-xen_smp_intr_init-_pv.patch @@ -0,0 +1,178 @@ +From 820c61fd8fcc43870d0fa0ba6bf7b8368e1bf0ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Nov 2022 23:58:57 +0800 +Subject: x86/xen: Fix memory leak in xen_smp_intr_init{_pv}() + +From: Xiu Jianfeng + +[ Upstream commit 69143f60868b3939ddc89289b29db593b647295e ] + +These local variables @{resched|pmu|callfunc...}_name saves the new +string allocated by kasprintf(), and when bind_{v}ipi_to_irqhandler() +fails, it goes to the @fail tag, and calls xen_smp_intr_free{_pv}() to +free resource, however the new string is not saved, which cause a memory +leak issue. fix it. + +Fixes: 9702785a747a ("i386: move xen") +Signed-off-by: Xiu Jianfeng +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/r/20221123155858.11382-2-xiujianfeng@huawei.com +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + arch/x86/xen/smp.c | 24 ++++++++++++------------ + arch/x86/xen/smp_pv.c | 12 ++++++------ + 2 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c +index c1b2f764b29a..cdec892b28e2 100644 +--- a/arch/x86/xen/smp.c ++++ b/arch/x86/xen/smp.c +@@ -32,30 +32,30 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) + + void xen_smp_intr_free(unsigned int cpu) + { ++ kfree(per_cpu(xen_resched_irq, cpu).name); ++ per_cpu(xen_resched_irq, cpu).name = NULL; + if (per_cpu(xen_resched_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL); + per_cpu(xen_resched_irq, cpu).irq = -1; +- kfree(per_cpu(xen_resched_irq, cpu).name); +- per_cpu(xen_resched_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_callfunc_irq, cpu).name); ++ per_cpu(xen_callfunc_irq, cpu).name = NULL; + if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL); + per_cpu(xen_callfunc_irq, cpu).irq = -1; +- kfree(per_cpu(xen_callfunc_irq, cpu).name); +- per_cpu(xen_callfunc_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_debug_irq, cpu).name); ++ per_cpu(xen_debug_irq, cpu).name = NULL; + if (per_cpu(xen_debug_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL); + per_cpu(xen_debug_irq, cpu).irq = -1; +- kfree(per_cpu(xen_debug_irq, cpu).name); +- per_cpu(xen_debug_irq, cpu).name = NULL; + } ++ kfree(per_cpu(xen_callfuncsingle_irq, cpu).name); ++ per_cpu(xen_callfuncsingle_irq, cpu).name = NULL; + if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq, + NULL); + per_cpu(xen_callfuncsingle_irq, cpu).irq = -1; +- kfree(per_cpu(xen_callfuncsingle_irq, cpu).name); +- per_cpu(xen_callfuncsingle_irq, cpu).name = NULL; + } + } + +@@ -65,6 +65,7 @@ int xen_smp_intr_init(unsigned int cpu) + char *resched_name, *callfunc_name, *debug_name; + + resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu); ++ per_cpu(xen_resched_irq, cpu).name = resched_name; + rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR, + cpu, + xen_reschedule_interrupt, +@@ -74,9 +75,9 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_resched_irq, cpu).irq = rc; +- per_cpu(xen_resched_irq, cpu).name = resched_name; + + callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu); ++ per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR, + cpu, + xen_call_function_interrupt, +@@ -86,10 +87,10 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_callfunc_irq, cpu).irq = rc; +- per_cpu(xen_callfunc_irq, cpu).name = callfunc_name; + + if (!xen_fifo_events) { + debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu); ++ per_cpu(xen_debug_irq, cpu).name = debug_name; + rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, + xen_debug_interrupt, + IRQF_PERCPU | IRQF_NOBALANCING, +@@ -97,10 +98,10 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_debug_irq, cpu).irq = rc; +- per_cpu(xen_debug_irq, cpu).name = debug_name; + } + + callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu); ++ per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR, + cpu, + xen_call_function_single_interrupt, +@@ -110,7 +111,6 @@ int xen_smp_intr_init(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_callfuncsingle_irq, cpu).irq = rc; +- per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name; + + return 0; + +diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c +index cd5539fc5eb4..b47b5111397a 100644 +--- a/arch/x86/xen/smp_pv.c ++++ b/arch/x86/xen/smp_pv.c +@@ -97,18 +97,18 @@ asmlinkage __visible void cpu_bringup_and_idle(void) + + void xen_smp_intr_free_pv(unsigned int cpu) + { ++ kfree(per_cpu(xen_irq_work, cpu).name); ++ per_cpu(xen_irq_work, cpu).name = NULL; + if (per_cpu(xen_irq_work, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL); + per_cpu(xen_irq_work, cpu).irq = -1; +- kfree(per_cpu(xen_irq_work, cpu).name); +- per_cpu(xen_irq_work, cpu).name = NULL; + } + ++ kfree(per_cpu(xen_pmu_irq, cpu).name); ++ per_cpu(xen_pmu_irq, cpu).name = NULL; + if (per_cpu(xen_pmu_irq, cpu).irq >= 0) { + unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL); + per_cpu(xen_pmu_irq, cpu).irq = -1; +- kfree(per_cpu(xen_pmu_irq, cpu).name); +- per_cpu(xen_pmu_irq, cpu).name = NULL; + } + } + +@@ -118,6 +118,7 @@ int xen_smp_intr_init_pv(unsigned int cpu) + char *callfunc_name, *pmu_name; + + callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu); ++ per_cpu(xen_irq_work, cpu).name = callfunc_name; + rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR, + cpu, + xen_irq_work_interrupt, +@@ -127,10 +128,10 @@ int xen_smp_intr_init_pv(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_irq_work, cpu).irq = rc; +- per_cpu(xen_irq_work, cpu).name = callfunc_name; + + if (is_xen_pmu) { + pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu); ++ per_cpu(xen_pmu_irq, cpu).name = pmu_name; + rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu, + xen_pmu_irq_handler, + IRQF_PERCPU|IRQF_NOBALANCING, +@@ -138,7 +139,6 @@ int xen_smp_intr_init_pv(unsigned int cpu) + if (rc < 0) + goto fail; + per_cpu(xen_pmu_irq, cpu).irq = rc; +- per_cpu(xen_pmu_irq, cpu).name = pmu_name; + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.15/xen-privcmd-fix-a-possible-warning-in-privcmd_ioctl_.patch b/queue-5.15/xen-privcmd-fix-a-possible-warning-in-privcmd_ioctl_.patch new file mode 100644 index 00000000000..6a57d7be63d --- /dev/null +++ b/queue-5.15/xen-privcmd-fix-a-possible-warning-in-privcmd_ioctl_.patch @@ -0,0 +1,46 @@ +From 2443f12d37ae745487829aabeb6a1b4e24b61ed6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Nov 2022 21:07:45 -0800 +Subject: xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource() + +From: Harshit Mogalapalli + +[ Upstream commit 8b997b2bb2c53b76a6db6c195930e9ab8e4b0c79 ] + +As 'kdata.num' is user-controlled data, if user tries to allocate +memory larger than(>=) MAX_ORDER, then kcalloc() will fail, it +creates a stack trace and messes up dmesg with a warning. + +Call trace: +-> privcmd_ioctl +--> privcmd_ioctl_mmap_resource + +Add __GFP_NOWARN in order to avoid too large allocation warning. +This is detected by static analysis using smatch. + +Fixes: 3ad0876554ca ("xen/privcmd: add IOCTL_PRIVCMD_MMAP_RESOURCE") +Signed-off-by: Harshit Mogalapalli +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/r/20221126050745.778967-1-harshit.m.mogalapalli@oracle.com +Signed-off-by: Juergen Gross +Signed-off-by: Sasha Levin +--- + drivers/xen/privcmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c +index e88e8f6f0a33..719c5d1dda27 100644 +--- a/drivers/xen/privcmd.c ++++ b/drivers/xen/privcmd.c +@@ -760,7 +760,7 @@ static long privcmd_ioctl_mmap_resource(struct file *file, + goto out; + } + +- pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL); ++ pfns = kcalloc(kdata.num, sizeof(*pfns), GFP_KERNEL | __GFP_NOWARN); + if (!pfns) { + rc = -ENOMEM; + goto out; +-- +2.35.1 + diff --git a/queue-5.15/xprtrdma-fix-regbuf-data-not-freed-in-rpcrdma_req_cr.patch b/queue-5.15/xprtrdma-fix-regbuf-data-not-freed-in-rpcrdma_req_cr.patch new file mode 100644 index 00000000000..2a909ae378b --- /dev/null +++ b/queue-5.15/xprtrdma-fix-regbuf-data-not-freed-in-rpcrdma_req_cr.patch @@ -0,0 +1,36 @@ +From f2b30ab54684e38a76efdb303c22e6ef347715d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 20 Nov 2022 15:34:29 +0800 +Subject: xprtrdma: Fix regbuf data not freed in rpcrdma_req_create() + +From: Zhang Xiaoxu + +[ Upstream commit 9181f40fb2952fd59ecb75e7158620c9c669eee3 ] + +If rdma receive buffer allocate failed, should call rpcrdma_regbuf_free() +to free the send buffer, otherwise, the buffer data will be leaked. + +Fixes: bb93a1ae2bf4 ("xprtrdma: Allocate req's regbufs at xprt create time") +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/xprtrdma/verbs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c +index 1295f9ab839f..507ba8b79992 100644 +--- a/net/sunrpc/xprtrdma/verbs.c ++++ b/net/sunrpc/xprtrdma/verbs.c +@@ -858,7 +858,7 @@ struct rpcrdma_req *rpcrdma_req_create(struct rpcrdma_xprt *r_xprt, size_t size, + return req; + + out3: +- kfree(req->rl_sendbuf); ++ rpcrdma_regbuf_free(req->rl_sendbuf); + out2: + kfree(req); + out1: +-- +2.35.1 +