From: Sasha Levin Date: Mon, 17 Oct 2022 02:10:15 +0000 (-0400) Subject: Fixes for 5.19 X-Git-Tag: v5.4.219~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a47867185f6550d49bf3cffbe9b19ca196b34536;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.19 Signed-off-by: Sasha Levin --- diff --git a/queue-5.19/acpi-apei-do-not-add-task_work-to-kernel-thread-to-a.patch b/queue-5.19/acpi-apei-do-not-add-task_work-to-kernel-thread-to-a.patch new file mode 100644 index 00000000000..771071d980f --- /dev/null +++ b/queue-5.19/acpi-apei-do-not-add-task_work-to-kernel-thread-to-a.patch @@ -0,0 +1,78 @@ +From 617cfbfe94d529838c40d2f8730a3fd590d886f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 15:49:53 +0800 +Subject: ACPI: APEI: do not add task_work to kernel thread to avoid memory + leak + +From: Shuai Xue + +[ Upstream commit 415fed694fe11395df56e05022d6e7cee1d39dd3 ] + +If an error is detected as a result of user-space process accessing a +corrupt memory location, the CPU may take an abort. Then the platform +firmware reports kernel via NMI like notifications, e.g. NOTIFY_SEA, +NOTIFY_SOFTWARE_DELEGATED, etc. + +For NMI like notifications, commit 7f17b4a121d0 ("ACPI: APEI: Kick the +memory_failure() queue for synchronous errors") keep track of whether +memory_failure() work was queued, and make task_work pending to flush out +the queue so that the work is processed before return to user-space. + +The code use init_mm to check whether the error occurs in user space: + + if (current->mm != &init_mm) + +The condition is always true, becase _nobody_ ever has "init_mm" as a real +VM any more. + +In addition to abort, errors can also be signaled as asynchronous +exceptions, such as interrupt and SError. In such case, the interrupted +current process could be any kind of thread. When a kernel thread is +interrupted, the work ghes_kick_task_work deferred to task_work will never +be processed because entry_handler returns to call ret_to_kernel() instead +of ret_to_user(). Consequently, the estatus_node alloced from +ghes_estatus_pool in ghes_in_nmi_queue_one_entry() will not be freed. +After around 200 allocations in our platform, the ghes_estatus_pool will +run of memory and ghes_in_nmi_queue_one_entry() returns ENOMEM. As a +result, the event failed to be processed. + + sdei: event 805 on CPU 113 failed with error: -2 + +Finally, a lot of unhandled events may cause platform firmware to exceed +some threshold and reboot. + +The condition should generally just do + + if (current->mm) + +as described in active_mm.rst documentation. + +Then if an asynchronous error is detected when a kernel thread is running, +(e.g. when detected by a background scrubber), do not add task_work to it +as the original patch intends to do. + +Fixes: 7f17b4a121d0 ("ACPI: APEI: Kick the memory_failure() queue for synchronous errors") +Signed-off-by: Shuai Xue +Reviewed-by: Tony Luck +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/apei/ghes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c +index d91ad378c00d..80ad530583c9 100644 +--- a/drivers/acpi/apei/ghes.c ++++ b/drivers/acpi/apei/ghes.c +@@ -985,7 +985,7 @@ static void ghes_proc_in_irq(struct irq_work *irq_work) + ghes_estatus_cache_add(generic, estatus); + } + +- if (task_work_pending && current->mm != &init_mm) { ++ if (task_work_pending && current->mm) { + estatus_node->task_work.func = ghes_kick_task_work; + estatus_node->task_work_cpu = smp_processor_id(); + ret = task_work_add(current, &estatus_node->task_work, +-- +2.35.1 + diff --git a/queue-5.19/acpi-pcc-fix-tx-acknowledge-in-the-pcc-address-space.patch b/queue-5.19/acpi-pcc-fix-tx-acknowledge-in-the-pcc-address-space.patch new file mode 100644 index 00000000000..cb4f0bb23e7 --- /dev/null +++ b/queue-5.19/acpi-pcc-fix-tx-acknowledge-in-the-pcc-address-space.patch @@ -0,0 +1,43 @@ +From 765908939efbdccf1e919ac8540d967b14353a25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 17:45:00 +0800 +Subject: ACPI: PCC: Fix Tx acknowledge in the PCC address space handler + +From: Huisong Li + +[ Upstream commit 18729106c26fb97d4c9ae63ba7aba9889a058dc4 ] + +Currently, mbox_client_txdone() is called from the PCC address space +handler and that expects the user the Tx state machine to be controlled +by the client which is not the case and the below warning is thrown: + + | PCCT: Client can't run the TX ticker + +Let the controller run the state machine and the end of Tx can be +acknowledge by calling mbox_chan_txdone() instead. + +Fixes: 77e2a04745ff ("ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype") +Signed-off-by: Huisong Li +Reviewed-by: Sudeep Holla +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_pcc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c +index 16ba875e3293..ee4ce5ba1fb2 100644 +--- a/drivers/acpi/acpi_pcc.c ++++ b/drivers/acpi/acpi_pcc.c +@@ -121,7 +121,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, + } + } + +- mbox_client_txdone(data->pcc_chan->mchan, ret); ++ mbox_chan_txdone(data->pcc_chan->mchan, ret); + + memcpy_fromio(value, data->pcc_comm_addr, data->ctx.length); + +-- +2.35.1 + diff --git a/queue-5.19/acpi-pcc-release-resources-on-address-space-setup-fa.patch b/queue-5.19/acpi-pcc-release-resources-on-address-space-setup-fa.patch new file mode 100644 index 00000000000..b32fe61734b --- /dev/null +++ b/queue-5.19/acpi-pcc-release-resources-on-address-space-setup-fa.patch @@ -0,0 +1,47 @@ +From 8a024b2e8bf4f41c6df5feef3cbceecad3e6e7d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 12:33:19 -0300 +Subject: ACPI: PCC: Release resources on address space setup failure path + +From: Rafael Mendonca + +[ Upstream commit f890157e61b85ce8ae01a41ffa375e3b99853698 ] + +The allocated memory for the pcc_data struct doesn't get freed under an +error path in pcc_mbox_request_channel() or acpi_os_ioremap(). Also, the +PCC mailbox channel doesn't get freed under an error path in +acpi_os_ioremap(). + +Fixes: 77e2a04745ff8 ("ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype") +Signed-off-by: Rafael Mendonca +Reviewed-by: Sudeep Holla +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_pcc.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c +index a12b55d81209..84f1ac416b57 100644 +--- a/drivers/acpi/acpi_pcc.c ++++ b/drivers/acpi/acpi_pcc.c +@@ -63,6 +63,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, + if (IS_ERR(data->pcc_chan)) { + pr_err("Failed to find PCC channel for subspace %d\n", + ctx->subspace_id); ++ kfree(data); + return AE_NOT_FOUND; + } + +@@ -72,6 +73,8 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function, + if (!data->pcc_comm_addr) { + pr_err("Failed to ioremap PCC comm region mem for %d\n", + ctx->subspace_id); ++ pcc_mbox_free_channel(data->pcc_chan); ++ kfree(data); + return AE_NO_MEMORY; + } + +-- +2.35.1 + diff --git a/queue-5.19/acpi-pcc-replace-wait_for_completion.patch b/queue-5.19/acpi-pcc-replace-wait_for_completion.patch new file mode 100644 index 00000000000..0315ccaf3cf --- /dev/null +++ b/queue-5.19/acpi-pcc-replace-wait_for_completion.patch @@ -0,0 +1,76 @@ +From dd448a0fb78812e156bc4c79c050e465d53d260c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 17:44:59 +0800 +Subject: ACPI: PCC: replace wait_for_completion() + +From: Huisong Li + +[ Upstream commit 91cefefb699120efd0a5ba345d12626b688f86ce ] + +Currently, the function waiting for completion of mailbox operation is +'wait_for_completion()'. The PCC method will be permanently blocked if +this mailbox message fails to execute. So this patch replaces it with +'wait_for_completion_timeout()'. And set the timeout interval to an +arbitrary retries on top of nominal to prevent the remote processor is +slow to respond to PCC commands. + +Fixes: 77e2a04745ff ("ACPI: PCC: Implement OperationRegion handler for the PCC Type 3 subtype") +Signed-off-by: Huisong Li +Reviewed-by: Sudeep Holla +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_pcc.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c +index 84f1ac416b57..16ba875e3293 100644 +--- a/drivers/acpi/acpi_pcc.c ++++ b/drivers/acpi/acpi_pcc.c +@@ -23,6 +23,12 @@ + + #include + ++/* ++ * Arbitrary retries in case the remote processor is slow to respond ++ * to PCC commands ++ */ ++#define PCC_CMD_WAIT_RETRIES_NUM 500 ++ + struct pcc_data { + struct pcc_mbox_chan *pcc_chan; + void __iomem *pcc_comm_addr; +@@ -89,6 +95,7 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, + { + int ret; + struct pcc_data *data = region_context; ++ u64 usecs_lat; + + reinit_completion(&data->done); + +@@ -99,8 +106,20 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr, + if (ret < 0) + return AE_ERROR; + +- if (data->pcc_chan->mchan->mbox->txdone_irq) +- wait_for_completion(&data->done); ++ if (data->pcc_chan->mchan->mbox->txdone_irq) { ++ /* ++ * pcc_chan->latency is just a Nominal value. In reality the remote ++ * processor could be much slower to reply. So add an arbitrary ++ * amount of wait on top of Nominal. ++ */ ++ usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency; ++ ret = wait_for_completion_timeout(&data->done, ++ usecs_to_jiffies(usecs_lat)); ++ if (ret == 0) { ++ pr_err("PCC command executed timeout!\n"); ++ return AE_TIME; ++ } ++ } + + mbox_client_txdone(data->pcc_chan->mchan, ret); + +-- +2.35.1 + diff --git a/queue-5.19/acpi-tables-fpdt-don-t-call-acpi_os_map_memory-on-in.patch b/queue-5.19/acpi-tables-fpdt-don-t-call-acpi_os_map_memory-on-in.patch new file mode 100644 index 00000000000..a3b9d87a64f --- /dev/null +++ b/queue-5.19/acpi-tables-fpdt-don-t-call-acpi_os_map_memory-on-in.patch @@ -0,0 +1,108 @@ +From e1a1be4d40f7a2b7585e575b920498fa650dc8ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 14:34:12 +0200 +Subject: ACPI: tables: FPDT: Don't call acpi_os_map_memory() on invalid phys + address + +From: Hans de Goede + +[ Upstream commit 211391bf04b3c74e250c566eeff9cf808156c693 ] + +On a Packard Bell Dot SC (Intel Atom N2600 model) there is a FPDT table +which contains invalid physical addresses, with high bits set which fall +outside the range of the CPU-s supported physical address range. + +Calling acpi_os_map_memory() on such an invalid phys address leads to +the below WARN_ON in ioremap triggering resulting in an oops/stacktrace. + +Add code to verify the physical address before calling acpi_os_map_memory() +to fix / avoid the oops. + +[ 1.226900] ioremap: invalid physical address 3001000000000000 +[ 1.226949] ------------[ cut here ]------------ +[ 1.226962] WARNING: CPU: 1 PID: 1 at arch/x86/mm/ioremap.c:200 __ioremap_caller.cold+0x43/0x5f +[ 1.226996] Modules linked in: +[ 1.227016] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc3+ #490 +[ 1.227029] Hardware name: Packard Bell dot s/SJE01_CT, BIOS V1.10 07/23/2013 +[ 1.227038] RIP: 0010:__ioremap_caller.cold+0x43/0x5f +[ 1.227054] Code: 96 00 00 e9 f8 af 24 ff 89 c6 48 c7 c7 d8 0c 84 99 e8 6a 96 00 00 e9 76 af 24 ff 48 89 fe 48 c7 c7 a8 0c 84 99 e8 56 96 00 00 <0f> 0b e9 60 af 24 ff 48 8b 34 24 48 c7 c7 40 0d 84 99 e8 3f 96 00 +[ 1.227067] RSP: 0000:ffffb18c40033d60 EFLAGS: 00010286 +[ 1.227084] RAX: 0000000000000032 RBX: 3001000000000000 RCX: 0000000000000000 +[ 1.227095] RDX: 0000000000000001 RSI: 00000000ffffdfff RDI: 00000000ffffffff +[ 1.227105] RBP: 3001000000000000 R08: 0000000000000000 R09: ffffb18c40033c18 +[ 1.227115] R10: 0000000000000003 R11: ffffffff99d62fe8 R12: 0000000000000008 +[ 1.227124] R13: 0003001000000000 R14: 0000000000001000 R15: 3001000000000000 +[ 1.227135] FS: 0000000000000000(0000) GS:ffff913a3c080000(0000) knlGS:0000000000000000 +[ 1.227146] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 1.227156] CR2: 0000000000000000 CR3: 0000000018c26000 CR4: 00000000000006e0 +[ 1.227167] Call Trace: +[ 1.227176] +[ 1.227185] ? acpi_os_map_iomem+0x1c9/0x1e0 +[ 1.227215] ? kmem_cache_alloc_trace+0x187/0x370 +[ 1.227254] acpi_os_map_iomem+0x1c9/0x1e0 +[ 1.227288] acpi_init_fpdt+0xa8/0x253 +[ 1.227308] ? acpi_debugfs_init+0x1f/0x1f +[ 1.227339] do_one_initcall+0x5a/0x300 +[ 1.227406] ? rcu_read_lock_sched_held+0x3f/0x80 +[ 1.227442] kernel_init_freeable+0x28b/0x2cc +[ 1.227512] ? rest_init+0x170/0x170 +[ 1.227538] kernel_init+0x16/0x140 +[ 1.227552] ret_from_fork+0x1f/0x30 +[ 1.227639] +[ 1.227647] irq event stamp: 186819 +[ 1.227656] hardirqs last enabled at (186825): [] __up_console_sem+0x5e/0x70 +[ 1.227672] hardirqs last disabled at (186830): [] __up_console_sem+0x43/0x70 +[ 1.227686] softirqs last enabled at (186576): [] __irq_exit_rcu+0xed/0x160 +[ 1.227701] softirqs last disabled at (186569): [] __irq_exit_rcu+0xed/0x160 +[ 1.227715] ---[ end trace 0000000000000000 ]--- + +Signed-off-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_fpdt.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/drivers/acpi/acpi_fpdt.c b/drivers/acpi/acpi_fpdt.c +index 6922a44b3ce7..a2056c4c8cb7 100644 +--- a/drivers/acpi/acpi_fpdt.c ++++ b/drivers/acpi/acpi_fpdt.c +@@ -143,6 +143,23 @@ static const struct attribute_group boot_attr_group = { + + static struct kobject *fpdt_kobj; + ++#if defined CONFIG_X86 && defined CONFIG_PHYS_ADDR_T_64BIT ++#include ++static bool fpdt_address_valid(u64 address) ++{ ++ /* ++ * On some systems the table contains invalid addresses ++ * with unsuppored high address bits set, check for this. ++ */ ++ return !(address >> boot_cpu_data.x86_phys_bits); ++} ++#else ++static bool fpdt_address_valid(u64 address) ++{ ++ return true; ++} ++#endif ++ + static int fpdt_process_subtable(u64 address, u32 subtable_type) + { + struct fpdt_subtable_header *subtable_header; +@@ -151,6 +168,11 @@ static int fpdt_process_subtable(u64 address, u32 subtable_type) + u32 length, offset; + int result; + ++ if (!fpdt_address_valid(address)) { ++ pr_info(FW_BUG "invalid physical address: 0x%llx!\n", address); ++ return -EINVAL; ++ } ++ + subtable_header = acpi_os_map_memory(address, sizeof(*subtable_header)); + if (!subtable_header) + return -ENOMEM; +-- +2.35.1 + diff --git a/queue-5.19/acpi-video-add-toshiba-satellite-portege-z830-quirk.patch b/queue-5.19/acpi-video-add-toshiba-satellite-portege-z830-quirk.patch new file mode 100644 index 00000000000..2547140f254 --- /dev/null +++ b/queue-5.19/acpi-video-add-toshiba-satellite-portege-z830-quirk.patch @@ -0,0 +1,59 @@ +From 9d8bf434ce9fe60e50ba2f4ad4b4342224858141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 20:49:50 +0200 +Subject: ACPI: video: Add Toshiba Satellite/Portege Z830 quirk + +From: Arvid Norlander + +[ Upstream commit 574160b8548deff8b80b174f03201e94ab8431e2 ] + +Toshiba Satellite Z830 needs the quirk video_disable_backlight_sysfs_if +for proper backlight control after suspend/resume cycles. + +Toshiba Portege Z830 is simply the same laptop rebranded for certain +markets (I looked through the manual to other language sections to confirm +this) and thus also needs this quirk. + +Thanks to Hans de Goede for suggesting this fix. + +Link: https://www.spinics.net/lists/platform-driver-x86/msg34394.html +Suggested-by: Hans de Goede +Signed-off-by: Arvid Norlander +Reviewed-by: Hans de Goede +Tested-by: Arvid Norlander +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/acpi_video.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c +index eaea733b368a..03f5f92b603c 100644 +--- a/drivers/acpi/acpi_video.c ++++ b/drivers/acpi/acpi_video.c +@@ -496,6 +496,22 @@ static const struct dmi_system_id video_dmi_table[] = { + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"), + }, + }, ++ { ++ .callback = video_disable_backlight_sysfs_if, ++ .ident = "Toshiba Satellite Z830", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Z830"), ++ }, ++ }, ++ { ++ .callback = video_disable_backlight_sysfs_if, ++ .ident = "Toshiba Portege Z830", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE Z830"), ++ }, ++ }, + /* + * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set + * but the IDs actually follow the Device ID Scheme. +-- +2.35.1 + diff --git a/queue-5.19/acpi-x86-add-a-quirk-for-dell-inspiron-14-2-in-1-for.patch b/queue-5.19/acpi-x86-add-a-quirk-for-dell-inspiron-14-2-in-1-for.patch new file mode 100644 index 00000000000..c257d7f6f45 --- /dev/null +++ b/queue-5.19/acpi-x86-add-a-quirk-for-dell-inspiron-14-2-in-1-for.patch @@ -0,0 +1,63 @@ +From 79ae9fb529ab3763b78e14e9ccd7d28c5760e5b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 13:23:14 -0500 +Subject: ACPI: x86: Add a quirk for Dell Inspiron 14 2-in-1 for + StorageD3Enable + +From: Mario Limonciello + +[ Upstream commit 018d6711c26e4bd26e20a819fcc7f8ab902608f3 ] + +Dell Inspiron 14 2-in-1 has two ACPI nodes under GPP1 both with _ADR of +0, both without _HID. It's ambiguous which the kernel should take, but +it seems to take "DEV0". Unfortunately "DEV0" is missing the device +property `StorageD3Enable` which is present on "NVME". + +To avoid this causing problems for suspend, add a quirk for this system +to behave like `StorageD3Enable` property was found. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216440 +Reported-and-tested-by: Luya Tshimbalanga +Signed-off-by: Mario Limonciello +Reviewed-by: Hans de Goede +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/acpi/x86/utils.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c +index 664070fc8349..d7cdd8406c84 100644 +--- a/drivers/acpi/x86/utils.c ++++ b/drivers/acpi/x86/utils.c +@@ -207,9 +207,26 @@ static const struct x86_cpu_id storage_d3_cpu_ids[] = { + {} + }; + ++static const struct dmi_system_id force_storage_d3_dmi[] = { ++ { ++ /* ++ * _ADR is ambiguous between GPP1.DEV0 and GPP1.NVME ++ * but .NVME is needed to get StorageD3Enable node ++ * https://bugzilla.kernel.org/show_bug.cgi?id=216440 ++ */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 14 7425 2-in-1"), ++ } ++ }, ++ {} ++}; ++ + bool force_storage_d3(void) + { +- return x86_match_cpu(storage_d3_cpu_ids); ++ const struct dmi_system_id *dmi_id = dmi_first_match(force_storage_d3_dmi); ++ ++ return dmi_id || x86_match_cpu(storage_d3_cpu_ids); + } + + /* +-- +2.35.1 + diff --git a/queue-5.19/af_unix-fix-memory-leaks-of-the-whole-sk-due-to-oob-.patch b/queue-5.19/af_unix-fix-memory-leaks-of-the-whole-sk-due-to-oob-.patch new file mode 100644 index 00000000000..fa42dfdb610 --- /dev/null +++ b/queue-5.19/af_unix-fix-memory-leaks-of-the-whole-sk-due-to-oob-.patch @@ -0,0 +1,102 @@ +From b066e36a1ed950ce57fa0be482a2feb208dac948 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 08:52:04 -0700 +Subject: af_unix: Fix memory leaks of the whole sk due to OOB skb. + +From: Kuniyuki Iwashima + +[ Upstream commit 7a62ed61367b8fd01bae1e18e30602c25060d824 ] + +syzbot reported a sequence of memory leaks, and one of them indicated we +failed to free a whole sk: + + unreferenced object 0xffff8880126e0000 (size 1088): + comm "syz-executor419", pid 326, jiffies 4294773607 (age 12.609s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 7d 00 00 00 00 00 00 00 ........}....... + 01 00 07 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............ + backtrace: + [<000000006fefe750>] sk_prot_alloc+0x64/0x2a0 net/core/sock.c:1970 + [<0000000074006db5>] sk_alloc+0x3b/0x800 net/core/sock.c:2029 + [<00000000728cd434>] unix_create1+0xaf/0x920 net/unix/af_unix.c:928 + [<00000000a279a139>] unix_create+0x113/0x1d0 net/unix/af_unix.c:997 + [<0000000068259812>] __sock_create+0x2ab/0x550 net/socket.c:1516 + [<00000000da1521e1>] sock_create net/socket.c:1566 [inline] + [<00000000da1521e1>] __sys_socketpair+0x1a8/0x550 net/socket.c:1698 + [<000000007ab259e1>] __do_sys_socketpair net/socket.c:1751 [inline] + [<000000007ab259e1>] __se_sys_socketpair net/socket.c:1748 [inline] + [<000000007ab259e1>] __x64_sys_socketpair+0x97/0x100 net/socket.c:1748 + [<000000007dedddc1>] do_syscall_x64 arch/x86/entry/common.c:50 [inline] + [<000000007dedddc1>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80 + [<000000009456679f>] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +We can reproduce this issue by creating two AF_UNIX SOCK_STREAM sockets, +send()ing an OOB skb to each other, and close()ing them without consuming +the OOB skbs. + + int skpair[2]; + + socketpair(AF_UNIX, SOCK_STREAM, 0, skpair); + + send(skpair[0], "x", 1, MSG_OOB); + send(skpair[1], "x", 1, MSG_OOB); + + close(skpair[0]); + close(skpair[1]); + +Currently, we free an OOB skb in unix_sock_destructor() which is called via +__sk_free(), but it's too late because the receiver's unix_sk(sk)->oob_skb +is accounted against the sender's sk->sk_wmem_alloc and __sk_free() is +called only when sk->sk_wmem_alloc is 0. + +In the repro sequences, we do not consume the OOB skb, so both two sk's +sock_put() never reach __sk_free() due to the positive sk->sk_wmem_alloc. +Then, no one can consume the OOB skb nor call __sk_free(), and we finally +leak the two whole sk. + +Thus, we must free the unconsumed OOB skb earlier when close()ing the +socket. + +Fixes: 314001f0bf92 ("af_unix: Add OOB support") +Reported-by: syzbot +Signed-off-by: Kuniyuki Iwashima +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 3453e0053f76..0a93ac784baa 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -548,12 +548,6 @@ static void unix_sock_destructor(struct sock *sk) + + skb_queue_purge(&sk->sk_receive_queue); + +-#if IS_ENABLED(CONFIG_AF_UNIX_OOB) +- if (u->oob_skb) { +- kfree_skb(u->oob_skb); +- u->oob_skb = NULL; +- } +-#endif + DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc)); + DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk)); + DEBUG_NET_WARN_ON_ONCE(sk->sk_socket); +@@ -598,6 +592,13 @@ static void unix_release_sock(struct sock *sk, int embrion) + + unix_state_unlock(sk); + ++#if IS_ENABLED(CONFIG_AF_UNIX_OOB) ++ if (u->oob_skb) { ++ kfree_skb(u->oob_skb); ++ u->oob_skb = NULL; ++ } ++#endif ++ + wake_up_interruptible_all(&u->peer_wait); + + if (skpair != NULL) { +-- +2.35.1 + diff --git a/queue-5.19/af_unix-use-debug_net_warn_on_once.patch b/queue-5.19/af_unix-use-debug_net_warn_on_once.patch new file mode 100644 index 00000000000..d164c49ec20 --- /dev/null +++ b/queue-5.19/af_unix-use-debug_net_warn_on_once.patch @@ -0,0 +1,49 @@ +From f06efd8a325a77b7f9fd863d7d8031d59abacd5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 09:04:35 -0700 +Subject: af_unix: use DEBUG_NET_WARN_ON_ONCE() + +From: Eric Dumazet + +[ Upstream commit dd29c67dbbbf97c8aa786a502977856d8eb9a73d ] + +Replace four WARN_ON() that have not triggered recently +with DEBUG_NET_WARN_ON_ONCE(). + +Signed-off-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Stable-dep-of: 7a62ed61367b ("af_unix: Fix memory leaks of the whole sk due to OOB skb.") +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 2206e6f8902d..3453e0053f76 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -302,7 +302,7 @@ static void __unix_remove_socket(struct sock *sk) + + static void __unix_insert_socket(struct sock *sk) + { +- WARN_ON(!sk_unhashed(sk)); ++ DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk)); + sk_add_node(sk, &unix_socket_table[sk->sk_hash]); + } + +@@ -554,9 +554,9 @@ static void unix_sock_destructor(struct sock *sk) + u->oob_skb = NULL; + } + #endif +- WARN_ON(refcount_read(&sk->sk_wmem_alloc)); +- WARN_ON(!sk_unhashed(sk)); +- WARN_ON(sk->sk_socket); ++ DEBUG_NET_WARN_ON_ONCE(refcount_read(&sk->sk_wmem_alloc)); ++ DEBUG_NET_WARN_ON_ONCE(!sk_unhashed(sk)); ++ DEBUG_NET_WARN_ON_ONCE(sk->sk_socket); + if (!sock_flag(sk, SOCK_DEAD)) { + pr_info("Attempt to release alive unix socket: %p\n", sk); + return; +-- +2.35.1 + diff --git a/queue-5.19/alsa-dmaengine-increment-buffer-pointer-atomically.patch b/queue-5.19/alsa-dmaengine-increment-buffer-pointer-atomically.patch new file mode 100644 index 00000000000..3fa1086b573 --- /dev/null +++ b/queue-5.19/alsa-dmaengine-increment-buffer-pointer-atomically.patch @@ -0,0 +1,49 @@ +From 6cb1877aa18a69434705ad91651a3aade20e067f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 18:58:13 +0200 +Subject: ALSA: dmaengine: increment buffer pointer atomically + +From: Andreas Pape + +[ Upstream commit d1c442019594692c64a70a86ad88eb5b6db92216 ] + +Setting pointer and afterwards checking for wraparound leads +to the possibility of returning the inconsistent pointer position. + +This patch increments buffer pointer atomically to avoid this issue. + +Fixes: e7f73a1613567a ("ASoC: Add dmaengine PCM helper functions") +Signed-off-by: Andreas Pape +Signed-off-by: Eugeniu Rosca +Link: https://lore.kernel.org/r/1664211493-11789-1-git-send-email-erosca@de.adit-jv.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/core/pcm_dmaengine.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c +index af6f717e1e7e..c6ccb75036ae 100644 +--- a/sound/core/pcm_dmaengine.c ++++ b/sound/core/pcm_dmaengine.c +@@ -131,12 +131,14 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); + + static void dmaengine_pcm_dma_complete(void *arg) + { ++ unsigned int new_pos; + struct snd_pcm_substream *substream = arg; + struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); + +- prtd->pos += snd_pcm_lib_period_bytes(substream); +- if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) +- prtd->pos = 0; ++ new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); ++ if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) ++ new_pos = 0; ++ prtd->pos = new_pos; + + snd_pcm_period_elapsed(substream); + } +-- +2.35.1 + diff --git a/queue-5.19/alsa-hda-beep-simplify-keep-power-at-enable-behavior.patch b/queue-5.19/alsa-hda-beep-simplify-keep-power-at-enable-behavior.patch new file mode 100644 index 00000000000..f389d6e08c1 --- /dev/null +++ b/queue-5.19/alsa-hda-beep-simplify-keep-power-at-enable-behavior.patch @@ -0,0 +1,135 @@ +From 0e1117576c384accb36cc1f8460e55fa52376b4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 11:23:06 +0200 +Subject: ALSA: hda: beep: Simplify keep-power-at-enable behavior + +From: Takashi Iwai + +[ Upstream commit 4c8d695cb9bc5f6fd298a586602947b2fc099a64 ] + +The recent fix for IDT codecs to keep the power up while the beep is +enabled can be better integrated into the beep helper code. +This patch cleans up the code with refactoring. + +Fixes: 414d38ba8710 ("ALSA: hda/sigmatel: Keep power up while beep is enabled") +Link: https://lore.kernel.org/r/20220906092306.26183-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/hda_beep.c | 15 +++++++++++++-- + sound/pci/hda/hda_beep.h | 1 + + sound/pci/hda/patch_sigmatel.c | 25 ++----------------------- + 3 files changed, 16 insertions(+), 25 deletions(-) + +diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c +index 53a2b89f8983..e63621bcb214 100644 +--- a/sound/pci/hda/hda_beep.c ++++ b/sound/pci/hda/hda_beep.c +@@ -118,6 +118,12 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, + return 0; + } + ++static void turn_on_beep(struct hda_beep *beep) ++{ ++ if (beep->keep_power_at_enable) ++ snd_hda_power_up_pm(beep->codec); ++} ++ + static void turn_off_beep(struct hda_beep *beep) + { + cancel_work_sync(&beep->beep_work); +@@ -125,6 +131,8 @@ static void turn_off_beep(struct hda_beep *beep) + /* turn off beep */ + generate_tone(beep, 0); + } ++ if (beep->keep_power_at_enable) ++ snd_hda_power_down_pm(beep->codec); + } + + /** +@@ -140,7 +148,9 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) + enable = !!enable; + if (beep->enabled != enable) { + beep->enabled = enable; +- if (!enable) ++ if (enable) ++ turn_on_beep(beep); ++ else + turn_off_beep(beep); + return 1; + } +@@ -167,7 +177,8 @@ static int beep_dev_disconnect(struct snd_device *device) + input_unregister_device(beep->dev); + else + input_free_device(beep->dev); +- turn_off_beep(beep); ++ if (beep->enabled) ++ turn_off_beep(beep); + return 0; + } + +diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h +index a25358a4807a..db76e3ddba65 100644 +--- a/sound/pci/hda/hda_beep.h ++++ b/sound/pci/hda/hda_beep.h +@@ -25,6 +25,7 @@ struct hda_beep { + unsigned int enabled:1; + unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ + unsigned int playing:1; ++ unsigned int keep_power_at_enable:1; /* set by driver */ + struct work_struct beep_work; /* scheduled task for beep event */ + struct mutex mutex; + void (*power_hook)(struct hda_beep *beep, bool on); +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index 7f340f18599c..a794a01a68ca 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -4311,6 +4311,8 @@ static int stac_parse_auto_config(struct hda_codec *codec) + if (codec->beep) { + /* IDT/STAC codecs have linear beep tone parameter */ + codec->beep->linear_tone = spec->linear_tone_beep; ++ /* keep power up while beep is enabled */ ++ codec->beep->keep_power_at_enable = 1; + /* if no beep switch is available, make its own one */ + caps = query_amp_caps(codec, nid, HDA_OUTPUT); + if (!(caps & AC_AMPCAP_MUTE)) { +@@ -4444,28 +4446,6 @@ static int stac_suspend(struct hda_codec *codec) + + return 0; + } +- +-static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid) +-{ +-#ifdef CONFIG_SND_HDA_INPUT_BEEP +- struct sigmatel_spec *spec = codec->spec; +-#endif +- int ret = snd_hda_gen_check_power_status(codec, nid); +- +-#ifdef CONFIG_SND_HDA_INPUT_BEEP +- if (nid == spec->gen.beep_nid && codec->beep) { +- if (codec->beep->enabled != spec->beep_power_on) { +- spec->beep_power_on = codec->beep->enabled; +- if (spec->beep_power_on) +- snd_hda_power_up_pm(codec); +- else +- snd_hda_power_down_pm(codec); +- } +- ret |= spec->beep_power_on; +- } +-#endif +- return ret; +-} + #else + #define stac_suspend NULL + #endif /* CONFIG_PM */ +@@ -4478,7 +4458,6 @@ static const struct hda_codec_ops stac_patch_ops = { + .unsol_event = snd_hda_jack_unsol_event, + #ifdef CONFIG_PM + .suspend = stac_suspend, +- .check_power_status = stac_check_power_status, + #endif + }; + +-- +2.35.1 + diff --git a/queue-5.19/alsa-hda-hdmi-don-t-skip-notification-handling-durin.patch b/queue-5.19/alsa-hda-hdmi-don-t-skip-notification-handling-durin.patch new file mode 100644 index 00000000000..8817a728aef --- /dev/null +++ b/queue-5.19/alsa-hda-hdmi-don-t-skip-notification-handling-durin.patch @@ -0,0 +1,63 @@ +From 95086fd99e3993eab1b4ce5f75b4bff149f1a072 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 09:48:10 +0200 +Subject: ALSA: hda/hdmi: Don't skip notification handling during PM operation + +From: Takashi Iwai + +[ Upstream commit 5226c7b9784eee215e3914f440b3c2e1764f67a8 ] + +The HDMI driver skips the notification handling from the graphics +driver when the codec driver is being in the PM operation. This +behavior was introduced by the commit eb399d3c99d8 ("ALSA: hda - Skip +ELD notification during PM process"). This skip may cause a problem, +as we may miss the ELD update when the connection/disconnection +happens right at the runtime-PM operation of the audio codec. + +Although this workaround was valid at that time, it's no longer true; +the fix was required just because the ELD update procedure needed to +wake up the audio codec, which had lead to a runtime-resume during a +runtime-suspend. Meanwhile, the ELD update procedure doesn't need a +codec wake up any longer since the commit 788d441a164c ("ALSA: hda - +Use component ops for i915 HDMI/DP audio jack handling"); i.e. there +is no much reason for skipping the notification. + +Let's drop those checks for addressing the missing notification. + +Fixes: 788d441a164c ("ALSA: hda - Use component ops for i915 HDMI/DP audio jack handling") +Reported-by: Brent Lu +Link: https://lore.kernel.org/r/20220927135807.4097052-1-brent.lu@intel.com +Link: https://lore.kernel.org/r/20221001074809.7461-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_hdmi.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index c239d9dbbaef..63c0c84348d0 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -2747,9 +2747,6 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) + */ + if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) + return; +- /* ditto during suspend/resume process itself */ +- if (snd_hdac_is_in_pm(&codec->core)) +- return; + + check_presence_and_report(codec, pin_nid, dev_id); + } +@@ -2933,9 +2930,6 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) + */ + if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) + return; +- /* ditto during suspend/resume process itself */ +- if (snd_hdac_is_in_pm(&codec->core)) +- return; + + snd_hdac_i915_set_bclk(&codec->bus->core); + check_presence_and_report(codec, pin_nid, dev_id); +-- +2.35.1 + diff --git a/queue-5.19/alsa-intel-dspconfig-add-es8336-support-for-alderlak.patch b/queue-5.19/alsa-intel-dspconfig-add-es8336-support-for-alderlak.patch new file mode 100644 index 00000000000..46d621cce99 --- /dev/null +++ b/queue-5.19/alsa-intel-dspconfig-add-es8336-support-for-alderlak.patch @@ -0,0 +1,40 @@ +From 679d6f7f03d50434c29895206fc5ef3e8155b626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 13:45:48 +0200 +Subject: ALSA: intel-dspconfig: add ES8336 support for AlderLake-PS + +From: Muralidhar Reddy + +[ Upstream commit 9db1c9fa214ef41d098633ff40a87284ca6e1870 ] + +added quirks for ESS8336 for AlderLake-PS + +Reviewed-by: Ranjani Sridharan +Signed-off-by: Muralidhar Reddy +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20220919114548.42769-1-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/hda/intel-dsp-config.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c +index ec9cbb219bc1..dbc7dfd00c44 100644 +--- a/sound/hda/intel-dsp-config.c ++++ b/sound/hda/intel-dsp-config.c +@@ -422,6 +422,11 @@ static const struct config_entry config_table[] = { + .device = 0x51cd, + }, + /* Alderlake-PS */ ++ { ++ .flags = FLAG_SOF, ++ .device = 0x51c9, ++ .codec_hid = &essx_83x6, ++ }, + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51c9, +-- +2.35.1 + diff --git a/queue-5.19/alsa-usb-audio-add-quirk-to-enable-avid-mbox-3-suppo.patch b/queue-5.19/alsa-usb-audio-add-quirk-to-enable-avid-mbox-3-suppo.patch new file mode 100644 index 00000000000..e2c671dfd2c --- /dev/null +++ b/queue-5.19/alsa-usb-audio-add-quirk-to-enable-avid-mbox-3-suppo.patch @@ -0,0 +1,430 @@ +From 76c10432d14cb66169923c89fdfd7486f6567dd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 17:14:33 -0300 +Subject: ALSA: usb-audio: Add quirk to enable Avid Mbox 3 support + +From: Conner Knox + +[ Upstream commit b01104fc62b6194c852124f6c6df1c0a5c031fc1 ] + +Add support for Avid Mbox3 USB audio interface at 48kHz + +Signed-off-by: Conner Knox +Link: https://lore.kernel.org/r/20220818201433.16360-1-mbarriolinares@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/quirks-table.h | 76 ++++++++++ + sound/usb/quirks.c | 302 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 378 insertions(+) + +diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h +index f93201a830b5..06dfdd45cff8 100644 +--- a/sound/usb/quirks-table.h ++++ b/sound/usb/quirks-table.h +@@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), + } + } + }, ++/* DIGIDESIGN MBOX 3 */ ++{ ++ USB_DEVICE(0x0dba, 0x5000), ++ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { ++ .vendor_name = "Digidesign", ++ .product_name = "Mbox 3", ++ .ifnum = QUIRK_ANY_INTERFACE, ++ .type = QUIRK_COMPOSITE, ++ .data = (const struct snd_usb_audio_quirk[]) { ++ { ++ .ifnum = 0, ++ .type = QUIRK_IGNORE_INTERFACE ++ }, ++ { ++ .ifnum = 1, ++ .type = QUIRK_IGNORE_INTERFACE ++ }, ++ { ++ .ifnum = 2, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 4, ++ .iface = 2, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .attributes = 0x00, ++ .endpoint = 0x01, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC | ++ USB_ENDPOINT_SYNC_ASYNC, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .nr_rates = 1, ++ .rate_table = (unsigned int[]) { ++ 48000 ++ } ++ } ++ }, ++ { ++ .ifnum = 3, ++ .type = QUIRK_AUDIO_FIXED_ENDPOINT, ++ .data = &(const struct audioformat) { ++ .formats = SNDRV_PCM_FMTBIT_S24_3LE, ++ .channels = 4, ++ .iface = 3, ++ .altsetting = 1, ++ .altset_idx = 1, ++ .endpoint = 0x81, ++ .attributes = 0x00, ++ .ep_attr = USB_ENDPOINT_XFER_ISOC | ++ USB_ENDPOINT_SYNC_ASYNC, ++ .maxpacksize = 0x009c, ++ .rates = SNDRV_PCM_RATE_48000, ++ .rate_min = 48000, ++ .rate_max = 48000, ++ .nr_rates = 1, ++ .rate_table = (unsigned int[]) { ++ 48000 ++ } ++ } ++ }, ++ { ++ .ifnum = 4, ++ .type = QUIRK_MIDI_FIXED_ENDPOINT, ++ .data = &(const struct snd_usb_midi_endpoint_info) { ++ .out_cables = 0x0001, ++ .in_cables = 0x0001 ++ } ++ }, ++ { ++ .ifnum = -1 ++ } ++ } ++ } ++}, + { + /* Tascam US122 MKII - playback-only support */ + USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 5b4d8f5eade2..194c75c45628 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) + return 0; + } + ++static void mbox3_setup_48_24_magic(struct usb_device *dev) ++{ ++ /* The Mbox 3 is "little endian" */ ++ /* max volume is: 0x0000. */ ++ /* min volume is: 0x0080 (shown in little endian form) */ ++ ++ ++ /* Load 48000Hz rate into buffer */ ++ u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00}; ++ ++ /* Set 48000Hz sample rate */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 0x01, 0x21, 0x0100, 0x0001, &com_buff, 4); //Is this really needed? ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 0x01, 0x21, 0x0100, 0x8101, &com_buff, 4); ++ ++ /* Deactivate Tuner */ ++ /* on = 0x01*/ ++ /* off = 0x00*/ ++ com_buff[0] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 0x01, 0x21, 0x0003, 0x2001, &com_buff, 1); ++ ++ /* Set clock source to Internal (as opposed to S/PDIF) */ ++ com_buff[0] = 0x01; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0100, 0x8001, &com_buff, 1); ++ ++ /* Mute the hardware loopbacks to start the device in a known state. */ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* Analogue input 1 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0110, 0x4001, &com_buff, 2); ++ /* Analogue input 1 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0111, 0x4001, &com_buff, 2); ++ /* Analogue input 2 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0114, 0x4001, &com_buff, 2); ++ /* Analogue input 2 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0115, 0x4001, &com_buff, 2); ++ /* Analogue input 3 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0118, 0x4001, &com_buff, 2); ++ /* Analogue input 3 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0119, 0x4001, &com_buff, 2); ++ /* Analogue input 4 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011c, 0x4001, &com_buff, 2); ++ /* Analogue input 4 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011d, 0x4001, &com_buff, 2); ++ ++ /* Set software sends to output */ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x00; ++ /* Analogue software return 1 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0100, 0x4001, &com_buff, 2); ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* Analogue software return 1 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0101, 0x4001, &com_buff, 2); ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* Analogue software return 2 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0104, 0x4001, &com_buff, 2); ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x00; ++ /* Analogue software return 2 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0105, 0x4001, &com_buff, 2); ++ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* Analogue software return 3 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0108, 0x4001, &com_buff, 2); ++ /* Analogue software return 3 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0109, 0x4001, &com_buff, 2); ++ /* Analogue software return 4 left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010c, 0x4001, &com_buff, 2); ++ /* Analogue software return 4 right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010d, 0x4001, &com_buff, 2); ++ ++ /* Return to muting sends */ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* Analogue fx return left channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0120, 0x4001, &com_buff, 2); ++ /* Analogue fx return right channel: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0121, 0x4001, &com_buff, 2); ++ ++ /* Analogue software input 1 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0100, 0x4201, &com_buff, 2); ++ /* Analogue software input 2 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0101, 0x4201, &com_buff, 2); ++ /* Analogue software input 3 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0102, 0x4201, &com_buff, 2); ++ /* Analogue software input 4 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0103, 0x4201, &com_buff, 2); ++ /* Analogue input 1 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0104, 0x4201, &com_buff, 2); ++ /* Analogue input 2 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0105, 0x4201, &com_buff, 2); ++ /* Analogue input 3 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0106, 0x4201, &com_buff, 2); ++ /* Analogue input 4 fx send: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0107, 0x4201, &com_buff, 2); ++ ++ /* Toggle allowing host control */ ++ com_buff[0] = 0x02; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 3, 0x21, 0x0000, 0x2001, &com_buff, 1); ++ ++ /* Do not dim fx returns */ ++ com_buff[0] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 3, 0x21, 0x0002, 0x2001, &com_buff, 1); ++ ++ /* Do not set fx returns to mono */ ++ com_buff[0] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 3, 0x21, 0x0001, 0x2001, &com_buff, 1); ++ ++ /* Mute the S/PDIF hardware loopback ++ * same odd volume logic here as above ++ */ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* S/PDIF hardware input 1 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0112, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 1 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0113, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 2 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0116, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 2 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0117, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 3 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011a, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 3 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011b, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 4 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011e, 0x4001, &com_buff, 2); ++ /* S/PDIF hardware input 4 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x011f, 0x4001, &com_buff, 2); ++ /* S/PDIF software return 1 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0102, 0x4001, &com_buff, 2); ++ /* S/PDIF software return 1 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0103, 0x4001, &com_buff, 2); ++ /* S/PDIF software return 2 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0106, 0x4001, &com_buff, 2); ++ /* S/PDIF software return 2 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0107, 0x4001, &com_buff, 2); ++ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x00; ++ /* S/PDIF software return 3 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010a, 0x4001, &com_buff, 2); ++ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* S/PDIF software return 3 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010b, 0x4001, &com_buff, 2); ++ /* S/PDIF software return 4 left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010e, 0x4001, &com_buff, 2); ++ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x00; ++ /* S/PDIF software return 4 right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x010f, 0x4001, &com_buff, 2); ++ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x80; ++ /* S/PDIF fx returns left channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0122, 0x4001, &com_buff, 2); ++ /* S/PDIF fx returns right channel */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0123, 0x4001, &com_buff, 2); ++ ++ /* Set the dropdown "Effect" to the first option */ ++ /* Room1 = 0x00 */ ++ /* Room2 = 0x01 */ ++ /* Room3 = 0x02 */ ++ /* Hall 1 = 0x03 */ ++ /* Hall 2 = 0x04 */ ++ /* Plate = 0x05 */ ++ /* Delay = 0x06 */ ++ /* Echo = 0x07 */ ++ com_buff[0] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */ ++ /* min is 0x00 */ ++ ++ ++ /* Set the effect duration to 0 */ ++ /* max is 0xffff */ ++ /* min is 0x0000 */ ++ com_buff[0] = 0x00; ++ com_buff[1] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0400, 0x4301, &com_buff, 2); ++ ++ /* Set the effect volume and feedback to 0 */ ++ /* max is 0xff */ ++ /* min is 0x00 */ ++ com_buff[0] = 0x00; ++ /* feedback: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0500, 0x4301, &com_buff, 1); ++ /* volume: */ ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 1, 0x21, 0x0300, 0x4301, &com_buff, 1); ++ ++ /* Set soft button hold duration */ ++ /* 0x03 = 250ms */ ++ /* 0x05 = 500ms DEFAULT */ ++ /* 0x08 = 750ms */ ++ /* 0x0a = 1sec */ ++ com_buff[0] = 0x05; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 3, 0x21, 0x0005, 0x2001, &com_buff, 1); ++ ++ /* Use dim LEDs for button of state */ ++ com_buff[0] = 0x00; ++ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), ++ 3, 0x21, 0x0004, 0x2001, &com_buff, 1); ++} ++ ++#define MBOX3_DESCRIPTOR_SIZE 464 ++ ++static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) ++{ ++ struct usb_host_config *config = dev->actconfig; ++ int err; ++ int descriptor_size; ++ ++ descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); ++ ++ if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { ++ dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); ++ return -ENODEV; ++ } ++ ++ dev_dbg(&dev->dev, "device initialised!\n"); ++ ++ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, ++ &dev->descriptor, sizeof(dev->descriptor)); ++ config = dev->actconfig; ++ if (err < 0) ++ dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); ++ ++ err = usb_reset_configuration(dev); ++ if (err < 0) ++ dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); ++ dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", ++ le16_to_cpu(get_cfg_desc(config)->wTotalLength)); ++ ++ mbox3_setup_48_24_magic(dev); ++ dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); ++ ++ return 0; /* Successful boot */ ++} + + #define MICROBOOK_BUF_SIZE 128 + +@@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, + case USB_ID(0x0dba, 0x3000): + /* Digidesign Mbox 2 */ + return snd_usb_mbox2_boot_quirk(dev); ++ case USB_ID(0x0dba, 0x5000): ++ /* Digidesign Mbox 3 */ ++ return snd_usb_mbox3_boot_quirk(dev); ++ + + case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ + case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */ +-- +2.35.1 + diff --git a/queue-5.19/alsa-usb-audio-properly-refcounting-clock-rate.patch b/queue-5.19/alsa-usb-audio-properly-refcounting-clock-rate.patch new file mode 100644 index 00000000000..de2fe8a7262 --- /dev/null +++ b/queue-5.19/alsa-usb-audio-properly-refcounting-clock-rate.patch @@ -0,0 +1,73 @@ +From e99aef0c11ae97bf4deaea44f049edcf477fab0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 20:11:26 +0200 +Subject: ALSA: usb-audio: Properly refcounting clock rate + +From: Takashi Iwai + +[ Upstream commit 9a737e7f8b371e97eb649904276407cee2c9cf30 ] + +We fixed the bug introduced by the patch for managing the shared +clocks at the commit 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock +rate at closing EP"), but it was merely a workaround. By this change, +the clock reference rate is cleared at each EP close, hence the still +remaining EP may need a re-setup of rate unnecessarily. + +This patch introduces the proper refcounting for the clock reference +object so that the clock setup is done only when needed. + +Fixes: 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock rate at closing EP") +Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock") +Link: https://lore.kernel.org/r/20220920181126.4912-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/endpoint.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 971c33937dca..26fcbf61c890 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -39,6 +39,7 @@ struct snd_usb_iface_ref { + struct snd_usb_clock_ref { + unsigned char clock; + atomic_t locked; ++ int opened; + int rate; + bool need_setup; + struct list_head list; +@@ -804,6 +805,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, + ep = NULL; + goto unlock; + } ++ ep->clock_ref->opened++; + } + + ep->cur_audiofmt = fp; +@@ -927,8 +929,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, + endpoint_set_interface(chip, ep, false); + + if (!--ep->opened) { +- if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked)) +- ep->clock_ref->rate = 0; ++ if (ep->clock_ref) { ++ if (!--ep->clock_ref->opened) ++ ep->clock_ref->rate = 0; ++ } + ep->iface = 0; + ep->altsetting = 0; + ep->cur_audiofmt = NULL; +@@ -1649,8 +1653,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) + WRITE_ONCE(ep->sync_source->sync_sink, NULL); + stop_urbs(ep, false, keep_pending); + if (ep->clock_ref) +- if (!atomic_dec_return(&ep->clock_ref->locked)) +- ep->clock_ref->rate = 0; ++ atomic_dec(&ep->clock_ref->locked); + } + } + +-- +2.35.1 + diff --git a/queue-5.19/alsa-usb-audio-register-card-at-the-last-interface.patch b/queue-5.19/alsa-usb-audio-register-card-at-the-last-interface.patch new file mode 100644 index 00000000000..23064a0c10f --- /dev/null +++ b/queue-5.19/alsa-usb-audio-register-card-at-the-last-interface.patch @@ -0,0 +1,192 @@ +From 8e41547d983e41d921c658e27e16f0169900e0f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 18:12:47 +0200 +Subject: ALSA: usb-audio: Register card at the last interface + +From: Takashi Iwai + +[ Upstream commit 6392dcd1d0c7034ccf630ec55fc9e5810ecadf3b ] + +The USB-audio driver matches per interface, and as default, it +registers the card instance at the very first instance. This can be a +problem for the devices that have multiple interfaces to be probed, as +the udev rule isn't applied properly for the later appearing +interfaces. Although we introduced the delayed_register option and +the quirks for covering those shortcomings, it's nothing but a +workaround for specific devices. + +This patch is an another attempt to fix the problem in a more generic +way. Now the driver checks the whole USB device descriptor at the +very first time when an interface is attached to a sound card. It +looks at each matching interface in the descriptor and remembers the +last matching one. The snd_card_register() is invoked only when this +last interface is probed. + +After this change, the quirks for the delayed registration become +superfluous, hence they are removed along with the patch. OTOH, the +delayed_register option is still kept, as it might be useful for some +corner cases (e.g. a special driver overtakes the interface probe from +the standard driver, and the last interface probe may miss). + +Link: https://lore.kernel.org/r/20220904161247.16461-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/card.c | 32 +++++++++++++++++++++++++------- + sound/usb/quirks.c | 42 ------------------------------------------ + sound/usb/quirks.h | 2 -- + sound/usb/usbaudio.h | 1 + + 4 files changed, 26 insertions(+), 51 deletions(-) + +diff --git a/sound/usb/card.c b/sound/usb/card.c +index 706d249a9ad6..3aea241435fb 100644 +--- a/sound/usb/card.c ++++ b/sound/usb/card.c +@@ -690,7 +690,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id) + return false; + } + +-static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) ++static int check_delayed_register_option(struct snd_usb_audio *chip) + { + int i; + unsigned int id, inum; +@@ -699,14 +699,31 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) + if (delayed_register[i] && + sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 && + id == chip->usb_id) +- return iface < inum; ++ return inum; + } + +- return false; ++ return -1; + } + + static const struct usb_device_id usb_audio_ids[]; /* defined below */ + ++/* look for the last interface that matches with our ids and remember it */ ++static void find_last_interface(struct snd_usb_audio *chip) ++{ ++ struct usb_host_config *config = chip->dev->actconfig; ++ struct usb_interface *intf; ++ int i; ++ ++ if (!config) ++ return; ++ for (i = 0; i < config->desc.bNumInterfaces; i++) { ++ intf = config->interface[i]; ++ if (usb_match_id(intf, usb_audio_ids)) ++ chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber; ++ } ++ usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface); ++} ++ + /* look for the corresponding quirk */ + static const struct snd_usb_audio_quirk * + get_alias_quirk(struct usb_device *dev, unsigned int id) +@@ -813,6 +830,7 @@ static int usb_audio_probe(struct usb_interface *intf, + err = -ENODEV; + goto __error; + } ++ find_last_interface(chip); + } + + if (chip->num_interfaces >= MAX_CARD_INTERFACES) { +@@ -862,11 +880,11 @@ static int usb_audio_probe(struct usb_interface *intf, + chip->need_delayed_register = false; /* clear again */ + } + +- /* we are allowed to call snd_card_register() many times, but first +- * check to see if a device needs to skip it or do anything special ++ /* register card if we reach to the last interface or to the specified ++ * one given via option + */ +- if (!snd_usb_registration_quirk(chip, ifnum) && +- !check_delayed_register_option(chip, ifnum)) { ++ if (check_delayed_register_option(chip) == ifnum || ++ chip->last_iface == ifnum) { + err = snd_card_register(chip->card); + if (err < 0) + goto __error; +diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c +index 194c75c45628..eadac586bcc8 100644 +--- a/sound/usb/quirks.c ++++ b/sound/usb/quirks.c +@@ -2030,48 +2030,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, + } + } + +-/* +- * registration quirk: +- * the registration is skipped if a device matches with the given ID, +- * unless the interface reaches to the defined one. This is for delaying +- * the registration until the last known interface, so that the card and +- * devices appear at the same time. +- */ +- +-struct registration_quirk { +- unsigned int usb_id; /* composed via USB_ID() */ +- unsigned int interface; /* the interface to trigger register */ +-}; +- +-#define REG_QUIRK_ENTRY(vendor, product, iface) \ +- { .usb_id = USB_ID(vendor, product), .interface = (iface) } +- +-static const struct registration_quirk registration_quirks[] = { +- REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ +- REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ +- REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ +- REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ +- REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ +- REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ +- REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ +- REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ +- REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ +- { 0 } /* terminator */ +-}; +- +-/* return true if skipping registration */ +-bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) +-{ +- const struct registration_quirk *q; +- +- for (q = registration_quirks; q->usb_id; q++) +- if (chip->usb_id == q->usb_id) +- return iface < q->interface; +- +- /* Register as normal */ +- return false; +-} +- + /* + * driver behavior quirk flags + */ +diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h +index 31abb7cb01a5..f9bfd5ac7bab 100644 +--- a/sound/usb/quirks.h ++++ b/sound/usb/quirks.h +@@ -48,8 +48,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, + struct audioformat *fp, + int stream); + +-bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface); +- + void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); + + #endif /* __USBAUDIO_QUIRKS_H */ +diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h +index ffbb4b0d09a0..2c6575029b1c 100644 +--- a/sound/usb/usbaudio.h ++++ b/sound/usb/usbaudio.h +@@ -37,6 +37,7 @@ struct snd_usb_audio { + unsigned int quirk_flags; + unsigned int need_delayed_register:1; /* warn for delayed registration */ + int num_interfaces; ++ int last_iface; + int num_suspended_intf; + int sample_rate_read_error; + +-- +2.35.1 + diff --git a/queue-5.19/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch b/queue-5.19/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch new file mode 100644 index 00000000000..64cf04a78a0 --- /dev/null +++ b/queue-5.19/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch @@ -0,0 +1,345 @@ +From 7ece01c95251b46c43f46d36e4344827e849fcd5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 20:11:06 +0200 +Subject: ALSA: usb-audio: Split endpoint setups for hw_params and prepare + (take#2) + +From: Takashi Iwai + +[ Upstream commit 2be79d58645465351af5320eb14c70a94724c5ef ] + +This is a second attempt to fix the bug appearing on Android with the +recent kernel; the first try was ff878b408a03 and reverted at commit +79764ec772bc. + +The details taken from the v1 patch: + +One of the former changes for the endpoint management was the more +consistent setup of endpoints at hw_params. +snd_usb_endpoint_configure() is a single function that does the full +setup, and it's called from both PCM hw_params and prepare callbacks. +Although the EP setup at the prepare phase is usually skipped (by +checking need_setup flag), it may be still effective in some cases +like suspend/resume that requires the interface setup again. + +As it's a full and single setup, the invocation of +snd_usb_endpoint_configure() includes not only the USB interface setup +but also the buffer release and allocation. OTOH, doing the buffer +release and re-allocation at PCM prepare phase is rather superfluous, +and better to be done only in the hw_params phase. + +For those optimizations, this patch splits the endpoint setup to two +phases: snd_usb_endpoint_set_params() and snd_usb_endpoint_prepare(), +to be called from hw_params and from prepare, respectively. + +Note that this patch changes the driver operation slightly, +effectively moving the USB interface setup again to PCM prepare stage +instead of hw_params stage, while the buffer allocation and such +initializations are still done at hw_params stage. + +And, the change of the USB interface setup timing (moving to prepare) +gave an interesting "fix", too: it was reported that the recent +kernels caused silent output at the beginning on playbacks on some +devices on Android, and this change casually fixed the regression. +It seems that those devices are picky about the sample rate change (or +the interface change?), and don't follow the too immediate rate +changes. + +Meanwhile, Android operates the PCM in the following order: +- open, then hw_params with the possibly highest sample rate +- close without prepare +- re-open, hw_params with the normal sample rate +- prepare, and start streaming +This procedure ended up the hw_params twice with different rates, and +because the recent kernel did set up the sample rate twice one and +after, it screwed up the device. OTOH, the earlier kernels didn't set +up the USB interface at hw_params, hence this problem didn't appear. + +Now, with this patch, the USB interface setup is again back to the +prepare phase, and it works around the problem automagically. +Although we should address the sample rate problem in a more solid +way in future, let's keep things working as before for now. + +*** + +What's new in the take#2 patch: +- The regression caused by the v1 patch (bko#216500) was due to the + missing check of need_setup flag at hw_params. Now the check is + added, and the snd_usb_endpoint_set_params() call is skipped when + the running EP is re-opened. + +- There was another bug in v1 where the clock reference rate wasn't + updated at hw_params phase, which may lead to a lack of the proper + hw constraints when an application doesn't issue the prepare but + only the hw_params call. This patch fixes it as well by tracking + the clock rate change in the prepare callback with a new flag + "need_update" for the clock reference object, just like others. + +- The configure_endpoints() are simplified and folded back into + snd_usb_pcm_prepare(). + +Fixes: bf6313a0ff76 ("ALSA: usb-audio: Refactor endpoint management") +Fixes: ff878b408a03 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare") +Reported-by: chihhao chen +Link: https://lore.kernel.org/r/87e6d6ae69d68dc588ac9acc8c0f24d6188375c3.camel@mediatek.com +Link: https://lore.kernel.org/r/20220901124136.4984-1-tiwai@suse.de +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216500 +Link: https://lore.kernel.org/r/20220920181106.4894-1-tiwai@suse.de +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/endpoint.c | 76 +++++++++++++++++++++++++++----------------- + sound/usb/endpoint.h | 6 ++-- + sound/usb/pcm.c | 51 ++++++++++++----------------- + 3 files changed, 70 insertions(+), 63 deletions(-) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index 7a7f5ebafe4a..971c33937dca 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -40,6 +40,7 @@ struct snd_usb_clock_ref { + unsigned char clock; + atomic_t locked; + int rate; ++ bool need_setup; + struct list_head list; + }; + +@@ -759,7 +760,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, + * The endpoint needs to be closed via snd_usb_endpoint_close() later. + * + * Note that this function doesn't configure the endpoint. The substream +- * needs to set it up later via snd_usb_endpoint_configure(). ++ * needs to set it up later via snd_usb_endpoint_set_params() and ++ * snd_usb_endpoint_prepare(). + */ + struct snd_usb_endpoint * + snd_usb_endpoint_open(struct snd_usb_audio *chip, +@@ -1289,15 +1291,39 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) + return -ENOMEM; + } + ++/* update the rate of the referred clock; return the actual rate */ ++static int update_clock_ref_rate(struct snd_usb_audio *chip, ++ struct snd_usb_endpoint *ep) ++{ ++ struct snd_usb_clock_ref *clock = ep->clock_ref; ++ int rate = ep->cur_rate; ++ ++ if (!clock || clock->rate == rate) ++ return rate; ++ if (clock->rate) { ++ if (atomic_read(&clock->locked)) ++ return clock->rate; ++ if (clock->rate != rate) { ++ usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", ++ clock->rate, rate, ep->ep_num); ++ return clock->rate; ++ } ++ } ++ clock->rate = rate; ++ clock->need_setup = true; ++ return rate; ++} ++ + /* + * snd_usb_endpoint_set_params: configure an snd_usb_endpoint + * ++ * It's called either from hw_params callback. + * Determine the number of URBs to be used on this endpoint. + * An endpoint must be configured before it can be started. + * An endpoint that is already running can not be reconfigured. + */ +-static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, +- struct snd_usb_endpoint *ep) ++int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, ++ struct snd_usb_endpoint *ep) + { + const struct audioformat *fmt = ep->cur_audiofmt; + int err; +@@ -1349,49 +1375,46 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; + ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; + +- return 0; ++ return update_clock_ref_rate(chip, ep); + } + + static int init_sample_rate(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) + { + struct snd_usb_clock_ref *clock = ep->clock_ref; +- int err; ++ int rate, err; + +- if (clock) { +- if (atomic_read(&clock->locked)) +- return 0; +- if (clock->rate == ep->cur_rate) +- return 0; +- if (clock->rate && clock->rate != ep->cur_rate) { +- usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", +- clock->rate, ep->cur_rate, ep->ep_num); +- return -EINVAL; +- } +- } ++ rate = update_clock_ref_rate(chip, ep); ++ if (rate < 0) ++ return rate; ++ if (clock && !clock->need_setup) ++ return 0; + +- err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate); +- if (err < 0) ++ err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); ++ if (err < 0) { ++ if (clock) ++ clock->rate = 0; /* reset rate */ + return err; ++ } + + if (clock) +- clock->rate = ep->cur_rate; ++ clock->need_setup = false; + return 0; + } + + /* +- * snd_usb_endpoint_configure: Configure the endpoint ++ * snd_usb_endpoint_prepare: Prepare the endpoint + * + * This function sets up the EP to be fully usable state. +- * It's called either from hw_params or prepare callback. ++ * It's called either from prepare callback. + * The function checks need_setup flag, and performs nothing unless needed, + * so it's safe to call this multiple times. + * + * This returns zero if unchanged, 1 if the configuration has changed, + * or a negative error code. + */ +-int snd_usb_endpoint_configure(struct snd_usb_audio *chip, +- struct snd_usb_endpoint *ep) ++int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, ++ struct snd_usb_endpoint *ep) + { + bool iface_first; + int err = 0; +@@ -1412,9 +1435,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + if (err < 0) + goto unlock; + } +- err = snd_usb_endpoint_set_params(chip, ep); +- if (err < 0) +- goto unlock; + goto done; + } + +@@ -1442,10 +1462,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + if (err < 0) + goto unlock; + +- err = snd_usb_endpoint_set_params(chip, ep); +- if (err < 0) +- goto unlock; +- + err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt); + if (err < 0) + goto unlock; +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index 6a9af04cf175..e67ea28faa54 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, + bool is_sync_ep); + void snd_usb_endpoint_close(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); +-int snd_usb_endpoint_configure(struct snd_usb_audio *chip, +- struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, ++ struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, ++ struct snd_usb_endpoint *ep); + int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); + + bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index e692ae04436a..0551d86b379f 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip, + } + } + +-static int configure_endpoints(struct snd_usb_audio *chip, +- struct snd_usb_substream *subs) +-{ +- int err; +- +- if (subs->data_endpoint->need_setup) { +- /* stop any running stream beforehand */ +- if (stop_endpoints(subs, false)) +- sync_pending_stops(subs); +- if (subs->sync_endpoint) { +- err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); +- if (err < 0) +- return err; +- } +- err = snd_usb_endpoint_configure(chip, subs->data_endpoint); +- if (err < 0) +- return err; +- snd_usb_set_format_quirk(subs, subs->cur_audiofmt); +- } else { +- if (subs->sync_endpoint) { +- err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); +- if (err < 0) +- return err; +- } +- } +- +- return 0; +-} +- + /* + * hw_params callback + * +@@ -551,7 +522,16 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, + subs->cur_audiofmt = fmt; + mutex_unlock(&chip->mutex); + +- ret = configure_endpoints(chip, subs); ++ if (!subs->data_endpoint->need_setup) ++ goto unlock; ++ ++ if (subs->sync_endpoint) { ++ ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint); ++ if (ret < 0) ++ goto unlock; ++ } ++ ++ ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint); + + unlock: + if (ret < 0) +@@ -634,9 +614,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + goto unlock; + } + +- ret = configure_endpoints(chip, subs); ++ if (subs->sync_endpoint) { ++ ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); ++ if (ret < 0) ++ goto unlock; ++ } ++ ++ ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); + if (ret < 0) + goto unlock; ++ else if (ret > 0) ++ snd_usb_set_format_quirk(subs, subs->cur_audiofmt); ++ ret = 0; + + /* reset the pointer */ + subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); +-- +2.35.1 + diff --git a/queue-5.19/arm-9233-1-stacktrace-skip-frame-pointer-boundary-ch.patch b/queue-5.19/arm-9233-1-stacktrace-skip-frame-pointer-boundary-ch.patch new file mode 100644 index 00000000000..f2eebb042d9 --- /dev/null +++ b/queue-5.19/arm-9233-1-stacktrace-skip-frame-pointer-boundary-ch.patch @@ -0,0 +1,131 @@ +From bae0285bbf7ff95ee94de3cff03c40b3ab9f3429 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 09:06:22 +0100 +Subject: ARM: 9233/1: stacktrace: Skip frame pointer boundary check for + call_with_stack() + +From: Li Huafei + +[ Upstream commit 5854e4d8530e6ed4c2532a71a6b0474e199d44dd ] + +When using the frame pointer unwinder, it was found that the stack trace +output of stack_trace_save() is incomplete if the stack contains +call_with_stack(): + + [0x7f00002c] dump_stack_task+0x2c/0x90 [hrtimer] + [0x7f0000a0] hrtimer_hander+0x10/0x18 [hrtimer] + [0x801a67f0] __hrtimer_run_queues+0x1b0/0x3b4 + [0x801a7350] hrtimer_run_queues+0xc4/0xd8 + [0x801a597c] update_process_times+0x3c/0x88 + [0x801b5a98] tick_periodic+0x50/0xd8 + [0x801b5bf4] tick_handle_periodic+0x24/0x84 + [0x8010ffc4] twd_handler+0x38/0x48 + [0x8017d220] handle_percpu_devid_irq+0xa8/0x244 + [0x80176e9c] generic_handle_domain_irq+0x2c/0x3c + [0x8052e3a8] gic_handle_irq+0x7c/0x90 + [0x808ab15c] generic_handle_arch_irq+0x60/0x80 + [0x8051191c] call_with_stack+0x1c/0x20 + +For the frame pointer unwinder, unwind_frame() checks stackframe::fp by +stackframe::sp. Since call_with_stack() switches the SP from one stack +to another, stackframe::fp and stackframe: :sp will point to different +stacks, so we can no longer check stackframe::fp by stackframe::sp. Skip +checking stackframe::fp at this point to avoid this problem. + +Signed-off-by: Li Huafei +Reviewed-by: Linus Waleij +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/kernel/stacktrace.c | 40 ++++++++++++++++++++++++++++------ + arch/arm/lib/call_with_stack.S | 2 ++ + 2 files changed, 35 insertions(+), 7 deletions(-) + +diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c +index d0fa2037460a..af87040b0353 100644 +--- a/arch/arm/kernel/stacktrace.c ++++ b/arch/arm/kernel/stacktrace.c +@@ -9,6 +9,8 @@ + #include + #include + ++#include "reboot.h" ++ + #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) + /* + * Unwind the current stack frame and store the new register values in the +@@ -39,29 +41,53 @@ + * Note that with framepointer enabled, even the leaf functions have the same + * prologue and epilogue, therefore we can ignore the LR value in this case. + */ +-int notrace unwind_frame(struct stackframe *frame) ++ ++extern unsigned long call_with_stack_end; ++ ++static int frame_pointer_check(struct stackframe *frame) + { + unsigned long high, low; + unsigned long fp = frame->fp; ++ unsigned long pc = frame->pc; ++ ++ /* ++ * call_with_stack() is the only place we allow SP to jump from one ++ * stack to another, with FP and SP pointing to different stacks, ++ * skipping the FP boundary check at this point. ++ */ ++ if (pc >= (unsigned long)&call_with_stack && ++ pc < (unsigned long)&call_with_stack_end) ++ return 0; + + /* only go to a higher address on the stack */ + low = frame->sp; + high = ALIGN(low, THREAD_SIZE); + +-#ifdef CONFIG_CC_IS_CLANG + /* check current frame pointer is within bounds */ ++#ifdef CONFIG_CC_IS_CLANG + if (fp < low + 4 || fp > high - 4) + return -EINVAL; +- +- frame->sp = frame->fp; +- frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); +- frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); + #else +- /* check current frame pointer is within bounds */ + if (fp < low + 12 || fp > high - 4) + return -EINVAL; ++#endif ++ ++ return 0; ++} ++ ++int notrace unwind_frame(struct stackframe *frame) ++{ ++ unsigned long fp = frame->fp; ++ ++ if (frame_pointer_check(frame)) ++ return -EINVAL; + + /* restore the registers from the stack frame */ ++#ifdef CONFIG_CC_IS_CLANG ++ frame->sp = frame->fp; ++ frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp)); ++ frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4)); ++#else + frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12)); + frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8)); + frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4)); +diff --git a/arch/arm/lib/call_with_stack.S b/arch/arm/lib/call_with_stack.S +index 0a268a6c513c..5030d4e8d126 100644 +--- a/arch/arm/lib/call_with_stack.S ++++ b/arch/arm/lib/call_with_stack.S +@@ -46,4 +46,6 @@ UNWIND( .setfp fpreg, sp ) + pop {fpreg, pc} + UNWIND( .fnend ) + #endif ++ .globl call_with_stack_end ++call_with_stack_end: + ENDPROC(call_with_stack) +-- +2.35.1 + diff --git a/queue-5.19/arm-9234-1-stacktrace-avoid-duplicate-saving-of-exce.patch b/queue-5.19/arm-9234-1-stacktrace-avoid-duplicate-saving-of-exce.patch new file mode 100644 index 00000000000..00a1121375c --- /dev/null +++ b/queue-5.19/arm-9234-1-stacktrace-avoid-duplicate-saving-of-exce.patch @@ -0,0 +1,177 @@ +From 3b2afaeb4e269491baff7d4b21dec0fe573c20ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 09:08:46 +0100 +Subject: ARM: 9234/1: stacktrace: Avoid duplicate saving of exception PC value + +From: Li Huafei + +[ Upstream commit 752ec621ef5c30777958cc5eb5f1cf394f7733f4 ] + +Because an exception stack frame is not created in the exception entry, +save_trace() does special handling for the exception PC, but this is +only needed when CONFIG_FRAME_POINTER_UNWIND=y. When +CONFIG_ARM_UNWIND=y, unwind annotations have been added to the exception +entry and save_trace() will repeatedly save the exception PC: + + [0x7f000090] hrtimer_hander+0x8/0x10 [hrtimer] + [0x8019ec50] __hrtimer_run_queues+0x18c/0x394 + [0x8019f760] hrtimer_run_queues+0xbc/0xd0 + [0x8019def0] update_process_times+0x34/0x80 + [0x801ad2a4] tick_periodic+0x48/0xd0 + [0x801ad3dc] tick_handle_periodic+0x1c/0x7c + [0x8010f2e0] twd_handler+0x30/0x40 + [0x80177620] handle_percpu_devid_irq+0xa0/0x23c + [0x801718d0] generic_handle_domain_irq+0x24/0x34 + [0x80502d28] gic_handle_irq+0x74/0x88 + [0x8085817c] generic_handle_arch_irq+0x58/0x78 + [0x80100ba8] __irq_svc+0x88/0xc8 + [0x80108114] arch_cpu_idle+0x38/0x3c + [0x80108114] arch_cpu_idle+0x38/0x3c <==== duplicate saved exception PC + [0x80861bf8] default_idle_call+0x38/0x130 + [0x8015d5cc] do_idle+0x150/0x214 + [0x8015d978] cpu_startup_entry+0x18/0x1c + [0x808589c0] rest_init+0xd8/0xdc + [0x80c00a44] arch_post_acpi_subsys_init+0x0/0x8 + +We can move the special handling of the exception PC in save_trace() to +the unwind_frame() of the frame pointer unwinder. + +Signed-off-by: Li Huafei +Reviewed-by: Linus Waleij +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/include/asm/stacktrace.h | 6 +++++ + arch/arm/kernel/return_address.c | 1 + + arch/arm/kernel/stacktrace.c | 44 +++++++++++++++++++++---------- + 3 files changed, 37 insertions(+), 14 deletions(-) + +diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h +index 3e78f921b8b2..39be2d1aa27b 100644 +--- a/arch/arm/include/asm/stacktrace.h ++++ b/arch/arm/include/asm/stacktrace.h +@@ -21,6 +21,9 @@ struct stackframe { + struct llist_node *kr_cur; + struct task_struct *tsk; + #endif ++#ifdef CONFIG_UNWINDER_FRAME_POINTER ++ bool ex_frame; ++#endif + }; + + static __always_inline +@@ -34,6 +37,9 @@ void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame) + frame->kr_cur = NULL; + frame->tsk = current; + #endif ++#ifdef CONFIG_UNWINDER_FRAME_POINTER ++ frame->ex_frame = in_entry_text(frame->pc); ++#endif + } + + extern int unwind_frame(struct stackframe *frame); +diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c +index 8aac1e10b117..38f1ea9c724d 100644 +--- a/arch/arm/kernel/return_address.c ++++ b/arch/arm/kernel/return_address.c +@@ -47,6 +47,7 @@ void *return_address(unsigned int level) + frame.kr_cur = NULL; + frame.tsk = current; + #endif ++ frame.ex_frame = false; + + walk_stackframe(&frame, save_return_addr, &data); + +diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c +index af87040b0353..85443b5d1922 100644 +--- a/arch/arm/kernel/stacktrace.c ++++ b/arch/arm/kernel/stacktrace.c +@@ -82,6 +82,27 @@ int notrace unwind_frame(struct stackframe *frame) + if (frame_pointer_check(frame)) + return -EINVAL; + ++ /* ++ * When we unwind through an exception stack, include the saved PC ++ * value into the stack trace. ++ */ ++ if (frame->ex_frame) { ++ struct pt_regs *regs = (struct pt_regs *)frame->sp; ++ ++ /* ++ * We check that 'regs + sizeof(struct pt_regs)' (that is, ++ * ®s[1]) does not exceed the bottom of the stack to avoid ++ * accessing data outside the task's stack. This may happen ++ * when frame->ex_frame is a false positive. ++ */ ++ if ((unsigned long)®s[1] > ALIGN(frame->sp, THREAD_SIZE)) ++ return -EINVAL; ++ ++ frame->pc = regs->ARM_pc; ++ frame->ex_frame = false; ++ return 0; ++ } ++ + /* restore the registers from the stack frame */ + #ifdef CONFIG_CC_IS_CLANG + frame->sp = frame->fp; +@@ -98,6 +119,9 @@ int notrace unwind_frame(struct stackframe *frame) + (void *)frame->fp, &frame->kr_cur); + #endif + ++ if (in_entry_text(frame->pc)) ++ frame->ex_frame = true; ++ + return 0; + } + #endif +@@ -128,7 +152,6 @@ static int save_trace(struct stackframe *frame, void *d) + { + struct stack_trace_data *data = d; + struct stack_trace *trace = data->trace; +- struct pt_regs *regs; + unsigned long addr = frame->pc; + + if (data->no_sched_functions && in_sched_functions(addr)) +@@ -139,19 +162,6 @@ static int save_trace(struct stackframe *frame, void *d) + } + + trace->entries[trace->nr_entries++] = addr; +- +- if (trace->nr_entries >= trace->max_entries) +- return 1; +- +- if (!in_entry_text(frame->pc)) +- return 0; +- +- regs = (struct pt_regs *)frame->sp; +- if ((unsigned long)®s[1] > ALIGN(frame->sp, THREAD_SIZE)) +- return 0; +- +- trace->entries[trace->nr_entries++] = regs->ARM_pc; +- + return trace->nr_entries >= trace->max_entries; + } + +@@ -193,6 +203,9 @@ static noinline void __save_stack_trace(struct task_struct *tsk, + frame.kr_cur = NULL; + frame.tsk = tsk; + #endif ++#ifdef CONFIG_UNWINDER_FRAME_POINTER ++ frame.ex_frame = false; ++#endif + + walk_stackframe(&frame, save_trace, &data); + } +@@ -214,6 +227,9 @@ void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) + frame.kr_cur = NULL; + frame.tsk = current; + #endif ++#ifdef CONFIG_UNWINDER_FRAME_POINTER ++ frame.ex_frame = in_entry_text(frame.pc); ++#endif + + walk_stackframe(&frame, save_trace, &data); + } +-- +2.35.1 + diff --git a/queue-5.19/arm-9242-1-kasan-only-map-modules-if-config_kasan_vm.patch b/queue-5.19/arm-9242-1-kasan-only-map-modules-if-config_kasan_vm.patch new file mode 100644 index 00000000000..0bcee6661e1 --- /dev/null +++ b/queue-5.19/arm-9242-1-kasan-only-map-modules-if-config_kasan_vm.patch @@ -0,0 +1,77 @@ +From 79983be1e7612ea031532353f28fbc308bd3c58a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 16:26:59 +0100 +Subject: ARM: 9242/1: kasan: Only map modules if CONFIG_KASAN_VMALLOC=n + +From: Alex Sverdlin + +[ Upstream commit 823f606ab6b4759a1faf0388abcf4fb0776710d2 ] + +In case CONFIG_KASAN_VMALLOC=y kasan_populate_vmalloc() allocates the +shadow pages dynamically. But even worse is that kasan_release_vmalloc() +releases them, which is not compatible with create_mapping() of +MODULES_VADDR..MODULES_END range: + +BUG: Bad page state in process kworker/9:1 pfn:2068b +page:e5e06160 refcount:0 mapcount:0 mapping:00000000 index:0x0 +flags: 0x1000(reserved) +raw: 00001000 e5e06164 e5e06164 00000000 00000000 00000000 ffffffff 00000000 +page dumped because: PAGE_FLAGS_CHECK_AT_FREE flag(s) set +bad because of flags: 0x1000(reserved) +Modules linked in: ip_tables +CPU: 9 PID: 154 Comm: kworker/9:1 Not tainted 5.4.188-... #1 +Hardware name: LSI Axxia AXM55XX +Workqueue: events do_free_init +unwind_backtrace +show_stack +dump_stack +bad_page +free_pcp_prepare +free_unref_page +kasan_depopulate_vmalloc_pte +__apply_to_page_range +apply_to_existing_page_range +kasan_release_vmalloc +__purge_vmap_area_lazy +_vm_unmap_aliases.part.0 +__vunmap +do_free_init +process_one_work +worker_thread +kthread + +Reviewed-by: Linus Walleij +Signed-off-by: Alexander Sverdlin +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/mm/kasan_init.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c +index 5ad0d6c56d56..29d7233e5ad2 100644 +--- a/arch/arm/mm/kasan_init.c ++++ b/arch/arm/mm/kasan_init.c +@@ -264,12 +264,17 @@ void __init kasan_init(void) + + /* + * 1. The module global variables are in MODULES_VADDR ~ MODULES_END, +- * so we need to map this area. ++ * so we need to map this area if CONFIG_KASAN_VMALLOC=n. With ++ * VMALLOC support KASAN will manage this region dynamically, ++ * refer to kasan_populate_vmalloc() and ARM's implementation of ++ * module_alloc(). + * 2. PKMAP_BASE ~ PKMAP_BASE+PMD_SIZE's shadow and MODULES_VADDR + * ~ MODULES_END's shadow is in the same PMD_SIZE, so we can't + * use kasan_populate_zero_shadow. + */ +- create_mapping((void *)MODULES_VADDR, (void *)(PKMAP_BASE + PMD_SIZE)); ++ if (!IS_ENABLED(CONFIG_KASAN_VMALLOC) && IS_ENABLED(CONFIG_MODULES)) ++ create_mapping((void *)MODULES_VADDR, (void *)(MODULES_END)); ++ create_mapping((void *)PKMAP_BASE, (void *)(PKMAP_BASE + PMD_SIZE)); + + /* + * KAsan may reuse the contents of kasan_early_shadow_pte directly, so +-- +2.35.1 + diff --git a/queue-5.19/arm-9243-1-riscpc-unbreak-the-build.patch b/queue-5.19/arm-9243-1-riscpc-unbreak-the-build.patch new file mode 100644 index 00000000000..5e1f2ec0d1b --- /dev/null +++ b/queue-5.19/arm-9243-1-riscpc-unbreak-the-build.patch @@ -0,0 +1,57 @@ +From 1c2749bcddffdd0a6271f24d6aff82f1abbccf4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 23:13:53 +0100 +Subject: ARM: 9243/1: riscpc: Unbreak the build +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bart Van Assche + +[ Upstream commit 32844a8eecaa4a3e65841c53e43e04a9087d1ef6 ] + +This patch fixes the following build error: + +In file included from ./include/linux/io.h:13, + from ./arch/arm/mach-rpc/include/mach/uncompress.h:9, + from arch/arm/boot/compressed/misc.c:31: +./arch/arm/include/asm/io.h:85:22: error: conflicting types for ‘__raw_writeb’ + 85 | #define __raw_writeb __raw_writeb + | ^~~~~~~~~~~~ +./arch/arm/include/asm/io.h:86:20: note: in expansion of macro ‘__raw_writeb’ + 86 | static inline void __raw_writeb(u8 val, volatile void __iomem *addr) + | ^~~~~~~~~~~~ +In file included from arch/arm/boot/compressed/misc.c:26: +arch/arm/boot/compressed/misc-ep93xx.h:13:20: note: previous definition of ‘__raw_writeb’ was here + 13 | static inline void __raw_writeb(unsigned char value, unsigned int ptr) + | ^~~~~~~~~~~~ + +To: Russell King + +Cc: Arnd Bergmann +Cc: linux-arm-kernel@lists.infradead.org +Fixes: 0361c7e504b1 ("ARM: ep93xx: multiplatform support") +Signed-off-by: Bart Van Assche +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/boot/compressed/misc.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c +index cb2e069dc73f..abfed1aa2baa 100644 +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -23,7 +23,9 @@ unsigned int __machine_arch_type; + #include + #include + #include "misc.h" ++#ifdef CONFIG_ARCH_EP93XX + #include "misc-ep93xx.h" ++#endif + + static void putstr(const char *ptr); + +-- +2.35.1 + diff --git a/queue-5.19/arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch b/queue-5.19/arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch new file mode 100644 index 00000000000..5a7b3c49c7a --- /dev/null +++ b/queue-5.19/arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch @@ -0,0 +1,36 @@ +From 0d4d8b6f1759819656edced889486fc87b15202f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 05:25:51 +0100 +Subject: ARM: 9244/1: dump: Fix wrong pg_level in walk_pmd() + +From: Wang Kefeng + +[ Upstream commit 2ccd19b3ffac07cc7e75a2bd1ed779728bb67197 ] + +After ARM supports p4d page tables, the pg_level for note_page() +in walk_pmd() should be 4, not 3, fix it. + +Fixes: 84e6ffb2c49c ("arm: add support for folded p4d page tables") +Signed-off-by: Kefeng Wang +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/mm/dump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/mm/dump.c b/arch/arm/mm/dump.c +index fb688003d156..712da6a81b23 100644 +--- a/arch/arm/mm/dump.c ++++ b/arch/arm/mm/dump.c +@@ -346,7 +346,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start) + addr = start + i * PMD_SIZE; + domain = get_domain_name(pmd); + if (pmd_none(*pmd) || pmd_large(*pmd) || !pmd_present(*pmd)) +- note_page(st, addr, 3, pmd_val(*pmd), domain); ++ note_page(st, addr, 4, pmd_val(*pmd), domain); + else + walk_pte(st, pmd, addr, domain); + +-- +2.35.1 + diff --git a/queue-5.19/arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch b/queue-5.19/arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch new file mode 100644 index 00000000000..791f116cce0 --- /dev/null +++ b/queue-5.19/arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch @@ -0,0 +1,46 @@ +From dd538f692f7d989c1c47f1ca656d0bb583d2906d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:10:49 +0100 +Subject: ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE + +From: Wang Kefeng + +[ Upstream commit 14ca1a4690750bb54e1049e49f3140ef48958a6e ] + +MT_MEMORY_RO is introduced by commit 598f0a99fa8a ("ARM: 9210/1: +Mark the FDT_FIXED sections as shareable"), which is a readonly +memory type for FDT area, but there are some different between +ARM_LPAE and non-ARM_LPAE, we need to setup PMD_SECT_AP2 and +L_PMD_SECT_RDONLY for MT_MEMORY_RO when ARM_LAPE enabled. + +non-ARM_LPAE 0xff800000-0xffa00000 2M PGD KERNEL ro NX SHD +ARM_LPAE 0xff800000-0xffc00000 4M PMD RW NX SHD +ARM_LPAE+fix 0xff800000-0xffc00000 4M PMD ro NX SHD + +Fixes: 598f0a99fa8a ("ARM: 9210/1: Mark the FDT_FIXED sections as shareable") +Signed-off-by: Kefeng Wang +Signed-off-by: Russell King (Oracle) +Signed-off-by: Sasha Levin +--- + arch/arm/mm/mmu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c +index cd17e324aa51..83a91e0ab848 100644 +--- a/arch/arm/mm/mmu.c ++++ b/arch/arm/mm/mmu.c +@@ -300,7 +300,11 @@ static struct mem_type mem_types[] __ro_after_init = { + .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | + L_PTE_XN | L_PTE_RDONLY, + .prot_l1 = PMD_TYPE_TABLE, ++#ifdef CONFIG_ARM_LPAE ++ .prot_sect = PMD_TYPE_SECT | L_PMD_SECT_RDONLY | PMD_SECT_AP2, ++#else + .prot_sect = PMD_TYPE_SECT, ++#endif + .domain = DOMAIN_KERNEL, + }, + [MT_ROM] = { +-- +2.35.1 + diff --git a/queue-5.19/arm-decompressor-include-.data.rel.ro.local.patch b/queue-5.19/arm-decompressor-include-.data.rel.ro.local.patch new file mode 100644 index 00000000000..5bbab049ce4 --- /dev/null +++ b/queue-5.19/arm-decompressor-include-.data.rel.ro.local.patch @@ -0,0 +1,50 @@ +From 364e507f7d078fcd4d4a56592a124d5c2d9db5e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 15:41:03 -0700 +Subject: ARM: decompressor: Include .data.rel.ro.local + +From: Kees Cook + +[ Upstream commit 1b64daf413acd86c2c13f5443f6b4ef3690c8061 ] + +The .data.rel.ro.local section has the same semantics as .data.rel.ro +here, so include it in the .rodata section of the decompressor. +Additionally since the .printk_index section isn't usable outside of +the core kernel, discard it in the decompressor. Avoids these warnings: + +arm-linux-gnueabi-ld: warning: orphan section `.data.rel.ro.local' from `arch/arm/boot/compressed/fdt_rw.o' being placed in section `.data.rel.ro.local' +arm-linux-gnueabi-ld: warning: orphan section `.printk_index' from `arch/arm/boot/compressed/fdt_rw.o' being placed in section `.printk_index' + +Reported-by: kernel test robot +Link: https://lore.kernel.org/linux-mm/202209080545.qMIVj7YM-lkp@intel.com +Cc: Russell King +Cc: linux-arm-kernel@lists.infradead.org +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + arch/arm/boot/compressed/vmlinux.lds.S | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S +index 1bcb68ac4b01..3fcb3e62dc56 100644 +--- a/arch/arm/boot/compressed/vmlinux.lds.S ++++ b/arch/arm/boot/compressed/vmlinux.lds.S +@@ -23,6 +23,7 @@ SECTIONS + *(.ARM.extab*) + *(.note.*) + *(.rel.*) ++ *(.printk_index) + /* + * Discard any r/w data - this produces a link error if we have any, + * which is required for PIC decompression. Local data generates +@@ -57,6 +58,7 @@ SECTIONS + *(.rodata) + *(.rodata.*) + *(.data.rel.ro) ++ *(.data.rel.ro.*) + } + .piggydata : { + *(.piggydata) +-- +2.35.1 + diff --git a/queue-5.19/arm-drop-cmdline_-dependency-on-atags.patch b/queue-5.19/arm-drop-cmdline_-dependency-on-atags.patch new file mode 100644 index 00000000000..95a3f66b450 --- /dev/null +++ b/queue-5.19/arm-drop-cmdline_-dependency-on-atags.patch @@ -0,0 +1,45 @@ +From 5560eb000d87a971543b3553373e039204cfddda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 15:28:26 +0200 +Subject: ARM: Drop CMDLINE_* dependency on ATAGS + +From: Geert Uytterhoeven + +[ Upstream commit 136f4b1ec7c962ee37a787e095fd37b058d72bd3 ] + +On arm32, the configuration options to specify the kernel command line +type depend on ATAGS. However, the actual CMDLINE cofiguration option +does not depend on ATAGS, and the code that handles this is not specific +to ATAGS (see drivers/of/fdt.c:early_init_dt_scan_chosen()). + +Hence users who desire to override the kernel command line on arm32 must +enable support for ATAGS, even on a pure-DT system. Other architectures +(arm64, loongarch, microblaze, nios2, powerpc, and riscv) do not impose +such a restriction. + +Hence drop the dependency on ATAGS. + +Fixes: bd51e2f595580fb6 ("ARM: 7506/1: allow for ATAGS to be configured out when DT support is selected") +Signed-off-by: Geert Uytterhoeven +Acked-by: Ard Biesheuvel +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 7630ba9cb6cc..ccc4706484d3 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1653,7 +1653,6 @@ config CMDLINE + choice + prompt "Kernel command line type" if CMDLINE != "" + default CMDLINE_FROM_BOOTLOADER +- depends on ATAGS + + config CMDLINE_FROM_BOOTLOADER + bool "Use bootloader kernel arguments if available" +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-exynos-add-panel-and-backlight-to-p4note.patch b/queue-5.19/arm-dts-exynos-add-panel-and-backlight-to-p4note.patch new file mode 100644 index 00000000000..c2931d0231b --- /dev/null +++ b/queue-5.19/arm-dts-exynos-add-panel-and-backlight-to-p4note.patch @@ -0,0 +1,166 @@ +From d7d5751b85040ecb50c47907be2f19295159d4e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 May 2022 21:37:09 +0200 +Subject: ARM: dts: exynos: add panel and backlight to p4note +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin Jücker + +[ Upstream commit 6c52573bf4c3a0f6e7142264fb36b31ae2c3707a ] + +Add configuration for the LTL101AL01 panel and a pwm backlight to drive +the display in the p4note devices. + +Signed-off-by: Martin Jücker +Link: https://lore.kernel.org/r/20220516193709.10037-3-martin.juecker@gmail.com +Signed-off-by: Krzysztof Kozlowski +Stable-dep-of: a26aa1238415 ("ntfs3: rework xattr handlers and switch to POSIX ACL VFS helpers") +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/exynos4412-p4note.dtsi | 84 ++++++++++++++++++++---- + 1 file changed, 71 insertions(+), 13 deletions(-) + +diff --git a/arch/arm/boot/dts/exynos4412-p4note.dtsi b/arch/arm/boot/dts/exynos4412-p4note.dtsi +index 97f131b1014b..1fd051b52387 100644 +--- a/arch/arm/boot/dts/exynos4412-p4note.dtsi ++++ b/arch/arm/boot/dts/exynos4412-p4note.dtsi +@@ -106,6 +106,16 @@ + regulator-always-on; + }; + ++ panel_vdd: voltage-regulator-4 { ++ compatible = "regulator-fixed"; ++ regulator-name = "LCD_ENABLE"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&lcd_enable>; ++ gpios = <&gpc0 1 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ regulator-boot-on; ++ }; ++ + wlan_pwrseq: sdhci3-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpm3 5 GPIO_ACTIVE_LOW>; +@@ -216,6 +226,32 @@ + monitored-battery = <&battery_cell>; + }; + }; ++ ++ panel { ++ compatible = "samsung,ltl101al01"; ++ pinctrl-0 = <&lvds_nshdn>; ++ pinctrl-names = "default"; ++ power-supply = <&panel_vdd>; ++ enable-gpios = <&gpm0 5 GPIO_ACTIVE_HIGH>; ++ backlight = <&backlight>; ++ ++ port { ++ lcd_ep: endpoint { ++ remote-endpoint = <&fimd_ep>; ++ }; ++ }; ++ }; ++ ++ backlight: backlight { ++ compatible = "pwm-backlight"; ++ pinctrl-0 = <&led_bl_reset>; ++ pinctrl-names = "default"; ++ enable-gpios = <&gpm0 1 GPIO_ACTIVE_HIGH>; ++ pwms = <&pwm 1 78770 0>; ++ brightness-levels = <0 48 128 255>; ++ num-interpolated-steps = <8>; ++ default-brightness-level = <12>; ++ }; + }; + + &adc { +@@ -295,22 +331,19 @@ + }; + + &fimd { +- pinctrl-0 = <&lcd_clk &lcd_data24 &pwm1_out>; ++ pinctrl-0 = <&lcd_clk &lcd_data24>; + pinctrl-names = "default"; ++ #address-cells = <1>; ++ #size-cells = <0>; + status = "okay"; + +- display-timings { +- timing0 { +- clock-frequency = <66666666>; +- hactive = <1280>; +- vactive = <800>; +- hfront-porch = <18>; +- hback-porch = <36>; +- hsync-len = <16>; +- vback-porch = <16>; +- vfront-porch = <4>; +- vsync-len = <3>; +- hsync-active = <1>; ++ samsung,invert-vclk; ++ ++ port@3 { ++ reg = <3>; ++ ++ fimd_ep: endpoint { ++ remote-endpoint = <&lcd_ep>; + }; + }; + }; +@@ -687,6 +720,12 @@ + samsung,pin-pud = ; + }; + ++ lcd_enable: lcd-enable-pins { ++ samsung,pins = "gpc0-1"; ++ samsung,pin-function = ; ++ samsung,pin-pud = ; ++ }; ++ + sleep0: sleep-state { + PIN_SLP(gpa0-0, INPUT, NONE); + PIN_SLP(gpa0-1, OUT0, NONE); +@@ -809,12 +848,24 @@ + /* 0 = CP, 1 = AP (serial output) */ + }; + ++ led_bl_reset: led-bl-reset-pins { ++ samsung,pins = "gpm0-1"; ++ samsung,pin-function = ; ++ samsung,pin-pud = ; ++ }; ++ + tsp_rst: tsp-rst-pins { + samsung,pins = "gpm0-4"; + samsung,pin-function = ; + samsung,pin-pud = ; + }; + ++ lvds_nshdn: lvds-nshdn-pins { ++ samsung,pins = "gpm0-5"; ++ samsung,pin-function = ; ++ samsung,pin-pud = ; ++ }; ++ + tsp_irq: tsp-irq-pins { + samsung,pins = "gpm2-3"; + samsung,pin-function = ; +@@ -1100,6 +1151,13 @@ + assigned-clock-parents = <&clock CLK_XUSBXTI>; + }; + ++&pwm { ++ pinctrl-0 = <&pwm1_out>; ++ pinctrl-names = "default"; ++ samsung,pwm-outputs = <1>; ++ status = "okay"; ++}; ++ + &rtc { + clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>; + clock-names = "rtc", "rtc_src"; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-exynos-correct-s5k6a3-reset-polarity-on-mida.patch b/queue-5.19/arm-dts-exynos-correct-s5k6a3-reset-polarity-on-mida.patch new file mode 100644 index 00000000000..bea4a158c16 --- /dev/null +++ b/queue-5.19/arm-dts-exynos-correct-s5k6a3-reset-polarity-on-mida.patch @@ -0,0 +1,42 @@ +From 38170b5c11b9ac5f32b471de5b90fd459d5a40eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 12:43:53 +0200 +Subject: ARM: dts: exynos: correct s5k6a3 reset polarity on Midas family + +From: Dmitry Torokhov + +[ Upstream commit 3ba2d4bb9592bf7a6a3fe3dbe711ecfc3d004bab ] + +According to s5k6a3 driver code, the reset line for the chip appears to +be active low. This also matches the typical polarity of reset lines in +general. Let's fix it up as having correct polarity in DTS is important +when the driver will be switched over to gpiod API. + +Fixes: b4fec64758ab ("ARM: dts: Add camera device nodes for Exynos4412 TRATS2 board") +Signed-off-by: Dmitry Torokhov +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20220913164104.203957-1-dmitry.torokhov@gmail.com +Link: https://lore.kernel.org/r/20220926104354.118578-2-krzysztof.kozlowski@linaro.org' +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/exynos4412-midas.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/exynos4412-midas.dtsi b/arch/arm/boot/dts/exynos4412-midas.dtsi +index 23f50c9be527..6ca9108b7633 100644 +--- a/arch/arm/boot/dts/exynos4412-midas.dtsi ++++ b/arch/arm/boot/dts/exynos4412-midas.dtsi +@@ -585,7 +585,7 @@ + clocks = <&camera 1>; + clock-names = "extclk"; + samsung,camclk-out = <1>; +- gpios = <&gpm1 6 GPIO_ACTIVE_HIGH>; ++ gpios = <&gpm1 6 GPIO_ACTIVE_LOW>; + + port { + is_s5k6a3_ep: endpoint { +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-exynos-fix-polarity-of-vbus-gpio-of-origen.patch b/queue-5.19/arm-dts-exynos-fix-polarity-of-vbus-gpio-of-origen.patch new file mode 100644 index 00000000000..9d188e94e39 --- /dev/null +++ b/queue-5.19/arm-dts-exynos-fix-polarity-of-vbus-gpio-of-origen.patch @@ -0,0 +1,39 @@ +From 36eb99ea0e9b2333a1bbb93888797676ce2afdae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 15:05:03 -0700 +Subject: ARM: dts: exynos: fix polarity of VBUS GPIO of Origen + +From: Dmitry Torokhov + +[ Upstream commit a08137bd1e0a7ce951dce9ce4a83e39d379b6e1b ] + +EHCI Oxynos (drivers/usb/host/ehci-exynos.c) drives VBUS GPIO high when +trying to power up the bus, therefore the GPIO in DTS must be marked as +"active high". This will be important when EHCI driver is converted to +gpiod API that respects declared polarities. + +Fixes: 4e8991def565 ("ARM: dts: exynos: Enable AX88760 USB hub on Origen board") +Signed-off-by: Dmitry Torokhov +Link: https://lore.kernel.org/r/20220927220504.3744878-1-dmitry.torokhov@gmail.com +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/exynos4412-origen.dts | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts +index 6db09dba07ff..a3905e27b9cd 100644 +--- a/arch/arm/boot/dts/exynos4412-origen.dts ++++ b/arch/arm/boot/dts/exynos4412-origen.dts +@@ -95,7 +95,7 @@ + }; + + &ehci { +- samsung,vbus-gpio = <&gpx3 5 1>; ++ samsung,vbus-gpio = <&gpx3 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>; + phy-names = "hsic0", "hsic1"; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6-delete-interrupts-property-if-interrupt.patch b/queue-5.19/arm-dts-imx6-delete-interrupts-property-if-interrupt.patch new file mode 100644 index 00000000000..9222c690bb2 --- /dev/null +++ b/queue-5.19/arm-dts-imx6-delete-interrupts-property-if-interrupt.patch @@ -0,0 +1,170 @@ +From aa89370507b7da7890d08477f13bfd2111729a6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Jul 2022 08:41:58 +0200 +Subject: ARM: dts: imx6: delete interrupts property if interrupts-extended is + set + +From: Alexander Stein + +[ Upstream commit c9d38ff7080b2c4fa6786b82210fa13115895aae ] + +In most cases this is related to fsl,err006687-workaround-present, which +requires a GPIO interrupt next a GIC interrupt. + +This fixes the dtbs_check warning: +imx6dl-mba6a.dtb: ethernet@2188000: More than one condition true in oneOf schema: + {'$filename': 'Documentation/devicetree/bindings/net/fsl,fec.yaml', +[...] + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6dl-riotboard.dts | 1 + + arch/arm/boot/dts/imx6q-arm2.dts | 1 + + arch/arm/boot/dts/imx6q-evi.dts | 1 + + arch/arm/boot/dts/imx6q-mccmon6.dts | 1 + + arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-sabreauto.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-tqma6a.dtsi | 1 + + arch/arm/boot/dts/imx6qdl-ts7970.dtsi | 1 + + 11 files changed, 11 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts +index e7d9bfbfd0e4..e7be05f205d3 100644 +--- a/arch/arm/boot/dts/imx6dl-riotboard.dts ++++ b/arch/arm/boot/dts/imx6dl-riotboard.dts +@@ -90,6 +90,7 @@ + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii-id"; + phy-handle = <&rgmii_phy>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts +index 0b40f52268b3..75586299d9ca 100644 +--- a/arch/arm/boot/dts/imx6q-arm2.dts ++++ b/arch/arm/boot/dts/imx6q-arm2.dts +@@ -178,6 +178,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6q-evi.dts b/arch/arm/boot/dts/imx6q-evi.dts +index c63f371ede8b..78d941fef5df 100644 +--- a/arch/arm/boot/dts/imx6q-evi.dts ++++ b/arch/arm/boot/dts/imx6q-evi.dts +@@ -146,6 +146,7 @@ + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6q-mccmon6.dts b/arch/arm/boot/dts/imx6q-mccmon6.dts +index 55692c73943d..64ab01018b71 100644 +--- a/arch/arm/boot/dts/imx6q-mccmon6.dts ++++ b/arch/arm/boot/dts/imx6q-mccmon6.dts +@@ -100,6 +100,7 @@ + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + phy-reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; +diff --git a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi +index 0ad4cb4f1e82..a53a5d0766a5 100644 +--- a/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi +@@ -192,6 +192,7 @@ + phy-mode = "rgmii"; + phy-handle = <ðphy>; + phy-reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi +index beaa2dcd436c..57c21a01f126 100644 +--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi +@@ -334,6 +334,7 @@ + phy-mode = "rgmii"; + phy-handle = <ðphy>; + phy-reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi +index ee7e2371f94b..000e9dc97b1a 100644 +--- a/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi +@@ -263,6 +263,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi +index 904d5d051d63..731759bdd7f5 100644 +--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi +@@ -267,6 +267,7 @@ + phy-mode = "rgmii"; + phy-handle = <ðphy>; + phy-reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +index 1368a4762037..3dbb460ef102 100644 +--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi +@@ -295,6 +295,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii-id"; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-tqma6a.dtsi b/arch/arm/boot/dts/imx6qdl-tqma6a.dtsi +index 7dc3f0005b0f..0a36e1bce375 100644 +--- a/arch/arm/boot/dts/imx6qdl-tqma6a.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-tqma6a.dtsi +@@ -7,6 +7,7 @@ + #include + + &fec { ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +diff --git a/arch/arm/boot/dts/imx6qdl-ts7970.dtsi b/arch/arm/boot/dts/imx6qdl-ts7970.dtsi +index d6ba4b2a60f6..c096d25a6f5b 100644 +--- a/arch/arm/boot/dts/imx6qdl-ts7970.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-ts7970.dtsi +@@ -192,6 +192,7 @@ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; ++ /delete-property/ interrupts; + interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>, + <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>; + fsl,err006687-workaround-present; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6dl-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6dl-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..140f443354d --- /dev/null +++ b/queue-5.19/arm-dts-imx6dl-add-missing-properties-for-sram.patch @@ -0,0 +1,38 @@ +From 1e3bb3e68d56865e667375b80f91eab29db70936 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:32 +0200 +Subject: ARM: dts: imx6dl: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit f5848b95633d598bacf0500e0108dc5961af88c0 ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@900000: '#address-cells' is a required property +sram@900000: '#size-cells' is a required property +sram@900000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6dl.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi +index fdd81fdc3f35..cd3183c36488 100644 +--- a/arch/arm/boot/dts/imx6dl.dtsi ++++ b/arch/arm/boot/dts/imx6dl.dtsi +@@ -84,6 +84,9 @@ + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x20000>; ++ ranges = <0 0x00900000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6QDL_CLK_OCRAM>; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6q-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6q-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..1fef76d8924 --- /dev/null +++ b/queue-5.19/arm-dts-imx6q-add-missing-properties-for-sram.patch @@ -0,0 +1,38 @@ +From 288a6651f91bf0fe71dd88df5b126e09d1483bd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:31 +0200 +Subject: ARM: dts: imx6q: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit b11d083c5dcec7c42fe982c854706d404ddd3a5f ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@900000: '#address-cells' is a required property +sram@900000: '#size-cells' is a required property +sram@900000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6q.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi +index 9caba4529c71..a8069e0a8fe8 100644 +--- a/arch/arm/boot/dts/imx6q.dtsi ++++ b/arch/arm/boot/dts/imx6q.dtsi +@@ -163,6 +163,9 @@ + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x40000>; ++ ranges = <0 0x00900000 0x40000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6QDL_CLK_OCRAM>; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6qdl-kontron-samx6i-hook-up-ddc-i2c-bus.patch b/queue-5.19/arm-dts-imx6qdl-kontron-samx6i-hook-up-ddc-i2c-bus.patch new file mode 100644 index 00000000000..888aaafe710 --- /dev/null +++ b/queue-5.19/arm-dts-imx6qdl-kontron-samx6i-hook-up-ddc-i2c-bus.patch @@ -0,0 +1,50 @@ +From 9904c77f6503abef13f5a63d070acfa23fdeed9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Jul 2022 15:05:23 +0200 +Subject: ARM: dts: imx6qdl-kontron-samx6i: hook up DDC i2c bus + +From: Lucas Stach + +[ Upstream commit afd8f77957e3e83adf21d9229c61ff37f44a177a ] + +i2c2 is routed to the pins dedicated as DDC in the module standard. +Reduce clock rate to 100kHz to be in line with VESA standard and hook +this bus up to the HDMI node. + +Fixes: 708ed2649ad8 ("ARM: dts: imx6qdl-kontron-samx6i: increase i2c-frequency") +Signed-off-by: Lucas Stach +[m.felsch@pengutronix.de: add fixes line] +Signed-off-by: Marco Felsch +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi b/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi +index 6b791d515e29..683f6e58ab23 100644 +--- a/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi ++++ b/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi +@@ -263,6 +263,10 @@ + phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>; + }; + ++&hdmi { ++ ddc-i2c-bus = <&i2c2>; ++}; ++ + &i2c_intern { + pmic@8 { + compatible = "fsl,pfuze100"; +@@ -387,7 +391,7 @@ + + /* HDMI_CTRL */ + &i2c2 { +- clock-frequency = <375000>; ++ clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + }; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6qp-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6qp-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..e167dbcd9d6 --- /dev/null +++ b/queue-5.19/arm-dts-imx6qp-add-missing-properties-for-sram.patch @@ -0,0 +1,47 @@ +From 00684479e15fa1b04910bed783f0f5dbd438cc76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:33 +0200 +Subject: ARM: dts: imx6qp: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit 088fe5237435ee2f7ed4450519b2ef58b94c832f ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@940000: '#address-cells' is a required property +sram@940000: '#size-cells' is a required property +sram@940000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6qp.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi +index 050365513836..fc164991d2ae 100644 +--- a/arch/arm/boot/dts/imx6qp.dtsi ++++ b/arch/arm/boot/dts/imx6qp.dtsi +@@ -9,12 +9,18 @@ + ocram2: sram@940000 { + compatible = "mmio-sram"; + reg = <0x00940000 0x20000>; ++ ranges = <0 0x00940000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6QDL_CLK_OCRAM>; + }; + + ocram3: sram@960000 { + compatible = "mmio-sram"; + reg = <0x00960000 0x20000>; ++ ranges = <0 0x00960000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6QDL_CLK_OCRAM>; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6sl-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6sl-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..9e6238c0490 --- /dev/null +++ b/queue-5.19/arm-dts-imx6sl-add-missing-properties-for-sram.patch @@ -0,0 +1,38 @@ +From 4fd5438940dfad37aa9233eeb53614f333f8c453 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:34 +0200 +Subject: ARM: dts: imx6sl: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit 60c9213a1d9941a8b33db570796c3f9be8984974 ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@900000: '#address-cells' is a required property +sram@900000: '#size-cells' is a required property +sram@900000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sl.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi +index 06a515121dfc..cfd6b4972ae7 100644 +--- a/arch/arm/boot/dts/imx6sl.dtsi ++++ b/arch/arm/boot/dts/imx6sl.dtsi +@@ -115,6 +115,9 @@ + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x20000>; ++ ranges = <0 0x00900000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6SL_CLK_OCRAM>; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6sl-use-tabs-for-code-indent.patch b/queue-5.19/arm-dts-imx6sl-use-tabs-for-code-indent.patch new file mode 100644 index 00000000000..aaf64d06069 --- /dev/null +++ b/queue-5.19/arm-dts-imx6sl-use-tabs-for-code-indent.patch @@ -0,0 +1,97 @@ +From a78cb0699f7c78256fbeb36b975ac67d3c374ee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 21:22:48 +0200 +Subject: ARM: dts: imx6sl: use tabs for code indent + +From: Marcel Ziswiler + +[ Upstream commit 218db824a7519856d0eaaeb5c41ca504ed550210 ] + +This fixes the following error: + +arch/arm/boot/dts/imx6sl.dtsi:714: error: code indent should use tabs +where possible + +Signed-off-by: Marcel Ziswiler +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sl.dtsi | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi +index cfd6b4972ae7..01122ddfdc0d 100644 +--- a/arch/arm/boot/dts/imx6sl.dtsi ++++ b/arch/arm/boot/dts/imx6sl.dtsi +@@ -61,10 +61,10 @@ + <792000 1175000>, + <396000 975000>; + fsl,soc-operating-points = +- /* ARM kHz SOC-PU uV */ +- <996000 1225000>, +- <792000 1175000>, +- <396000 1175000>; ++ /* ARM kHz SOC-PU uV */ ++ <996000 1225000>, ++ <792000 1175000>, ++ <396000 1175000>; + clock-latency = <61036>; /* two CLK32 periods */ + #cooling-cells = <2>; + clocks = <&clks IMX6SL_CLK_ARM>, <&clks IMX6SL_CLK_PLL2_PFD2>, +@@ -225,7 +225,7 @@ + + uart5: serial@2018000 { + compatible = "fsl,imx6sl-uart", +- "fsl,imx6q-uart", "fsl,imx21-uart"; ++ "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02018000 0x4000>; + interrupts = <0 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SL_CLK_UART>, +@@ -238,7 +238,7 @@ + + uart1: serial@2020000 { + compatible = "fsl,imx6sl-uart", +- "fsl,imx6q-uart", "fsl,imx21-uart"; ++ "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02020000 0x4000>; + interrupts = <0 26 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SL_CLK_UART>, +@@ -251,7 +251,7 @@ + + uart2: serial@2024000 { + compatible = "fsl,imx6sl-uart", +- "fsl,imx6q-uart", "fsl,imx21-uart"; ++ "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02024000 0x4000>; + interrupts = <0 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SL_CLK_UART>, +@@ -312,7 +312,7 @@ + + uart3: serial@2034000 { + compatible = "fsl,imx6sl-uart", +- "fsl,imx6q-uart", "fsl,imx21-uart"; ++ "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02034000 0x4000>; + interrupts = <0 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SL_CLK_UART>, +@@ -325,7 +325,7 @@ + + uart4: serial@2038000 { + compatible = "fsl,imx6sl-uart", +- "fsl,imx6q-uart", "fsl,imx21-uart"; ++ "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x02038000 0x4000>; + interrupts = <0 29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clks IMX6SL_CLK_UART>, +@@ -714,7 +714,7 @@ + #power-domain-cells = <0>; + power-supply = <®_pu>; + clocks = <&clks IMX6SL_CLK_GPU2D_OVG>, +- <&clks IMX6SL_CLK_GPU2D_PODF>; ++ <&clks IMX6SL_CLK_GPU2D_PODF>; + }; + + pd_disp: power-domain@2 { +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6sll-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6sll-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..69d0969730f --- /dev/null +++ b/queue-5.19/arm-dts-imx6sll-add-missing-properties-for-sram.patch @@ -0,0 +1,38 @@ +From 2b7251d083819f3b1ef54c738ce48d6fa640066b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:35 +0200 +Subject: ARM: dts: imx6sll: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit 7492a83ed9b7a151e2dd11d64b06da7a7f0fa7f9 ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@900000: '#address-cells' is a required property +sram@900000: '#size-cells' is a required property +sram@900000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sll.dtsi | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6sll.dtsi b/arch/arm/boot/dts/imx6sll.dtsi +index d4a000c3dde7..2873369a57c0 100644 +--- a/arch/arm/boot/dts/imx6sll.dtsi ++++ b/arch/arm/boot/dts/imx6sll.dtsi +@@ -115,6 +115,9 @@ + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x20000>; ++ ranges = <0 0x00900000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + }; + + intc: interrupt-controller@a01000 { +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6sx-add-missing-properties-for-sram.patch b/queue-5.19/arm-dts-imx6sx-add-missing-properties-for-sram.patch new file mode 100644 index 00000000000..c07e90cadf1 --- /dev/null +++ b/queue-5.19/arm-dts-imx6sx-add-missing-properties-for-sram.patch @@ -0,0 +1,47 @@ +From 5ed1510d8f14604e758bd743ad46f437c6d7e626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 07:53:36 +0200 +Subject: ARM: dts: imx6sx: add missing properties for sram + +From: Alexander Stein + +[ Upstream commit 415432c008b2bce8138841356ba444631cabaa50 ] + +All 3 properties are required by sram.yaml. Fixes the dtbs_check warning: +sram@900000: '#address-cells' is a required property +sram@900000: '#size-cells' is a required property +sram@900000: 'ranges' is a required property + +Signed-off-by: Alexander Stein +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sx.dtsi | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi +index fc6334336b3d..719c61f7e914 100644 +--- a/arch/arm/boot/dts/imx6sx.dtsi ++++ b/arch/arm/boot/dts/imx6sx.dtsi +@@ -164,12 +164,18 @@ + ocram_s: sram@8f8000 { + compatible = "mmio-sram"; + reg = <0x008f8000 0x4000>; ++ ranges = <0 0x008f8000 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6SX_CLK_OCRAM_S>; + }; + + ocram: sram@900000 { + compatible = "mmio-sram"; + reg = <0x00900000 0x20000>; ++ ranges = <0 0x00900000 0x20000>; ++ #address-cells = <1>; ++ #size-cells = <1>; + clocks = <&clks IMX6SX_CLK_OCRAM>; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx6sx-udoo-neo-don-t-use-multiple-blank-lin.patch b/queue-5.19/arm-dts-imx6sx-udoo-neo-don-t-use-multiple-blank-lin.patch new file mode 100644 index 00000000000..0407572b7cc --- /dev/null +++ b/queue-5.19/arm-dts-imx6sx-udoo-neo-don-t-use-multiple-blank-lin.patch @@ -0,0 +1,77 @@ +From 052eb7daeb494ee55820497aca580d0c71c4f23b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 21:22:49 +0200 +Subject: ARM: dts: imx6sx-udoo-neo: don't use multiple blank lines + +From: Marcel Ziswiler + +[ Upstream commit fd2dd7077c7498765e7326c1b7f34bde85f1a975 ] + +This fixes the following warning: + +arch/arm/boot/dts/imx6sx-udoo-neo.dtsi:309: check: Please don't use multiple +blank lines + +While at it, use tabs indent for some pinctrl entries. + +Signed-off-by: Marcel Ziswiler +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx6sx-udoo-neo.dtsi | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi +index 35861bbea94e..c84ea1fac5e9 100644 +--- a/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi ++++ b/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi +@@ -226,7 +226,7 @@ + &iomuxc { + pinctrl_bt_reg: btreggrp { + fsl,pins = +- ; ++ ; + }; + + pinctrl_enet1: enet1grp { +@@ -306,7 +306,6 @@ + >; + }; + +- + pinctrl_uart1: uart1grp { + fsl,pins = + , +@@ -347,24 +346,23 @@ + + pinctrl_otg1_reg: otg1grp { + fsl,pins = +- ; ++ ; + }; + +- + pinctrl_otg2_reg: otg2grp { + fsl,pins = +- ; ++ ; + }; + + pinctrl_usb_otg1: usbotg1grp { + fsl,pins = +- , +- ; ++ , ++ ; + }; + + pinctrl_usb_otg2: usbot2ggrp { + fsl,pins = +- ; ++ ; + }; + + pinctrl_usdhc2: usdhc2grp { +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-imx7d-sdb-config-the-max-pressure-for-tsc204.patch b/queue-5.19/arm-dts-imx7d-sdb-config-the-max-pressure-for-tsc204.patch new file mode 100644 index 00000000000..7ba7c095352 --- /dev/null +++ b/queue-5.19/arm-dts-imx7d-sdb-config-the-max-pressure-for-tsc204.patch @@ -0,0 +1,60 @@ +From 535612b8a5dac69ca906f4a99326a246e4ac2ea4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 18:16:22 +0800 +Subject: ARM: dts: imx7d-sdb: config the max pressure for tsc2046 + +From: Haibo Chen + +[ Upstream commit e7c4ebe2f9cd68588eb24ba4ed122e696e2d5272 ] + +Use the general touchscreen method to config the max pressure for +touch tsc2046(data sheet suggest 8 bit pressure), otherwise, for +ABS_PRESSURE, when config the same max and min value, weston will +meet the following issue, + +[17:19:39.183] event1 - ADS7846 Touchscreen: is tagged by udev as: Touchscreen +[17:19:39.183] event1 - ADS7846 Touchscreen: kernel bug: device has min == max on ABS_PRESSURE +[17:19:39.183] event1 - ADS7846 Touchscreen: was rejected +[17:19:39.183] event1 - not using input device '/dev/input/event1' + +This will then cause the APP weston-touch-calibrator can't list touch devices. + +root@imx6ul7d:~# weston-touch-calibrator +could not load cursor 'dnd-move' +could not load cursor 'dnd-copy' +could not load cursor 'dnd-none' +No devices listed. + +And accroding to binding Doc, "ti,x-max", "ti,y-max", "ti,pressure-max" +belong to the deprecated properties, so remove them. Also for "ti,x-min", +"ti,y-min", "ti,x-plate-ohms", the value set in dts equal to the default +value in driver, so are redundant, also remove here. + +Signed-off-by: Haibo Chen +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/imx7d-sdb.dts | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts +index f053f5122741..0fe0a2f5e433 100644 +--- a/arch/arm/boot/dts/imx7d-sdb.dts ++++ b/arch/arm/boot/dts/imx7d-sdb.dts +@@ -206,12 +206,7 @@ + interrupt-parent = <&gpio2>; + interrupts = <29 0>; + pendown-gpio = <&gpio2 29 GPIO_ACTIVE_HIGH>; +- ti,x-min = /bits/ 16 <0>; +- ti,x-max = /bits/ 16 <0>; +- ti,y-min = /bits/ 16 <0>; +- ti,y-max = /bits/ 16 <0>; +- ti,pressure-max = /bits/ 16 <0>; +- ti,x-plate-ohms = /bits/ 16 <400>; ++ touchscreen-max-pressure = <255>; + wakeup-source; + }; + }; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-kirkwood-lsxl-fix-serial-line.patch b/queue-5.19/arm-dts-kirkwood-lsxl-fix-serial-line.patch new file mode 100644 index 00000000000..1b90549fd09 --- /dev/null +++ b/queue-5.19/arm-dts-kirkwood-lsxl-fix-serial-line.patch @@ -0,0 +1,50 @@ +From c7e12912228837a9fc7225c6255c4c8c7f5c47f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 02:10:24 +0200 +Subject: ARM: dts: kirkwood: lsxl: fix serial line + +From: Michael Walle + +[ Upstream commit 04eabc6ac10fda9424606d9a7ab6ab9a5d95350a ] + +Commit 327e15428977 ("ARM: dts: kirkwood: consolidate common pinctrl +settings") unknowingly broke the serial output on this board. Before +this commit, the pinmux was still configured by the bootloader and the +kernel didn't reconfigured it again. This was an oversight by the +initial board support where the pinmux for the serial line was never +configured by the kernel. But with this commit, the serial line will be +reconfigured to the wrong pins. This is especially confusing, because +the output still works, but the input doesn't. Presumingly, the input is +reconfigured to MPP10, but the output is connected to both MPP11 and +MPP5. + +Override the pinmux in the board device tree. + +Fixes: 327e15428977 ("ARM: dts: kirkwood: consolidate common pinctrl settings") +Signed-off-by: Michael Walle +Reviewed-by: Andrew Lunn +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/kirkwood-lsxl.dtsi | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi +index 7b151acb9984..321a40a98ed2 100644 +--- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi ++++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi +@@ -10,6 +10,11 @@ + + ocp@f1000000 { + pinctrl: pin-controller@10000 { ++ /* Non-default UART pins */ ++ pmx_uart0: pmx-uart0 { ++ marvell,pins = "mpp4", "mpp5"; ++ }; ++ + pmx_power_hdd: pmx-power-hdd { + marvell,pins = "mpp10"; + marvell,function = "gpo"; +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-kirkwood-lsxl-remove-first-ethernet-port.patch b/queue-5.19/arm-dts-kirkwood-lsxl-remove-first-ethernet-port.patch new file mode 100644 index 00000000000..0ea8975dd25 --- /dev/null +++ b/queue-5.19/arm-dts-kirkwood-lsxl-remove-first-ethernet-port.patch @@ -0,0 +1,53 @@ +From a9c9e01566ad3312a34508e8a345d44efac11ad7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 02:10:25 +0200 +Subject: ARM: dts: kirkwood: lsxl: remove first ethernet port + +From: Michael Walle + +[ Upstream commit 2d528eda7c96ce5c70f895854ecd5684bd5d80b9 ] + +Both the Linkstation LS-CHLv2 and the LS-XHL have only one ethernet +port. This has always been wrong, i.e. the board code used to set up +both ports, but the driver will play nice and return -ENODEV if the +assiciated PHY is not found. Nevertheless, it is wrong. Remove it. + +Fixes: 876e23333511 ("ARM: kirkwood: add gigabit ethernet and mvmdio device tree nodes") +Signed-off-by: Michael Walle +Reviewed-by: Andrew Lunn +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/kirkwood-lsxl.dtsi | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/arch/arm/boot/dts/kirkwood-lsxl.dtsi b/arch/arm/boot/dts/kirkwood-lsxl.dtsi +index 321a40a98ed2..88b70ba1c8fe 100644 +--- a/arch/arm/boot/dts/kirkwood-lsxl.dtsi ++++ b/arch/arm/boot/dts/kirkwood-lsxl.dtsi +@@ -218,22 +218,11 @@ + &mdio { + status = "okay"; + +- ethphy0: ethernet-phy@0 { +- reg = <0>; +- }; +- + ethphy1: ethernet-phy@8 { + reg = <8>; + }; + }; + +-ð0 { +- status = "okay"; +- ethernet0-port@0 { +- phy-handle = <ðphy0>; +- }; +-}; +- + ð1 { + status = "okay"; + ethernet1-port@0 { +-- +2.35.1 + diff --git a/queue-5.19/arm-dts-turris-omnia-fix-mpp26-pin-name-and-comment.patch b/queue-5.19/arm-dts-turris-omnia-fix-mpp26-pin-name-and-comment.patch new file mode 100644 index 00000000000..6449ddd68c7 --- /dev/null +++ b/queue-5.19/arm-dts-turris-omnia-fix-mpp26-pin-name-and-comment.patch @@ -0,0 +1,53 @@ +From 88dbdf1f6397adf58cff59aba187529f39516aff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 14:56:10 +0200 +Subject: ARM: dts: turris-omnia: Fix mpp26 pin name and comment +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit 49e93898f0dc177e645c22d0664813567fd9ec00 ] + +There is a bug in Turris Omnia's schematics, whereupon the MPP[26] pin, +which is routed to CN11 pin header, is documented as SPI CS1, but +MPP[26] pin does not support this function. Instead it controls chip +select 2 if in "spi0" mode. + +Fix the name of the pin node in pinctrl node and fix the comment in SPI +node. + +Fixes: 26ca8b52d6e1 ("ARM: dts: add support for Turris Omnia") +Signed-off-by: Marek Behún +Signed-off-by: Gregory CLEMENT +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/armada-385-turris-omnia.dts | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts +index f4878df39753..487dece2033c 100644 +--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts ++++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts +@@ -478,7 +478,7 @@ + marvell,function = "spi0"; + }; + +- spi0cs1_pins: spi0cs1-pins { ++ spi0cs2_pins: spi0cs2-pins { + marvell,pins = "mpp26"; + marvell,function = "spi0"; + }; +@@ -513,7 +513,7 @@ + }; + }; + +- /* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */ ++ /* MISO, MOSI, SCLK and CS2 are routed to pin header CN11 */ + }; + + &uart0 { +-- +2.35.1 + diff --git a/queue-5.19/arm-orion-fix-include-path.patch b/queue-5.19/arm-orion-fix-include-path.patch new file mode 100644 index 00000000000..947e3aa57c4 --- /dev/null +++ b/queue-5.19/arm-orion-fix-include-path.patch @@ -0,0 +1,39 @@ +From 57077e422c540c2a2a5a8affc069587951c1d16d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Sep 2022 21:55:50 +0200 +Subject: ARM: orion: fix include path + +From: Arnd Bergmann + +[ Upstream commit 63872304bdb3decd5454f4dd210c25395278ed13 ] + +Now that CONFIG_ARCH_MULTIPLATFORM can be disabled anywhere, +there is a build failure for plat-orion: + +arch/arm/plat-orion/irq.c:19:10: fatal error: plat/irq.h: No such file or directory + +Make the include path unconditional. + +Reported-by: kernel test robot +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/plat-orion/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm/plat-orion/Makefile b/arch/arm/plat-orion/Makefile +index 4e3f25de13c1..830b0be038c6 100644 +--- a/arch/arm/plat-orion/Makefile ++++ b/arch/arm/plat-orion/Makefile +@@ -2,7 +2,7 @@ + # + # Makefile for the linux kernel. + # +-ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include ++ccflags-y := -I$(srctree)/$(src)/include + + orion-gpio-$(CONFIG_GPIOLIB) += gpio.o + obj-$(CONFIG_PLAT_ORION_LEGACY) += irq.o pcie.o time.o common.o mpp.o +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-imx8mm-kontron-use-the-vselect-signal-to-s.patch b/queue-5.19/arm64-dts-imx8mm-kontron-use-the-vselect-signal-to-s.patch new file mode 100644 index 00000000000..9f27f6ee693 --- /dev/null +++ b/queue-5.19/arm64-dts-imx8mm-kontron-use-the-vselect-signal-to-s.patch @@ -0,0 +1,81 @@ +From a942056776085c2036c4f601abba18901d9a2773 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 10:03:50 +0200 +Subject: arm64: dts: imx8mm-kontron: Use the VSELECT signal to switch SD card + IO voltage + +From: Frieder Schrempf + +[ Upstream commit eef2c0217e02b6c7ed5b10b82ea944127145e113 ] + +It turns out that it is not necessary to declare the VSELECT signal as +GPIO and let the PMIC driver set it to a fixed high level. This switches +the voltage between 3.3V and 1.8V by setting the PMIC register for LDO5 +accordingly. + +Instead we can do it like other boards already do and simply mux the +VSELECT signal of the USDHC interface to the pin. This makes sure that +the correct voltage is selected by setting the PMIC's SD_VSEL input +to high or low accordingly. + +Reported-by: Heiko Thiery +Signed-off-by: Frieder Schrempf +Reviewed-by: Heiko Thiery +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts | 3 +++ + arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-som.dtsi | 2 -- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts +index 23be1ec538ba..c54536c0a2ba 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts ++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dts +@@ -321,6 +321,7 @@ + MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0 + MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0 + MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019 ++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0 + >; + }; + +@@ -333,6 +334,7 @@ + MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4 + MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4 + MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019 ++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0 + >; + }; + +@@ -345,6 +347,7 @@ + MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6 + MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6 + MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019 ++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0 + >; + }; + }; +diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-som.dtsi +index 8f90eb02550d..6307af803429 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-som.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-som.dtsi +@@ -86,7 +86,6 @@ + pinctrl-0 = <&pinctrl_pmic>; + interrupt-parent = <&gpio1>; + interrupts = <0 IRQ_TYPE_LEVEL_LOW>; +- sd-vsel-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + + regulators { + reg_vdd_soc: BUCK1 { +@@ -229,7 +228,6 @@ + pinctrl_pmic: pmicgrp { + fsl,pins = < + MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x141 +- MX8MM_IOMUXC_GPIO1_IO04_GPIO1_IO4 0x141 + >; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-imx8mp-add-snps-gfladj-refclk-lpm-sel-quir.patch b/queue-5.19/arm64-dts-imx8mp-add-snps-gfladj-refclk-lpm-sel-quir.patch new file mode 100644 index 00000000000..e0041331684 --- /dev/null +++ b/queue-5.19/arm64-dts-imx8mp-add-snps-gfladj-refclk-lpm-sel-quir.patch @@ -0,0 +1,48 @@ +From 17c3255fa59481156f4b63008b67eb4801da59ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 08:28:54 +0200 +Subject: arm64: dts: imx8mp: Add snps,gfladj-refclk-lpm-sel quirk to USB nodes + +From: Alexander Stein + +[ Upstream commit 5c3d5ecf48ab06c709c012bf1e8f0c91e1fcd7ad ] + +With this set the SOF/ITP counter is based on ref_clk when 2.0 ports are +suspended. +snps,dis-u2-freeclk-exists-quirk can be removed as +snps,gfladj-refclk-lpm-sel also clears the free running clock configuration +bit. + +Signed-off-by: Alexander Stein +Link: https://lore.kernel.org/r/20220915062855.751881-4-alexander.stein@ew.tq-group.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8mp.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +index 410d0d5e6f1e..7faf2d71ba4f 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +@@ -1168,7 +1168,7 @@ + interrupts = ; + phys = <&usb3_phy0>, <&usb3_phy0>; + phy-names = "usb2-phy", "usb3-phy"; +- snps,dis-u2-freeclk-exists-quirk; ++ snps,gfladj-refclk-lpm-sel-quirk; + }; + + }; +@@ -1210,7 +1210,7 @@ + interrupts = ; + phys = <&usb3_phy1>, <&usb3_phy1>; + phy-names = "usb2-phy", "usb3-phy"; +- snps,dis-u2-freeclk-exists-quirk; ++ snps,gfladj-refclk-lpm-sel-quirk; + }; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-imx8mq-librem5-add-bq25895-as-max17055-s-p.patch b/queue-5.19/arm64-dts-imx8mq-librem5-add-bq25895-as-max17055-s-p.patch new file mode 100644 index 00000000000..ea36cd93b78 --- /dev/null +++ b/queue-5.19/arm64-dts-imx8mq-librem5-add-bq25895-as-max17055-s-p.patch @@ -0,0 +1,36 @@ +From 0213ef467e021b0ecfab57e593dd104d5467d62d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 10:42:13 +0200 +Subject: arm64: dts: imx8mq-librem5: Add bq25895 as max17055's power supply + +From: Sebastian Krzyszkowiak + +[ Upstream commit 6effe295e1a87408033c29dbcea9d5a5c8b937d5 ] + +This allows the userspace to notice that there's not enough +current provided to charge the battery, and also fixes issues +with 0% SOC values being considered invalid. + +Signed-off-by: Sebastian Krzyszkowiak +Signed-off-by: Martin Kepplinger +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi +index 587e55aaa57b..11f56138c533 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi +@@ -1077,6 +1077,7 @@ + interrupts = <20 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gauge>; ++ power-supplies = <&bq25895>; + maxim,over-heat-temp = <700>; + maxim,over-volt = <4500>; + maxim,rsns-microohm = <5000>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-imx8ulp-no-executable-source-file-permissi.patch b/queue-5.19/arm64-dts-imx8ulp-no-executable-source-file-permissi.patch new file mode 100644 index 00000000000..de97338e6c1 --- /dev/null +++ b/queue-5.19/arm64-dts-imx8ulp-no-executable-source-file-permissi.patch @@ -0,0 +1,29 @@ +From fcac01675620d30b9917b3a2cc1751106f69af76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 21:22:50 +0200 +Subject: arm64: dts: imx8ulp: no executable source file permission + +From: Marcel Ziswiler + +[ Upstream commit 7db9905d48e1b9a97a28224c5a201262ebce7489 ] + +This fixes the following error: + +arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h: error: do not set + execute permissions for source files + +Signed-off-by: Marcel Ziswiler +Acked-by: Peng Fan +Signed-off-by: Shawn Guo +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + mode change 100755 => 100644 arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h + +diff --git a/arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8ulp-pinfunc.h +old mode 100755 +new mode 100644 +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-ipq8074-fix-pcie-phy-serdes-size.patch b/queue-5.19/arm64-dts-qcom-ipq8074-fix-pcie-phy-serdes-size.patch new file mode 100644 index 00000000000..7295b5ad4be --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-ipq8074-fix-pcie-phy-serdes-size.patch @@ -0,0 +1,47 @@ +From df410b8212489bdbf4fe65ba0d49d436b5873644 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 16:34:30 +0200 +Subject: arm64: dts: qcom: ipq8074: fix PCIe PHY serdes size + +From: Johan Hovold + +[ Upstream commit ed22cc93abae68f9d3fc4957c20a1d902cf28882 ] + +The size of the PCIe PHY serdes register region is 0x1c4 and the +corresponding 'reg' property should specifically not include the +adjacent regions that are defined in the child node (e.g. tx and rx). + +Fixes: 33057e1672fe ("ARM: dts: ipq8074: Add pcie nodes") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220915143431.19842-1-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +index 697f46e17903..0088323827d0 100644 +--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi ++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi +@@ -195,7 +195,7 @@ + + pcie_qmp0: phy@86000 { + compatible = "qcom,ipq8074-qmp-pcie-phy"; +- reg = <0x00086000 0x1000>; ++ reg = <0x00086000 0x1c4>; + #address-cells = <1>; + #size-cells = <1>; + ranges; +@@ -223,7 +223,7 @@ + + pcie_qmp1: phy@8e000 { + compatible = "qcom,ipq8074-qmp-pcie-phy"; +- reg = <0x0008e000 0x1000>; ++ reg = <0x0008e000 0x1c4>; + #address-cells = <1>; + #size-cells = <1>; + ranges; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-pm8350c-drop-pwm-reg-declaration.patch b/queue-5.19/arm64-dts-qcom-pm8350c-drop-pwm-reg-declaration.patch new file mode 100644 index 00000000000..47af621ae5a --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-pm8350c-drop-pwm-reg-declaration.patch @@ -0,0 +1,41 @@ +From 1b03e77f482c3ddd0a8a5e2904b6b81ea121f6a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Aug 2022 14:26:48 +0100 +Subject: arm64: dts: qcom: pm8350c: Drop PWM reg declaration + +From: Bryan O'Donoghue + +[ Upstream commit eeca7d46217ccfe9289530e959c0fb29190af0d6 ] + +The PWM is a part of the SPMI PMIC block and maps several different +addresses within the SPMI block. It is not accurate to describe as pwm@reg +as a result. + +Fixes: 5be66d2dc887 ("arm64: dts: qcom: pm8350c: Add pwm support") +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Bryan O'Donoghue +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220828132648.3624126-3-bryan.odonoghue@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/pm8350c.dtsi | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/pm8350c.dtsi b/arch/arm64/boot/dts/qcom/pm8350c.dtsi +index e0bbb67717fe..f28e71487d5c 100644 +--- a/arch/arm64/boot/dts/qcom/pm8350c.dtsi ++++ b/arch/arm64/boot/dts/qcom/pm8350c.dtsi +@@ -30,9 +30,8 @@ + #interrupt-cells = <2>; + }; + +- pm8350c_pwm: pwm@e800 { ++ pm8350c_pwm: pwm { + compatible = "qcom,pm8350c-pwm"; +- reg = <0xe800>; + #pwm-cells = <2>; + status = "disabled"; + }; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc7180-trogdor-keep-pm6150_adc-enable.patch b/queue-5.19/arm64-dts-qcom-sc7180-trogdor-keep-pm6150_adc-enable.patch new file mode 100644 index 00000000000..a448aaca52a --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc7180-trogdor-keep-pm6150_adc-enable.patch @@ -0,0 +1,58 @@ +From ae5012f97a96ce56a81f41088a2b157bd6d214e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 17:49:00 -0700 +Subject: arm64: dts: qcom: sc7180-trogdor: Keep pm6150_adc enabled for TZ + +From: Stephen Boyd + +[ Upstream commit 144fbd028fdec2deeb3b99d5e60dbf3167950ebe ] + +There's still a thermal zone using pm6150_adc in the pm6150.dtsi file, +pm6150_thermal. It's not super obvious because it indirectly uses the +adc through an iio channel in pm6150_temp. Let's keep this enabled on +lazor and coachz so that reading the temperature of the pm6150_thermal +zone continues to work. Otherwise we get -EINVAL when reading the zone, +and I suspect the PMIC temperature trip doesn't work properly so we +don't shutdown when the PMIC overheats. + +Cc: Matthias Kaehlcke +Fixes: b8d1e3d33487 ("arm64: dts: qcom: sc7180-trogdor: Delete ADC config for unused thermistors") +Signed-off-by: Stephen Boyd +Reviewed-by: Matthias Kaehlcke +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220827004901.511543-1-swboyd@chromium.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz-r1.dts | 2 -- + arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi | 2 -- + 2 files changed, 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz-r1.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz-r1.dts +index 8290d036044a..edfcd47e1a00 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz-r1.dts ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz-r1.dts +@@ -24,8 +24,6 @@ + }; + + &pm6150_adc { +- status = "disabled"; +- + /delete-node/ skin-temp-thermistor@4e; + /delete-node/ charger-thermistor@4f; + }; +diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi +index 88f6a7d4d020..711f9361aa3e 100644 +--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi +@@ -54,8 +54,6 @@ ap_ts_pen_1v8: &i2c4 { + }; + + &pm6150_adc { +- status = "disabled"; +- + /delete-node/ charger-thermistor@4f; + }; + +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc7280-cleanup-the-lpasscc-node.patch b/queue-5.19/arm64-dts-qcom-sc7280-cleanup-the-lpasscc-node.patch new file mode 100644 index 00000000000..ddbacd54458 --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc7280-cleanup-the-lpasscc-node.patch @@ -0,0 +1,42 @@ +From 74d22b8eea56e796eaea8b0f606afde3b01d1b77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Aug 2022 10:35:07 +0530 +Subject: arm64: dts: qcom: sc7280: Cleanup the lpasscc node + +From: Satya Priya + +[ Upstream commit 8c7ebabd2e3f33ef24378d3cac00d3e59886cecb ] + +Remove "cc" regmap from lpasscc node which is overlapping +with the lpass_aon regmap. + +Fixes: 422a295221bb ("arm64: dts: qcom: sc7280: Add clock controller nodes") +Signed-off-by: Satya Priya +Signed-off-by: Taniya Das +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/1660107909-27947-2-git-send-email-quic_c_skakit@quicinc.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc7280.dtsi | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi +index 75e174316d00..0a4c58f95439 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi +@@ -2168,9 +2168,8 @@ + lpasscc: lpasscc@3000000 { + compatible = "qcom,sc7280-lpasscc"; + reg = <0 0x03000000 0 0x40>, +- <0 0x03c04000 0 0x4>, +- <0 0x03389000 0 0x24>; +- reg-names = "qdsp6ss", "top_cc", "cc"; ++ <0 0x03c04000 0 0x4>; ++ reg-names = "qdsp6ss", "top_cc"; + clocks = <&gcc GCC_CFG_NOC_LPASS_CLK>; + clock-names = "iface"; + #clock-cells = <1>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc7280-idp-correct-adc-channel-node-n.patch b/queue-5.19/arm64-dts-qcom-sc7280-idp-correct-adc-channel-node-n.patch new file mode 100644 index 00000000000..bdaec385444 --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc7280-idp-correct-adc-channel-node-n.patch @@ -0,0 +1,59 @@ +From 510c9438396e03d760d49f33c330a892dfdd1602 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 28 Aug 2022 11:43:38 +0300 +Subject: arm64: dts: qcom: sc7280-idp: correct ADC channel node name and unit + address + +From: Krzysztof Kozlowski + +[ Upstream commit 5589ffb2da2a66988ab3a68334dad3e68b42e3a9 ] + +Correct SPMI PMIC VADC channel node name: +1. Use hyphens instead of underscores, +2. Add missing unit address. + +This fixes `make dtbs_check` warnings like: + + qcom/sc7280-idp.dtb: pmic@0: adc@3100: 'pmk8350_die_temp', 'pmr735a_die_temp' do not match any of the regexes: '^.*@[0-9a-f]+$', 'pinctrl-[0-9]+' + +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Stephen Boyd +Reviewed-by: Vinod Koul +Reviewed-by: David Heidelberg +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220828084341.112146-12-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc7280-idp.dts | 2 +- + arch/arm64/boot/dts/qcom/sc7280-idp.dtsi | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dts b/arch/arm64/boot/dts/qcom/sc7280-idp.dts +index 6d3ff80582ae..e2e37a0292ad 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dts ++++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dts +@@ -78,7 +78,7 @@ + }; + + &pmk8350_vadc { +- pmr735a_die_temp { ++ pmr735a-die-temp@403 { + reg = ; + label = "pmr735a_die_temp"; + qcom,pre-scaling = <1 1>; +diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi +index 5eb668991e24..893d3031cfd5 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi +@@ -264,7 +264,7 @@ + }; + + &pmk8350_vadc { +- pmk8350_die_temp { ++ pmk8350-die-temp@3 { + reg = ; + label = "pmk8350_die_temp"; + qcom,pre-scaling = <1 1>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc7280-update-lpasscore-node.patch b/queue-5.19/arm64-dts-qcom-sc7280-update-lpasscore-node.patch new file mode 100644 index 00000000000..092086ba12c --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc7280-update-lpasscore-node.patch @@ -0,0 +1,46 @@ +From a0085ecb6253fe696f8c2c179038bcb3c2eb585f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Aug 2022 10:35:09 +0530 +Subject: arm64: dts: qcom: sc7280: Update lpasscore node + +From: Satya Priya + +[ Upstream commit d9a1e922730389afc425f2250de361b7f07acdbc ] + +To maintain consistency with other lpass nodes(lpass_audiocc, +lpass_aon and lpass_hm), update lpasscore to lpass_core. + +Fixes: 9499240d15f2 ("arm64: dts: qcom: sc7280: Add lpasscore & lpassaudio clock controllers") +Signed-off-by: Taniya Das +Signed-off-by: Satya Priya +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/1660107909-27947-4-git-send-email-quic_c_skakit@quicinc.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc7280.dtsi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi +index 0a4c58f95439..694cdf88af38 100644 +--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi +@@ -2191,13 +2191,13 @@ + reg = <0 0x03380000 0 0x30000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&rpmhcc RPMH_CXO_CLK_A>, +- <&lpasscore LPASS_CORE_CC_CORE_CLK>; ++ <&lpass_core LPASS_CORE_CC_CORE_CLK>; + clock-names = "bi_tcxo", "bi_tcxo_ao", "iface"; + #clock-cells = <1>; + #power-domain-cells = <1>; + }; + +- lpasscore: clock-controller@3900000 { ++ lpass_core: clock-controller@3900000 { + compatible = "qcom,sc7280-lpasscorecc"; + reg = <0 0x03900000 0 0x50000>; + clocks = <&rpmhcc RPMH_CXO_CLK>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc8280xp-add-reference-device.patch b/queue-5.19/arm64-dts-qcom-sc8280xp-add-reference-device.patch new file mode 100644 index 00000000000..1123e94d7a9 --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc8280xp-add-reference-device.patch @@ -0,0 +1,594 @@ +From 3608b8cb4e2cd0139be22ba591672c90a1def2b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 21:14:37 -0700 +Subject: arm64: dts: qcom: sc8280xp: Add reference device + +From: Bjorn Andersson + +[ Upstream commit ccd3517faf18330c051068f07dd8ef79853238c7 ] + +Add basic support for the SC8280XP reference device, which allows it to +boot to a shell (using EFIFB) with functional storage (UFS), USB, +keyboard, touchpad, touchscreen, backlight and remoteprocs. + +The PMICs are, per socinfo, reused from other platforms. But given that +the address of the PMICs doesn't match other cases and that it's +desirable to label things according to the schematics a new dtsi file is +created to represent the reference combination of PMICs. + +Signed-off-by: Bjorn Andersson +Reviewed-by: Johan Hovold +Link: https://lore.kernel.org/r/20220629041438.1352536-5-bjorn.andersson@linaro.org +Stable-dep-of: 7dac7991408f ("arm64: dts: qcom: sc8280xp-pmics: Remove reg entry & use correct node name for pmc8280c_lpg node") +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/Makefile | 1 + + arch/arm64/boot/dts/qcom/sc8280xp-crd.dts | 427 +++++++++++++++++++ + arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi | 109 +++++ + 3 files changed, 537 insertions(+) + create mode 100644 arch/arm64/boot/dts/qcom/sc8280xp-crd.dts + create mode 100644 arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi + +diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile +index 12bb2f8bdac2..c0569280821c 100644 +--- a/arch/arm64/boot/dts/qcom/Makefile ++++ b/arch/arm64/boot/dts/qcom/Makefile +@@ -89,6 +89,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-villager-r0.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp2.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-crd-r3.dtb ++dtb-$(CONFIG_ARCH_QCOM) += sc8280xp-crd.dtb + dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb + dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-ganges-kirin.dtb + dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-discovery.dtb +diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts +new file mode 100644 +index 000000000000..45058ad0a1c8 +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts +@@ -0,0 +1,427 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2021, The Linux Foundation. All rights reserved. ++ * Copyright (c) 2022, Linaro Limited ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++ ++#include "sc8280xp.dtsi" ++#include "sc8280xp-pmics.dtsi" ++ ++/ { ++ model = "Qualcomm SC8280XP CRD"; ++ compatible = "qcom,sc8280xp-crd", "qcom,sc8280xp"; ++ ++ aliases { ++ serial0 = &qup2_uart17; ++ }; ++ ++ backlight { ++ compatible = "pwm-backlight"; ++ pwms = <&pmc8280c_lpg 3 1000000>; ++ enable-gpios = <&pmc8280_1_gpios 8 GPIO_ACTIVE_HIGH>; ++ power-supply = <&vreg_edp_bl>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&edp_bl_en>, <&edp_bl_pwm>; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ vreg_edp_bl: regulator-edp-bl { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "VREG_EDP_BL"; ++ regulator-min-microvolt = <3600000>; ++ regulator-max-microvolt = <3600000>; ++ ++ gpio = <&pmc8280_1_gpios 9 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&edp_bl_reg_en>; ++ ++ regulator-boot-on; ++ }; ++ ++ vreg_misc_3p3: regulator-misc-3p3 { ++ compatible = "regulator-fixed"; ++ ++ regulator-name = "VREG_MISC_3P3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ gpio = <&pmc8280_1_gpios 1 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&misc_3p3_reg_en>; ++ ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++}; ++ ++&apps_rsc { ++ pmc8280-1-rpmh-regulators { ++ compatible = "qcom,pm8350-rpmh-regulators"; ++ qcom,pmic-id = "b"; ++ ++ vdd-l3-l5-supply = <&vreg_s11b>; ++ ++ vreg_s11b: smps11 { ++ regulator-name = "vreg_s11b"; ++ regulator-min-microvolt = <1272000>; ++ regulator-max-microvolt = <1272000>; ++ regulator-initial-mode = ; ++ }; ++ ++ vreg_l3b: ldo3 { ++ regulator-name = "vreg_l3b"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ vreg_l4b: ldo4 { ++ regulator-name = "vreg_l4b"; ++ regulator-min-microvolt = <912000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l6b: ldo6 { ++ regulator-name = "vreg_l6b"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <880000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ regulator-boot-on; ++ }; ++ }; ++ ++ pmc8280c-rpmh-regulators { ++ compatible = "qcom,pm8350c-rpmh-regulators"; ++ qcom,pmic-id = "c"; ++ ++ vreg_l1c: ldo1 { ++ regulator-name = "vreg_l1c"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l7c: ldo7 { ++ regulator-name = "vreg_l7c"; ++ regulator-min-microvolt = <2504000>; ++ regulator-max-microvolt = <2504000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l13c: ldo13 { ++ regulator-name = "vreg_l13c"; ++ regulator-min-microvolt = <3072000>; ++ regulator-max-microvolt = <3072000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ }; ++ ++ pmc8280-2-rpmh-regulators { ++ compatible = "qcom,pm8350-rpmh-regulators"; ++ qcom,pmic-id = "d"; ++ ++ vdd-l1-l4-supply = <&vreg_s11b>; ++ ++ vreg_l3d: ldo3 { ++ regulator-name = "vreg_l3d"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l4d: ldo4 { ++ regulator-name = "vreg_l4d"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l6d: ldo6 { ++ regulator-name = "vreg_l6d"; ++ regulator-min-microvolt = <880000>; ++ regulator-max-microvolt = <880000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l7d: ldo7 { ++ regulator-name = "vreg_l7d"; ++ regulator-min-microvolt = <3072000>; ++ regulator-max-microvolt = <3072000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l9d: ldo9 { ++ regulator-name = "vreg_l9d"; ++ regulator-min-microvolt = <912000>; ++ regulator-max-microvolt = <912000>; ++ regulator-initial-mode = ; ++ regulator-allow-set-load; ++ }; ++ }; ++}; ++ ++&pmc8280c_lpg { ++ status = "okay"; ++}; ++ ++&pmk8280_pon_pwrkey { ++ status = "okay"; ++}; ++ ++&qup0 { ++ status = "okay"; ++}; ++ ++&qup0_i2c4 { ++ clock-frequency = <400000>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qup0_i2c4_default>, <&ts0_default>; ++ ++ status = "okay"; ++ ++ touchscreen@10 { ++ compatible = "hid-over-i2c"; ++ reg = <0x10>; ++ hid-descr-addr = <0x1>; ++ interrupts-extended = <&tlmm 175 IRQ_TYPE_LEVEL_LOW>; ++ vdd-supply = <&vreg_misc_3p3>; ++ }; ++}; ++ ++&qup1 { ++ status = "okay"; ++}; ++ ++&qup2 { ++ status = "okay"; ++}; ++ ++&qup2_i2c5 { ++ clock-frequency = <400000>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&qup2_i2c5_default>, <&kybd_default>, <&tpad_default>; ++ ++ status = "okay"; ++ ++ touchpad@15 { ++ compatible = "hid-over-i2c"; ++ reg = <0x15>; ++ hid-descr-addr = <0x1>; ++ interrupts-extended = <&tlmm 182 IRQ_TYPE_LEVEL_LOW>; ++ vdd-supply = <&vreg_misc_3p3>; ++ }; ++ ++ keyboard@68 { ++ compatible = "hid-over-i2c"; ++ reg = <0x68>; ++ hid-descr-addr = <0x1>; ++ interrupts-extended = <&tlmm 104 IRQ_TYPE_LEVEL_LOW>; ++ vdd-supply = <&vreg_misc_3p3>; ++ }; ++}; ++ ++&qup2_uart17 { ++ compatible = "qcom,geni-debug-uart"; ++ ++ status = "okay"; ++}; ++ ++&remoteproc_adsp { ++ firmware-name = "qcom/sc8280xp/qcadsp8280.mbn"; ++ ++ status = "okay"; ++}; ++ ++&remoteproc_nsp0 { ++ firmware-name = "qcom/sc8280xp/qccdsp8280.mbn"; ++ ++ status = "okay"; ++}; ++ ++&ufs_mem_hc { ++ reset-gpios = <&tlmm 228 GPIO_ACTIVE_LOW>; ++ ++ vcc-supply = <&vreg_l7c>; ++ vcc-max-microamp = <800000>; ++ vccq-supply = <&vreg_l3d>; ++ vccq-max-microamp = <900000>; ++ ++ status = "okay"; ++}; ++ ++&ufs_mem_phy { ++ vdda-phy-supply = <&vreg_l6b>; ++ vdda-pll-supply = <&vreg_l3b>; ++ ++ status = "okay"; ++}; ++ ++&usb_0 { ++ status = "okay"; ++}; ++ ++&usb_0_dwc3 { ++ /* TODO: Define USB-C connector properly */ ++ dr_mode = "host"; ++}; ++ ++&usb_0_hsphy { ++ vdda-pll-supply = <&vreg_l9d>; ++ vdda18-supply = <&vreg_l1c>; ++ vdda33-supply = <&vreg_l7d>; ++ ++ status = "okay"; ++}; ++ ++&usb_0_qmpphy { ++ vdda-phy-supply = <&vreg_l9d>; ++ vdda-pll-supply = <&vreg_l4d>; ++ ++ status = "okay"; ++}; ++ ++&usb_1 { ++ status = "okay"; ++}; ++ ++&usb_1_dwc3 { ++ /* TODO: Define USB-C connector properly */ ++ dr_mode = "host"; ++}; ++ ++&usb_1_hsphy { ++ vdda-pll-supply = <&vreg_l4b>; ++ vdda18-supply = <&vreg_l1c>; ++ vdda33-supply = <&vreg_l13c>; ++ ++ status = "okay"; ++}; ++ ++&usb_1_qmpphy { ++ vdda-phy-supply = <&vreg_l4b>; ++ vdda-pll-supply = <&vreg_l3b>; ++ ++ status = "okay"; ++}; ++ ++&xo_board_clk { ++ clock-frequency = <38400000>; ++}; ++ ++/* PINCTRL - additions to nodes defined in sc8280xp.dtsi */ ++ ++&pmc8280_1_gpios { ++ edp_bl_en: edp-bl-en-state { ++ pins = "gpio8"; ++ function = "normal"; ++ }; ++ ++ edp_bl_reg_en: edp-bl-reg-en-state { ++ pins = "gpio9"; ++ function = "normal"; ++ }; ++ ++ misc_3p3_reg_en: misc-3p3-reg-en-state { ++ pins = "gpio1"; ++ function = "normal"; ++ }; ++}; ++ ++&pmc8280c_gpios { ++ edp_bl_pwm: edp-bl-pwm-state { ++ pins = "gpio8"; ++ function = "func1"; ++ }; ++}; ++ ++&tlmm { ++ gpio-reserved-ranges = <74 6>, <83 4>, <125 2>, <128 2>, <154 7>; ++ ++ kybd_default: kybd-default-state { ++ disable { ++ pins = "gpio102"; ++ function = "gpio"; ++ output-low; ++ }; ++ ++ int-n { ++ pins = "gpio104"; ++ function = "gpio"; ++ bias-disable; ++ }; ++ ++ reset { ++ pins = "gpio105"; ++ function = "gpio"; ++ bias-disable; ++ }; ++ }; ++ ++ qup0_i2c4_default: qup0-i2c4-default-state { ++ pins = "gpio171", "gpio172"; ++ function = "qup4"; ++ ++ bias-disable; ++ drive-strength = <16>; ++ }; ++ ++ qup2_i2c5_default: qup2-i2c5-default-state { ++ pins = "gpio81", "gpio82"; ++ function = "qup21"; ++ ++ bias-disable; ++ drive-strength = <16>; ++ }; ++ ++ tpad_default: tpad-default-state { ++ int-n { ++ pins = "gpio182"; ++ function = "gpio"; ++ bias-disable; ++ }; ++ }; ++ ++ ts0_default: ts0-default-state { ++ int-n { ++ pins = "gpio175"; ++ function = "gpio"; ++ bias-pull-up; ++ }; ++ ++ reset-n { ++ pins = "gpio99"; ++ function = "gpio"; ++ output-high; ++ drive-strength = <16>; ++ }; ++ }; ++}; +diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi +new file mode 100644 +index 000000000000..ae90b97aecb8 +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi +@@ -0,0 +1,109 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2022, Linaro Limited ++ */ ++ ++#include ++#include ++#include ++ ++&spmi_bus { ++ pmk8280: pmic@0 { ++ compatible = "qcom,pmk8350", "qcom,spmi-pmic"; ++ reg = <0x0 SPMI_USID>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmk8280_pon: pon@1300 { ++ compatible = "qcom,pm8998-pon"; ++ reg = <0x1300>; ++ ++ pmk8280_pon_pwrkey: pwrkey { ++ compatible = "qcom,pmk8350-pwrkey"; ++ interrupts = <0x0 0x13 0x7 IRQ_TYPE_EDGE_BOTH>; ++ linux,code = ; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ pmc8280_1: pmic@1 { ++ compatible = "qcom,pm8350", "qcom,spmi-pmic"; ++ reg = <0x1 SPMI_USID>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmc8280_1_gpios: gpio@8800 { ++ compatible = "qcom,pm8350-gpio", "qcom,spmi-gpio"; ++ reg = <0x8800>; ++ gpio-controller; ++ gpio-ranges = <&pmc8280_1_gpios 0 0 10>; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; ++ ++ pmc8280c: pmic@2 { ++ compatible = "qcom,pm8350c", "qcom,spmi-pmic"; ++ reg = <0x2 SPMI_USID>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmc8280c_gpios: gpio@8800 { ++ compatible = "qcom,pm8350c-gpio", "qcom,spmi-gpio"; ++ reg = <0x8800>; ++ gpio-controller; ++ gpio-ranges = <&pmc8280c_gpios 0 0 9>; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ ++ pmc8280c_lpg: lpg@e800 { ++ compatible = "qcom,pm8350c-pwm"; ++ reg = <0xe800>; ++ ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ #pwm-cells = <2>; ++ ++ status = "disabled"; ++ }; ++ }; ++ ++ pmc8280_2: pmic@3 { ++ compatible = "qcom,pm8350", "qcom,spmi-pmic"; ++ reg = <0x3 SPMI_USID>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmc8280_2_gpios: gpio@8800 { ++ compatible = "qcom,pm8350-gpio", "qcom,spmi-gpio"; ++ reg = <0x8800>; ++ gpio-controller; ++ gpio-ranges = <&pmc8280_2_gpios 0 0 10>; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; ++ ++ pmr735a: pmic@4 { ++ compatible = "qcom,pmr735a", "qcom,spmi-pmic"; ++ reg = <0x4 SPMI_USID>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmr735a_gpios: gpio@8800 { ++ compatible = "qcom,pmr735a-gpio", "qcom,spmi-gpio"; ++ reg = <0x8800>; ++ gpio-controller; ++ gpio-ranges = <&pmr735a_gpios 0 0 4>; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ }; ++ }; ++}; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sc8280xp-pmics-remove-reg-entry-use-c.patch b/queue-5.19/arm64-dts-qcom-sc8280xp-pmics-remove-reg-entry-use-c.patch new file mode 100644 index 00000000000..1f649a8d8b0 --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sc8280xp-pmics-remove-reg-entry-use-c.patch @@ -0,0 +1,55 @@ +From a11c3720b4aa9ec0ce13ab7eb689ab5e38b84d8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:32:40 +0530 +Subject: arm64: dts: qcom: sc8280xp-pmics: Remove reg entry & use correct node + name for pmc8280c_lpg node + +From: Bhupesh Sharma + +[ Upstream commit 7dac7991408f77b0b33ee5e6b729baa683889277 ] + +Commit eeca7d46217c ("arm64: dts: qcom: pm8350c: Drop PWM reg declaration") +dropped PWM reg declaration for pm8350c pwm(s), but there is a leftover +'reg' entry inside the lpg/pwm node in sc8280xp dts file. Remove the same. + +While at it, also remove the unused unit address in the node +label. + +Also, since dt-bindings expect LPG/PWM node name to be "pwm", +use correct node name as well, to fix the following +error reported by 'make dtbs_check': + + 'lpg' does not match any of the regexes + +Fixes: eeca7d46217c ("arm64: dts: qcom: pm8350c: Drop PWM reg declaration") +Cc: Krzysztof Kozlowski +Cc: Bryan O'Donoghue +Cc: Bjorn Andersson +Signed-off-by: Bhupesh Sharma +Reviewed-by: Bryan O'Donoghue +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220905070240.1634997-1-bhupesh.sharma@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi +index ae90b97aecb8..24836b6b9bbc 100644 +--- a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi ++++ b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi +@@ -60,9 +60,8 @@ + #interrupt-cells = <2>; + }; + +- pmc8280c_lpg: lpg@e800 { ++ pmc8280c_lpg: pwm { + compatible = "qcom,pm8350c-pwm"; +- reg = <0xe800>; + + #address-cells = <1>; + #size-cells = <0>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sdm660-add-initial-inforce-ifc6560-bo.patch b/queue-5.19/arm64-dts-qcom-sdm660-add-initial-inforce-ifc6560-bo.patch new file mode 100644 index 00000000000..780ce19018a --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sdm660-add-initial-inforce-ifc6560-bo.patch @@ -0,0 +1,511 @@ +From de9e83143066ba84b91fcfb99f5d9dbf45daa627 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 21 May 2022 23:27:08 +0300 +Subject: arm64: dts: qcom: sdm660: Add initial Inforce IFC6560 board support + +From: Dmitry Baryshkov + +[ Upstream commit 34279d6e3f32c7b2dd1192d8ba3e1d28b6ac775e ] + +The IFC6560 is a board from Inforce Computing, built around the SDA660 +SoC. This patch describes core clocks, some regulators from the two +PMICs, debug uart, storage, bluetooth and audio DSP remoteproc. + +The regulator settings are inherited from prior work by Konrad Dybcio +and AngeloGioacchino Del Regno. + +Reviewed-by: Marijn Suijten +Signed-off-by: Dmitry Baryshkov +Co-developed-by: Bjorn Andersson +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220521202708.1509308-12-dmitry.baryshkov@linaro.org +Stable-dep-of: 7dac7991408f ("arm64: dts: qcom: sc8280xp-pmics: Remove reg entry & use correct node name for pmc8280c_lpg node") +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/Makefile | 1 + + .../boot/dts/qcom/sda660-inforce-ifc6560.dts | 461 ++++++++++++++++++ + 2 files changed, 462 insertions(+) + create mode 100644 arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts + +diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile +index 2f8aec2cc6db..12bb2f8bdac2 100644 +--- a/arch/arm64/boot/dts/qcom/Makefile ++++ b/arch/arm64/boot/dts/qcom/Makefile +@@ -89,6 +89,7 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-villager-r0.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp2.dtb + dtb-$(CONFIG_ARCH_QCOM) += sc7280-crd-r3.dtb ++dtb-$(CONFIG_ARCH_QCOM) += sda660-inforce-ifc6560.dtb + dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-ganges-kirin.dtb + dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-discovery.dtb + dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-pioneer.dtb +diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts +new file mode 100644 +index 000000000000..28050bc5f081 +--- /dev/null ++++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts +@@ -0,0 +1,461 @@ ++// SPDX-License-Identifier: BSD-3-Clause ++/* ++ * Copyright (c) 2021, Linaro Ltd. ++ * Copyright (c) 2020, Konrad Dybcio ++ * Copyright (c) 2020, AngeloGioacchino Del Regno ++ * ++ */ ++ ++/dts-v1/; ++ ++#include "sdm660.dtsi" ++#include "pm660.dtsi" ++#include "pm660l.dtsi" ++ ++/ { ++ model = "Inforce 6560 Single Board Computer"; ++ compatible = "inforce,ifc6560", "qcom,sda660"; ++ chassis-type = "embedded"; /* SBC */ ++ ++ aliases { ++ serial0 = &blsp1_uart2; ++ serial1 = &blsp2_uart1; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ gpio-keys { ++ compatible = "gpio-keys"; ++ ++ volup { ++ label = "Volume Up"; ++ gpios = <&pm660l_gpios 7 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <15>; ++ }; ++ }; ++ ++ /* ++ * Until we hook up type-c detection, we ++ * have to stick with this. But it works. ++ */ ++ extcon_usb: extcon-usb { ++ compatible = "linux,extcon-usb-gpio"; ++ id-gpio = <&tlmm 58 GPIO_ACTIVE_HIGH>; ++ }; ++ ++ hdmi-out { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ++ port { ++ hdmi_con: endpoint { ++ remote-endpoint = <&adv7533_out>; ++ }; ++ }; ++ }; ++ ++ vph_pwr: vph-pwr-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vph_pwr"; ++ regulator-min-microvolt = <3800000>; ++ regulator-max-microvolt = <3800000>; ++ ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ v3p3_bck_bst: v3p3-bck-bst-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "v3p3_bck_bst"; ++ ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ vin-supply = <&vph_pwr>; ++ }; ++ ++ v1p2_ldo: v1p2-ldo-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "v1p2_ldo"; ++ ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ ++ vin-supply = <&vph_pwr>; ++ }; ++ ++ v5p0_boost: v5p0-boost-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "v5p0_boost"; ++ ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ ++ vin-supply = <&vph_pwr>; ++ }; ++}; ++ ++&adsp_pil { ++ firmware-name = "qcom/ifc6560/adsp.mbn"; ++}; ++ ++&blsp_i2c6 { ++ status = "okay"; ++ ++ adv7533: hdmi@39 { ++ compatible = "adi,adv7535"; ++ reg = <0x39>, <0x66>; ++ reg-names = "main", "edid"; ++ ++ interrupt-parent = <&pm660l_gpios>; ++ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ ++ clocks = <&rpmcc RPM_SMD_BB_CLK2>; ++ clock-names = "cec"; ++ /* ++ * Limit to 3 lanes to prevent the bridge from changing amount ++ * of lanes in the fly. MSM DSI host doesn't like that. ++ */ ++ adi,dsi-lanes = <3>; ++ avdd-supply = <&vreg_l13a_1p8>; ++ dvdd-supply = <&vreg_l13a_1p8>; ++ pvdd-supply = <&vreg_l13a_1p8>; ++ a2vdd-supply = <&vreg_l13a_1p8>; ++ v3p3-supply = <&v3p3_bck_bst>; ++ ++ ports { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ port@0 { ++ reg = <0>; ++ ++ adv7533_in: endpoint { ++ remote-endpoint = <&dsi0_out>; ++ }; ++ }; ++ ++ port@1 { ++ reg = <1>; ++ ++ adv7533_out: endpoint { ++ remote-endpoint = <&hdmi_con>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&blsp1_dma { ++ /* ++ * The board will lock up if we toggle the BLSP clock, unless the ++ * BAM DMA interconnects support is in place. ++ */ ++ /delete-property/ clocks; ++}; ++ ++&blsp1_uart2 { ++ status = "okay"; ++}; ++ ++&blsp2_dma { ++ /* ++ * The board will lock up if we toggle the BLSP clock, unless the ++ * BAM DMA interconnects support is in place. ++ */ ++ /delete-property/ clocks; ++}; ++ ++&blsp2_uart1 { ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "qcom,wcn3990-bt"; ++ ++ vddio-supply = <&vreg_l13a_1p8>; ++ vddxo-supply = <&vreg_l9a_1p8>; ++ vddrf-supply = <&vreg_l6a_1p3>; ++ vddch0-supply = <&vreg_l19a_3p3>; ++ max-speed = <3200000>; ++ }; ++}; ++ ++&dsi0 { ++ status = "okay"; ++ vdda-supply = <&vreg_l1a_1p225>; ++}; ++ ++&dsi0_out { ++ remote-endpoint = <&adv7533_in>; ++ data-lanes = <0 1 2 3>; ++}; ++ ++&dsi0_phy { ++ status = "okay"; ++ vcca-supply = <&vreg_l1b_0p925>; ++}; ++ ++&mdss { ++ status = "okay"; ++}; ++ ++&mmss_smmu { ++ status = "okay"; ++}; ++ ++&pon_pwrkey { ++ status = "okay"; ++}; ++ ++&pon_resin { ++ status = "okay"; ++ ++ linux,code = ; ++}; ++ ++&qusb2phy0 { ++ status = "okay"; ++ ++ vdd-supply = <&vreg_l1b_0p925>; ++ vdda-phy-dpdm-supply = <&vreg_l7b_3p125>; ++}; ++ ++&qusb2phy1 { ++ status = "okay"; ++ ++ vdd-supply = <&vreg_l1b_0p925>; ++ vdda-phy-dpdm-supply = <&vreg_l7b_3p125>; ++}; ++ ++&rpm_requests { ++ pm660-regulators { ++ compatible = "qcom,rpm-pm660-regulators"; ++ ++ vdd_s1-supply = <&vph_pwr>; ++ vdd_s2-supply = <&vph_pwr>; ++ vdd_s3-supply = <&vph_pwr>; ++ vdd_s4-supply = <&vph_pwr>; ++ vdd_s5-supply = <&vph_pwr>; ++ vdd_s6-supply = <&vph_pwr>; ++ ++ vdd_l1_l6_l7-supply = <&vreg_s5a_1p35>; ++ vdd_l2_l3-supply = <&vreg_s2b_1p05>; ++ vdd_l5-supply = <&vreg_s2b_1p05>; ++ vdd_l8_l9_l10_l11_l12_l13_l14-supply = <&vreg_s4a_2p04>; ++ vdd_l15_l16_l17_l18_l19-supply = <&vreg_bob>; ++ ++ vreg_s4a_2p04: s4 { ++ regulator-min-microvolt = <1805000>; ++ regulator-max-microvolt = <2040000>; ++ regulator-enable-ramp-delay = <200>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ }; ++ ++ vreg_s5a_1p35: s5 { ++ regulator-min-microvolt = <1224000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-enable-ramp-delay = <200>; ++ regulator-ramp-delay = <0>; ++ }; ++ ++ vreg_l1a_1p225: l1 { ++ regulator-min-microvolt = <1150000>; ++ regulator-max-microvolt = <1250000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l6a_1p3: l6 { ++ regulator-min-microvolt = <1304000>; ++ regulator-max-microvolt = <1368000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l8a_1p8: l8 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-system-load = <325000>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l9a_1p8: l9 { ++ regulator-min-microvolt = <1804000>; ++ regulator-max-microvolt = <1896000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l13a_1p8: l13 { ++ /* This gives power to the LPDDR4: never turn it off! */ ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1944000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-always-on; ++ regulator-boot-on; ++ }; ++ ++ vreg_l19a_3p3: l19 { ++ regulator-min-microvolt = <3312000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-allow-set-load; ++ }; ++ }; ++ ++ pm660l-regulators { ++ compatible = "qcom,rpm-pm660l-regulators"; ++ ++ vdd_s1-supply = <&vph_pwr>; ++ vdd_s2-supply = <&vph_pwr>; ++ vdd_s3_s4-supply = <&vph_pwr>; ++ vdd_s5-supply = <&vph_pwr>; ++ vdd_s6-supply = <&vph_pwr>; ++ ++ vdd_l1_l9_l10-supply = <&vreg_s2b_1p05>; ++ vdd_l2-supply = <&vreg_bob>; ++ vdd_l3_l5_l7_l8-supply = <&vreg_bob>; ++ vdd_l4_l6-supply = <&vreg_bob>; ++ vdd_bob-supply = <&vph_pwr>; ++ ++ vreg_s2b_1p05: s2 { ++ regulator-min-microvolt = <1050000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-enable-ramp-delay = <200>; ++ regulator-ramp-delay = <0>; ++ }; ++ ++ vreg_l1b_0p925: l1 { ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <925000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l2b_2p95: l2 { ++ regulator-min-microvolt = <1648000>; ++ regulator-max-microvolt = <3100000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l4b_2p95: l4 { ++ regulator-min-microvolt = <2944000>; ++ regulator-max-microvolt = <2952000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ ++ regulator-min-microamp = <200>; ++ regulator-max-microamp = <600000>; ++ regulator-system-load = <570000>; ++ regulator-allow-set-load; ++ }; ++ ++ /* ++ * Downstream specifies a range of 1721-3600mV, ++ * but the only assigned consumers are SDHCI2 VMMC ++ * and Coresight QPDI that both request pinned 2.95V. ++ * Tighten the range to 1.8-3.328 (closest to 3.3) to ++ * make the mmc driver happy. ++ */ ++ vreg_l5b_2p95: l5 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3328000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-system-load = <800000>; ++ regulator-ramp-delay = <0>; ++ regulator-allow-set-load; ++ }; ++ ++ vreg_l7b_3p125: l7 { ++ regulator-min-microvolt = <2700000>; ++ regulator-max-microvolt = <3125000>; ++ regulator-enable-ramp-delay = <250>; ++ }; ++ ++ vreg_l8b_3p3: l8 { ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-enable-ramp-delay = <250>; ++ regulator-ramp-delay = <0>; ++ }; ++ ++ vreg_bob: bob { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3624000>; ++ regulator-enable-ramp-delay = <500>; ++ regulator-ramp-delay = <0>; ++ }; ++ }; ++}; ++ ++&sdc2_state_on { ++ sd-cd { ++ pins = "gpio54"; ++ bias-pull-up; ++ drive-strength = <2>; ++ }; ++}; ++ ++&sdc2_state_off { ++ sd-cd { ++ pins = "gpio54"; ++ bias-disable; ++ drive-strength = <2>; ++ }; ++}; ++ ++&sdhc_1 { ++ status = "okay"; ++ supports-cqe; ++ ++ vmmc-supply = <&vreg_l4b_2p95>; ++ vqmmc-supply = <&vreg_l8a_1p8>; ++ ++ mmc-ddr-1_8v; ++ mmc-hs400-1_8v; ++ mmc-hs400-enhanced-strobe; ++}; ++ ++&sdhc_2 { ++ status = "okay"; ++ ++ vmmc-supply = <&vreg_l5b_2p95>; ++ vqmmc-supply = <&vreg_l2b_2p95>; ++ ++ cd-gpios = <&tlmm 54 GPIO_ACTIVE_LOW>; ++ no-sdio; ++ no-emmc; ++}; ++ ++&tlmm { ++ gpio-reserved-ranges = <0 4>, <8 4>; ++}; ++ ++&usb2 { ++ status = "okay"; ++}; ++ ++&usb2_dwc3 { ++ dr_mode = "host"; ++}; ++ ++&usb3 { ++ status = "okay"; ++}; ++ ++&usb3_dwc3 { ++ dr_mode = "peripheral"; ++ extcon = <&extcon_usb>; ++}; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sdm845-narrow-llcc-address-space.patch b/queue-5.19/arm64-dts-qcom-sdm845-narrow-llcc-address-space.patch new file mode 100644 index 00000000000..2a3b2359fbe --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sdm845-narrow-llcc-address-space.patch @@ -0,0 +1,44 @@ +From 0a956cf8c57b1139c024bdc1e94859819410e9a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 13:37:47 +0200 +Subject: arm64: dts: qcom: sdm845: narrow LLCC address space + +From: Krzysztof Kozlowski + +[ Upstream commit 300b5f661eebefb8571841b78091343eb87eca54 ] + +The Last Level Cache Controller (LLCC) device does not need to access +entire LLCC address space. Currently driver uses only hardware info and +status registers which both reside in LLCC0_COMMON range (offset +0x30000, size 0x1000). Narrow the address space to allow binding other +drivers to rest of LLCC address space. + +Cc: Rajendra Nayak +Cc: Sibi Sankar +Reported-by: Steev Klimaszewski +Suggested-by: Sibi Sankar +Signed-off-by: Krzysztof Kozlowski +Tested-by: Steev Klimaszewski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220728113748.170548-11-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi +index 7783005c8028..6d9787e32b88 100644 +--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi ++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi +@@ -2021,7 +2021,7 @@ + + llcc: system-cache-controller@1100000 { + compatible = "qcom,sdm845-llcc"; +- reg = <0 0x01100000 0 0x200000>, <0 0x01300000 0 0x50000>; ++ reg = <0 0x01100000 0 0x31000>, <0 0x01300000 0 0x50000>; + reg-names = "llcc_base", "llcc_broadcast_base"; + interrupts = ; + }; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sm8350-sagami-correct-ts-pin-property.patch b/queue-5.19/arm64-dts-qcom-sm8350-sagami-correct-ts-pin-property.patch new file mode 100644 index 00000000000..0cee99c09ce --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sm8350-sagami-correct-ts-pin-property.patch @@ -0,0 +1,36 @@ +From b1e13343844756a408bb2c7b357b0e780b991bda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 08:17:42 +0200 +Subject: arm64: dts: qcom: sm8350-sagami: correct TS pin property + +From: Krzysztof Kozlowski + +[ Upstream commit c9c53d1f4329564f98ed0decfe3c377c6639ec5d ] + +The pin configuration is selected with "pins", not "pin" property. + +Fixes: 1209e9246632 ("arm64: dts: qcom: sm8350-sagami: Enable and populate I2C/SPI nodes") +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220912061746.6311-37-krzysztof.kozlowski@linaro.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi +index 90b13cbe2fa6..9224a06f5469 100644 +--- a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi +@@ -223,7 +223,7 @@ + gpio-reserved-ranges = <44 4>; + + ts_int_default: ts-int-default { +- pin = "gpio23"; ++ pins = "gpio23"; + function = "gpio"; + drive-strength = <2>; + bias-disable; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-qcom-sm8450-fix-ufs-phy-serdes-size.patch b/queue-5.19/arm64-dts-qcom-sm8450-fix-ufs-phy-serdes-size.patch new file mode 100644 index 00000000000..6b1759d0d03 --- /dev/null +++ b/queue-5.19/arm64-dts-qcom-sm8450-fix-ufs-phy-serdes-size.patch @@ -0,0 +1,38 @@ +From d443b6b82209d5cbca576e137b5737b77dc3d551 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 16:34:31 +0200 +Subject: arm64: dts: qcom: sm8450: fix UFS PHY serdes size + +From: Johan Hovold + +[ Upstream commit 677920072e9d757ae158d66b8fdb695992bb3f1a ] + +The size of the UFS PHY serdes register region is 0x1c4 and the +corresponding 'reg' property should specifically not include the +adjacent regions that are defined in the child node (e.g. tx and rx). + +Fixes: 07fa917a335e ("arm64: dts: qcom: sm8450: add ufs nodes") +Signed-off-by: Johan Hovold +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220915143431.19842-2-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/qcom/sm8450.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi +index c958f5d4adc2..45fc1de2fd29 100644 +--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi ++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi +@@ -3082,7 +3082,7 @@ + + ufs_mem_phy: phy@1d87000 { + compatible = "qcom,sm8450-qmp-ufs-phy"; +- reg = <0 0x01d87000 0 0xe10>; ++ reg = <0 0x01d87000 0 0x1c4>; + #address-cells = <2>; + #size-cells = <2>; + ranges; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-renesas-r9a07g043-fix-sci-rx-tx-interrupt-.patch b/queue-5.19/arm64-dts-renesas-r9a07g043-fix-sci-rx-tx-interrupt-.patch new file mode 100644 index 00000000000..6b09cf92e8d --- /dev/null +++ b/queue-5.19/arm64-dts-renesas-r9a07g043-fix-sci-rx-tx-interrupt-.patch @@ -0,0 +1,50 @@ +From 55f29a705d023a3e189fec43aabc50f7049d5a2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 11:15:34 +0100 +Subject: arm64: dts: renesas: r9a07g043: Fix SCI{Rx,Tx} interrupt types + +From: Biju Das + +[ Upstream commit 72a482dbaec4b9e4d54b81be6bdb8c016fd2f4bd ] + +As per the RZ/G2UL Hardware User's Manual (Rev.1.00 Apr, 2022), +the interrupt type of SCI{Rx,Tx} is edge triggered. + +Signed-off-by: Biju Das +Fixes: cf40c9689e5109bf ("arm64: dts: renesas: Add initial DTSI for RZ/G2UL SoC") +Link: https://lore.kernel.org/r/20220802101534.1401342-3-biju.das.jz@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/r9a07g043.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi +index b31fb713ae4d..434ae73664a2 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi +@@ -334,8 +334,8 @@ + compatible = "renesas,r9a07g043-sci", "renesas,sci"; + reg = <0 0x1004d000 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G043_SCI0_CLKP>; +@@ -349,8 +349,8 @@ + compatible = "renesas,r9a07g043-sci", "renesas,sci"; + reg = <0 0x1004d400 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G043_SCI1_CLKP>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-renesas-r9a07g044-fix-sci-rx-tx-interrupt-.patch b/queue-5.19/arm64-dts-renesas-r9a07g044-fix-sci-rx-tx-interrupt-.patch new file mode 100644 index 00000000000..5b735adb5b5 --- /dev/null +++ b/queue-5.19/arm64-dts-renesas-r9a07g044-fix-sci-rx-tx-interrupt-.patch @@ -0,0 +1,50 @@ +From 2a92deac98b0c2c1bff88d00b1dcbff8b5dda2f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 11:15:32 +0100 +Subject: arm64: dts: renesas: r9a07g044: Fix SCI{Rx,Tx} interrupt types + +From: Biju Das + +[ Upstream commit f3b7bc89c97b98aa6f157d5f296695af8940a5ac ] + +As per the latest RZ/G2L Hardware User's Manual (Rev.1.10 Apr, 2022), +the interrupt type of SCI{Rx,Tx} is edge triggered. + +Signed-off-by: Biju Das +Fixes: f9a2adcc9e908907 ("arm64: dts: renesas: r9a07g044: Add SCI[0-1] nodes") +Link: https://lore.kernel.org/r/20220802101534.1401342-1-biju.das.jz@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/r9a07g044.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +index 3652e511160f..265140b20dad 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi +@@ -394,8 +394,8 @@ + compatible = "renesas,r9a07g044-sci", "renesas,sci"; + reg = <0 0x1004d000 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCI0_CLKP>; +@@ -409,8 +409,8 @@ + compatible = "renesas,r9a07g044-sci", "renesas,sci"; + reg = <0 0x1004d400 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G044_SCI1_CLKP>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-renesas-r9a07g054-fix-sci-rx-tx-interrupt-.patch b/queue-5.19/arm64-dts-renesas-r9a07g054-fix-sci-rx-tx-interrupt-.patch new file mode 100644 index 00000000000..88a20dc06ba --- /dev/null +++ b/queue-5.19/arm64-dts-renesas-r9a07g054-fix-sci-rx-tx-interrupt-.patch @@ -0,0 +1,50 @@ +From f3f7cd796056d73399a2da2731b0ac5a68d3ccf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 11:15:33 +0100 +Subject: arm64: dts: renesas: r9a07g054: Fix SCI{Rx,Tx} interrupt types + +From: Biju Das + +[ Upstream commit 13dec051c7f139eef345c55a60941843e72128f1 ] + +As per the RZ/V2L Hardware User's Manual (Rev.1.00 Nov, 2021), +the interrupt type of SCI{Rx,Tx} is edge triggered. + +Signed-off-by: Biju Das +Fixes: 7c2b8198f4f321df ("arm64: dts: renesas: Add initial DTSI for RZ/V2L SoC") +Link: https://lore.kernel.org/r/20220802101534.1401342-2-biju.das.jz@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/renesas/r9a07g054.dtsi | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +index 4d6b9d7684c9..d0eeca4f6aa1 100644 +--- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi ++++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi +@@ -399,8 +399,8 @@ + compatible = "renesas,r9a07g054-sci", "renesas,sci"; + reg = <0 0x1004d000 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G054_SCI0_CLKP>; +@@ -414,8 +414,8 @@ + compatible = "renesas,r9a07g054-sci", "renesas,sci"; + reg = <0 0x1004d400 0 0x400>; + interrupts = , +- , +- , ++ , ++ , + ; + interrupt-names = "eri", "rxi", "txi", "tei"; + clocks = <&cpg CPG_MOD R9A07G054_SCI1_CLKP>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-ti-k3-j7200-fix-main-pinmux-range.patch b/queue-5.19/arm64-dts-ti-k3-j7200-fix-main-pinmux-range.patch new file mode 100644 index 00000000000..5f1894c7b41 --- /dev/null +++ b/queue-5.19/arm64-dts-ti-k3-j7200-fix-main-pinmux-range.patch @@ -0,0 +1,78 @@ +From 0ceed7d2ac1dfc8de169dcda302a745914c96307 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 13:57:23 -0700 +Subject: arm64: dts: ti: k3-j7200: fix main pinmux range + +From: Matt Ranostay + +[ Upstream commit 0d0a0b4413460383331088b2203ba09a6971bc3a ] + +Range size of 0x2b4 was incorrect since there isn't 173 configurable +pins for muxing. Additionally there is a non-addressable region in the +mapping which requires splitting into two ranges. + +main_pmx0 -> 67 pins +main_pmx1 -> 3 pins + +Fixes: d361ed88455f ("arm64: dts: ti: Add support for J7200 SoC") +Signed-off-by: Matt Ranostay +Signed-off-by: Vignesh Raghavendra +Tested-by: Vaishnav Achath +Link: https://lore.kernel.org/r/20220919205723.8342-1-mranostay@ti.com +Signed-off-by: Sasha Levin +--- + arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts | 10 ++++++---- + arch/arm64/boot/dts/ti/k3-j7200-main.dtsi | 11 ++++++++++- + 2 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +index 121975dc8239..7e8552fd2b6a 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts ++++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts +@@ -134,15 +134,17 @@ + >; + }; + +- main_usbss0_pins_default: main-usbss0-pins-default { ++ vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { + pinctrl-single,pins = < +- J721E_IOPAD(0x120, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */ ++ J721E_IOPAD(0xd0, PIN_OUTPUT, 7) /* (T5) SPI0_D1.GPIO0_55 */ + >; + }; ++}; + +- vdd_sd_dv_pins_default: vdd-sd-dv-pins-default { ++&main_pmx1 { ++ main_usbss0_pins_default: main-usbss0-pins-default { + pinctrl-single,pins = < +- J721E_IOPAD(0xd0, PIN_OUTPUT, 7) /* (T5) SPI0_D1.GPIO0_55 */ ++ J721E_IOPAD(0x04, PIN_OUTPUT, 0) /* (T4) USB0_DRVVBUS */ + >; + }; + }; +diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +index 16684a2f054d..e12a53f1857f 100644 +--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi ++++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +@@ -295,7 +295,16 @@ + main_pmx0: pinctrl@11c000 { + compatible = "pinctrl-single"; + /* Proxy 0 addressing */ +- reg = <0x00 0x11c000 0x00 0x2b4>; ++ reg = <0x00 0x11c000 0x00 0x10c>; ++ #pinctrl-cells = <1>; ++ pinctrl-single,register-width = <32>; ++ pinctrl-single,function-mask = <0xffffffff>; ++ }; ++ ++ main_pmx1: pinctrl@11c11c { ++ compatible = "pinctrl-single"; ++ /* Proxy 0 addressing */ ++ reg = <0x00 0x11c11c 0x00 0xc>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; +-- +2.35.1 + diff --git a/queue-5.19/arm64-dts-uniphier-add-usb-device-support-for-pxs3-r.patch b/queue-5.19/arm64-dts-uniphier-add-usb-device-support-for-pxs3-r.patch new file mode 100644 index 00000000000..9bfd593167f --- /dev/null +++ b/queue-5.19/arm64-dts-uniphier-add-usb-device-support-for-pxs3-r.patch @@ -0,0 +1,162 @@ +From 17d489618fc2fe4d9cf72b10c9c50bd08b219348 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 13:23:18 +0900 +Subject: arm64: dts: uniphier: Add USB-device support for PXs3 reference board + +From: Kunihiko Hayashi + +[ Upstream commit 19fee1a1096d21ab1f1e712148b5417bda2939a2 ] + +PXs3 reference board can change each USB port 0 and 1 to device mode +with jumpers. Prepare devicetree sources for USB port 0 and 1. + +This specifies dr_mode, pinctrl, and some quirks and removes nodes for +unused phys and vbus-supply properties. + +Signed-off-by: Kunihiko Hayashi +Link: https://lore.kernel.org/r/20220913042321.4817-8-hayashi.kunihiko@socionext.com' +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/boot/dts/uniphier-pinctrl.dtsi | 10 +++++ + arch/arm64/boot/dts/socionext/Makefile | 4 +- + .../socionext/uniphier-pxs3-ref-gadget0.dts | 41 +++++++++++++++++++ + .../socionext/uniphier-pxs3-ref-gadget1.dts | 40 ++++++++++++++++++ + 4 files changed, 94 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget0.dts + create mode 100644 arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget1.dts + +diff --git a/arch/arm/boot/dts/uniphier-pinctrl.dtsi b/arch/arm/boot/dts/uniphier-pinctrl.dtsi +index c0fd029b37e5..f909ec2e5333 100644 +--- a/arch/arm/boot/dts/uniphier-pinctrl.dtsi ++++ b/arch/arm/boot/dts/uniphier-pinctrl.dtsi +@@ -196,11 +196,21 @@ + function = "usb0"; + }; + ++ pinctrl_usb0_device: usb0-device { ++ groups = "usb0_device"; ++ function = "usb0"; ++ }; ++ + pinctrl_usb1: usb1 { + groups = "usb1"; + function = "usb1"; + }; + ++ pinctrl_usb1_device: usb1-device { ++ groups = "usb1_device"; ++ function = "usb1"; ++ }; ++ + pinctrl_usb2: usb2 { + groups = "usb2"; + function = "usb2"; +diff --git a/arch/arm64/boot/dts/socionext/Makefile b/arch/arm64/boot/dts/socionext/Makefile +index dda3da33614b..33989a9643ac 100644 +--- a/arch/arm64/boot/dts/socionext/Makefile ++++ b/arch/arm64/boot/dts/socionext/Makefile +@@ -5,4 +5,6 @@ dtb-$(CONFIG_ARCH_UNIPHIER) += \ + uniphier-ld20-akebi96.dtb \ + uniphier-ld20-global.dtb \ + uniphier-ld20-ref.dtb \ +- uniphier-pxs3-ref.dtb ++ uniphier-pxs3-ref.dtb \ ++ uniphier-pxs3-ref-gadget0.dtb \ ++ uniphier-pxs3-ref-gadget1.dtb +diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget0.dts b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget0.dts +new file mode 100644 +index 000000000000..7069f51bc120 +--- /dev/null ++++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget0.dts +@@ -0,0 +1,41 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++// ++// Device Tree Source for UniPhier PXs3 Reference Board (for USB-Device #0) ++// ++// Copyright (C) 2021 Socionext Inc. ++// Author: Kunihiko Hayashi ++ ++/dts-v1/; ++#include "uniphier-pxs3-ref.dts" ++ ++/ { ++ model = "UniPhier PXs3 Reference Board (USB-Device #0)"; ++}; ++ ++/* I2C3 pinctrl is shared with USB*VBUSIN */ ++&i2c3 { ++ status = "disabled"; ++}; ++ ++&usb0 { ++ status = "okay"; ++ dr_mode = "peripheral"; ++ pinctrl-0 = <&pinctrl_usb0_device>; ++ snps,dis_enblslpm_quirk; ++ snps,dis_u2_susphy_quirk; ++ snps,dis_u3_susphy_quirk; ++ snps,usb2_gadget_lpm_disable; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phys = <&usb0_hsphy0>, <&usb0_ssphy0>; ++}; ++ ++&usb0_hsphy0 { ++ /delete-property/ vbus-supply; ++}; ++ ++&usb0_ssphy0 { ++ /delete-property/ vbus-supply; ++}; ++ ++/delete-node/ &usb0_hsphy1; ++/delete-node/ &usb0_ssphy1; +diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget1.dts b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget1.dts +new file mode 100644 +index 000000000000..a3cfa8113ffb +--- /dev/null ++++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3-ref-gadget1.dts +@@ -0,0 +1,40 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT ++// ++// Device Tree Source for UniPhier PXs3 Reference Board (for USB-Device #1) ++// ++// Copyright (C) 2021 Socionext Inc. ++// Author: Kunihiko Hayashi ++ ++/dts-v1/; ++#include "uniphier-pxs3-ref.dts" ++ ++/ { ++ model = "UniPhier PXs3 Reference Board (USB-Device #1)"; ++}; ++ ++/* I2C3 pinctrl is shared with USB*VBUSIN */ ++&i2c3 { ++ status = "disabled"; ++}; ++ ++&usb1 { ++ status = "okay"; ++ dr_mode = "peripheral"; ++ pinctrl-0 = <&pinctrl_usb1_device>; ++ snps,dis_enblslpm_quirk; ++ snps,dis_u2_susphy_quirk; ++ snps,dis_u3_susphy_quirk; ++ snps,usb2_gadget_lpm_disable; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phys = <&usb1_hsphy0>, <&usb1_ssphy0>; ++}; ++ ++&usb1_hsphy0 { ++ /delete-property/ vbus-supply; ++}; ++ ++&usb1_ssphy0 { ++ /delete-property/ vbus-supply; ++}; ++ ++/delete-node/ &usb1_hsphy1; +-- +2.35.1 + diff --git a/queue-5.19/arm64-ftrace-fix-module-plts-with-mcount.patch b/queue-5.19/arm64-ftrace-fix-module-plts-with-mcount.patch new file mode 100644 index 00000000000..975f1cba4e1 --- /dev/null +++ b/queue-5.19/arm64-ftrace-fix-module-plts-with-mcount.patch @@ -0,0 +1,127 @@ +From 84bbf440a2129a6782fdfe606bb13d556250b745 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 14:45:25 +0100 +Subject: arm64: ftrace: fix module PLTs with mcount + +From: Mark Rutland + +[ Upstream commit 8cfb08575c6d4585f1ce0deeb189e5c824776b04 ] + +Li Huafei reports that mcount-based ftrace with module PLTs was broken +by commit: + + a6253579977e4c6f ("arm64: ftrace: consistently handle PLTs.") + +When a module PLTs are used and a module is loaded sufficiently far away +from the kernel, we'll create PLTs for any branches which are +out-of-range. These are separate from the special ftrace trampoline +PLTs, which the module PLT code doesn't directly manipulate. + +When mcount is in use this is a problem, as each mcount callsite in a +module will be initialized to point to a module PLT, but since commit +a6253579977e4c6f ftrace_make_nop() will assume that the callsite has +been initialized to point to the special ftrace trampoline PLT, and +ftrace_find_callable_addr() rejects other cases. + +This means that when ftrace tries to initialize a callsite via +ftrace_make_nop(), the call to ftrace_find_callable_addr() will find +that the `_mcount` stub is out-of-range and is not handled by the ftrace +PLT, resulting in a splat: + +| ftrace_test: loading out-of-tree module taints kernel. +| ftrace: no module PLT for _mcount +| ------------[ ftrace bug ]------------ +| ftrace failed to modify +| [] 0xffff800029180014 +| actual: 44:00:00:94 +| Initializing ftrace call sites +| ftrace record flags: 2000000 +| (0) +| expected tramp: ffff80000802eb3c +| ------------[ cut here ]------------ +| WARNING: CPU: 3 PID: 157 at kernel/trace/ftrace.c:2120 ftrace_bug+0x94/0x270 +| Modules linked in: +| CPU: 3 PID: 157 Comm: insmod Tainted: G O 6.0.0-rc6-00151-gcd722513a189-dirty #22 +| Hardware name: linux,dummy-virt (DT) +| pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +| pc : ftrace_bug+0x94/0x270 +| lr : ftrace_bug+0x21c/0x270 +| sp : ffff80000b2bbaf0 +| x29: ffff80000b2bbaf0 x28: 0000000000000000 x27: ffff0000c4d38000 +| x26: 0000000000000001 x25: ffff800009d7e000 x24: ffff0000c4d86e00 +| x23: 0000000002000000 x22: ffff80000a62b000 x21: ffff8000098ebea8 +| x20: ffff0000c4d38000 x19: ffff80000aa24158 x18: ffffffffffffffff +| x17: 0000000000000000 x16: 0a0d2d2d2d2d2d2d x15: ffff800009aa9118 +| x14: 0000000000000000 x13: 6333626532303830 x12: 3030303866666666 +| x11: 203a706d61727420 x10: 6465746365707865 x9 : 3362653230383030 +| x8 : c0000000ffffefff x7 : 0000000000017fe8 x6 : 000000000000bff4 +| x5 : 0000000000057fa8 x4 : 0000000000000000 x3 : 0000000000000001 +| x2 : ad2cb14bb5438900 x1 : 0000000000000000 x0 : 0000000000000022 +| Call trace: +| ftrace_bug+0x94/0x270 +| ftrace_process_locs+0x308/0x430 +| ftrace_module_init+0x44/0x60 +| load_module+0x15b4/0x1ce8 +| __do_sys_init_module+0x1ec/0x238 +| __arm64_sys_init_module+0x24/0x30 +| invoke_syscall+0x54/0x118 +| el0_svc_common.constprop.4+0x84/0x100 +| do_el0_svc+0x3c/0xd0 +| el0_svc+0x1c/0x50 +| el0t_64_sync_handler+0x90/0xb8 +| el0t_64_sync+0x15c/0x160 +| ---[ end trace 0000000000000000 ]--- +| ---------test_init----------- + +Fix this by reverting to the old behaviour of ignoring the old +instruction when initialising an mcount callsite in a module, which was +the behaviour prior to commit a6253579977e4c6f. + +Signed-off-by: Mark Rutland +Fixes: a6253579977e ("arm64: ftrace: consistently handle PLTs.") +Reported-by: Li Huafei +Link: https://lore.kernel.org/linux-arm-kernel/20220929094134.99512-1-lihuafei1@huawei.com +Cc: Ard Biesheuvel +Cc: Will Deacon +Link: https://lore.kernel.org/r/20220929134525.798593-1-mark.rutland@arm.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/kernel/ftrace.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c +index ea5dc7c90f46..b49ba9a24bcc 100644 +--- a/arch/arm64/kernel/ftrace.c ++++ b/arch/arm64/kernel/ftrace.c +@@ -217,11 +217,26 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, + unsigned long pc = rec->ip; + u32 old = 0, new; + ++ new = aarch64_insn_gen_nop(); ++ ++ /* ++ * When using mcount, callsites in modules may have been initalized to ++ * call an arbitrary module PLT (which redirects to the _mcount stub) ++ * rather than the ftrace PLT we'll use at runtime (which redirects to ++ * the ftrace trampoline). We can ignore the old PLT when initializing ++ * the callsite. ++ * ++ * Note: 'mod' is only set at module load time. ++ */ ++ if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) && ++ IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && mod) { ++ return aarch64_insn_patch_text_nosync((void *)pc, new); ++ } ++ + if (!ftrace_find_callable_addr(rec, mod, &addr)) + return -EINVAL; + + old = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK); +- new = aarch64_insn_gen_nop(); + + return ftrace_modify_code(pc, old, new, true); + } +-- +2.35.1 + diff --git a/queue-5.19/arm64-run-softirqs-on-the-per-cpu-irq-stack.patch b/queue-5.19/arm64-run-softirqs-on-the-per-cpu-irq-stack.patch new file mode 100644 index 00000000000..6f25abe8f10 --- /dev/null +++ b/queue-5.19/arm64-run-softirqs-on-the-per-cpu-irq-stack.patch @@ -0,0 +1,77 @@ +From 4feb063f3cb5158e76785d83ffabeb9501bc5925 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 20:47:39 +0800 +Subject: arm64: run softirqs on the per-CPU IRQ stack + +From: Qi Zheng + +[ Upstream commit 8eb858c44b98e0326bb32fca34ae671995cd73bb ] + +Currently arm64 supports per-CPU IRQ stack, but softirqs +are still handled in the task context. + +Since any call to local_bh_enable() at any level in the task's +call stack may trigger a softirq processing run, which could +potentially cause a task stack overflow if the combined stack +footprints exceed the stack's size, let's run these softirqs +on the IRQ stack as well. + +Signed-off-by: Qi Zheng +Reviewed-by: Arnd Bergmann +Acked-by: Will Deacon +Link: https://lore.kernel.org/r/20220815124739.15948-1-zhengqi.arch@bytedance.com +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + arch/arm64/Kconfig | 1 + + arch/arm64/kernel/irq.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig +index dfd9228c2adc..38e0a8b19f82 100644 +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -227,6 +227,7 @@ config ARM64 + select HAVE_ARCH_USERFAULTFD_MINOR if USERFAULTFD + select TRACE_IRQFLAGS_SUPPORT + select TRACE_IRQFLAGS_NMI_SUPPORT ++ select HAVE_SOFTIRQ_ON_OWN_STACK + help + ARM 64-bit (AArch64) Linux support. + +diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c +index bda49430c9ea..38dbd3828f13 100644 +--- a/arch/arm64/kernel/irq.c ++++ b/arch/arm64/kernel/irq.c +@@ -21,7 +21,9 @@ + #include + #include + #include ++#include + #include ++#include + + /* Only access this in an NMI enter/exit */ + DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts); +@@ -71,6 +73,18 @@ static void init_irq_stacks(void) + } + #endif + ++#ifndef CONFIG_PREEMPT_RT ++static void ____do_softirq(struct pt_regs *regs) ++{ ++ __do_softirq(); ++} ++ ++void do_softirq_own_stack(void) ++{ ++ call_on_irq_stack(NULL, ____do_softirq); ++} ++#endif ++ + static void default_handle_irq(struct pt_regs *regs) + { + panic("IRQ taken without a root IRQ handler\n"); +-- +2.35.1 + diff --git a/queue-5.19/asoc-codecs-tx-macro-fix-kcontrol-put.patch b/queue-5.19/asoc-codecs-tx-macro-fix-kcontrol-put.patch new file mode 100644 index 00000000000..5bcf1473ae3 --- /dev/null +++ b/queue-5.19/asoc-codecs-tx-macro-fix-kcontrol-put.patch @@ -0,0 +1,68 @@ +From a8448a963d9590ceab3b08cf0cdeb680ac638321 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 18:01:05 +0100 +Subject: ASoC: codecs: tx-macro: fix kcontrol put + +From: Srinivas Kandagatla + +[ Upstream commit c1057a08af438e0cf5450c1d977a3011198ed2f8 ] + +tx_macro_tx_mixer_put() and tx_macro_dec_mode_put() currently returns zero +eventhough it changes the value. +Fix this, so that change notifications are sent correctly. + +Fixes: d207bdea0ca9 ("ASoC: codecs: lpass-tx-macro: add dapm widgets and route") +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20220906170112.1984-6-srinivas.kandagatla@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/lpass-tx-macro.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c +index 55503ba480bb..e162a08d9945 100644 +--- a/sound/soc/codecs/lpass-tx-macro.c ++++ b/sound/soc/codecs/lpass-tx-macro.c +@@ -823,17 +823,23 @@ static int tx_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + + if (enable) { ++ if (tx->active_decimator[dai_id] == dec_id) ++ return 0; ++ + set_bit(dec_id, &tx->active_ch_mask[dai_id]); + tx->active_ch_cnt[dai_id]++; + tx->active_decimator[dai_id] = dec_id; + } else { ++ if (tx->active_decimator[dai_id] == -1) ++ return 0; ++ + tx->active_ch_cnt[dai_id]--; + clear_bit(dec_id, &tx->active_ch_mask[dai_id]); + tx->active_decimator[dai_id] = -1; + } + snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, update); + +- return 0; ++ return 1; + } + + static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w, +@@ -1019,9 +1025,12 @@ static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol, + int path = e->shift_l; + struct tx_macro *tx = snd_soc_component_get_drvdata(component); + ++ if (tx->dec_mode[path] == value) ++ return 0; ++ + tx->dec_mode[path] = value; + +- return 0; ++ return 1; + } + + static int tx_macro_get_bcs(struct snd_kcontrol *kcontrol, +-- +2.35.1 + diff --git a/queue-5.19/asoc-da7219-fix-an-error-handling-path-in-da7219_reg.patch b/queue-5.19/asoc-da7219-fix-an-error-handling-path-in-da7219_reg.patch new file mode 100644 index 00000000000..0ad2736d313 --- /dev/null +++ b/queue-5.19/asoc-da7219-fix-an-error-handling-path-in-da7219_reg.patch @@ -0,0 +1,58 @@ +From a69f3897be7baee989e3296128ebd44e451ecf92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 21:44:57 +0200 +Subject: ASoC: da7219: Fix an error handling path in + da7219_register_dai_clks() + +From: Christophe JAILLET + +[ Upstream commit abb4e4349afe7eecdb0499582f1c777031e3a7c8 ] + +If clk_hw_register() fails, the corresponding clk should not be +unregistered. + +To handle errors from loops, clean up partial iterations before doing the +goto. So add a clk_hw_unregister(). +Then use a while (--i >= 0) loop in the unwind section. + +Fixes: 78013a1cf297 ("ASoC: da7219: Fix clock handling around codec level probe") +Reported-by: Dan Carpenter +Signed-off-by: Christophe JAILLET +Reviewed-by: Dan Carpenter +Link: https://lore.kernel.org/r/e4acceab57a0d9e477a8d5890a45c5309e553e7c.1663875789.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/da7219.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c +index 7fdef38ed8cd..1bfba7ef51ce 100644 +--- a/sound/soc/codecs/da7219.c ++++ b/sound/soc/codecs/da7219.c +@@ -2196,6 +2196,7 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) + dai_clk_lookup = clkdev_hw_create(dai_clk_hw, init.name, + "%s", dev_name(dev)); + if (!dai_clk_lookup) { ++ clk_hw_unregister(dai_clk_hw); + ret = -ENOMEM; + goto err; + } else { +@@ -2217,12 +2218,12 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) + return 0; + + err: +- do { ++ while (--i >= 0) { + if (da7219->dai_clks_lookup[i]) + clkdev_drop(da7219->dai_clks_lookup[i]); + + clk_hw_unregister(&da7219->dai_clks_hw[i]); +- } while (i-- > 0); ++ } + + if (np) + kfree(da7219->clk_hw_data); +-- +2.35.1 + diff --git a/queue-5.19/asoc-eureka-tlv320-hold-reference-returned-from-of_f.patch b/queue-5.19/asoc-eureka-tlv320-hold-reference-returned-from-of_f.patch new file mode 100644 index 00000000000..40da6941cf0 --- /dev/null +++ b/queue-5.19/asoc-eureka-tlv320-hold-reference-returned-from-of_f.patch @@ -0,0 +1,69 @@ +From 7df756efd473070c6cfbeb7d928f043f5fd4c35b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 21:43:54 +0800 +Subject: ASoC: eureka-tlv320: Hold reference returned from of_find_xxx API + +From: Liang He + +[ Upstream commit bfb735a3ceff0bab6473bac275da96f9b2a06dec ] + +In eukrea_tlv320_probe(), we need to hold the reference returned +from of_find_compatible_node() which has increased the refcount +and then call of_node_put() with it when done. + +Fixes: 66f232908de2 ("ASoC: eukrea-tlv320: Add DT support.") +Co-authored-by: Kelin Wang +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220914134354.3995587-1-windhl@126.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/fsl/eukrea-tlv320.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c +index 8b61582753c8..9af4c4a35eb1 100644 +--- a/sound/soc/fsl/eukrea-tlv320.c ++++ b/sound/soc/fsl/eukrea-tlv320.c +@@ -86,7 +86,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) + int ret; + int int_port = 0, ext_port; + struct device_node *np = pdev->dev.of_node; +- struct device_node *ssi_np = NULL, *codec_np = NULL; ++ struct device_node *ssi_np = NULL, *codec_np = NULL, *tmp_np = NULL; + + eukrea_tlv320.dev = &pdev->dev; + if (np) { +@@ -143,7 +143,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) + } + + if (machine_is_eukrea_cpuimx27() || +- of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux")) { ++ (tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux"))) { + imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_TFSDIR | +@@ -158,10 +158,11 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) + IMX_AUDMUX_V1_PCR_SYN | + IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) + ); ++ of_node_put(tmp_np); + } else if (machine_is_eukrea_cpuimx25sd() || + machine_is_eukrea_cpuimx35sd() || + machine_is_eukrea_cpuimx51sd() || +- of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux")) { ++ (tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux"))) { + if (!np) + ext_port = machine_is_eukrea_cpuimx25sd() ? + 4 : 3; +@@ -178,6 +179,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) + IMX_AUDMUX_V2_PTCR_SYN, + IMX_AUDMUX_V2_PDCR_RXDSEL(int_port) + ); ++ of_node_put(tmp_np); + } else { + if (np) { + /* The eukrea,asoc-tlv320 driver was explicitly +-- +2.35.1 + diff --git a/queue-5.19/asoc-mt6359-fix-tests-for-platform_get_irq-failure.patch b/queue-5.19/asoc-mt6359-fix-tests-for-platform_get_irq-failure.patch new file mode 100644 index 00000000000..b4735e30afa --- /dev/null +++ b/queue-5.19/asoc-mt6359-fix-tests-for-platform_get_irq-failure.patch @@ -0,0 +1,55 @@ +From f8d35db1f81734225e14800f9c2c70568cee3539 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 14:01:26 +0300 +Subject: ASoC: mt6359: fix tests for platform_get_irq() failure + +From: Dan Carpenter + +[ Upstream commit 51eea3a6fb4d39c2cc71824e6eee5949d7ae4d1c ] + +The platform_get_irq() returns negative error codes. It can't actually +return zero, but if it did that should be treated as success. + +Fixes: eef07b9e0925 ("ASoC: mediatek: mt6359: add MT6359 accdet jack driver") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/YvThhr86N3qQM2EO@kili +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/mt6359-accdet.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c +index c190628e2905..7f624854948c 100644 +--- a/sound/soc/codecs/mt6359-accdet.c ++++ b/sound/soc/codecs/mt6359-accdet.c +@@ -965,7 +965,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev) + mutex_init(&priv->res_lock); + + priv->accdet_irq = platform_get_irq(pdev, 0); +- if (priv->accdet_irq) { ++ if (priv->accdet_irq >= 0) { + ret = devm_request_threaded_irq(&pdev->dev, priv->accdet_irq, + NULL, mt6359_accdet_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, +@@ -979,7 +979,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev) + + if (priv->caps & ACCDET_PMIC_EINT0) { + priv->accdet_eint0 = platform_get_irq(pdev, 1); +- if (priv->accdet_eint0) { ++ if (priv->accdet_eint0 >= 0) { + ret = devm_request_threaded_irq(&pdev->dev, + priv->accdet_eint0, + NULL, mt6359_accdet_irq, +@@ -994,7 +994,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev) + } + } else if (priv->caps & ACCDET_PMIC_EINT1) { + priv->accdet_eint1 = platform_get_irq(pdev, 2); +- if (priv->accdet_eint1) { ++ if (priv->accdet_eint1 >= 0) { + ret = devm_request_threaded_irq(&pdev->dev, + priv->accdet_eint1, + NULL, mt6359_accdet_irq, +-- +2.35.1 + diff --git a/queue-5.19/asoc-mt6660-fix-pm-disable-depth-imbalance-in-mt6660.patch b/queue-5.19/asoc-mt6660-fix-pm-disable-depth-imbalance-in-mt6660.patch new file mode 100644 index 00000000000..44ac7574306 --- /dev/null +++ b/queue-5.19/asoc-mt6660-fix-pm-disable-depth-imbalance-in-mt6660.patch @@ -0,0 +1,51 @@ +From e7089ab2dc3a4b1c61514f8e58b4d3676506c810 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:01:16 +0800 +Subject: ASoC: mt6660: Fix PM disable depth imbalance in mt6660_i2c_probe + +From: Zhang Qilong + +[ Upstream commit b73f11e895e140537e7f8c7251211ccd3ce0782b ] + +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 moving +pm_runtime_enable to the endding of mt6660_i2c_probe. + +Fixes:f289e55c6eeb4 ("ASoC: Add MediaTek MT6660 Speaker Amp Driver") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220928160116.125020-5-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/mt6660.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c +index ba11555796ad..45e0df13afb9 100644 +--- a/sound/soc/codecs/mt6660.c ++++ b/sound/soc/codecs/mt6660.c +@@ -503,13 +503,17 @@ static int mt6660_i2c_probe(struct i2c_client *client) + dev_err(chip->dev, "read chip revision fail\n"); + goto probe_fail; + } +- pm_runtime_set_active(chip->dev); +- pm_runtime_enable(chip->dev); + + ret = devm_snd_soc_register_component(chip->dev, + &mt6660_component_driver, + &mt6660_codec_dai, 1); ++ if (!ret) { ++ pm_runtime_set_active(chip->dev); ++ pm_runtime_enable(chip->dev); ++ } ++ + return ret; ++ + probe_fail: + _mt6660_chip_power_on(chip, 0); + mutex_destroy(&chip->io_lock); +-- +2.35.1 + diff --git a/queue-5.19/asoc-rsnd-add-check-for-rsnd_mod_power_on.patch b/queue-5.19/asoc-rsnd-add-check-for-rsnd_mod_power_on.patch new file mode 100644 index 00000000000..73969f406d6 --- /dev/null +++ b/queue-5.19/asoc-rsnd-add-check-for-rsnd_mod_power_on.patch @@ -0,0 +1,116 @@ +From 5292b8ea1bcfc32f0c9b65d5acb95f04a260ffaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 09:30:30 +0800 +Subject: ASoC: rsnd: Add check for rsnd_mod_power_on + +From: Jiasheng Jiang + +[ Upstream commit 376be51caf8871419bbcbb755e1e615d30dc3153 ] + +As rsnd_mod_power_on() can return negative numbers, +it should be better to check the return value and +deal with the exception. + +Fixes: e7d850dd10f4 ("ASoC: rsnd: use mod base common method on SSI-parent") +Signed-off-by: Jiasheng Jiang +Acked-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/20220902013030.3691266-1-jiasheng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sh/rcar/ctu.c | 6 +++++- + sound/soc/sh/rcar/dvc.c | 6 +++++- + sound/soc/sh/rcar/mix.c | 6 +++++- + sound/soc/sh/rcar/src.c | 5 ++++- + sound/soc/sh/rcar/ssi.c | 4 +++- + 5 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c +index 6156445bcb69..e39eb2ac7e95 100644 +--- a/sound/soc/sh/rcar/ctu.c ++++ b/sound/soc/sh/rcar/ctu.c +@@ -171,7 +171,11 @@ static int rsnd_ctu_init(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) + { +- rsnd_mod_power_on(mod); ++ int ret; ++ ++ ret = rsnd_mod_power_on(mod); ++ if (ret < 0) ++ return ret; + + rsnd_ctu_activation(mod); + +diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c +index 5137e03a9d7c..16befcbc312c 100644 +--- a/sound/soc/sh/rcar/dvc.c ++++ b/sound/soc/sh/rcar/dvc.c +@@ -186,7 +186,11 @@ static int rsnd_dvc_init(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) + { +- rsnd_mod_power_on(mod); ++ int ret; ++ ++ ret = rsnd_mod_power_on(mod); ++ if (ret < 0) ++ return ret; + + rsnd_dvc_activation(mod); + +diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c +index 3572c2c5686c..1de0e085804c 100644 +--- a/sound/soc/sh/rcar/mix.c ++++ b/sound/soc/sh/rcar/mix.c +@@ -146,7 +146,11 @@ static int rsnd_mix_init(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv) + { +- rsnd_mod_power_on(mod); ++ int ret; ++ ++ ret = rsnd_mod_power_on(mod); ++ if (ret < 0) ++ return ret; + + rsnd_mix_activation(mod); + +diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c +index 0ea84ae57c6a..f832165e46bc 100644 +--- a/sound/soc/sh/rcar/src.c ++++ b/sound/soc/sh/rcar/src.c +@@ -463,11 +463,14 @@ static int rsnd_src_init(struct rsnd_mod *mod, + struct rsnd_priv *priv) + { + struct rsnd_src *src = rsnd_mod_to_src(mod); ++ int ret; + + /* reset sync convert_rate */ + src->sync.val = 0; + +- rsnd_mod_power_on(mod); ++ ret = rsnd_mod_power_on(mod); ++ if (ret < 0) ++ return ret; + + rsnd_src_activation(mod); + +diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c +index 43c5e27dc5c8..7ade6c5ed96f 100644 +--- a/sound/soc/sh/rcar/ssi.c ++++ b/sound/soc/sh/rcar/ssi.c +@@ -480,7 +480,9 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, + + ssi->usrcnt++; + +- rsnd_mod_power_on(mod); ++ ret = rsnd_mod_power_on(mod); ++ if (ret < 0) ++ return ret; + + rsnd_ssi_config_init(mod, io); + +-- +2.35.1 + diff --git a/queue-5.19/asoc-soc-pcm.c-call-__soc_pcm_close-in-soc_pcm_close.patch b/queue-5.19/asoc-soc-pcm.c-call-__soc_pcm_close-in-soc_pcm_close.patch new file mode 100644 index 00000000000..69883790d7c --- /dev/null +++ b/queue-5.19/asoc-soc-pcm.c-call-__soc_pcm_close-in-soc_pcm_close.patch @@ -0,0 +1,55 @@ +From 6453ab08222bbc3fed030a800a0c737d1b1d1bb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 02:35:32 +0000 +Subject: ASoC: soc-pcm.c: call __soc_pcm_close() in soc_pcm_close() + +From: Kuninori Morimoto + +[ Upstream commit 6bbabd28805f36baf6d0f3eb082db032a638f612 ] + +commit b7898396f4bbe16 ("ASoC: soc-pcm: Fix and cleanup DPCM locking") +added __soc_pcm_close() for non-lock version of soc_pcm_close(). +But soc_pcm_close() is not using it. It is no problem, but confusable. + + static int __soc_pcm_close(...) + { +=> return soc_pcm_clean(rtd, substream, 0); + } + + static int soc_pcm_close(...) + { + ... + snd_soc_dpcm_mutex_lock(rtd); +=> soc_pcm_clean(rtd, substream, 0); + snd_soc_dpcm_mutex_unlock(rtd); + return 0; + } + +This patch use it. + +Fixes: b7898396f4bbe16 ("ASoC: soc-pcm: Fix and cleanup DPCM locking") +Cc: Takashi Iwai +Signed-off-by: Kuninori Morimoto +Link: https://lore.kernel.org/r/87czctgg3w.wl-kuninori.morimoto.gx@renesas.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/soc-pcm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c +index 0c1de5624842..6359d00b7bda 100644 +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -723,7 +723,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + + snd_soc_dpcm_mutex_lock(rtd); +- soc_pcm_clean(rtd, substream, 0); ++ __soc_pcm_close(rtd, substream); + snd_soc_dpcm_mutex_unlock(rtd); + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/asoc-sof-add-quirk-to-override-topology-mclk_id.patch b/queue-5.19/asoc-sof-add-quirk-to-override-topology-mclk_id.patch new file mode 100644 index 00000000000..86b24e3e5d3 --- /dev/null +++ b/queue-5.19/asoc-sof-add-quirk-to-override-topology-mclk_id.patch @@ -0,0 +1,105 @@ +From 1a9aeb555bafac7b0c700a881f036502d25d5a19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 13:53:48 +0200 +Subject: ASoC: SOF: add quirk to override topology mclk_id + +From: Pierre-Louis Bossart + +[ Upstream commit d136949dd8e2e309dc2f186507486b71cbe9acdb ] + +Some Intel-based platforms rely on a topology file that hard-codes the +use of MCLK0. This is incorrect in 10% of the cases. Rather than +generating yet another set of topology files, this patch adds a kernel +module parameter to override the topology value. + +In hindsight, we should never have allowed mclks to be specified in +topology, this is a hardware-level information that should not have +been visible in the topology. + +Future patches will try to set this value automagically, e.g. by +parsing the NHLT content. + +Signed-off-by: Pierre-Louis Bossart +Reviewed-by: Kai Vehmanen +Reviewed-by: Bard Liao +Link: https://lore.kernel.org/r/20220919115350.43104-3-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sof/intel/hda.c | 11 +++++++++++ + sound/soc/sof/ipc3-topology.c | 7 +++++++ + sound/soc/sof/sof-priv.h | 4 ++++ + 3 files changed, 22 insertions(+) + +diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c +index 17f2f3a982c3..7d9e62ab9d0e 100644 +--- a/sound/soc/sof/intel/hda.c ++++ b/sound/soc/sof/intel/hda.c +@@ -376,6 +376,10 @@ static int dmic_num_override = -1; + module_param_named(dmic_num, dmic_num_override, int, 0444); + MODULE_PARM_DESC(dmic_num, "SOF HDA DMIC number"); + ++static int mclk_id_override = -1; ++module_param_named(mclk_id, mclk_id_override, int, 0444); ++MODULE_PARM_DESC(mclk_id, "SOF SSP mclk_id"); ++ + #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) + static bool hda_codec_use_common_hdmi = IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI); + module_param_named(use_common_hdmi, hda_codec_use_common_hdmi, bool, 0444); +@@ -1433,6 +1437,13 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) + + sof_pdata->tplg_filename = tplg_filename; + } ++ ++ /* check if mclk_id should be modified from topology defaults */ ++ if (mclk_id_override >= 0) { ++ dev_info(sdev->dev, "Overriding topology with MCLK %d from kernel_parameter\n", mclk_id_override); ++ sdev->mclk_id_override = true; ++ sdev->mclk_id_quirk = mclk_id_override; ++ } + } + + /* +diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c +index e97f50d5bcba..b8ec302bc887 100644 +--- a/sound/soc/sof/ipc3-topology.c ++++ b/sound/soc/sof/ipc3-topology.c +@@ -1233,6 +1233,7 @@ static int sof_link_afe_load(struct snd_soc_component *scomp, struct snd_sof_dai + static int sof_link_ssp_load(struct snd_soc_component *scomp, struct snd_sof_dai_link *slink, + struct sof_ipc_dai_config *config, struct snd_sof_dai *dai) + { ++ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + struct snd_soc_tplg_hw_config *hw_config = slink->hw_configs; + struct sof_dai_private_data *private = dai->private; + u32 size = sizeof(*config); +@@ -1257,6 +1258,12 @@ static int sof_link_ssp_load(struct snd_soc_component *scomp, struct snd_sof_dai + + config[i].hdr.size = size; + ++ if (sdev->mclk_id_override) { ++ dev_dbg(scomp->dev, "tplg: overriding topology mclk_id %d by quirk %d\n", ++ config[i].ssp.mclk_id, sdev->mclk_id_quirk); ++ config[i].ssp.mclk_id = sdev->mclk_id_quirk; ++ } ++ + /* copy differentiating hw configs to ipc structs */ + config[i].ssp.mclk_rate = le32_to_cpu(hw_config[i].mclk_rate); + config[i].ssp.bclk_rate = le32_to_cpu(hw_config[i].bclk_rate); +diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h +index f11f575fd1da..544e5be9d10e 100644 +--- a/sound/soc/sof/sof-priv.h ++++ b/sound/soc/sof/sof-priv.h +@@ -585,6 +585,10 @@ struct snd_sof_dev { + /* to protect the ipc_rx_handler_list and dsp_state_handler_list list */ + struct mutex client_event_handler_mutex; + ++ /* quirks to override topology values */ ++ bool mclk_id_override; ++ u16 mclk_id_quirk; /* same size as in IPC3 definitions */ ++ + void *private; /* core does not touch this */ + }; + +-- +2.35.1 + diff --git a/queue-5.19/asoc-sof-mediatek-mt8195-import-namespace-snd_soc_so.patch b/queue-5.19/asoc-sof-mediatek-mt8195-import-namespace-snd_soc_so.patch new file mode 100644 index 00000000000..3be5cf242b6 --- /dev/null +++ b/queue-5.19/asoc-sof-mediatek-mt8195-import-namespace-snd_soc_so.patch @@ -0,0 +1,34 @@ +From 4b89d9b9356d8b96a65af7ff0f427880bd9149f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 11:27:24 +0200 +Subject: ASoC: SOF: mediatek: mt8195: Import namespace SND_SOC_SOF_MTK_COMMON + +From: AngeloGioacchino Del Regno + +[ Upstream commit 404bec4c8f6c38ae5fa208344f1086d38026e93d ] + +Here we're using function mtk_adsp_dump() from mtk-adsp-common: +explicitly import its namespace. + +Fixes: 3a054f90e955 ("ASoC: SOF: mediatek: Add mt8195 debug dump") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220906092727.37324-3-angelogioacchino.delregno@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sof/mediatek/mt8195/mt8195.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c +index 30111ab23bf5..30ab2274fbf8 100644 +--- a/sound/soc/sof/mediatek/mt8195/mt8195.c ++++ b/sound/soc/sof/mediatek/mt8195/mt8195.c +@@ -634,4 +634,5 @@ static struct platform_driver snd_sof_of_mt8195_driver = { + module_platform_driver(snd_sof_of_mt8195_driver); + + MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA); ++MODULE_IMPORT_NS(SND_SOC_SOF_MTK_COMMON); + MODULE_LICENSE("Dual BSD/GPL"); +-- +2.35.1 + diff --git a/queue-5.19/asoc-sof-pci-change-dmi-match-info-to-support-all-ch.patch b/queue-5.19/asoc-sof-pci-change-dmi-match-info-to-support-all-ch.patch new file mode 100644 index 00000000000..e80f79c8466 --- /dev/null +++ b/queue-5.19/asoc-sof-pci-change-dmi-match-info-to-support-all-ch.patch @@ -0,0 +1,45 @@ +From 4eeb1157e0166f5c8816adc90845c03f653a3de6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 13:44:29 +0200 +Subject: ASoC: SOF: pci: Change DMI match info to support all Chrome platforms + +From: Jairaj Arava + +[ Upstream commit c1c1fc8103f794a10c5c15e3c17879caf4f42c8f ] + +In some Chrome platforms if OEM's use their own string as SYS_VENDOR than +"Google", it leads to firmware load failure from intel/sof/community path. + +Hence, changing SYS_VENDOR to PRODUCT_FAMILY in which "Google" is used +as common prefix and is supported in all Chrome platforms. + +Reviewed-by: Ranjani Sridharan +Reviewed-by: Chao Song +Reviewed-by: Curtis Malainey +Signed-off-by: Jairaj Arava +Signed-off-by: Curtis Malainey +Signed-off-by: Sathyanarayana Nujella +Signed-off-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20220919114429.42700-1-pierre-louis.bossart@linux.intel.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sof/sof-pci-dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c +index d627092b399d..643fd1036d60 100644 +--- a/sound/soc/sof/sof-pci-dev.c ++++ b/sound/soc/sof/sof-pci-dev.c +@@ -138,7 +138,7 @@ static const struct dmi_system_id community_key_platforms[] = { + .ident = "Google Chromebooks", + .callback = chromebook_use_community_key, + .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "Google"), ++ DMI_MATCH(DMI_PRODUCT_FAMILY, "Google"), + } + }, + {}, +-- +2.35.1 + diff --git a/queue-5.19/asoc-stm-fix-pm-disable-depth-imbalance-in-stm32_i2s.patch b/queue-5.19/asoc-stm-fix-pm-disable-depth-imbalance-in-stm32_i2s.patch new file mode 100644 index 00000000000..ed6ad841560 --- /dev/null +++ b/queue-5.19/asoc-stm-fix-pm-disable-depth-imbalance-in-stm32_i2s.patch @@ -0,0 +1,50 @@ +From ea4dfdfe39087f8d2491b7794cc6a1744c24cc96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 22:26:40 +0800 +Subject: ASoC: stm: Fix PM disable depth imbalance in stm32_i2s_probe + +From: Zhang Qilong + +[ Upstream commit 93618e5e05a3ce4aa6750268c5025bdb4cb7dc6e ] + +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 moving +pm_runtime_enable to the endding of stm32_i2s_probe. + +Fixes:32a956a1fadf ("ASoC: stm32: i2s: add pm_runtime support") + +Signed-off-by: Zhang Qilong +Reviewed-by: Olivier Moysan +Link: https://lore.kernel.org/r/20220927142640.64647-1-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/stm/stm32_i2s.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c +index ac5dff4d1677..d9e622f4c422 100644 +--- a/sound/soc/stm/stm32_i2s.c ++++ b/sound/soc/stm/stm32_i2s.c +@@ -1135,8 +1135,6 @@ static int stm32_i2s_probe(struct platform_device *pdev) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap), + "Regmap init error\n"); + +- pm_runtime_enable(&pdev->dev); +- + ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0); + if (ret) + return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n"); +@@ -1179,6 +1177,8 @@ static int stm32_i2s_probe(struct platform_device *pdev) + FIELD_GET(I2S_VERR_MIN_MASK, val)); + } + ++ pm_runtime_enable(&pdev->dev); ++ + return ret; + + error: +-- +2.35.1 + diff --git a/queue-5.19/asoc-stm32-dfsdm-fix-pm-disable-depth-imbalance-in-s.patch b/queue-5.19/asoc-stm32-dfsdm-fix-pm-disable-depth-imbalance-in-s.patch new file mode 100644 index 00000000000..7d95ee533d7 --- /dev/null +++ b/queue-5.19/asoc-stm32-dfsdm-fix-pm-disable-depth-imbalance-in-s.patch @@ -0,0 +1,57 @@ +From b29ae9f8517c860622e36d90004363f2e1217505 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 22:26:00 +0800 +Subject: ASoC: stm32: dfsdm: Fix PM disable depth imbalance in + stm32_adfsdm_probe + +From: Zhang Qilong + +[ Upstream commit b9a0da5b2edcae2a901b85c8cc42efc5bec4bd7b ] + +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 moving +pm_runtime_enable to the endding of stm32_adfsdm_probe. + +Fixes:98e500a12f934 ("ASoC: stm32: dfsdm: add pm_runtime support for audio") + +Signed-off-by: Zhang Qilong +Reviewed-by: Olivier Moysan +Link: https://lore.kernel.org/r/20220927142601.64266-2-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/stm/stm32_adfsdm.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c +index 6ee714542b84..c0f964891b58 100644 +--- a/sound/soc/stm/stm32_adfsdm.c ++++ b/sound/soc/stm/stm32_adfsdm.c +@@ -334,8 +334,6 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + + dev_set_drvdata(&pdev->dev, priv); + +- pm_runtime_enable(&pdev->dev); +- + ret = devm_snd_soc_register_component(&pdev->dev, + &stm32_adfsdm_dai_component, + &priv->dai_drv, 1); +@@ -365,9 +363,13 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) + #endif + + ret = snd_soc_add_component(component, NULL, 0); +- if (ret < 0) ++ if (ret < 0) { + dev_err(&pdev->dev, "%s: Failed to register PCM platform\n", + __func__); ++ return ret; ++ } ++ ++ pm_runtime_enable(&pdev->dev); + + return ret; + } +-- +2.35.1 + diff --git a/queue-5.19/asoc-stm32-spdifrx-fix-pm-disable-depth-imbalance-in.patch b/queue-5.19/asoc-stm32-spdifrx-fix-pm-disable-depth-imbalance-in.patch new file mode 100644 index 00000000000..b538233fc28 --- /dev/null +++ b/queue-5.19/asoc-stm32-spdifrx-fix-pm-disable-depth-imbalance-in.patch @@ -0,0 +1,51 @@ +From d5a691205e087abe536a6bfd4951261cda899a27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 22:26:01 +0800 +Subject: ASoC: stm32: spdifrx: Fix PM disable depth imbalance in + stm32_spdifrx_probe + +From: Zhang Qilong + +[ Upstream commit 0325cc0ac7980e1c7b744aab8df59afab6daeb43 ] + +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 moving +pm_runtime_enable to the endding of stm32_spdifrx_probe. + +Fixes:ac5e3efd55868 ("ASoC: stm32: spdifrx: add pm_runtime support") + +Signed-off-by: Zhang Qilong +Reviewed-by: Olivier Moysan +Link: https://lore.kernel.org/r/20220927142601.64266-3-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/stm/stm32_spdifrx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c +index 6f7882c4fe6a..60be4894e5fd 100644 +--- a/sound/soc/stm/stm32_spdifrx.c ++++ b/sound/soc/stm/stm32_spdifrx.c +@@ -1001,8 +1001,6 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) + udelay(2); + reset_control_deassert(rst); + +- pm_runtime_enable(&pdev->dev); +- + pcm_config = &stm32_spdifrx_pcm_config; + ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); + if (ret) +@@ -1035,6 +1033,8 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) + FIELD_GET(SPDIFRX_VERR_MIN_MASK, ver)); + } + ++ pm_runtime_enable(&pdev->dev); ++ + return ret; + + error: +-- +2.35.1 + diff --git a/queue-5.19/asoc-tas2764-allow-mono-streams.patch b/queue-5.19/asoc-tas2764-allow-mono-streams.patch new file mode 100644 index 00000000000..890f5fb5572 --- /dev/null +++ b/queue-5.19/asoc-tas2764-allow-mono-streams.patch @@ -0,0 +1,43 @@ +From 84663f41ec725ad748be3a469aec81d49788c708 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 16:02:37 +0200 +Subject: ASoC: tas2764: Allow mono streams +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin PoviÅ¡er + +[ Upstream commit 23204d928a27146d13e11c9383632775345ecca8 ] + +The part is a mono speaker amp, but it can do downmix and switch between +left and right channel, so the right channel range is 1 to 2. + +(This mirrors commit bf54d97a835d ("ASoC: tas2770: Allow mono streams") +which was a fix to the tas2770 driver.) + +Fixes: 827ed8a0fa50 ("ASoC: tas2764: Add the driver for the TAS2764") +Signed-off-by: Martin PoviÅ¡er +Link: https://lore.kernel.org/r/20220825140241.53963-2-povik+lin@cutebit.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 4cb788f3e5f7..00df36fb3ede 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -485,7 +485,7 @@ static struct snd_soc_dai_driver tas2764_dai_driver[] = { + .id = 0, + .playback = { + .stream_name = "ASI1 Playback", +- .channels_min = 2, ++ .channels_min = 1, + .channels_max = 2, + .rates = TAS2764_RATES, + .formats = TAS2764_FORMATS, +-- +2.35.1 + diff --git a/queue-5.19/asoc-tas2764-drop-conflicting-set_bias_level-power-s.patch b/queue-5.19/asoc-tas2764-drop-conflicting-set_bias_level-power-s.patch new file mode 100644 index 00000000000..72456292f46 --- /dev/null +++ b/queue-5.19/asoc-tas2764-drop-conflicting-set_bias_level-power-s.patch @@ -0,0 +1,83 @@ +From 599e031d318863a03c10fff0a3ebf7e4829d8441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 16:02:38 +0200 +Subject: ASoC: tas2764: Drop conflicting set_bias_level power setting +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin PoviÅ¡er + +[ Upstream commit 09273f38832406db19a8907a934687cc10660a6b ] + +The driver is setting the PWR_CTRL field in both the set_bias_level +callback and on DAPM events of the DAC widget (and also in the +mute_stream method). Drop the set_bias_level callback altogether as the +power setting it does is in conflict with the other code paths. + +(This mirrors commit c8a6ae3fe1c8 ("ASoC: tas2770: Drop conflicting +set_bias_level power setting") which was a fix to the tas2770 driver.) + +Fixes: 827ed8a0fa50 ("ASoC: tas2764: Add the driver for the TAS2764") +Signed-off-by: Martin PoviÅ¡er +Link: https://lore.kernel.org/r/20220825140241.53963-3-povik+lin@cutebit.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 33 --------------------------------- + 1 file changed, 33 deletions(-) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index 00df36fb3ede..c11406bbe5bc 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -50,38 +50,6 @@ static void tas2764_reset(struct tas2764_priv *tas2764) + usleep_range(1000, 2000); + } + +-static int tas2764_set_bias_level(struct snd_soc_component *component, +- enum snd_soc_bias_level level) +-{ +- struct tas2764_priv *tas2764 = snd_soc_component_get_drvdata(component); +- +- switch (level) { +- case SND_SOC_BIAS_ON: +- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_ACTIVE); +- break; +- case SND_SOC_BIAS_STANDBY: +- case SND_SOC_BIAS_PREPARE: +- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_MUTE); +- break; +- case SND_SOC_BIAS_OFF: +- snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_SHUTDOWN); +- break; +- +- default: +- dev_err(tas2764->dev, +- "wrong power level setting %d\n", level); +- return -EINVAL; +- } +- +- return 0; +-} +- + #ifdef CONFIG_PM + static int tas2764_codec_suspend(struct snd_soc_component *component) + { +@@ -549,7 +517,6 @@ static const struct snd_soc_component_driver soc_component_driver_tas2764 = { + .probe = tas2764_codec_probe, + .suspend = tas2764_codec_suspend, + .resume = tas2764_codec_resume, +- .set_bias_level = tas2764_set_bias_level, + .controls = tas2764_snd_controls, + .num_controls = ARRAY_SIZE(tas2764_snd_controls), + .dapm_widgets = tas2764_dapm_widgets, +-- +2.35.1 + diff --git a/queue-5.19/asoc-tas2764-fix-mute-unmute.patch b/queue-5.19/asoc-tas2764-fix-mute-unmute.patch new file mode 100644 index 00000000000..378c8cbf527 --- /dev/null +++ b/queue-5.19/asoc-tas2764-fix-mute-unmute.patch @@ -0,0 +1,139 @@ +From 83d9741de74bf95851f84ab5dbee63b659344fce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 16:02:39 +0200 +Subject: ASoC: tas2764: Fix mute/unmute +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Martin PoviÅ¡er + +[ Upstream commit f5ad67f13623548e5aff847f89700c178aaf2a98 ] + +Because the PWR_CTRL field is modeled as the power state of the DAC +widget, and at the same time it is used to implement mute/unmute, we +need some additional book-keeping to have the right end result no matter +the sequence of calls. Without this fix, one permanently mutes an +ongoing stream by toggling the associated speaker pin control. + +(This mirrors commit 1e5907bcb3a3 ("ASoC: tas2770: Fix handling of +mute/unmute") which was a fix to the tas2770 driver.) + +Fixes: 827ed8a0fa50 ("ASoC: tas2764: Add the driver for the TAS2764") +Signed-off-by: Martin PoviÅ¡er +Link: https://lore.kernel.org/r/20220825140241.53963-4-povik+lin@cutebit.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2764.c | 57 +++++++++++++++++++++----------------- + 1 file changed, 32 insertions(+), 25 deletions(-) + +diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c +index c11406bbe5bc..7ae7a5249f95 100644 +--- a/sound/soc/codecs/tas2764.c ++++ b/sound/soc/codecs/tas2764.c +@@ -34,6 +34,9 @@ struct tas2764_priv { + + int v_sense_slot; + int i_sense_slot; ++ ++ bool dac_powered; ++ bool unmuted; + }; + + static void tas2764_reset(struct tas2764_priv *tas2764) +@@ -50,6 +53,26 @@ static void tas2764_reset(struct tas2764_priv *tas2764) + usleep_range(1000, 2000); + } + ++static int tas2764_update_pwr_ctrl(struct tas2764_priv *tas2764) ++{ ++ struct snd_soc_component *component = tas2764->component; ++ unsigned int val; ++ int ret; ++ ++ if (tas2764->dac_powered) ++ val = tas2764->unmuted ? ++ TAS2764_PWR_CTRL_ACTIVE : TAS2764_PWR_CTRL_MUTE; ++ else ++ val = TAS2764_PWR_CTRL_SHUTDOWN; ++ ++ ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, ++ TAS2764_PWR_CTRL_MASK, val); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ + #ifdef CONFIG_PM + static int tas2764_codec_suspend(struct snd_soc_component *component) + { +@@ -82,9 +105,7 @@ static int tas2764_codec_resume(struct snd_soc_component *component) + usleep_range(1000, 2000); + } + +- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_ACTIVE); ++ ret = tas2764_update_pwr_ctrl(tas2764); + + if (ret < 0) + return ret; +@@ -118,14 +139,12 @@ static int tas2764_dac_event(struct snd_soc_dapm_widget *w, + + switch (event) { + case SND_SOC_DAPM_POST_PMU: +- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_MUTE); ++ tas2764->dac_powered = true; ++ ret = tas2764_update_pwr_ctrl(tas2764); + break; + case SND_SOC_DAPM_PRE_PMD: +- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_SHUTDOWN); ++ tas2764->dac_powered = false; ++ ret = tas2764_update_pwr_ctrl(tas2764); + break; + default: + dev_err(tas2764->dev, "Unsupported event\n"); +@@ -170,17 +189,11 @@ static const struct snd_soc_dapm_route tas2764_audio_map[] = { + + static int tas2764_mute(struct snd_soc_dai *dai, int mute, int direction) + { +- struct snd_soc_component *component = dai->component; +- int ret; +- +- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- mute ? TAS2764_PWR_CTRL_MUTE : 0); ++ struct tas2764_priv *tas2764 = ++ snd_soc_component_get_drvdata(dai->component); + +- if (ret < 0) +- return ret; +- +- return 0; ++ tas2764->unmuted = !mute; ++ return tas2764_update_pwr_ctrl(tas2764); + } + + static int tas2764_set_bitwidth(struct tas2764_priv *tas2764, int bitwidth) +@@ -494,12 +507,6 @@ static int tas2764_codec_probe(struct snd_soc_component *component) + if (ret < 0) + return ret; + +- ret = snd_soc_component_update_bits(component, TAS2764_PWR_CTRL, +- TAS2764_PWR_CTRL_MASK, +- TAS2764_PWR_CTRL_MUTE); +- if (ret < 0) +- return ret; +- + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/asoc-wm5102-fix-pm-disable-depth-imbalance-in-wm5102.patch b/queue-5.19/asoc-wm5102-fix-pm-disable-depth-imbalance-in-wm5102.patch new file mode 100644 index 00000000000..f13a4980526 --- /dev/null +++ b/queue-5.19/asoc-wm5102-fix-pm-disable-depth-imbalance-in-wm5102.patch @@ -0,0 +1,51 @@ +From 79ee4dbd14c6534fba0e4732aad7bddd6e443301 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:01:15 +0800 +Subject: ASoC: wm5102: Fix PM disable depth imbalance in wm5102_probe + +From: Zhang Qilong + +[ Upstream commit fcbb60820cd3008bb44334a0395e5e57ccb77329 ] + +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 moving +pm_runtime_enable to the endding of wm5102_probe. + +Fixes:93e8791dd34ca ("ASoC: wm5102: Initial driver") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220928160116.125020-4-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wm5102.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c +index b034df47a5ef..e92daeba11f2 100644 +--- a/sound/soc/codecs/wm5102.c ++++ b/sound/soc/codecs/wm5102.c +@@ -2100,9 +2100,6 @@ static int wm5102_probe(struct platform_device *pdev) + regmap_update_bits(arizona->regmap, wm5102_digital_vu[i], + WM5102_DIG_VU, WM5102_DIG_VU); + +- pm_runtime_enable(&pdev->dev); +- pm_runtime_idle(&pdev->dev); +- + ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", wm5102_adsp2_irq, + wm5102); +@@ -2135,6 +2132,9 @@ static int wm5102_probe(struct platform_device *pdev) + goto err_spk_irqs; + } + ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_idle(&pdev->dev); ++ + return ret; + + err_spk_irqs: +-- +2.35.1 + diff --git a/queue-5.19/asoc-wm5110-fix-pm-disable-depth-imbalance-in-wm5110.patch b/queue-5.19/asoc-wm5110-fix-pm-disable-depth-imbalance-in-wm5110.patch new file mode 100644 index 00000000000..456d7b130e1 --- /dev/null +++ b/queue-5.19/asoc-wm5110-fix-pm-disable-depth-imbalance-in-wm5110.patch @@ -0,0 +1,51 @@ +From be2baea3f9587ceae45ad0abc8183a0169cd442a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:01:14 +0800 +Subject: ASoC: wm5110: Fix PM disable depth imbalance in wm5110_probe + +From: Zhang Qilong + +[ Upstream commit 86b46bf1feb83898d89a2b4a8d08d21e9ea277a7 ] + +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 moving +pm_runtime_enable to the endding of wm5110_probe. + +Fixes:5c6af635fd772 ("ASoC: wm5110: Add audio CODEC driver") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220928160116.125020-3-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wm5110.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c +index 4ab7a672f8de..1b0da02b5c79 100644 +--- a/sound/soc/codecs/wm5110.c ++++ b/sound/soc/codecs/wm5110.c +@@ -2458,9 +2458,6 @@ static int wm5110_probe(struct platform_device *pdev) + regmap_update_bits(arizona->regmap, wm5110_digital_vu[i], + WM5110_DIG_VU, WM5110_DIG_VU); + +- pm_runtime_enable(&pdev->dev); +- pm_runtime_idle(&pdev->dev); +- + ret = arizona_request_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, + "ADSP2 Compressed IRQ", wm5110_adsp2_irq, + wm5110); +@@ -2493,6 +2490,9 @@ static int wm5110_probe(struct platform_device *pdev) + goto err_spk_irqs; + } + ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_idle(&pdev->dev); ++ + return ret; + + err_spk_irqs: +-- +2.35.1 + diff --git a/queue-5.19/asoc-wm8997-fix-pm-disable-depth-imbalance-in-wm8997.patch b/queue-5.19/asoc-wm8997-fix-pm-disable-depth-imbalance-in-wm8997.patch new file mode 100644 index 00000000000..19046d95298 --- /dev/null +++ b/queue-5.19/asoc-wm8997-fix-pm-disable-depth-imbalance-in-wm8997.patch @@ -0,0 +1,51 @@ +From 5425b7d9c99030bd3918e01e49844644e7d5bec3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:01:13 +0800 +Subject: ASoC: wm8997: Fix PM disable depth imbalance in wm8997_probe + +From: Zhang Qilong + +[ Upstream commit 41a736ac20602f64773e80f0f5b32cde1830a44a ] + +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 moving +pm_runtime_enable to the endding of wm8997_probe + +Fixes:40843aea5a9bd ("ASoC: wm8997: Initial CODEC driver") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220928160116.125020-2-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wm8997.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c +index 38ef631d1a1f..c8c711e555c0 100644 +--- a/sound/soc/codecs/wm8997.c ++++ b/sound/soc/codecs/wm8997.c +@@ -1162,9 +1162,6 @@ static int wm8997_probe(struct platform_device *pdev) + regmap_update_bits(arizona->regmap, wm8997_digital_vu[i], + WM8997_DIG_VU, WM8997_DIG_VU); + +- pm_runtime_enable(&pdev->dev); +- pm_runtime_idle(&pdev->dev); +- + arizona_init_common(arizona); + + ret = arizona_init_vol_limit(arizona); +@@ -1183,6 +1180,9 @@ static int wm8997_probe(struct platform_device *pdev) + goto err_spk_irqs; + } + ++ pm_runtime_enable(&pdev->dev); ++ pm_runtime_idle(&pdev->dev); ++ + return ret; + + err_spk_irqs: +-- +2.35.1 + diff --git a/queue-5.19/asoc-wm_adsp-handle-optional-legacy-support.patch b/queue-5.19/asoc-wm_adsp-handle-optional-legacy-support.patch new file mode 100644 index 00000000000..2dbdd6a5ed1 --- /dev/null +++ b/queue-5.19/asoc-wm_adsp-handle-optional-legacy-support.patch @@ -0,0 +1,57 @@ +From 50997d1898bae7400f2c276f67094865a12a1321 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 01:05:30 +0300 +Subject: ASoC: wm_adsp: Handle optional legacy support + +From: Cristian Ciocaltea + +[ Upstream commit 35c8ae25c4fdeabf490e005692795a3be17ca5f6 ] + +The tracing capabilities for the speaker protection fw enabled via +commit c55b3e46cb99 ("ASoC: wm_adsp: Add trace caps to speaker +protection FW") are not be available on all platforms, such as the +Valve's Steam Deck which is based on the Halo Core DSP. + +As a consequence, whenever the firmware is loaded, a rather misleading +'Failed to parse legacy: -19' error message is written to the kernel +ring buffer: + +[ 288.977412] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: Firmware version: 3 +[ 288.978002] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: cs35l41-dsp1-spk-prot.wmfw: Fri 02 Apr 2021 21:03:50 W. Europe Daylight Time +[ 289.094065] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: Firmware: 400a4 vendor: 0x2 v0.33.0, 2 algorithms +[ 289.095073] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: 0: ID cd v29.53.0 XM@94 YM@e +[ 289.095665] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: 1: ID f20b v0.0.1 XM@170 YM@0 +[ 289.096275] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: Protection: C:\Users\ocanavan\Desktop\cirrusTune_july2021.bin +[ 291.172383] steamdeck kernel: cs35l41 spi-VLV1776:01: DSP1: Failed to parse legacy: -19 + +Update wm_adsp_buffer_init() to print a more descriptive info message +when wm_adsp_buffer_parse_legacy() returns -ENODEV. + +Fixes: c55b3e46cb99 ("ASoC: wm_adsp: Add trace caps to speaker protection FW") +Signed-off-by: Cristian Ciocaltea +Acked-by: Charles Keepax +Link: https://lore.kernel.org/r/20220825220530.1205141-1-cristian.ciocaltea@collabora.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/wm_adsp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c +index a7784ac15dde..0e2c785d911f 100644 +--- a/sound/soc/codecs/wm_adsp.c ++++ b/sound/soc/codecs/wm_adsp.c +@@ -1617,7 +1617,9 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp) + if (list_empty(&dsp->buffer_list)) { + /* Fall back to legacy support */ + ret = wm_adsp_buffer_parse_legacy(dsp); +- if (ret) ++ if (ret == -ENODEV) ++ adsp_info(dsp, "Legacy support not available\n"); ++ else if (ret) + adsp_warn(dsp, "Failed to parse legacy: %d\n", ret); + } + +-- +2.35.1 + diff --git a/queue-5.19/ata-fix-ata_id_has_devslp.patch b/queue-5.19/ata-fix-ata_id_has_devslp.patch new file mode 100644 index 00000000000..77c0888f9da --- /dev/null +++ b/queue-5.19/ata-fix-ata_id_has_devslp.patch @@ -0,0 +1,57 @@ +From 9b880e56de06faf3bdf33212834d5ce942e068ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 14:28:33 +0200 +Subject: ata: fix ata_id_has_devslp() + +From: Niklas Cassel + +[ Upstream commit 9c6e09a434e1317e09b78b3b69cd384022ec9a03 ] + +ACS-5 section +7.13.6.36 Word 78: Serial ATA features supported +states that: + +If word 76 is not 0000h or FFFFh, word 78 reports the features supported +by the device. If this word is not supported, the word shall be cleared +to zero. + +(This text also exists in really old ACS standards, e.g. ACS-3.) + +Additionally, move the macro to the other ATA_ID_FEATURE_SUPP macros +(which already have this check), thus making it more likely that the +next ATA_ID_FEATURE_SUPP macro that is added will include this check. + +Fixes: 65fe1f0f66a5 ("ahci: implement aggressive SATA device sleep support") +Signed-off-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + include/linux/ata.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/include/linux/ata.h b/include/linux/ata.h +index 868bfd503aee..bc136a43689f 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -566,6 +566,10 @@ struct ata_bmdma_prd { + ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ + ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 2))) ++#define ata_id_has_devslp(id) \ ++ ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ ++ ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ ++ ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))) + #define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10)) + #define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11)) + #define ata_id_u32(id,n) \ +@@ -578,7 +582,6 @@ struct ata_bmdma_prd { + + #define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20) + #define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4)) +-#define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8)) + #define ata_id_has_ncq_autosense(id) \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7)) + +-- +2.35.1 + diff --git a/queue-5.19/ata-fix-ata_id_has_dipm.patch b/queue-5.19/ata-fix-ata_id_has_dipm.patch new file mode 100644 index 00000000000..ef3ef8c8e84 --- /dev/null +++ b/queue-5.19/ata-fix-ata_id_has_dipm.patch @@ -0,0 +1,76 @@ +From 3c50cc2b972556cb5df91585e5a771777c593d75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 14:28:35 +0200 +Subject: ata: fix ata_id_has_dipm() + +From: Niklas Cassel + +[ Upstream commit 630624cb1b5826d753ac8e01a0e42de43d66dedf ] + +ACS-5 section +7.13.6.36 Word 78: Serial ATA features supported +states that: + +If word 76 is not 0000h or FFFFh, word 78 reports the features supported +by the device. If this word is not supported, the word shall be cleared +to zero. + +(This text also exists in really old ACS standards, e.g. ACS-3.) + +The problem with ata_id_has_dipm() is that the while it performs a +check against 0 and 0xffff, it performs the check against +ATA_ID_FEATURE_SUPP (word 78), the same word where the feature bit +is stored. + +Fix this by performing the check against ATA_ID_SATA_CAPABILITY +(word 76), like required by the spec. The feature bit check itself +is of course still performed against ATA_ID_FEATURE_SUPP (word 78). + +Additionally, move the macro to the other ATA_ID_FEATURE_SUPP macros +(which already have this check), thus making it more likely that the +next ATA_ID_FEATURE_SUPP macro that is added will include this check. + +Fixes: ca77329fb713 ("[libata] Link power management infrastructure") +Signed-off-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + include/linux/ata.h | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/include/linux/ata.h b/include/linux/ata.h +index 4845443e0f08..e3050e153a71 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -574,6 +574,10 @@ struct ata_bmdma_prd { + ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ + ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))) ++#define ata_id_has_dipm(id) \ ++ ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ ++ ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ ++ ((id)[ATA_ID_FEATURE_SUPP] & (1 << 3))) + #define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10)) + #define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11)) + #define ata_id_u32(id,n) \ +@@ -597,17 +601,6 @@ static inline bool ata_id_has_hipm(const u16 *id) + return val & (1 << 9); + } + +-static inline bool ata_id_has_dipm(const u16 *id) +-{ +- u16 val = id[ATA_ID_FEATURE_SUPP]; +- +- if (val == 0 || val == 0xffff) +- return false; +- +- return val & (1 << 3); +-} +- +- + static inline bool ata_id_has_fua(const u16 *id) + { + if ((id[ATA_ID_CFSSE] & 0xC000) != 0x4000) +-- +2.35.1 + diff --git a/queue-5.19/ata-fix-ata_id_has_ncq_autosense.patch b/queue-5.19/ata-fix-ata_id_has_ncq_autosense.patch new file mode 100644 index 00000000000..254bfcb232e --- /dev/null +++ b/queue-5.19/ata-fix-ata_id_has_ncq_autosense.patch @@ -0,0 +1,58 @@ +From d02139f429b99c6e9ce3bacae9b6474a64f4a1b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 14:28:34 +0200 +Subject: ata: fix ata_id_has_ncq_autosense() + +From: Niklas Cassel + +[ Upstream commit a5fb6bf853148974dbde092ec1bde553bea5e49f ] + +ACS-5 section +7.13.6.36 Word 78: Serial ATA features supported +states that: + +If word 76 is not 0000h or FFFFh, word 78 reports the features supported +by the device. If this word is not supported, the word shall be cleared +to zero. + +(This text also exists in really old ACS standards, e.g. ACS-3.) + +Additionally, move the macro to the other ATA_ID_FEATURE_SUPP macros +(which already have this check), thus making it more likely that the +next ATA_ID_FEATURE_SUPP macro that is added will include this check. + +Fixes: 5b01e4b9efa0 ("libata: Implement NCQ autosense") +Signed-off-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + include/linux/ata.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/include/linux/ata.h b/include/linux/ata.h +index bc136a43689f..4845443e0f08 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -570,6 +570,10 @@ struct ata_bmdma_prd { + ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ + ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ + ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))) ++#define ata_id_has_ncq_autosense(id) \ ++ ((((id)[ATA_ID_SATA_CAPABILITY] != 0x0000) && \ ++ ((id)[ATA_ID_SATA_CAPABILITY] != 0xffff)) && \ ++ ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))) + #define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10)) + #define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11)) + #define ata_id_u32(id,n) \ +@@ -582,8 +586,6 @@ struct ata_bmdma_prd { + + #define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20) + #define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4)) +-#define ata_id_has_ncq_autosense(id) \ +- ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7)) + + static inline bool ata_id_has_hipm(const u16 *id) + { +-- +2.35.1 + diff --git a/queue-5.19/ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch b/queue-5.19/ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch new file mode 100644 index 00000000000..f32637d2c69 --- /dev/null +++ b/queue-5.19/ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch @@ -0,0 +1,72 @@ +From 4dc68b61bb15300f6e94e8abead12b121e0a5d1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 14:28:32 +0200 +Subject: ata: fix ata_id_sense_reporting_enabled() and + ata_id_has_sense_reporting() + +From: Niklas Cassel + +[ Upstream commit 690aa8c3ae308bc696ec8b1b357b995193927083 ] + +ACS-5 section +7.13.6.41 Words 85..87, 120: Commands and feature sets supported or enabled +states that: + +If bit 15 of word 86 is set to one, bit 14 of word 119 is set to one, +and bit 15 of word 119 is cleared to zero, then word 119 is valid. + +If bit 15 of word 86 is set to one, bit 14 of word 120 is set to one, +and bit 15 of word 120 is cleared to zero, then word 120 is valid. + +(This text also exists in really old ACS standards, e.g. ACS-3.) + +Currently, ata_id_sense_reporting_enabled() and +ata_id_has_sense_reporting() both check bit 15 of word 86, +but neither of them check that bit 14 of word 119 is set to one, +or that bit 15 of word 119 is cleared to zero. + +Additionally, make ata_id_sense_reporting_enabled() return false +if !ata_id_has_sense_reporting(), similar to how e.g. +ata_id_flush_ext_enabled() returns false if !ata_id_has_flush_ext(). + +Fixes: e87fd28cf9a2 ("libata: Implement support for sense data reporting") +Signed-off-by: Niklas Cassel +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + include/linux/ata.h | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/include/linux/ata.h b/include/linux/ata.h +index 21292b5bbb55..868bfd503aee 100644 +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -771,16 +771,21 @@ static inline bool ata_id_has_read_log_dma_ext(const u16 *id) + + static inline bool ata_id_has_sense_reporting(const u16 *id) + { +- if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) ++ if (!(id[ATA_ID_CFS_ENABLE_2] & BIT(15))) ++ return false; ++ if ((id[ATA_ID_COMMAND_SET_3] & (BIT(15) | BIT(14))) != BIT(14)) + return false; +- return id[ATA_ID_COMMAND_SET_3] & (1 << 6); ++ return id[ATA_ID_COMMAND_SET_3] & BIT(6); + } + + static inline bool ata_id_sense_reporting_enabled(const u16 *id) + { +- if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15))) ++ if (!ata_id_has_sense_reporting(id)) ++ return false; ++ /* ata_id_has_sense_reporting() == true, word 86 must have bit 15 set */ ++ if ((id[ATA_ID_COMMAND_SET_4] & (BIT(15) | BIT(14))) != BIT(14)) + return false; +- return id[ATA_ID_COMMAND_SET_4] & (1 << 6); ++ return id[ATA_ID_COMMAND_SET_4] & BIT(6); + } + + /** +-- +2.35.1 + diff --git a/queue-5.19/ata-libahci_platform-sanity-check-the-dt-child-nodes.patch b/queue-5.19/ata-libahci_platform-sanity-check-the-dt-child-nodes.patch new file mode 100644 index 00000000000..065b4d0fa90 --- /dev/null +++ b/queue-5.19/ata-libahci_platform-sanity-check-the-dt-child-nodes.patch @@ -0,0 +1,67 @@ +From e1388d070499d9e64d7724001a7aabfe9e8ee668 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 22:36:06 +0300 +Subject: ata: libahci_platform: Sanity check the DT child nodes number + +From: Serge Semin + +[ Upstream commit 3c132ea6508b34956e5ed88d04936983ec230601 ] + +Having greater than AHCI_MAX_PORTS (32) ports detected isn't that critical +from the further AHCI-platform initialization point of view since +exceeding the ports upper limit will cause allocating more resources than +will be used afterwards. But detecting too many child DT-nodes doesn't +seem right since it's very unlikely to have it on an ordinary platform. In +accordance with the AHCI specification there can't be more than 32 ports +implemented at least due to having the CAP.NP field of 5 bits wide and the +PI register of dword size. Thus if such situation is found the DTB must +have been corrupted and the data read from it shouldn't be reliable. Let's +consider that as an erroneous situation and halt further resources +allocation. + +Note it's logically more correct to have the nports set only after the +initialization value is checked for being sane. So while at it let's make +sure nports is assigned with a correct value. + +Signed-off-by: Serge Semin +Reviewed-by: Hannes Reinecke +Signed-off-by: Damien Le Moal +Signed-off-by: Sasha Levin +--- + drivers/ata/libahci_platform.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c +index 32495ae96567..986f1923a76d 100644 +--- a/drivers/ata/libahci_platform.c ++++ b/drivers/ata/libahci_platform.c +@@ -451,14 +451,24 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, + } + } + +- hpriv->nports = child_nodes = of_get_child_count(dev->of_node); ++ /* ++ * Too many sub-nodes most likely means having something wrong with ++ * the firmware. ++ */ ++ child_nodes = of_get_child_count(dev->of_node); ++ if (child_nodes > AHCI_MAX_PORTS) { ++ rc = -EINVAL; ++ goto err_out; ++ } + + /* + * If no sub-node was found, we still need to set nports to + * one in order to be able to use the + * ahci_platform_[en|dis]able_[phys|regulators] functions. + */ +- if (!child_nodes) ++ if (child_nodes) ++ hpriv->nports = child_nodes; ++ else + hpriv->nports = 1; + + hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL); +-- +2.35.1 + diff --git a/queue-5.19/audit-explicitly-check-audit_context-context-enum-va.patch b/queue-5.19/audit-explicitly-check-audit_context-context-enum-va.patch new file mode 100644 index 00000000000..ac8f4526595 --- /dev/null +++ b/queue-5.19/audit-explicitly-check-audit_context-context-enum-va.patch @@ -0,0 +1,36 @@ +From 4ca9b243f8c9f992dae659a09abfd5db50e3a811 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 15:32:38 -0400 +Subject: audit: explicitly check audit_context->context enum value + +From: Richard Guy Briggs + +[ Upstream commit 3ed66951f952ed8f1a5d03e171722bf2631e8d58 ] + +Be explicit in checking the struct audit_context "context" member enum +value rather than assuming the order of context enum values. + +Fixes: 12c5e81d3fd0 ("audit: prepare audit_context for use in calling contexts beyond syscalls") +Signed-off-by: Richard Guy Briggs +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +--- + kernel/auditsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/auditsc.c b/kernel/auditsc.c +index 0c33e04c293a..65d816cda5df 100644 +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -2094,7 +2094,7 @@ void __audit_syscall_exit(int success, long return_code) + /* run through both filters to ensure we set the filterkey properly */ + audit_filter_syscall(current, context); + audit_filter_inodes(current, context); +- if (context->current_state < AUDIT_STATE_RECORD) ++ if (context->current_state != AUDIT_STATE_RECORD) + goto out; + + audit_log_exit(); +-- +2.35.1 + diff --git a/queue-5.19/audit-free-audit_proctitle-only-on-task-exit.patch b/queue-5.19/audit-free-audit_proctitle-only-on-task-exit.patch new file mode 100644 index 00000000000..3bdecf79d29 --- /dev/null +++ b/queue-5.19/audit-free-audit_proctitle-only-on-task-exit.patch @@ -0,0 +1,45 @@ +From 863774451f69de9853ca6c8d2d31a17a6ef39aef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 15:32:39 -0400 +Subject: audit: free audit_proctitle only on task exit + +From: Richard Guy Briggs + +[ Upstream commit c3f3ea8af44d0c5fba79fe8b198087342d0c7e04 ] + +Since audit_proctitle is generated at syscall exit time, its value is +used immediately and cached for the next syscall. Since this is the +case, then only clear it at task exit time. Otherwise, there is no +point in caching the value OR bearing the overhead of regenerating it. + +Fixes: 12c5e81d3fd0 ("audit: prepare audit_context for use in calling contexts beyond syscalls") +Signed-off-by: Richard Guy Briggs +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +--- + kernel/auditsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/auditsc.c b/kernel/auditsc.c +index 65d816cda5df..73121c0185ce 100644 +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -1016,7 +1016,6 @@ static void audit_reset_context(struct audit_context *ctx) + WARN_ON(!list_empty(&ctx->killed_trees)); + audit_free_module(ctx); + ctx->fds[0] = -1; +- audit_proctitle_free(ctx); + ctx->type = 0; /* reset last for audit_free_*() */ + } + +@@ -1102,6 +1101,7 @@ static inline void audit_free_context(struct audit_context *context) + { + /* resetting is extra work, but it is likely just noise */ + audit_reset_context(context); ++ audit_proctitle_free(context); + free_tree_refs(context); + kfree(context->filterkey); + kfree(context); +-- +2.35.1 + diff --git a/queue-5.19/bcache-fix-set_at_max_writeback_rate-for-multiple-at.patch b/queue-5.19/bcache-fix-set_at_max_writeback_rate-for-multiple-at.patch new file mode 100644 index 00000000000..de4b9458ef0 --- /dev/null +++ b/queue-5.19/bcache-fix-set_at_max_writeback_rate-for-multiple-at.patch @@ -0,0 +1,136 @@ +From 17fc005c425d2c659f61f99ac88a1925f64194ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 00:16:47 +0800 +Subject: bcache: fix set_at_max_writeback_rate() for multiple attached devices + +From: Coly Li + +[ Upstream commit d2d05b88035d2d51a5bb6c5afec88a0880c73df4 ] + +Inside set_at_max_writeback_rate() the calculation in following if() +check is wrong, + if (atomic_inc_return(&c->idle_counter) < + atomic_read(&c->attached_dev_nr) * 6) + +Because each attached backing device has its own writeback thread +running and increasing c->idle_counter, the counter increates much +faster than expected. The correct calculation should be, + (counter / dev_nr) < dev_nr * 6 +which equals to, + counter < dev_nr * dev_nr * 6 + +This patch fixes the above mistake with correct calculation, and helper +routine idle_counter_exceeded() is added to make code be more clear. + +Reported-by: Mingzhe Zou +Signed-off-by: Coly Li +Acked-by: Mingzhe Zou +Link: https://lore.kernel.org/r/20220919161647.81238-6-colyli@suse.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/md/bcache/writeback.c | 73 +++++++++++++++++++++++++---------- + 1 file changed, 52 insertions(+), 21 deletions(-) + +diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c +index 3f0ff3aab6f2..9c227e4a8465 100644 +--- a/drivers/md/bcache/writeback.c ++++ b/drivers/md/bcache/writeback.c +@@ -157,6 +157,53 @@ static void __update_writeback_rate(struct cached_dev *dc) + dc->writeback_rate_target = target; + } + ++static bool idle_counter_exceeded(struct cache_set *c) ++{ ++ int counter, dev_nr; ++ ++ /* ++ * If c->idle_counter is overflow (idel for really long time), ++ * reset as 0 and not set maximum rate this time for code ++ * simplicity. ++ */ ++ counter = atomic_inc_return(&c->idle_counter); ++ if (counter <= 0) { ++ atomic_set(&c->idle_counter, 0); ++ return false; ++ } ++ ++ dev_nr = atomic_read(&c->attached_dev_nr); ++ if (dev_nr == 0) ++ return false; ++ ++ /* ++ * c->idle_counter is increased by writeback thread of all ++ * attached backing devices, in order to represent a rough ++ * time period, counter should be divided by dev_nr. ++ * Otherwise the idle time cannot be larger with more backing ++ * device attached. ++ * The following calculation equals to checking ++ * (counter / dev_nr) < (dev_nr * 6) ++ */ ++ if (counter < (dev_nr * dev_nr * 6)) ++ return false; ++ ++ return true; ++} ++ ++/* ++ * Idle_counter is increased every time when update_writeback_rate() is ++ * called. If all backing devices attached to the same cache set have ++ * identical dc->writeback_rate_update_seconds values, it is about 6 ++ * rounds of update_writeback_rate() on each backing device before ++ * c->at_max_writeback_rate is set to 1, and then max wrteback rate set ++ * to each dc->writeback_rate.rate. ++ * In order to avoid extra locking cost for counting exact dirty cached ++ * devices number, c->attached_dev_nr is used to calculate the idle ++ * throushold. It might be bigger if not all cached device are in write- ++ * back mode, but it still works well with limited extra rounds of ++ * update_writeback_rate(). ++ */ + static bool set_at_max_writeback_rate(struct cache_set *c, + struct cached_dev *dc) + { +@@ -167,21 +214,8 @@ static bool set_at_max_writeback_rate(struct cache_set *c, + /* Don't set max writeback rate if gc is running */ + if (!c->gc_mark_valid) + return false; +- /* +- * Idle_counter is increased everytime when update_writeback_rate() is +- * called. If all backing devices attached to the same cache set have +- * identical dc->writeback_rate_update_seconds values, it is about 6 +- * rounds of update_writeback_rate() on each backing device before +- * c->at_max_writeback_rate is set to 1, and then max wrteback rate set +- * to each dc->writeback_rate.rate. +- * In order to avoid extra locking cost for counting exact dirty cached +- * devices number, c->attached_dev_nr is used to calculate the idle +- * throushold. It might be bigger if not all cached device are in write- +- * back mode, but it still works well with limited extra rounds of +- * update_writeback_rate(). +- */ +- if (atomic_inc_return(&c->idle_counter) < +- atomic_read(&c->attached_dev_nr) * 6) ++ ++ if (!idle_counter_exceeded(c)) + return false; + + if (atomic_read(&c->at_max_writeback_rate) != 1) +@@ -195,13 +229,10 @@ static bool set_at_max_writeback_rate(struct cache_set *c, + dc->writeback_rate_change = 0; + + /* +- * Check c->idle_counter and c->at_max_writeback_rate agagain in case +- * new I/O arrives during before set_at_max_writeback_rate() returns. +- * Then the writeback rate is set to 1, and its new value should be +- * decided via __update_writeback_rate(). ++ * In case new I/O arrives during before ++ * set_at_max_writeback_rate() returns. + */ +- if ((atomic_read(&c->idle_counter) < +- atomic_read(&c->attached_dev_nr) * 6) || ++ if (!idle_counter_exceeded(c) || + !atomic_read(&c->at_max_writeback_rate)) + return false; + +-- +2.35.1 + diff --git a/queue-5.19/blk-mq-use-quiesced-elevator-switch-when-reinitializ.patch b/queue-5.19/blk-mq-use-quiesced-elevator-switch-when-reinitializ.patch new file mode 100644 index 00000000000..f6a0af20229 --- /dev/null +++ b/queue-5.19/blk-mq-use-quiesced-elevator-switch-when-reinitializ.patch @@ -0,0 +1,118 @@ +From 9f098d6ec1b45843e8c1ea417019c52092b8ae14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 08:56:52 -0700 +Subject: blk-mq: use quiesced elevator switch when reinitializing queues + +From: Keith Busch + +[ Upstream commit 8237c01f1696bc53c470493bf1fe092a107648a6 ] + +The hctx's run_work may be racing with the elevator switch when +reinitializing hardware queues. The queue is merely frozen in this +context, but that only prevents requests from allocating and doesn't +stop the hctx work from running. The work may get an elevator pointer +that's being torn down, and can result in use-after-free errors and +kernel panics (example below). Use the quiesced elevator switch instead, +and make the previous one static since it is now only used locally. + + nvme nvme0: resetting controller + nvme nvme0: 32/0/0 default/read/poll queues + BUG: kernel NULL pointer dereference, address: 0000000000000008 + #PF: supervisor read access in kernel mode + #PF: error_code(0x0000) - not-present page + PGD 80000020c8861067 P4D 80000020c8861067 PUD 250f8c8067 PMD 0 + Oops: 0000 [#1] SMP PTI + Workqueue: kblockd blk_mq_run_work_fn + RIP: 0010:kyber_has_work+0x29/0x70 + +... + + Call Trace: + __blk_mq_do_dispatch_sched+0x83/0x2b0 + __blk_mq_sched_dispatch_requests+0x12e/0x170 + blk_mq_sched_dispatch_requests+0x30/0x60 + __blk_mq_run_hw_queue+0x2b/0x50 + process_one_work+0x1ef/0x380 + worker_thread+0x2d/0x3e0 + +Signed-off-by: Keith Busch +Reviewed-by: Ming Lei +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20220927155652.3260724-1-kbusch@fb.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-mq.c | 6 +++--- + block/blk.h | 3 +-- + block/elevator.c | 4 ++-- + 3 files changed, 6 insertions(+), 7 deletions(-) + +diff --git a/block/blk-mq.c b/block/blk-mq.c +index 69d0a58f9e2f..302b8d92deef 100644 +--- a/block/blk-mq.c ++++ b/block/blk-mq.c +@@ -4481,14 +4481,14 @@ static bool blk_mq_elv_switch_none(struct list_head *head, + list_add(&qe->node, head); + + /* +- * After elevator_switch_mq, the previous elevator_queue will be ++ * After elevator_switch, the previous elevator_queue will be + * released by elevator_release. The reference of the io scheduler + * module get by elevator_get will also be put. So we need to get + * a reference of the io scheduler module here to prevent it to be + * removed. + */ + __module_get(qe->type->elevator_owner); +- elevator_switch_mq(q, NULL); ++ elevator_switch(q, NULL); + mutex_unlock(&q->sysfs_lock); + + return true; +@@ -4520,7 +4520,7 @@ static void blk_mq_elv_switch_back(struct list_head *head, + kfree(qe); + + mutex_lock(&q->sysfs_lock); +- elevator_switch_mq(q, t); ++ elevator_switch(q, t); + mutex_unlock(&q->sysfs_lock); + } + +diff --git a/block/blk.h b/block/blk.h +index 0d6668663ab5..af2aaea23966 100644 +--- a/block/blk.h ++++ b/block/blk.h +@@ -260,8 +260,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list, + + void blk_insert_flush(struct request *rq); + +-int elevator_switch_mq(struct request_queue *q, +- struct elevator_type *new_e); ++int elevator_switch(struct request_queue *q, struct elevator_type *new_e); + void elevator_exit(struct request_queue *q); + int elv_register_queue(struct request_queue *q, bool uevent); + void elv_unregister_queue(struct request_queue *q); +diff --git a/block/elevator.c b/block/elevator.c +index c319765892bb..bd71f0fc4e4b 100644 +--- a/block/elevator.c ++++ b/block/elevator.c +@@ -588,7 +588,7 @@ void elv_unregister(struct elevator_type *e) + } + EXPORT_SYMBOL_GPL(elv_unregister); + +-int elevator_switch_mq(struct request_queue *q, ++static int elevator_switch_mq(struct request_queue *q, + struct elevator_type *new_e) + { + int ret; +@@ -723,7 +723,7 @@ void elevator_init_mq(struct request_queue *q) + * need for the new one. this way we have a chance of going back to the old + * one, if the new one fails init for some reason. + */ +-static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) ++int elevator_switch(struct request_queue *q, struct elevator_type *new_e) + { + int err; + +-- +2.35.1 + diff --git a/queue-5.19/blk-throttle-prevent-overflow-while-calculating-wait.patch b/queue-5.19/blk-throttle-prevent-overflow-while-calculating-wait.patch new file mode 100644 index 00000000000..9169b7c1505 --- /dev/null +++ b/queue-5.19/blk-throttle-prevent-overflow-while-calculating-wait.patch @@ -0,0 +1,51 @@ +From 10f00f7a50d30b0b872d2b52d44032ace76e07b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 10:22:38 +0800 +Subject: blk-throttle: prevent overflow while calculating wait time + +From: Yu Kuai + +[ Upstream commit 8d6bbaada2e0a65f9012ac4c2506460160e7237a ] + +There is a problem found by code review in tg_with_in_bps_limit() that +'bps_limit * jiffy_elapsed_rnd' might overflow. Fix the problem by +calling mul_u64_u64_div_u64() instead. + +Signed-off-by: Yu Kuai +Acked-by: Tejun Heo +Link: https://lore.kernel.org/r/20220829022240.3348319-3-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-throttle.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/block/blk-throttle.c b/block/blk-throttle.c +index 387783980024..acdd85a07f92 100644 +--- a/block/blk-throttle.c ++++ b/block/blk-throttle.c +@@ -806,7 +806,7 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio, + u64 bps_limit, unsigned long *wait) + { + bool rw = bio_data_dir(bio); +- u64 bytes_allowed, extra_bytes, tmp; ++ u64 bytes_allowed, extra_bytes; + unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd; + unsigned int bio_size = throtl_bio_data_size(bio); + +@@ -824,10 +824,8 @@ static bool tg_with_in_bps_limit(struct throtl_grp *tg, struct bio *bio, + jiffy_elapsed_rnd = tg->td->throtl_slice; + + jiffy_elapsed_rnd = roundup(jiffy_elapsed_rnd, tg->td->throtl_slice); +- +- tmp = bps_limit * jiffy_elapsed_rnd; +- do_div(tmp, HZ); +- bytes_allowed = tmp; ++ bytes_allowed = mul_u64_u64_div_u64(bps_limit, (u64)jiffy_elapsed_rnd, ++ (u64)HZ); + + if (tg->bytes_disp[rw] + bio_size <= bytes_allowed) { + if (wait) +-- +2.35.1 + diff --git a/queue-5.19/block-fix-the-enum-blk_eh_timer_return-documentation.patch b/queue-5.19/block-fix-the-enum-blk_eh_timer_return-documentation.patch new file mode 100644 index 00000000000..3b11d460026 --- /dev/null +++ b/queue-5.19/block-fix-the-enum-blk_eh_timer_return-documentation.patch @@ -0,0 +1,55 @@ +From 5c96542e731ab35867bd905c8e78a7d80304feab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 13:06:26 -0700 +Subject: block: Fix the enum blk_eh_timer_return documentation + +From: Bart Van Assche + +[ Upstream commit b2bed51a5261f4266ecb857bba680a7f668d3ddf ] + +The documentation of the blk_eh_timer_return enumeration values does not +reflect correctly how e.g. the SCSI core uses these values. Fix the +documentation. + +Cc: Christoph Hellwig +Cc: Ming Lei +Cc: Hannes Reinecke +Cc: Damien Le Moal +Cc: Johannes Thumshirn +Fixes: 88b0cfad2888 ("block: document the blk_eh_timer_return values") +Signed-off-by: Bart Van Assche +Reviewed-by: Johannes Thumshirn +Reviewed-by: Damien Le Moal +Link: https://lore.kernel.org/r/20220920200626.3422296-1-bvanassche@acm.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + include/linux/blk-mq.h | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h +index 0fd96e92c6c6..681ee69c85db 100644 +--- a/include/linux/blk-mq.h ++++ b/include/linux/blk-mq.h +@@ -265,9 +265,16 @@ static inline void rq_list_move(struct request **src, struct request **dst, + rq_list_add(dst, rq); + } + ++/** ++ * enum blk_eh_timer_return - How the timeout handler should proceed ++ * @BLK_EH_DONE: The block driver completed the command or will complete it at ++ * a later time. ++ * @BLK_EH_RESET_TIMER: Reset the request timer and continue waiting for the ++ * request to complete. ++ */ + enum blk_eh_timer_return { +- BLK_EH_DONE, /* drivers has completed the command */ +- BLK_EH_RESET_TIMER, /* reset timer and try again */ ++ BLK_EH_DONE, ++ BLK_EH_RESET_TIMER, + }; + + #define BLK_TAG_ALLOC_FIFO 0 /* allocate starting from 0 */ +-- +2.35.1 + diff --git a/queue-5.19/block-replace-blk_queue_nowait-with-bdev_nowait.patch b/queue-5.19/block-replace-blk_queue_nowait-with-bdev_nowait.patch new file mode 100644 index 00000000000..c6be6094115 --- /dev/null +++ b/queue-5.19/block-replace-blk_queue_nowait-with-bdev_nowait.patch @@ -0,0 +1,116 @@ +From f4d158f7c6ee4371a447a0c2c515a6b049c7fac0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 09:58:15 +0200 +Subject: block: replace blk_queue_nowait with bdev_nowait + +From: Christoph Hellwig + +[ Upstream commit 568ec936bf1384fc15873908c96a9aeb62536edb ] + +Replace blk_queue_nowait with a bdev_nowait helpers that takes the +block_device given that the I/O submission path should not have to +look into the request_queue. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Pankaj Raghav +Link: https://lore.kernel.org/r/20220927075815.269694-1-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-core.c | 2 +- + drivers/md/dm-table.c | 4 +--- + drivers/md/md.c | 4 ++-- + include/linux/blkdev.h | 6 +++++- + io_uring/io_uring.c | 2 +- + 5 files changed, 10 insertions(+), 8 deletions(-) + +diff --git a/block/blk-core.c b/block/blk-core.c +index 7743c68177e8..5970c47ae86f 100644 +--- a/block/blk-core.c ++++ b/block/blk-core.c +@@ -727,7 +727,7 @@ void submit_bio_noacct(struct bio *bio) + * For a REQ_NOWAIT based request, return -EOPNOTSUPP + * if queue does not support NOWAIT. + */ +- if ((bio->bi_opf & REQ_NOWAIT) && !blk_queue_nowait(q)) ++ if ((bio->bi_opf & REQ_NOWAIT) && !bdev_nowait(bdev)) + goto not_supported; + + if (should_fail_bio(bio)) +diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c +index bd539afbfe88..1f73ce6ac925 100644 +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -1869,9 +1869,7 @@ static bool dm_table_supports_write_zeroes(struct dm_table *t) + static int device_not_nowait_capable(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) + { +- struct request_queue *q = bdev_get_queue(dev->bdev); +- +- return !blk_queue_nowait(q); ++ return !bdev_nowait(dev->bdev); + } + + static bool dm_table_supports_nowait(struct dm_table *t) +diff --git a/drivers/md/md.c b/drivers/md/md.c +index 25d18b67a162..cb8eddcd018e 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -5852,7 +5852,7 @@ int md_run(struct mddev *mddev) + } + } + sysfs_notify_dirent_safe(rdev->sysfs_state); +- nowait = nowait && blk_queue_nowait(bdev_get_queue(rdev->bdev)); ++ nowait = nowait && bdev_nowait(rdev->bdev); + } + + if (!bioset_initialized(&mddev->bio_set)) { +@@ -6989,7 +6989,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev) + * If the new disk does not support REQ_NOWAIT, + * disable on the whole MD. + */ +- if (!blk_queue_nowait(bdev_get_queue(rdev->bdev))) { ++ if (!bdev_nowait(rdev->bdev)) { + pr_info("%s: Disabling nowait because %pg does not support nowait\n", + mdname(mddev), rdev->bdev); + blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, mddev->queue); +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index 83eb8869a8c9..a49ea5e19a9b 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -614,7 +614,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q); + #define blk_queue_quiesced(q) test_bit(QUEUE_FLAG_QUIESCED, &(q)->queue_flags) + #define blk_queue_pm_only(q) atomic_read(&(q)->pm_only) + #define blk_queue_registered(q) test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags) +-#define blk_queue_nowait(q) test_bit(QUEUE_FLAG_NOWAIT, &(q)->queue_flags) + #define blk_queue_sq_sched(q) test_bit(QUEUE_FLAG_SQ_SCHED, &(q)->queue_flags) + + extern void blk_set_pm_only(struct request_queue *q); +@@ -1314,6 +1313,11 @@ static inline bool bdev_fua(struct block_device *bdev) + return test_bit(QUEUE_FLAG_FUA, &bdev_get_queue(bdev)->queue_flags); + } + ++static inline bool bdev_nowait(struct block_device *bdev) ++{ ++ return test_bit(QUEUE_FLAG_NOWAIT, &bdev_get_queue(bdev)->queue_flags); ++} ++ + static inline enum blk_zoned_model bdev_zoned_model(struct block_device *bdev) + { + struct request_queue *q = bdev_get_queue(bdev); +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 096b6d14f40d..81ca3e3ea8de 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -3348,7 +3348,7 @@ static void io_iopoll_req_issued(struct io_kiocb *req, unsigned int issue_flags) + + static bool io_bdev_nowait(struct block_device *bdev) + { +- return !bdev || blk_queue_nowait(bdev_get_queue(bdev)); ++ return !bdev || bdev_nowait(bdev); + } + + /* +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-btintel-mark-intel-controller-to-support-l.patch b/queue-5.19/bluetooth-btintel-mark-intel-controller-to-support-l.patch new file mode 100644 index 00000000000..ddd1a7f76e2 --- /dev/null +++ b/queue-5.19/bluetooth-btintel-mark-intel-controller-to-support-l.patch @@ -0,0 +1,73 @@ +From 4e3383871787bc1d96974a0522afb97cec5250d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 12:49:45 +0530 +Subject: Bluetooth: btintel: Mark Intel controller to support LE_STATES quirk + +From: Kiran K + +[ Upstream commit dd0a1794f4334ddbf9b7c5e7d642aaffff38c69b ] + +HarrrisonPeak, CyclonePeak, SnowFieldPeak and SandyPeak controllers +are marked to support HCI_QUIRK_LE_STATES. + +Signed-off-by: Kiran K +Signed-off-by: Chethan T N +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btintel.c | 17 ++++++++--------- + 1 file changed, 8 insertions(+), 9 deletions(-) + +diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c +index 818681c89db8..d44a96667517 100644 +--- a/drivers/bluetooth/btintel.c ++++ b/drivers/bluetooth/btintel.c +@@ -2439,15 +2439,20 @@ static int btintel_setup_combined(struct hci_dev *hdev) + INTEL_ROM_LEGACY_NO_WBS_SUPPORT)) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + &hdev->quirks); ++ if (ver.hw_variant == 0x08 && ver.fw_variant == 0x22) ++ set_bit(HCI_QUIRK_VALID_LE_STATES, ++ &hdev->quirks); + + err = btintel_legacy_rom_setup(hdev, &ver); + break; + case 0x0b: /* SfP */ +- case 0x0c: /* WsP */ + case 0x11: /* JfP */ + case 0x12: /* ThP */ + case 0x13: /* HrP */ + case 0x14: /* CcP */ ++ set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ fallthrough; ++ case 0x0c: /* WsP */ + /* Apply the device specific HCI quirks + * + * All Legacy bootloader devices support WBS +@@ -2455,11 +2460,6 @@ static int btintel_setup_combined(struct hci_dev *hdev) + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, + &hdev->quirks); + +- /* Valid LE States quirk for JfP/ThP familiy */ +- if (ver.hw_variant == 0x11 || ver.hw_variant == 0x12) +- set_bit(HCI_QUIRK_VALID_LE_STATES, +- &hdev->quirks); +- + /* Setup MSFT Extension support */ + btintel_set_msft_opcode(hdev, ver.hw_variant); + +@@ -2530,9 +2530,8 @@ static int btintel_setup_combined(struct hci_dev *hdev) + */ + set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks); + +- /* Valid LE States quirk for JfP/ThP familiy */ +- if (ver.hw_variant == 0x11 || ver.hw_variant == 0x12) +- set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); ++ /* Set Valid LE States quirk */ ++ set_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks); + + /* Setup MSFT Extension support */ + btintel_set_msft_opcode(hdev, ver.hw_variant); +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-btusb-mediatek-fix-wmt-failure-during-runt.patch b/queue-5.19/bluetooth-btusb-mediatek-fix-wmt-failure-during-runt.patch new file mode 100644 index 00000000000..485929c8c82 --- /dev/null +++ b/queue-5.19/bluetooth-btusb-mediatek-fix-wmt-failure-during-runt.patch @@ -0,0 +1,62 @@ +From aba0fb2c77e6b0a5667fb7fc7adf636a83156f40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 08:49:07 +0800 +Subject: Bluetooth: btusb: mediatek: fix WMT failure during runtime suspend + +From: Sean Wang + +[ Upstream commit fd3f106677bac70437dc12e76c827294ed495a44 ] + +WMT cmd/event doesn't follow up the generic HCI cmd/event handling, it +needs constantly polling control pipe until the host received the WMT +event, thus, we should require to specifically acquire PM counter on the +USB to prevent the interface from entering auto suspended while WMT +cmd/event in progress. + +Fixes: a1c49c434e15 ("Bluetooth: btusb: Add protocol support for MediaTek MT7668U USB devices") +Co-developed-by: Jing Cai +Signed-off-by: Jing Cai +Signed-off-by: Sean Wang +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index aaba2d737178..6a320ece3276 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2451,15 +2451,29 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, + + set_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); + ++ /* WMT cmd/event doesn't follow up the generic HCI cmd/event handling, ++ * it needs constantly polling control pipe until the host received the ++ * WMT event, thus, we should require to specifically acquire PM counter ++ * on the USB to prevent the interface from entering auto suspended ++ * while WMT cmd/event in progress. ++ */ ++ err = usb_autopm_get_interface(data->intf); ++ if (err < 0) ++ goto err_free_wc; ++ + err = __hci_cmd_send(hdev, 0xfc6f, hlen, wc); + + if (err < 0) { + clear_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags); ++ usb_autopm_put_interface(data->intf); + goto err_free_wc; + } + + /* Submit control IN URB on demand to process the WMT event */ + err = btusb_mtk_submit_wmt_recv_urb(hdev); ++ ++ usb_autopm_put_interface(data->intf); ++ + if (err < 0) + goto err_free_wc; + +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-hci_-ldisc-serdev-check-percpu_init_rwsem-.patch b/queue-5.19/bluetooth-hci_-ldisc-serdev-check-percpu_init_rwsem-.patch new file mode 100644 index 00000000000..91917d5f2ad --- /dev/null +++ b/queue-5.19/bluetooth-hci_-ldisc-serdev-check-percpu_init_rwsem-.patch @@ -0,0 +1,93 @@ +From 7982c9b100cbdc73dbe4bdd9981abb4877fdae97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 23:58:12 +0900 +Subject: Bluetooth: hci_{ldisc,serdev}: check percpu_init_rwsem() failure + +From: Tetsuo Handa + +[ Upstream commit 3124d320c22f3f4388d9ac5c8f37eaad0cefd6b1 ] + +syzbot is reporting NULL pointer dereference at hci_uart_tty_close() [1], +for rcu_sync_enter() is called without rcu_sync_init() due to +hci_uart_tty_open() ignoring percpu_init_rwsem() failure. + +While we are at it, fix that hci_uart_register_device() ignores +percpu_init_rwsem() failure and hci_uart_unregister_device() does not +call percpu_free_rwsem(). + +Link: https://syzkaller.appspot.com/bug?extid=576dfca25381fb6fbc5f [1] +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Fixes: 67d2f8781b9f00d1 ("Bluetooth: hci_ldisc: Allow sleeping while proto locks are held.") +Fixes: d73e172816652772 ("Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/hci_ldisc.c | 7 +++++-- + drivers/bluetooth/hci_serdev.c | 10 +++++++--- + 2 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c +index f537673ede17..865112e96ff9 100644 +--- a/drivers/bluetooth/hci_ldisc.c ++++ b/drivers/bluetooth/hci_ldisc.c +@@ -493,6 +493,11 @@ static int hci_uart_tty_open(struct tty_struct *tty) + BT_ERR("Can't allocate control structure"); + return -ENFILE; + } ++ if (percpu_init_rwsem(&hu->proto_lock)) { ++ BT_ERR("Can't allocate semaphore structure"); ++ kfree(hu); ++ return -ENOMEM; ++ } + + tty->disc_data = hu; + hu->tty = tty; +@@ -505,8 +510,6 @@ static int hci_uart_tty_open(struct tty_struct *tty) + INIT_WORK(&hu->init_ready, hci_uart_init_work); + INIT_WORK(&hu->write_work, hci_uart_write_work); + +- percpu_init_rwsem(&hu->proto_lock); +- + /* Flush any pending characters in the driver */ + tty_driver_flush_buffer(tty); + +diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c +index c0e5f42ec6b7..f16fd79bc02b 100644 +--- a/drivers/bluetooth/hci_serdev.c ++++ b/drivers/bluetooth/hci_serdev.c +@@ -310,11 +310,12 @@ int hci_uart_register_device(struct hci_uart *hu, + + serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); + ++ if (percpu_init_rwsem(&hu->proto_lock)) ++ return -ENOMEM; ++ + err = serdev_device_open(hu->serdev); + if (err) +- return err; +- +- percpu_init_rwsem(&hu->proto_lock); ++ goto err_rwsem; + + err = p->open(hu); + if (err) +@@ -389,6 +390,8 @@ int hci_uart_register_device(struct hci_uart *hu, + p->close(hu); + err_open: + serdev_device_close(hu->serdev); ++err_rwsem: ++ percpu_free_rwsem(&hu->proto_lock); + return err; + } + EXPORT_SYMBOL_GPL(hci_uart_register_device); +@@ -410,5 +413,6 @@ void hci_uart_unregister_device(struct hci_uart *hu) + clear_bit(HCI_UART_PROTO_READY, &hu->flags); + serdev_device_close(hu->serdev); + } ++ percpu_free_rwsem(&hu->proto_lock); + } + EXPORT_SYMBOL_GPL(hci_uart_unregister_device); +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-hci_core-fix-not-handling-link-timeouts-pr.patch b/queue-5.19/bluetooth-hci_core-fix-not-handling-link-timeouts-pr.patch new file mode 100644 index 00000000000..5d9918ce752 --- /dev/null +++ b/queue-5.19/bluetooth-hci_core-fix-not-handling-link-timeouts-pr.patch @@ -0,0 +1,104 @@ +From 9d0880c1eadf010cd7f21b699b3a37d78894be83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 15:44:42 -0700 +Subject: Bluetooth: hci_core: Fix not handling link timeouts propertly + +From: Luiz Augusto von Dentz + +[ Upstream commit 116523c8fac05d1d26f748fee7919a4ec5df67ea ] + +Change that introduced the use of __check_timeout did not account for +link types properly, it always assumes ACL_LINK is used thus causing +hdev->acl_last_tx to be used even in case of LE_LINK and then again +uses ACL_LINK with hci_link_tx_to. + +To fix this __check_timeout now takes the link type as parameter and +then procedure to use the right last_tx based on the link type and pass +it to hci_link_tx_to. + +Fixes: 1b1d29e51499 ("Bluetooth: Make use of __check_timeout on hci_sched_le") +Signed-off-by: Luiz Augusto von Dentz +Tested-by: David Beinder +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_core.c | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 48029a390c65..8ecc0a18df76 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -3370,15 +3370,27 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) + return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len); + } + +-static void __check_timeout(struct hci_dev *hdev, unsigned int cnt) ++static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type) + { +- if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { +- /* ACL tx timeout must be longer than maximum +- * link supervision timeout (40.9 seconds) */ +- if (!cnt && time_after(jiffies, hdev->acl_last_tx + +- HCI_ACL_TX_TIMEOUT)) +- hci_link_tx_to(hdev, ACL_LINK); ++ unsigned long last_tx; ++ ++ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) ++ return; ++ ++ switch (type) { ++ case LE_LINK: ++ last_tx = hdev->le_last_tx; ++ break; ++ default: ++ last_tx = hdev->acl_last_tx; ++ break; + } ++ ++ /* tx timeout must be longer than maximum link supervision timeout ++ * (40.9 seconds) ++ */ ++ if (!cnt && time_after(jiffies, last_tx + HCI_ACL_TX_TIMEOUT)) ++ hci_link_tx_to(hdev, type); + } + + /* Schedule SCO */ +@@ -3436,7 +3448,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) + struct sk_buff *skb; + int quote; + +- __check_timeout(hdev, cnt); ++ __check_timeout(hdev, cnt, ACL_LINK); + + while (hdev->acl_cnt && + (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { +@@ -3479,8 +3491,6 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) + int quote; + u8 type; + +- __check_timeout(hdev, cnt); +- + BT_DBG("%s", hdev->name); + + if (hdev->dev_type == HCI_AMP) +@@ -3488,6 +3498,8 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) + else + type = ACL_LINK; + ++ __check_timeout(hdev, cnt, type); ++ + while (hdev->block_cnt > 0 && + (chan = hci_chan_sent(hdev, type, "e))) { + u32 priority = (skb_peek(&chan->data_q))->priority; +@@ -3561,7 +3573,7 @@ static void hci_sched_le(struct hci_dev *hdev) + + cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt; + +- __check_timeout(hdev, cnt); ++ __check_timeout(hdev, cnt, LE_LINK); + + tmp = cnt; + while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) { +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-hci_sync-fix-not-indicating-power-state.patch b/queue-5.19/bluetooth-hci_sync-fix-not-indicating-power-state.patch new file mode 100644 index 00000000000..b443c333ec4 --- /dev/null +++ b/queue-5.19/bluetooth-hci_sync-fix-not-indicating-power-state.patch @@ -0,0 +1,37 @@ +From 25a48fc254a7f0c49d2462f5a43932092bafa141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 13:12:30 -0700 +Subject: Bluetooth: hci_sync: Fix not indicating power state + +From: Luiz Augusto von Dentz + +[ Upstream commit 6abf0dae8c3c927f54e62c46faf8aba580ba0d04 ] + +When setting power state using legacy/non-mgmt API +(e.g hcitool hci0 up) the likes of mgmt_set_powered_complete won't be +called causing clients of the MGMT API to not be notified of the change +of the state. + +Fixes: cf75ad8b41d2 ("Bluetooth: hci_sync: Convert MGMT_SET_POWERED") +Signed-off-by: Luiz Augusto von Dentz +Tested-by: Tedd Ho-Jeong An +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 3b4cee67bbd6..a7c0cd2fabfb 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -4033,6 +4033,7 @@ int hci_dev_open_sync(struct hci_dev *hdev) + hci_dev_test_flag(hdev, HCI_MGMT) && + hdev->dev_type == HCI_PRIMARY) { + ret = hci_powered_update_sync(hdev); ++ mgmt_power_on(hdev, ret); + } + } else { + /* Init failed, cleanup */ +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-hci_sysfs-fix-attempting-to-call-device_ad.patch b/queue-5.19/bluetooth-hci_sysfs-fix-attempting-to-call-device_ad.patch new file mode 100644 index 00000000000..acb44773050 --- /dev/null +++ b/queue-5.19/bluetooth-hci_sysfs-fix-attempting-to-call-device_ad.patch @@ -0,0 +1,67 @@ +From a79bdb327b0d1def2719de60881fff8703c33118 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 10:56:59 -0700 +Subject: Bluetooth: hci_sysfs: Fix attempting to call device_add multiple + times + +From: Luiz Augusto von Dentz + +[ Upstream commit 448a496f760664d3e2e79466aa1787e6abc922b5 ] + +device_add shall not be called multiple times as stated in its +documentation: + + 'Do not call this routine or device_register() more than once for + any device structure' + +Syzkaller reports a bug as follows [1]: +------------[ cut here ]------------ +kernel BUG at lib/list_debug.c:33! +invalid opcode: 0000 [#1] PREEMPT SMP KASAN +[...] +Call Trace: + + __list_add include/linux/list.h:69 [inline] + list_add_tail include/linux/list.h:102 [inline] + kobj_kset_join lib/kobject.c:164 [inline] + kobject_add_internal+0x18f/0x8f0 lib/kobject.c:214 + kobject_add_varg lib/kobject.c:358 [inline] + kobject_add+0x150/0x1c0 lib/kobject.c:410 + device_add+0x368/0x1e90 drivers/base/core.c:3452 + hci_conn_add_sysfs+0x9b/0x1b0 net/bluetooth/hci_sysfs.c:53 + hci_le_cis_estabilished_evt+0x57c/0xae0 net/bluetooth/hci_event.c:6799 + hci_le_meta_evt+0x2b8/0x510 net/bluetooth/hci_event.c:7110 + hci_event_func net/bluetooth/hci_event.c:7440 [inline] + hci_event_packet+0x63d/0xfd0 net/bluetooth/hci_event.c:7495 + hci_rx_work+0xae7/0x1230 net/bluetooth/hci_core.c:4007 + process_one_work+0x991/0x1610 kernel/workqueue.c:2289 + worker_thread+0x665/0x1080 kernel/workqueue.c:2436 + kthread+0x2e4/0x3a0 kernel/kthread.c:376 + ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306 + + +Link: https://syzkaller.appspot.com/bug?id=da3246e2d33afdb92d66bc166a0934c5b146404a +Signed-off-by: Luiz Augusto von Dentz +Tested-by: Hawkins Jiawei +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sysfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c +index 4e3e0451b08c..08542dfc2dc5 100644 +--- a/net/bluetooth/hci_sysfs.c ++++ b/net/bluetooth/hci_sysfs.c +@@ -48,6 +48,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn) + + BT_DBG("conn %p", conn); + ++ if (device_is_registered(&conn->dev)) ++ return; ++ + dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle); + + if (device_add(&conn->dev) < 0) { +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-l2cap-fix-user-after-free.patch b/queue-5.19/bluetooth-l2cap-fix-user-after-free.patch new file mode 100644 index 00000000000..5a486b3e5c6 --- /dev/null +++ b/queue-5.19/bluetooth-l2cap-fix-user-after-free.patch @@ -0,0 +1,61 @@ +From aefaf29ce30c90047927768e338e7b7c3bec5b57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 13:27:13 -0700 +Subject: Bluetooth: L2CAP: Fix user-after-free + +From: Luiz Augusto von Dentz + +[ Upstream commit 35fcbc4243aad7e7d020b7c1dfb14bb888b20a4f ] + +This uses l2cap_chan_hold_unless_zero() after calling +__l2cap_get_chan_blah() to prevent the following trace: + +Bluetooth: l2cap_core.c:static void l2cap_chan_destroy(struct kref +*kref) +Bluetooth: chan 0000000023c4974d +Bluetooth: parent 00000000ae861c08 +================================================================== +BUG: KASAN: use-after-free in __mutex_waiter_is_first +kernel/locking/mutex.c:191 [inline] +BUG: KASAN: use-after-free in __mutex_lock_common +kernel/locking/mutex.c:671 [inline] +BUG: KASAN: use-after-free in __mutex_lock+0x278/0x400 +kernel/locking/mutex.c:729 +Read of size 8 at addr ffff888006a49b08 by task kworker/u3:2/389 + +Link: https://lore.kernel.org/lkml/20220622082716.478486-1-lee.jones@linaro.org +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sungwoo Kim +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index a8835c8367af..0f98c5d8c4de 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -4308,6 +4308,12 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, + } + } + ++ chan = l2cap_chan_hold_unless_zero(chan); ++ if (!chan) { ++ err = -EBADSLT; ++ goto unlock; ++ } ++ + err = 0; + + l2cap_chan_lock(chan); +@@ -4337,6 +4343,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, + } + + l2cap_chan_unlock(chan); ++ l2cap_chan_put(chan); + + unlock: + mutex_unlock(&conn->chan_lock); +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-l2cap-initialize-delayed-works-at-l2cap_ch.patch b/queue-5.19/bluetooth-l2cap-initialize-delayed-works-at-l2cap_ch.patch new file mode 100644 index 00000000000..d9d2d7f00ed --- /dev/null +++ b/queue-5.19/bluetooth-l2cap-initialize-delayed-works-at-l2cap_ch.patch @@ -0,0 +1,82 @@ +From 6b56ae03a59289b392f5d9947a7886b53a082182 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 00:32:56 +0900 +Subject: Bluetooth: L2CAP: initialize delayed works at l2cap_chan_create() + +From: Tetsuo Handa + +[ Upstream commit 2d2cb3066f2c90cd8ca540b36ba7a55e7f2406e0 ] + +syzbot is reporting cancel_delayed_work() without INIT_DELAYED_WORK() at +l2cap_chan_del() [1], for CONF_NOT_COMPLETE flag (which meant to prevent +l2cap_chan_del() from calling cancel_delayed_work()) is cleared by timer +which fires before l2cap_chan_del() is called by closing file descriptor +created by socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP). + +l2cap_bredr_sig_cmd(L2CAP_CONF_REQ) and l2cap_bredr_sig_cmd(L2CAP_CONF_RSP) +are calling l2cap_ertm_init(chan), and they call l2cap_chan_ready() (which +clears CONF_NOT_COMPLETE flag) only when l2cap_ertm_init(chan) succeeded. + +l2cap_sock_init() does not call l2cap_ertm_init(chan), and it instead sets +CONF_NOT_COMPLETE flag by calling l2cap_chan_set_defaults(). However, when +connect() is requested, "command 0x0409 tx timeout" happens after 2 seconds + from connect() request, and CONF_NOT_COMPLETE flag is cleared after 4 +seconds from connect() request, for l2cap_conn_start() from +l2cap_info_timeout() callback scheduled by + + schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); + +in l2cap_connect() is calling l2cap_chan_ready(). + +Fix this problem by initializing delayed works used by L2CAP_MODE_ERTM +mode as soon as l2cap_chan_create() allocates a channel, like I did in +commit be8597239379f0f5 ("Bluetooth: initialize skb_queue_head at +l2cap_chan_create()"). + +Link: https://syzkaller.appspot.com/bug?extid=83672956c7aa6af698b3 [1] +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 48fbd0ae882b..a8835c8367af 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -61,6 +61,9 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); + + static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, + struct sk_buff_head *skbs, u8 event); ++static void l2cap_retrans_timeout(struct work_struct *work); ++static void l2cap_monitor_timeout(struct work_struct *work); ++static void l2cap_ack_timeout(struct work_struct *work); + + static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) + { +@@ -476,6 +479,9 @@ struct l2cap_chan *l2cap_chan_create(void) + write_unlock(&chan_list_lock); + + INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); ++ INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); ++ INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); ++ INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); + + chan->state = BT_OPEN; + +@@ -3319,10 +3325,6 @@ int l2cap_ertm_init(struct l2cap_chan *chan) + chan->rx_state = L2CAP_RX_STATE_RECV; + chan->tx_state = L2CAP_TX_STATE_XMIT; + +- INIT_DELAYED_WORK(&chan->retrans_timer, l2cap_retrans_timeout); +- INIT_DELAYED_WORK(&chan->monitor_timer, l2cap_monitor_timeout); +- INIT_DELAYED_WORK(&chan->ack_timer, l2cap_ack_timeout); +- + skb_queue_head_init(&chan->srej_q); + + err = l2cap_seq_list_init(&chan->srej_list, chan->tx_win); +-- +2.35.1 + diff --git a/queue-5.19/bluetooth-rfcomm-fix-possible-deadlock-on-socket-shu.patch b/queue-5.19/bluetooth-rfcomm-fix-possible-deadlock-on-socket-shu.patch new file mode 100644 index 00000000000..a2832130ee9 --- /dev/null +++ b/queue-5.19/bluetooth-rfcomm-fix-possible-deadlock-on-socket-shu.patch @@ -0,0 +1,51 @@ +From 206ebad1fc5699250cfa04444932f891bd8b8f32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 16:08:13 -0700 +Subject: Bluetooth: RFCOMM: Fix possible deadlock on socket shutdown/release + +From: Luiz Augusto von Dentz + +[ Upstream commit 812e92b824c1db16c9519f8624d48a9901a0d38f ] + +Due to change to switch to use lock_sock inside rfcomm_sk_state_change +the socket shutdown/release procedure can cause a deadlock: + + rfcomm_sock_shutdown(): + lock_sock(); + __rfcomm_sock_close(): + rfcomm_dlc_close(): + __rfcomm_dlc_close(): + rfcomm_dlc_lock(); + rfcomm_sk_state_change(): + lock_sock(); + +To fix this when the call __rfcomm_sock_close is now done without +holding the lock_sock since rfcomm_dlc_lock exists to protect +the dlc data there is no need to use lock_sock in that code path. + +Link: https://lore.kernel.org/all/CAD+dNTsbuU4w+Y_P7o+VEN7BYCAbZuwZx2+tH+OTzCdcZF82YA@mail.gmail.com/ +Fixes: b7ce436a5d79 ("Bluetooth: switch to lock_sock in RFCOMM") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/rfcomm/sock.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 4bf4ea6cbb5e..21e24da4847f 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -902,7 +902,10 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) + lock_sock(sk); + if (!sk->sk_shutdown) { + sk->sk_shutdown = SHUTDOWN_MASK; ++ ++ release_sock(sk); + __rfcomm_sock_close(sk); ++ lock_sock(sk); + + if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && + !(current->flags & PF_EXITING)) +-- +2.35.1 + diff --git a/queue-5.19/bnx2x-fix-potential-memory-leak-in-bnx2x_tpa_stop.patch b/queue-5.19/bnx2x-fix-potential-memory-leak-in-bnx2x_tpa_stop.patch new file mode 100644 index 00000000000..cba5f9c83b8 --- /dev/null +++ b/queue-5.19/bnx2x-fix-potential-memory-leak-in-bnx2x_tpa_stop.patch @@ -0,0 +1,40 @@ +From 6cdc46ef3ba66669fb6a0ddc809332694e41772b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 14:28:43 +0800 +Subject: bnx2x: fix potential memory leak in bnx2x_tpa_stop() + +From: Jianglei Nie + +[ Upstream commit b43f9acbb8942b05252be83ac25a81cec70cc192 ] + +bnx2x_tpa_stop() allocates a memory chunk from new_data with +bnx2x_frag_alloc(). The new_data should be freed when gets some error. +But when "pad + len > fp->rx_buf_size" is true, bnx2x_tpa_stop() returns +without releasing the new_data, which will lead to a memory leak. + +We should free the new_data with bnx2x_frag_free() when "pad + len > +fp->rx_buf_size" is true. + +Fixes: 07b0f00964def8af9321cfd6c4a7e84f6362f728 ("bnx2x: fix possible panic under memory stress") +Signed-off-by: Jianglei Nie +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +index 5729a5ab059d..4cbd3ba5acb9 100644 +--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c ++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +@@ -789,6 +789,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, + BNX2X_ERR("skb_put is about to fail... pad %d len %d rx_buf_size %d\n", + pad, len, fp->rx_buf_size); + bnx2x_panic(); ++ bnx2x_frag_free(fp, new_data); + return; + } + #endif +-- +2.35.1 + diff --git a/queue-5.19/bnxt_en-replace-reset-with-config-timestamps.patch b/queue-5.19/bnxt_en-replace-reset-with-config-timestamps.patch new file mode 100644 index 00000000000..d12d0fc9655 --- /dev/null +++ b/queue-5.19/bnxt_en-replace-reset-with-config-timestamps.patch @@ -0,0 +1,53 @@ +From 5c18174e067923473c528c05bb3088156c4a5fd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 22:10:38 +0300 +Subject: bnxt_en: replace reset with config timestamps + +From: Vadim Fedorenko + +[ Upstream commit 8db3d514e96715c897fe793c4d5fc0fd86aca517 ] + +Any change to the hardware timestamps configuration triggers nic restart, +which breaks transmition and reception of network packets for a while. +But there is no need to fully restart the device because while configuring +hardware timestamps. The code for changing configuration runs after all +of the initialisation, when the NIC is actually up and running. This patch +changes the code that ioctl will only update configuration registers and +will not trigger carrier status change, but in case of timestamps for +all rx packetes it fallbacks to close()/open() sequnce because of +synchronization issues in the hardware. Tested on BCM57504. + +Cc: Richard Cochran +Signed-off-by: Vadim Fedorenko +Reviewed-by: Michael Chan +Link: https://lore.kernel.org/r/20220922191038.29921-1-vfedorenko@novek.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +index 8e316367f6ce..2132ce63193c 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +@@ -505,9 +505,13 @@ static int bnxt_hwrm_ptp_cfg(struct bnxt *bp) + ptp->tstamp_filters = flags; + + if (netif_running(bp->dev)) { +- rc = bnxt_close_nic(bp, false, false); +- if (!rc) +- rc = bnxt_open_nic(bp, false, false); ++ if (ptp->rx_filter == HWTSTAMP_FILTER_ALL) { ++ rc = bnxt_close_nic(bp, false, false); ++ if (!rc) ++ rc = bnxt_open_nic(bp, false, false); ++ } else { ++ bnxt_ptp_cfg_tstamp_filters(bp); ++ } + if (!rc && !ptp->tstamp_filters) + rc = -EIO; + } +-- +2.35.1 + diff --git a/queue-5.19/bpf-adjust-kprobe_multi-entry_ip-for-config_x86_kern.patch b/queue-5.19/bpf-adjust-kprobe_multi-entry_ip-for-config_x86_kern.patch new file mode 100644 index 00000000000..9107bfd9697 --- /dev/null +++ b/queue-5.19/bpf-adjust-kprobe_multi-entry_ip-for-config_x86_kern.patch @@ -0,0 +1,108 @@ +From a3165b0f9a1a0a9b115b6d645e2a262044fb545a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 17:33:38 +0200 +Subject: bpf: Adjust kprobe_multi entry_ip for CONFIG_X86_KERNEL_IBT + +From: Jiri Olsa + +[ Upstream commit c09eb2e578eb1668bbc84dc07e8d8bd6f04b9a02 ] + +Martynas reported bpf_get_func_ip returning +4 address when +CONFIG_X86_KERNEL_IBT option is enabled. + +When CONFIG_X86_KERNEL_IBT is enabled we'll have endbr instruction +at the function entry, which screws return value of bpf_get_func_ip() +helper that should return the function address. + +There's short term workaround for kprobe_multi bpf program made by +Alexei [1], but we need this fixup also for bpf_get_attach_cookie, +that returns cookie based on the entry_ip value. + +Moving the fixup in the fprobe handler, so both bpf_get_func_ip +and bpf_get_attach_cookie get expected function address when +CONFIG_X86_KERNEL_IBT option is enabled. + +Also renaming kprobe_multi_link_handler entry_ip argument to fentry_ip +so it's clearer this is an ftrace __fentry__ ip. + +[1] commit 7f0059b58f02 ("selftests/bpf: Fix kprobe_multi test.") + +Cc: Peter Zijlstra +Reported-by: Martynas Pumputis +Acked-by: Andrii Nakryiko +Signed-off-by: Jiri Olsa +Link: https://lore.kernel.org/r/20220926153340.1621984-5-jolsa@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/trace/bpf_trace.c | 20 +++++++++++++++++-- + .../selftests/bpf/progs/kprobe_multi.c | 4 +--- + 2 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c +index 88589d74a892..af13fdf1d86c 100644 +--- a/kernel/trace/bpf_trace.c ++++ b/kernel/trace/bpf_trace.c +@@ -1026,6 +1026,22 @@ static const struct bpf_func_proto bpf_get_func_ip_proto_tracing = { + .arg1_type = ARG_PTR_TO_CTX, + }; + ++#ifdef CONFIG_X86_KERNEL_IBT ++static unsigned long get_entry_ip(unsigned long fentry_ip) ++{ ++ u32 instr; ++ ++ /* Being extra safe in here in case entry ip is on the page-edge. */ ++ if (get_kernel_nofault(instr, (u32 *) fentry_ip - 1)) ++ return fentry_ip; ++ if (is_endbr(instr)) ++ fentry_ip -= ENDBR_INSN_SIZE; ++ return fentry_ip; ++} ++#else ++#define get_entry_ip(fentry_ip) fentry_ip ++#endif ++ + BPF_CALL_1(bpf_get_func_ip_kprobe, struct pt_regs *, regs) + { + struct kprobe *kp = kprobe_running(); +@@ -2414,13 +2430,13 @@ kprobe_multi_link_prog_run(struct bpf_kprobe_multi_link *link, + } + + static void +-kprobe_multi_link_handler(struct fprobe *fp, unsigned long entry_ip, ++kprobe_multi_link_handler(struct fprobe *fp, unsigned long fentry_ip, + struct pt_regs *regs) + { + struct bpf_kprobe_multi_link *link; + + link = container_of(fp, struct bpf_kprobe_multi_link, fp); +- kprobe_multi_link_prog_run(link, entry_ip, regs); ++ kprobe_multi_link_prog_run(link, get_entry_ip(fentry_ip), regs); + } + + static int symbols_cmp_r(const void *a, const void *b, const void *priv) +diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi.c b/tools/testing/selftests/bpf/progs/kprobe_multi.c +index 08f95a8155d1..98c3399e15c0 100644 +--- a/tools/testing/selftests/bpf/progs/kprobe_multi.c ++++ b/tools/testing/selftests/bpf/progs/kprobe_multi.c +@@ -36,15 +36,13 @@ __u64 kretprobe_test6_result = 0; + __u64 kretprobe_test7_result = 0; + __u64 kretprobe_test8_result = 0; + +-extern bool CONFIG_X86_KERNEL_IBT __kconfig __weak; +- + static void kprobe_multi_check(void *ctx, bool is_return) + { + if (bpf_get_current_pid_tgid() >> 32 != pid) + return; + + __u64 cookie = test_cookie ? bpf_get_attach_cookie(ctx) : 0; +- __u64 addr = bpf_get_func_ip(ctx) - (CONFIG_X86_KERNEL_IBT ? 4 : 0); ++ __u64 addr = bpf_get_func_ip(ctx); + + #define SET(__var, __addr, __cookie) ({ \ + if (((const void *) addr == __addr) && \ +-- +2.35.1 + diff --git a/queue-5.19/bpf-btf-fix-truncated-last_member_type_id-in-btf_str.patch b/queue-5.19/bpf-btf-fix-truncated-last_member_type_id-in-btf_str.patch new file mode 100644 index 00000000000..50955b96dce --- /dev/null +++ b/queue-5.19/bpf-btf-fix-truncated-last_member_type_id-in-btf_str.patch @@ -0,0 +1,47 @@ +From a4cd55abadc2961922ff0435642ce7921880c7cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Sep 2022 11:01:20 +0000 +Subject: bpf: btf: fix truncated last_member_type_id in btf_struct_resolve + +From: Lorenz Bauer + +[ Upstream commit a37a32583e282d8d815e22add29bc1e91e19951a ] + +When trying to finish resolving a struct member, btf_struct_resolve +saves the member type id in a u16 temporary variable. This truncates +the 32 bit type id value if it exceeds UINT16_MAX. + +As a result, structs that have members with type ids > UINT16_MAX and +which need resolution will fail with a message like this: + + [67414] STRUCT ff_device size=120 vlen=12 + effect_owners type_id=67434 bits_offset=960 Member exceeds struct_size + +Fix this by changing the type of last_member_type_id to u32. + +Fixes: a0791f0df7d2 ("bpf: fix BTF limits") +Reviewed-by: Stanislav Fomichev +Signed-off-by: Lorenz Bauer +Link: https://lore.kernel.org/r/20220910110120.339242-1-oss@lmb.io +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/btf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c +index eb12d4f705cc..ff4a2c0b14ea 100644 +--- a/kernel/bpf/btf.c ++++ b/kernel/bpf/btf.c +@@ -3120,7 +3120,7 @@ static int btf_struct_resolve(struct btf_verifier_env *env, + if (v->next_member) { + const struct btf_type *last_member_type; + const struct btf_member *last_member; +- u16 last_member_type_id; ++ u32 last_member_type_id; + + last_member = btf_type_member(v->t) + v->next_member - 1; + last_member_type_id = last_member->type; +-- +2.35.1 + diff --git a/queue-5.19/bpf-cleanup-check_refcount_ok.patch b/queue-5.19/bpf-cleanup-check_refcount_ok.patch new file mode 100644 index 00000000000..3b852e2b440 --- /dev/null +++ b/queue-5.19/bpf-cleanup-check_refcount_ok.patch @@ -0,0 +1,171 @@ +From ca323286560a3a2854e01b34c5a07118fd5f6600 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Aug 2022 10:15:59 -0700 +Subject: bpf: Cleanup check_refcount_ok + +From: Dave Marchevsky + +[ Upstream commit b2d8ef19c6e7ed71ba5092feb0710063a751834f ] + +Discussion around a recently-submitted patch provided historical +context for check_refcount_ok [0]. Specifically, the function and its +helpers - may_be_acquire_function and arg_type_may_be_refcounted - +predate the OBJ_RELEASE type flag and the addition of many more helpers +with acquire/release semantics. + +The purpose of check_refcount_ok is to ensure: + 1) Helper doesn't have multiple uses of return reg's ref_obj_id + 2) Helper with release semantics only has one arg needing to be + released, since that's tracked using meta->ref_obj_id + +With current verifier, it's safe to remove check_refcount_ok and its +helpers. Since addition of OBJ_RELEASE type flag, case 2) has been +handled by the arg_type_is_release check in check_func_arg. To ensure +case 1) won't result in verifier silently prioritizing one use of +ref_obj_id, this patch adds a helper_multiple_ref_obj_use check which +fails loudly if a helper passes > 1 test for use of ref_obj_id. + + [0]: lore.kernel.org/bpf/20220713234529.4154673-1-davemarchevsky@fb.com + +Signed-off-by: Dave Marchevsky +Acked-by: Martin KaFai Lau +Acked-by: Joanne Koong +Acked-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20220808171559.3251090-1-davemarchevsky@fb.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier") +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 74 +++++++++++++++++-------------------------- + 1 file changed, 29 insertions(+), 45 deletions(-) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 339147061127..210793b5cd6c 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -467,25 +467,11 @@ static bool type_is_rdonly_mem(u32 type) + return type & MEM_RDONLY; + } + +-static bool arg_type_may_be_refcounted(enum bpf_arg_type type) +-{ +- return type == ARG_PTR_TO_SOCK_COMMON; +-} +- + static bool type_may_be_null(u32 type) + { + return type & PTR_MAYBE_NULL; + } + +-static bool may_be_acquire_function(enum bpf_func_id func_id) +-{ +- return func_id == BPF_FUNC_sk_lookup_tcp || +- func_id == BPF_FUNC_sk_lookup_udp || +- func_id == BPF_FUNC_skc_lookup_tcp || +- func_id == BPF_FUNC_map_lookup_elem || +- func_id == BPF_FUNC_ringbuf_reserve; +-} +- + static bool is_acquire_function(enum bpf_func_id func_id, + const struct bpf_map *map) + { +@@ -518,6 +504,26 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id) + func_id == BPF_FUNC_skc_to_tcp_request_sock; + } + ++static bool is_dynptr_acquire_function(enum bpf_func_id func_id) ++{ ++ return func_id == BPF_FUNC_dynptr_data; ++} ++ ++static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id, ++ const struct bpf_map *map) ++{ ++ int ref_obj_uses = 0; ++ ++ if (is_ptr_cast_function(func_id)) ++ ref_obj_uses++; ++ if (is_acquire_function(func_id, map)) ++ ref_obj_uses++; ++ if (is_dynptr_acquire_function(func_id)) ++ ref_obj_uses++; ++ ++ return ref_obj_uses > 1; ++} ++ + static bool is_cmpxchg_insn(const struct bpf_insn *insn) + { + return BPF_CLASS(insn->code) == BPF_STX && +@@ -6456,33 +6462,6 @@ static bool check_arg_pair_ok(const struct bpf_func_proto *fn) + return true; + } + +-static bool check_refcount_ok(const struct bpf_func_proto *fn, int func_id) +-{ +- int count = 0; +- +- if (arg_type_may_be_refcounted(fn->arg1_type)) +- count++; +- if (arg_type_may_be_refcounted(fn->arg2_type)) +- count++; +- if (arg_type_may_be_refcounted(fn->arg3_type)) +- count++; +- if (arg_type_may_be_refcounted(fn->arg4_type)) +- count++; +- if (arg_type_may_be_refcounted(fn->arg5_type)) +- count++; +- +- /* A reference acquiring function cannot acquire +- * another refcounted ptr. +- */ +- if (may_be_acquire_function(func_id) && count) +- return false; +- +- /* We only support one arg being unreferenced at the moment, +- * which is sufficient for the helper functions we have right now. +- */ +- return count <= 1; +-} +- + static bool check_btf_id_ok(const struct bpf_func_proto *fn) + { + int i; +@@ -6506,8 +6485,7 @@ static int check_func_proto(const struct bpf_func_proto *fn, int func_id, + { + return check_raw_mode_ok(fn) && + check_arg_pair_ok(fn) && +- check_btf_id_ok(fn) && +- check_refcount_ok(fn, func_id) ? 0 : -EINVAL; ++ check_btf_id_ok(fn) ? 0 : -EINVAL; + } + + /* Packet data might have moved, any old PTR_TO_PACKET[_META,_END] +@@ -7410,6 +7388,12 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn + if (type_may_be_null(regs[BPF_REG_0].type)) + regs[BPF_REG_0].id = ++env->id_gen; + ++ if (helper_multiple_ref_obj_use(func_id, meta.map_ptr)) { ++ verbose(env, "verifier internal error: func %s#%d sets ref_obj_id more than once\n", ++ func_id_name(func_id), func_id); ++ return -EFAULT; ++ } ++ + if (is_ptr_cast_function(func_id)) { + /* For release_reference() */ + regs[BPF_REG_0].ref_obj_id = meta.ref_obj_id; +@@ -7422,10 +7406,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn + regs[BPF_REG_0].id = id; + /* For release_reference() */ + regs[BPF_REG_0].ref_obj_id = id; +- } else if (func_id == BPF_FUNC_dynptr_data) { ++ } else if (is_dynptr_acquire_function(func_id)) { + int dynptr_id = 0, i; + +- /* Find the id of the dynptr we're acquiring a reference to */ ++ /* Find the id of the dynptr we're tracking the reference of */ + for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) { + if (arg_type_is_dynptr(fn->arg_type[i])) { + if (dynptr_id) { +-- +2.35.1 + diff --git a/queue-5.19/bpf-convert-cgroup_bpf.progs-to-hlist.patch b/queue-5.19/bpf-convert-cgroup_bpf.progs-to-hlist.patch new file mode 100644 index 00000000000..f38b5050be7 --- /dev/null +++ b/queue-5.19/bpf-convert-cgroup_bpf.progs-to-hlist.patch @@ -0,0 +1,366 @@ +From 5773bf9b030eb4559ed2b2662156c9fe5afe0b8f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 10:43:05 -0700 +Subject: bpf: convert cgroup_bpf.progs to hlist + +From: Stanislav Fomichev + +[ Upstream commit 00442143a2ab7f1da46fbf4d2a99c85df767d49a ] + +This lets us reclaim some space to be used by new cgroup lsm slots. + +Before: +struct cgroup_bpf { + struct bpf_prog_array * effective[23]; /* 0 184 */ + /* --- cacheline 2 boundary (128 bytes) was 56 bytes ago --- */ + struct list_head progs[23]; /* 184 368 */ + /* --- cacheline 8 boundary (512 bytes) was 40 bytes ago --- */ + u32 flags[23]; /* 552 92 */ + + /* XXX 4 bytes hole, try to pack */ + + /* --- cacheline 10 boundary (640 bytes) was 8 bytes ago --- */ + struct list_head storages; /* 648 16 */ + struct bpf_prog_array * inactive; /* 664 8 */ + struct percpu_ref refcnt; /* 672 16 */ + struct work_struct release_work; /* 688 32 */ + + /* size: 720, cachelines: 12, members: 7 */ + /* sum members: 716, holes: 1, sum holes: 4 */ + /* last cacheline: 16 bytes */ +}; + +After: +struct cgroup_bpf { + struct bpf_prog_array * effective[23]; /* 0 184 */ + /* --- cacheline 2 boundary (128 bytes) was 56 bytes ago --- */ + struct hlist_head progs[23]; /* 184 184 */ + /* --- cacheline 5 boundary (320 bytes) was 48 bytes ago --- */ + u8 flags[23]; /* 368 23 */ + + /* XXX 1 byte hole, try to pack */ + + /* --- cacheline 6 boundary (384 bytes) was 8 bytes ago --- */ + struct list_head storages; /* 392 16 */ + struct bpf_prog_array * inactive; /* 408 8 */ + struct percpu_ref refcnt; /* 416 16 */ + struct work_struct release_work; /* 432 72 */ + + /* size: 504, cachelines: 8, members: 7 */ + /* sum members: 503, holes: 1, sum holes: 1 */ + /* last cacheline: 56 bytes */ +}; + +Suggested-by: Jakub Sitnicki +Reviewed-by: Jakub Sitnicki +Reviewed-by: Martin KaFai Lau +Signed-off-by: Stanislav Fomichev +Link: https://lore.kernel.org/r/20220628174314.1216643-3-sdf@google.com +Signed-off-by: Alexei Starovoitov +Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier") +Signed-off-by: Sasha Levin +--- + include/linux/bpf-cgroup-defs.h | 4 +- + include/linux/bpf-cgroup.h | 2 +- + kernel/bpf/cgroup.c | 76 +++++++++++++++++++-------------- + 3 files changed, 47 insertions(+), 35 deletions(-) + +diff --git a/include/linux/bpf-cgroup-defs.h b/include/linux/bpf-cgroup-defs.h +index 695d1224a71b..5d268e76d8e6 100644 +--- a/include/linux/bpf-cgroup-defs.h ++++ b/include/linux/bpf-cgroup-defs.h +@@ -47,8 +47,8 @@ struct cgroup_bpf { + * have either zero or one element + * when BPF_F_ALLOW_MULTI the list can have up to BPF_CGROUP_MAX_PROGS + */ +- struct list_head progs[MAX_CGROUP_BPF_ATTACH_TYPE]; +- u32 flags[MAX_CGROUP_BPF_ATTACH_TYPE]; ++ struct hlist_head progs[MAX_CGROUP_BPF_ATTACH_TYPE]; ++ u8 flags[MAX_CGROUP_BPF_ATTACH_TYPE]; + + /* list of cgroup shared storages */ + struct list_head storages; +diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h +index 669d96d074ad..6673acfbf2ef 100644 +--- a/include/linux/bpf-cgroup.h ++++ b/include/linux/bpf-cgroup.h +@@ -95,7 +95,7 @@ struct bpf_cgroup_link { + }; + + struct bpf_prog_list { +- struct list_head node; ++ struct hlist_node node; + struct bpf_prog *prog; + struct bpf_cgroup_link *link; + struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]; +diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c +index 34dfa45ef4f3..13526b01f1fd 100644 +--- a/kernel/bpf/cgroup.c ++++ b/kernel/bpf/cgroup.c +@@ -157,11 +157,12 @@ static void cgroup_bpf_release(struct work_struct *work) + mutex_lock(&cgroup_mutex); + + for (atype = 0; atype < ARRAY_SIZE(cgrp->bpf.progs); atype++) { +- struct list_head *progs = &cgrp->bpf.progs[atype]; +- struct bpf_prog_list *pl, *pltmp; ++ struct hlist_head *progs = &cgrp->bpf.progs[atype]; ++ struct bpf_prog_list *pl; ++ struct hlist_node *pltmp; + +- list_for_each_entry_safe(pl, pltmp, progs, node) { +- list_del(&pl->node); ++ hlist_for_each_entry_safe(pl, pltmp, progs, node) { ++ hlist_del(&pl->node); + if (pl->prog) + bpf_prog_put(pl->prog); + if (pl->link) +@@ -217,12 +218,12 @@ static struct bpf_prog *prog_list_prog(struct bpf_prog_list *pl) + /* count number of elements in the list. + * it's slow but the list cannot be long + */ +-static u32 prog_list_length(struct list_head *head) ++static u32 prog_list_length(struct hlist_head *head) + { + struct bpf_prog_list *pl; + u32 cnt = 0; + +- list_for_each_entry(pl, head, node) { ++ hlist_for_each_entry(pl, head, node) { + if (!prog_list_prog(pl)) + continue; + cnt++; +@@ -291,7 +292,7 @@ static int compute_effective_progs(struct cgroup *cgrp, + if (cnt > 0 && !(p->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) + continue; + +- list_for_each_entry(pl, &p->bpf.progs[atype], node) { ++ hlist_for_each_entry(pl, &p->bpf.progs[atype], node) { + if (!prog_list_prog(pl)) + continue; + +@@ -342,7 +343,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp) + cgroup_bpf_get(p); + + for (i = 0; i < NR; i++) +- INIT_LIST_HEAD(&cgrp->bpf.progs[i]); ++ INIT_HLIST_HEAD(&cgrp->bpf.progs[i]); + + INIT_LIST_HEAD(&cgrp->bpf.storages); + +@@ -418,7 +419,7 @@ static int update_effective_progs(struct cgroup *cgrp, + + #define BPF_CGROUP_MAX_PROGS 64 + +-static struct bpf_prog_list *find_attach_entry(struct list_head *progs, ++static struct bpf_prog_list *find_attach_entry(struct hlist_head *progs, + struct bpf_prog *prog, + struct bpf_cgroup_link *link, + struct bpf_prog *replace_prog, +@@ -428,12 +429,12 @@ static struct bpf_prog_list *find_attach_entry(struct list_head *progs, + + /* single-attach case */ + if (!allow_multi) { +- if (list_empty(progs)) ++ if (hlist_empty(progs)) + return NULL; +- return list_first_entry(progs, typeof(*pl), node); ++ return hlist_entry(progs->first, typeof(*pl), node); + } + +- list_for_each_entry(pl, progs, node) { ++ hlist_for_each_entry(pl, progs, node) { + if (prog && pl->prog == prog && prog != replace_prog) + /* disallow attaching the same prog twice */ + return ERR_PTR(-EINVAL); +@@ -444,7 +445,7 @@ static struct bpf_prog_list *find_attach_entry(struct list_head *progs, + + /* direct prog multi-attach w/ replacement case */ + if (replace_prog) { +- list_for_each_entry(pl, progs, node) { ++ hlist_for_each_entry(pl, progs, node) { + if (pl->prog == replace_prog) + /* a match found */ + return pl; +@@ -480,7 +481,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + struct bpf_cgroup_storage *new_storage[MAX_BPF_CGROUP_STORAGE_TYPE] = {}; + enum cgroup_bpf_attach_type atype; + struct bpf_prog_list *pl; +- struct list_head *progs; ++ struct hlist_head *progs; + int err; + + if (((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI)) || +@@ -503,7 +504,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + if (!hierarchy_allows_attach(cgrp, atype)) + return -EPERM; + +- if (!list_empty(progs) && cgrp->bpf.flags[atype] != saved_flags) ++ if (!hlist_empty(progs) && cgrp->bpf.flags[atype] != saved_flags) + /* Disallow attaching non-overridable on top + * of existing overridable in this cgroup. + * Disallow attaching multi-prog if overridable or none +@@ -525,12 +526,22 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + if (pl) { + old_prog = pl->prog; + } else { ++ struct hlist_node *last = NULL; ++ + pl = kmalloc(sizeof(*pl), GFP_KERNEL); + if (!pl) { + bpf_cgroup_storages_free(new_storage); + return -ENOMEM; + } +- list_add_tail(&pl->node, progs); ++ if (hlist_empty(progs)) ++ hlist_add_head(&pl->node, progs); ++ else ++ hlist_for_each(last, progs) { ++ if (last->next) ++ continue; ++ hlist_add_behind(&pl->node, last); ++ break; ++ } + } + + pl->prog = prog; +@@ -556,7 +567,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp, + } + bpf_cgroup_storages_free(new_storage); + if (!old_prog) { +- list_del(&pl->node); ++ hlist_del(&pl->node); + kfree(pl); + } + return err; +@@ -587,7 +598,7 @@ static void replace_effective_prog(struct cgroup *cgrp, + struct cgroup_subsys_state *css; + struct bpf_prog_array *progs; + struct bpf_prog_list *pl; +- struct list_head *head; ++ struct hlist_head *head; + struct cgroup *cg; + int pos; + +@@ -603,7 +614,7 @@ static void replace_effective_prog(struct cgroup *cgrp, + continue; + + head = &cg->bpf.progs[atype]; +- list_for_each_entry(pl, head, node) { ++ hlist_for_each_entry(pl, head, node) { + if (!prog_list_prog(pl)) + continue; + if (pl->link == link) +@@ -637,7 +648,7 @@ static int __cgroup_bpf_replace(struct cgroup *cgrp, + enum cgroup_bpf_attach_type atype; + struct bpf_prog *old_prog; + struct bpf_prog_list *pl; +- struct list_head *progs; ++ struct hlist_head *progs; + bool found = false; + + atype = to_cgroup_bpf_attach_type(link->type); +@@ -649,7 +660,7 @@ static int __cgroup_bpf_replace(struct cgroup *cgrp, + if (link->link.prog->type != new_prog->type) + return -EINVAL; + +- list_for_each_entry(pl, progs, node) { ++ hlist_for_each_entry(pl, progs, node) { + if (pl->link == link) { + found = true; + break; +@@ -688,7 +699,7 @@ static int cgroup_bpf_replace(struct bpf_link *link, struct bpf_prog *new_prog, + return ret; + } + +-static struct bpf_prog_list *find_detach_entry(struct list_head *progs, ++static struct bpf_prog_list *find_detach_entry(struct hlist_head *progs, + struct bpf_prog *prog, + struct bpf_cgroup_link *link, + bool allow_multi) +@@ -696,14 +707,14 @@ static struct bpf_prog_list *find_detach_entry(struct list_head *progs, + struct bpf_prog_list *pl; + + if (!allow_multi) { +- if (list_empty(progs)) ++ if (hlist_empty(progs)) + /* report error when trying to detach and nothing is attached */ + return ERR_PTR(-ENOENT); + + /* to maintain backward compatibility NONE and OVERRIDE cgroups + * allow detaching with invalid FD (prog==NULL) in legacy mode + */ +- return list_first_entry(progs, typeof(*pl), node); ++ return hlist_entry(progs->first, typeof(*pl), node); + } + + if (!prog && !link) +@@ -713,7 +724,7 @@ static struct bpf_prog_list *find_detach_entry(struct list_head *progs, + return ERR_PTR(-EINVAL); + + /* find the prog or link and detach it */ +- list_for_each_entry(pl, progs, node) { ++ hlist_for_each_entry(pl, progs, node) { + if (pl->prog == prog && pl->link == link) + return pl; + } +@@ -737,7 +748,7 @@ static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog, + struct cgroup_subsys_state *css; + struct bpf_prog_array *progs; + struct bpf_prog_list *pl; +- struct list_head *head; ++ struct hlist_head *head; + struct cgroup *cg; + int pos; + +@@ -754,7 +765,7 @@ static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog, + continue; + + head = &cg->bpf.progs[atype]; +- list_for_each_entry(pl, head, node) { ++ hlist_for_each_entry(pl, head, node) { + if (!prog_list_prog(pl)) + continue; + if (pl->prog == prog && pl->link == link) +@@ -793,7 +804,7 @@ static int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + enum cgroup_bpf_attach_type atype; + struct bpf_prog *old_prog; + struct bpf_prog_list *pl; +- struct list_head *progs; ++ struct hlist_head *progs; + u32 flags; + + atype = to_cgroup_bpf_attach_type(type); +@@ -824,9 +835,10 @@ static int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog, + } + + /* now can actually delete it from this cgroup list */ +- list_del(&pl->node); ++ hlist_del(&pl->node); ++ + kfree(pl); +- if (list_empty(progs)) ++ if (hlist_empty(progs)) + /* last program was detached, reset flags to zero */ + cgrp->bpf.flags[atype] = 0; + if (old_prog) +@@ -854,7 +866,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + enum bpf_attach_type type = attr->query.attach_type; + enum cgroup_bpf_attach_type atype; + struct bpf_prog_array *effective; +- struct list_head *progs; ++ struct hlist_head *progs; + struct bpf_prog *prog; + int cnt, ret = 0, i; + u32 flags; +@@ -893,7 +905,7 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, + u32 id; + + i = 0; +- list_for_each_entry(pl, progs, node) { ++ hlist_for_each_entry(pl, progs, node) { + prog = prog_list_prog(pl); + id = prog->aux->id; + if (copy_to_user(prog_ids + i, &id, sizeof(id))) +-- +2.35.1 + diff --git a/queue-5.19/bpf-disable-preemption-when-increasing-per-cpu-map_l.patch b/queue-5.19/bpf-disable-preemption-when-increasing-per-cpu-map_l.patch new file mode 100644 index 00000000000..f6ec3040fc1 --- /dev/null +++ b/queue-5.19/bpf-disable-preemption-when-increasing-per-cpu-map_l.patch @@ -0,0 +1,113 @@ +From 8b788e90a38ea73ccedfac1e89d00eb18bc91f89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 12:26:27 +0800 +Subject: bpf: Disable preemption when increasing per-cpu map_locked + +From: Hou Tao + +[ Upstream commit 2775da21628738ce073a3a6a806adcbaada0f091 ] + +Per-cpu htab->map_locked is used to prohibit the concurrent accesses +from both NMI and non-NMI contexts. But since commit 74d862b682f5 +("sched: Make migrate_disable/enable() independent of RT"), +migrate_disable() is also preemptible under CONFIG_PREEMPT case, so now +map_locked also disallows concurrent updates from normal contexts +(e.g. userspace processes) unexpectedly as shown below: + +process A process B + +htab_map_update_elem() + htab_lock_bucket() + migrate_disable() + /* return 1 */ + __this_cpu_inc_return() + /* preempted by B */ + + htab_map_update_elem() + /* the same bucket as A */ + htab_lock_bucket() + migrate_disable() + /* return 2, so lock fails */ + __this_cpu_inc_return() + return -EBUSY + +A fix that seems feasible is using in_nmi() in htab_lock_bucket() and +only checking the value of map_locked for nmi context. But it will +re-introduce dead-lock on bucket lock if htab_lock_bucket() is re-entered +through non-tracing program (e.g. fentry program). + +One cannot use preempt_disable() to fix this issue as htab_use_raw_lock +being false causes the bucket lock to be a spin lock which can sleep and +does not work with preempt_disable(). + +Therefore, use migrate_disable() when using the spinlock instead of +preempt_disable() and defer fixing concurrent updates to when the kernel +has its own BPF memory allocator. + +Fixes: 74d862b682f5 ("sched: Make migrate_disable/enable() independent of RT") +Reviewed-by: Hao Luo +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20220831042629.130006-2-houtao@huaweicloud.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + kernel/bpf/hashtab.c | 23 ++++++++++++++++++----- + 1 file changed, 18 insertions(+), 5 deletions(-) + +diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c +index 4dd5e0005afa..717f85973443 100644 +--- a/kernel/bpf/hashtab.c ++++ b/kernel/bpf/hashtab.c +@@ -162,17 +162,25 @@ static inline int htab_lock_bucket(const struct bpf_htab *htab, + unsigned long *pflags) + { + unsigned long flags; ++ bool use_raw_lock; + + hash = hash & HASHTAB_MAP_LOCK_MASK; + +- migrate_disable(); ++ use_raw_lock = htab_use_raw_lock(htab); ++ if (use_raw_lock) ++ preempt_disable(); ++ else ++ migrate_disable(); + if (unlikely(__this_cpu_inc_return(*(htab->map_locked[hash])) != 1)) { + __this_cpu_dec(*(htab->map_locked[hash])); +- migrate_enable(); ++ if (use_raw_lock) ++ preempt_enable(); ++ else ++ migrate_enable(); + return -EBUSY; + } + +- if (htab_use_raw_lock(htab)) ++ if (use_raw_lock) + raw_spin_lock_irqsave(&b->raw_lock, flags); + else + spin_lock_irqsave(&b->lock, flags); +@@ -185,13 +193,18 @@ static inline void htab_unlock_bucket(const struct bpf_htab *htab, + struct bucket *b, u32 hash, + unsigned long flags) + { ++ bool use_raw_lock = htab_use_raw_lock(htab); ++ + hash = hash & HASHTAB_MAP_LOCK_MASK; +- if (htab_use_raw_lock(htab)) ++ if (use_raw_lock) + raw_spin_unlock_irqrestore(&b->raw_lock, flags); + else + spin_unlock_irqrestore(&b->lock, flags); + __this_cpu_dec(*(htab->map_locked[hash])); +- migrate_enable(); ++ if (use_raw_lock) ++ preempt_enable(); ++ else ++ migrate_enable(); + } + + static bool htab_lru_map_delete_node(void *arg, struct bpf_lru_node *node); +-- +2.35.1 + diff --git a/queue-5.19/bpf-ensure-correct-locking-around-vulnerable-functio.patch b/queue-5.19/bpf-ensure-correct-locking-around-vulnerable-functio.patch new file mode 100644 index 00000000000..1054a1c6657 --- /dev/null +++ b/queue-5.19/bpf-ensure-correct-locking-around-vulnerable-functio.patch @@ -0,0 +1,43 @@ +From 778ce00609ff6e8122f55d88b4121e06080d6fdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 14:38:55 +0100 +Subject: bpf: Ensure correct locking around vulnerable function find_vpid() + +From: Lee Jones + +[ Upstream commit 83c10cc362d91c0d8d25e60779ee52fdbbf3894d ] + +The documentation for find_vpid() clearly states: + + "Must be called with the tasklist_lock or rcu_read_lock() held." + +Presently we do neither for find_vpid() instance in bpf_task_fd_query(). +Add proper rcu_read_lock/unlock() to fix the issue. + +Fixes: 41bdc4b40ed6f ("bpf: introduce bpf subcommand BPF_TASK_FD_QUERY") +Signed-off-by: Lee Jones +Signed-off-by: Daniel Borkmann +Acked-by: Yonghong Song +Link: https://lore.kernel.org/bpf/20220912133855.1218900-1-lee@kernel.org +Signed-off-by: Sasha Levin +--- + kernel/bpf/syscall.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 7a3444988c84..494ba88054e8 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -4361,7 +4361,9 @@ static int bpf_task_fd_query(const union bpf_attr *attr, + if (attr->task_fd_query.flags != 0) + return -EINVAL; + ++ rcu_read_lock(); + task = get_pid_task(find_vpid(pid), PIDTYPE_PID); ++ rcu_read_unlock(); + if (!task) + return -ENOENT; + +-- +2.35.1 + diff --git a/queue-5.19/bpf-fix-non-static-bpf_func_proto-struct-definitions.patch b/queue-5.19/bpf-fix-non-static-bpf_func_proto-struct-definitions.patch new file mode 100644 index 00000000000..5087daf1213 --- /dev/null +++ b/queue-5.19/bpf-fix-non-static-bpf_func_proto-struct-definitions.patch @@ -0,0 +1,123 @@ +From 4e9e2dfcd2fa4925dab1d6d77e703f411db70167 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 15:54:07 -0700 +Subject: bpf: Fix non-static bpf_func_proto struct definitions + +From: Joanne Koong + +[ Upstream commit dc368e1c658e4f478a45e8d1d5b0c8392ca87506 ] + +This patch does two things: + +1) Marks the dynptr bpf_func_proto structs that were added in [1] + as static, as pointed out by the kernel test robot in [2]. + +2) There are some bpf_func_proto structs marked as extern which can + instead be statically defined. + + [1] https://lore.kernel.org/bpf/20220523210712.3641569-1-joannelkoong@gmail.com/ + [2] https://lore.kernel.org/bpf/62ab89f2.Pko7sI08RAKdF8R6%25lkp@intel.com/ + +Reported-by: kernel test robot +Signed-off-by: Joanne Koong +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20220616225407.1878436-1-joannelkoong@gmail.com +Stable-dep-of: 883743422ced ("bpf: Fix ref_obj_id for dynptr data slices in verifier") +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 3 --- + kernel/bpf/helpers.c | 12 ++++++------ + kernel/bpf/syscall.c | 2 +- + 3 files changed, 7 insertions(+), 10 deletions(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index ed352c00330c..647438166558 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -2273,12 +2273,9 @@ extern const struct bpf_func_proto bpf_for_each_map_elem_proto; + extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto; + extern const struct bpf_func_proto bpf_sk_setsockopt_proto; + extern const struct bpf_func_proto bpf_sk_getsockopt_proto; +-extern const struct bpf_func_proto bpf_kallsyms_lookup_name_proto; + extern const struct bpf_func_proto bpf_find_vma_proto; + extern const struct bpf_func_proto bpf_loop_proto; +-extern const struct bpf_func_proto bpf_strncmp_proto; + extern const struct bpf_func_proto bpf_copy_from_user_task_proto; +-extern const struct bpf_func_proto bpf_kptr_xchg_proto; + + const struct bpf_func_proto *tracing_prog_func_proto( + enum bpf_func_id func_id, const struct bpf_prog *prog); +diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c +index fb03f40116eb..ed7649b04704 100644 +--- a/kernel/bpf/helpers.c ++++ b/kernel/bpf/helpers.c +@@ -584,7 +584,7 @@ BPF_CALL_3(bpf_strncmp, const char *, s1, u32, s1_sz, const char *, s2) + return strncmp(s1, s2, s1_sz); + } + +-const struct bpf_func_proto bpf_strncmp_proto = { ++static const struct bpf_func_proto bpf_strncmp_proto = { + .func = bpf_strncmp, + .gpl_only = false, + .ret_type = RET_INTEGER, +@@ -1402,7 +1402,7 @@ BPF_CALL_2(bpf_kptr_xchg, void *, map_value, void *, ptr) + */ + #define BPF_PTR_POISON ((void *)((0xeB9FUL << 2) + POISON_POINTER_DELTA)) + +-const struct bpf_func_proto bpf_kptr_xchg_proto = { ++static const struct bpf_func_proto bpf_kptr_xchg_proto = { + .func = bpf_kptr_xchg, + .gpl_only = false, + .ret_type = RET_PTR_TO_BTF_ID_OR_NULL, +@@ -1489,7 +1489,7 @@ BPF_CALL_4(bpf_dynptr_from_mem, void *, data, u32, size, u64, flags, struct bpf_ + return err; + } + +-const struct bpf_func_proto bpf_dynptr_from_mem_proto = { ++static const struct bpf_func_proto bpf_dynptr_from_mem_proto = { + .func = bpf_dynptr_from_mem, + .gpl_only = false, + .ret_type = RET_INTEGER, +@@ -1516,7 +1516,7 @@ BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, struct bpf_dynptr_kern *, src + return 0; + } + +-const struct bpf_func_proto bpf_dynptr_read_proto = { ++static const struct bpf_func_proto bpf_dynptr_read_proto = { + .func = bpf_dynptr_read, + .gpl_only = false, + .ret_type = RET_INTEGER, +@@ -1544,7 +1544,7 @@ BPF_CALL_5(bpf_dynptr_write, struct bpf_dynptr_kern *, dst, u32, offset, void *, + return 0; + } + +-const struct bpf_func_proto bpf_dynptr_write_proto = { ++static const struct bpf_func_proto bpf_dynptr_write_proto = { + .func = bpf_dynptr_write, + .gpl_only = false, + .ret_type = RET_INTEGER, +@@ -1572,7 +1572,7 @@ BPF_CALL_3(bpf_dynptr_data, struct bpf_dynptr_kern *, ptr, u32, offset, u32, len + return (unsigned long)(ptr->data + ptr->offset + offset); + } + +-const struct bpf_func_proto bpf_dynptr_data_proto = { ++static const struct bpf_func_proto bpf_dynptr_data_proto = { + .func = bpf_dynptr_data, + .gpl_only = false, + .ret_type = RET_PTR_TO_DYNPTR_MEM_OR_NULL, +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index d334aeb23407..7a3444988c84 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -5138,7 +5138,7 @@ BPF_CALL_4(bpf_kallsyms_lookup_name, const char *, name, int, name_sz, int, flag + return *res ? 0 : -ENOENT; + } + +-const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { ++static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = { + .func = bpf_kallsyms_lookup_name, + .gpl_only = false, + .ret_type = RET_INTEGER, +-- +2.35.1 + diff --git a/queue-5.19/bpf-fix-reference-state-management-for-synchronous-c.patch b/queue-5.19/bpf-fix-reference-state-management-for-synchronous-c.patch new file mode 100644 index 00000000000..4d9b171e650 --- /dev/null +++ b/queue-5.19/bpf-fix-reference-state-management-for-synchronous-c.patch @@ -0,0 +1,190 @@ +From 92bb4163c18cb06a5d6c421990b8d7fc1059427b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 03:31:25 +0200 +Subject: bpf: Fix reference state management for synchronous callbacks + +From: Kumar Kartikeya Dwivedi + +[ Upstream commit 9d9d00ac29d0ef7ce426964de46fa6b380357d0a ] + +Currently, verifier verifies callback functions (sync and async) as if +they will be executed once, (i.e. it explores execution state as if the +function was being called once). The next insn to explore is set to +start of subprog and the exit from nested frame is handled using +curframe > 0 and prepare_func_exit. In case of async callback it uses a +customized variant of push_stack simulating a kind of branch to set up +custom state and execution context for the async callback. + +While this approach is simple and works when callback really will be +executed only once, it is unsafe for all of our current helpers which +are for_each style, i.e. they execute the callback multiple times. + +A callback releasing acquired references of the caller may do so +multiple times, but currently verifier sees it as one call inside the +frame, which then returns to caller. Hence, it thinks it released some +reference that the cb e.g. got access through callback_ctx (register +filled inside cb from spilled typed register on stack). + +Similarly, it may see that an acquire call is unpaired inside the +callback, so the caller will copy the reference state of callback and +then will have to release the register with new ref_obj_ids. But again, +the callback may execute multiple times, but the verifier will only +account for acquired references for a single symbolic execution of the +callback, which will cause leaks. + +Note that for async callback case, things are different. While currently +we have bpf_timer_set_callback which only executes it once, even for +multiple executions it would be safe, as reference state is NULL and +check_reference_leak would force program to release state before +BPF_EXIT. The state is also unaffected by analysis for the caller frame. +Hence async callback is safe. + +Since we want the reference state to be accessible, e.g. for pointers +loaded from stack through callback_ctx's PTR_TO_STACK, we still have to +copy caller's reference_state to callback's bpf_func_state, but we +enforce that whatever references it adds to that reference_state has +been released before it hits BPF_EXIT. This requires introducing a new +callback_ref member in the reference state to distinguish between caller +vs callee references. Hence, check_reference_leak now errors out if it +sees we are in callback_fn and we have not released callback_ref refs. +Since there can be multiple nested callbacks, like frame 0 -> cb1 -> cb2 +etc. we need to also distinguish between whether this particular ref +belongs to this callback frame or parent, and only error for our own, so +we store state->frameno (which is always non-zero for callbacks). + +In short, callbacks can read parent reference_state, but cannot mutate +it, to be able to use pointers acquired by the caller. They must only +undo their changes (by releasing their own acquired_refs before +BPF_EXIT) on top of caller reference_state before returning (at which +point the caller and callback state will match anyway, so no need to +copy it back to caller). + +Fixes: 69c087ba6225 ("bpf: Add bpf_for_each_map_elem() helper") +Signed-off-by: Kumar Kartikeya Dwivedi +Link: https://lore.kernel.org/r/20220823013125.24938-1-memxor@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + include/linux/bpf_verifier.h | 11 ++++++++++ + kernel/bpf/verifier.c | 42 ++++++++++++++++++++++++++++-------- + 2 files changed, 44 insertions(+), 9 deletions(-) + +diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h +index e8439f6cbe57..e66ee8d87e27 100644 +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -212,6 +212,17 @@ struct bpf_reference_state { + * is used purely to inform the user of a reference leak. + */ + int insn_idx; ++ /* There can be a case like: ++ * main (frame 0) ++ * cb (frame 1) ++ * func (frame 3) ++ * cb (frame 4) ++ * Hence for frame 4, if callback_ref just stored boolean, it would be ++ * impossible to distinguish nested callback refs. Hence store the ++ * frameno and compare that to callback_ref in check_reference_leak when ++ * exiting a callback function. ++ */ ++ int callback_ref; + }; + + /* state of the program: +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 210793b5cd6c..b908ff6e520f 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1092,6 +1092,7 @@ static int acquire_reference_state(struct bpf_verifier_env *env, int insn_idx) + id = ++env->id_gen; + state->refs[new_ofs].id = id; + state->refs[new_ofs].insn_idx = insn_idx; ++ state->refs[new_ofs].callback_ref = state->in_callback_fn ? state->frameno : 0; + + return id; + } +@@ -1104,6 +1105,9 @@ static int release_reference_state(struct bpf_func_state *state, int ptr_id) + last_idx = state->acquired_refs - 1; + for (i = 0; i < state->acquired_refs; i++) { + if (state->refs[i].id == ptr_id) { ++ /* Cannot release caller references in callbacks */ ++ if (state->in_callback_fn && state->refs[i].callback_ref != state->frameno) ++ return -EINVAL; + if (last_idx && i != last_idx) + memcpy(&state->refs[i], &state->refs[last_idx], + sizeof(*state->refs)); +@@ -6919,10 +6923,17 @@ static int prepare_func_exit(struct bpf_verifier_env *env, int *insn_idx) + caller->regs[BPF_REG_0] = *r0; + } + +- /* Transfer references to the caller */ +- err = copy_reference_state(caller, callee); +- if (err) +- return err; ++ /* callback_fn frame should have released its own additions to parent's ++ * reference state at this point, or check_reference_leak would ++ * complain, hence it must be the same as the caller. There is no need ++ * to copy it back. ++ */ ++ if (!callee->in_callback_fn) { ++ /* Transfer references to the caller */ ++ err = copy_reference_state(caller, callee); ++ if (err) ++ return err; ++ } + + *insn_idx = callee->callsite + 1; + if (env->log.level & BPF_LOG_LEVEL) { +@@ -7044,13 +7055,20 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta, + static int check_reference_leak(struct bpf_verifier_env *env) + { + struct bpf_func_state *state = cur_func(env); ++ bool refs_lingering = false; + int i; + ++ if (state->frameno && !state->in_callback_fn) ++ return 0; ++ + for (i = 0; i < state->acquired_refs; i++) { ++ if (state->in_callback_fn && state->refs[i].callback_ref != state->frameno) ++ continue; + verbose(env, "Unreleased reference id=%d alloc_insn=%d\n", + state->refs[i].id, state->refs[i].insn_idx); ++ refs_lingering = true; + } +- return state->acquired_refs ? -EINVAL : 0; ++ return refs_lingering ? -EINVAL : 0; + } + + static int check_bpf_snprintf_call(struct bpf_verifier_env *env, +@@ -12244,6 +12262,16 @@ static int do_check(struct bpf_verifier_env *env) + return -EINVAL; + } + ++ /* We must do check_reference_leak here before ++ * prepare_func_exit to handle the case when ++ * state->curframe > 0, it may be a callback ++ * function, for which reference_state must ++ * match caller reference state when it exits. ++ */ ++ err = check_reference_leak(env); ++ if (err) ++ return err; ++ + if (state->curframe) { + /* exit from nested function */ + err = prepare_func_exit(env, &env->insn_idx); +@@ -12253,10 +12281,6 @@ static int do_check(struct bpf_verifier_env *env) + continue; + } + +- err = check_reference_leak(env); +- if (err) +- return err; +- + err = check_return_code(env); + if (err) + return err; +-- +2.35.1 + diff --git a/queue-5.19/bpf-propagate-error-from-htab_lock_bucket-to-userspa.patch b/queue-5.19/bpf-propagate-error-from-htab_lock_bucket-to-userspa.patch new file mode 100644 index 00000000000..b4a540206f6 --- /dev/null +++ b/queue-5.19/bpf-propagate-error-from-htab_lock_bucket-to-userspa.patch @@ -0,0 +1,50 @@ +From 78ef66bbaaf81736f28a0664edbc781116026a1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 12:26:28 +0800 +Subject: bpf: Propagate error from htab_lock_bucket() to userspace + +From: Hou Tao + +[ Upstream commit 66a7a92e4d0d091e79148a4c6ec15d1da65f4280 ] + +In __htab_map_lookup_and_delete_batch() if htab_lock_bucket() returns +-EBUSY, it will go to next bucket. Going to next bucket may not only +skip the elements in current bucket silently, but also incur +out-of-bound memory access or expose kernel memory to userspace if +current bucket_cnt is greater than bucket_size or zero. + +Fixing it by stopping batch operation and returning -EBUSY when +htab_lock_bucket() fails, and the application can retry or skip the busy +batch as needed. + +Fixes: 20b6cc34ea74 ("bpf: Avoid hashtab deadlock with map_locked") +Reported-by: Hao Sun +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20220831042629.130006-3-houtao@huaweicloud.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + kernel/bpf/hashtab.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c +index 717f85973443..e20f3d0e3fc7 100644 +--- a/kernel/bpf/hashtab.c ++++ b/kernel/bpf/hashtab.c +@@ -1704,8 +1704,11 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map, + /* do not grab the lock unless need it (bucket_cnt > 0). */ + if (locked) { + ret = htab_lock_bucket(htab, b, batch, &flags); +- if (ret) +- goto next_batch; ++ if (ret) { ++ rcu_read_unlock(); ++ bpf_enable_instrumentation(); ++ goto after_loop; ++ } + } + + bucket_cnt = 0; +-- +2.35.1 + diff --git a/queue-5.19/bpf-use-bpf_prog_pack-for-bpf_dispatcher.patch b/queue-5.19/bpf-use-bpf_prog_pack-for-bpf_dispatcher.patch new file mode 100644 index 00000000000..26b784e0a1f --- /dev/null +++ b/queue-5.19/bpf-use-bpf_prog_pack-for-bpf_dispatcher.patch @@ -0,0 +1,244 @@ +From 623a14ad019ef918cd9a41bc27148dd017bbe36a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 11:47:38 -0700 +Subject: bpf: use bpf_prog_pack for bpf_dispatcher + +From: Song Liu + +[ Upstream commit 19c02415da2345d0dda2b5c4495bc17cc14b18b5 ] + +Allocate bpf_dispatcher with bpf_prog_pack_alloc so that bpf_dispatcher +can share pages with bpf programs. + +arch_prepare_bpf_dispatcher() is updated to provide a RW buffer as working +area for arch code to write to. + +This also fixes CPA W^X warnning like: + +CPA refuse W^X violation: 8000000000000163 -> 0000000000000163 range: ... + +Signed-off-by: Song Liu +Link: https://lore.kernel.org/r/20220926184739.3512547-2-song@kernel.org +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + arch/x86/net/bpf_jit_comp.c | 16 ++++++++-------- + include/linux/bpf.h | 3 ++- + include/linux/filter.h | 5 +++++ + kernel/bpf/core.c | 9 +++++++-- + kernel/bpf/dispatcher.c | 27 +++++++++++++++++++++------ + 5 files changed, 43 insertions(+), 17 deletions(-) + +diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c +index 41d170653e8d..fc4d899f10f6 100644 +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -2216,7 +2216,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i + return ret; + } + +-static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs) ++static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image, u8 *buf) + { + u8 *jg_reloc, *prog = *pprog; + int pivot, err, jg_bytes = 1; +@@ -2232,12 +2232,12 @@ static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs) + EMIT2_off32(0x81, add_1reg(0xF8, BPF_REG_3), + progs[a]); + err = emit_cond_near_jump(&prog, /* je func */ +- (void *)progs[a], prog, ++ (void *)progs[a], image + (prog - buf), + X86_JE); + if (err) + return err; + +- emit_indirect_jump(&prog, 2 /* rdx */, prog); ++ emit_indirect_jump(&prog, 2 /* rdx */, image + (prog - buf)); + + *pprog = prog; + return 0; +@@ -2262,7 +2262,7 @@ static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs) + jg_reloc = prog; + + err = emit_bpf_dispatcher(&prog, a, a + pivot, /* emit lower_part */ +- progs); ++ progs, image, buf); + if (err) + return err; + +@@ -2276,7 +2276,7 @@ static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs) + emit_code(jg_reloc - jg_bytes, jg_offset, jg_bytes); + + err = emit_bpf_dispatcher(&prog, a + pivot + 1, /* emit upper_part */ +- b, progs); ++ b, progs, image, buf); + if (err) + return err; + +@@ -2296,12 +2296,12 @@ static int cmp_ips(const void *a, const void *b) + return 0; + } + +-int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs) ++int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs) + { +- u8 *prog = image; ++ u8 *prog = buf; + + sort(funcs, num_funcs, sizeof(funcs[0]), cmp_ips, NULL); +- return emit_bpf_dispatcher(&prog, 0, num_funcs - 1, funcs); ++ return emit_bpf_dispatcher(&prog, 0, num_funcs - 1, funcs, image, buf); + } + + struct x64_jit_data { +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 647438166558..33ec4658c1ee 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -869,6 +869,7 @@ struct bpf_dispatcher { + struct bpf_dispatcher_prog progs[BPF_DISPATCHER_MAX]; + int num_progs; + void *image; ++ void *rw_image; + u32 image_off; + struct bpf_ksym ksym; + }; +@@ -888,7 +889,7 @@ int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_trampolin + struct bpf_trampoline *bpf_trampoline_get(u64 key, + struct bpf_attach_target_info *tgt_info); + void bpf_trampoline_put(struct bpf_trampoline *tr); +-int arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs); ++int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs); + #define BPF_DISPATCHER_INIT(_name) { \ + .mutex = __MUTEX_INITIALIZER(_name.mutex), \ + .func = &_name##_func, \ +diff --git a/include/linux/filter.h b/include/linux/filter.h +index 8fd2e2f58eeb..e11335c70982 100644 +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -1052,6 +1052,8 @@ extern long bpf_jit_limit_max; + + typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size); + ++void bpf_jit_fill_hole_with_zero(void *area, unsigned int size); ++ + struct bpf_binary_header * + bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, + unsigned int alignment, +@@ -1064,6 +1066,9 @@ void bpf_jit_free(struct bpf_prog *fp); + struct bpf_binary_header * + bpf_jit_binary_pack_hdr(const struct bpf_prog *fp); + ++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns); ++void bpf_prog_pack_free(struct bpf_binary_header *hdr); ++ + static inline bool bpf_prog_kallsyms_verify_off(const struct bpf_prog *fp) + { + return list_empty(&fp->aux->ksym.lnode) || +diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c +index cf44ff50b1f2..be736aa97927 100644 +--- a/kernel/bpf/core.c ++++ b/kernel/bpf/core.c +@@ -822,6 +822,11 @@ struct bpf_prog_pack { + unsigned long bitmap[]; + }; + ++void bpf_jit_fill_hole_with_zero(void *area, unsigned int size) ++{ ++ memset(area, 0, size); ++} ++ + #define BPF_PROG_SIZE_TO_NBITS(size) (round_up(size, BPF_PROG_CHUNK_SIZE) / BPF_PROG_CHUNK_SIZE) + + static size_t bpf_prog_pack_size = -1; +@@ -892,7 +897,7 @@ static struct bpf_prog_pack *alloc_new_pack(bpf_jit_fill_hole_t bpf_fill_ill_ins + return pack; + } + +-static void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) ++void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insns) + { + unsigned int nbits = BPF_PROG_SIZE_TO_NBITS(size); + struct bpf_prog_pack *pack; +@@ -936,7 +941,7 @@ static void *bpf_prog_pack_alloc(u32 size, bpf_jit_fill_hole_t bpf_fill_ill_insn + return ptr; + } + +-static void bpf_prog_pack_free(struct bpf_binary_header *hdr) ++void bpf_prog_pack_free(struct bpf_binary_header *hdr) + { + struct bpf_prog_pack *pack = NULL, *tmp; + unsigned int nbits; +diff --git a/kernel/bpf/dispatcher.c b/kernel/bpf/dispatcher.c +index 2444bd15cc2d..fa64b80b8bca 100644 +--- a/kernel/bpf/dispatcher.c ++++ b/kernel/bpf/dispatcher.c +@@ -85,12 +85,12 @@ static bool bpf_dispatcher_remove_prog(struct bpf_dispatcher *d, + return false; + } + +-int __weak arch_prepare_bpf_dispatcher(void *image, s64 *funcs, int num_funcs) ++int __weak arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_funcs) + { + return -ENOTSUPP; + } + +-static int bpf_dispatcher_prepare(struct bpf_dispatcher *d, void *image) ++static int bpf_dispatcher_prepare(struct bpf_dispatcher *d, void *image, void *buf) + { + s64 ips[BPF_DISPATCHER_MAX] = {}, *ipsp = &ips[0]; + int i; +@@ -99,12 +99,12 @@ static int bpf_dispatcher_prepare(struct bpf_dispatcher *d, void *image) + if (d->progs[i].prog) + *ipsp++ = (s64)(uintptr_t)d->progs[i].prog->bpf_func; + } +- return arch_prepare_bpf_dispatcher(image, &ips[0], d->num_progs); ++ return arch_prepare_bpf_dispatcher(image, buf, &ips[0], d->num_progs); + } + + static void bpf_dispatcher_update(struct bpf_dispatcher *d, int prev_num_progs) + { +- void *old, *new; ++ void *old, *new, *tmp; + u32 noff; + int err; + +@@ -117,8 +117,14 @@ static void bpf_dispatcher_update(struct bpf_dispatcher *d, int prev_num_progs) + } + + new = d->num_progs ? d->image + noff : NULL; ++ tmp = d->num_progs ? d->rw_image + noff : NULL; + if (new) { +- if (bpf_dispatcher_prepare(d, new)) ++ /* Prepare the dispatcher in d->rw_image. Then use ++ * bpf_arch_text_copy to update d->image, which is RO+X. ++ */ ++ if (bpf_dispatcher_prepare(d, new, tmp)) ++ return; ++ if (IS_ERR(bpf_arch_text_copy(new, tmp, PAGE_SIZE / 2))) + return; + } + +@@ -140,9 +146,18 @@ void bpf_dispatcher_change_prog(struct bpf_dispatcher *d, struct bpf_prog *from, + + mutex_lock(&d->mutex); + if (!d->image) { +- d->image = bpf_jit_alloc_exec_page(); ++ d->image = bpf_prog_pack_alloc(PAGE_SIZE, bpf_jit_fill_hole_with_zero); + if (!d->image) + goto out; ++ d->rw_image = bpf_jit_alloc_exec(PAGE_SIZE); ++ if (!d->rw_image) { ++ u32 size = PAGE_SIZE; ++ ++ bpf_arch_text_copy(d->image, &size, sizeof(size)); ++ bpf_prog_pack_free((struct bpf_binary_header *)d->image); ++ d->image = NULL; ++ goto out; ++ } + bpf_image_ksym_add(d->image, &d->ksym); + } + +-- +2.35.1 + diff --git a/queue-5.19/bpf-use-this_cpu_-inc-dec-inc_return-for-bpf_task_st.patch b/queue-5.19/bpf-use-this_cpu_-inc-dec-inc_return-for-bpf_task_st.patch new file mode 100644 index 00000000000..1ed02e81fc5 --- /dev/null +++ b/queue-5.19/bpf-use-this_cpu_-inc-dec-inc_return-for-bpf_task_st.patch @@ -0,0 +1,80 @@ +From 2421183c133b6d64cbc134013de69ecc754ca355 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 14:19:35 +0800 +Subject: bpf: Use this_cpu_{inc|dec|inc_return} for bpf_task_storage_busy + +From: Hou Tao + +[ Upstream commit 197827a05e13808c60f52632e9887eede63f1c16 ] + +Now migrate_disable() does not disable preemption and under some +architectures (e.g. arm64) __this_cpu_{inc|dec|inc_return} are neither +preemption-safe nor IRQ-safe, so for fully preemptible kernel concurrent +lookups or updates on the same task local storage and on the same CPU +may make bpf_task_storage_busy be imbalanced, and +bpf_task_storage_trylock() on the specific cpu will always fail. + +Fixing it by using this_cpu_{inc|dec|inc_return} when manipulating +bpf_task_storage_busy. + +Fixes: bc235cdb423a ("bpf: Prevent deadlock from recursive bpf_task_storage_[get|delete]") +Signed-off-by: Hou Tao +Acked-by: Alexei Starovoitov +Link: https://lore.kernel.org/r/20220901061938.3789460-2-houtao@huaweicloud.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + kernel/bpf/bpf_local_storage.c | 4 ++-- + kernel/bpf/bpf_task_storage.c | 8 ++++---- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/kernel/bpf/bpf_local_storage.c b/kernel/bpf/bpf_local_storage.c +index 8ce40fd869f6..d13ffb00e981 100644 +--- a/kernel/bpf/bpf_local_storage.c ++++ b/kernel/bpf/bpf_local_storage.c +@@ -555,11 +555,11 @@ void bpf_local_storage_map_free(struct bpf_local_storage_map *smap, + struct bpf_local_storage_elem, map_node))) { + if (busy_counter) { + migrate_disable(); +- __this_cpu_inc(*busy_counter); ++ this_cpu_inc(*busy_counter); + } + bpf_selem_unlink(selem, false); + if (busy_counter) { +- __this_cpu_dec(*busy_counter); ++ this_cpu_dec(*busy_counter); + migrate_enable(); + } + cond_resched_rcu(); +diff --git a/kernel/bpf/bpf_task_storage.c b/kernel/bpf/bpf_task_storage.c +index e9014dc62682..6f290623347e 100644 +--- a/kernel/bpf/bpf_task_storage.c ++++ b/kernel/bpf/bpf_task_storage.c +@@ -26,20 +26,20 @@ static DEFINE_PER_CPU(int, bpf_task_storage_busy); + static void bpf_task_storage_lock(void) + { + migrate_disable(); +- __this_cpu_inc(bpf_task_storage_busy); ++ this_cpu_inc(bpf_task_storage_busy); + } + + static void bpf_task_storage_unlock(void) + { +- __this_cpu_dec(bpf_task_storage_busy); ++ this_cpu_dec(bpf_task_storage_busy); + migrate_enable(); + } + + static bool bpf_task_storage_trylock(void) + { + migrate_disable(); +- if (unlikely(__this_cpu_inc_return(bpf_task_storage_busy) != 1)) { +- __this_cpu_dec(bpf_task_storage_busy); ++ if (unlikely(this_cpu_inc_return(bpf_task_storage_busy) != 1)) { ++ this_cpu_dec(bpf_task_storage_busy); + migrate_enable(); + return false; + } +-- +2.35.1 + diff --git a/queue-5.19/bpf-use-this_cpu_-inc_return-dec-for-prog-active.patch b/queue-5.19/bpf-use-this_cpu_-inc_return-dec-for-prog-active.patch new file mode 100644 index 00000000000..1a53aff91c8 --- /dev/null +++ b/queue-5.19/bpf-use-this_cpu_-inc_return-dec-for-prog-active.patch @@ -0,0 +1,69 @@ +From 6451c042bba14e0780cfacdb4a53fc6875cf08e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 14:19:36 +0800 +Subject: bpf: Use this_cpu_{inc_return|dec} for prog->active + +From: Hou Tao + +[ Upstream commit c89e843a11f1075d27684f6b42256213e4592383 ] + +Both __this_cpu_inc_return() and __this_cpu_dec() are not preemption +safe and now migrate_disable() doesn't disable preemption, so the update +of prog-active is not atomic and in theory under fully preemptible kernel +recurisve prevention may do not work. + +Fixing by using the preemption-safe and IRQ-safe variants. + +Fixes: ca06f55b9002 ("bpf: Add per-program recursion prevention mechanism") +Signed-off-by: Hou Tao +Acked-by: Alexei Starovoitov +Link: https://lore.kernel.org/r/20220901061938.3789460-3-houtao@huaweicloud.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + kernel/bpf/trampoline.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c +index 93c7675f0c9e..fe4f4d9d043b 100644 +--- a/kernel/bpf/trampoline.c ++++ b/kernel/bpf/trampoline.c +@@ -585,7 +585,7 @@ u64 notrace __bpf_prog_enter(struct bpf_prog *prog, struct bpf_tramp_run_ctx *ru + + run_ctx->saved_run_ctx = bpf_set_run_ctx(&run_ctx->run_ctx); + +- if (unlikely(__this_cpu_inc_return(*(prog->active)) != 1)) { ++ if (unlikely(this_cpu_inc_return(*(prog->active)) != 1)) { + inc_misses_counter(prog); + return 0; + } +@@ -620,7 +620,7 @@ void notrace __bpf_prog_exit(struct bpf_prog *prog, u64 start, struct bpf_tramp_ + bpf_reset_run_ctx(run_ctx->saved_run_ctx); + + update_prog_stats(prog, start); +- __this_cpu_dec(*(prog->active)); ++ this_cpu_dec(*(prog->active)); + migrate_enable(); + rcu_read_unlock(); + } +@@ -631,7 +631,7 @@ u64 notrace __bpf_prog_enter_sleepable(struct bpf_prog *prog, struct bpf_tramp_r + migrate_disable(); + might_fault(); + +- if (unlikely(__this_cpu_inc_return(*(prog->active)) != 1)) { ++ if (unlikely(this_cpu_inc_return(*(prog->active)) != 1)) { + inc_misses_counter(prog); + return 0; + } +@@ -647,7 +647,7 @@ void notrace __bpf_prog_exit_sleepable(struct bpf_prog *prog, u64 start, + bpf_reset_run_ctx(run_ctx->saved_run_ctx); + + update_prog_stats(prog, start); +- __this_cpu_dec(*(prog->active)); ++ this_cpu_dec(*(prog->active)); + migrate_enable(); + rcu_read_unlock_trace(); + } +-- +2.35.1 + diff --git a/queue-5.19/bpftool-clear-errno-after-libcap-s-checks.patch b/queue-5.19/bpftool-clear-errno-after-libcap-s-checks.patch new file mode 100644 index 00000000000..9fc4e799433 --- /dev/null +++ b/queue-5.19/bpftool-clear-errno-after-libcap-s-checks.patch @@ -0,0 +1,70 @@ +From bd1b040c80f91a12a3a32be91d96ea3839f04456 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 17:22:05 +0100 +Subject: bpftool: Clear errno after libcap's checks + +From: Quentin Monnet + +[ Upstream commit cea558855c39b7f1f02ff50dcf701ca6596bc964 ] + +When bpftool is linked against libcap, the library runs a "constructor" +function to compute the number of capabilities of the running kernel +[0], at the beginning of the execution of the program. As part of this, +it performs multiple calls to prctl(). Some of these may fail, and set +errno to a non-zero value: + + # strace -e prctl ./bpftool version + prctl(PR_CAPBSET_READ, CAP_MAC_OVERRIDE) = 1 + prctl(PR_CAPBSET_READ, 0x30 /* CAP_??? */) = -1 EINVAL (Invalid argument) + prctl(PR_CAPBSET_READ, CAP_CHECKPOINT_RESTORE) = 1 + prctl(PR_CAPBSET_READ, 0x2c /* CAP_??? */) = -1 EINVAL (Invalid argument) + prctl(PR_CAPBSET_READ, 0x2a /* CAP_??? */) = -1 EINVAL (Invalid argument) + prctl(PR_CAPBSET_READ, 0x29 /* CAP_??? */) = -1 EINVAL (Invalid argument) + ** fprintf added at the top of main(): we have errno == 1 + ./bpftool v7.0.0 + using libbpf v1.0 + features: libbfd, libbpf_strict, skeletons + +++ exited with 0 +++ + +This has been addressed in libcap 2.63 [1], but until this version is +available everywhere, we can fix it on bpftool side. + +Let's clean errno at the beginning of the main() function, to make sure +that these checks do not interfere with the batch mode, where we error +out if errno is set after a bpftool command. + + [0] https://git.kernel.org/pub/scm/libs/libcap/libcap.git/tree/libcap/cap_alloc.c?h=libcap-2.65#n20 + [1] https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=f25a1b7e69f7b33e6afb58b3e38f3450b7d2d9a0 + +Signed-off-by: Quentin Monnet +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20220815162205.45043-1-quentin@isovalent.com +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c +index 9062ef2b8767..0881437587ba 100644 +--- a/tools/bpf/bpftool/main.c ++++ b/tools/bpf/bpftool/main.c +@@ -435,6 +435,16 @@ int main(int argc, char **argv) + + setlinebuf(stdout); + ++#ifdef USE_LIBCAP ++ /* Libcap < 2.63 hooks before main() to compute the number of ++ * capabilities of the running kernel, and doing so it calls prctl() ++ * which may fail and set errno to non-zero. ++ * Let's reset errno to make sure this does not interfere with the ++ * batch mode. ++ */ ++ errno = 0; ++#endif ++ + last_do_help = do_help; + pretty_output = false; + json_output = false; +-- +2.35.1 + diff --git a/queue-5.19/bpftool-fix-a-wrong-type-cast-in-btf_dumper_int.patch b/queue-5.19/bpftool-fix-a-wrong-type-cast-in-btf_dumper_int.patch new file mode 100644 index 00000000000..28943aa232e --- /dev/null +++ b/queue-5.19/bpftool-fix-a-wrong-type-cast-in-btf_dumper_int.patch @@ -0,0 +1,40 @@ +From 5cf664e8c99b1dc233bdec8df91e6be0a7f448e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 15:59:00 -0700 +Subject: bpftool: Fix a wrong type cast in btf_dumper_int + +From: Lam Thai + +[ Upstream commit 7184aef9c0f7a81db8fd18d183ee42481d89bf35 ] + +When `data` points to a boolean value, casting it to `int *` is problematic +and could lead to a wrong value being passed to `jsonw_bool`. Change the +cast to `bool *` instead. + +Fixes: b12d6ec09730 ("bpf: btf: add btf print functionality") +Signed-off-by: Lam Thai +Signed-off-by: Andrii Nakryiko +Reviewed-by: Quentin Monnet +Acked-by: John Fastabend +Link: https://lore.kernel.org/bpf/20220824225859.9038-1-lamthai@arista.com +Signed-off-by: Sasha Levin +--- + tools/bpf/bpftool/btf_dumper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c +index f5dddf8ef404..6d041d1f5395 100644 +--- a/tools/bpf/bpftool/btf_dumper.c ++++ b/tools/bpf/bpftool/btf_dumper.c +@@ -426,7 +426,7 @@ static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset, + *(char *)data); + break; + case BTF_INT_BOOL: +- jsonw_bool(jw, *(int *)data); ++ jsonw_bool(jw, *(bool *)data); + break; + default: + /* shouldn't happen */ +-- +2.35.1 + diff --git a/queue-5.19/btrfs-add-kcsan-annotations-for-unlocked-access-to-b.patch b/queue-5.19/btrfs-add-kcsan-annotations-for-unlocked-access-to-b.patch new file mode 100644 index 00000000000..bcef590419e --- /dev/null +++ b/queue-5.19/btrfs-add-kcsan-annotations-for-unlocked-access-to-b.patch @@ -0,0 +1,90 @@ +From 89489c0edd36ee5ab911d4152849aa4d96e85ac5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 18:32:23 +0200 +Subject: btrfs: add KCSAN annotations for unlocked access to block_rsv->full + +From: David Sterba + +[ Upstream commit 748f553c3c4c4f175c6c834358632aff802d72cf ] + +KCSAN reports that there's unlocked access mixed with locked access, +which is technically correct but is not a bug. To avoid false alerts at +least from KCSAN, add annotation and use a wrapper whenever ->full is +accessed for read outside of lock. + +It is used as a fast check and only advisory. In the worst case the +block reserve is found !full and becomes full in the meantime, but +properly handled. + +Depending on the value of ->full, btrfs_block_rsv_release decides +where to return the reservation, and block_rsv_release_bytes handles a +NULL pointer for block_rsv and if it's not NULL then it double checks +the full status under a lock. + +Link: https://lore.kernel.org/linux-btrfs/CAAwBoOJDjei5Hnem155N_cJwiEkVwJYvgN-tQrwWbZQGhFU=cA@mail.gmail.com/ +Link: https://lore.kernel.org/linux-btrfs/YvHU/vsXd7uz5V6j@hungrycats.org +Reported-by: Zygo Blaxell +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/block-rsv.c | 2 +- + fs/btrfs/block-rsv.h | 9 +++++++++ + fs/btrfs/transaction.c | 4 ++-- + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index b3ee49b0b1e8..7a586fccddda 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -286,7 +286,7 @@ u64 btrfs_block_rsv_release(struct btrfs_fs_info *fs_info, + */ + if (block_rsv == delayed_rsv) + target = global_rsv; +- else if (block_rsv != global_rsv && !delayed_rsv->full) ++ else if (block_rsv != global_rsv && !btrfs_block_rsv_full(delayed_rsv)) + target = delayed_rsv; + + if (target && block_rsv->space_info != target->space_info) +diff --git a/fs/btrfs/block-rsv.h b/fs/btrfs/block-rsv.h +index 3b67ff08d434..fe97f4112028 100644 +--- a/fs/btrfs/block-rsv.h ++++ b/fs/btrfs/block-rsv.h +@@ -91,4 +91,13 @@ static inline void btrfs_unuse_block_rsv(struct btrfs_fs_info *fs_info, + btrfs_block_rsv_release(fs_info, block_rsv, 0, NULL); + } + ++/* ++ * Fast path to check if the reserve is full, may be carefully used outside of ++ * locks. ++ */ ++static inline bool btrfs_block_rsv_full(const struct btrfs_block_rsv *rsv) ++{ ++ return data_race(rsv->full); ++} ++ + #endif /* BTRFS_BLOCK_RSV_H */ +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 875b801ab3d7..eec5c17b7c5a 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -624,7 +624,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items, + */ + num_bytes = btrfs_calc_insert_metadata_size(fs_info, num_items); + if (flush == BTRFS_RESERVE_FLUSH_ALL && +- delayed_refs_rsv->full == 0) { ++ btrfs_block_rsv_full(delayed_refs_rsv) == 0) { + delayed_refs_bytes = num_bytes; + num_bytes <<= 1; + } +@@ -649,7 +649,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items, + if (rsv->space_info->force_alloc) + do_chunk_alloc = true; + } else if (num_items == 0 && flush == BTRFS_RESERVE_FLUSH_ALL && +- !delayed_refs_rsv->full) { ++ !btrfs_block_rsv_full(delayed_refs_rsv)) { + /* + * Some people call with btrfs_start_transaction(root, 0) + * because they can be throttled, but have some other mechanism +-- +2.35.1 + diff --git a/queue-5.19/btrfs-add-macros-for-annotating-wait-events-with-loc.patch b/queue-5.19/btrfs-add-macros-for-annotating-wait-events-with-loc.patch new file mode 100644 index 00000000000..ddb4b4aad91 --- /dev/null +++ b/queue-5.19/btrfs-add-macros-for-annotating-wait-events-with-loc.patch @@ -0,0 +1,143 @@ +From e444bea4707bcdad792b420041dfd32f9201d1d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 15:11:46 -0700 +Subject: btrfs: add macros for annotating wait events with lockdep + +From: Ioannis Angelakopoulos + +[ Upstream commit ab9a323f9ab576000795285dd7ac6afeedf29e32 ] + +Introduce four macros that are used to annotate wait events in btrfs code +with lockdep; + + 1) the btrfs_lockdep_init_map + 2) the btrfs_lockdep_acquire, + 3) the btrfs_lockdep_release + 4) the btrfs_might_wait_for_event macros. + +The btrfs_lockdep_init_map macro is used to initialize a lockdep map. + +The btrfs_lockdep_ macros are used by threads to take +the lockdep map as readers (shared lock) and release it, respectively. + +The btrfs_might_wait_for_event macro is used by threads to take the +lockdep map as writers (exclusive lock) and release it. + +In general, the lockdep annotation for wait events work as follows: + +The condition for a wait event can be modified and signaled at the same +time by multiple threads. These threads hold the lockdep map as readers +when they enter a context in which blocking would prevent signaling the +condition. Frequently, this occurs when a thread violates a condition +(lockdep map acquire), before restoring it and signaling it at a later +point (lockdep map release). + +The threads that block on the wait event take the lockdep map as writers +(exclusive lock). These threads have to block until all the threads that +hold the lockdep map as readers signal the condition for the wait event +and release the lockdep map. + +The lockdep annotation is used to warn about potential deadlock scenarios +that involve the threads that modify and signal the wait event condition +and threads that block on the wait event. A simple example is illustrated +below: + +Without lockdep: + +TA TB +cond = false + lock(A) + wait_event(w, cond) + unlock(A) +lock(A) +cond = true +signal(w) +unlock(A) + +With lockdep: + +TA TB +rwsem_acquire_read(lockdep_map) +cond = false + lock(A) + rwsem_acquire(lockdep_map) + rwsem_release(lockdep_map) + wait_event(w, cond) + unlock(A) +lock(A) +cond = true +signal(w) +unlock(A) +rwsem_release(lockdep_map) + +In the second case, with the lockdep annotation, lockdep would warn about +an ABBA deadlock, while the first case would just deadlock at some point. + +Reviewed-by: Josef Bacik +Signed-off-by: Ioannis Angelakopoulos +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/ctree.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index 1bbc810574f2..8d35db5b2b62 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -1148,6 +1148,51 @@ enum { + BTRFS_ROOT_RESET_LOCKDEP_CLASS, + }; + ++/* ++ * Lockdep annotation for wait events. ++ * ++ * @owner: The struct where the lockdep map is defined ++ * @lock: The lockdep map corresponding to a wait event ++ * ++ * This macro is used to annotate a wait event. In this case a thread acquires ++ * the lockdep map as writer (exclusive lock) because it has to block until all ++ * the threads that hold the lock as readers signal the condition for the wait ++ * event and release their locks. ++ */ ++#define btrfs_might_wait_for_event(owner, lock) \ ++ do { \ ++ rwsem_acquire(&owner->lock##_map, 0, 0, _THIS_IP_); \ ++ rwsem_release(&owner->lock##_map, _THIS_IP_); \ ++ } while (0) ++ ++/* ++ * Protection for the resource/condition of a wait event. ++ * ++ * @owner: The struct where the lockdep map is defined ++ * @lock: The lockdep map corresponding to a wait event ++ * ++ * Many threads can modify the condition for the wait event at the same time ++ * and signal the threads that block on the wait event. The threads that modify ++ * the condition and do the signaling acquire the lock as readers (shared ++ * lock). ++ */ ++#define btrfs_lockdep_acquire(owner, lock) \ ++ rwsem_acquire_read(&owner->lock##_map, 0, 0, _THIS_IP_) ++ ++/* ++ * Used after signaling the condition for a wait event to release the lockdep ++ * map held by a reader thread. ++ */ ++#define btrfs_lockdep_release(owner, lock) \ ++ rwsem_release(&owner->lock##_map, _THIS_IP_) ++ ++/* Initialization of the lockdep map */ ++#define btrfs_lockdep_init_map(owner, lock) \ ++ do { \ ++ static struct lock_class_key lock##_key; \ ++ lockdep_init_map(&owner->lock##_map, #lock, &lock##_key, 0); \ ++ } while (0) ++ + static inline void btrfs_wake_unfinished_drop(struct btrfs_fs_info *fs_info) + { + clear_and_wake_up_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags); +-- +2.35.1 + diff --git a/queue-5.19/btrfs-call-__btrfs_remove_free_space_cache_locked-on.patch b/queue-5.19/btrfs-call-__btrfs_remove_free_space_cache_locked-on.patch new file mode 100644 index 00000000000..34a4760e637 --- /dev/null +++ b/queue-5.19/btrfs-call-__btrfs_remove_free_space_cache_locked-on.patch @@ -0,0 +1,156 @@ +From 781a234850014298e1d5b59e66ab900529f400b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Aug 2022 16:10:26 -0400 +Subject: btrfs: call __btrfs_remove_free_space_cache_locked on cache load + failure + +From: Josef Bacik + +[ Upstream commit 8a1ae2781dee9fc21ca82db682d37bea4bd074ad ] + +Now that lockdep is staying enabled through our entire CI runs I started +seeing the following stack in generic/475 + +------------[ cut here ]------------ +WARNING: CPU: 1 PID: 2171864 at fs/btrfs/discard.c:604 btrfs_discard_update_discardable+0x98/0xb0 +CPU: 1 PID: 2171864 Comm: kworker/u4:0 Not tainted 5.19.0-rc8+ #789 +Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 +Workqueue: btrfs-cache btrfs_work_helper +RIP: 0010:btrfs_discard_update_discardable+0x98/0xb0 +RSP: 0018:ffffb857c2f7bad0 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: ffff8c85c605c200 RCX: 0000000000000001 +RDX: 0000000000000000 RSI: ffffffff86807c5b RDI: ffffffff868a831e +RBP: ffff8c85c4c54000 R08: 0000000000000000 R09: 0000000000000000 +R10: ffff8c85c66932f0 R11: 0000000000000001 R12: ffff8c85c3899010 +R13: ffff8c85d5be4f40 R14: ffff8c85c4c54000 R15: ffff8c86114bfa80 +FS: 0000000000000000(0000) GS:ffff8c863bd00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f2e7f168160 CR3: 000000010289a004 CR4: 0000000000370ee0 +Call Trace: + + __btrfs_remove_free_space_cache+0x27/0x30 + load_free_space_cache+0xad2/0xaf0 + caching_thread+0x40b/0x650 + ? lock_release+0x137/0x2d0 + btrfs_work_helper+0xf2/0x3e0 + ? lock_is_held_type+0xe2/0x140 + process_one_work+0x271/0x590 + ? process_one_work+0x590/0x590 + worker_thread+0x52/0x3b0 + ? process_one_work+0x590/0x590 + kthread+0xf0/0x120 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x1f/0x30 + +This is the code + + ctl = block_group->free_space_ctl; + discard_ctl = &block_group->fs_info->discard_ctl; + + lockdep_assert_held(&ctl->tree_lock); + +We have a temporary free space ctl for loading the free space cache in +order to avoid having allocations happening while we're loading the +cache. When we hit an error we free it all up, however this also calls +btrfs_discard_update_discardable, which requires +block_group->free_space_ctl->tree_lock to be held. However this is our +temporary ctl so this lock isn't held. Fix this by calling +__btrfs_remove_free_space_cache_locked instead so that we only clean up +the entries and do not mess with the discardable stats. + +Signed-off-by: Josef Bacik +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 53 +++++++++++++++++++++++-------------- + 1 file changed, 33 insertions(+), 20 deletions(-) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index d9577f822ba5..19e58e553fa1 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -48,6 +48,25 @@ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl, + struct btrfs_free_space *info, u64 offset, + u64 bytes, bool update_stats); + ++static void __btrfs_remove_free_space_cache_locked( ++ struct btrfs_free_space_ctl *ctl) ++{ ++ struct btrfs_free_space *info; ++ struct rb_node *node; ++ ++ while ((node = rb_last(&ctl->free_space_offset)) != NULL) { ++ info = rb_entry(node, struct btrfs_free_space, offset_index); ++ if (!info->bitmap) { ++ unlink_free_space(ctl, info, true); ++ kmem_cache_free(btrfs_free_space_cachep, info); ++ } else { ++ free_bitmap(ctl, info); ++ } ++ ++ cond_resched_lock(&ctl->tree_lock); ++ } ++} ++ + static struct inode *__lookup_free_space_inode(struct btrfs_root *root, + struct btrfs_path *path, + u64 offset) +@@ -881,7 +900,14 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, + return ret; + free_cache: + io_ctl_drop_pages(&io_ctl); +- __btrfs_remove_free_space_cache(ctl); ++ ++ /* ++ * We need to call the _locked variant so we don't try to update the ++ * discard counters. ++ */ ++ spin_lock(&ctl->tree_lock); ++ __btrfs_remove_free_space_cache_locked(ctl); ++ spin_unlock(&ctl->tree_lock); + goto out; + } + +@@ -1017,7 +1043,13 @@ int load_free_space_cache(struct btrfs_block_group *block_group) + if (ret == 0) + ret = 1; + } else { ++ /* ++ * We need to call the _locked variant so we don't try to update ++ * the discard counters. ++ */ ++ spin_lock(&tmp_ctl.tree_lock); + __btrfs_remove_free_space_cache(&tmp_ctl); ++ spin_unlock(&tmp_ctl.tree_lock); + btrfs_warn(fs_info, + "block group %llu has wrong amount of free space", + block_group->start); +@@ -2980,25 +3012,6 @@ static void __btrfs_return_cluster_to_free_space( + btrfs_put_block_group(block_group); + } + +-static void __btrfs_remove_free_space_cache_locked( +- struct btrfs_free_space_ctl *ctl) +-{ +- struct btrfs_free_space *info; +- struct rb_node *node; +- +- while ((node = rb_last(&ctl->free_space_offset)) != NULL) { +- info = rb_entry(node, struct btrfs_free_space, offset_index); +- if (!info->bitmap) { +- unlink_free_space(ctl, info, true); +- kmem_cache_free(btrfs_free_space_cachep, info); +- } else { +- free_bitmap(ctl, info); +- } +- +- cond_resched_lock(&ctl->tree_lock); +- } +-} +- + void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl) + { + spin_lock(&ctl->tree_lock); +-- +2.35.1 + diff --git a/queue-5.19/btrfs-change-the-lockdep-class-of-free-space-inode-s.patch b/queue-5.19/btrfs-change-the-lockdep-class-of-free-space-inode-s.patch new file mode 100644 index 00000000000..532af7cc027 --- /dev/null +++ b/queue-5.19/btrfs-change-the-lockdep-class-of-free-space-inode-s.patch @@ -0,0 +1,61 @@ +From 64796875b3d6eef72b90481ed83ae4db55ce12c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 15:11:57 -0700 +Subject: btrfs: change the lockdep class of free space inode's invalidate_lock + +From: Ioannis Angelakopoulos + +[ Upstream commit 9d7464c87b159bbf763c24faeb7a2dcaac96e4a1 ] + +Reinitialize the class of the lockdep map for struct inode's +mapping->invalidate_lock in load_free_space_cache() function in +fs/btrfs/free-space-cache.c. This will prevent lockdep from producing +false positives related to execution paths that make use of free space +inodes and paths that make use of normal inodes. + +Specifically, with this change lockdep will create separate lock +dependencies that include the invalidate_lock, in the case that free +space inodes are used and in the case that normal inodes are used. + +The lockdep class for this lock was first initialized in +inode_init_always() in fs/inode.c. + +Reviewed-by: Josef Bacik +Signed-off-by: Ioannis Angelakopoulos +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index 16710d4571da..d9577f822ba5 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -920,6 +920,8 @@ static int copy_free_space_cache(struct btrfs_block_group *block_group, + return ret; + } + ++static struct lock_class_key btrfs_free_space_inode_key; ++ + int load_free_space_cache(struct btrfs_block_group *block_group) + { + struct btrfs_fs_info *fs_info = block_group->fs_info; +@@ -989,6 +991,14 @@ int load_free_space_cache(struct btrfs_block_group *block_group) + } + spin_unlock(&block_group->lock); + ++ /* ++ * Reinitialize the class of struct inode's mapping->invalidate_lock for ++ * free space inodes to prevent false positives related to locks for normal ++ * inodes. ++ */ ++ lockdep_set_class(&(&inode->i_data)->invalidate_lock, ++ &btrfs_free_space_inode_key); ++ + ret = __load_free_space_cache(fs_info->tree_root, inode, &tmp_ctl, + path, block_group->start); + btrfs_free_path(path); +-- +2.35.1 + diff --git a/queue-5.19/btrfs-check-superblock-to-ensure-the-fs-was-not-modi.patch b/queue-5.19/btrfs-check-superblock-to-ensure-the-fs-was-not-modi.patch new file mode 100644 index 00000000000..a49effaeffd --- /dev/null +++ b/queue-5.19/btrfs-check-superblock-to-ensure-the-fs-was-not-modi.patch @@ -0,0 +1,254 @@ +From e69472b7611bd51247177446c783392d45302651 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 20:16:22 +0800 +Subject: btrfs: check superblock to ensure the fs was not modified at thaw + time + +From: Qu Wenruo + +[ Upstream commit a05d3c9153145283ce9c58a1d7a9056fbb85f6a1 ] + +[BACKGROUND] +There is an incident report that, one user hibernated the system, with +one btrfs on removable device still mounted. + +Then by some incident, the btrfs got mounted and modified by another +system/OS, then back to the hibernated system. + +After resuming from the hibernation, new write happened into the victim btrfs. + +Now the fs is completely broken, since the underlying btrfs is no longer +the same one before the hibernation, and the user lost their data due to +various transid mismatch. + +[REPRODUCER] +We can emulate the situation using the following small script: + + truncate -s 1G $dev + mkfs.btrfs -f $dev + mount $dev $mnt + fsstress -w -d $mnt -n 500 + sync + xfs_freeze -f $mnt + cp $dev $dev.backup + + # There is no way to mount the same cloned fs on the same system, + # as the conflicting fsid will be rejected by btrfs. + # Thus here we have to wipe the fs using a different btrfs. + mkfs.btrfs -f $dev.backup + + dd if=$dev.backup of=$dev bs=1M + xfs_freeze -u $mnt + fsstress -w -d $mnt -n 20 + umount $mnt + btrfs check $dev + +The final fsck will fail due to some tree blocks has incorrect fsid. + +This is enough to emulate the problem hit by the unfortunate user. + +[ENHANCEMENT] +Although such case should not be that common, it can still happen from +time to time. + +From the view of btrfs, we can detect any unexpected super block change, +and if there is any unexpected change, we just mark the fs read-only, +and thaw the fs. + +By this we can limit the damage to minimal, and I hope no one would lose +their data by this anymore. + +Suggested-by: Goffredo Baroncelli +Link: https://lore.kernel.org/linux-btrfs/83bf3b4b-7f4c-387a-b286-9251e3991e34@bluemole.com/ +Reviewed-by: Anand Jain +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/disk-io.c | 25 ++++++++++++++----- + fs/btrfs/disk-io.h | 4 +++- + fs/btrfs/super.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/volumes.c | 2 +- + 4 files changed, 83 insertions(+), 8 deletions(-) + +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index 20ad619a8a97..218f62fb76a0 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -2705,8 +2705,8 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info) + * 1, 2 2nd and 3rd backup copy + * -1 skip bytenr check + */ +-static int validate_super(struct btrfs_fs_info *fs_info, +- struct btrfs_super_block *sb, int mirror_num) ++int btrfs_validate_super(struct btrfs_fs_info *fs_info, ++ struct btrfs_super_block *sb, int mirror_num) + { + u64 nodesize = btrfs_super_nodesize(sb); + u64 sectorsize = btrfs_super_sectorsize(sb); +@@ -2890,7 +2890,7 @@ static int validate_super(struct btrfs_fs_info *fs_info, + */ + static int btrfs_validate_mount_super(struct btrfs_fs_info *fs_info) + { +- return validate_super(fs_info, fs_info->super_copy, 0); ++ return btrfs_validate_super(fs_info, fs_info->super_copy, 0); + } + + /* +@@ -2904,7 +2904,7 @@ static int btrfs_validate_write_super(struct btrfs_fs_info *fs_info, + { + int ret; + +- ret = validate_super(fs_info, sb, -1); ++ ret = btrfs_validate_super(fs_info, sb, -1); + if (ret < 0) + goto out; + if (!btrfs_supported_super_csum(btrfs_super_csum_type(sb))) { +@@ -3945,7 +3945,7 @@ static void btrfs_end_super_write(struct bio *bio) + } + + struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, +- int copy_num) ++ int copy_num, bool drop_cache) + { + struct btrfs_super_block *super; + struct page *page; +@@ -3963,6 +3963,19 @@ struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, + if (bytenr + BTRFS_SUPER_INFO_SIZE >= bdev_nr_bytes(bdev)) + return ERR_PTR(-EINVAL); + ++ if (drop_cache) { ++ /* This should only be called with the primary sb. */ ++ ASSERT(copy_num == 0); ++ ++ /* ++ * Drop the page of the primary superblock, so later read will ++ * always read from the device. ++ */ ++ invalidate_inode_pages2_range(mapping, ++ bytenr >> PAGE_SHIFT, ++ (bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT); ++ } ++ + page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS); + if (IS_ERR(page)) + return ERR_CAST(page); +@@ -3994,7 +4007,7 @@ struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev) + * later supers, using BTRFS_SUPER_MIRROR_MAX instead + */ + for (i = 0; i < 1; i++) { +- super = btrfs_read_dev_one_super(bdev, i); ++ super = btrfs_read_dev_one_super(bdev, i, false); + if (IS_ERR(super)) + continue; + +diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h +index b4962b7d7117..ece5a3112b4f 100644 +--- a/fs/btrfs/disk-io.h ++++ b/fs/btrfs/disk-io.h +@@ -53,10 +53,12 @@ int __cold open_ctree(struct super_block *sb, + struct btrfs_fs_devices *fs_devices, + char *options); + void __cold close_ctree(struct btrfs_fs_info *fs_info); ++int btrfs_validate_super(struct btrfs_fs_info *fs_info, ++ struct btrfs_super_block *sb, int mirror_num); + int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors); + struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev); + struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, +- int copy_num); ++ int copy_num, bool drop_cache); + int btrfs_commit_super(struct btrfs_fs_info *fs_info); + struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, + struct btrfs_key *key); +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index b2a5291e5e4b..80f480b8252c 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2571,11 +2571,71 @@ static int btrfs_freeze(struct super_block *sb) + return btrfs_commit_transaction(trans); + } + ++static int check_dev_super(struct btrfs_device *dev) ++{ ++ struct btrfs_fs_info *fs_info = dev->fs_info; ++ struct btrfs_super_block *sb; ++ int ret = 0; ++ ++ /* This should be called with fs still frozen. */ ++ ASSERT(test_bit(BTRFS_FS_FROZEN, &fs_info->flags)); ++ ++ /* Missing dev, no need to check. */ ++ if (!dev->bdev) ++ return 0; ++ ++ /* Only need to check the primary super block. */ ++ sb = btrfs_read_dev_one_super(dev->bdev, 0, true); ++ if (IS_ERR(sb)) ++ return PTR_ERR(sb); ++ ++ /* Btrfs_validate_super() includes fsid check against super->fsid. */ ++ ret = btrfs_validate_super(fs_info, sb, 0); ++ if (ret < 0) ++ goto out; ++ ++ if (btrfs_super_generation(sb) != fs_info->last_trans_committed) { ++ btrfs_err(fs_info, "transid mismatch, has %llu expect %llu", ++ btrfs_super_generation(sb), ++ fs_info->last_trans_committed); ++ ret = -EUCLEAN; ++ goto out; ++ } ++out: ++ btrfs_release_disk_super(sb); ++ return ret; ++} ++ + static int btrfs_unfreeze(struct super_block *sb) + { + struct btrfs_fs_info *fs_info = btrfs_sb(sb); ++ struct btrfs_device *device; ++ int ret = 0; + ++ /* ++ * Make sure the fs is not changed by accident (like hibernation then ++ * modified by other OS). ++ * If we found anything wrong, we mark the fs error immediately. ++ * ++ * And since the fs is frozen, no one can modify the fs yet, thus ++ * we don't need to hold device_list_mutex. ++ */ ++ list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) { ++ ret = check_dev_super(device); ++ if (ret < 0) { ++ btrfs_handle_fs_error(fs_info, ret, ++ "super block on devid %llu got modified unexpectedly", ++ device->devid); ++ break; ++ } ++ } + clear_bit(BTRFS_FS_FROZEN, &fs_info->flags); ++ ++ /* ++ * We still return 0, to allow VFS layer to unfreeze the fs even the ++ * above checks failed. Since the fs is either fine or read-only, we're ++ * safe to continue, without causing further damage. ++ */ + return 0; + } + +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 16e01fbdcec8..4f9c0c5b9613 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2016,7 +2016,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, + struct page *page; + int ret; + +- disk_super = btrfs_read_dev_one_super(bdev, copy_num); ++ disk_super = btrfs_read_dev_one_super(bdev, copy_num, false); + if (IS_ERR(disk_super)) + continue; + +-- +2.35.1 + diff --git a/queue-5.19/btrfs-don-t-print-information-about-space-cache-or-t.patch b/queue-5.19/btrfs-don-t-print-information-about-space-cache-or-t.patch new file mode 100644 index 00000000000..a35590f58a8 --- /dev/null +++ b/queue-5.19/btrfs-don-t-print-information-about-space-cache-or-t.patch @@ -0,0 +1,61 @@ +From 542d0f00e2aff018c94bf20119c1f50a0b255216 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 17:28:20 +0200 +Subject: btrfs: don't print information about space cache or tree every + remount + +From: Maciej S. Szmigiero + +[ Upstream commit dbecac26630014d336a8e5ea67096ff18210fb9c ] + +btrfs currently prints information about space cache or free space tree +being in use on every remount, regardless whether such remount actually +enabled or disabled one of these features. + +This is actually unnecessary since providing remount options changing the +state of these features will explicitly print the appropriate notice. + +Let's instead print such unconditional information just on an initial mount +to avoid filling the kernel log when, for example, laptop-mode-tools +remount the fs on some events. + +Signed-off-by: Maciej S. Szmigiero +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/super.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index 72923496490f..b2a5291e5e4b 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -625,6 +625,7 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, + int saved_compress_level; + bool saved_compress_force; + int no_compress = 0; ++ const bool remounting = test_bit(BTRFS_FS_STATE_REMOUNTING, &info->fs_state); + + if (btrfs_fs_compat_ro(info, FREE_SPACE_TREE)) + btrfs_set_opt(info->mount_opt, FREE_SPACE_TREE); +@@ -1136,10 +1137,12 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, + } + if (!ret) + ret = btrfs_check_mountopts_zoned(info); +- if (!ret && btrfs_test_opt(info, SPACE_CACHE)) +- btrfs_info(info, "disk space caching is enabled"); +- if (!ret && btrfs_test_opt(info, FREE_SPACE_TREE)) +- btrfs_info(info, "using free space tree"); ++ if (!ret && !remounting) { ++ if (btrfs_test_opt(info, SPACE_CACHE)) ++ btrfs_info(info, "disk space caching is enabled"); ++ if (btrfs_test_opt(info, FREE_SPACE_TREE)) ++ btrfs_info(info, "using free space tree"); ++ } + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.19/btrfs-dump-extra-info-if-one-free-space-cache-has-mo.patch b/queue-5.19/btrfs-dump-extra-info-if-one-free-space-cache-has-mo.patch new file mode 100644 index 00000000000..56cdb8144a7 --- /dev/null +++ b/queue-5.19/btrfs-dump-extra-info-if-one-free-space-cache-has-mo.patch @@ -0,0 +1,66 @@ +From 9a9cc1849b3bb3bb5d389a34ed3a4ac54417484a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 09:35:57 +0800 +Subject: btrfs: dump extra info if one free space cache has more bitmaps than + it should + +From: Qu Wenruo + +[ Upstream commit 62cd9d4474282a1eb84f945955c56cbfc42e1ffe ] + +There is an internal report on hitting the following ASSERT() in +recalculate_thresholds(): + + ASSERT(ctl->total_bitmaps <= max_bitmaps); + +Above @max_bitmaps is calculated using the following variables: + +- bytes_per_bg + 8 * 4096 * 4096 (128M) for x86_64/x86. + +- block_group->length + The length of the block group. + +@max_bitmaps is the rounded up value of block_group->length / 128M. + +Normally one free space cache should not have more bitmaps than above +value, but when it happens the ASSERT() can be triggered if +CONFIG_BTRFS_ASSERT is also enabled. + +But the ASSERT() itself won't provide enough info to know which is going +wrong. +Is the bg too small thus it only allows one bitmap? +Or is there something else wrong? + +So although I haven't found extra reports or crash dump to do further +investigation, add the extra info to make it more helpful to debug. + +Reviewed-by: Anand Jain +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/free-space-cache.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c +index b1ae3ba2ca2c..16710d4571da 100644 +--- a/fs/btrfs/free-space-cache.c ++++ b/fs/btrfs/free-space-cache.c +@@ -693,6 +693,12 @@ static void recalculate_thresholds(struct btrfs_free_space_ctl *ctl) + + max_bitmaps = max_t(u64, max_bitmaps, 1); + ++ if (ctl->total_bitmaps > max_bitmaps) ++ btrfs_err(block_group->fs_info, ++"invalid free space control: bg start=%llu len=%llu total_bitmaps=%u unit=%u max_bitmaps=%llu bytes_per_bg=%llu", ++ block_group->start, block_group->length, ++ ctl->total_bitmaps, ctl->unit, max_bitmaps, ++ bytes_per_bg); + ASSERT(ctl->total_bitmaps <= max_bitmaps); + + /* +-- +2.35.1 + diff --git a/queue-5.19/btrfs-scrub-properly-report-super-block-errors-in-sy.patch b/queue-5.19/btrfs-scrub-properly-report-super-block-errors-in-sy.patch new file mode 100644 index 00000000000..59643213ad2 --- /dev/null +++ b/queue-5.19/btrfs-scrub-properly-report-super-block-errors-in-sy.patch @@ -0,0 +1,145 @@ +From 05345855299de13487456554f32651ffcc156333 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 14:53:02 +0800 +Subject: btrfs: scrub: properly report super block errors in system log + +From: Qu Wenruo + +[ Upstream commit e69bf81c9a339f1b2c041b112a6fbb9f60fc9340 ] + +[PROBLEM] + +Unlike data/metadata corruption, if scrub detected some error in the +super block, the only error message is from the updated device status: + + BTRFS info (device dm-1): scrub: started on devid 2 + BTRFS error (device dm-1): bdev /dev/mapper/test-scratch2 errs: wr 0, rd 0, flush 0, corrupt 1, gen 0 + BTRFS info (device dm-1): scrub: finished on devid 2 with status: 0 + +This is not helpful at all. + +[CAUSE] +Unlike data/metadata error reporting, there is no visible report in +kernel dmesg to report supper block errors. + +In fact, return value of scrub_checksum_super() is intentionally +skipped, thus scrub_handle_errored_block() will never be called for +super blocks. + +[FIX] +Make super block errors to output an error message, now the full +dmesg would looks like this: + + BTRFS info (device dm-1): scrub: started on devid 2 + BTRFS warning (device dm-1): super block error on device /dev/mapper/test-scratch2, physical 67108864 + BTRFS error (device dm-1): bdev /dev/mapper/test-scratch2 errs: wr 0, rd 0, flush 0, corrupt 1, gen 0 + BTRFS info (device dm-1): scrub: finished on devid 2 with status: 0 + BTRFS info (device dm-1): scrub: started on devid 2 + +This fix involves: + +- Move the super_errors reporting to scrub_handle_errored_block() + This allows the device status message to show after the super block + error message. + But now we no longer distinguish super block corruption and generation + mismatch, now all counted as corruption. + +- Properly check the return value from scrub_checksum_super() +- Add extra super block error reporting for scrub_print_warning(). + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/scrub.c | 33 ++++++++++++--------------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index e7b0323e6efd..f62bfa023178 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -731,6 +731,13 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) + dev = sblock->sectors[0]->dev; + fs_info = sblock->sctx->fs_info; + ++ /* Super block error, no need to search extent tree. */ ++ if (sblock->sectors[0]->flags & BTRFS_EXTENT_FLAG_SUPER) { ++ btrfs_warn_in_rcu(fs_info, "%s on device %s, physical %llu", ++ errstr, rcu_str_deref(dev->name), ++ sblock->sectors[0]->physical); ++ return; ++ } + path = btrfs_alloc_path(); + if (!path) + return; +@@ -806,7 +813,7 @@ static inline void scrub_put_recover(struct btrfs_fs_info *fs_info, + static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) + { + struct scrub_ctx *sctx = sblock_to_check->sctx; +- struct btrfs_device *dev; ++ struct btrfs_device *dev = sblock_to_check->sectors[0]->dev; + struct btrfs_fs_info *fs_info; + u64 logical; + unsigned int failed_mirror_index; +@@ -827,13 +834,15 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) + fs_info = sctx->fs_info; + if (sblock_to_check->sectors[0]->flags & BTRFS_EXTENT_FLAG_SUPER) { + /* +- * if we find an error in a super block, we just report it. ++ * If we find an error in a super block, we just report it. + * They will get written with the next transaction commit + * anyway + */ ++ scrub_print_warning("super block error", sblock_to_check); + spin_lock(&sctx->stat_lock); + ++sctx->stat.super_errors; + spin_unlock(&sctx->stat_lock); ++ btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_CORRUPTION_ERRS); + return 0; + } + logical = sblock_to_check->sectors[0]->logical; +@@ -842,7 +851,6 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check) + is_metadata = !(sblock_to_check->sectors[0]->flags & + BTRFS_EXTENT_FLAG_DATA); + have_csum = sblock_to_check->sectors[0]->have_csum; +- dev = sblock_to_check->sectors[0]->dev; + + if (!sctx->is_dev_replace && btrfs_repair_one_zone(fs_info, logical)) + return 0; +@@ -1773,7 +1781,7 @@ static int scrub_checksum(struct scrub_block *sblock) + else if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) + ret = scrub_checksum_tree_block(sblock); + else if (flags & BTRFS_EXTENT_FLAG_SUPER) +- (void)scrub_checksum_super(sblock); ++ ret = scrub_checksum_super(sblock); + else + WARN_ON(1); + if (ret) +@@ -1912,23 +1920,6 @@ static int scrub_checksum_super(struct scrub_block *sblock) + if (memcmp(calculated_csum, s->csum, sctx->fs_info->csum_size)) + ++fail_cor; + +- if (fail_cor + fail_gen) { +- /* +- * if we find an error in a super block, we just report it. +- * They will get written with the next transaction commit +- * anyway +- */ +- spin_lock(&sctx->stat_lock); +- ++sctx->stat.super_errors; +- spin_unlock(&sctx->stat_lock); +- if (fail_cor) +- btrfs_dev_stat_inc_and_print(sector->dev, +- BTRFS_DEV_STAT_CORRUPTION_ERRS); +- else +- btrfs_dev_stat_inc_and_print(sector->dev, +- BTRFS_DEV_STAT_GENERATION_ERRS); +- } +- + return fail_cor + fail_gen; + } + +-- +2.35.1 + diff --git a/queue-5.19/btrfs-scrub-try-to-fix-super-block-errors.patch b/queue-5.19/btrfs-scrub-try-to-fix-super-block-errors.patch new file mode 100644 index 00000000000..939f41a7b5e --- /dev/null +++ b/queue-5.19/btrfs-scrub-try-to-fix-super-block-errors.patch @@ -0,0 +1,147 @@ +From 9e228d221589912263579d9181366afd5fb5913b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 14:53:03 +0800 +Subject: btrfs: scrub: try to fix super block errors + +From: Qu Wenruo + +[ Upstream commit f9eab5f0bba76742af654f33d517bf62a0db8f12 ] + +[BUG] +The following script shows that, although scrub can detect super block +errors, it never tries to fix it: + + mkfs.btrfs -f -d raid1 -m raid1 $dev1 $dev2 + xfs_io -c "pwrite 67108864 4k" $dev2 + + mount $dev1 $mnt + btrfs scrub start -B $dev2 + btrfs scrub start -Br $dev2 + umount $mnt + +The first scrub reports the super error correctly: + + scrub done for f3289218-abd3-41ac-a630-202f766c0859 + Scrub started: Tue Aug 2 14:44:11 2022 + Status: finished + Duration: 0:00:00 + Total to scrub: 1.26GiB + Rate: 0.00B/s + Error summary: super=1 + Corrected: 0 + Uncorrectable: 0 + Unverified: 0 + +But the second read-only scrub still reports the same super error: + + Scrub started: Tue Aug 2 14:44:11 2022 + Status: finished + Duration: 0:00:00 + Total to scrub: 1.26GiB + Rate: 0.00B/s + Error summary: super=1 + Corrected: 0 + Uncorrectable: 0 + Unverified: 0 + +[CAUSE] +The comments already shows that super block can be easily fixed by +committing a transaction: + + /* + * If we find an error in a super block, we just report it. + * They will get written with the next transaction commit + * anyway + */ + +But the truth is, such assumption is not always true, and since scrub +should try to repair every error it found (except for read-only scrub), +we should really actively commit a transaction to fix this. + +[FIX] +Just commit a transaction if we found any super block errors, after +everything else is done. + +We cannot do this just after scrub_supers(), as +btrfs_commit_transaction() will try to pause and wait for the running +scrub, thus we can not call it with scrub_lock hold. + +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/scrub.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c +index f62bfa023178..a14f97bf2a40 100644 +--- a/fs/btrfs/scrub.c ++++ b/fs/btrfs/scrub.c +@@ -4112,6 +4112,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, + int ret; + struct btrfs_device *dev; + unsigned int nofs_flag; ++ bool need_commit = false; + + if (btrfs_fs_closing(fs_info)) + return -EAGAIN; +@@ -4215,6 +4216,12 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, + */ + nofs_flag = memalloc_nofs_save(); + if (!is_dev_replace) { ++ u64 old_super_errors; ++ ++ spin_lock(&sctx->stat_lock); ++ old_super_errors = sctx->stat.super_errors; ++ spin_unlock(&sctx->stat_lock); ++ + btrfs_info(fs_info, "scrub: started on devid %llu", devid); + /* + * by holding device list mutex, we can +@@ -4223,6 +4230,16 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, + mutex_lock(&fs_info->fs_devices->device_list_mutex); + ret = scrub_supers(sctx, dev); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); ++ ++ spin_lock(&sctx->stat_lock); ++ /* ++ * Super block errors found, but we can not commit transaction ++ * at current context, since btrfs_commit_transaction() needs ++ * to pause the current running scrub (hold by ourselves). ++ */ ++ if (sctx->stat.super_errors > old_super_errors && !sctx->readonly) ++ need_commit = true; ++ spin_unlock(&sctx->stat_lock); + } + + if (!ret) +@@ -4249,6 +4266,25 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start, + scrub_workers_put(fs_info); + scrub_put_ctx(sctx); + ++ /* ++ * We found some super block errors before, now try to force a ++ * transaction commit, as scrub has finished. ++ */ ++ if (need_commit) { ++ struct btrfs_trans_handle *trans; ++ ++ trans = btrfs_start_transaction(fs_info->tree_root, 0); ++ if (IS_ERR(trans)) { ++ ret = PTR_ERR(trans); ++ btrfs_err(fs_info, ++ "scrub: failed to start transaction to fix super block errors: %d", ret); ++ return ret; ++ } ++ ret = btrfs_commit_transaction(trans); ++ if (ret < 0) ++ btrfs_err(fs_info, ++ "scrub: failed to commit transaction to fix super block errors: %d", ret); ++ } + return ret; + out: + scrub_workers_put(fs_info); +-- +2.35.1 + diff --git a/queue-5.19/btrfs-separate-out-the-eb-and-extent-state-leak-help.patch b/queue-5.19/btrfs-separate-out-the-eb-and-extent-state-leak-help.patch new file mode 100644 index 00000000000..6dd89d35c2b --- /dev/null +++ b/queue-5.19/btrfs-separate-out-the-eb-and-extent-state-leak-help.patch @@ -0,0 +1,144 @@ +From cedca0827f5d311bddf414ed15cd8e54e13a6fe0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 17:53:19 -0400 +Subject: btrfs: separate out the eb and extent state leak helpers + +From: Josef Bacik + +[ Upstream commit a40246e8afc0af3ffdee21854fb755c9364b8346 ] + +Currently we have the add/del functions generic so that we can use them +for both extent buffers and extent states. We want to separate this +code however, so separate these helpers into per-object helpers in +anticipation of the split. + +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 58 +++++++++++++++++++++++++++++--------------- + 1 file changed, 38 insertions(+), 20 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 5785ed241f6f..8c83d00fcb8c 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -44,25 +44,42 @@ static inline bool extent_state_in_tree(const struct extent_state *state) + static LIST_HEAD(states); + static DEFINE_SPINLOCK(leak_lock); + +-static inline void btrfs_leak_debug_add(spinlock_t *lock, +- struct list_head *new, +- struct list_head *head) ++static inline void btrfs_leak_debug_add_eb(struct extent_buffer *eb) ++{ ++ struct btrfs_fs_info *fs_info = eb->fs_info; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fs_info->eb_leak_lock, flags); ++ list_add(&eb->leak_list, &fs_info->allocated_ebs); ++ spin_unlock_irqrestore(&fs_info->eb_leak_lock, flags); ++} ++ ++static inline void btrfs_leak_debug_add_state(struct extent_state *state) + { + unsigned long flags; + +- spin_lock_irqsave(lock, flags); +- list_add(new, head); +- spin_unlock_irqrestore(lock, flags); ++ spin_lock_irqsave(&leak_lock, flags); ++ list_add(&state->leak_list, &states); ++ spin_unlock_irqrestore(&leak_lock, flags); ++} ++ ++static inline void btrfs_leak_debug_del_eb(struct extent_buffer *eb) ++{ ++ struct btrfs_fs_info *fs_info = eb->fs_info; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fs_info->eb_leak_lock, flags); ++ list_del(&eb->leak_list); ++ spin_unlock_irqrestore(&fs_info->eb_leak_lock, flags); + } + +-static inline void btrfs_leak_debug_del(spinlock_t *lock, +- struct list_head *entry) ++static inline void btrfs_leak_debug_del_state(struct extent_state *state) + { + unsigned long flags; + +- spin_lock_irqsave(lock, flags); +- list_del(entry); +- spin_unlock_irqrestore(lock, flags); ++ spin_lock_irqsave(&leak_lock, flags); ++ list_del(&state->leak_list); ++ spin_unlock_irqrestore(&leak_lock, flags); + } + + void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) +@@ -126,9 +143,11 @@ static inline void __btrfs_debug_check_extent_io_range(const char *caller, + } + } + #else +-#define btrfs_leak_debug_add(lock, new, head) do {} while (0) +-#define btrfs_leak_debug_del(lock, entry) do {} while (0) +-#define btrfs_extent_state_leak_debug_check() do {} while (0) ++#define btrfs_leak_debug_add_eb(eb) do {} while (0) ++#define btrfs_leak_debug_add_state(state) do {} while (0) ++#define btrfs_leak_debug_del_eb(eb) do {} while (0) ++#define btrfs_leak_debug_del_state(state) do {} while (0) ++#define btrfs_extent_state_leak_debug_check() do {} while (0) + #define btrfs_debug_check_extent_io_range(c, s, e) do {} while (0) + #endif + +@@ -357,7 +376,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask) + state->state = 0; + state->failrec = NULL; + RB_CLEAR_NODE(&state->rb_node); +- btrfs_leak_debug_add(&leak_lock, &state->leak_list, &states); ++ btrfs_leak_debug_add_state(state); + refcount_set(&state->refs, 1); + init_waitqueue_head(&state->wq); + trace_alloc_extent_state(state, mask, _RET_IP_); +@@ -370,7 +389,7 @@ void free_extent_state(struct extent_state *state) + return; + if (refcount_dec_and_test(&state->refs)) { + WARN_ON(extent_state_in_tree(state)); +- btrfs_leak_debug_del(&leak_lock, &state->leak_list); ++ btrfs_leak_debug_del_state(state); + trace_free_extent_state(state, _RET_IP_); + kmem_cache_free(extent_state_cache, state); + } +@@ -5919,7 +5938,7 @@ static void btrfs_release_extent_buffer_pages(struct extent_buffer *eb) + static inline void btrfs_release_extent_buffer(struct extent_buffer *eb) + { + btrfs_release_extent_buffer_pages(eb); +- btrfs_leak_debug_del(&eb->fs_info->eb_leak_lock, &eb->leak_list); ++ btrfs_leak_debug_del_eb(eb); + __free_extent_buffer(eb); + } + +@@ -5936,8 +5955,7 @@ __alloc_extent_buffer(struct btrfs_fs_info *fs_info, u64 start, + eb->bflags = 0; + init_rwsem(&eb->lock); + +- btrfs_leak_debug_add(&fs_info->eb_leak_lock, &eb->leak_list, +- &fs_info->allocated_ebs); ++ btrfs_leak_debug_add_eb(eb); + INIT_LIST_HEAD(&eb->release_list); + + spin_lock_init(&eb->refs_lock); +@@ -6405,7 +6423,7 @@ static int release_extent_buffer(struct extent_buffer *eb) + spin_unlock(&eb->refs_lock); + } + +- btrfs_leak_debug_del(&eb->fs_info->eb_leak_lock, &eb->leak_list); ++ btrfs_leak_debug_del_eb(eb); + /* Should be safe to release our pages at this point */ + btrfs_release_extent_buffer_pages(eb); + #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS +-- +2.35.1 + diff --git a/queue-5.19/can-bcm-check-the-result-of-can_send-in-bcm_can_tx.patch b/queue-5.19/can-bcm-check-the-result-of-can_send-in-bcm_can_tx.patch new file mode 100644 index 00000000000..f08723d07b3 --- /dev/null +++ b/queue-5.19/can-bcm-check-the-result-of-can_send-in-bcm_can_tx.patch @@ -0,0 +1,53 @@ +From e5d796f1b65804d8dbbdd177f5b3fc266964ba0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 09:55:56 +0800 +Subject: can: bcm: check the result of can_send() in bcm_can_tx() + +From: Ziyang Xuan + +[ Upstream commit 3fd7bfd28cfd68ae80a2fe92ea1615722cc2ee6e ] + +If can_send() fail, it should not update frames_abs counter +in bcm_can_tx(). Add the result check for can_send() in bcm_can_tx(). + +Suggested-by: Marc Kleine-Budde +Suggested-by: Oliver Hartkopp +Signed-off-by: Ziyang Xuan +Link: https://lore.kernel.org/all/9851878e74d6d37aee2f1ee76d68361a46f89458.1663206163.git.william.xuanziyang@huawei.com +Acked-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + net/can/bcm.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/can/bcm.c b/net/can/bcm.c +index e60161bec850..f16271a7ae2e 100644 +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -274,6 +274,7 @@ static void bcm_can_tx(struct bcm_op *op) + struct sk_buff *skb; + struct net_device *dev; + struct canfd_frame *cf = op->frames + op->cfsiz * op->currframe; ++ int err; + + /* no target device? => exit */ + if (!op->ifindex) +@@ -298,11 +299,11 @@ static void bcm_can_tx(struct bcm_op *op) + /* send with loopback */ + skb->dev = dev; + can_skb_set_owner(skb, op->sk); +- can_send(skb, 1); ++ err = can_send(skb, 1); ++ if (!err) ++ op->frames_abs++; + +- /* update statistics */ + op->currframe++; +- op->frames_abs++; + + /* reached last frame? */ + if (op->currframe >= op->nframes) +-- +2.35.1 + diff --git a/queue-5.19/can-rx-offload-can_rx_offload_init_queue-fix-typo.patch b/queue-5.19/can-rx-offload-can_rx_offload_init_queue-fix-typo.patch new file mode 100644 index 00000000000..6582545d0fa --- /dev/null +++ b/queue-5.19/can-rx-offload-can_rx_offload_init_queue-fix-typo.patch @@ -0,0 +1,39 @@ +From 9cbdc56debb7ce393e3bec48ac36749bdd52c767 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Aug 2022 21:38:00 +0200 +Subject: can: rx-offload: can_rx_offload_init_queue(): fix typo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marc Kleine-Budde + +[ Upstream commit 766108d91246530d31b42765046f7ec2d1e42581 ] + +Fix typo "rounted" -> "rounded". + +Link: https://lore.kernel.org/all/20220811093617.1861938-2-mkl@pengutronix.de +Fixes: d254586c3453 ("can: rx-offload: Add support for HW fifo based irq offloading") +Reported-by: Uwe Kleine-König +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Sasha Levin +--- + drivers/net/can/dev/rx-offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c +index a32a01c172d4..ad8eb243fe78 100644 +--- a/drivers/net/can/dev/rx-offload.c ++++ b/drivers/net/can/dev/rx-offload.c +@@ -329,7 +329,7 @@ static int can_rx_offload_init_queue(struct net_device *dev, + { + offload->dev = dev; + +- /* Limit queue len to 4x the weight (rounted to next power of two) */ ++ /* Limit queue len to 4x the weight (rounded to next power of two) */ + offload->skb_queue_len_max = 2 << fls(weight); + offload->skb_queue_len_max *= 4; + skb_queue_head_init(&offload->skb_queue); +-- +2.35.1 + diff --git a/queue-5.19/cgroup-cpuset-enable-update_tasks_cpumask-on-top_cpu.patch b/queue-5.19/cgroup-cpuset-enable-update_tasks_cpumask-on-top_cpu.patch new file mode 100644 index 00000000000..b4421e30034 --- /dev/null +++ b/queue-5.19/cgroup-cpuset-enable-update_tasks_cpumask-on-top_cpu.patch @@ -0,0 +1,71 @@ +From 499615c99fdb8954bd606ead9fff6d8793c47d79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 16:57:36 -0400 +Subject: cgroup/cpuset: Enable update_tasks_cpumask() on top_cpuset + +From: Waiman Long + +[ Upstream commit ec5fbdfb99d18482619ac42605cb80fbb56068ee ] + +Previously, update_tasks_cpumask() is not supposed to be called with +top cpuset. With cpuset partition that takes CPUs away from the top +cpuset, adjusting the cpus_mask of the tasks in the top cpuset is +necessary. Percpu kthreads, however, are ignored. + +Fixes: ee8dde0cd2ce ("cpuset: Add new v2 cpuset.sched.partition flag") +Signed-off-by: Waiman Long +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/cpuset.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index 1f3a55297f39..50bf837571ac 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1127,10 +1128,18 @@ static void update_tasks_cpumask(struct cpuset *cs) + { + struct css_task_iter it; + struct task_struct *task; ++ bool top_cs = cs == &top_cpuset; + + css_task_iter_start(&cs->css, 0, &it); +- while ((task = css_task_iter_next(&it))) ++ while ((task = css_task_iter_next(&it))) { ++ /* ++ * Percpu kthreads in top_cpuset are ignored ++ */ ++ if (top_cs && (task->flags & PF_KTHREAD) && ++ kthread_is_per_cpu(task)) ++ continue; + set_cpus_allowed_ptr(task, cs->effective_cpus); ++ } + css_task_iter_end(&it); + } + +@@ -2092,12 +2101,7 @@ static int update_prstate(struct cpuset *cs, int new_prs) + update_flag(CS_CPU_EXCLUSIVE, cs, 0); + } + +- /* +- * Update cpumask of parent's tasks except when it is the top +- * cpuset as some system daemons cannot be mapped to other CPUs. +- */ +- if (parent != &top_cpuset) +- update_tasks_cpumask(parent); ++ update_tasks_cpumask(parent); + + if (parent->child_ecpus_count) + update_sibling_cpumasks(parent, cs, &tmpmask); +-- +2.35.1 + diff --git a/queue-5.19/cgroup-honor-caller-s-cgroup-ns-when-resolving-path.patch b/queue-5.19/cgroup-honor-caller-s-cgroup-ns-when-resolving-path.patch new file mode 100644 index 00000000000..6a17114cc0b --- /dev/null +++ b/queue-5.19/cgroup-honor-caller-s-cgroup-ns-when-resolving-path.patch @@ -0,0 +1,49 @@ +From 23a62bf7c23d360fd6ca0effe24cda1a1f7aaba6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 18:52:35 +0200 +Subject: cgroup: Honor caller's cgroup NS when resolving path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michal Koutný + +[ Upstream commit 74e4b956eb1cac0e4c10c240339b1bbfbc9a4c48 ] + +cgroup_get_from_path() is not widely used function. Its callers presume +the path is resolved under cgroup namespace. (There is one caller +currently and resolving in init NS won't make harm (netfilter). However, +future users may be subject to different effects when resolving +globally.) +Since, there's currently no use for the global resolution, modify the +existing function to take cgroup NS into account. + +Fixes: a79a908fd2b0 ("cgroup: introduce cgroup namespaces") +Signed-off-by: Michal Koutný +Signed-off-by: Tejun Heo +Signed-off-by: Sasha Levin +--- + kernel/cgroup/cgroup.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c +index 80c23f48f3b4..90019724c719 100644 +--- a/kernel/cgroup/cgroup.c ++++ b/kernel/cgroup/cgroup.c +@@ -6615,8 +6615,12 @@ struct cgroup *cgroup_get_from_path(const char *path) + { + struct kernfs_node *kn; + struct cgroup *cgrp = ERR_PTR(-ENOENT); ++ struct cgroup *root_cgrp; + +- kn = kernfs_walk_and_get(cgrp_dfl_root.cgrp.kn, path); ++ spin_lock_irq(&css_set_lock); ++ root_cgrp = current_cgns_cgroup_from_root(&cgrp_dfl_root); ++ kn = kernfs_walk_and_get(root_cgrp->kn, path); ++ spin_unlock_irq(&css_set_lock); + if (!kn) + goto out; + +-- +2.35.1 + diff --git a/queue-5.19/cifs-return-correct-error-in-calc_signature.patch b/queue-5.19/cifs-return-correct-error-in-calc_signature.patch new file mode 100644 index 00000000000..961ee5852d2 --- /dev/null +++ b/queue-5.19/cifs-return-correct-error-in-calc_signature.patch @@ -0,0 +1,57 @@ +From 7390f69c2e981e53ee2f1cc8058b006b9200221b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 20:57:05 -0300 +Subject: cifs: return correct error in ->calc_signature() + +From: Enzo Matsumiya + +[ Upstream commit 09a1f9a168ae1f69f701689429871793174417d2 ] + +If an error happens while getting the key or session in the +->calc_signature implementations, 0 (success) is returned. Fix it by +returning a proper error code. + +Since it seems to be highly unlikely to happen wrap the rc check in +unlikely() too. + +Reviewed-by: Ronnie Sahlberg +Fixes: 32811d242ff6 ("cifs: Start using per session key for smb2/3 for signature generation") +Signed-off-by: Enzo Matsumiya +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/cifs/smb2transport.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c +index 55e79f6ee78d..334d8471346f 100644 +--- a/fs/cifs/smb2transport.c ++++ b/fs/cifs/smb2transport.c +@@ -225,9 +225,9 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + struct smb_rqst drqst; + + ses = smb2_find_smb_ses(server, le64_to_cpu(shdr->SessionId)); +- if (!ses) { ++ if (unlikely(!ses)) { + cifs_server_dbg(VFS, "%s: Could not find session\n", __func__); +- return 0; ++ return -ENOENT; + } + + memset(smb2_signature, 0x0, SMB2_HMACSHA256_SIZE); +@@ -557,8 +557,10 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, + u8 key[SMB3_SIGN_KEY_SIZE]; + + rc = smb2_get_sign_key(le64_to_cpu(shdr->SessionId), server, key); +- if (rc) +- return 0; ++ if (unlikely(rc)) { ++ cifs_server_dbg(VFS, "%s: Could not get signing key\n", __func__); ++ return rc; ++ } + + if (allocate_crypto) { + rc = cifs_alloc_hash("cmac(aes)", &hash, &sdesc); +-- +2.35.1 + diff --git a/queue-5.19/clk-ast2600-bclk-comes-from-epll.patch b/queue-5.19/clk-ast2600-bclk-comes-from-epll.patch new file mode 100644 index 00000000000..d8eee1a4b78 --- /dev/null +++ b/queue-5.19/clk-ast2600-bclk-comes-from-epll.patch @@ -0,0 +1,38 @@ +From 5b0f982eb3e504231513a094b8a28391963f5f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Apr 2022 13:34:26 +0930 +Subject: clk: ast2600: BCLK comes from EPLL + +From: Joel Stanley + +[ Upstream commit b8c1dc9c00b252b3be853720a71b05ed451ddd9f ] + +This correction was made in the u-boot SDK recently. There are no +in-tree users of this clock so the impact is minimal. + +Fixes: d3d04f6c330a ("clk: Add support for AST2600 SoC") +Link: https://github.com/AspeedTech-BMC/u-boot/commit/8ad54a5ae15f27fea5e894cc2539a20d90019717 +Signed-off-by: Joel Stanley +Link: https://lore.kernel.org/r/20220421040426.171256-1-joel@jms.id.au +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-ast2600.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c +index 24dab2312bc6..9c3305bcb27a 100644 +--- a/drivers/clk/clk-ast2600.c ++++ b/drivers/clk/clk-ast2600.c +@@ -622,7 +622,7 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) + regmap_write(map, 0x308, 0x12000); /* 3x3 = 9 */ + + /* P-Bus (BCLK) clock divider */ +- hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0, ++ hw = clk_hw_register_divider_table(dev, "bclk", "epll", 0, + scu_g6_base + ASPEED_G6_CLK_SELECTION1, 20, 3, 0, + ast2600_div_table, + &aspeed_g6_clk_lock); +-- +2.35.1 + diff --git a/queue-5.19/clk-baikal-t1-add-sata-internal-ref-clock-buffer.patch b/queue-5.19/clk-baikal-t1-add-sata-internal-ref-clock-buffer.patch new file mode 100644 index 00000000000..3ab0c202c5a --- /dev/null +++ b/queue-5.19/clk-baikal-t1-add-sata-internal-ref-clock-buffer.patch @@ -0,0 +1,234 @@ +From 2bef985867bc973fcb5c90ff9368100fe96709d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 01:53:58 +0300 +Subject: clk: baikal-t1: Add SATA internal ref clock buffer + +From: Serge Semin + +[ Upstream commit 081a9b7c74eae4e12b2cb1b86720f836a8f29247 ] + +It turns out the internal SATA reference clock signal will stay +unavailable for the SATA interface consumer until the buffer on it's way +is ungated. So aside with having the actual clock divider enabled we need +to ungate a buffer placed on the signal way to the SATA controller (most +likely some rudiment from the initial SoC release). Seeing the switch flag +is placed in the same register as the SATA-ref clock divider at a +non-standard ffset, let's implement it as a separate clock controller with +the set-rate propagation to the parental clock divider wrapper. As such +we'll be able to disable/enable and still change the original clock source +rate. + +Fixes: 353afa3a8d2e ("clk: Add Baikal-T1 CCU Dividers driver") +Signed-off-by: Serge Semin +Link: https://lore.kernel.org/r/20220929225402.9696-5-Sergey.Semin@baikalelectronics.ru +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/baikal-t1/ccu-div.c | 64 +++++++++++++++++++++++++++++ + drivers/clk/baikal-t1/ccu-div.h | 4 ++ + drivers/clk/baikal-t1/clk-ccu-div.c | 18 +++++++- + 3 files changed, 85 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/baikal-t1/ccu-div.c b/drivers/clk/baikal-t1/ccu-div.c +index bbfa3526ee10..a6642f3d33d4 100644 +--- a/drivers/clk/baikal-t1/ccu-div.c ++++ b/drivers/clk/baikal-t1/ccu-div.c +@@ -34,6 +34,7 @@ + #define CCU_DIV_CTL_CLKDIV_MASK(_width) \ + GENMASK((_width) + CCU_DIV_CTL_CLKDIV_FLD - 1, CCU_DIV_CTL_CLKDIV_FLD) + #define CCU_DIV_CTL_LOCK_SHIFTED BIT(27) ++#define CCU_DIV_CTL_GATE_REF_BUF BIT(28) + #define CCU_DIV_CTL_LOCK_NORMAL BIT(31) + + #define CCU_DIV_RST_DELAY_US 1 +@@ -170,6 +171,40 @@ static int ccu_div_gate_is_enabled(struct clk_hw *hw) + return !!(val & CCU_DIV_CTL_EN); + } + ++static int ccu_div_buf_enable(struct clk_hw *hw) ++{ ++ struct ccu_div *div = to_ccu_div(hw); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&div->lock, flags); ++ regmap_update_bits(div->sys_regs, div->reg_ctl, ++ CCU_DIV_CTL_GATE_REF_BUF, 0); ++ spin_unlock_irqrestore(&div->lock, flags); ++ ++ return 0; ++} ++ ++static void ccu_div_buf_disable(struct clk_hw *hw) ++{ ++ struct ccu_div *div = to_ccu_div(hw); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&div->lock, flags); ++ regmap_update_bits(div->sys_regs, div->reg_ctl, ++ CCU_DIV_CTL_GATE_REF_BUF, CCU_DIV_CTL_GATE_REF_BUF); ++ spin_unlock_irqrestore(&div->lock, flags); ++} ++ ++static int ccu_div_buf_is_enabled(struct clk_hw *hw) ++{ ++ struct ccu_div *div = to_ccu_div(hw); ++ u32 val = 0; ++ ++ regmap_read(div->sys_regs, div->reg_ctl, &val); ++ ++ return !(val & CCU_DIV_CTL_GATE_REF_BUF); ++} ++ + static unsigned long ccu_div_var_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) + { +@@ -323,6 +358,7 @@ static const struct ccu_div_dbgfs_bit ccu_div_bits[] = { + CCU_DIV_DBGFS_BIT_ATTR("div_en", CCU_DIV_CTL_EN), + CCU_DIV_DBGFS_BIT_ATTR("div_rst", CCU_DIV_CTL_RST), + CCU_DIV_DBGFS_BIT_ATTR("div_bypass", CCU_DIV_CTL_SET_CLKDIV), ++ CCU_DIV_DBGFS_BIT_ATTR("div_buf", CCU_DIV_CTL_GATE_REF_BUF), + CCU_DIV_DBGFS_BIT_ATTR("div_lock", CCU_DIV_CTL_LOCK_NORMAL) + }; + +@@ -441,6 +477,9 @@ static void ccu_div_var_debug_init(struct clk_hw *hw, struct dentry *dentry) + continue; + } + ++ if (!strcmp("div_buf", name)) ++ continue; ++ + bits[didx] = ccu_div_bits[bidx]; + bits[didx].div = div; + +@@ -477,6 +516,21 @@ static void ccu_div_gate_debug_init(struct clk_hw *hw, struct dentry *dentry) + &ccu_div_dbgfs_fixed_clkdiv_fops); + } + ++static void ccu_div_buf_debug_init(struct clk_hw *hw, struct dentry *dentry) ++{ ++ struct ccu_div *div = to_ccu_div(hw); ++ struct ccu_div_dbgfs_bit *bit; ++ ++ bit = kmalloc(sizeof(*bit), GFP_KERNEL); ++ if (!bit) ++ return; ++ ++ *bit = ccu_div_bits[3]; ++ bit->div = div; ++ debugfs_create_file_unsafe(bit->name, ccu_div_dbgfs_mode, dentry, bit, ++ &ccu_div_dbgfs_bit_fops); ++} ++ + static void ccu_div_fixed_debug_init(struct clk_hw *hw, struct dentry *dentry) + { + struct ccu_div *div = to_ccu_div(hw); +@@ -489,6 +543,7 @@ static void ccu_div_fixed_debug_init(struct clk_hw *hw, struct dentry *dentry) + + #define ccu_div_var_debug_init NULL + #define ccu_div_gate_debug_init NULL ++#define ccu_div_buf_debug_init NULL + #define ccu_div_fixed_debug_init NULL + + #endif /* !CONFIG_DEBUG_FS */ +@@ -520,6 +575,13 @@ static const struct clk_ops ccu_div_gate_ops = { + .debug_init = ccu_div_gate_debug_init + }; + ++static const struct clk_ops ccu_div_buf_ops = { ++ .enable = ccu_div_buf_enable, ++ .disable = ccu_div_buf_disable, ++ .is_enabled = ccu_div_buf_is_enabled, ++ .debug_init = ccu_div_buf_debug_init ++}; ++ + static const struct clk_ops ccu_div_fixed_ops = { + .recalc_rate = ccu_div_fixed_recalc_rate, + .round_rate = ccu_div_fixed_round_rate, +@@ -566,6 +628,8 @@ struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *div_init) + } else if (div_init->type == CCU_DIV_GATE) { + hw_init.ops = &ccu_div_gate_ops; + div->divider = div_init->divider; ++ } else if (div_init->type == CCU_DIV_BUF) { ++ hw_init.ops = &ccu_div_buf_ops; + } else if (div_init->type == CCU_DIV_FIXED) { + hw_init.ops = &ccu_div_fixed_ops; + div->divider = div_init->divider; +diff --git a/drivers/clk/baikal-t1/ccu-div.h b/drivers/clk/baikal-t1/ccu-div.h +index b6a9c8e45318..4eb49ff4803c 100644 +--- a/drivers/clk/baikal-t1/ccu-div.h ++++ b/drivers/clk/baikal-t1/ccu-div.h +@@ -15,8 +15,10 @@ + + /* + * CCU Divider private clock IDs ++ * @CCU_SYS_SATA_CLK: CCU SATA internal clock + * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock + */ ++#define CCU_SYS_SATA_CLK -1 + #define CCU_SYS_XGMAC_CLK -2 + + /* +@@ -37,11 +39,13 @@ + * enum ccu_div_type - CCU Divider types + * @CCU_DIV_VAR: Clocks gate with variable divider. + * @CCU_DIV_GATE: Clocks gate with fixed divider. ++ * @CCU_DIV_BUF: Clock gate with no divider. + * @CCU_DIV_FIXED: Ungateable clock with fixed divider. + */ + enum ccu_div_type { + CCU_DIV_VAR, + CCU_DIV_GATE, ++ CCU_DIV_BUF, + CCU_DIV_FIXED + }; + +diff --git a/drivers/clk/baikal-t1/clk-ccu-div.c b/drivers/clk/baikal-t1/clk-ccu-div.c +index 3953ae5664be..90f4fda406ee 100644 +--- a/drivers/clk/baikal-t1/clk-ccu-div.c ++++ b/drivers/clk/baikal-t1/clk-ccu-div.c +@@ -76,6 +76,16 @@ + .divider = _divider \ + } + ++#define CCU_DIV_BUF_INFO(_id, _name, _pname, _base, _flags) \ ++ { \ ++ .id = _id, \ ++ .name = _name, \ ++ .parent_name = _pname, \ ++ .base = _base, \ ++ .type = CCU_DIV_BUF, \ ++ .flags = _flags \ ++ } ++ + #define CCU_DIV_FIXED_INFO(_id, _name, _pname, _divider) \ + { \ + .id = _id, \ +@@ -188,11 +198,14 @@ static const struct ccu_div_rst_map axi_rst_map[] = { + * for the SoC devices registers IO-operations. + */ + static const struct ccu_div_info sys_info[] = { +- CCU_DIV_VAR_INFO(CCU_SYS_SATA_REF_CLK, "sys_sata_ref_clk", ++ CCU_DIV_VAR_INFO(CCU_SYS_SATA_CLK, "sys_sata_clk", + "sata_clk", CCU_SYS_SATA_REF_BASE, 4, + CLK_SET_RATE_GATE, + CCU_DIV_SKIP_ONE | CCU_DIV_LOCK_SHIFTED | + CCU_DIV_RESET_DOMAIN), ++ CCU_DIV_BUF_INFO(CCU_SYS_SATA_REF_CLK, "sys_sata_ref_clk", ++ "sys_sata_clk", CCU_SYS_SATA_REF_BASE, ++ CLK_SET_RATE_PARENT), + CCU_DIV_VAR_INFO(CCU_SYS_APB_CLK, "sys_apb_clk", + "pcie_clk", CCU_SYS_APB_BASE, 5, + CLK_IS_CRITICAL, CCU_DIV_RESET_DOMAIN), +@@ -398,6 +411,9 @@ static int ccu_div_clk_register(struct ccu_div_data *data) + init.base = info->base; + init.sys_regs = data->sys_regs; + init.divider = info->divider; ++ } else if (init.type == CCU_DIV_BUF) { ++ init.base = info->base; ++ init.sys_regs = data->sys_regs; + } else { + init.divider = info->divider; + } +-- +2.35.1 + diff --git a/queue-5.19/clk-baikal-t1-add-shared-xgmac-ref-ptp-clocks-intern.patch b/queue-5.19/clk-baikal-t1-add-shared-xgmac-ref-ptp-clocks-intern.patch new file mode 100644 index 00000000000..eaa0aff8c3d --- /dev/null +++ b/queue-5.19/clk-baikal-t1-add-shared-xgmac-ref-ptp-clocks-intern.patch @@ -0,0 +1,84 @@ +From 8bd50414ef1fd37d9fe03c67007b9c24002de78e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 01:53:57 +0300 +Subject: clk: baikal-t1: Add shared xGMAC ref/ptp clocks internal parent + +From: Serge Semin + +[ Upstream commit e2eef312762e0b5a5a70d29fe59a245c0a3cffa0 ] + +Baikal-T1 CCU reference manual says that both xGMAC reference and xGMAC +PTP clocks are generated by two different wrappers with the same constant +divider thus each producing a 156.25 MHz signal. But for some reason both +of these clock sources are gated by a single switch-flag in the CCU +registers space - CCU_SYS_XGMAC_BASE.BIT(0). In order to make the clocks +handled independently we need to define a shared parental gate so the base +clock signal would be switched off only if both of the child-clocks are +disabled. + +Note the ID is intentionally set to -2 since we are going to add a one +more internal clock identifier in the next commit. + +Fixes: 353afa3a8d2e ("clk: Add Baikal-T1 CCU Dividers driver") +Signed-off-by: Serge Semin +Link: https://lore.kernel.org/r/20220929225402.9696-4-Sergey.Semin@baikalelectronics.ru +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/baikal-t1/ccu-div.c | 1 + + drivers/clk/baikal-t1/ccu-div.h | 6 ++++++ + drivers/clk/baikal-t1/clk-ccu-div.c | 8 +++++--- + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/baikal-t1/ccu-div.c b/drivers/clk/baikal-t1/ccu-div.c +index 4062092d67f9..bbfa3526ee10 100644 +--- a/drivers/clk/baikal-t1/ccu-div.c ++++ b/drivers/clk/baikal-t1/ccu-div.c +@@ -579,6 +579,7 @@ struct ccu_div *ccu_div_hw_register(const struct ccu_div_init_data *div_init) + goto err_free_div; + } + parent_data.fw_name = div_init->parent_name; ++ parent_data.name = div_init->parent_name; + hw_init.parent_data = &parent_data; + hw_init.num_parents = 1; + +diff --git a/drivers/clk/baikal-t1/ccu-div.h b/drivers/clk/baikal-t1/ccu-div.h +index 795665caefbd..b6a9c8e45318 100644 +--- a/drivers/clk/baikal-t1/ccu-div.h ++++ b/drivers/clk/baikal-t1/ccu-div.h +@@ -13,6 +13,12 @@ + #include + #include + ++/* ++ * CCU Divider private clock IDs ++ * @CCU_SYS_XGMAC_CLK: CCU XGMAC internal clock ++ */ ++#define CCU_SYS_XGMAC_CLK -2 ++ + /* + * CCU Divider private flags + * @CCU_DIV_SKIP_ONE: Due to some reason divider can't be set to 1. +diff --git a/drivers/clk/baikal-t1/clk-ccu-div.c b/drivers/clk/baikal-t1/clk-ccu-div.c +index ea77eec40ddd..3953ae5664be 100644 +--- a/drivers/clk/baikal-t1/clk-ccu-div.c ++++ b/drivers/clk/baikal-t1/clk-ccu-div.c +@@ -204,10 +204,12 @@ static const struct ccu_div_info sys_info[] = { + "eth_clk", CCU_SYS_GMAC1_BASE, 5), + CCU_DIV_FIXED_INFO(CCU_SYS_GMAC1_PTP_CLK, "sys_gmac1_ptp_clk", + "eth_clk", 10), +- CCU_DIV_GATE_INFO(CCU_SYS_XGMAC_REF_CLK, "sys_xgmac_ref_clk", +- "eth_clk", CCU_SYS_XGMAC_BASE, 8), ++ CCU_DIV_GATE_INFO(CCU_SYS_XGMAC_CLK, "sys_xgmac_clk", ++ "eth_clk", CCU_SYS_XGMAC_BASE, 1), ++ CCU_DIV_FIXED_INFO(CCU_SYS_XGMAC_REF_CLK, "sys_xgmac_ref_clk", ++ "sys_xgmac_clk", 8), + CCU_DIV_FIXED_INFO(CCU_SYS_XGMAC_PTP_CLK, "sys_xgmac_ptp_clk", +- "eth_clk", 8), ++ "sys_xgmac_clk", 8), + CCU_DIV_GATE_INFO(CCU_SYS_USB_CLK, "sys_usb_clk", + "eth_clk", CCU_SYS_USB_BASE, 10), + CCU_DIV_VAR_INFO(CCU_SYS_PVT_CLK, "sys_pvt_clk", +-- +2.35.1 + diff --git a/queue-5.19/clk-baikal-t1-fix-invalid-xgmac-ptp-clock-divider.patch b/queue-5.19/clk-baikal-t1-fix-invalid-xgmac-ptp-clock-divider.patch new file mode 100644 index 00000000000..24ef0524d85 --- /dev/null +++ b/queue-5.19/clk-baikal-t1-fix-invalid-xgmac-ptp-clock-divider.patch @@ -0,0 +1,38 @@ +From e6ebfe737383cd8b7c0d628650ed1ac97d5a79c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 01:53:56 +0300 +Subject: clk: baikal-t1: Fix invalid xGMAC PTP clock divider + +From: Serge Semin + +[ Upstream commit 3c742088686ce922704aec5b11d09bcc5a396589 ] + +Most likely due to copy-paste mistake the divider has been set to 10 while +according to the SoC reference manual it's supposed to be 8 thus having +PTP clock frequency of 156.25 MHz. + +Fixes: 353afa3a8d2e ("clk: Add Baikal-T1 CCU Dividers driver") +Signed-off-by: Serge Semin +Link: https://lore.kernel.org/r/20220929225402.9696-3-Sergey.Semin@baikalelectronics.ru +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/baikal-t1/clk-ccu-div.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/baikal-t1/clk-ccu-div.c b/drivers/clk/baikal-t1/clk-ccu-div.c +index f141fda12b09..ea77eec40ddd 100644 +--- a/drivers/clk/baikal-t1/clk-ccu-div.c ++++ b/drivers/clk/baikal-t1/clk-ccu-div.c +@@ -207,7 +207,7 @@ static const struct ccu_div_info sys_info[] = { + CCU_DIV_GATE_INFO(CCU_SYS_XGMAC_REF_CLK, "sys_xgmac_ref_clk", + "eth_clk", CCU_SYS_XGMAC_BASE, 8), + CCU_DIV_FIXED_INFO(CCU_SYS_XGMAC_PTP_CLK, "sys_xgmac_ptp_clk", +- "eth_clk", 10), ++ "eth_clk", 8), + CCU_DIV_GATE_INFO(CCU_SYS_USB_CLK, "sys_usb_clk", + "eth_clk", CCU_SYS_USB_BASE, 10), + CCU_DIV_VAR_INFO(CCU_SYS_PVT_CLK, "sys_pvt_clk", +-- +2.35.1 + diff --git a/queue-5.19/clk-bcm2835-fix-bcm2835_clock_rate_from_divisor-decl.patch b/queue-5.19/clk-bcm2835-fix-bcm2835_clock_rate_from_divisor-decl.patch new file mode 100644 index 00000000000..00dde3c4006 --- /dev/null +++ b/queue-5.19/clk-bcm2835-fix-bcm2835_clock_rate_from_divisor-decl.patch @@ -0,0 +1,43 @@ +From 41a23753bfedd691ee4c170a2e73f9ca5118c7cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 16:10:37 +0200 +Subject: clk: bcm2835: fix bcm2835_clock_rate_from_divisor declaration + +From: Stefan Wahren + +[ Upstream commit 0b919a3728691c172312dee99ba654055ccd8c84 ] + +The return value of bcm2835_clock_rate_from_divisor is always unsigned +and also all caller expect this. So fix the declaration accordingly. + +Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks") +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20220904141037.38816-1-stefan.wahren@i2se.com +Reviewed-by: Ivan T. Ivanov +Reviewed-by: Florian Fainelli +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/bcm/clk-bcm2835.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 48a1eb9f2d55..9e9f8b242958 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -966,9 +966,9 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, + return div; + } + +-static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock, +- unsigned long parent_rate, +- u32 div) ++static unsigned long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock, ++ unsigned long parent_rate, ++ u32 div) + { + const struct bcm2835_clock_data *data = clock->data; + u64 temp; +-- +2.35.1 + diff --git a/queue-5.19/clk-bcm2835-make-peripheral-pllc-critical.patch b/queue-5.19/clk-bcm2835-make-peripheral-pllc-critical.patch new file mode 100644 index 00000000000..70a3226ebcf --- /dev/null +++ b/queue-5.19/clk-bcm2835-make-peripheral-pllc-critical.patch @@ -0,0 +1,50 @@ +From b54e848c686071f107ec85f12ca30a634b02bbb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 10:45:09 +0200 +Subject: clk: bcm2835: Make peripheral PLLC critical +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maxime Ripard + +[ Upstream commit 6c5422851d8be8c7451e968fd2e6da41b6109e17 ] + +When testing for a series affecting the VEC, it was discovered that +turning off and on the VEC clock is crashing the system. + +It turns out that, when disabling the VEC clock, it's the only child of +the PLLC-per clock which will also get disabled. The source of the crash +is PLLC-per being disabled. + +It's likely that some other device might not take a clock reference that +it actually needs, but it's unclear which at this point. Let's make +PLLC-per critical so that we don't have that crash. + +Reported-by: Noralf Trønnes +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20220926084509.12233-1-maxime@cerno.tech +Reviewed-by: Stefan Wahren +Acked-by: Noralf Trønnes +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/bcm/clk-bcm2835.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index 9e9f8b242958..f1102b4c7e88 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -1784,7 +1784,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .load_mask = CM_PLLC_LOADPER, + .hold_mask = CM_PLLC_HOLDPER, + .fixed_divider = 1, +- .flags = CLK_SET_RATE_PARENT), ++ .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + + /* + * PLLD is the display PLL, used to drive DSI display panels. +-- +2.35.1 + diff --git a/queue-5.19/clk-bcm2835-round-uart-input-clock-up.patch b/queue-5.19/clk-bcm2835-round-uart-input-clock-up.patch new file mode 100644 index 00000000000..c0f14eb7890 --- /dev/null +++ b/queue-5.19/clk-bcm2835-round-uart-input-clock-up.patch @@ -0,0 +1,126 @@ +From 23e9ed21ce2d11171b0832117e56a58eda11a034 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 11:13:04 +0300 +Subject: clk: bcm2835: Round UART input clock up + +From: Ivan T. Ivanov + +[ Upstream commit f690a4d7a8f66430662975511c86819dc9965bcc ] + +It was reported that RPi3[1] and RPi Zero 2W boards have issues with +the Bluetooth. It turns out that when switching from initial to +operation speed host and device no longer can talk each other because +host uses incorrect UART baud rate. + +The UART driver used in this case is amba-pl011. Original fix, see +below Github link[2], was inside pl011 module, but somehow it didn't +look as the right place to fix. Beside that this original rounding +function is not exactly perfect for all possible clock values. So I +deiced to move the hack to the platform which actually need it. + +The UART clock is initialised to be as close to the requested +frequency as possible without exceeding it. Now that there is a +clock manager that returns the actual frequencies, an expected +48MHz clock is reported as 47999625. If the requested baud rate +== requested clock/16, there is no headroom and the slight +reduction in actual clock rate results in failure. + +If increasing a clock by less than 0.1% changes it from ..999.. +to ..000.., round it up. + +[1] https://bugzilla.suse.com/show_bug.cgi?id=1188238 +[2] https://github.com/raspberrypi/linux/commit/ab3f1b39537f6d3825b8873006fbe2fc5ff057b7 + +Cc: Phil Elwell +Signed-off-by: Ivan T. Ivanov +Reviewed-by: Stefan Wahren +Link: https://lore.kernel.org/r/20220912081306.24662-1-iivanov@suse.de +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/bcm/clk-bcm2835.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c +index f1102b4c7e88..e74fe6219d14 100644 +--- a/drivers/clk/bcm/clk-bcm2835.c ++++ b/drivers/clk/bcm/clk-bcm2835.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -502,6 +503,8 @@ struct bcm2835_clock_data { + bool low_jitter; + + u32 tcnt_mux; ++ ++ bool round_up; + }; + + struct bcm2835_gate_data { +@@ -993,12 +996,34 @@ static unsigned long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock + return temp; + } + ++static unsigned long bcm2835_round_rate(unsigned long rate) ++{ ++ unsigned long scaler; ++ unsigned long limit; ++ ++ limit = rate / 100000; ++ ++ scaler = 1; ++ while (scaler < limit) ++ scaler *= 10; ++ ++ /* ++ * If increasing a clock by less than 0.1% changes it ++ * from ..999.. to ..000.., round up. ++ */ ++ if ((rate + scaler - 1) / scaler % 1000 == 0) ++ rate = roundup(rate, scaler); ++ ++ return rate; ++} ++ + static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, + unsigned long parent_rate) + { + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; ++ unsigned long rate; + u32 div; + + if (data->int_bits == 0 && data->frac_bits == 0) +@@ -1006,7 +1031,12 @@ static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw, + + div = cprman_read(cprman, data->div_reg); + +- return bcm2835_clock_rate_from_divisor(clock, parent_rate, div); ++ rate = bcm2835_clock_rate_from_divisor(clock, parent_rate, div); ++ ++ if (data->round_up) ++ rate = bcm2835_round_rate(rate); ++ ++ return rate; + } + + static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock) +@@ -2143,7 +2173,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { + .div_reg = CM_UARTDIV, + .int_bits = 10, + .frac_bits = 12, +- .tcnt_mux = 28), ++ .tcnt_mux = 28, ++ .round_up = true), + + /* TV encoder clock. Only operating frequency is 108Mhz. */ + [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK( +-- +2.35.1 + diff --git a/queue-5.19/clk-berlin-add-of_node_put-for-of_get_parent.patch b/queue-5.19/clk-berlin-add-of_node_put-for-of_get_parent.patch new file mode 100644 index 00000000000..1a1da592761 --- /dev/null +++ b/queue-5.19/clk-berlin-add-of_node_put-for-of_get_parent.patch @@ -0,0 +1,77 @@ +From e80f20d97427333d4078e5e151b148ae02a0fa57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Jul 2022 16:49:00 +0800 +Subject: clk: berlin: Add of_node_put() for of_get_parent() + +From: Liang He + +[ Upstream commit 37c381b812dcbfde9c3f1f3d3e75fdfc1b40d5bc ] + +In berlin2_clock_setup() and berlin2q_clock_setup(), we need to +call of_node_put() for the reference returned by of_get_parent() +which has increased the refcount. We should call *_put() in fail +path or when it is not used anymore. + +Fixes: 26b3b6b959b2 ("clk: berlin: prepare simple-mfd conversion") +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220708084900.311684-1-windhl@126.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/berlin/bg2.c | 5 ++++- + drivers/clk/berlin/bg2q.c | 6 +++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c +index bccdfa00fd37..67a9edbba29c 100644 +--- a/drivers/clk/berlin/bg2.c ++++ b/drivers/clk/berlin/bg2.c +@@ -500,12 +500,15 @@ static void __init berlin2_clock_setup(struct device_node *np) + int n, ret; + + clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); +- if (!clk_data) ++ if (!clk_data) { ++ of_node_put(parent_np); + return; ++ } + clk_data->num = MAX_CLKS; + hws = clk_data->hws; + + gbase = of_iomap(parent_np, 0); ++ of_node_put(parent_np); + if (!gbase) + return; + +diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c +index e9518d35f262..dd2784bb75b6 100644 +--- a/drivers/clk/berlin/bg2q.c ++++ b/drivers/clk/berlin/bg2q.c +@@ -286,19 +286,23 @@ static void __init berlin2q_clock_setup(struct device_node *np) + int n, ret; + + clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); +- if (!clk_data) ++ if (!clk_data) { ++ of_node_put(parent_np); + return; ++ } + clk_data->num = MAX_CLKS; + hws = clk_data->hws; + + gbase = of_iomap(parent_np, 0); + if (!gbase) { ++ of_node_put(parent_np); + pr_err("%pOF: Unable to map global base\n", np); + return; + } + + /* BG2Q CPU PLL is not part of global registers */ + cpupll_base = of_iomap(parent_np, 1); ++ of_node_put(parent_np); + if (!cpupll_base) { + pr_err("%pOF: Unable to map cpupll base\n", np); + iounmap(gbase); +-- +2.35.1 + diff --git a/queue-5.19/clk-generalize-devm_clk_get-a-bit.patch b/queue-5.19/clk-generalize-devm_clk_get-a-bit.patch new file mode 100644 index 00000000000..1b134e04755 --- /dev/null +++ b/queue-5.19/clk-generalize-devm_clk_get-a-bit.patch @@ -0,0 +1,124 @@ +From 93861fad9d3b7b1fedb6b378c95f14c1df2a25e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 May 2022 09:57:35 +0200 +Subject: clk: generalize devm_clk_get() a bit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit abae8e57e49aa75f6db76aa866c775721523908f ] + +Allow to add an exit hook to devm managed clocks. Also use +clk_get_optional() in devm_clk_get_optional instead of open coding it. +The generalisation will be used in the next commit to add some more +devm_clk helpers. + +Reviewed-by: Jonathan Cameron +Reviewed-by: Alexandru Ardelean +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20220520075737.758761-3-u.kleine-koenig@pengutronix.de +Signed-off-by: Stephen Boyd +Stable-dep-of: 10a2199caf43 ("hwrng: imx-rngc - Moving IRQ handler registering after imx_rngc_irq_mask_clear()") +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-devres.c | 66 +++++++++++++++++++++++++++++----------- + 1 file changed, 49 insertions(+), 17 deletions(-) + +diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c +index f9d5b7334341..c822f4ef1584 100644 +--- a/drivers/clk/clk-devres.c ++++ b/drivers/clk/clk-devres.c +@@ -4,39 +4,71 @@ + #include + #include + ++struct devm_clk_state { ++ struct clk *clk; ++ void (*exit)(struct clk *clk); ++}; ++ + static void devm_clk_release(struct device *dev, void *res) + { +- clk_put(*(struct clk **)res); ++ struct devm_clk_state *state = *(struct devm_clk_state **)res; ++ ++ if (state->exit) ++ state->exit(state->clk); ++ ++ clk_put(state->clk); + } + +-struct clk *devm_clk_get(struct device *dev, const char *id) ++static struct clk *__devm_clk_get(struct device *dev, const char *id, ++ struct clk *(*get)(struct device *dev, const char *id), ++ int (*init)(struct clk *clk), ++ void (*exit)(struct clk *clk)) + { +- struct clk **ptr, *clk; ++ struct devm_clk_state *state; ++ struct clk *clk; ++ int ret; + +- ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); +- if (!ptr) ++ state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL); ++ if (!state) + return ERR_PTR(-ENOMEM); + +- clk = clk_get(dev, id); +- if (!IS_ERR(clk)) { +- *ptr = clk; +- devres_add(dev, ptr); +- } else { +- devres_free(ptr); ++ clk = get(dev, id); ++ if (IS_ERR(clk)) { ++ ret = PTR_ERR(clk); ++ goto err_clk_get; + } + ++ if (init) { ++ ret = init(clk); ++ if (ret) ++ goto err_clk_init; ++ } ++ ++ state->clk = clk; ++ state->exit = exit; ++ ++ devres_add(dev, state); ++ + return clk; ++ ++err_clk_init: ++ ++ clk_put(clk); ++err_clk_get: ++ ++ devres_free(state); ++ return ERR_PTR(ret); ++} ++ ++struct clk *devm_clk_get(struct device *dev, const char *id) ++{ ++ return __devm_clk_get(dev, id, clk_get, NULL, NULL); + } + EXPORT_SYMBOL(devm_clk_get); + + struct clk *devm_clk_get_optional(struct device *dev, const char *id) + { +- struct clk *clk = devm_clk_get(dev, id); +- +- if (clk == ERR_PTR(-ENOENT)) +- return NULL; +- +- return clk; ++ return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL); + } + EXPORT_SYMBOL(devm_clk_get_optional); + +-- +2.35.1 + diff --git a/queue-5.19/clk-imx-scu-fix-memleak-on-platform_device_add-fails.patch b/queue-5.19/clk-imx-scu-fix-memleak-on-platform_device_add-fails.patch new file mode 100644 index 00000000000..063f04a9127 --- /dev/null +++ b/queue-5.19/clk-imx-scu-fix-memleak-on-platform_device_add-fails.patch @@ -0,0 +1,42 @@ +From 22fdfedeca75af75e6a9ad8b9c61127237613912 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 11:32:06 +0800 +Subject: clk: imx: scu: fix memleak on platform_device_add() fails + +From: Lin Yujun + +[ Upstream commit 855ae87a2073ebf1b395e020de54fdf9ce7d166f ] + +No error handling is performed when platform_device_add() +fails. Add error processing before return, and modified +the return value. + +Fixes: 77d8f3068c63 ("clk: imx: scu: add two cells binding support") +Signed-off-by: Lin Yujun +Link: https://lore.kernel.org/r/20220914033206.98046-1-linyujun809@huawei.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/imx/clk-scu.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c +index c56e406138db..1e6870f3671f 100644 +--- a/drivers/clk/imx/clk-scu.c ++++ b/drivers/clk/imx/clk-scu.c +@@ -695,7 +695,11 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, + pr_warn("%s: failed to attached the power domain %d\n", + name, ret); + +- platform_device_add(pdev); ++ ret = platform_device_add(pdev); ++ if (ret) { ++ platform_device_put(pdev); ++ return ERR_PTR(ret); ++ } + + /* For API backwards compatiblilty, simply return NULL for success */ + return NULL; +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-clk-mt8195-mfg-reparent-mfg_bg3d-and-pr.patch b/queue-5.19/clk-mediatek-clk-mt8195-mfg-reparent-mfg_bg3d-and-pr.patch new file mode 100644 index 00000000000..453be2a223c --- /dev/null +++ b/queue-5.19/clk-mediatek-clk-mt8195-mfg-reparent-mfg_bg3d-and-pr.patch @@ -0,0 +1,55 @@ +From 0abfc9562df9c6f94279ad95ad13a2e38fd44e2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 12:11:23 +0200 +Subject: clk: mediatek: clk-mt8195-mfg: Reparent mfg_bg3d and propagate rate + changes + +From: AngeloGioacchino Del Regno + +[ Upstream commit a5f7bf5458c2cf6730106e16a6373638a0e5ed1e ] + +The MFG_BG3D is a gate to enable/disable clock output to the GPU, +but the actual output is decided by multiple muxes; in particular: +mfg_ck_fast_ref muxes between "slow" (top_mfg_core_tmp) and +"fast" (MFGPLL) clock, while top_mfg_core_tmp muxes between the +26MHz clock and various system PLLs. + +The clock gate comes after all the muxes, so its parent is +mfg_ck_fast_reg, not top_mfg_core_tmp. +Reparent MFG_BG3D to the latter to match the hardware and add the +CLK_SET_RATE_PARENT flag to it: this way we ensure propagating +rate changes that are requested on MFG_BG3D along its entire clock +tree. + +Fixes: 35016f10c0e5 ("clk: mediatek: Add MT8195 mfgcfg clock support") +Signed-off-by: AngeloGioacchino Del Regno +Reviewed-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20220927101128.44758-6-angelogioacchino.delregno@collabora.com +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mt8195-mfg.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/mediatek/clk-mt8195-mfg.c b/drivers/clk/mediatek/clk-mt8195-mfg.c +index 9411c556a5a9..c94cb71bd9b9 100644 +--- a/drivers/clk/mediatek/clk-mt8195-mfg.c ++++ b/drivers/clk/mediatek/clk-mt8195-mfg.c +@@ -17,10 +17,12 @@ static const struct mtk_gate_regs mfg_cg_regs = { + }; + + #define GATE_MFG(_id, _name, _parent, _shift) \ +- GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) ++ GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, \ ++ _shift, &mtk_clk_gate_ops_setclr, \ ++ CLK_SET_RATE_PARENT) + + static const struct mtk_gate mfg_clks[] = { +- GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "top_mfg_core_tmp", 0), ++ GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_ck_fast_ref", 0), + }; + + static const struct mtk_clk_desc mfg_desc = { +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-clk-mt8195-vdo0-set-rate-on-vdo0_dp_int.patch b/queue-5.19/clk-mediatek-clk-mt8195-vdo0-set-rate-on-vdo0_dp_int.patch new file mode 100644 index 00000000000..3535d4c993c --- /dev/null +++ b/queue-5.19/clk-mediatek-clk-mt8195-vdo0-set-rate-on-vdo0_dp_int.patch @@ -0,0 +1,59 @@ +From 4bcfd8a8a48a3e77d8f6607cb3736c08370b5c44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 15:32:55 -0400 +Subject: clk: mediatek: clk-mt8195-vdo0: Set rate on vdo0_dp_intf0_dp_intf's + parent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: AngeloGioacchino Del Regno + +[ Upstream commit 3f0dadd230cc2630202a977fe52cd1dd7a7579a7 ] + +Add the CLK_SET_RATE_PARENT flag to the CLK_VDO0_DP_INTF0_DP_INTF +clock: this is required to trigger clock source selection on +CLK_TOP_EDP, while avoiding to manage the enablement of the former +separately from the latter in the displayport driver. + +Fixes: 70282c90d4a2 ("clk: mediatek: Add MT8195 vdosys0 clock support") +Signed-off-by: AngeloGioacchino Del Regno +Tested-by: Bo-Chen Chen +Reviewed-by: Bo-Chen Chen +Signed-off-by: Nícolas F. R. A. Prado + +Link: https://lore.kernel.org/r/20220816193257.658487-2-nfraprado@collabora.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mt8195-vdo0.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c +index 261a7f76dd3c..07b46bfd5040 100644 +--- a/drivers/clk/mediatek/clk-mt8195-vdo0.c ++++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c +@@ -37,6 +37,10 @@ static const struct mtk_gate_regs vdo0_2_cg_regs = { + #define GATE_VDO0_2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo0_2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + ++#define GATE_VDO0_2_FLAGS(_id, _name, _parent, _shift, _flags) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &vdo0_2_cg_regs, _shift, \ ++ &mtk_clk_gate_ops_setclr, _flags) ++ + static const struct mtk_gate vdo0_clks[] = { + /* VDO0_0 */ + GATE_VDO0_0(CLK_VDO0_DISP_OVL0, "vdo0_disp_ovl0", "top_vpp", 0), +@@ -85,7 +89,8 @@ static const struct mtk_gate vdo0_clks[] = { + /* VDO0_2 */ + GATE_VDO0_2(CLK_VDO0_DSI0_DSI, "vdo0_dsi0_dsi", "top_dsi_occ", 0), + GATE_VDO0_2(CLK_VDO0_DSI1_DSI, "vdo0_dsi1_dsi", "top_dsi_occ", 8), +- GATE_VDO0_2(CLK_VDO0_DP_INTF0_DP_INTF, "vdo0_dp_intf0_dp_intf", "top_edp", 16), ++ GATE_VDO0_2_FLAGS(CLK_VDO0_DP_INTF0_DP_INTF, "vdo0_dp_intf0_dp_intf", ++ "top_edp", 16, CLK_SET_RATE_PARENT), + }; + + static int clk_mt8195_vdo0_probe(struct platform_device *pdev) +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-clk-mt8195-vdo1-reparent-and-set-rate-o.patch b/queue-5.19/clk-mediatek-clk-mt8195-vdo1-reparent-and-set-rate-o.patch new file mode 100644 index 00000000000..1b48219321d --- /dev/null +++ b/queue-5.19/clk-mediatek-clk-mt8195-vdo1-reparent-and-set-rate-o.patch @@ -0,0 +1,60 @@ +From 4ffed2894c56021f1ae129765bfcff9ca27aa3d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 15:32:56 -0400 +Subject: clk: mediatek: clk-mt8195-vdo1: Reparent and set rate on + vdo1_dpintf's parent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: AngeloGioacchino Del Regno + +[ Upstream commit f24d71feb206631116ff9adaa6d43650c5dd8849 ] + +Like it was done for the vdo0_dp_intf0_dp_intf clock (used for eDP), +add the CLK_SET_RATE_PARENT flag to CLK_VDO1_DPINTF (used for DP) +and also fix its parent clock name as it has to be "top_dp" for two +reasons: + - This is its real parent! + - Likewise to eDP/VDO0 counterpart, we need clock source + selection on CLK_TOP_DP. + +Fixes: 269987505ba9 ("clk: mediatek: Add MT8195 vdosys1 clock support") +Signed-off-by: AngeloGioacchino Del Regno +Tested-by: Bo-Chen Chen +Reviewed-by: Bo-Chen Chen +Signed-off-by: Nícolas F. R. A. Prado +Link: https://lore.kernel.org/r/20220816193257.658487-3-nfraprado@collabora.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mt8195-vdo1.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c +index 3378487d2c90..d54d7726d186 100644 +--- a/drivers/clk/mediatek/clk-mt8195-vdo1.c ++++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c +@@ -43,6 +43,10 @@ static const struct mtk_gate_regs vdo1_3_cg_regs = { + #define GATE_VDO1_2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + ++#define GATE_VDO1_2_FLAGS(_id, _name, _parent, _shift, _flags) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &vdo1_2_cg_regs, _shift, \ ++ &mtk_clk_gate_ops_setclr, _flags) ++ + #define GATE_VDO1_3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_3_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +@@ -99,7 +103,7 @@ static const struct mtk_gate vdo1_clks[] = { + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPI0, "vdo1_disp_monitor_dpi0", "top_vpp", 1), + GATE_VDO1_2(CLK_VDO1_DPI1, "vdo1_dpi1", "top_vpp", 8), + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPI1, "vdo1_disp_monitor_dpi1", "top_vpp", 9), +- GATE_VDO1_2(CLK_VDO1_DPINTF, "vdo1_dpintf", "top_vpp", 16), ++ GATE_VDO1_2_FLAGS(CLK_VDO1_DPINTF, "vdo1_dpintf", "top_dp", 16, CLK_SET_RATE_PARENT), + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPINTF, "vdo1_disp_monitor_dpintf", "top_vpp", 17), + /* VDO1_3 */ + GATE_VDO1_3(CLK_VDO1_26M_SLOW, "vdo1_26m_slow", "clk26m", 8), +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-fix-unregister-function-in-mtk_clk_regi.patch b/queue-5.19/clk-mediatek-fix-unregister-function-in-mtk_clk_regi.patch new file mode 100644 index 00000000000..3e96f96a8c7 --- /dev/null +++ b/queue-5.19/clk-mediatek-fix-unregister-function-in-mtk_clk_regi.patch @@ -0,0 +1,42 @@ +From 0924888d68af25441bc4287fde7ca9bdae5b582f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 18:25:18 +0800 +Subject: clk: mediatek: fix unregister function in mtk_clk_register_dividers + cleanup + +From: Chen-Yu Tsai + +[ Upstream commit 20f7a0dba9075fb0e3d645495bc24d7025b58de1 ] + +When the cleanup paths for the various clk register APIs in the MediaTek +clk library were added, the one in the dividers type used the wrong type +of unregister function. This would result in incorrect dereferencing of +the clk pointer and freeing of invalid pointers. + +Fix this by switching to the correct type of clk unregistration call. + +Fixes: 3c3ba2ab0226 ("clk: mediatek: mtk: Implement error handling in register APIs") +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220926102523.2367530-2-wenst@chromium.org +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mtk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c +index b9188000ab3c..53bb8b88332f 100644 +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -393,7 +393,7 @@ int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) + continue; + +- mtk_clk_unregister_composite(clk_data->hws[mcd->id]); ++ clk_hw_unregister_divider(clk_data->hws[mcd->id]); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); + } + +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-migrate-remaining-clk_unregister_-to-cl.patch b/queue-5.19/clk-mediatek-migrate-remaining-clk_unregister_-to-cl.patch new file mode 100644 index 00000000000..46f863bf7d8 --- /dev/null +++ b/queue-5.19/clk-mediatek-migrate-remaining-clk_unregister_-to-cl.patch @@ -0,0 +1,78 @@ +From 8db87f3461360248f255b764d23bcf07fe20cd89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 18:25:19 +0800 +Subject: clk: mediatek: Migrate remaining clk_unregister_*() to + clk_hw_unregister_*() + +From: Chen-Yu Tsai + +[ Upstream commit fef14676fc4be40b8441745a3c96b7e7d7d8592d ] + +During the previous |struct clk| to |struct clk_hw| clk provider API +migration in commit 6f691a586296 ("clk: mediatek: Switch to clk_hw +provider APIs"), a few clk_unregister_*() calls were missed. + +Migrate the remaining ones to the |struct clk_hw| provider API, i.e. +change clk_unregister_*() to clk_hw_unregister_*(). + +Fixes: 6f691a586296 ("clk: mediatek: Switch to clk_hw provider APIs") +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220926102523.2367530-3-wenst@chromium.org +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mtk.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c +index 53bb8b88332f..35845163edae 100644 +--- a/drivers/clk/mediatek/clk-mtk.c ++++ b/drivers/clk/mediatek/clk-mtk.c +@@ -80,7 +80,7 @@ int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) + continue; + +- clk_unregister_fixed_rate(clk_data->hws[rc->id]->clk); ++ clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); + } + +@@ -102,7 +102,7 @@ void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) + continue; + +- clk_unregister_fixed_rate(clk_data->hws[rc->id]->clk); ++ clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); + } + } +@@ -146,7 +146,7 @@ int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) + continue; + +- clk_unregister_fixed_factor(clk_data->hws[ff->id]->clk); ++ clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); + } + +@@ -168,7 +168,7 @@ void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) + continue; + +- clk_unregister_fixed_factor(clk_data->hws[ff->id]->clk); ++ clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); + } + } +@@ -414,7 +414,7 @@ void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) + continue; + +- clk_unregister_divider(clk_data->hws[mcd->id]->clk); ++ clk_hw_unregister_divider(clk_data->hws[mcd->id]); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); + } + } +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-mt8183-mfgcfg-propagate-rate-changes-to.patch b/queue-5.19/clk-mediatek-mt8183-mfgcfg-propagate-rate-changes-to.patch new file mode 100644 index 00000000000..017256cf9e2 --- /dev/null +++ b/queue-5.19/clk-mediatek-mt8183-mfgcfg-propagate-rate-changes-to.patch @@ -0,0 +1,44 @@ +From 46ecb22366b5c45b5cfb16d22453ab576cc86408 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 12:11:20 +0200 +Subject: clk: mediatek: mt8183: mfgcfg: Propagate rate changes to parent + +From: Chen-Yu Tsai + +[ Upstream commit 9f94f545f258b15bfa6357eb62e1e307b712851e ] + +The only clock in the MT8183 MFGCFG block feeds the GPU. Propagate its +rate change requests to its parent, so that DVFS for the GPU can work +properly. + +Fixes: acddfc2c261b ("clk: mediatek: Add MT8183 clock support") +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220927101128.44758-3-angelogioacchino.delregno@collabora.com +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mt8183-mfgcfg.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c +index d774edaf760b..230299728859 100644 +--- a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c ++++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c +@@ -18,9 +18,9 @@ static const struct mtk_gate_regs mfg_cg_regs = { + .sta_ofs = 0x0, + }; + +-#define GATE_MFG(_id, _name, _parent, _shift) \ +- GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, \ +- &mtk_clk_gate_ops_setclr) ++#define GATE_MFG(_id, _name, _parent, _shift) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, \ ++ &mtk_clk_gate_ops_setclr, CLK_SET_RATE_PARENT) + + static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0) +-- +2.35.1 + diff --git a/queue-5.19/clk-mediatek-mt8195-infra_ao-set-pwrmcu-clocks-as-cr.patch b/queue-5.19/clk-mediatek-mt8195-infra_ao-set-pwrmcu-clocks-as-cr.patch new file mode 100644 index 00000000000..ce0e39ce822 --- /dev/null +++ b/queue-5.19/clk-mediatek-mt8195-infra_ao-set-pwrmcu-clocks-as-cr.patch @@ -0,0 +1,65 @@ +From aa99e1c3a8aaffba2854c214d25be597ad476afd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jul 2022 11:33:16 +0200 +Subject: clk: mediatek: mt8195-infra_ao: Set pwrmcu clocks as critical + +From: AngeloGioacchino Del Regno + +[ Upstream commit 3f10f49cd9f8ab6471639d4ca2c6db9451121779 ] + +The pwrmcu is responsible for power management and idle states in SSPM: +on older SoCs this was managed in Linux drivers like sspm/mcupm/eemgpu +but, at least on MT8195, this functionality was transferred to the ATF +firmware. +For this reason, turning off the pwrmcu related clocks from the kernel +will lead to unability to resume the platform after suspend and other +currently unknown PM related side-effects. + +Set the PWRMCU and PWRMCU_BUS_H clocks as critical to prevent the +kernel from turning them off, fixing the aforementioned issue. + +Fixes: e2edf59dec0b ("clk: mediatek: Add MT8195 infrastructure clock support") +Signed-off-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220719093316.37253-1-angelogioacchino.delregno@collabora.com +Reviewed-by: Matthias Brugger +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/mediatek/clk-mt8195-infra_ao.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/mediatek/clk-mt8195-infra_ao.c b/drivers/clk/mediatek/clk-mt8195-infra_ao.c +index 8ebe3b9415c4..0faa876815e8 100644 +--- a/drivers/clk/mediatek/clk-mt8195-infra_ao.c ++++ b/drivers/clk/mediatek/clk-mt8195-infra_ao.c +@@ -54,8 +54,12 @@ static const struct mtk_gate_regs infra_ao4_cg_regs = { + #define GATE_INFRA_AO1(_id, _name, _parent, _shift) \ + GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, 0) + ++#define GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, _flag) \ ++ GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao2_cg_regs, _shift, \ ++ &mtk_clk_gate_ops_setclr, _flag) ++ + #define GATE_INFRA_AO2(_id, _name, _parent, _shift) \ +- GATE_MTK(_id, _name, _parent, &infra_ao2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) ++ GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, 0) + + #define GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao3_cg_regs, _shift, \ +@@ -135,8 +139,11 @@ static const struct mtk_gate infra_ao_clks[] = { + GATE_INFRA_AO2(CLK_INFRA_AO_UNIPRO_SYS, "infra_ao_unipro_sys", "top_ufs", 11), + GATE_INFRA_AO2(CLK_INFRA_AO_UNIPRO_TICK, "infra_ao_unipro_tick", "top_ufs_tick1us", 12), + GATE_INFRA_AO2(CLK_INFRA_AO_UFS_MP_SAP_B, "infra_ao_ufs_mp_sap_b", "top_ufs_mp_sap_cfg", 13), +- GATE_INFRA_AO2(CLK_INFRA_AO_PWRMCU, "infra_ao_pwrmcu", "top_pwrmcu", 15), +- GATE_INFRA_AO2(CLK_INFRA_AO_PWRMCU_BUS_H, "infra_ao_pwrmcu_bus_h", "top_axi", 17), ++ /* pwrmcu is used by ATF for platform PM: clocks must never be disabled by the kernel */ ++ GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_PWRMCU, "infra_ao_pwrmcu", "top_pwrmcu", 15, ++ CLK_IS_CRITICAL), ++ GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_PWRMCU_BUS_H, "infra_ao_pwrmcu_bus_h", "top_axi", 17, ++ CLK_IS_CRITICAL), + GATE_INFRA_AO2(CLK_INFRA_AO_APDMA_B, "infra_ao_apdma_b", "top_axi", 18), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI4, "infra_ao_spi4", "top_spi", 25), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI5, "infra_ao_spi5", "top_spi", 26), +-- +2.35.1 + diff --git a/queue-5.19/clk-meson-hold-reference-returned-by-of_get_parent.patch b/queue-5.19/clk-meson-hold-reference-returned-by-of_get_parent.patch new file mode 100644 index 00000000000..0e3bae6223a --- /dev/null +++ b/queue-5.19/clk-meson-hold-reference-returned-by-of_get_parent.patch @@ -0,0 +1,98 @@ +From 8783e0588432fe07157e6921915283617c556e66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 22:10:38 +0800 +Subject: clk: meson: Hold reference returned by of_get_parent() + +From: Liang He + +[ Upstream commit 89ab396d712f7c91fe94f55cff23460426f5fc81 ] + +We should hold the reference returned by of_get_parent() and use it +to call of_node_put() for refcount balance. + +Fixes: 88e2da81241e ("clk: meson: aoclk: refactor common code into dedicated file") +Fixes: 6682bd4d443f ("clk: meson: factorise meson64 peripheral clock controller drivers") +Fixes: bb6eddd1d28c ("clk: meson: meson8b: use the HHI syscon if available") + +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220628141038.168383-1-windhl@126.com +Reviewed-by: Neil Armstrong +Reviewed-by: Martin Blumenstingl +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/meson/meson-aoclk.c | 5 ++++- + drivers/clk/meson/meson-eeclk.c | 5 ++++- + drivers/clk/meson/meson8b.c | 5 ++++- + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c +index 27cd2c1f3f61..434cd8f9de82 100644 +--- a/drivers/clk/meson/meson-aoclk.c ++++ b/drivers/clk/meson/meson-aoclk.c +@@ -38,6 +38,7 @@ int meson_aoclkc_probe(struct platform_device *pdev) + struct meson_aoclk_reset_controller *rstc; + struct meson_aoclk_data *data; + struct device *dev = &pdev->dev; ++ struct device_node *np; + struct regmap *regmap; + int ret, clkid; + +@@ -49,7 +50,9 @@ int meson_aoclkc_probe(struct platform_device *pdev) + if (!rstc) + return -ENOMEM; + +- regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); ++ np = of_get_parent(dev->of_node); ++ regmap = syscon_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to get regmap\n"); + return PTR_ERR(regmap); +diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c +index 8d5a5dab955a..0e5e6b57eb20 100644 +--- a/drivers/clk/meson/meson-eeclk.c ++++ b/drivers/clk/meson/meson-eeclk.c +@@ -18,6 +18,7 @@ int meson_eeclkc_probe(struct platform_device *pdev) + { + const struct meson_eeclkc_data *data; + struct device *dev = &pdev->dev; ++ struct device_node *np; + struct regmap *map; + int ret, i; + +@@ -26,7 +27,9 @@ int meson_eeclkc_probe(struct platform_device *pdev) + return -EINVAL; + + /* Get the hhi system controller node */ +- map = syscon_node_to_regmap(of_get_parent(dev->of_node)); ++ np = of_get_parent(dev->of_node); ++ map = syscon_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(map)) { + dev_err(dev, + "failed to get HHI regmap\n"); +diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c +index 8f3b7a94a667..827e78fb16a8 100644 +--- a/drivers/clk/meson/meson8b.c ++++ b/drivers/clk/meson/meson8b.c +@@ -3792,12 +3792,15 @@ static void __init meson8b_clkc_init_common(struct device_node *np, + struct clk_hw_onecell_data *clk_hw_onecell_data) + { + struct meson8b_clk_reset *rstc; ++ struct device_node *parent_np; + const char *notifier_clk_name; + struct clk *notifier_clk; + struct regmap *map; + int i, ret; + +- map = syscon_node_to_regmap(of_get_parent(np)); ++ parent_np = of_get_parent(np); ++ map = syscon_node_to_regmap(parent_np); ++ of_node_put(parent_np); + if (IS_ERR(map)) { + pr_err("failed to get HHI regmap - Trying obsolete regs\n"); + return; +-- +2.35.1 + diff --git a/queue-5.19/clk-oxnas-hold-reference-returned-by-of_get_parent.patch b/queue-5.19/clk-oxnas-hold-reference-returned-by-of_get_parent.patch new file mode 100644 index 00000000000..f8ac4fa4d52 --- /dev/null +++ b/queue-5.19/clk-oxnas-hold-reference-returned-by-of_get_parent.patch @@ -0,0 +1,49 @@ +From d943b345187927e5f37cd0c40f090ba16999f783 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 22:31:55 +0800 +Subject: clk: oxnas: Hold reference returned by of_get_parent() + +From: Liang He + +[ Upstream commit 1d6aa08c54cd0e005210ab8e3b1e92ede70f8a4f ] + +In oxnas_stdclk_probe(), we need to hold the reference returned by +of_get_parent() and use it to call of_node_put() for refcount +balance. + +Fixes: 0bbd72b4c64f ("clk: Add Oxford Semiconductor OXNAS Standard Clocks") +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220628143155.170550-1-windhl@126.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-oxnas.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c +index cda5e258355b..584e293156ad 100644 +--- a/drivers/clk/clk-oxnas.c ++++ b/drivers/clk/clk-oxnas.c +@@ -207,7 +207,7 @@ static const struct of_device_id oxnas_stdclk_dt_ids[] = { + + static int oxnas_stdclk_probe(struct platform_device *pdev) + { +- struct device_node *np = pdev->dev.of_node; ++ struct device_node *np = pdev->dev.of_node, *parent_np; + const struct oxnas_stdclk_data *data; + struct regmap *regmap; + int ret; +@@ -215,7 +215,9 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) + + data = of_device_get_match_data(&pdev->dev); + +- regmap = syscon_node_to_regmap(of_get_parent(np)); ++ parent_np = of_get_parent(np); ++ regmap = syscon_node_to_regmap(parent_np); ++ of_node_put(parent_np); + if (IS_ERR(regmap)) { + dev_err(&pdev->dev, "failed to have parent regmap\n"); + return PTR_ERR(regmap); +-- +2.35.1 + diff --git a/queue-5.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch b/queue-5.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch new file mode 100644 index 00000000000..05ace615530 --- /dev/null +++ b/queue-5.19/clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch @@ -0,0 +1,214 @@ +From 2c9243c9fc77edec150d7819b16a69d373d2193c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 May 2022 09:57:36 +0200 +Subject: clk: Provide new devm_clk helpers for prepared and enabled clocks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 7ef9651e9792b08eb310c6beb202cbc947f43cab ] + +When a driver keeps a clock prepared (or enabled) during the whole +lifetime of the driver, these helpers allow to simplify the drivers. + +Reviewed-by: Jonathan Cameron +Reviewed-by: Alexandru Ardelean +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20220520075737.758761-4-u.kleine-koenig@pengutronix.de +Signed-off-by: Stephen Boyd +Stable-dep-of: 10a2199caf43 ("hwrng: imx-rngc - Moving IRQ handler registering after imx_rngc_irq_mask_clear()") +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-devres.c | 27 ++++++++++ + include/linux/clk.h | 109 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 136 insertions(+) + +diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c +index c822f4ef1584..43ccd20e0298 100644 +--- a/drivers/clk/clk-devres.c ++++ b/drivers/clk/clk-devres.c +@@ -66,12 +66,39 @@ struct clk *devm_clk_get(struct device *dev, const char *id) + } + EXPORT_SYMBOL(devm_clk_get); + ++struct clk *devm_clk_get_prepared(struct device *dev, const char *id) ++{ ++ return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare); ++} ++EXPORT_SYMBOL_GPL(devm_clk_get_prepared); ++ ++struct clk *devm_clk_get_enabled(struct device *dev, const char *id) ++{ ++ return __devm_clk_get(dev, id, clk_get, ++ clk_prepare_enable, clk_disable_unprepare); ++} ++EXPORT_SYMBOL_GPL(devm_clk_get_enabled); ++ + struct clk *devm_clk_get_optional(struct device *dev, const char *id) + { + return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL); + } + EXPORT_SYMBOL(devm_clk_get_optional); + ++struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id) ++{ ++ return __devm_clk_get(dev, id, clk_get_optional, ++ clk_prepare, clk_unprepare); ++} ++EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared); ++ ++struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id) ++{ ++ return __devm_clk_get(dev, id, clk_get_optional, ++ clk_prepare_enable, clk_disable_unprepare); ++} ++EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled); ++ + struct clk_bulk_devres { + struct clk_bulk_data *clks; + int num_clks; +diff --git a/include/linux/clk.h b/include/linux/clk.h +index 39faa54efe88..d2394b1f4efe 100644 +--- a/include/linux/clk.h ++++ b/include/linux/clk.h +@@ -458,6 +458,47 @@ int __must_check devm_clk_bulk_get_all(struct device *dev, + */ + struct clk *devm_clk_get(struct device *dev, const char *id); + ++/** ++ * devm_clk_get_prepared - devm_clk_get() + clk_prepare() ++ * @dev: device for clock "consumer" ++ * @id: clock consumer ID ++ * ++ * Context: May sleep. ++ * ++ * Return: a struct clk corresponding to the clock producer, or ++ * valid IS_ERR() condition containing errno. The implementation ++ * uses @dev and @id to determine the clock consumer, and thereby ++ * the clock producer. (IOW, @id may be identical strings, but ++ * clk_get may return different clock producers depending on @dev.) ++ * ++ * The returned clk (if valid) is prepared. Drivers must however assume ++ * that the clock is not enabled. ++ * ++ * The clock will automatically be unprepared and freed when the device ++ * is unbound from the bus. ++ */ ++struct clk *devm_clk_get_prepared(struct device *dev, const char *id); ++ ++/** ++ * devm_clk_get_enabled - devm_clk_get() + clk_prepare_enable() ++ * @dev: device for clock "consumer" ++ * @id: clock consumer ID ++ * ++ * Context: May sleep. ++ * ++ * Return: a struct clk corresponding to the clock producer, or ++ * valid IS_ERR() condition containing errno. The implementation ++ * uses @dev and @id to determine the clock consumer, and thereby ++ * the clock producer. (IOW, @id may be identical strings, but ++ * clk_get may return different clock producers depending on @dev.) ++ * ++ * The returned clk (if valid) is prepared and enabled. ++ * ++ * The clock will automatically be disabled, unprepared and freed ++ * when the device is unbound from the bus. ++ */ ++struct clk *devm_clk_get_enabled(struct device *dev, const char *id); ++ + /** + * devm_clk_get_optional - lookup and obtain a managed reference to an optional + * clock producer. +@@ -469,6 +510,50 @@ struct clk *devm_clk_get(struct device *dev, const char *id); + */ + struct clk *devm_clk_get_optional(struct device *dev, const char *id); + ++/** ++ * devm_clk_get_optional_prepared - devm_clk_get_optional() + clk_prepare() ++ * @dev: device for clock "consumer" ++ * @id: clock consumer ID ++ * ++ * Context: May sleep. ++ * ++ * Return: a struct clk corresponding to the clock producer, or ++ * valid IS_ERR() condition containing errno. The implementation ++ * uses @dev and @id to determine the clock consumer, and thereby ++ * the clock producer. If no such clk is found, it returns NULL ++ * which serves as a dummy clk. That's the only difference compared ++ * to devm_clk_get_prepared(). ++ * ++ * The returned clk (if valid) is prepared. Drivers must however ++ * assume that the clock is not enabled. ++ * ++ * The clock will automatically be unprepared and freed when the ++ * device is unbound from the bus. ++ */ ++struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id); ++ ++/** ++ * devm_clk_get_optional_enabled - devm_clk_get_optional() + ++ * clk_prepare_enable() ++ * @dev: device for clock "consumer" ++ * @id: clock consumer ID ++ * ++ * Context: May sleep. ++ * ++ * Return: a struct clk corresponding to the clock producer, or ++ * valid IS_ERR() condition containing errno. The implementation ++ * uses @dev and @id to determine the clock consumer, and thereby ++ * the clock producer. If no such clk is found, it returns NULL ++ * which serves as a dummy clk. That's the only difference compared ++ * to devm_clk_get_enabled(). ++ * ++ * The returned clk (if valid) is prepared and enabled. ++ * ++ * The clock will automatically be disabled, unprepared and freed ++ * when the device is unbound from the bus. ++ */ ++struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id); ++ + /** + * devm_get_clk_from_child - lookup and obtain a managed reference to a + * clock producer from child node. +@@ -813,12 +898,36 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id) + return NULL; + } + ++static inline struct clk *devm_clk_get_prepared(struct device *dev, ++ const char *id) ++{ ++ return NULL; ++} ++ ++static inline struct clk *devm_clk_get_enabled(struct device *dev, ++ const char *id) ++{ ++ return NULL; ++} ++ + static inline struct clk *devm_clk_get_optional(struct device *dev, + const char *id) + { + return NULL; + } + ++static inline struct clk *devm_clk_get_optional_prepared(struct device *dev, ++ const char *id) ++{ ++ return NULL; ++} ++ ++static inline struct clk *devm_clk_get_optional_enabled(struct device *dev, ++ const char *id) ++{ ++ return NULL; ++} ++ + static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, + struct clk_bulk_data *clks) + { +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch b/queue-5.19/clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch new file mode 100644 index 00000000000..43ae9574efe --- /dev/null +++ b/queue-5.19/clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch @@ -0,0 +1,73 @@ +From 698a6b241ed60ebbc0192cfd0f33ebc4ea7efe04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 00:06:21 +0200 +Subject: clk: qcom: apss-ipq6018: fix apcs_alias0_clk_src + +From: Robert Marko + +[ Upstream commit 43a56cbf2a38170b02db29654607575b1b4b5bc0 ] + +While working on IPQ8074 APSS driver it was discovered that IPQ6018 and +IPQ8074 use almost the same PLL and APSS clocks, however APSS driver is +currently broken. + +More precisely apcs_alias0_clk_src is broken, it was added as regmap_mux +clock. +However after debugging why it was always stuck at 800Mhz, it was figured +out that its not regmap_mux compatible at all. +It is a simple mux but it uses RCG2 register layout and control bits, so +utilize the new clk_rcg2_mux_closest_ops to correctly drive it while not +having to provide a dummy frequency table. + +While we are here, use ARRAY_SIZE for number of parents. + +Tested on IPQ6018-CP01-C1 reference board and multiple IPQ8074 boards. + +Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller") +Signed-off-by: Robert Marko +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-2-robimarko@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/apss-ipq6018.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c +index d78ff2f310bf..be952d417ded 100644 +--- a/drivers/clk/qcom/apss-ipq6018.c ++++ b/drivers/clk/qcom/apss-ipq6018.c +@@ -16,7 +16,7 @@ + #include "clk-regmap.h" + #include "clk-branch.h" + #include "clk-alpha-pll.h" +-#include "clk-regmap-mux.h" ++#include "clk-rcg.h" + + enum { + P_XO, +@@ -33,16 +33,15 @@ static const struct parent_map parents_apcs_alias0_clk_src_map[] = { + { P_APSS_PLL_EARLY, 5 }, + }; + +-static struct clk_regmap_mux apcs_alias0_clk_src = { +- .reg = 0x0050, +- .width = 3, +- .shift = 7, ++static struct clk_rcg2 apcs_alias0_clk_src = { ++ .cmd_rcgr = 0x0050, ++ .hid_width = 5, + .parent_map = parents_apcs_alias0_clk_src_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "apcs_alias0_clk_src", + .parent_data = parents_apcs_alias0_clk_src, +- .num_parents = 2, +- .ops = &clk_regmap_mux_closest_ops, ++ .num_parents = ARRAY_SIZE(parents_apcs_alias0_clk_src), ++ .ops = &clk_rcg2_mux_closest_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }; +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-apss-ipq6018-mark-apcs_alias0_core_clk-as-c.patch b/queue-5.19/clk-qcom-apss-ipq6018-mark-apcs_alias0_core_clk-as-c.patch new file mode 100644 index 00000000000..8ea952a5ac4 --- /dev/null +++ b/queue-5.19/clk-qcom-apss-ipq6018-mark-apcs_alias0_core_clk-as-c.patch @@ -0,0 +1,42 @@ +From 91638dd7029b48b37cc9d7117541eb75dd6892c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 00:06:22 +0200 +Subject: clk: qcom: apss-ipq6018: mark apcs_alias0_core_clk as critical + +From: Robert Marko + +[ Upstream commit 86e78995c93ee182433f965babfccd48417d4dcf ] + +While fixing up the driver I noticed that my IPQ8074 board was hanging +after CPUFreq switched the frequency during boot, WDT would eventually +reset it. + +So mark apcs_alias0_core_clk as critical since its the clock feeding the +CPU cluster and must never be disabled. + +Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller") +Signed-off-by: Robert Marko +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-3-robimarko@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/apss-ipq6018.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c +index be952d417ded..f2f502e2d5a4 100644 +--- a/drivers/clk/qcom/apss-ipq6018.c ++++ b/drivers/clk/qcom/apss-ipq6018.c +@@ -56,7 +56,7 @@ static struct clk_branch apcs_alias0_core_clk = { + .parent_hws = (const struct clk_hw *[]){ + &apcs_alias0_clk_src.clkr.hw }, + .num_parents = 1, +- .flags = CLK_SET_RATE_PARENT, ++ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch b/queue-5.19/clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch new file mode 100644 index 00000000000..b2af5db0b31 --- /dev/null +++ b/queue-5.19/clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch @@ -0,0 +1,64 @@ +From a907b2b91eacbccb605c9a6286e9b128b70f814e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 00:06:20 +0200 +Subject: clk: qcom: clk-rcg2: add rcg2 mux ops + +From: Christian Marangi + +[ Upstream commit c5d2c96b3a7bd8987fad9957510034130037fccf ] + +An RCG may act as a mux that switch between 2 parents. +This is the case on IPQ6018 and IPQ8074 where the APCS core clk that feeds +the CPU cluster clock just switches between XO and the PLL that feeds it. + +Add the required ops to add support for this special configuration and use +the generic mux function to determine the rate. + +This way we dont have to keep a essentially dummy frequency table to use +RCG2 as a mux. + +Signed-off-by: Christian Marangi +Signed-off-by: Robert Marko +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220818220628.339366-1-robimarko@gmail.com +Stable-dep-of: 43a56cbf2a38 ("clk: qcom: apss-ipq6018: fix apcs_alias0_clk_src") +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/clk-rcg.h | 1 + + drivers/clk/qcom/clk-rcg2.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h +index 012e745794fd..01581f4d2c39 100644 +--- a/drivers/clk/qcom/clk-rcg.h ++++ b/drivers/clk/qcom/clk-rcg.h +@@ -167,6 +167,7 @@ struct clk_rcg2_gfx3d { + + extern const struct clk_ops clk_rcg2_ops; + extern const struct clk_ops clk_rcg2_floor_ops; ++extern const struct clk_ops clk_rcg2_mux_closest_ops; + extern const struct clk_ops clk_edp_pixel_ops; + extern const struct clk_ops clk_byte_ops; + extern const struct clk_ops clk_byte2_ops; +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index 28019edd2a50..609c10f8d0d9 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -509,6 +509,13 @@ const struct clk_ops clk_rcg2_floor_ops = { + }; + EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); + ++const struct clk_ops clk_rcg2_mux_closest_ops = { ++ .determine_rate = __clk_mux_determine_rate_closest, ++ .get_parent = clk_rcg2_get_parent, ++ .set_parent = clk_rcg2_set_parent, ++}; ++EXPORT_SYMBOL_GPL(clk_rcg2_mux_closest_ops); ++ + struct frac_entry { + int num; + int den; +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-gcc-sdm660-use-floor-ops-for-sdcc1-clock.patch b/queue-5.19/clk-qcom-gcc-sdm660-use-floor-ops-for-sdcc1-clock.patch new file mode 100644 index 00000000000..13ea7640a7c --- /dev/null +++ b/queue-5.19/clk-qcom-gcc-sdm660-use-floor-ops-for-sdcc1-clock.patch @@ -0,0 +1,46 @@ +From 31a6a5b354199b65fd908efa4a559836d81d7e6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 22:38:22 +0200 +Subject: clk: qcom: gcc-sdm660: Use floor ops for SDCC1 clock + +From: Marijn Suijten + +[ Upstream commit 6956c18f4ad9200aa945f7ea37d65a05afc49d51 ] + +In commit 3f905469c8ce ("clk: qcom: gcc: Use floor ops for SDCC clocks") +floor ops were applied to SDCC2 only, but flooring is also required on +the SDCC1 apps clock which is used by the eMMC card on Sony's Nile +platform, and otherwise result in the typicial "Card appears +overclocked" warnings observed on many other platforms before: + + mmc0: Card appears overclocked; req 52000000 Hz, actual 100000000 Hz + mmc0: Card appears overclocked; req 52000000 Hz, actual 100000000 Hz + mmc0: Card appears overclocked; req 104000000 Hz, actual 192000000 Hz + +Fixes: f2a76a2955c0 ("clk: qcom: Add Global Clock controller (GCC) driver for SDM660") +Signed-off-by: Marijn Suijten +Tested-by: Alexey Minnekhanov +Reviewed-by: Stephen Boyd +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220714203822.186448-1-marijn.suijten@somainline.org +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-sdm660.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c +index 9b97425008ce..db918c92a522 100644 +--- a/drivers/clk/qcom/gcc-sdm660.c ++++ b/drivers/clk/qcom/gcc-sdm660.c +@@ -757,7 +757,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { + .name = "sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_xo_gpll0_gpll4_gpll0_early_div, + .num_parents = ARRAY_SIZE(gcc_parent_data_xo_gpll0_gpll4_gpll0_early_div), +- .ops = &clk_rcg2_ops, ++ .ops = &clk_rcg2_floor_ops, + }, + }; + +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-gcc-sm6115-override-default-alpha-pll-regs.patch b/queue-5.19/clk-qcom-gcc-sm6115-override-default-alpha-pll-regs.patch new file mode 100644 index 00000000000..10fb1eaa263 --- /dev/null +++ b/queue-5.19/clk-qcom-gcc-sm6115-override-default-alpha-pll-regs.patch @@ -0,0 +1,193 @@ +From d46ec4e68d46ef0927bc646fbe74017ba73f7477 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 10:56:18 +0300 +Subject: clk: qcom: gcc-sm6115: Override default Alpha PLL regs + +From: Adam Skladowski + +[ Upstream commit 068a0605ef5a6b430e7278c169bfcd25b680b28f ] + +The DEFAULT and BRAMMO PLL offsets are non-standard in downstream, but +currently only BRAMMO ones are overridden. Override DEFAULT ones too. + +A very similar thing is happening in gcc-qcm2290 driver. + +Fixes: cbe63bfdc54f ("clk: qcom: Add Global Clock controller (GCC) driver for SM6115") +Signed-off-by: Adam Skladowski +Signed-off-by: Iskren Chernev +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220830075620.974009-2-iskren.chernev@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/gcc-sm6115.c | 46 +++++++++++++++++++++++------------ + 1 file changed, 30 insertions(+), 16 deletions(-) + +diff --git a/drivers/clk/qcom/gcc-sm6115.c b/drivers/clk/qcom/gcc-sm6115.c +index 68fe9f6f0d2f..e24a977c2580 100644 +--- a/drivers/clk/qcom/gcc-sm6115.c ++++ b/drivers/clk/qcom/gcc-sm6115.c +@@ -53,11 +53,25 @@ static struct pll_vco gpll10_vco[] = { + { 750000000, 1500000000, 1 }, + }; + ++static const u8 clk_alpha_pll_regs_offset[][PLL_OFF_MAX_REGS] = { ++ [CLK_ALPHA_PLL_TYPE_DEFAULT] = { ++ [PLL_OFF_L_VAL] = 0x04, ++ [PLL_OFF_ALPHA_VAL] = 0x08, ++ [PLL_OFF_ALPHA_VAL_U] = 0x0c, ++ [PLL_OFF_TEST_CTL] = 0x10, ++ [PLL_OFF_TEST_CTL_U] = 0x14, ++ [PLL_OFF_USER_CTL] = 0x18, ++ [PLL_OFF_USER_CTL_U] = 0x1c, ++ [PLL_OFF_CONFIG_CTL] = 0x20, ++ [PLL_OFF_STATUS] = 0x24, ++ }, ++}; ++ + static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(0), +@@ -83,7 +97,7 @@ static struct clk_alpha_pll_postdiv gpll0_out_aux2 = { + .post_div_table = post_div_table_gpll0_out_aux2, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_aux2), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_aux2", + .parent_hws = (const struct clk_hw *[]){ &gpll0.clkr.hw }, +@@ -115,7 +129,7 @@ static struct clk_alpha_pll_postdiv gpll0_out_main = { + .post_div_table = post_div_table_gpll0_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll0.clkr.hw }, +@@ -137,7 +151,7 @@ static struct clk_alpha_pll gpll10 = { + .offset = 0xa000, + .vco_table = gpll10_vco, + .num_vco = ARRAY_SIZE(gpll10_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(10), +@@ -163,7 +177,7 @@ static struct clk_alpha_pll_postdiv gpll10_out_main = { + .post_div_table = post_div_table_gpll10_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll10_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll10_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll10.clkr.hw }, +@@ -189,7 +203,7 @@ static struct clk_alpha_pll gpll11 = { + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), + .flags = SUPPORTS_DYNAMIC_UPDATE, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(11), +@@ -215,7 +229,7 @@ static struct clk_alpha_pll_postdiv gpll11_out_main = { + .post_div_table = post_div_table_gpll11_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll11_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll11_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll11.clkr.hw }, +@@ -229,7 +243,7 @@ static struct clk_alpha_pll gpll3 = { + .offset = 0x3000, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(3), +@@ -248,7 +262,7 @@ static struct clk_alpha_pll gpll4 = { + .offset = 0x4000, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(4), +@@ -274,7 +288,7 @@ static struct clk_alpha_pll_postdiv gpll4_out_main = { + .post_div_table = post_div_table_gpll4_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll4_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll4_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll4.clkr.hw }, +@@ -287,7 +301,7 @@ static struct clk_alpha_pll gpll6 = { + .offset = 0x6000, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(6), +@@ -313,7 +327,7 @@ static struct clk_alpha_pll_postdiv gpll6_out_main = { + .post_div_table = post_div_table_gpll6_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll6_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll6_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll6.clkr.hw }, +@@ -326,7 +340,7 @@ static struct clk_alpha_pll gpll7 = { + .offset = 0x7000, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(7), +@@ -352,7 +366,7 @@ static struct clk_alpha_pll_postdiv gpll7_out_main = { + .post_div_table = post_div_table_gpll7_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll7_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll7_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll7.clkr.hw }, +@@ -380,7 +394,7 @@ static struct clk_alpha_pll gpll8 = { + .offset = 0x8000, + .vco_table = default_vco, + .num_vco = ARRAY_SIZE(default_vco), +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .enable_reg = 0x79000, +@@ -407,7 +421,7 @@ static struct clk_alpha_pll_postdiv gpll8_out_main = { + .post_div_table = post_div_table_gpll8_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_gpll8_out_main), + .width = 4, +- .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], ++ .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll8_out_main", + .parent_hws = (const struct clk_hw *[]){ &gpll8.clkr.hw }, +-- +2.35.1 + diff --git a/queue-5.19/clk-qcom-sm6115-select-qcom_gdsc.patch b/queue-5.19/clk-qcom-sm6115-select-qcom_gdsc.patch new file mode 100644 index 00000000000..c1e8bd86a1c --- /dev/null +++ b/queue-5.19/clk-qcom-sm6115-select-qcom_gdsc.patch @@ -0,0 +1,42 @@ +From 4afbe4c67094a3d371ad2fb32ae5bb8c4f593489 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Sep 2022 00:02:07 +0700 +Subject: clk: qcom: sm6115: Select QCOM_GDSC + +From: Dang Huynh + +[ Upstream commit 50ee65dc512b9b5c4de354cf3b4dded34f46c571 ] + +While working on the Fxtec Pro1X device, this error shows up with +my own minimal configuration: + +gcc-sm6115: probe of 1400000.clock-controller failed with error -38 + +The clock driver depends on CONFIG_QCOM_GDSC and after enabling +that, the driver probes successfully. + +Signed-off-by: Dang Huynh +Fixes: cbe63bfdc54f ("clk: qcom: Add Global Clock controller (GCC) +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220910170207.1592220-1-danct12@riseup.net +Signed-off-by: Sasha Levin +--- + drivers/clk/qcom/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig +index bc4dcf356d82..b1b141abc01c 100644 +--- a/drivers/clk/qcom/Kconfig ++++ b/drivers/clk/qcom/Kconfig +@@ -637,6 +637,7 @@ config SM_DISPCC_6350 + + config SM_GCC_6115 + tristate "SM6115 and SM4250 Global Clock Controller" ++ select QCOM_GDSC + help + Support for the global clock controller on SM6115 and SM4250 devices. + Say Y if you want to use peripheral devices such as UART, SPI, +-- +2.35.1 + diff --git a/queue-5.19/clk-qoriq-hold-reference-returned-by-of_get_parent.patch b/queue-5.19/clk-qoriq-hold-reference-returned-by-of_get_parent.patch new file mode 100644 index 00000000000..927a166566d --- /dev/null +++ b/queue-5.19/clk-qoriq-hold-reference-returned-by-of_get_parent.patch @@ -0,0 +1,56 @@ +From ec9e35105188d1c5f68ce8926d926a4b14021905 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 22:38:51 +0800 +Subject: clk: qoriq: Hold reference returned by of_get_parent() + +From: Liang He + +[ Upstream commit a8ea4273bc26256ce3cce83164f0f51c5bf6e127 ] + +In legacy_init_clockgen(), we need to hold the reference returned +by of_get_parent() and use it to call of_node_put() for refcount +balance. + +Beside, in create_sysclk(), we need to call of_node_put() on 'sysclk' +also for refcount balance. + +Fixes: 0dfc86b3173f ("clk: qoriq: Move chip-specific knowledge into driver") +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220628143851.171299-1-windhl@126.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-qoriq.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c +index 88898b97a443..5eddb9f0d6bd 100644 +--- a/drivers/clk/clk-qoriq.c ++++ b/drivers/clk/clk-qoriq.c +@@ -1063,8 +1063,13 @@ static void __init _clockgen_init(struct device_node *np, bool legacy); + */ + static void __init legacy_init_clockgen(struct device_node *np) + { +- if (!clockgen.node) +- _clockgen_init(of_get_parent(np), true); ++ if (!clockgen.node) { ++ struct device_node *parent_np; ++ ++ parent_np = of_get_parent(np); ++ _clockgen_init(parent_np, true); ++ of_node_put(parent_np); ++ } + } + + /* Legacy node */ +@@ -1159,6 +1164,7 @@ static struct clk * __init create_sysclk(const char *name) + sysclk = of_get_child_by_name(clockgen.node, "sysclk"); + if (sysclk) { + clk = sysclk_from_fixed(sysclk, name); ++ of_node_put(sysclk); + if (!IS_ERR(clk)) + return clk; + } +-- +2.35.1 + diff --git a/queue-5.19/clk-samsung-exynosautov9-correct-register-offsets-of.patch b/queue-5.19/clk-samsung-exynosautov9-correct-register-offsets-of.patch new file mode 100644 index 00000000000..7271884234b --- /dev/null +++ b/queue-5.19/clk-samsung-exynosautov9-correct-register-offsets-of.patch @@ -0,0 +1,76 @@ +From 265980eeffac643e19fc7d09cd12eebbed68c63f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 11:13:57 +0900 +Subject: clk: samsung: exynosautov9: correct register offsets of peric0/c1 + +From: Chanho Park + +[ Upstream commit 67d98943408bce835185688cb75ebbb45b91e572 ] + +Some register offsets of peric0 and peric1 cmu blocks need to be +corrected and re-ordered by numerical order. + +Fixes: f2dd366992d0 ("clk: samsung: exynosautov9: add cmu_peric0 clock support") +Fixes: b35f27fe73d8 ("clk: samsung: exynosautov9: add cmu_peric1 clock support") +Signed-off-by: Chanho Park +Reviewed-by: Krzysztof Kozlowski +Acked-by: Chanwoo Choi +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220727021357.152421-4-chanho61.park@samsung.com +Signed-off-by: Sasha Levin +--- + drivers/clk/samsung/clk-exynosautov9.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c +index d9e1f8e4a7b4..487a71b32a00 100644 +--- a/drivers/clk/samsung/clk-exynosautov9.c ++++ b/drivers/clk/samsung/clk-exynosautov9.c +@@ -1170,9 +1170,9 @@ static const struct samsung_cmu_info fsys2_cmu_info __initconst = { + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_2 0x2058 + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_3 0x205c + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_4 0x2060 +-#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_7 0x206c + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_5 0x2064 + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_6 0x2068 ++#define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_7 0x206c + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_8 0x2070 + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_9 0x2074 + #define CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_PCLK_10 0x204c +@@ -1418,14 +1418,14 @@ static const struct samsung_cmu_info peric0_cmu_info __initconst = { + #define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_11 0x2020 + #define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_0 0x2044 + #define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_1 0x2048 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2 0x2058 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3 0x205c +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4 0x2060 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7 0x206c +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5 0x2064 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6 0x2068 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8 0x2070 +-#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9 0x2074 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2 0x2054 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3 0x2058 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4 0x205c ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5 0x2060 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6 0x2064 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7 0x2068 ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8 0x206c ++#define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9 0x2070 + #define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_10 0x204c + #define CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_11 0x2050 + +@@ -1463,9 +1463,9 @@ static const unsigned long peric1_clk_regs[] __initconst = { + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_2, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_3, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_4, +- CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_5, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_6, ++ CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_7, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_8, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_9, + CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_PCLK_10, +-- +2.35.1 + diff --git a/queue-5.19/clk-sprd-hold-reference-returned-by-of_get_parent.patch b/queue-5.19/clk-sprd-hold-reference-returned-by-of_get_parent.patch new file mode 100644 index 00000000000..3b2a1da6a6c --- /dev/null +++ b/queue-5.19/clk-sprd-hold-reference-returned-by-of_get_parent.patch @@ -0,0 +1,52 @@ +From c8cf8ccc9c0bc71707e466b16fbc05ee01d12b3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 08:47:29 +0800 +Subject: clk: sprd: Hold reference returned by of_get_parent() + +From: Liang He + +[ Upstream commit 91e6455bf715fb1558a0bf8f645ec1c131254a3c ] + +We should hold the reference returned by of_get_parent() and use it +to call of_node_put() for refcount balance. + +Fixes: f95e8c7923d1 ("clk: sprd: support to get regmap from parent node") +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220704004729.272481-1-windhl@126.com +Reviewed-by: Orson Zhai +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/sprd/common.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c +index d620bbbcdfc8..ce81e4087a8f 100644 +--- a/drivers/clk/sprd/common.c ++++ b/drivers/clk/sprd/common.c +@@ -41,7 +41,7 @@ int sprd_clk_regmap_init(struct platform_device *pdev, + { + void __iomem *base; + struct device *dev = &pdev->dev; +- struct device_node *node = dev->of_node; ++ struct device_node *node = dev->of_node, *np; + struct regmap *regmap; + + if (of_find_property(node, "sprd,syscon", NULL)) { +@@ -50,9 +50,10 @@ int sprd_clk_regmap_init(struct platform_device *pdev, + pr_err("%s: failed to get syscon regmap\n", __func__); + return PTR_ERR(regmap); + } +- } else if (of_device_is_compatible(of_get_parent(dev->of_node), +- "syscon")) { +- regmap = device_node_to_regmap(of_get_parent(dev->of_node)); ++ } else if (of_device_is_compatible(np = of_get_parent(node), "syscon") || ++ (of_node_put(np), 0)) { ++ regmap = device_node_to_regmap(np); ++ of_node_put(np); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to get regmap from its parent.\n"); + return PTR_ERR(regmap); +-- +2.35.1 + diff --git a/queue-5.19/clk-st-hold-reference-returned-by-of_get_parent.patch b/queue-5.19/clk-st-hold-reference-returned-by-of_get_parent.patch new file mode 100644 index 00000000000..5d2bd5cc458 --- /dev/null +++ b/queue-5.19/clk-st-hold-reference-returned-by-of_get_parent.patch @@ -0,0 +1,73 @@ +From b9a37b0f2d0c3f9ce6616a44fad4c43eb5afc1dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Jun 2022 22:24:15 +0800 +Subject: clk: st: Hold reference returned by of_get_parent() + +From: Liang He + +[ Upstream commit 429973306f860470cbbb8402c8c53143b450faba ] + +We should hold the reference returned by of_get_parent() and use it +to call of_node_put() for refcount balance. + +Fixes: 3efe64ef5186 ("clk: st: clkgen-fsyn: search reg within node or parent") +Fixes: 810251b0d36a ("clk: st: clkgen-mux: search reg within node or parent") + +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220628142416.169808-1-windhl@126.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/st/clkgen-fsyn.c | 5 ++++- + drivers/clk/st/clkgen-mux.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c +index 582a22c04919..d820292a381d 100644 +--- a/drivers/clk/st/clkgen-fsyn.c ++++ b/drivers/clk/st/clkgen-fsyn.c +@@ -987,6 +987,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, + const char *pll_name, *clk_parent_name; + void __iomem *reg; + spinlock_t *lock; ++ struct device_node *parent_np; + + /* + * First check for reg property within the node to keep backward +@@ -994,7 +995,9 @@ static void __init st_of_quadfs_setup(struct device_node *np, + */ + reg = of_iomap(np, 0); + if (!reg) { +- reg = of_iomap(of_get_parent(np), 0); ++ parent_np = of_get_parent(np); ++ reg = of_iomap(parent_np, 0); ++ of_node_put(parent_np); + if (!reg) { + pr_err("%s: Failed to get base address\n", __func__); + return; +diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c +index ee39af7a0b72..596e939ad905 100644 +--- a/drivers/clk/st/clkgen-mux.c ++++ b/drivers/clk/st/clkgen-mux.c +@@ -56,6 +56,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np, + void __iomem *reg; + const char **parents; + int num_parents = 0; ++ struct device_node *parent_np; + + /* + * First check for reg property within the node to keep backward +@@ -63,7 +64,9 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np, + */ + reg = of_iomap(np, 0); + if (!reg) { +- reg = of_iomap(of_get_parent(np), 0); ++ parent_np = of_get_parent(np); ++ reg = of_iomap(parent_np, 0); ++ of_node_put(parent_np); + if (!reg) { + pr_err("%s: Failed to get base address\n", __func__); + return; +-- +2.35.1 + diff --git a/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch b/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch new file mode 100644 index 00000000000..cdb8a92ce46 --- /dev/null +++ b/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch @@ -0,0 +1,37 @@ +From c6501d668bb733b8bef07f6273947e80d037bc91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 May 2022 18:38:34 +0400 +Subject: clk: tegra: Fix refcount leak in tegra114_clock_init + +From: Miaoqian Lin + +[ Upstream commit db16a80c76ea395766913082b1e3f939dde29b2c ] + +of_find_matching_node() returns a node pointer with refcount +incremented, we should use of_node_put() on it when not need anymore. +Add missing of_node_put() to avoid refcount leak. + +Fixes: 2cb5efefd6f7 ("clk: tegra: Implement clocks for Tegra114") +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20220523143834.7587-1-linmq006@gmail.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/tegra/clk-tegra114.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c +index ef718c4b3826..f7405a58877e 100644 +--- a/drivers/clk/tegra/clk-tegra114.c ++++ b/drivers/clk/tegra/clk-tegra114.c +@@ -1317,6 +1317,7 @@ static void __init tegra114_clock_init(struct device_node *np) + } + + pmc_base = of_iomap(node, 0); ++ of_node_put(node); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + WARN_ON(1); +-- +2.35.1 + diff --git a/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch b/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch new file mode 100644 index 00000000000..742d89786de --- /dev/null +++ b/queue-5.19/clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch @@ -0,0 +1,37 @@ +From 60407b80ac8f296377f8e3269a9195417c1a5710 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 May 2022 18:26:08 +0400 +Subject: clk: tegra: Fix refcount leak in tegra210_clock_init + +From: Miaoqian Lin + +[ Upstream commit 56c78cb1f00a9dde8cd762131ce8f4c5eb046fbb ] + +of_find_matching_node() returns a node pointer with refcount +incremented, we should use of_node_put() on it when not need anymore. +Add missing of_node_put() to avoid refcount leak. + +Fixes: 6b301a059eb2 ("clk: tegra: Add support for Tegra210 clocks") +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20220523142608.65074-1-linmq006@gmail.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/tegra/clk-tegra210.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c +index b9099012dc7b..499f999e91e1 100644 +--- a/drivers/clk/tegra/clk-tegra210.c ++++ b/drivers/clk/tegra/clk-tegra210.c +@@ -3748,6 +3748,7 @@ static void __init tegra210_clock_init(struct device_node *np) + } + + pmc_base = of_iomap(node, 0); ++ of_node_put(node); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + WARN_ON(1); +-- +2.35.1 + diff --git a/queue-5.19/clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch b/queue-5.19/clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch new file mode 100644 index 00000000000..8a5e9adc48e --- /dev/null +++ b/queue-5.19/clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch @@ -0,0 +1,37 @@ +From 3f0db71a641d7f8e171c855fa49dd427eee14a37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 May 2022 19:28:11 +0400 +Subject: clk: tegra20: Fix refcount leak in tegra20_clock_init + +From: Miaoqian Lin + +[ Upstream commit 4e343bafe03ff68a62f48f8235cf98f2c685468b ] + +of_find_matching_node() returns a node pointer with refcount +incremented, we should use of_node_put() on it when not need anymore. +Add missing of_node_put() to avoid refcount leak. + +Fixes: 37c26a906527 ("clk: tegra: add clock support for Tegra20") +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20220523152811.19692-1-linmq006@gmail.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/tegra/clk-tegra20.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c +index be3c33441cfc..8a4514f6d503 100644 +--- a/drivers/clk/tegra/clk-tegra20.c ++++ b/drivers/clk/tegra/clk-tegra20.c +@@ -1131,6 +1131,7 @@ static void __init tegra20_clock_init(struct device_node *np) + } + + pmc_base = of_iomap(node, 0); ++ of_node_put(node); + if (!pmc_base) { + pr_err("Can't map pmc registers\n"); + BUG(); +-- +2.35.1 + diff --git a/queue-5.19/clk-ti-balance-of_node_get-calls-for-of_find_node_by.patch b/queue-5.19/clk-ti-balance-of_node_get-calls-for-of_find_node_by.patch new file mode 100644 index 00000000000..985e2edaf83 --- /dev/null +++ b/queue-5.19/clk-ti-balance-of_node_get-calls-for-of_find_node_by.patch @@ -0,0 +1,48 @@ +From dd8153b60ee372499faaee39431e8890769f0d0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 11:11:21 +0800 +Subject: clk: ti: Balance of_node_get() calls for of_find_node_by_name() + +From: Liang He + +[ Upstream commit 058a3996b888ab60eb1857fb4fd28f1b89a9a95a ] + +In ti_find_clock_provider(), of_find_node_by_name() will call +of_node_put() for the 'from' argument, possibly putting the node one too +many times. Let's maintain the of_node_get() from the previous search +and only put when we're exiting the function early. This should avoid a +misbalanced reference count on the node. + +Fixes: 51f661ef9a10 ("clk: ti: Add ti_find_clock_provider() to use clock-output-names") +Signed-off-by: Liang He +Link: https://lore.kernel.org/r/20220915031121.4003589-1-windhl@126.com +[sboyd@kernel.org: Rewrite commit text, maintain reference instead of +get again] +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/ti/clk.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c +index 121d8610beb1..6b2de32ef88d 100644 +--- a/drivers/clk/ti/clk.c ++++ b/drivers/clk/ti/clk.c +@@ -148,11 +148,12 @@ static struct device_node *ti_find_clock_provider(struct device_node *from, + break; + } + } +- of_node_put(from); + kfree(tmp); + +- if (found) ++ if (found) { ++ of_node_put(from); + return np; ++ } + + /* Fall back to using old node name base provider name */ + return of_find_node_by_name(from, name); +-- +2.35.1 + diff --git a/queue-5.19/clk-ti-dra7-atl-fix-reference-leak-in-of_dra7_atl_cl.patch b/queue-5.19/clk-ti-dra7-atl-fix-reference-leak-in-of_dra7_atl_cl.patch new file mode 100644 index 00000000000..bc198682f66 --- /dev/null +++ b/queue-5.19/clk-ti-dra7-atl-fix-reference-leak-in-of_dra7_atl_cl.patch @@ -0,0 +1,60 @@ +From 652fccd88d06921060e42f641115b3558b5486b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 2 Jun 2022 07:08:36 +0400 +Subject: clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe + +From: Miaoqian Lin + +[ Upstream commit 9c59a01caba26ec06fefd6ca1f22d5fd1de57d63 ] + +pm_runtime_get_sync() will increment pm usage counter. +Forgetting to putting operation will result in reference leak. +Add missing pm_runtime_put_sync in some error paths. + +Fixes: 9ac33b0ce81f ("CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic)") +Signed-off-by: Miaoqian Lin +Link: https://lore.kernel.org/r/20220602030838.52057-1-linmq006@gmail.com +Reviewed-by: Tony Lindgren +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/ti/clk-dra7-atl.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c +index aa0950c4f498..5c278d6c985e 100644 +--- a/drivers/clk/ti/clk-dra7-atl.c ++++ b/drivers/clk/ti/clk-dra7-atl.c +@@ -253,14 +253,16 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) + if (rc) { + pr_err("%s: failed to lookup atl clock %d\n", __func__, + i); +- return -EINVAL; ++ ret = -EINVAL; ++ goto pm_put; + } + + clk = of_clk_get_from_provider(&clkspec); + if (IS_ERR(clk)) { + pr_err("%s: failed to get atl clock %d from provider\n", + __func__, i); +- return PTR_ERR(clk); ++ ret = PTR_ERR(clk); ++ goto pm_put; + } + + cdesc = to_atl_desc(__clk_get_hw(clk)); +@@ -293,8 +295,9 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) + if (cdesc->enabled) + atl_clk_enable(__clk_get_hw(clk)); + } +- pm_runtime_put_sync(cinfo->dev); + ++pm_put: ++ pm_runtime_put_sync(cinfo->dev); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.19/clk-vc5-fix-5p49v6901-outputs-disabling-when-enablin.patch b/queue-5.19/clk-vc5-fix-5p49v6901-outputs-disabling-when-enablin.patch new file mode 100644 index 00000000000..5b62e861b84 --- /dev/null +++ b/queue-5.19/clk-vc5-fix-5p49v6901-outputs-disabling-when-enablin.patch @@ -0,0 +1,55 @@ +From adbbdfb4003a47a11fe4ad563e52fa85aeabf8f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 01:53:55 +0300 +Subject: clk: vc5: Fix 5P49V6901 outputs disabling when enabling FOD + +From: Serge Semin + +[ Upstream commit c388cc804016cf0f65afdc2362b120aa594ff3e6 ] + +We have discovered random glitches during the system boot up procedure. +The problem investigation led us to the weird outcomes: when none of the +Renesas 5P49V6901 ports are explicitly enabled by the kernel driver, the +glitches disappeared. It was a mystery since the SoC external clock +domains were fed with different 5P49V6901 outputs. The driver code didn't +seem like bogus either. We almost despaired to find out a root cause when +the solution has been found for a more modern revision of the chip. It +turned out the 5P49V6901 clock generator stopped its output for a short +period of time during the VC5_OUT_DIV_CONTROL register writing. The same +problem was found for the 5P49V6965 revision of the chip and was +successfully fixed in commit fc336ae622df ("clk: vc5: fix output disabling +when enabling a FOD") by enabling the "bypass_sync" flag hidden inside +"Unused Factory Reserved Register". Even though the 5P49V6901 registers +description and programming guide doesn't provide any intel regarding that +flag, setting it up anyway in the officially unused register completely +eliminated the denoted glitches. Thus let's activate the functionality +submitted in commit fc336ae622df ("clk: vc5: fix output disabling when +enabling a FOD") for the Renesas 5P49V6901 chip too in order to remove the +ports implicit inter-dependency. + +Fixes: dbf6b16f5683 ("clk: vc5: Add support for IDT VersaClock 5P49V6901") +Signed-off-by: Serge Semin +Reviewed-by: Luca Ceresoli +Link: https://lore.kernel.org/r/20220929225402.9696-2-Sergey.Semin@baikalelectronics.ru +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/clk-versaclock5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c +index e7be3e54b9be..03cfef494b49 100644 +--- a/drivers/clk/clk-versaclock5.c ++++ b/drivers/clk/clk-versaclock5.c +@@ -1204,7 +1204,7 @@ static const struct vc5_chip_info idt_5p49v6901_info = { + .model = IDT_VC6_5P49V6901, + .clk_fod_cnt = 4, + .clk_out_cnt = 5, +- .flags = VC5_HAS_PFD_FREQ_DBL, ++ .flags = VC5_HAS_PFD_FREQ_DBL | VC5_HAS_BYPASS_SYNC_BIT, + }; + + static const struct vc5_chip_info idt_5p49v6965_info = { +-- +2.35.1 + diff --git a/queue-5.19/clk-zynqmp-fix-stack-out-of-bounds-in-strncpy.patch b/queue-5.19/clk-zynqmp-fix-stack-out-of-bounds-in-strncpy.patch new file mode 100644 index 00000000000..78e363e2fcd --- /dev/null +++ b/queue-5.19/clk-zynqmp-fix-stack-out-of-bounds-in-strncpy.patch @@ -0,0 +1,118 @@ +From c9dee5eb569ac05f800a4a2f0574aeb4e070be5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 May 2022 12:31:54 +0530 +Subject: clk: zynqmp: Fix stack-out-of-bounds in strncpy` + +From: Ian Nam + +[ Upstream commit dd80fb2dbf1cd8751efbe4e53e54056f56a9b115 ] + +"BUG: KASAN: stack-out-of-bounds in strncpy+0x30/0x68" + +Linux-ATF interface is using 16 bytes of SMC payload. In case clock name is +longer than 15 bytes, string terminated NULL character will not be received +by Linux. Add explicit NULL character at last byte to fix issues when clock +name is longer. + +This fixes below bug reported by KASAN: + + ================================================================== + BUG: KASAN: stack-out-of-bounds in strncpy+0x30/0x68 + Read of size 1 at addr ffff0008c89a7410 by task swapper/0/1 + + CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.4.0-00396-g81ef9e7-dirty #3 + Hardware name: Xilinx Versal vck190 Eval board revA (QSPI) (DT) + Call trace: + dump_backtrace+0x0/0x1e8 + show_stack+0x14/0x20 + dump_stack+0xd4/0x108 + print_address_description.isra.0+0xbc/0x37c + __kasan_report+0x144/0x198 + kasan_report+0xc/0x18 + __asan_load1+0x5c/0x68 + strncpy+0x30/0x68 + zynqmp_clock_probe+0x238/0x7b8 + platform_drv_probe+0x6c/0xc8 + really_probe+0x14c/0x418 + driver_probe_device+0x74/0x130 + __device_attach_driver+0xc4/0xe8 + bus_for_each_drv+0xec/0x150 + __device_attach+0x160/0x1d8 + device_initial_probe+0x10/0x18 + bus_probe_device+0xe0/0xf0 + device_add+0x528/0x950 + of_device_add+0x5c/0x80 + of_platform_device_create_pdata+0x120/0x168 + of_platform_bus_create+0x244/0x4e0 + of_platform_populate+0x50/0xe8 + zynqmp_firmware_probe+0x370/0x3a8 + platform_drv_probe+0x6c/0xc8 + really_probe+0x14c/0x418 + driver_probe_device+0x74/0x130 + device_driver_attach+0x94/0xa0 + __driver_attach+0x70/0x108 + bus_for_each_dev+0xe4/0x158 + driver_attach+0x30/0x40 + bus_add_driver+0x21c/0x2b8 + driver_register+0xbc/0x1d0 + __platform_driver_register+0x7c/0x88 + zynqmp_firmware_driver_init+0x1c/0x24 + do_one_initcall+0xa4/0x234 + kernel_init_freeable+0x1b0/0x24c + kernel_init+0x10/0x110 + ret_from_fork+0x10/0x18 + + The buggy address belongs to the page: + page:ffff0008f9be1c88 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 + raw: 0008d00000000000 ffff0008f9be1c90 ffff0008f9be1c90 0000000000000000 + raw: 0000000000000000 0000000000000000 00000000ffffffff + page dumped because: kasan: bad access detected + + addr ffff0008c89a7410 is located in stack of task swapper/0/1 at offset 112 in frame: + zynqmp_clock_probe+0x0/0x7b8 + + this frame has 3 objects: + [32, 44) 'response' + [64, 80) 'ret_payload' + [96, 112) 'name' + + Memory state around the buggy address: + ffff0008c89a7300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff0008c89a7380: 00 00 00 00 f1 f1 f1 f1 00 04 f2 f2 00 00 f2 f2 + >ffff0008c89a7400: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 + ^ + ffff0008c89a7480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ffff0008c89a7500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ================================================================== + +Signed-off-by: Ian Nam +Signed-off-by: Shubhrajyoti Datta +Link: https://lore.kernel.org/r/20220510070154.29528-3-shubhrajyoti.datta@xilinx.com +Acked-by: Michal Simek +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/zynqmp/clkc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c +index eb25303eefed..2c9da6623b84 100644 +--- a/drivers/clk/zynqmp/clkc.c ++++ b/drivers/clk/zynqmp/clkc.c +@@ -710,6 +710,13 @@ static void zynqmp_get_clock_info(void) + FIELD_PREP(CLK_ATTR_NODE_INDEX, i); + + zynqmp_pm_clock_get_name(clock[i].clk_id, &name); ++ ++ /* ++ * Terminate with NULL character in case name provided by firmware ++ * is longer and truncated due to size limit. ++ */ ++ name.name[sizeof(name.name) - 1] = '\0'; ++ + if (!strcmp(name.name, RESERVED_CLK_NAME)) + continue; + strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN); +-- +2.35.1 + diff --git a/queue-5.19/clk-zynqmp-pll-rectify-rate-rounding-in-zynqmp_pll_r.patch b/queue-5.19/clk-zynqmp-pll-rectify-rate-rounding-in-zynqmp_pll_r.patch new file mode 100644 index 00000000000..58d003a3c9f --- /dev/null +++ b/queue-5.19/clk-zynqmp-pll-rectify-rate-rounding-in-zynqmp_pll_r.patch @@ -0,0 +1,92 @@ +From aa4587723463f3178398b9b84dded4dcfd8a6189 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 22:20:30 +0800 +Subject: clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate + +From: Quanyang Wang + +[ Upstream commit 30eaf02149ecc3c5815e45d27187bf09e925071d ] + +The function zynqmp_pll_round_rate is used to find a most appropriate +PLL frequency which the hardware can generate according to the desired +frequency. For example, if the desired frequency is 297MHz, considering +the limited range from PS_PLL_VCO_MIN (1.5GHz) to PS_PLL_VCO_MAX (3.0GHz) +of PLL, zynqmp_pll_round_rate should return 1.872GHz (297MHz * 5). + +There are two problems with the current code of zynqmp_pll_round_rate: + +1) When the rate is below PS_PLL_VCO_MIN, it can't find a correct rate +when the parameter "rate" is an integer multiple of *prate, in other words, +if "f" is zero, zynqmp_pll_round_rate won't return a valid frequency which +is from PS_PLL_VCO_MIN to PS_PLL_VCO_MAX. For example, *prate is 33MHz +and the rate is 660MHz, zynqmp_pll_round_rate will not boost up rate and +just return 660MHz, and this will cause clk_calc_new_rates failure since +zynqmp_pll_round_rate returns an invalid rate out of its boundaries. + +2) Even if the rate is higher than PS_PLL_VCO_MIN, there is still a risk +that zynqmp_pll_round_rate returns an invalid rate because the function +DIV_ROUND_CLOSEST makes some loss in the fractional part. If the parent +clock *prate is 33333333Hz and we want to set the PLL rate to 1.5GHz, +this function will return 1499999985Hz by using the formula below: + value = *prate * DIV_ROUND_CLOSEST(rate, *prate)). +This value is also invalid since it's slightly smaller than PS_PLL_VCO_MIN. +because DIV_ROUND_CLOSEST makes some loss in the fractional part. + +Signed-off-by: Quanyang Wang +Link: https://lore.kernel.org/r/20220826142030.213805-1-quanyang.wang@windriver.com +Reviewed-by: Shubhrajyoti Datta +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/zynqmp/pll.c | 31 +++++++++++++++---------------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c +index 91a6b4cc910e..0d3e1377b092 100644 +--- a/drivers/clk/zynqmp/pll.c ++++ b/drivers/clk/zynqmp/pll.c +@@ -102,26 +102,25 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) + { + u32 fbdiv; +- long rate_div, f; ++ u32 mult, div; + +- /* Enable the fractional mode if needed */ +- rate_div = (rate * FRAC_DIV) / *prate; +- f = rate_div % FRAC_DIV; +- if (f) { +- if (rate > PS_PLL_VCO_MAX) { +- fbdiv = rate / PS_PLL_VCO_MAX; +- rate = rate / (fbdiv + 1); +- } +- if (rate < PS_PLL_VCO_MIN) { +- fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); +- rate = rate * fbdiv; +- } +- return rate; ++ /* Let rate fall inside the range PS_PLL_VCO_MIN ~ PS_PLL_VCO_MAX */ ++ if (rate > PS_PLL_VCO_MAX) { ++ div = DIV_ROUND_UP(rate, PS_PLL_VCO_MAX); ++ rate = rate / div; ++ } ++ if (rate < PS_PLL_VCO_MIN) { ++ mult = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); ++ rate = rate * mult; + } + + fbdiv = DIV_ROUND_CLOSEST(rate, *prate); +- fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); +- return *prate * fbdiv; ++ if (fbdiv < PLL_FBDIV_MIN || fbdiv > PLL_FBDIV_MAX) { ++ fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); ++ rate = *prate * fbdiv; ++ } ++ ++ return rate; + } + + /** +-- +2.35.1 + diff --git a/queue-5.19/clocksource-drivers-arm_arch_timer-fix-handling-of-a.patch b/queue-5.19/clocksource-drivers-arm_arch_timer-fix-handling-of-a.patch new file mode 100644 index 00000000000..9e73b29c054 --- /dev/null +++ b/queue-5.19/clocksource-drivers-arm_arch_timer-fix-handling-of-a.patch @@ -0,0 +1,48 @@ +From 6b125d9f54e08c94e69bc411314d5dbb54e98853 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 14:14:24 +0800 +Subject: clocksource/drivers/arm_arch_timer: Fix handling of ARM erratum + 858921 + +From: Kunkun Jiang + +[ Upstream commit 6c3b62d93e195f78c1437c8fa7581e9b2f00886e ] + +The commit a38b71b0833e ("clocksource/drivers/arm_arch_timer: +Move system register timer programming over to CVAL") moves the +programming of the timers from the countdown timer (TVAL) over +to the comparator (CVAL). This makes it necessary to read the +counter when programming next event. However, the workaround of +Cortex-A73 erratum 858921 does not set the corresponding +set_next_event_phys and set_next_event_virt. + +Add the appropriate hooks to apply the erratum mitigation when +programming the next timer event. + +Fixes: a38b71b0833e ("clocksource/drivers/arm_arch_timer: Move system register timer programming over to CVAL") +Signed-off-by: Kunkun Jiang +Acked-by: Marc Zyngier +Reviewed-by: Oliver Upton +Link: https://lore.kernel.org/r/20220914061424.1260-1-jiangkunkun@huawei.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/clocksource/arm_arch_timer.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c +index 8122a1646925..a7ff77550e17 100644 +--- a/drivers/clocksource/arm_arch_timer.c ++++ b/drivers/clocksource/arm_arch_timer.c +@@ -473,6 +473,8 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { + .desc = "ARM erratum 858921", + .read_cntpct_el0 = arm64_858921_read_cntpct_el0, + .read_cntvct_el0 = arm64_858921_read_cntvct_el0, ++ .set_next_event_phys = erratum_set_next_event_phys, ++ .set_next_event_virt = erratum_set_next_event_virt, + }, + #endif + #ifdef CONFIG_SUN50I_ERRATUM_UNKNOWN1 +-- +2.35.1 + diff --git a/queue-5.19/clocksource-drivers-timer-gxp-add-missing-error-hand.patch b/queue-5.19/clocksource-drivers-timer-gxp-add-missing-error-hand.patch new file mode 100644 index 00000000000..793ed56979b --- /dev/null +++ b/queue-5.19/clocksource-drivers-timer-gxp-add-missing-error-hand.patch @@ -0,0 +1,50 @@ +From 0c046d233d6d72be68b9d508039760ab32fecf07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 11:30:18 +0800 +Subject: clocksource/drivers/timer-gxp: Add missing error handling in + gxp_timer_probe + +From: Lin Yujun + +[ Upstream commit 0e2c8e6d769bcdc4f6634a02c545356282275e68 ] + +Add platform_device_put() to make sure to free the platform +device in the event platform_device_add() fails. + +Fixes: 5184f4bf151b ("clocksource/drivers/timer-gxp: Add HPE GXP Timer") +Signed-off-by: Lin Yujun +Link: https://lore.kernel.org/r/20220914033018.97484-1-linyujun809@huawei.com +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/clocksource/timer-gxp.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/clocksource/timer-gxp.c b/drivers/clocksource/timer-gxp.c +index 8b38b3212388..fe4fa8d7b3f1 100644 +--- a/drivers/clocksource/timer-gxp.c ++++ b/drivers/clocksource/timer-gxp.c +@@ -171,6 +171,7 @@ static int gxp_timer_probe(struct platform_device *pdev) + { + struct platform_device *gxp_watchdog_device; + struct device *dev = &pdev->dev; ++ int ret; + + if (!gxp_timer) { + pr_err("Gxp Timer not initialized, cannot create watchdog"); +@@ -187,7 +188,11 @@ static int gxp_timer_probe(struct platform_device *pdev) + gxp_watchdog_device->dev.platform_data = gxp_timer->counter; + gxp_watchdog_device->dev.parent = dev; + +- return platform_device_add(gxp_watchdog_device); ++ ret = platform_device_add(gxp_watchdog_device); ++ if (ret) ++ platform_device_put(gxp_watchdog_device); ++ ++ return ret; + } + + static const struct of_device_id gxp_timer_of_match[] = { +-- +2.35.1 + diff --git a/queue-5.19/cpufreq-amd-pstate-fix-initial-highest_perf-value.patch b/queue-5.19/cpufreq-amd-pstate-fix-initial-highest_perf-value.patch new file mode 100644 index 00000000000..1ca3c989cc5 --- /dev/null +++ b/queue-5.19/cpufreq-amd-pstate-fix-initial-highest_perf-value.patch @@ -0,0 +1,83 @@ +From 3033da890170b6948daac389a08aadb50f699ed3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 09:56:00 +0800 +Subject: cpufreq: amd-pstate: Fix initial highest_perf value + +From: Perry Yuan + +[ Upstream commit bedadcfb011fef55273bd686e8893fdd8911dcdb ] + +To avoid some new AMD processors use wrong highest perf when amd pstate +driver loaded, this fix will query the highest perf from MSR register +MSR_AMD_CPPC_CAP1 and cppc_acpi interface firstly, then compare with the +highest perf value got by calling amd_get_highest_perf() function. + +The lower value will be the correct highest perf we need to use. +Otherwise the CPU max MHz will be incorrect if the +amd_get_highest_perf() did not cover the new process family and model ID. + +Like this lscpu info, the max frequency is incorrect. + +Vendor ID: AuthenticAMD + Socket(s): 1 + Stepping: 2 + CPU max MHz: 5410.0000 + CPU min MHz: 400.0000 + BogoMIPS: 5600.54 + +Fixes: 3743d55b289c2 (x86, sched: Fix the AMD CPPC maximum performance value on certain AMD Ryzen generations) +Acked-by: Huang Rui +Signed-off-by: Perry Yuan +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 9ac75c1cde9c..365f3ad166a7 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -152,6 +152,7 @@ static inline int amd_pstate_enable(bool enable) + static int pstate_init_perf(struct amd_cpudata *cpudata) + { + u64 cap1; ++ u32 highest_perf; + + int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1, + &cap1); +@@ -163,7 +164,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata) + * + * CPPC entry doesn't indicate the highest performance in some ASICs. + */ +- WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf()); ++ highest_perf = amd_get_highest_perf(); ++ if (highest_perf > AMD_CPPC_HIGHEST_PERF(cap1)) ++ highest_perf = AMD_CPPC_HIGHEST_PERF(cap1); ++ ++ WRITE_ONCE(cpudata->highest_perf, highest_perf); + + WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1)); + WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1)); +@@ -175,12 +180,17 @@ static int pstate_init_perf(struct amd_cpudata *cpudata) + static int cppc_init_perf(struct amd_cpudata *cpudata) + { + struct cppc_perf_caps cppc_perf; ++ u32 highest_perf; + + int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); + if (ret) + return ret; + +- WRITE_ONCE(cpudata->highest_perf, amd_get_highest_perf()); ++ highest_perf = amd_get_highest_perf(); ++ if (highest_perf > cppc_perf.highest_perf) ++ highest_perf = cppc_perf.highest_perf; ++ ++ WRITE_ONCE(cpudata->highest_perf, highest_perf); + + WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf); + WRITE_ONCE(cpudata->lowest_nonlinear_perf, +-- +2.35.1 + diff --git a/queue-5.19/cpufreq-amd_pstate-fix-wrong-lowest-perf-fetch.patch b/queue-5.19/cpufreq-amd_pstate-fix-wrong-lowest-perf-fetch.patch new file mode 100644 index 00000000000..f29764bf244 --- /dev/null +++ b/queue-5.19/cpufreq-amd_pstate-fix-wrong-lowest-perf-fetch.patch @@ -0,0 +1,40 @@ +From 1a62710dc21a184994fc718db12fd0e27f8a5b19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 00:35:45 +0800 +Subject: cpufreq: amd_pstate: fix wrong lowest perf fetch + +From: Perry Yuan + +[ Upstream commit b185c5053c65b7704ead4537e4d4d9b33dc398dc ] + +Fix the wrong lowest perf value reading which is used for new +des_perf calculation by governor requested, the incorrect min_perf will +get incorrect des_perf to be set , that will cause the system frequency +changing unexpectedly. + +Reviewed-by: Huang Rui +Acked-by: Viresh Kumar +Signed-off-by: Perry Yuan +Signed-off-by: Su Jinzhou +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/amd-pstate.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 365f3ad166a7..d63a28c5f95a 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -322,7 +322,7 @@ static int amd_pstate_target(struct cpufreq_policy *policy, + return -ENODEV; + + cap_perf = READ_ONCE(cpudata->highest_perf); +- min_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); ++ min_perf = READ_ONCE(cpudata->lowest_perf); + max_perf = cap_perf; + + freqs.old = policy->cur; +-- +2.35.1 + diff --git a/queue-5.19/cpufreq-intel_pstate-add-tigerlake-support-in-no-hwp.patch b/queue-5.19/cpufreq-intel_pstate-add-tigerlake-support-in-no-hwp.patch new file mode 100644 index 00000000000..ee27232a574 --- /dev/null +++ b/queue-5.19/cpufreq-intel_pstate-add-tigerlake-support-in-no-hwp.patch @@ -0,0 +1,44 @@ +From 99e2e7751ff529f446e7a23998ec282e047827f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 13:28:57 -0700 +Subject: cpufreq: intel_pstate: Add Tigerlake support in no-HWP mode + +From: Doug Smythies + +[ Upstream commit 71bb5c82aaaea007167f3ba68d3a669c74d7d55d ] + +Users may disable HWP in firmware, in which case intel_pstate wouldn't load +unless the CPU model is explicitly supported. + +Add TIGERLAKE to the list of CPUs that can register intel_pstate while not +advertising the HWP capability. Without this change, an TIGERLAKE in no-HWP +mode could only use the acpi_cpufreq frequency scaling driver. + +See also commits: +d8de7a44e11f: cpufreq: intel_pstate: Add Skylake servers support +fbdc21e9b038: cpufreq: intel_pstate: Add Icelake servers support in no-HWP mode +706c5328851d: cpufreq: intel_pstate: Add Cometlake support in no-HWP mode + +Reported by: M. Cargi Ari +Signed-off-by: Doug Smythies +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/cpufreq/intel_pstate.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c +index 57cdb3679885..fc3ebeb0bbe5 100644 +--- a/drivers/cpufreq/intel_pstate.c ++++ b/drivers/cpufreq/intel_pstate.c +@@ -2416,6 +2416,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = { + X86_MATCH(SKYLAKE_X, core_funcs), + X86_MATCH(COMETLAKE, core_funcs), + X86_MATCH(ICELAKE_X, core_funcs), ++ X86_MATCH(TIGERLAKE, core_funcs), + {} + }; + MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids); +-- +2.35.1 + diff --git a/queue-5.19/cpuidle-riscv-sbi-fix-cpu_pm_cpu_idle_enter_xyz-macr.patch b/queue-5.19/cpuidle-riscv-sbi-fix-cpu_pm_cpu_idle_enter_xyz-macr.patch new file mode 100644 index 00000000000..d49093e680d --- /dev/null +++ b/queue-5.19/cpuidle-riscv-sbi-fix-cpu_pm_cpu_idle_enter_xyz-macr.patch @@ -0,0 +1,49 @@ +From 5862a39acc7d84d60ca2b5a0d383bc505c0d25cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Jul 2022 14:15:53 +0530 +Subject: cpuidle: riscv-sbi: Fix CPU_PM_CPU_IDLE_ENTER_xyz() macro usage + +From: Anup Patel + +[ Upstream commit cfadbb9df8c4dc917787da4458327e5ec14743d4 ] + +Currently, we are using CPU_PM_CPU_IDLE_ENTER_PARAM() for all SBI HSM +suspend types so retentive suspend types are also treated non-retentive +and kernel will do redundant additional work for these states. + +The BIT[31] of SBI HSM suspend types allows us to differentiate between +retentive and non-retentive suspend types so we should use this BIT +to call appropriate CPU_PM_CPU_IDLE_ENTER_xyz() macro. + +Fixes: 6abf32f1d9c5 ("cpuidle: Add RISC-V SBI CPU idle driver") +Signed-off-by: Anup Patel +Link: https://lore.kernel.org/r/20220718084553.2056169-1-apatel@ventanamicro.com/ +Reviewed-by: Andrew Jones +Signed-off-by: Palmer Dabbelt +Signed-off-by: Sasha Levin +--- + drivers/cpuidle/cpuidle-riscv-sbi.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/cpuidle/cpuidle-riscv-sbi.c b/drivers/cpuidle/cpuidle-riscv-sbi.c +index 1151e5e2ba82..33c92fec4365 100644 +--- a/drivers/cpuidle/cpuidle-riscv-sbi.c ++++ b/drivers/cpuidle/cpuidle-riscv-sbi.c +@@ -97,8 +97,13 @@ static int sbi_cpuidle_enter_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) + { + u32 *states = __this_cpu_read(sbi_cpuidle_data.states); ++ u32 state = states[idx]; + +- return CPU_PM_CPU_IDLE_ENTER_PARAM(sbi_suspend, idx, states[idx]); ++ if (state & SBI_HSM_SUSP_NON_RET_BIT) ++ return CPU_PM_CPU_IDLE_ENTER_PARAM(sbi_suspend, idx, state); ++ else ++ return CPU_PM_CPU_IDLE_ENTER_RETENTION_PARAM(sbi_suspend, ++ idx, state); + } + + static int __sbi_enter_domain_idle_state(struct cpuidle_device *dev, +-- +2.35.1 + diff --git a/queue-5.19/crypto-akcipher-default-implementation-for-setting-a.patch b/queue-5.19/crypto-akcipher-default-implementation-for-setting-a.patch new file mode 100644 index 00000000000..b4724bf7502 --- /dev/null +++ b/queue-5.19/crypto-akcipher-default-implementation-for-setting-a.patch @@ -0,0 +1,70 @@ +From acfeda0f23b5ca2bd2af8e709585bddbf051dd3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 19:37:06 +0100 +Subject: crypto: akcipher - default implementation for setting a private key + +From: Ignat Korchagin + +[ Upstream commit bc155c6c188c2f0c5749993b1405673d25a80389 ] + +Changes from v1: + * removed the default implementation from set_pub_key: it is assumed that + an implementation must always have this callback defined as there are + no use case for an algorithm, which doesn't need a public key + +Many akcipher implementations (like ECDSA) support only signature +verifications, so they don't have all callbacks defined. + +Commit 78a0324f4a53 ("crypto: akcipher - default implementations for +request callbacks") introduced default callbacks for sign/verify +operations, which just return an error code. + +However, these are not enough, because before calling sign the caller would +likely call set_priv_key first on the instantiated transform (as the +in-kernel testmgr does). This function does not have a default stub, so the +kernel crashes, when trying to set a private key on an akcipher, which +doesn't support signature generation. + +I've noticed this, when trying to add a KAT vector for ECDSA signature to +the testmgr. + +With this patch the testmgr returns an error in dmesg (as it should) +instead of crashing the kernel NULL ptr dereference. + +Fixes: 78a0324f4a53 ("crypto: akcipher - default implementations for request callbacks") +Signed-off-by: Ignat Korchagin +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + crypto/akcipher.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/crypto/akcipher.c b/crypto/akcipher.c +index f866085c8a4a..ab975a420e1e 100644 +--- a/crypto/akcipher.c ++++ b/crypto/akcipher.c +@@ -120,6 +120,12 @@ static int akcipher_default_op(struct akcipher_request *req) + return -ENOSYS; + } + ++static int akcipher_default_set_key(struct crypto_akcipher *tfm, ++ const void *key, unsigned int keylen) ++{ ++ return -ENOSYS; ++} ++ + int crypto_register_akcipher(struct akcipher_alg *alg) + { + struct crypto_alg *base = &alg->base; +@@ -132,6 +138,8 @@ int crypto_register_akcipher(struct akcipher_alg *alg) + alg->encrypt = akcipher_default_op; + if (!alg->decrypt) + alg->decrypt = akcipher_default_op; ++ if (!alg->set_priv_key) ++ alg->set_priv_key = akcipher_default_set_key; + + akcipher_prepare_alg(alg); + return crypto_register_alg(base); +-- +2.35.1 + diff --git a/queue-5.19/crypto-cavium-prevent-integer-overflow-loading-firmw.patch b/queue-5.19/crypto-cavium-prevent-integer-overflow-loading-firmw.patch new file mode 100644 index 00000000000..4babef2b639 --- /dev/null +++ b/queue-5.19/crypto-cavium-prevent-integer-overflow-loading-firmw.patch @@ -0,0 +1,56 @@ +From 91bb37b17c7a7b49708c86db8404e141ea6a8339 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 09:43:27 +0300 +Subject: crypto: cavium - prevent integer overflow loading firmware + +From: Dan Carpenter + +[ Upstream commit 2526d6bf27d15054bb0778b2f7bc6625fd934905 ] + +The "code_length" value comes from the firmware file. If your firmware +is untrusted realistically there is probably very little you can do to +protect yourself. Still we try to limit the damage as much as possible. +Also Smatch marks any data read from the filesystem as untrusted and +prints warnings if it not capped correctly. + +The "ntohl(ucode->code_length) * 2" multiplication can have an +integer overflow. + +Fixes: 9e2c7d99941d ("crypto: cavium - Add Support for Octeon-tx CPT Engine") +Signed-off-by: Dan Carpenter +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/cavium/cpt/cptpf_main.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/cavium/cpt/cptpf_main.c b/drivers/crypto/cavium/cpt/cptpf_main.c +index 8c32d0eb8fcf..6872ac344001 100644 +--- a/drivers/crypto/cavium/cpt/cptpf_main.c ++++ b/drivers/crypto/cavium/cpt/cptpf_main.c +@@ -253,6 +253,7 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae) + const struct firmware *fw_entry; + struct device *dev = &cpt->pdev->dev; + struct ucode_header *ucode; ++ unsigned int code_length; + struct microcode *mcode; + int j, ret = 0; + +@@ -263,11 +264,12 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae) + ucode = (struct ucode_header *)fw_entry->data; + mcode = &cpt->mcode[cpt->next_mc_idx]; + memcpy(mcode->version, (u8 *)fw_entry->data, CPT_UCODE_VERSION_SZ); +- mcode->code_size = ntohl(ucode->code_length) * 2; +- if (!mcode->code_size) { ++ code_length = ntohl(ucode->code_length); ++ if (code_length == 0 || code_length >= INT_MAX / 2) { + ret = -EINVAL; + goto fw_release; + } ++ mcode->code_size = code_length * 2; + + mcode->is_ae = is_ae; + mcode->core_mask = 0ULL; +-- +2.35.1 + diff --git a/queue-5.19/crypto-ccp-fail-the-psp-initialization-when-writing-.patch b/queue-5.19/crypto-ccp-fail-the-psp-initialization-when-writing-.patch new file mode 100644 index 00000000000..4e8f6b497b9 --- /dev/null +++ b/queue-5.19/crypto-ccp-fail-the-psp-initialization-when-writing-.patch @@ -0,0 +1,111 @@ +From 9ac7ab1c828ce92df7d5d42a558aefb138bfe9a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 19:32:09 +0000 +Subject: crypto: ccp - Fail the PSP initialization when writing psp data file + failed + +From: Jacky Li + +[ Upstream commit efb4b01c1c993d245e6608076684ff2162cf9dc6 ] + +Currently the OS continues the PSP initialization when there is a write +failure to the init_ex_file. Therefore, the userspace would be told that +SEV is properly INIT'd even though the psp data file is not updated. +This is problematic because later when asked for the SEV data, the OS +won't be able to provide it. + +Fixes: 3d725965f836 ("crypto: ccp - Add SEV_INIT_EX support") +Reported-by: Peter Gonda +Reported-by: kernel test robot +Signed-off-by: Jacky Li +Acked-by: David Rientjes +Acked-by: Tom Lendacky +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/sev-dev.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c +index 9f588c9728f8..6c49e6d06114 100644 +--- a/drivers/crypto/ccp/sev-dev.c ++++ b/drivers/crypto/ccp/sev-dev.c +@@ -231,7 +231,7 @@ static int sev_read_init_ex_file(void) + return 0; + } + +-static void sev_write_init_ex_file(void) ++static int sev_write_init_ex_file(void) + { + struct sev_device *sev = psp_master->sev_data; + struct file *fp; +@@ -241,14 +241,16 @@ static void sev_write_init_ex_file(void) + lockdep_assert_held(&sev_cmd_mutex); + + if (!sev_init_ex_buffer) +- return; ++ return 0; + + fp = open_file_as_root(init_ex_path, O_CREAT | O_WRONLY, 0600); + if (IS_ERR(fp)) { ++ int ret = PTR_ERR(fp); ++ + dev_err(sev->dev, +- "SEV: could not open file for write, error %ld\n", +- PTR_ERR(fp)); +- return; ++ "SEV: could not open file for write, error %d\n", ++ ret); ++ return ret; + } + + nwrite = kernel_write(fp, sev_init_ex_buffer, NV_LENGTH, &offset); +@@ -259,18 +261,20 @@ static void sev_write_init_ex_file(void) + dev_err(sev->dev, + "SEV: failed to write %u bytes to non volatile memory area, ret %ld\n", + NV_LENGTH, nwrite); +- return; ++ return -EIO; + } + + dev_dbg(sev->dev, "SEV: write successful to NV file\n"); ++ ++ return 0; + } + +-static void sev_write_init_ex_file_if_required(int cmd_id) ++static int sev_write_init_ex_file_if_required(int cmd_id) + { + lockdep_assert_held(&sev_cmd_mutex); + + if (!sev_init_ex_buffer) +- return; ++ return 0; + + /* + * Only a few platform commands modify the SPI/NV area, but none of the +@@ -285,10 +289,10 @@ static void sev_write_init_ex_file_if_required(int cmd_id) + case SEV_CMD_PEK_GEN: + break; + default: +- return; ++ return 0; + } + +- sev_write_init_ex_file(); ++ return sev_write_init_ex_file(); + } + + static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) +@@ -361,7 +365,7 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) + cmd, reg & PSP_CMDRESP_ERR_MASK); + ret = -EIO; + } else { +- sev_write_init_ex_file_if_required(cmd); ++ ret = sev_write_init_ex_file_if_required(cmd); + } + + print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data, +-- +2.35.1 + diff --git a/queue-5.19/crypto-ccp-release-dma-channels-before-dmaengine-unr.patch b/queue-5.19/crypto-ccp-release-dma-channels-before-dmaengine-unr.patch new file mode 100644 index 00000000000..b8a3197b5e2 --- /dev/null +++ b/queue-5.19/crypto-ccp-release-dma-channels-before-dmaengine-unr.patch @@ -0,0 +1,54 @@ +From b3aa2a9cf1a26cb90432feac134c64de88d4e482 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 22:47:12 +0800 +Subject: crypto: ccp - Release dma channels before dmaengine unrgister + +From: Koba Ko + +[ Upstream commit 68dbe80f5b510c66c800b9e8055235c5b07e37d1 ] + +A warning is shown during shutdown, + +__dma_async_device_channel_unregister called while 2 clients hold a reference +WARNING: CPU: 15 PID: 1 at drivers/dma/dmaengine.c:1110 __dma_async_device_channel_unregister+0xb7/0xc0 + +Call dma_release_channel for occupied channles before dma_async_device_unregister. + +Fixes: 54cce8ecb925 ("crypto: ccp - ccp_dmaengine_unregister release dma channels") +Reported-by: kernel test robot +Signed-off-by: Koba Ko +Acked-by: Tom Lendacky +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/ccp/ccp-dmaengine.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/crypto/ccp/ccp-dmaengine.c b/drivers/crypto/ccp/ccp-dmaengine.c +index 7d4b4ad1db1f..9f753cb4f5f1 100644 +--- a/drivers/crypto/ccp/ccp-dmaengine.c ++++ b/drivers/crypto/ccp/ccp-dmaengine.c +@@ -641,6 +641,10 @@ static void ccp_dma_release(struct ccp_device *ccp) + for (i = 0; i < ccp->cmd_q_count; i++) { + chan = ccp->ccp_dma_chan + i; + dma_chan = &chan->dma_chan; ++ ++ if (dma_chan->client_count) ++ dma_release_channel(dma_chan); ++ + tasklet_kill(&chan->cleanup_tasklet); + list_del_rcu(&dma_chan->device_node); + } +@@ -766,8 +770,8 @@ void ccp_dmaengine_unregister(struct ccp_device *ccp) + if (!dmaengine) + return; + +- dma_async_device_unregister(dma_dev); + ccp_dma_release(ccp); ++ dma_async_device_unregister(dma_dev); + + kmem_cache_destroy(ccp->dma_desc_cache); + kmem_cache_destroy(ccp->dma_cmd_cache); +-- +2.35.1 + diff --git a/queue-5.19/crypto-hisilicon-qm-fix-missing-put-dfx-access.patch b/queue-5.19/crypto-hisilicon-qm-fix-missing-put-dfx-access.patch new file mode 100644 index 00000000000..48b2a98fdfe --- /dev/null +++ b/queue-5.19/crypto-hisilicon-qm-fix-missing-put-dfx-access.patch @@ -0,0 +1,41 @@ +From 2151f4e43fc3b9b746f5d05d6f9701b0aa4fe6c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Aug 2022 18:27:37 +0800 +Subject: crypto: hisilicon/qm - fix missing put dfx access + +From: Weili Qian + +[ Upstream commit 5afc904f443de2afd31c4e0686ba178beede86fe ] + +In function qm_cmd_write(), if function returns from +branch 'atomic_read(&qm->status.flags) == QM_STOP', +the got dfx access is forgotten to put. + +Fixes: 607c191b371d ("crypto: hisilicon - support runtime PM for accelerator device") +Signed-off-by: Weili Qian +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/qm.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c +index b4ca2eb034d7..eb82e9864d14 100644 +--- a/drivers/crypto/hisilicon/qm.c ++++ b/drivers/crypto/hisilicon/qm.c +@@ -2229,8 +2229,10 @@ static ssize_t qm_cmd_write(struct file *filp, const char __user *buffer, + return ret; + + /* Judge if the instance is being reset. */ +- if (unlikely(atomic_read(&qm->status.flags) == QM_STOP)) +- return 0; ++ if (unlikely(atomic_read(&qm->status.flags) == QM_STOP)) { ++ ret = 0; ++ goto put_dfx_access; ++ } + + if (count > QM_DBG_WRITE_LEN) { + ret = -ENOSPC; +-- +2.35.1 + diff --git a/queue-5.19/crypto-hisilicon-zip-fix-mismatch-in-get-set-sgl_sge.patch b/queue-5.19/crypto-hisilicon-zip-fix-mismatch-in-get-set-sgl_sge.patch new file mode 100644 index 00000000000..5f081bf1fc0 --- /dev/null +++ b/queue-5.19/crypto-hisilicon-zip-fix-mismatch-in-get-set-sgl_sge.patch @@ -0,0 +1,53 @@ +From 5ead1eefad2d35b6a4bb3e2d751f45d70f4ad502 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 10:07:58 +0800 +Subject: crypto: hisilicon/zip - fix mismatch in get/set sgl_sge_nr + +From: Ye Weihua + +[ Upstream commit d74f9340097a881869c4c22ca376654cc2516ecc ] + +KASAN reported this Bug: + + [17619.659757] BUG: KASAN: global-out-of-bounds in param_get_int+0x34/0x60 + [17619.673193] Read of size 4 at addr fffff01332d7ed00 by task read_all/1507958 + ... + [17619.698934] The buggy address belongs to the variable: + [17619.708371] sgl_sge_nr+0x0/0xffffffffffffa300 [hisi_zip] + +There is a mismatch in hisi_zip when get/set the variable sgl_sge_nr. +The type of sgl_sge_nr is u16, and get/set sgl_sge_nr by +param_get/set_int. + +Replacing param_get/set_int to param_get/set_ushort can fix this bug. + +Fixes: f081fda293ffb ("crypto: hisilicon - add sgl_sge_nr module param for zip") +Signed-off-by: Ye Weihua +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/hisilicon/zip/zip_crypto.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c +index 67869513e48c..d90b10ae005b 100644 +--- a/drivers/crypto/hisilicon/zip/zip_crypto.c ++++ b/drivers/crypto/hisilicon/zip/zip_crypto.c +@@ -122,12 +122,12 @@ static int sgl_sge_nr_set(const char *val, const struct kernel_param *kp) + if (ret || n == 0 || n > HISI_ACC_SGL_SGE_NR_MAX) + return -EINVAL; + +- return param_set_int(val, kp); ++ return param_set_ushort(val, kp); + } + + static const struct kernel_param_ops sgl_sge_nr_ops = { + .set = sgl_sge_nr_set, +- .get = param_get_int, ++ .get = param_get_ushort, + }; + + static u16 sgl_sge_nr = HZIP_SGL_SGE_NR; +-- +2.35.1 + diff --git a/queue-5.19/crypto-inside-secure-change-swab-to-swab32.patch b/queue-5.19/crypto-inside-secure-change-swab-to-swab32.patch new file mode 100644 index 00000000000..c88ab1bcdd2 --- /dev/null +++ b/queue-5.19/crypto-inside-secure-change-swab-to-swab32.patch @@ -0,0 +1,65 @@ +From 5ee5c57d52785cc34a6a7f12e09a553f4b832ced Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 10:51:28 +0800 +Subject: crypto: inside-secure - Change swab to swab32 + +From: Peter Harliman Liem + +[ Upstream commit 664593407e936b6438fbfaaf98876910fd31cf9a ] + +The use of swab() is causing failures in 64-bit arch, as it +translates to __swab64() instead of the intended __swab32(). +It eventually causes wrong results in xcbcmac & cmac algo. + +Fixes: 78cf1c8bfcb8 ("crypto: inside-secure - Move ipad/opad into safexcel_context") +Signed-off-by: Peter Harliman Liem +Acked-by: Antoine Tenart +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/inside-secure/safexcel_hash.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c +index bc60b5802256..2124416742f8 100644 +--- a/drivers/crypto/inside-secure/safexcel_hash.c ++++ b/drivers/crypto/inside-secure/safexcel_hash.c +@@ -383,7 +383,7 @@ static int safexcel_ahash_send_req(struct crypto_async_request *async, int ring, + u32 x; + + x = ipad[i] ^ ipad[i + 4]; +- cache[i] ^= swab(x); ++ cache[i] ^= swab32(x); + } + } + cache_len = AES_BLOCK_SIZE; +@@ -821,7 +821,7 @@ static int safexcel_ahash_final(struct ahash_request *areq) + u32 *result = (void *)areq->result; + + /* K3 */ +- result[i] = swab(ctx->base.ipad.word[i + 4]); ++ result[i] = swab32(ctx->base.ipad.word[i + 4]); + } + areq->result[0] ^= 0x80; // 10- padding + crypto_cipher_encrypt_one(ctx->kaes, areq->result, areq->result); +@@ -2106,7 +2106,7 @@ static int safexcel_xcbcmac_setkey(struct crypto_ahash *tfm, const u8 *key, + crypto_cipher_encrypt_one(ctx->kaes, (u8 *)key_tmp + AES_BLOCK_SIZE, + "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3"); + for (i = 0; i < 3 * AES_BLOCK_SIZE / sizeof(u32); i++) +- ctx->base.ipad.word[i] = swab(key_tmp[i]); ++ ctx->base.ipad.word[i] = swab32(key_tmp[i]); + + crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); + crypto_cipher_set_flags(ctx->kaes, crypto_ahash_get_flags(tfm) & +@@ -2189,7 +2189,7 @@ static int safexcel_cmac_setkey(struct crypto_ahash *tfm, const u8 *key, + return ret; + + for (i = 0; i < len / sizeof(u32); i++) +- ctx->base.ipad.word[i + 8] = swab(aes.key_enc[i]); ++ ctx->base.ipad.word[i + 8] = swab32(aes.key_enc[i]); + + /* precompute the CMAC key material */ + crypto_cipher_clear_flags(ctx->kaes, CRYPTO_TFM_REQ_MASK); +-- +2.35.1 + diff --git a/queue-5.19/crypto-marvell-octeontx-prevent-integer-overflows.patch b/queue-5.19/crypto-marvell-octeontx-prevent-integer-overflows.patch new file mode 100644 index 00000000000..f5188ebc3fd --- /dev/null +++ b/queue-5.19/crypto-marvell-octeontx-prevent-integer-overflows.patch @@ -0,0 +1,79 @@ +From 3c545b92d85419b6fbd87acdf8be8e247a4e65c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 09:43:19 +0300 +Subject: crypto: marvell/octeontx - prevent integer overflows + +From: Dan Carpenter + +[ Upstream commit caca37cf6c749ff0303f68418cfe7b757a4e0697 ] + +The "code_length" value comes from the firmware file. If your firmware +is untrusted realistically there is probably very little you can do to +protect yourself. Still we try to limit the damage as much as possible. +Also Smatch marks any data read from the filesystem as untrusted and +prints warnings if it not capped correctly. + +The "code_length * 2" can overflow. The round_up(ucode_size, 16) + +sizeof() expression can overflow too. Prevent these overflows. + +Fixes: d9110b0b01ff ("crypto: marvell - add support for OCTEON TX CPT engine") +Signed-off-by: Dan Carpenter +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + .../crypto/marvell/octeontx/otx_cptpf_ucode.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +index 40b482198ebc..a765eefb18c2 100644 +--- a/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c ++++ b/drivers/crypto/marvell/octeontx/otx_cptpf_ucode.c +@@ -286,6 +286,7 @@ static int process_tar_file(struct device *dev, + struct tar_ucode_info_t *tar_info; + struct otx_cpt_ucode_hdr *ucode_hdr; + int ucode_type, ucode_size; ++ unsigned int code_length; + + /* + * If size is less than microcode header size then don't report +@@ -303,7 +304,13 @@ static int process_tar_file(struct device *dev, + if (get_ucode_type(ucode_hdr, &ucode_type)) + return 0; + +- ucode_size = ntohl(ucode_hdr->code_length) * 2; ++ code_length = ntohl(ucode_hdr->code_length); ++ if (code_length >= INT_MAX / 2) { ++ dev_err(dev, "Invalid code_length %u\n", code_length); ++ return -EINVAL; ++ } ++ ++ ucode_size = code_length * 2; + if (!ucode_size || (size < round_up(ucode_size, 16) + + sizeof(struct otx_cpt_ucode_hdr) + OTX_CPT_UCODE_SIGN_LEN)) { + dev_err(dev, "Ucode %s invalid size\n", filename); +@@ -886,6 +893,7 @@ static int ucode_load(struct device *dev, struct otx_cpt_ucode *ucode, + { + struct otx_cpt_ucode_hdr *ucode_hdr; + const struct firmware *fw; ++ unsigned int code_length; + int ret; + + set_ucode_filename(ucode, ucode_filename); +@@ -896,7 +904,13 @@ static int ucode_load(struct device *dev, struct otx_cpt_ucode *ucode, + ucode_hdr = (struct otx_cpt_ucode_hdr *) fw->data; + memcpy(ucode->ver_str, ucode_hdr->ver_str, OTX_CPT_UCODE_VER_STR_SZ); + ucode->ver_num = ucode_hdr->ver_num; +- ucode->size = ntohl(ucode_hdr->code_length) * 2; ++ code_length = ntohl(ucode_hdr->code_length); ++ if (code_length >= INT_MAX / 2) { ++ dev_err(dev, "Ucode invalid code_length %u\n", code_length); ++ ret = -EINVAL; ++ goto release_fw; ++ } ++ ucode->size = code_length * 2; + if (!ucode->size || (fw->size < round_up(ucode->size, 16) + + sizeof(struct otx_cpt_ucode_hdr) + OTX_CPT_UCODE_SIGN_LEN)) { + dev_err(dev, "Ucode %s invalid size\n", ucode_filename); +-- +2.35.1 + diff --git a/queue-5.19/crypto-qat-fix-default-value-of-wdt-timer.patch b/queue-5.19/crypto-qat-fix-default-value-of-wdt-timer.patch new file mode 100644 index 00000000000..29a4b1a1b07 --- /dev/null +++ b/queue-5.19/crypto-qat-fix-default-value-of-wdt-timer.patch @@ -0,0 +1,41 @@ +From 7f6dfb30df1f3a61307debe2da75cd5ad93a6ee0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 12:32:16 +0200 +Subject: crypto: qat - fix default value of WDT timer + +From: Lucas Segarra Fernandez + +[ Upstream commit cc40b04c08400d86d2d6ea0159e0617e717f729c ] + +The QAT HW supports an hardware mechanism to detect an accelerator hang. +The reporting of a hang occurs after a watchdog timer (WDT) expires. + +The value of the WDT set previously was too small and was causing false +positives. +Change the default value of the WDT to 0x7000000ULL to avoid this. + +Fixes: 1c4d9d5bbb5a ("crypto: qat - enable detection of accelerators hang") +Reviewed-by: Giovanni Cabiddu +Signed-off-by: Lucas Segarra Fernandez +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/adf_gen4_hw_data.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/crypto/qat/qat_common/adf_gen4_hw_data.h b/drivers/crypto/qat/qat_common/adf_gen4_hw_data.h +index 43b8f864806b..4fb4b3df5a18 100644 +--- a/drivers/crypto/qat/qat_common/adf_gen4_hw_data.h ++++ b/drivers/crypto/qat/qat_common/adf_gen4_hw_data.h +@@ -107,7 +107,7 @@ do { \ + * Timeout is in cycles. Clock speed may vary across products but this + * value should be a few milli-seconds. + */ +-#define ADF_SSM_WDT_DEFAULT_VALUE 0x200000 ++#define ADF_SSM_WDT_DEFAULT_VALUE 0x7000000ULL + #define ADF_SSM_WDT_PKE_DEFAULT_VALUE 0x8000000 + #define ADF_SSMWDTL_OFFSET 0x54 + #define ADF_SSMWDTH_OFFSET 0x5C +-- +2.35.1 + diff --git a/queue-5.19/crypto-qat-fix-dma-transfer-direction.patch b/queue-5.19/crypto-qat-fix-dma-transfer-direction.patch new file mode 100644 index 00000000000..b134832b1c5 --- /dev/null +++ b/queue-5.19/crypto-qat-fix-dma-transfer-direction.patch @@ -0,0 +1,156 @@ +From 0c90d6920a1c28839da718b6c7ddfa2eeb9db03c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 11:49:12 +0100 +Subject: crypto: qat - fix DMA transfer direction + +From: Damian Muszynski + +[ Upstream commit cf5bb835b7c8a5fee7f26455099cca7feb57f5e9 ] + +When CONFIG_DMA_API_DEBUG is selected, while running the crypto self +test on the QAT crypto algorithms, the function add_dma_entry() reports +a warning similar to the one below, saying that overlapping mappings +are not supported. This occurs in tests where the input and the output +scatter list point to the same buffers (i.e. two different scatter lists +which point to the same chunks of memory). + +The logic that implements the mapping uses the flag DMA_BIDIRECTIONAL +for both the input and the output scatter lists which leads to +overlapped write mappings. These are not supported by the DMA layer. + +Fix by specifying the correct DMA transfer directions when mapping +buffers. For in-place operations where the input scatter list +matches the output scatter list, buffers are mapped once with +DMA_BIDIRECTIONAL, otherwise input buffers are mapped using the flag +DMA_TO_DEVICE and output buffers are mapped with DMA_FROM_DEVICE. +Overlapping a read mapping with a write mapping is a valid case in +dma-coherent devices like QAT. +The function that frees and unmaps the buffers, qat_alg_free_bufl() +has been changed accordingly to the changes to the mapping function. + + DMA-API: 4xxx 0000:06:00.0: cacheline tracking EEXIST, overlapping mappings aren't supported + WARNING: CPU: 53 PID: 4362 at kernel/dma/debug.c:570 add_dma_entry+0x1e9/0x270 + ... + Call Trace: + dma_map_page_attrs+0x82/0x2d0 + ? preempt_count_add+0x6a/0xa0 + qat_alg_sgl_to_bufl+0x45b/0x990 [intel_qat] + qat_alg_aead_dec+0x71/0x250 [intel_qat] + crypto_aead_decrypt+0x3d/0x70 + test_aead_vec_cfg+0x649/0x810 + ? number+0x310/0x3a0 + ? vsnprintf+0x2a3/0x550 + ? scnprintf+0x42/0x70 + ? valid_sg_divisions.constprop.0+0x86/0xa0 + ? test_aead_vec+0xdf/0x120 + test_aead_vec+0xdf/0x120 + alg_test_aead+0x185/0x400 + alg_test+0x3d8/0x500 + ? crypto_acomp_scomp_free_ctx+0x30/0x30 + ? __schedule+0x32a/0x12a0 + ? ttwu_queue_wakelist+0xbf/0x110 + ? _raw_spin_unlock_irqrestore+0x23/0x40 + ? try_to_wake_up+0x83/0x570 + ? _raw_spin_unlock_irqrestore+0x23/0x40 + ? __set_cpus_allowed_ptr_locked+0xea/0x1b0 + ? crypto_acomp_scomp_free_ctx+0x30/0x30 + cryptomgr_test+0x27/0x50 + kthread+0xe6/0x110 + ? kthread_complete_and_exit+0x20/0x20 + ret_from_fork+0x1f/0x30 + +Fixes: d370cec ("crypto: qat - Intel(R) QAT crypto interface") +Link: https://lore.kernel.org/linux-crypto/20220223080400.139367-1-gilad@benyossef.com/ +Signed-off-by: Damian Muszynski +Signed-off-by: Giovanni Cabiddu +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/qat/qat_common/qat_algs.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c +index 148edbe379e3..0828d856d6b0 100644 +--- a/drivers/crypto/qat/qat_common/qat_algs.c ++++ b/drivers/crypto/qat/qat_common/qat_algs.c +@@ -673,11 +673,14 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, + dma_addr_t blpout = qat_req->buf.bloutp; + size_t sz = qat_req->buf.sz; + size_t sz_out = qat_req->buf.sz_out; ++ int bl_dma_dir; + int i; + ++ bl_dma_dir = blp != blpout ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ + for (i = 0; i < bl->num_bufs; i++) + dma_unmap_single(dev, bl->bufers[i].addr, +- bl->bufers[i].len, DMA_BIDIRECTIONAL); ++ bl->bufers[i].len, bl_dma_dir); + + dma_unmap_single(dev, blp, sz, DMA_TO_DEVICE); + +@@ -691,7 +694,7 @@ static void qat_alg_free_bufl(struct qat_crypto_instance *inst, + for (i = bufless; i < blout->num_bufs; i++) { + dma_unmap_single(dev, blout->bufers[i].addr, + blout->bufers[i].len, +- DMA_BIDIRECTIONAL); ++ DMA_FROM_DEVICE); + } + dma_unmap_single(dev, blpout, sz_out, DMA_TO_DEVICE); + +@@ -716,6 +719,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + struct scatterlist *sg; + size_t sz_out, sz = struct_size(bufl, bufers, n); + int node = dev_to_node(&GET_DEV(inst->accel_dev)); ++ int bufl_dma_dir; + + if (unlikely(!n)) + return -EINVAL; +@@ -733,6 +737,8 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + qat_req->buf.sgl_src_valid = true; + } + ++ bufl_dma_dir = sgl != sglout ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; ++ + for_each_sg(sgl, sg, n, i) + bufl->bufers[i].addr = DMA_MAPPING_ERROR; + +@@ -744,7 +750,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + + bufl->bufers[y].addr = dma_map_single(dev, sg_virt(sg), + sg->length, +- DMA_BIDIRECTIONAL); ++ bufl_dma_dir); + bufl->bufers[y].len = sg->length; + if (unlikely(dma_mapping_error(dev, bufl->bufers[y].addr))) + goto err_in; +@@ -787,7 +793,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + + bufers[y].addr = dma_map_single(dev, sg_virt(sg), + sg->length, +- DMA_BIDIRECTIONAL); ++ DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(dev, bufers[y].addr))) + goto err_out; + bufers[y].len = sg->length; +@@ -817,7 +823,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + if (!dma_mapping_error(dev, buflout->bufers[i].addr)) + dma_unmap_single(dev, buflout->bufers[i].addr, + buflout->bufers[i].len, +- DMA_BIDIRECTIONAL); ++ DMA_FROM_DEVICE); + + if (!qat_req->buf.sgl_dst_valid) + kfree(buflout); +@@ -831,7 +837,7 @@ static int qat_alg_sgl_to_bufl(struct qat_crypto_instance *inst, + if (!dma_mapping_error(dev, bufl->bufers[i].addr)) + dma_unmap_single(dev, bufl->bufers[i].addr, + bufl->bufers[i].len, +- DMA_BIDIRECTIONAL); ++ bufl_dma_dir); + + if (!qat_req->buf.sgl_src_valid) + kfree(bufl); +-- +2.35.1 + diff --git a/queue-5.19/crypto-sahara-don-t-sleep-when-in-softirq.patch b/queue-5.19/crypto-sahara-don-t-sleep-when-in-softirq.patch new file mode 100644 index 00000000000..f37de094102 --- /dev/null +++ b/queue-5.19/crypto-sahara-don-t-sleep-when-in-softirq.patch @@ -0,0 +1,95 @@ +From 4adf53622de30cbdb22e4a8d7108a2bcba80e67f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 12:09:28 +0800 +Subject: crypto: sahara - don't sleep when in softirq + +From: Zhengchao Shao + +[ Upstream commit 108586eba094b318e6a831f977f4ddcc403a15da ] + +Function of sahara_aes_crypt maybe could be called by function +of crypto_skcipher_encrypt during the rx softirq, so it is not +allowed to use mutex lock. + +Fixes: c0c3c89ae347 ("crypto: sahara - replace tasklets with...") +Signed-off-by: Zhengchao Shao +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/crypto/sahara.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c +index 457084b344c1..b07ae4ba165e 100644 +--- a/drivers/crypto/sahara.c ++++ b/drivers/crypto/sahara.c +@@ -26,10 +26,10 @@ + #include + #include + #include +-#include + #include + #include + #include ++#include + + #define SHA_BUFFER_LEN PAGE_SIZE + #define SAHARA_MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE +@@ -196,7 +196,7 @@ struct sahara_dev { + void __iomem *regs_base; + struct clk *clk_ipg; + struct clk *clk_ahb; +- struct mutex queue_mutex; ++ spinlock_t queue_spinlock; + struct task_struct *kthread; + struct completion dma_completion; + +@@ -642,9 +642,9 @@ static int sahara_aes_crypt(struct skcipher_request *req, unsigned long mode) + + rctx->mode = mode; + +- mutex_lock(&dev->queue_mutex); ++ spin_lock_bh(&dev->queue_spinlock); + err = crypto_enqueue_request(&dev->queue, &req->base); +- mutex_unlock(&dev->queue_mutex); ++ spin_unlock_bh(&dev->queue_spinlock); + + wake_up_process(dev->kthread); + +@@ -1043,10 +1043,10 @@ static int sahara_queue_manage(void *data) + do { + __set_current_state(TASK_INTERRUPTIBLE); + +- mutex_lock(&dev->queue_mutex); ++ spin_lock_bh(&dev->queue_spinlock); + backlog = crypto_get_backlog(&dev->queue); + async_req = crypto_dequeue_request(&dev->queue); +- mutex_unlock(&dev->queue_mutex); ++ spin_unlock_bh(&dev->queue_spinlock); + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); +@@ -1092,9 +1092,9 @@ static int sahara_sha_enqueue(struct ahash_request *req, int last) + rctx->first = 1; + } + +- mutex_lock(&dev->queue_mutex); ++ spin_lock_bh(&dev->queue_spinlock); + ret = crypto_enqueue_request(&dev->queue, &req->base); +- mutex_unlock(&dev->queue_mutex); ++ spin_unlock_bh(&dev->queue_spinlock); + + wake_up_process(dev->kthread); + +@@ -1449,7 +1449,7 @@ static int sahara_probe(struct platform_device *pdev) + + crypto_init_queue(&dev->queue, SAHARA_QUEUE_LENGTH); + +- mutex_init(&dev->queue_mutex); ++ spin_lock_init(&dev->queue_spinlock); + + dev_ptr = dev; + +-- +2.35.1 + diff --git a/queue-5.19/cw1200-fix-incorrect-check-to-determine-if-no-elemen.patch b/queue-5.19/cw1200-fix-incorrect-check-to-determine-if-no-elemen.patch new file mode 100644 index 00000000000..1d55b7f1688 --- /dev/null +++ b/queue-5.19/cw1200-fix-incorrect-check-to-determine-if-no-elemen.patch @@ -0,0 +1,75 @@ +From 9684af6eaa60f688f4c879b1125d01fb43073676 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Apr 2022 17:17:23 +0800 +Subject: cw1200: fix incorrect check to determine if no element is found in + list + +From: Xiaomeng Tong + +[ Upstream commit 86df5de5c632d3bd940f59bbb14ae912aa9cc363 ] + +The bug is here: "} else if (item) {". + +The list iterator value will *always* be set and non-NULL by +list_for_each_entry(), so it is incorrect to assume that the iterator +value will be NULL if the list is empty or no element is found in list. + +Use a new value 'iter' as the list iterator, while use the old value +'item' as a dedicated pointer to point to the found element, which +1. can fix this bug, due to now 'item' is NULL only if it's not found. +2. do not need to change all the uses of 'item' after the loop. +3. can also limit the scope of the list iterator 'iter' *only inside* + the traversal loop by simply declaring 'iter' inside the loop in the + future, as usage of the iterator outside of the list_for_each_entry + is considered harmful. https://lkml.org/lkml/2022/2/17/1032 + +Fixes: a910e4a94f692 ("cw1200: add driver for the ST-E CW1100 & CW1200 WLAN chipsets") +Signed-off-by: Xiaomeng Tong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220413091723.17596-1-xiam0nd.tong@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/st/cw1200/queue.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c +index e06da4b3b0d4..805a3c1bf8fe 100644 +--- a/drivers/net/wireless/st/cw1200/queue.c ++++ b/drivers/net/wireless/st/cw1200/queue.c +@@ -91,23 +91,25 @@ static void __cw1200_queue_gc(struct cw1200_queue *queue, + bool unlock) + { + struct cw1200_queue_stats *stats = queue->stats; +- struct cw1200_queue_item *item = NULL, *tmp; ++ struct cw1200_queue_item *item = NULL, *iter, *tmp; + bool wakeup_stats = false; + +- list_for_each_entry_safe(item, tmp, &queue->queue, head) { +- if (time_is_after_jiffies(item->queue_timestamp + queue->ttl)) ++ list_for_each_entry_safe(iter, tmp, &queue->queue, head) { ++ if (time_is_after_jiffies(iter->queue_timestamp + queue->ttl)) { ++ item = iter; + break; ++ } + --queue->num_queued; +- --queue->link_map_cache[item->txpriv.link_id]; ++ --queue->link_map_cache[iter->txpriv.link_id]; + spin_lock_bh(&stats->lock); + --stats->num_queued; +- if (!--stats->link_map_cache[item->txpriv.link_id]) ++ if (!--stats->link_map_cache[iter->txpriv.link_id]) + wakeup_stats = true; + spin_unlock_bh(&stats->lock); + cw1200_debug_tx_ttl(stats->priv); +- cw1200_queue_register_post_gc(head, item); +- item->skb = NULL; +- list_move_tail(&item->head, &queue->free_pool); ++ cw1200_queue_register_post_gc(head, iter); ++ iter->skb = NULL; ++ list_move_tail(&iter->head, &queue->free_pool); + } + + if (wakeup_stats) +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-hisilicon-add-multi-thread-support-for-a-d.patch b/queue-5.19/dmaengine-hisilicon-add-multi-thread-support-for-a-d.patch new file mode 100644 index 00000000000..25319b3aa37 --- /dev/null +++ b/queue-5.19/dmaengine-hisilicon-add-multi-thread-support-for-a-d.patch @@ -0,0 +1,102 @@ +From a9aa2414266013199f49491ee33bad8823d99c07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 14:22:47 +0800 +Subject: dmaengine: hisilicon: Add multi-thread support for a DMA channel + +From: Jie Hai + +[ Upstream commit 2cbb95883c990d0002a77e13d3278913ab26ad79 ] + +When we get a DMA channel and try to use it in multiple threads it +will cause oops and hanging the system. + +% echo 100 > /sys/module/dmatest/parameters/threads_per_chan +% echo 100 > /sys/module/dmatest/parameters/iterations +% echo 1 > /sys/module/dmatest/parameters/run +[383493.327077] Unable to handle kernel paging request at virtual + address dead000000000108 +[383493.335103] Mem abort info: +[383493.335103] ESR = 0x96000044 +[383493.335105] EC = 0x25: DABT (current EL), IL = 32 bits +[383493.335107] SET = 0, FnV = 0 +[383493.335108] EA = 0, S1PTW = 0 +[383493.335109] FSC = 0x04: level 0 translation fault +[383493.335110] Data abort info: +[383493.335111] ISV = 0, ISS = 0x00000044 +[383493.364739] CM = 0, WnR = 1 +[383493.367793] [dead000000000108] address between user and kernel + address ranges +[383493.375021] Internal error: Oops: 96000044 [#1] PREEMPT SMP +[383493.437574] CPU: 63 PID: 27895 Comm: dma0chan0-copy2 Kdump: + loaded Tainted: GO 5.17.0-rc4+ #2 +[383493.457851] pstate: 204000c9 (nzCv daIF +PAN -UAO -TCO -DIT + -SSBS BTYPE=--) +[383493.465331] pc : vchan_tx_submit+0x64/0xa0 +[383493.469957] lr : vchan_tx_submit+0x34/0xa0 + +This occurs because the transmission timed out, and that's due +to data race. Each thread rewrite channels's descriptor as soon as +device_issue_pending is called. It leads to the situation that +the driver thinks that it uses the right descriptor in interrupt +handler while channels's descriptor has been changed by other +thread. The descriptor which in fact reported interrupt will not +be handled any more, as well as its tx->callback. +That's why timeout reports. + +With current fixes channels' descriptor changes it's value only +when it has been used. A new descriptor is acquired from +vc->desc_issued queue that is already filled with descriptors +that are ready to be sent. Threads have no direct access to DMA +channel descriptor. In case of channel's descriptor is busy, try +to submit to HW again when a descriptor is completed. In this case, +vc->desc_issued may be empty when hisi_dma_start_transfer is called, +so delete error reporting on this. Now it is just possible to queue +a descriptor for further processing. + +Fixes: e9f08b65250d ("dmaengine: hisilicon: Add Kunpeng DMA engine support") +Signed-off-by: Jie Hai +Acked-by: Zhou Wang +Link: https://lore.kernel.org/r/20220830062251.52993-4-haijie1@huawei.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/hisi_dma.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c +index 837f7e4adfa6..0233b42143c7 100644 +--- a/drivers/dma/hisi_dma.c ++++ b/drivers/dma/hisi_dma.c +@@ -271,7 +271,6 @@ static void hisi_dma_start_transfer(struct hisi_dma_chan *chan) + + vd = vchan_next_desc(&chan->vc); + if (!vd) { +- dev_err(&hdma_dev->pdev->dev, "no issued task!\n"); + chan->desc = NULL; + return; + } +@@ -303,7 +302,7 @@ static void hisi_dma_issue_pending(struct dma_chan *c) + + spin_lock_irqsave(&chan->vc.lock, flags); + +- if (vchan_issue_pending(&chan->vc)) ++ if (vchan_issue_pending(&chan->vc) && !chan->desc) + hisi_dma_start_transfer(chan); + + spin_unlock_irqrestore(&chan->vc.lock, flags); +@@ -441,11 +440,10 @@ static irqreturn_t hisi_dma_irq(int irq, void *data) + chan->qp_num, chan->cq_head); + if (FIELD_GET(STATUS_MASK, cqe->w0) == STATUS_SUCC) { + vchan_cookie_complete(&desc->vd); ++ hisi_dma_start_transfer(chan); + } else { + dev_err(&hdma_dev->pdev->dev, "task error!\n"); + } +- +- chan->desc = NULL; + } + + spin_unlock(&chan->vc.lock); +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-hisilicon-disable-channels-when-unregister.patch b/queue-5.19/dmaengine-hisilicon-disable-channels-when-unregister.patch new file mode 100644 index 00000000000..b37dd483e49 --- /dev/null +++ b/queue-5.19/dmaengine-hisilicon-disable-channels-when-unregister.patch @@ -0,0 +1,72 @@ +From bd27948a839fb4a3972f4b5dc368b1e2abbe1b94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 14:22:45 +0800 +Subject: dmaengine: hisilicon: Disable channels when unregister hisi_dma + +From: Jie Hai + +[ Upstream commit e3bdaa04ada31f46d0586df83a2789b8913053c5 ] + +When hisi_dma is unloaded or unbinded, all of channels should be +disabled. This patch disables DMA channels when driver is unloaded +or unbinded. + +Fixes: e9f08b65250d ("dmaengine: hisilicon: Add Kunpeng DMA engine support") +Signed-off-by: Jie Hai +Acked-by: Zhou Wang +Link: https://lore.kernel.org/r/20220830062251.52993-2-haijie1@huawei.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/hisi_dma.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c +index 43817ced3a3e..98bc488893cc 100644 +--- a/drivers/dma/hisi_dma.c ++++ b/drivers/dma/hisi_dma.c +@@ -180,7 +180,8 @@ static void hisi_dma_reset_qp_point(struct hisi_dma_dev *hdma_dev, u32 index) + hisi_dma_chan_write(hdma_dev->base, HISI_DMA_CQ_HEAD_PTR, index, 0); + } + +-static void hisi_dma_reset_hw_chan(struct hisi_dma_chan *chan) ++static void hisi_dma_reset_or_disable_hw_chan(struct hisi_dma_chan *chan, ++ bool disable) + { + struct hisi_dma_dev *hdma_dev = chan->hdma_dev; + u32 index = chan->qp_num, tmp; +@@ -201,8 +202,11 @@ static void hisi_dma_reset_hw_chan(struct hisi_dma_chan *chan) + hisi_dma_do_reset(hdma_dev, index); + hisi_dma_reset_qp_point(hdma_dev, index); + hisi_dma_pause_dma(hdma_dev, index, false); +- hisi_dma_enable_dma(hdma_dev, index, true); +- hisi_dma_unmask_irq(hdma_dev, index); ++ ++ if (!disable) { ++ hisi_dma_enable_dma(hdma_dev, index, true); ++ hisi_dma_unmask_irq(hdma_dev, index); ++ } + + ret = readl_relaxed_poll_timeout(hdma_dev->base + + HISI_DMA_Q_FSM_STS + index * HISI_DMA_OFFSET, tmp, +@@ -218,7 +222,7 @@ static void hisi_dma_free_chan_resources(struct dma_chan *c) + struct hisi_dma_chan *chan = to_hisi_dma_chan(c); + struct hisi_dma_dev *hdma_dev = chan->hdma_dev; + +- hisi_dma_reset_hw_chan(chan); ++ hisi_dma_reset_or_disable_hw_chan(chan, false); + vchan_free_chan_resources(&chan->vc); + + memset(chan->sq, 0, sizeof(struct hisi_dma_sqe) * hdma_dev->chan_depth); +@@ -394,7 +398,7 @@ static void hisi_dma_enable_qp(struct hisi_dma_dev *hdma_dev, u32 qp_index) + + static void hisi_dma_disable_qp(struct hisi_dma_dev *hdma_dev, u32 qp_index) + { +- hisi_dma_reset_hw_chan(&hdma_dev->chan[qp_index]); ++ hisi_dma_reset_or_disable_hw_chan(&hdma_dev->chan[qp_index], true); + } + + static void hisi_dma_enable_qps(struct hisi_dma_dev *hdma_dev) +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-hisilicon-fix-cq-head-update.patch b/queue-5.19/dmaengine-hisilicon-fix-cq-head-update.patch new file mode 100644 index 00000000000..66aa620bb08 --- /dev/null +++ b/queue-5.19/dmaengine-hisilicon-fix-cq-head-update.patch @@ -0,0 +1,55 @@ +From 9146da800b5365b6dd3df4ed928150b57a230824 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 14:22:46 +0800 +Subject: dmaengine: hisilicon: Fix CQ head update + +From: Jie Hai + +[ Upstream commit 94477a79cf80e8ab55b68f14bc579a12ddea1e0b ] + +After completion of data transfer of one or multiple descriptors, +the completion status and the current head pointer to submission +queue are written into the CQ and interrupt can be generated to +inform the software. In interrupt process CQ is read and cq_head +is updated. + +hisi_dma_irq updates cq_head only when the completion status is +success. When an abnormal interrupt reports, cq_head will not update +which will cause subsequent interrupt processes read the error CQ +and never report the correct status. + +This patch updates cq_head whenever CQ is accessed. + +Fixes: e9f08b65250d ("dmaengine: hisilicon: Add Kunpeng DMA engine support") +Signed-off-by: Jie Hai +Acked-by: Zhou Wang +Link: https://lore.kernel.org/r/20220830062251.52993-3-haijie1@huawei.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/hisi_dma.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/dma/hisi_dma.c b/drivers/dma/hisi_dma.c +index 98bc488893cc..837f7e4adfa6 100644 +--- a/drivers/dma/hisi_dma.c ++++ b/drivers/dma/hisi_dma.c +@@ -436,12 +436,10 @@ static irqreturn_t hisi_dma_irq(int irq, void *data) + desc = chan->desc; + cqe = chan->cq + chan->cq_head; + if (desc) { ++ chan->cq_head = (chan->cq_head + 1) % hdma_dev->chan_depth; ++ hisi_dma_chan_write(hdma_dev->base, HISI_DMA_CQ_HEAD_PTR, ++ chan->qp_num, chan->cq_head); + if (FIELD_GET(STATUS_MASK, cqe->w0) == STATUS_SUCC) { +- chan->cq_head = (chan->cq_head + 1) % +- hdma_dev->chan_depth; +- hisi_dma_chan_write(hdma_dev->base, +- HISI_DMA_CQ_HEAD_PTR, chan->qp_num, +- chan->cq_head); + vchan_cookie_complete(&desc->vd); + } else { + dev_err(&hdma_dev->pdev->dev, "task error!\n"); +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-idxd-avoid-deadlock-in-process_misc_interr.patch b/queue-5.19/dmaengine-idxd-avoid-deadlock-in-process_misc_interr.patch new file mode 100644 index 00000000000..95a62f0725a --- /dev/null +++ b/queue-5.19/dmaengine-idxd-avoid-deadlock-in-process_misc_interr.patch @@ -0,0 +1,50 @@ +From 68b0b6d1facf5c846649472ea76f0a61d62fa10e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 09:37:09 -0700 +Subject: dmaengine: idxd: avoid deadlock in process_misc_interrupts() + +From: Jerry Snitselaar + +[ Upstream commit 407171717a4f4d2d80825584643374a2dfdb0540 ] + +idxd_device_clear_state() now grabs the idxd->dev_lock +itself, so don't grab the lock prior to calling it. + +This was seen in testing after dmar fault occurred on system, +resulting in lockup stack traces. + +Cc: Fenghua Yu +Cc: Dave Jiang +Cc: Vinod Koul +Cc: dmaengine@vger.kernel.org +Fixes: cf4ac3fef338 ("dmaengine: idxd: fix lockdep warning on device driver removal") +Signed-off-by: Jerry Snitselaar +Reviewed-by: Dave Jiang +Link: https://lore.kernel.org/r/20220823163709.2102468-1-jsnitsel@redhat.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/idxd/irq.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c +index 743ead5ebc57..5b9921475be6 100644 +--- a/drivers/dma/idxd/irq.c ++++ b/drivers/dma/idxd/irq.c +@@ -324,13 +324,11 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) + idxd->state = IDXD_DEV_HALTED; + idxd_wqs_quiesce(idxd); + idxd_wqs_unmap_portal(idxd); +- spin_lock(&idxd->dev_lock); + idxd_device_clear_state(idxd); + dev_err(&idxd->pdev->dev, + "idxd halted, need %s.\n", + gensts.reset_type == IDXD_DEVICE_RESET_FLR ? + "FLR" : "system reset"); +- spin_unlock(&idxd->dev_lock); + return -ENXIO; + } + } +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-ioat-stop-mod_timer-from-resurrecting-dele.patch b/queue-5.19/dmaengine-ioat-stop-mod_timer-from-resurrecting-dele.patch new file mode 100644 index 00000000000..62f9a13552f --- /dev/null +++ b/queue-5.19/dmaengine-ioat-stop-mod_timer-from-resurrecting-dele.patch @@ -0,0 +1,61 @@ +From fedcf8b247dacceecf38ce9be121a8483ce5175e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 09:58:42 -0700 +Subject: dmaengine: ioat: stop mod_timer from resurrecting deleted timer in + __cleanup() + +From: Dave Jiang + +[ Upstream commit 898ec89dbb55b8294695ad71694a0684e62b2a73 ] + +User reports observing timer event report channel halted but no error +observed in CHANERR register. The driver finished self-test and released +channel resources. Debug shows that __cleanup() can call +mod_timer() after the timer has been deleted and thus resurrect the +timer. While harmless, it causes suprious error message to be emitted. +Use mod_timer_pending() call to prevent deleted timer from being +resurrected. + +Fixes: 3372de5813e4 ("dmaengine: ioatdma: removal of dma_v3.c and relevant ioat3 references") +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/166360672197.3851724.17040290563764838369.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/ioat/dma.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c +index 37ff4ec7db76..e2070df6cad2 100644 +--- a/drivers/dma/ioat/dma.c ++++ b/drivers/dma/ioat/dma.c +@@ -656,7 +656,7 @@ static void __cleanup(struct ioatdma_chan *ioat_chan, dma_addr_t phys_complete) + if (active - i == 0) { + dev_dbg(to_dev(ioat_chan), "%s: cancel completion timeout\n", + __func__); +- mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); ++ mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); + } + + /* microsecond delay by sysfs variable per pending descriptor */ +@@ -682,7 +682,7 @@ static void ioat_cleanup(struct ioatdma_chan *ioat_chan) + + if (chanerr & + (IOAT_CHANERR_HANDLE_MASK | IOAT_CHANERR_RECOVER_MASK)) { +- mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); ++ mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); + ioat_eh(ioat_chan); + } + } +@@ -879,7 +879,7 @@ static void check_active(struct ioatdma_chan *ioat_chan) + } + + if (test_and_clear_bit(IOAT_CHAN_ACTIVE, &ioat_chan->state)) +- mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); ++ mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT); + } + + static void ioat_reboot_chan(struct ioatdma_chan *ioat_chan) +-- +2.35.1 + diff --git a/queue-5.19/dmaengine-ti-k3-udma-reset-udma_chan_rt-byte-counter.patch b/queue-5.19/dmaengine-ti-k3-udma-reset-udma_chan_rt-byte-counter.patch new file mode 100644 index 00000000000..dd610779320 --- /dev/null +++ b/queue-5.19/dmaengine-ti-k3-udma-reset-udma_chan_rt-byte-counter.patch @@ -0,0 +1,115 @@ +From 48e7671830287659bb185192944872f0284cc4f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Aug 2022 11:18:35 +0530 +Subject: dmaengine: ti: k3-udma: Reset UDMA_CHAN_RT byte counters to prevent + overflow + +From: Vaishnav Achath + +[ Upstream commit 7c94dcfa8fcff2dba53915f1dabfee49a3df8b88 ] + +UDMA_CHAN_RT_*BCNT_REG stores the real-time channel bytecount statistics. +These registers are 32-bit hardware counters and the driver uses these +counters to monitor the operational progress status for a channel, when +transferring more than 4GB of data it was observed that these counters +overflow and completion calculation of a operation gets affected and the +transfer hangs indefinitely. + +This commit adds changes to decrease the byte count for every complete +transaction so that these registers never overflow and the proper byte +count statistics is maintained for ongoing transaction by the RT counters. + +Earlier uc->bcnt used to maintain a count of the completed bytes at driver +side, since the RT counters maintain the statistics of current transaction +now, the maintenance of uc->bcnt is not necessary. + +Signed-off-by: Vaishnav Achath +Acked-by: Peter Ujfalusi +Link: https://lore.kernel.org/r/20220802054835.19482-1-vaishnav.a@ti.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/dma/ti/k3-udma.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c +index 2f0d2c68c93c..fcfcde947b30 100644 +--- a/drivers/dma/ti/k3-udma.c ++++ b/drivers/dma/ti/k3-udma.c +@@ -300,8 +300,6 @@ struct udma_chan { + + struct udma_tx_drain tx_drain; + +- u32 bcnt; /* number of bytes completed since the start of the channel */ +- + /* Channel configuration parameters */ + struct udma_chan_config config; + +@@ -757,6 +755,20 @@ static void udma_reset_rings(struct udma_chan *uc) + } + } + ++static void udma_decrement_byte_counters(struct udma_chan *uc, u32 val) ++{ ++ if (uc->desc->dir == DMA_DEV_TO_MEM) { ++ udma_rchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val); ++ udma_rchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val); ++ udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); ++ } else { ++ udma_tchanrt_write(uc, UDMA_CHAN_RT_BCNT_REG, val); ++ udma_tchanrt_write(uc, UDMA_CHAN_RT_SBCNT_REG, val); ++ if (!uc->bchan) ++ udma_tchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); ++ } ++} ++ + static void udma_reset_counters(struct udma_chan *uc) + { + u32 val; +@@ -790,8 +802,6 @@ static void udma_reset_counters(struct udma_chan *uc) + val = udma_rchanrt_read(uc, UDMA_CHAN_RT_PEER_BCNT_REG); + udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_BCNT_REG, val); + } +- +- uc->bcnt = 0; + } + + static int udma_reset_chan(struct udma_chan *uc, bool hard) +@@ -1115,7 +1125,7 @@ static void udma_check_tx_completion(struct work_struct *work) + if (uc->desc) { + struct udma_desc *d = uc->desc; + +- uc->bcnt += d->residue; ++ udma_decrement_byte_counters(uc, d->residue); + udma_start(uc); + vchan_cookie_complete(&d->vd); + break; +@@ -1168,7 +1178,7 @@ static irqreturn_t udma_ring_irq_handler(int irq, void *data) + vchan_cyclic_callback(&d->vd); + } else { + if (udma_is_desc_really_done(uc, d)) { +- uc->bcnt += d->residue; ++ udma_decrement_byte_counters(uc, d->residue); + udma_start(uc); + vchan_cookie_complete(&d->vd); + } else { +@@ -1204,7 +1214,7 @@ static irqreturn_t udma_udma_irq_handler(int irq, void *data) + vchan_cyclic_callback(&d->vd); + } else { + /* TODO: figure out the real amount of data */ +- uc->bcnt += d->residue; ++ udma_decrement_byte_counters(uc, d->residue); + udma_start(uc); + vchan_cookie_complete(&d->vd); + } +@@ -3809,7 +3819,6 @@ static enum dma_status udma_tx_status(struct dma_chan *chan, + bcnt = udma_tchanrt_read(uc, UDMA_CHAN_RT_BCNT_REG); + } + +- bcnt -= uc->bcnt; + if (bcnt && !(bcnt % uc->desc->residue)) + residue = 0; + else +-- +2.35.1 + diff --git a/queue-5.19/drivers-serial-jsm-fix-some-leaks-in-probe.patch b/queue-5.19/drivers-serial-jsm-fix-some-leaks-in-probe.patch new file mode 100644 index 00000000000..dbf3100efc3 --- /dev/null +++ b/queue-5.19/drivers-serial-jsm-fix-some-leaks-in-probe.patch @@ -0,0 +1,37 @@ +From 631059073129079f00becf9252337c9fdeaf29ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 14:22:47 +0300 +Subject: drivers: serial: jsm: fix some leaks in probe + +From: Dan Carpenter + +[ Upstream commit 1d5859ef229e381f4db38dce8ed58e4bf862006b ] + +This error path needs to unwind instead of just returning directly. + +Fixes: 03a8482c17dd ("drivers: serial: jsm: Enable support for Digi Classic adapters") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/YyxFh1+lOeZ9WfKO@kili +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/jsm/jsm_driver.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c +index 0ea799bf8dbb..417a5b6bffc3 100644 +--- a/drivers/tty/serial/jsm/jsm_driver.c ++++ b/drivers/tty/serial/jsm/jsm_driver.c +@@ -211,7 +211,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) + + break; + default: +- return -ENXIO; ++ rc = -ENXIO; ++ goto out_kfree_brd; + } + + rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "JSM", brd); +-- +2.35.1 + diff --git a/queue-5.19/drm-admgpu-skip-cg-pg-on-soc21-under-sriov-vf.patch b/queue-5.19/drm-admgpu-skip-cg-pg-on-soc21-under-sriov-vf.patch new file mode 100644 index 00000000000..c2096f4f189 --- /dev/null +++ b/queue-5.19/drm-admgpu-skip-cg-pg-on-soc21-under-sriov-vf.patch @@ -0,0 +1,47 @@ +From 1c67fa8cf3df5f450469e078d5f5601795f5eeec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 11:02:19 +0800 +Subject: drm/admgpu: Skip CG/PG on SOC21 under SRIOV VF +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yifan Zha + +[ Upstream commit 828418259254863e0af5805bd712284e2bd88e3b ] + +[Why] +There is no CG(Clock Gating)/PG(Power Gating) requirement on SRIOV VF. +For multi VF, VF should not enable any CG/PG features. +For one VF, PF will program CG/PG related registers. + +[How] +Do not set any cg/pg flag bit at early init under sriov. + +Acked-by: Christian König +Signed-off-by: Yifan Zha +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/soc21.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c +index 8d5c452a9100..6d3bfb0f0346 100644 +--- a/drivers/gpu/drm/amd/amdgpu/soc21.c ++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c +@@ -551,6 +551,10 @@ static int soc21_common_early_init(void *handle) + AMD_PG_SUPPORT_JPEG | + AMD_PG_SUPPORT_ATHUB | + AMD_PG_SUPPORT_MMHUB; ++ if (amdgpu_sriov_vf(adev)) { ++ adev->cg_flags = 0; ++ adev->pg_flags = 0; ++ } + adev->external_rev_id = adev->rev_id + 0x1; // TODO: need update + break; + case IP_VERSION(11, 0, 2): +-- +2.35.1 + diff --git a/queue-5.19/drm-amd-display-correct-hostvm-flag.patch b/queue-5.19/drm-amd-display-correct-hostvm-flag.patch new file mode 100644 index 00000000000..53e51df81a9 --- /dev/null +++ b/queue-5.19/drm-amd-display-correct-hostvm-flag.patch @@ -0,0 +1,43 @@ +From df6bfc8c4da587f7ebed9a004ac7a7a07ab202c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 00:12:44 +0800 +Subject: drm/amd/display: correct hostvm flag + +From: Sherry Wang + +[ Upstream commit 796d6a37ff5ffaf9f2dc0f3f4bf9f4a1034c00de ] + +[Why] +Hostvm should be enabled/disabled accordding to +the status of riommu_active, but hostvm always +be disabled on DCN31 which causes underflow + +[How] +Set correct hostvm flag on DCN31 + +Reviewed-by: Charlene Liu +Acked-by: Wayne Lin +Signed-off-by: Sherry Wang +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +index 3d9f07d4770b..8a0de6bfc716 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +@@ -892,7 +892,7 @@ static const struct dc_debug_options debug_defaults_drv = { + .enable_sw_cntl_psr = true, + .apply_vendor_specific_lttpr_wa = true, + .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ +- .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, ++ .dml_hostvm_override = DML_HOSTVM_NO_OVERRIDE, + }; + + static const struct dc_debug_options debug_defaults_diags = { +-- +2.35.1 + diff --git a/queue-5.19/drm-amd-display-fix-array-bounds-error-in-dc_stream_.patch b/queue-5.19/drm-amd-display-fix-array-bounds-error-in-dc_stream_.patch new file mode 100644 index 00000000000..da58683eb8f --- /dev/null +++ b/queue-5.19/drm-amd-display-fix-array-bounds-error-in-dc_stream_.patch @@ -0,0 +1,54 @@ +From 0ccf890efd910a6bc77d06b49198e789a09733d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 15:01:46 -0400 +Subject: drm/amd/display: fix array-bounds error in + dc_stream_remove_writeback() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hamza Mahfooz + +[ Upstream commit 5d8c3e836fc224dfe633e41f7f2856753b39a905 ] + +Address the following error: +drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_stream.c: In function ‘dc_stream_remove_writeback’: +drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_stream.c:527:55: error: array subscript [0, 0] is outside array bounds of ‘struct dc_writeback_info[1]’ [-Werror=array-bounds] + 527 | stream->writeback_info[j] = stream->writeback_info[i]; + | ~~~~~~~~~~~~~~~~~~~~~~^~~ +In file included from ./drivers/gpu/drm/amd/amdgpu/../display/dc/dc.h:1269, + from ./drivers/gpu/drm/amd/amdgpu/../display/dc/inc/core_types.h:29, + from ./drivers/gpu/drm/amd/amdgpu/../display/dc/basics/dc_common.h:29, + from drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_stream.c:27: +./drivers/gpu/drm/amd/amdgpu/../display/dc/dc_stream.h:241:34: note: while referencing ‘writeback_info’ + 241 | struct dc_writeback_info writeback_info[MAX_DWB_PIPES]; + | + +Currently, we aren't checking to see if j remains within +writeback_info[]'s bounds. So, add a check to make sure that we aren't +overflowing the buffer. + +Reviewed-by: Aurabindo Pillai +Signed-off-by: Hamza Mahfooz +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +index de8b214132a2..5e460b16d650 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +@@ -516,7 +516,7 @@ bool dc_stream_remove_writeback(struct dc *dc, + } + + /* remove writeback info for disabled writeback pipes from stream */ +- for (i = 0, j = 0; i < stream->num_wb_info; i++) { ++ for (i = 0, j = 0; i < stream->num_wb_info && j < MAX_DWB_PIPES; i++) { + if (stream->writeback_info[i].wb_enabled) { + if (i != j) + /* trim the array */ +-- +2.35.1 + diff --git a/queue-5.19/drm-amd-display-fix-overflow-on-min_i64-definition.patch b/queue-5.19/drm-amd-display-fix-overflow-on-min_i64-definition.patch new file mode 100644 index 00000000000..e520c40223c --- /dev/null +++ b/queue-5.19/drm-amd-display-fix-overflow-on-min_i64-definition.patch @@ -0,0 +1,57 @@ +From 926cdfe6e6aa488c3409cd720c0b67b17ac857c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 17:43:26 -0300 +Subject: drm/amd/display: fix overflow on MIN_I64 definition +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Gow + +[ Upstream commit 6ae0632d17759852c07e2d1e0a31c728eb6ba246 ] + +The definition of MIN_I64 in bw_fixed.c can cause gcc to whinge about +integer overflow, because it is treated as a positive value, which is +then negated. The temporary positive value is not necessarily +representable. + +This causes the following warning: +../drivers/gpu/drm/amd/amdgpu/../display/dc/dml/calcs/bw_fixed.c:30:19: +warning: integer overflow in expression ‘-9223372036854775808’ of type +‘long long int’ results in ‘-9223372036854775808’ [-Woverflow] + 30 | (int64_t)(-(1LL << 63)) + | ^ + +Writing out (-MAX_I64 - 1) works instead. + +Signed-off-by: David Gow +Signed-off-by: Tales Aparecida +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c +index 6ca288fb5fb9..2d46bc527b21 100644 +--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c ++++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c +@@ -26,12 +26,12 @@ + #include "bw_fixed.h" + + +-#define MIN_I64 \ +- (int64_t)(-(1LL << 63)) +- + #define MAX_I64 \ + (int64_t)((1ULL << 63) - 1) + ++#define MIN_I64 \ ++ (-MAX_I64 - 1) ++ + #define FRACTIONAL_PART_MASK \ + ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1) + +-- +2.35.1 + diff --git a/queue-5.19/drm-amd-display-polling-vid-stream-status-in-hpo-dp-.patch b/queue-5.19/drm-amd-display-polling-vid-stream-status-in-hpo-dp-.patch new file mode 100644 index 00000000000..b16c84dcec0 --- /dev/null +++ b/queue-5.19/drm-amd-display-polling-vid-stream-status-in-hpo-dp-.patch @@ -0,0 +1,44 @@ +From 37029554cef8961e32555a3c02f955c3b1fc1445 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 15:23:38 -0400 +Subject: drm/amd/display: polling vid stream status in hpo dp blank + +From: Wenjing Liu + +[ Upstream commit e32df0c7ecead95d70ca89f39b1b2b02a59ff691 ] + +[why] +vid stream control is double bufferred, if we don't wait for video +stream enable set to 0, we may get temporary image corruption +showing on the stream when setting PIXEL_TO_SYMBOL_FIFO_ENABLE to 0. + +Reviewed-by: Ariel Bernstein +Acked-by: Jasdeep Dhillon +Signed-off-by: Wenjing Liu +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +index 23621ff08c90..52fb2bf3d578 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +@@ -150,9 +150,9 @@ static void dcn31_hpo_dp_stream_enc_dp_blank( + * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode + + * a little more because we may not trust delay accuracy. + */ +- //REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, +- // VID_STREAM_STATUS, 0, +- // 10, 5000); ++ REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, ++ VID_STREAM_STATUS, 0, ++ 10, 5000); + + /* Disable SDP tranmission */ + REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, +-- +2.35.1 + diff --git a/queue-5.19/drm-amd-display-remove-interface-for-periodic-interr.patch b/queue-5.19/drm-amd-display-remove-interface-for-periodic-interr.patch new file mode 100644 index 00000000000..d4ced1d240c --- /dev/null +++ b/queue-5.19/drm-amd-display-remove-interface-for-periodic-interr.patch @@ -0,0 +1,205 @@ +From dcece38573c3618e04906e2b5183005a833ff8eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 18:07:59 -0400 +Subject: drm/amd/display: Remove interface for periodic interrupt 1 + +From: Aric Cyr + +[ Upstream commit 97d8d6f075bd8f988589be02b91f6fa644d0b0b8 ] + +[why] +Only a single VLINE interrupt is available so interface should not +expose the second one which is used by DMU firmware. + +[how] +Remove references to periodic_interrupt1 and VLINE1 from DC interfaces. + +Reviewed-by: Jaehyun Chung +Acked-by: Jasdeep Dhillon +Signed-off-by: Aric Cyr +Tested-by: Daniel Wheeler +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +++------ + drivers/gpu/drm/amd/display/dc/dc_stream.h | 6 ++-- + .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 35 ++++++------------- + .../amd/display/dc/dcn10/dcn10_hw_sequencer.h | 3 +- + .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 8 +---- + 5 files changed, 18 insertions(+), 50 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index 9dbd965d8afb..6ca29b887fce 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -2632,11 +2632,8 @@ static void copy_stream_update_to_stream(struct dc *dc, + if (update->abm_level) + stream->abm_level = *update->abm_level; + +- if (update->periodic_interrupt0) +- stream->periodic_interrupt0 = *update->periodic_interrupt0; +- +- if (update->periodic_interrupt1) +- stream->periodic_interrupt1 = *update->periodic_interrupt1; ++ if (update->periodic_interrupt) ++ stream->periodic_interrupt = *update->periodic_interrupt; + + if (update->gamut_remap) + stream->gamut_remap_matrix = *update->gamut_remap; +@@ -2723,13 +2720,8 @@ static void commit_planes_do_stream_update(struct dc *dc, + + if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) { + +- if (stream_update->periodic_interrupt0 && +- dc->hwss.setup_periodic_interrupt) +- dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0); +- +- if (stream_update->periodic_interrupt1 && +- dc->hwss.setup_periodic_interrupt) +- dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1); ++ if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt) ++ dc->hwss.setup_periodic_interrupt(dc, pipe_ctx); + + if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || + stream_update->vrr_infopacket || +diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h +index 58941f4defb3..a7f319d404a1 100644 +--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h ++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h +@@ -200,8 +200,7 @@ struct dc_stream_state { + /* DMCU info */ + unsigned int abm_level; + +- struct periodic_interrupt_config periodic_interrupt0; +- struct periodic_interrupt_config periodic_interrupt1; ++ struct periodic_interrupt_config periodic_interrupt; + + /* from core_stream struct */ + struct dc_context *ctx; +@@ -268,8 +267,7 @@ struct dc_stream_update { + struct dc_info_packet *hdr_static_metadata; + unsigned int *abm_level; + +- struct periodic_interrupt_config *periodic_interrupt0; +- struct periodic_interrupt_config *periodic_interrupt1; ++ struct periodic_interrupt_config *periodic_interrupt; + + struct dc_info_packet *vrr_infopacket; + struct dc_info_packet *vsc_infopacket; +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 d9ab27991535..33c87e53b6a3 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 +@@ -3623,7 +3623,7 @@ void dcn10_calc_vupdate_position( + { + const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing; + int vline_int_offset_from_vupdate = +- pipe_ctx->stream->periodic_interrupt0.lines_offset; ++ pipe_ctx->stream->periodic_interrupt.lines_offset; + int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx); + int start_position; + +@@ -3648,18 +3648,10 @@ void dcn10_calc_vupdate_position( + static void dcn10_cal_vline_position( + struct dc *dc, + struct pipe_ctx *pipe_ctx, +- enum vline_select vline, + uint32_t *start_line, + uint32_t *end_line) + { +- enum vertical_interrupt_ref_point ref_point = INVALID_POINT; +- +- if (vline == VLINE0) +- ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point; +- else if (vline == VLINE1) +- ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point; +- +- switch (ref_point) { ++ switch (pipe_ctx->stream->periodic_interrupt.ref_point) { + case START_V_UPDATE: + dcn10_calc_vupdate_position( + dc, +@@ -3668,7 +3660,9 @@ static void dcn10_cal_vline_position( + end_line); + break; + case START_V_SYNC: +- // Suppose to do nothing because vsync is 0; ++ // vsync is line 0 so start_line is just the requested line offset ++ *start_line = pipe_ctx->stream->periodic_interrupt.lines_offset; ++ *end_line = *start_line + 2; + break; + default: + ASSERT(0); +@@ -3678,24 +3672,15 @@ static void dcn10_cal_vline_position( + + void dcn10_setup_periodic_interrupt( + struct dc *dc, +- struct pipe_ctx *pipe_ctx, +- enum vline_select vline) ++ struct pipe_ctx *pipe_ctx) + { + struct timing_generator *tg = pipe_ctx->stream_res.tg; ++ uint32_t start_line = 0; ++ uint32_t end_line = 0; + +- if (vline == VLINE0) { +- uint32_t start_line = 0; +- uint32_t end_line = 0; ++ dcn10_cal_vline_position(dc, pipe_ctx, &start_line, &end_line); + +- dcn10_cal_vline_position(dc, pipe_ctx, vline, &start_line, &end_line); +- +- tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line); +- +- } else if (vline == VLINE1) { +- pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1( +- tg, +- pipe_ctx->stream->periodic_interrupt1.lines_offset); +- } ++ tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line); + } + + void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx) +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +index 9ae07c77fdc0..0ef7bf7ddb75 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +@@ -175,8 +175,7 @@ void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx); + void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx); + void dcn10_setup_periodic_interrupt( + struct dc *dc, +- struct pipe_ctx *pipe_ctx, +- enum vline_select vline); ++ struct pipe_ctx *pipe_ctx); + enum dc_status dcn10_set_clock(struct dc *dc, + enum dc_clock_type clock_type, + uint32_t clk_khz, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +index 05053f3b4ab7..21a9eedec092 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +@@ -32,11 +32,6 @@ + #include "inc/hw/link_encoder.h" + #include "core_status.h" + +-enum vline_select { +- VLINE0, +- VLINE1 +-}; +- + struct pipe_ctx; + struct dc_state; + struct dc_stream_status; +@@ -116,8 +111,7 @@ struct hw_sequencer_funcs { + int group_index, int group_size, + struct pipe_ctx *grouped_pipes[]); + void (*setup_periodic_interrupt)(struct dc *dc, +- struct pipe_ctx *pipe_ctx, +- enum vline_select vline); ++ struct pipe_ctx *pipe_ctx); + void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes, + struct dc_crtc_timing_adjust adjust); + void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, +-- +2.35.1 + diff --git a/queue-5.19/drm-amdgpu-add-missing-pci_disable_device-in-amdgpu_.patch b/queue-5.19/drm-amdgpu-add-missing-pci_disable_device-in-amdgpu_.patch new file mode 100644 index 00000000000..5f1a59e82e4 --- /dev/null +++ b/queue-5.19/drm-amdgpu-add-missing-pci_disable_device-in-amdgpu_.patch @@ -0,0 +1,40 @@ +From 77a729dd487a9e022576296371ce1005c49fa627 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 16:57:54 +0800 +Subject: drm/amdgpu: add missing pci_disable_device() in + amdgpu_pmops_runtime_resume() + +From: Yang Yingliang + +[ Upstream commit 6b11af6d1c8f5d4135332bb932baaa06e511173d ] + +Add missing pci_disable_device() if amdgpu_device_resume() fails. + +Fixes: 8e4d5d43cc6c ("drm/amdgpu: Handling of amdgpu_device_resume return value for graceful teardown") +Signed-off-by: Yang Yingliang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index 8890300766a5..5e8ca32bc3a9 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -2548,8 +2548,11 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) + amdgpu_device_baco_exit(drm_dev); + } + ret = amdgpu_device_resume(drm_dev, false); +- if (ret) ++ if (ret) { ++ if (amdgpu_device_supports_px(drm_dev)) ++ pci_disable_device(pdev); + return ret; ++ } + + if (amdgpu_device_supports_px(drm_dev)) + drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; +-- +2.35.1 + diff --git a/queue-5.19/drm-amdgpu-fix-initial-connector-audio-value.patch b/queue-5.19/drm-amdgpu-fix-initial-connector-audio-value.patch new file mode 100644 index 00000000000..092c805756a --- /dev/null +++ b/queue-5.19/drm-amdgpu-fix-initial-connector-audio-value.patch @@ -0,0 +1,64 @@ +From fe0b38e949720cb5ad7276fa09a7875b211c060c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 17:24:53 +0800 +Subject: drm/amdgpu: fix initial connector audio value + +From: hongao + +[ Upstream commit 4bb71fce58f30df3f251118291d6b0187ce531e6 ] + +This got lost somewhere along the way, This fixes +audio not working until set_property was called. + +Signed-off-by: hongao +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +index b7933c2ce765..491d4846fc02 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +@@ -1674,10 +1674,12 @@ amdgpu_connector_add(struct amdgpu_device *adev, + adev->mode_info.dither_property, + AMDGPU_FMT_DITHER_DISABLE); + +- if (amdgpu_audio != 0) ++ if (amdgpu_audio != 0) { + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.audio_property, + AMDGPU_AUDIO_AUTO); ++ amdgpu_connector->audio = AMDGPU_AUDIO_AUTO; ++ } + + subpixel_order = SubPixelHorizontalRGB; + connector->interlace_allowed = true; +@@ -1799,6 +1801,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.audio_property, + AMDGPU_AUDIO_AUTO); ++ amdgpu_connector->audio = AMDGPU_AUDIO_AUTO; + } + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.dither_property, +@@ -1852,6 +1855,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.audio_property, + AMDGPU_AUDIO_AUTO); ++ amdgpu_connector->audio = AMDGPU_AUDIO_AUTO; + } + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.dither_property, +@@ -1902,6 +1906,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.audio_property, + AMDGPU_AUDIO_AUTO); ++ amdgpu_connector->audio = AMDGPU_AUDIO_AUTO; + } + drm_object_attach_property(&amdgpu_connector->base.base, + adev->mode_info.dither_property, +-- +2.35.1 + diff --git a/queue-5.19/drm-amdgpu-fix-memory-leak-in-hpd_rx_irq_create_work.patch b/queue-5.19/drm-amdgpu-fix-memory-leak-in-hpd_rx_irq_create_work.patch new file mode 100644 index 00000000000..db27571bed7 --- /dev/null +++ b/queue-5.19/drm-amdgpu-fix-memory-leak-in-hpd_rx_irq_create_work.patch @@ -0,0 +1,51 @@ +From a428b0e30dff9ea5e0f64e328801e997c015e499 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 19:34:32 -0300 +Subject: drm/amdgpu: Fix memory leak in hpd_rx_irq_create_workqueue() + +From: Rafael Mendonca + +[ Upstream commit 7136f956c73c4ba50bfeb61653dfd6a9669ea915 ] + +If construction of the array of work queues to handle hpd_rx_irq offload +work fails, we need to unwind. Destroy all the created workqueues and +the allocated memory for the hpd_rx_irq_offload_work_queue struct array. + +Fixes: 8e794421bc98 ("drm/amd/display: Fork thread to offload work of hpd_rx_irq") +Signed-off-by: Rafael Mendonca +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index d752aadd34bf..612970a9fe65 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -1363,13 +1363,21 @@ static struct hpd_rx_irq_offload_work_queue *hpd_rx_irq_create_workqueue(struct + + if (hpd_rx_offload_wq[i].wq == NULL) { + DRM_ERROR("create amdgpu_dm_hpd_rx_offload_wq fail!"); +- return NULL; ++ goto out_err; + } + + spin_lock_init(&hpd_rx_offload_wq[i].offload_lock); + } + + return hpd_rx_offload_wq; ++ ++out_err: ++ for (i = 0; i < max_caps; i++) { ++ if (hpd_rx_offload_wq[i].wq) ++ destroy_workqueue(hpd_rx_offload_wq[i].wq); ++ } ++ kfree(hpd_rx_offload_wq); ++ return NULL; + } + + struct amdgpu_stutter_quirk { +-- +2.35.1 + diff --git a/queue-5.19/drm-amdgpu-sdma-update-use-unlocked-iterator.patch b/queue-5.19/drm-amdgpu-sdma-update-use-unlocked-iterator.patch new file mode 100644 index 00000000000..d80798883d1 --- /dev/null +++ b/queue-5.19/drm-amdgpu-sdma-update-use-unlocked-iterator.patch @@ -0,0 +1,63 @@ +From 3963d525068f485d7af22cd4cc905abf72cd1add Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 15:46:30 -0400 +Subject: drm/amdgpu: SDMA update use unlocked iterator +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Philip Yang + +[ Upstream commit 3913f0179ba366f7d7d160c506ce00de1602bbc4 ] + +SDMA update page table may be called from unlocked context, this +generate below warning. Use unlocked iterator to handle this case. + +WARNING: CPU: 0 PID: 1475 at +drivers/dma-buf/dma-resv.c:483 dma_resv_iter_next +Call Trace: + dma_resv_iter_first+0x43/0xa0 + amdgpu_vm_sdma_update+0x69/0x2d0 [amdgpu] + amdgpu_vm_ptes_update+0x29c/0x870 [amdgpu] + amdgpu_vm_update_range+0x2f6/0x6c0 [amdgpu] + svm_range_unmap_from_gpus+0x115/0x300 [amdgpu] + svm_range_cpu_invalidate_pagetables+0x510/0x5e0 [amdgpu] + __mmu_notifier_invalidate_range_start+0x1d3/0x230 + unmap_vmas+0x140/0x150 + unmap_region+0xa8/0x110 + +Signed-off-by: Philip Yang +Suggested-by: Felix Kuehling +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +index 1fd3cbca20a2..718db7d98e5a 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +@@ -211,12 +211,15 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p, + int r; + + /* Wait for PD/PT moves to be completed */ +- dma_resv_for_each_fence(&cursor, bo->tbo.base.resv, +- DMA_RESV_USAGE_KERNEL, fence) { ++ dma_resv_iter_begin(&cursor, bo->tbo.base.resv, DMA_RESV_USAGE_KERNEL); ++ dma_resv_for_each_fence_unlocked(&cursor, fence) { + r = amdgpu_sync_fence(&p->job->sync, fence); +- if (r) ++ if (r) { ++ dma_resv_iter_end(&cursor); + return r; ++ } + } ++ dma_resv_iter_end(&cursor); + + do { + ndw = p->num_dw_left; +-- +2.35.1 + diff --git a/queue-5.19/drm-amdgpu-skip-the-program-of-mmmc_vm_agp_-in-sriov.patch b/queue-5.19/drm-amdgpu-skip-the-program-of-mmmc_vm_agp_-in-sriov.patch new file mode 100644 index 00000000000..93e3aa7c146 --- /dev/null +++ b/queue-5.19/drm-amdgpu-skip-the-program-of-mmmc_vm_agp_-in-sriov.patch @@ -0,0 +1,59 @@ +From f7f6642c36059880284baaaac33520f13cd954f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 13:43:50 +0800 +Subject: drm/amdgpu: Skip the program of MMMC_VM_AGP_* in SRIOV on MMHUB + v3_0_0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yifan Zha + +[ Upstream commit c1026c6f319724dc88fc08d9d9d35bcbdf492b42 ] + +[Why] +VF should not program these registers, the value were defined in the host. + +[How] +Skip writing them in SRIOV environment and program them on host side. + +Acked-by: Christian König +Signed-off-by: Yifan Zha +Signed-off-by: Horace Chen +Reviewed-by: Hawking Zhang +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c +index bc11b2de37ae..a1d26c4d80b8 100644 +--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c ++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c +@@ -169,17 +169,17 @@ static void mmhub_v3_0_init_system_aperture_regs(struct amdgpu_device *adev) + uint64_t value; + uint32_t tmp; + +- /* Disable AGP. */ +- WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BASE, 0); +- WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, 0); +- WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, 0x00FFFFFF); +- + if (!amdgpu_sriov_vf(adev)) { + /* + * the new L1 policy will block SRIOV guest from writing + * these regs, and they will be programed at host. + * so skip programing these regs. + */ ++ /* Disable AGP. */ ++ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BASE, 0); ++ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_TOP, 0); ++ WREG32_SOC15(MMHUB, 0, regMMMC_VM_AGP_BOT, 0x00FFFFFF); ++ + /* Program the system aperture low logical page number. */ + WREG32_SOC15(MMHUB, 0, regMMMC_VM_SYSTEM_APERTURE_LOW_ADDR, + adev->gmc.vram_start >> 18); +-- +2.35.1 + diff --git a/queue-5.19/drm-amdkfd-fix-ubsan-shift-out-of-bounds-warning.patch b/queue-5.19/drm-amdkfd-fix-ubsan-shift-out-of-bounds-warning.patch new file mode 100644 index 00000000000..5c70de392f1 --- /dev/null +++ b/queue-5.19/drm-amdkfd-fix-ubsan-shift-out-of-bounds-warning.patch @@ -0,0 +1,106 @@ +From d15215d51f777dafb42c122681ea7af4baa245de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 17:45:59 -0400 +Subject: drm/amdkfd: Fix UBSAN shift-out-of-bounds warning + +From: Felix Kuehling + +[ Upstream commit b292cafe2dd02d96a07147e4b160927e8399d5cc ] + +This was fixed in initialize_cpsch before, but not in initialize_nocpsch. +Factor sdma bitmap initialization into a helper function to apply the +correct implementation in both cases without duplicating it. + +v2: Added a range check + +Reported-by: Ellis Michael +Signed-off-by: Felix Kuehling +Reviewed-by: Graham Sider +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + .../drm/amd/amdkfd/kfd_device_queue_manager.c | 45 +++++++++---------- + 1 file changed, 21 insertions(+), 24 deletions(-) + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +index e1797657b04c..7d3fc5849466 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +@@ -1232,6 +1232,24 @@ static void init_interrupts(struct device_queue_manager *dqm) + dqm->dev->kfd2kgd->init_interrupts(dqm->dev->adev, i); + } + ++static void init_sdma_bitmaps(struct device_queue_manager *dqm) ++{ ++ unsigned int num_sdma_queues = ++ min_t(unsigned int, sizeof(dqm->sdma_bitmap)*8, ++ get_num_sdma_queues(dqm)); ++ unsigned int num_xgmi_sdma_queues = ++ min_t(unsigned int, sizeof(dqm->xgmi_sdma_bitmap)*8, ++ get_num_xgmi_sdma_queues(dqm)); ++ ++ if (num_sdma_queues) ++ dqm->sdma_bitmap = GENMASK_ULL(num_sdma_queues-1, 0); ++ if (num_xgmi_sdma_queues) ++ dqm->xgmi_sdma_bitmap = GENMASK_ULL(num_xgmi_sdma_queues-1, 0); ++ ++ dqm->sdma_bitmap &= ~get_reserved_sdma_queues_bitmap(dqm); ++ pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap); ++} ++ + static int initialize_nocpsch(struct device_queue_manager *dqm) + { + int pipe, queue; +@@ -1260,11 +1278,7 @@ static int initialize_nocpsch(struct device_queue_manager *dqm) + + memset(dqm->vmid_pasid, 0, sizeof(dqm->vmid_pasid)); + +- dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm)); +- dqm->sdma_bitmap &= ~(get_reserved_sdma_queues_bitmap(dqm)); +- pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap); +- +- dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm)); ++ init_sdma_bitmaps(dqm); + + return 0; + } +@@ -1442,9 +1456,6 @@ static int set_sched_resources(struct device_queue_manager *dqm) + + static int initialize_cpsch(struct device_queue_manager *dqm) + { +- uint64_t num_sdma_queues; +- uint64_t num_xgmi_sdma_queues; +- + pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm)); + + mutex_init(&dqm->lock_hidden); +@@ -1453,24 +1464,10 @@ static int initialize_cpsch(struct device_queue_manager *dqm) + dqm->active_cp_queue_count = 0; + dqm->gws_queue_count = 0; + dqm->active_runlist = false; +- +- num_sdma_queues = get_num_sdma_queues(dqm); +- if (num_sdma_queues >= BITS_PER_TYPE(dqm->sdma_bitmap)) +- dqm->sdma_bitmap = ULLONG_MAX; +- else +- dqm->sdma_bitmap = (BIT_ULL(num_sdma_queues) - 1); +- +- dqm->sdma_bitmap &= ~(get_reserved_sdma_queues_bitmap(dqm)); +- pr_info("sdma_bitmap: %llx\n", dqm->sdma_bitmap); +- +- num_xgmi_sdma_queues = get_num_xgmi_sdma_queues(dqm); +- if (num_xgmi_sdma_queues >= BITS_PER_TYPE(dqm->xgmi_sdma_bitmap)) +- dqm->xgmi_sdma_bitmap = ULLONG_MAX; +- else +- dqm->xgmi_sdma_bitmap = (BIT_ULL(num_xgmi_sdma_queues) - 1); +- + INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception); + ++ init_sdma_bitmaps(dqm); ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/drm-bochs-fix-blanking.patch b/queue-5.19/drm-bochs-fix-blanking.patch new file mode 100644 index 00000000000..a3056b922b7 --- /dev/null +++ b/queue-5.19/drm-bochs-fix-blanking.patch @@ -0,0 +1,43 @@ +From d8883f13ba12811d6b81ed1b66547b2aa230b5c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 16:29:57 +0200 +Subject: drm/bochs: fix blanking + +From: Gerd Hoffmann + +[ Upstream commit e740ceb53e4579a7a4063712cebecac3c343b189 ] + +VGA_IS1_RC is the color mode register (VGA_IS1_RM the one for monochrome +mode, note C vs. M at the end). So when using VGA_IS1_RC make sure the +vga device is actually in color mode and set the corresponding bit in the +misc register. + +Reproducible when booting VMs in UEFI mode with some edk2 versions (edk2 +fix is on the way too). Doesn't happen in BIOS mode because in that +case the vgabios already flips the bit. + +Fixes: 250e743915d4 ("drm/bochs: Add screen blanking support") +Signed-off-by: Gerd Hoffmann +Acked-by: Thomas Zimmermann +Link: http://patchwork.freedesktop.org/patch/msgid/20220906142957.2763577-1-kraxel@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tiny/bochs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c +index ed971c8bb446..0cedb6f6f559 100644 +--- a/drivers/gpu/drm/tiny/bochs.c ++++ b/drivers/gpu/drm/tiny/bochs.c +@@ -306,6 +306,8 @@ static void bochs_hw_fini(struct drm_device *dev) + static void bochs_hw_blank(struct bochs_device *bochs, bool blank) + { + DRM_DEBUG_DRIVER("hw_blank %d\n", blank); ++ /* enable color bit (so VGA_IS1_RC access works) */ ++ bochs_vga_writeb(bochs, VGA_MIS_W, VGA_MIS_COLOR); + /* discard ar_flip_flop */ + (void)bochs_vga_readb(bochs, VGA_IS1_RC); + /* blank or unblank; we need only update index and set 0x20 */ +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-adv7511-fix-cec-power-down-control-regist.patch b/queue-5.19/drm-bridge-adv7511-fix-cec-power-down-control-regist.patch new file mode 100644 index 00000000000..90f83bab5bd --- /dev/null +++ b/queue-5.19/drm-bridge-adv7511-fix-cec-power-down-control-regist.patch @@ -0,0 +1,69 @@ +From aba3f1d0251d0e569c9f90cb9f97c5056ffda97f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jun 2022 16:48:53 +0200 +Subject: drm: bridge: adv7511: fix CEC power down control register offset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alvin Å ipraga + +[ Upstream commit 1d22b6033ea113a4c3850dfa2c0770885c81aec8 ] + +The ADV7511_REG_CEC_CTRL = 0xE2 register is part of the main register +map - not the CEC register map. As such, we shouldn't apply an offset to +the register address. Doing so will cause us to address a bogus register +for chips with a CEC register map offset (e.g. ADV7533). + +Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") +Signed-off-by: Alvin Å ipraga +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220612144854.2223873-2-alvin@pqrs.dk +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/adv7511/adv7511.h | 5 +---- + drivers/gpu/drm/bridge/adv7511/adv7511_cec.c | 4 ++-- + 2 files changed, 3 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h +index a031a0cd1f18..94de73cbeb2d 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h +@@ -394,10 +394,7 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1); + #else + static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) + { +- unsigned int offset = adv7511->type == ADV7533 ? +- ADV7533_REG_CEC_OFFSET : 0; +- +- regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, ++ regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, + ADV7511_CEC_CTRL_POWER_DOWN); + return 0; + } +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +index 0b266f28f150..99964f5a5457 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c +@@ -359,7 +359,7 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) + goto err_cec_alloc; + } + +- regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0); ++ regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0); + /* cec soft reset */ + regmap_write(adv7511->regmap_cec, + ADV7511_REG_CEC_SOFT_RESET + offset, 0x01); +@@ -386,7 +386,7 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511) + dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n", + ret); + err_cec_parse_dt: +- regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, ++ regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, + ADV7511_CEC_CTRL_POWER_DOWN); + return ret == -EPROBE_DEFER ? ret : 0; + } +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-adv7511-unregister-cec-i2c-device-after-c.patch b/queue-5.19/drm-bridge-adv7511-unregister-cec-i2c-device-after-c.patch new file mode 100644 index 00000000000..dab70bfcac5 --- /dev/null +++ b/queue-5.19/drm-bridge-adv7511-unregister-cec-i2c-device-after-c.patch @@ -0,0 +1,85 @@ +From b01af8485521381b06fff4cf8b2a02f84ec172b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jun 2022 16:48:54 +0200 +Subject: drm: bridge: adv7511: unregister cec i2c device after cec adapter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alvin Å ipraga + +[ Upstream commit 40cdb02cb9f965732eb543d47f15bef8d10f0f5f ] + +cec_unregister_adapter() assumes that the underlying adapter ops are +callable. For example, if the CEC adapter currently has a valid physical +address, then the unregistration procedure will invalidate the physical +address by setting it to f.f.f.f. Whence the following kernel oops +observed after removing the adv7511 module: + + Unable to handle kernel execution of user memory at virtual address 0000000000000000 + Internal error: Oops: 86000004 [#1] PREEMPT_RT SMP + Call trace: + 0x0 + adv7511_cec_adap_log_addr+0x1ac/0x1c8 [adv7511] + cec_adap_unconfigure+0x44/0x90 [cec] + __cec_s_phys_addr.part.0+0x68/0x230 [cec] + __cec_s_phys_addr+0x40/0x50 [cec] + cec_unregister_adapter+0xb4/0x118 [cec] + adv7511_remove+0x60/0x90 [adv7511] + i2c_device_remove+0x34/0xe0 + device_release_driver_internal+0x114/0x1f0 + driver_detach+0x54/0xe0 + bus_remove_driver+0x60/0xd8 + driver_unregister+0x34/0x60 + i2c_del_driver+0x2c/0x68 + adv7511_exit+0x1c/0x67c [adv7511] + __arm64_sys_delete_module+0x154/0x288 + invoke_syscall+0x48/0x100 + el0_svc_common.constprop.0+0x48/0xe8 + do_el0_svc+0x28/0x88 + el0_svc+0x1c/0x50 + el0t_64_sync_handler+0xa8/0xb0 + el0t_64_sync+0x15c/0x160 + Code: bad PC value + ---[ end trace 0000000000000000 ]--- + +Protect against this scenario by unregistering i2c_cec after +unregistering the CEC adapter. Duly disable the CEC clock afterwards +too. + +Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") +Signed-off-by: Alvin Å ipraga +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220612144854.2223873-3-alvin@pqrs.dk +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +index 38bf28720f3a..6031bdd92342 100644 +--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c ++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +@@ -1340,9 +1340,6 @@ static int adv7511_remove(struct i2c_client *i2c) + { + struct adv7511 *adv7511 = i2c_get_clientdata(i2c); + +- i2c_unregister_device(adv7511->i2c_cec); +- clk_disable_unprepare(adv7511->cec_clk); +- + adv7511_uninit_regulators(adv7511); + + drm_bridge_remove(&adv7511->bridge); +@@ -1350,6 +1347,8 @@ static int adv7511_remove(struct i2c_client *i2c) + adv7511_audio_exit(adv7511); + + cec_unregister_adapter(adv7511->cec_adap); ++ i2c_unregister_device(adv7511->i2c_cec); ++ clk_disable_unprepare(adv7511->cec_clk); + + i2c_unregister_device(adv7511->i2c_packet); + i2c_unregister_device(adv7511->i2c_edid); +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-avoid-uninitialized-variable-warning.patch b/queue-5.19/drm-bridge-avoid-uninitialized-variable-warning.patch new file mode 100644 index 00000000000..989afac0634 --- /dev/null +++ b/queue-5.19/drm-bridge-avoid-uninitialized-variable-warning.patch @@ -0,0 +1,49 @@ +From f19b30ec47772088418fa1b304b482137623328d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 13:55:40 +0300 +Subject: drm/bridge: Avoid uninitialized variable warning + +From: Dan Carpenter + +[ Upstream commit 7d1202738efda60155d98b370b3c70d336be0eea ] + +This code works, but technically it uses "num_in_bus_fmts" before it +has been initialized so it leads to static checker warnings and probably +KMEMsan warnings at run time. Initialize the variable to zero to +silence the warning. + +Fixes: f32df58acc68 ("drm/bridge: Add the necessary bits to support bus format negotiation") +Signed-off-by: Dan Carpenter +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/YrrIs3hoGcPVmXc5@kili +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_bridge.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c +index c96847fc0ebc..36ca4092c1ab 100644 +--- a/drivers/gpu/drm/drm_bridge.c ++++ b/drivers/gpu/drm/drm_bridge.c +@@ -823,8 +823,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, + struct drm_connector_state *conn_state, + u32 out_bus_fmt) + { ++ unsigned int i, num_in_bus_fmts = 0; + struct drm_bridge_state *cur_state; +- unsigned int num_in_bus_fmts, i; + struct drm_bridge *prev_bridge; + u32 *in_bus_fmts; + int ret; +@@ -945,7 +945,7 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge, + struct drm_connector *conn = conn_state->connector; + struct drm_encoder *encoder = bridge->encoder; + struct drm_bridge_state *last_bridge_state; +- unsigned int i, num_out_bus_fmts; ++ unsigned int i, num_out_bus_fmts = 0; + struct drm_bridge *last_bridge; + u32 *out_bus_fmts; + int ret = 0; +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-dw_hdmi-only-trigger-hotplug-event-on-lin.patch b/queue-5.19/drm-bridge-dw_hdmi-only-trigger-hotplug-event-on-lin.patch new file mode 100644 index 00000000000..322f69516ed --- /dev/null +++ b/queue-5.19/drm-bridge-dw_hdmi-only-trigger-hotplug-event-on-lin.patch @@ -0,0 +1,65 @@ +From 3bfe61f1efa92d6173162e6e62ef94289f7d8c20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 20:57:33 +0200 +Subject: drm: bridge: dw_hdmi: only trigger hotplug event on link change + +From: Lucas Stach + +[ Upstream commit da09daf881082266e4075657fac53c7966de8e4d ] + +There are two events that signal a real change of the link state: HPD going +high means the sink is newly connected or wants the source to re-read the +EDID, RX sense going low is a indication that the link has been disconnected. + +Ignore the other two events that also trigger interrupts, but don't need +immediate attention: HPD going low does not necessarily mean the link has +been lost and should not trigger a immediate read of the status. RX sense +going high also does not require a detect cycle, as HPD going high is the +right point in time to read the EDID. + +Signed-off-by: Lucas Stach +Reviewed-by: Neil Armstrong (v1) +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220826185733.3213248-1-l.stach@pengutronix.de +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +index 3e1be9894ed1..0552e9a3c838 100644 +--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ++++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +@@ -3095,6 +3095,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) + { + struct dw_hdmi *hdmi = dev_id; + u8 intr_stat, phy_int_pol, phy_pol_mask, phy_stat; ++ enum drm_connector_status status = connector_status_unknown; + + intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0); + phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); +@@ -3133,13 +3134,15 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id) + cec_notifier_phys_addr_invalidate(hdmi->cec_notifier); + mutex_unlock(&hdmi->cec_notifier_mutex); + } +- } + +- if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { +- enum drm_connector_status status = phy_int_pol & HDMI_PHY_HPD +- ? connector_status_connected +- : connector_status_disconnected; ++ if (phy_stat & HDMI_PHY_HPD) ++ status = connector_status_connected; ++ ++ if (!(phy_stat & (HDMI_PHY_HPD | HDMI_PHY_RX_SENSE))) ++ status = connector_status_disconnected; ++ } + ++ if (status != connector_status_unknown) { + dev_dbg(hdmi->dev, "EVENT=%s\n", + status == connector_status_connected ? + "plugin" : "plugout"); +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-it6505-fix-the-order-of-dp_set_power-comm.patch b/queue-5.19/drm-bridge-it6505-fix-the-order-of-dp_set_power-comm.patch new file mode 100644 index 00000000000..5480f1f8af1 --- /dev/null +++ b/queue-5.19/drm-bridge-it6505-fix-the-order-of-dp_set_power-comm.patch @@ -0,0 +1,61 @@ +From 134081e52c88faa0745ead62441aa13f509d66ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 12:57:56 +0800 +Subject: drm/bridge: it6505: Fix the order of DP_SET_POWER commands + +From: Pin-yen Lin + +[ Upstream commit 7c1dceaffd99247bf443606730515b54d6285969 ] + +Send DP_SET_POWER_D3 command to the downstream before stopping DP, so the +suspend process will not be interrupted by the HPD interrupt. Also modify +the order in .atomic_enable callback to make the callbacks symmetric. + +Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") +Signed-off-by: Pin-yen Lin +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220830045756.1655954-1-treapking@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/ite-it6505.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c +index e5626035f311..a09d1a39ab0a 100644 +--- a/drivers/gpu/drm/bridge/ite-it6505.c ++++ b/drivers/gpu/drm/bridge/ite-it6505.c +@@ -2945,9 +2945,6 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, + if (ret) + dev_err(dev, "Failed to setup AVI infoframe: %d", ret); + +- it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, +- DP_SET_POWER_D0); +- + it6505_update_video_parameter(it6505, mode); + + ret = it6505_send_video_infoframe(it6505, &frame); +@@ -2957,6 +2954,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, + + it6505_int_mask_enable(it6505); + it6505_video_reset(it6505); ++ ++ it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, ++ DP_SET_POWER_D0); + } + + static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, +@@ -2968,9 +2968,9 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge, + DRM_DEV_DEBUG_DRIVER(dev, "start"); + + if (it6505->powered) { +- it6505_video_disable(it6505); + it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, + DP_SET_POWER_D3); ++ it6505_video_disable(it6505); + } + } + +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-it6505-power-on-downstream-device-in-.ato.patch b/queue-5.19/drm-bridge-it6505-power-on-downstream-device-in-.ato.patch new file mode 100644 index 00000000000..b0cf10807b5 --- /dev/null +++ b/queue-5.19/drm-bridge-it6505-power-on-downstream-device-in-.ato.patch @@ -0,0 +1,42 @@ +From 6bf05679106e8748915dbb4071c14ba333d638f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Jul 2022 17:39:20 +0800 +Subject: drm/bridge: it6505: Power on downstream device in .atomic_enable + +From: Pin-Yen Lin + +[ Upstream commit fbc1fdaa8338ec4ebd862d918a0ce3e12033e8a3 ] + +Send DPCD DP_SET_POWER_D0 command to the monitor in .atomic_enable +callback. Without this command, some monitors won't show up again after +changing the resolution. + +Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") + +Signed-off-by: Pin-Yen Lin +Reviewed-by: Allen Chen +Fixes: 46ca7da7f1e8 ("drm/bridge: it6505: Send DPCD SET_POWER to downstream") +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220714173715.v2.1.I85af54e9ceda74ec69f661852825845f983fc343@changeid +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/ite-it6505.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c +index 4b673c4792d7..e5626035f311 100644 +--- a/drivers/gpu/drm/bridge/ite-it6505.c ++++ b/drivers/gpu/drm/bridge/ite-it6505.c +@@ -2945,6 +2945,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge, + if (ret) + dev_err(dev, "Failed to setup AVI infoframe: %d", ret); + ++ it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link, ++ DP_SET_POWER_D0); ++ + it6505_update_video_parameter(it6505, mode); + + ret = it6505_send_video_infoframe(it6505, &frame); +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-megachips-fix-a-null-pointer-dereference-.patch b/queue-5.19/drm-bridge-megachips-fix-a-null-pointer-dereference-.patch new file mode 100644 index 00000000000..f857814819d --- /dev/null +++ b/queue-5.19/drm-bridge-megachips-fix-a-null-pointer-dereference-.patch @@ -0,0 +1,52 @@ +From cb69fc2510d86b451ff86112a78a3f62ebff283c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:34:50 +0800 +Subject: drm/bridge: megachips: Fix a null pointer dereference bug + +From: Zheyu Ma + +[ Upstream commit 1ff673333d46d2c1b053ebd0c1c7c7c79e36943e ] + +When removing the module we will get the following warning: + +[ 31.911505] i2c-core: driver [stdp2690-ge-b850v3-fw] unregistered +[ 31.912484] general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN PTI +[ 31.913338] KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] +[ 31.915280] RIP: 0010:drm_bridge_remove+0x97/0x130 +[ 31.921825] Call Trace: +[ 31.922533] stdp4028_ge_b850v3_fw_remove+0x34/0x60 [megachips_stdpxxxx_ge_b850v3_fw] +[ 31.923139] i2c_device_remove+0x181/0x1f0 + +The two bridges (stdp2690, stdp4028) do not probe at the same time, so +the driver does not call ge_b850v3_resgiter() when probing, causing the +driver to try to remove the object that has not been initialized. + +Fix this by checking whether both the bridges are probed. + +Fixes: 11632d4aa2b3 ("drm/bridge: megachips: Ensure both bridges are probed before registration") +Signed-off-by: Zheyu Ma +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220830073450.1897020-1-zheyuma97@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +index cce98bf2a4e7..72248a565579 100644 +--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c ++++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +@@ -296,7 +296,9 @@ static void ge_b850v3_lvds_remove(void) + * This check is to avoid both the drivers + * removing the bridge in their remove() function + */ +- if (!ge_b850v3_lvds_ptr) ++ if (!ge_b850v3_lvds_ptr || ++ !ge_b850v3_lvds_ptr->stdp2690_i2c || ++ !ge_b850v3_lvds_ptr->stdp4028_i2c) + goto out; + + drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge); +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch b/queue-5.19/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch new file mode 100644 index 00000000000..88524cf3aaf --- /dev/null +++ b/queue-5.19/drm-bridge-parade-ps8640-fix-regulator-supply-order.patch @@ -0,0 +1,44 @@ +From eaca2b67441d508ebc0997fbca703f1ef82fe770 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 17:22:58 +0800 +Subject: drm/bridge: parade-ps8640: Fix regulator supply order + +From: Chen-Yu Tsai + +[ Upstream commit fc94224c2e0ae8d83ac511a3ef4962178505469d ] + +The datasheet says that VDD12 must be enabled and at full voltage before +VDD33 is enabled. + +Reorder the bulk regulator supply names so that VDD12 is enabled before +VDD33. Any enable ramp delays should be handled by setting proper +constraints on the regulators. + +Fixes: bc1aee7fc8f0 ("drm/bridge: Add I2C based driver for ps8640 bridge") +Signed-off-by: Chen-Yu Tsai +Reviewed-by: Neil Armstrong +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220721092258.3397461-1-wenst@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/parade-ps8640.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c +index edb939b14c04..38dcc606b499 100644 +--- a/drivers/gpu/drm/bridge/parade-ps8640.c ++++ b/drivers/gpu/drm/bridge/parade-ps8640.c +@@ -596,8 +596,8 @@ static int ps8640_probe(struct i2c_client *client) + if (!ps_bridge) + return -ENOMEM; + +- ps_bridge->supplies[0].supply = "vdd33"; +- ps_bridge->supplies[1].supply = "vdd12"; ++ ps_bridge->supplies[0].supply = "vdd12"; ++ ps_bridge->supplies[1].supply = "vdd33"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies), + ps_bridge->supplies); + if (ret) +-- +2.35.1 + diff --git a/queue-5.19/drm-bridge-tc358767-add-of_node_put-when-breaking-ou.patch b/queue-5.19/drm-bridge-tc358767-add-of_node_put-when-breaking-ou.patch new file mode 100644 index 00000000000..2746279362e --- /dev/null +++ b/queue-5.19/drm-bridge-tc358767-add-of_node_put-when-breaking-ou.patch @@ -0,0 +1,43 @@ +From 5819d9dc0c41b0a0015df371a92ad4a519d3d303 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jul 2022 14:54:47 +0800 +Subject: drm/bridge: tc358767: Add of_node_put() when breaking out of loop + +From: Liang He + +[ Upstream commit 14e7157afb055248ed34901fcd6fbf54201cfea1 ] + +In tc_probe_bridge_endpoint(), we should call of_node_put() when +breaking out of the for_each_endpoint_of_node() which will automatically +increase and decrease the refcount. + +Fixes: 71f7d9c03118 ("drm/bridge: tc358767: Detect bridge mode from connected endpoints in DT") +Signed-off-by: Liang He +Reviewed-by: Robert Foss +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220719065447.1080817-2-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/tc358767.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c +index 16affb42086a..c41c6c464b7f 100644 +--- a/drivers/gpu/drm/bridge/tc358767.c ++++ b/drivers/gpu/drm/bridge/tc358767.c +@@ -1986,9 +1986,10 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc) + + for_each_endpoint_of_node(dev->of_node, node) { + of_graph_parse_endpoint(node, &endpoint); +- if (endpoint.port > 2) ++ if (endpoint.port > 2) { ++ of_node_put(node); + return -EINVAL; +- ++ } + mode |= BIT(endpoint.port); + } + +-- +2.35.1 + diff --git a/queue-5.19/drm-dp-don-t-rewrite-link-config-when-setting-phy-te.patch b/queue-5.19/drm-dp-don-t-rewrite-link-config-when-setting-phy-te.patch new file mode 100644 index 00000000000..366147de509 --- /dev/null +++ b/queue-5.19/drm-dp-don-t-rewrite-link-config-when-setting-phy-te.patch @@ -0,0 +1,100 @@ +From db9f33c9456e229f406e7bb3058c43c56ff0e674 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 22:49:00 -0700 +Subject: drm/dp: Don't rewrite link config when setting phy test pattern + +From: Khaled Almahallawy + +[ Upstream commit 7b4d8db657192066bc6f1f6635d348413dac1e18 ] + +The sequence for Source DP PHY CTS automation is [2][1]: +1- Emulate successful Link Training(LT) +2- Short HPD and change link rates and number of lanes by LT. +(This is same flow for Link Layer CTS) +3- Short HPD and change PHY test pattern and swing/pre-emphasis +levels (This step should not trigger LT) + +The problem is with DP PHY compliance setup as follow: + + [DPTX + on board LTTPR]------Main Link--->[Scope] + ^ | + | | + | | + ----------Aux Ch------>[Aux Emulator] + +At step 3, before writing TRAINING_LANEx_SET/LINK_QUAL_PATTERN_SET +to declare the pattern/swing requested by scope, we write link +config in LINK_BW_SET/LANE_COUNT_SET on a port that has LTTPR. +As LTTPR snoops aux transaction, LINK_BW_SET/LANE_COUNT_SET writes +indicate a LT will start [Check DP 2.0 E11 -Sec 3.6.8.2 & 3.6.8.6.3], +and LTTPR will reset the link and stop sending DP signals to +DPTX/Scope causing the measurements to fail. Note that step 3 will +not trigger LT and DP link will never recovered by the +Aux Emulator/Scope. + +The reset of link can be tested with a monitor connected to LTTPR +port simply by writing to LINK_BW_SET or LANE_COUNT_SET as follow + + igt/tools/dpcd_reg write --offset=0x100 --value 0x14 --device=2 + +OR + + printf '\x14' | sudo dd of=/dev/drm_dp_aux2 bs=1 count=1 conv=notrunc + seek=$((0x100)) + +This single aux write causes the screen to blank, sending short HPD to +DPTX, setting LINK_STATUS_UPDATE = 1 in DPCD 0x204, and triggering LT. + +As stated in [1]: +"Before any TX electrical testing can be performed, the link between a +DPTX and DPRX (in this case, a piece of test equipment), including all +LTTPRs within the path, shall be trained as defined in this Standard." + +In addition, changing Phy pattern/Swing/Pre-emphasis (Step 3) uses the +same link rate and lane count applied on step 2, so no need to redo LT. + +The fix is to not rewrite link config in step 3, and just writes +TRAINING_LANEx_SET and LINK_QUAL_PATTERN_SET + +[1]: DP 2.0 E11 - 3.6.11.1 LTTPR DPTX_PHY Electrical Compliance + +[2]: Configuring UnigrafDPTC Controller - Automation Test Sequence +https://www.keysight.com/us/en/assets/9922-01244/help-files/ +D9040DPPC-DisplayPort-Test-Software-Online-Help-latest.chm + +Cc: Imre Deak +Cc: Jani Nikula +Cc: Or Cochvi +Signed-off-by: Khaled Almahallawy +Signed-off-by: Jani Nikula +Link: https://patchwork.freedesktop.org/patch/msgid/20220916054900.415804-1-khaled.almahallawy@intel.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/display/drm_dp_helper.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c +index e7c22c2ca90c..f27cd710bc86 100644 +--- a/drivers/gpu/drm/display/drm_dp_helper.c ++++ b/drivers/gpu/drm/display/drm_dp_helper.c +@@ -2636,17 +2636,8 @@ int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux, + struct drm_dp_phy_test_params *data, u8 dp_rev) + { + int err, i; +- u8 link_config[2]; + u8 test_pattern; + +- link_config[0] = drm_dp_link_rate_to_bw_code(data->link_rate); +- link_config[1] = data->num_lanes; +- if (data->enhanced_frame_cap) +- link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; +- err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, link_config, 2); +- if (err < 0) +- return err; +- + test_pattern = data->phy_pattern; + if (dp_rev < 0x12) { + test_pattern = (test_pattern << 2) & +-- +2.35.1 + diff --git a/queue-5.19/drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch b/queue-5.19/drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch new file mode 100644 index 00000000000..646a8a7c1d4 --- /dev/null +++ b/queue-5.19/drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch @@ -0,0 +1,57 @@ +From 88eb12c4e82cbea668b9a52a87b23f4afff2da85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Feb 2022 15:40:25 +0000 +Subject: drm/dp_mst: fix drm_dp_dpcd_read return value checks + +From: Simon Ser + +[ Upstream commit 2ac6cdd581f48c8f68747156fde5868486a44985 ] + +drm_dp_dpcd_read returns the number of bytes read. The previous code +would print garbage on DPCD error, and would exit with on error on +success. + +Signed-off-by: Simon Ser +Fixes: cb897542c6d2 ("drm/dp_mst: Fix W=1 warnings") +Cc: Lyude Paul +Cc: Benjamin Gaignard +Reviewed-by: Jani Nikula +Link: https://patchwork.freedesktop.org/patch/473500/ +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c +index 18f2b6075b78..28dd741f7da1 100644 +--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c ++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c +@@ -4916,14 +4916,14 @@ void drm_dp_mst_dump_topology(struct seq_file *m, + seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf); + + ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2); +- if (ret) { ++ if (ret != 2) { + seq_printf(m, "faux/mst read failed\n"); + goto out; + } + seq_printf(m, "faux/mst: %*ph\n", 2, buf); + + ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1); +- if (ret) { ++ if (ret != 1) { + seq_printf(m, "mst ctrl read failed\n"); + goto out; + } +@@ -4931,7 +4931,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m, + + /* dump the standard OUI branch header */ + ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE); +- if (ret) { ++ if (ret != DP_BRANCH_OUI_HEADER_SIZE) { + seq_printf(m, "branch oui read failed\n"); + goto out; + } +-- +2.35.1 + diff --git a/queue-5.19/drm-exynos-fix-return-type-for-mixer_mode_valid-and-.patch b/queue-5.19/drm-exynos-fix-return-type-for-mixer_mode_valid-and-.patch new file mode 100644 index 00000000000..e92c3568445 --- /dev/null +++ b/queue-5.19/drm-exynos-fix-return-type-for-mixer_mode_valid-and-.patch @@ -0,0 +1,66 @@ +From 18fd514d3c59e2b12fa3ca1a494a9d6a4050459f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 09:31:00 +0900 +Subject: drm/exynos: Fix return type for mixer_mode_valid and hdmi_mode_valid + +From: Nathan Huckleberry + +[ Upstream commit 1261255531088208daeca818e2b486030b5339e5 ] + +The field mode_valid in exynos_drm_crtc_ops is expected to be of type enum +drm_mode_status (*mode_valid)(struct exynos_drm_crtc *crtc, + const struct drm_display_mode *mode); + +Likewise for mode_valid in drm_connector_helper_funcs. + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of mixer_mode_valid and hdmi_mode_valid should be changed +from int to enum drm_mode_status. + +Reported-by: Dan Carpenter +Link: https://protect2.fireeye.com/v1/url?k=3e644738-5fef521d-3e65cc77- +74fe485cbff6-36ad29bf912d3c9f&q=1&e=5cc06174-77dd-4abd-ab50- +155da5711aa3&u=https%3A%2F%2Fgithub.com%2FClangBuiltLinux%2Flinux%2Fissues%2F +1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Signed-off-by: Inki Dae +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/exynos/exynos_hdmi.c | 4 ++-- + drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c +index 7655142a4651..912a7df9f8c4 100644 +--- a/drivers/gpu/drm/exynos/exynos_hdmi.c ++++ b/drivers/gpu/drm/exynos/exynos_hdmi.c +@@ -922,8 +922,8 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock) + return -EINVAL; + } + +-static int hdmi_mode_valid(struct drm_connector *connector, +- struct drm_display_mode *mode) ++static enum drm_mode_status hdmi_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) + { + struct hdmi_context *hdata = connector_to_hdmi(connector); + int ret; +diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c +index e5204be86093..c46bee9176da 100644 +--- a/drivers/gpu/drm/exynos/exynos_mixer.c ++++ b/drivers/gpu/drm/exynos/exynos_mixer.c +@@ -1042,7 +1042,7 @@ static void mixer_atomic_disable(struct exynos_drm_crtc *crtc) + clear_bit(MXR_BIT_POWERED, &ctx->flags); + } + +-static int mixer_mode_valid(struct exynos_drm_crtc *crtc, ++static enum drm_mode_status mixer_mode_valid(struct exynos_drm_crtc *crtc, + const struct drm_display_mode *mode) + { + struct mixer_context *ctx = crtc->ctx; +-- +2.35.1 + diff --git a/queue-5.19/drm-komeda-fix-handling-of-atomic-commits-in-the-ato.patch b/queue-5.19/drm-komeda-fix-handling-of-atomic-commits-in-the-ato.patch new file mode 100644 index 00000000000..3f39e570636 --- /dev/null +++ b/queue-5.19/drm-komeda-fix-handling-of-atomic-commits-in-the-ato.patch @@ -0,0 +1,116 @@ +From 5bb4ec97f814ccee557b9e708781b2b33b33b973 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Jul 2022 16:39:21 +0100 +Subject: drm/komeda: Fix handling of atomic commits in the atomic_commit_tail + hook + +From: Liviu Dudau + +[ Upstream commit eaa225b6b52233d45457fd33730e1528c604d92d ] + +Komeda driver relies on the generic DRM atomic helper functions to handle +commits. It only implements an atomic_commit_tail hook for the +mode_config_helper_funcs and even that one is pretty close to the generic +implementation with the exception of additional dma_fence signalling. + +What the generic helper framework doesn't do is waiting for the actual +hardware to signal that the commit parameters have been written into the +appropriate registers. As we signal CRTC events only on the irq handlers, +we need to flush the configuration and wait for the hardware to respond. + +Add the Komeda specific implementation for atomic_commit_hw_done() that +flushes and waits for flip done before calling drm_atomic_helper_commit_hw_done(). + +The fix was prompted by a patch from Carsten Haitzler where he was trying to +solve the same issue but in a different way that I think can lead to wrong +event signaling to userspace. + +Reported-by: Carsten Haitzler +Tested-by: Carsten Haitzler +Reviewed-by: Carsten Haitzler +Signed-off-by: Liviu Dudau +Link: https://patchwork.freedesktop.org/patch/msgid/20220722122139.288486-1-liviu.dudau@arm.com +Signed-off-by: Sasha Levin +--- + .../gpu/drm/arm/display/komeda/komeda_crtc.c | 4 ++-- + .../gpu/drm/arm/display/komeda/komeda_kms.c | 21 ++++++++++++++++++- + .../gpu/drm/arm/display/komeda/komeda_kms.h | 2 ++ + 3 files changed, 24 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +index 59172acb9738..292f533d8cf0 100644 +--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c ++++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +@@ -235,7 +235,7 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, + crtc->state->event = NULL; + drm_crtc_send_vblank_event(crtc, event); + } else { +- DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n", ++ DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n", + drm_crtc_index(&kcrtc->base)); + } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); +@@ -286,7 +286,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc, + komeda_crtc_do_flush(crtc, old); + } + +-static void ++void + komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, + struct completion *input_flip_done) + { +diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +index 93b7f09b96ca..327051bba5b6 100644 +--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c ++++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +@@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = { + .minor = 1, + }; + ++static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state) ++{ ++ struct drm_device *dev = state->dev; ++ struct komeda_kms_dev *kms = to_kdev(dev); ++ int i; ++ ++ for (i = 0; i < kms->n_crtcs; i++) { ++ struct komeda_crtc *kcrtc = &kms->crtcs[i]; ++ ++ if (kcrtc->base.state->active) { ++ struct completion *flip_done = NULL; ++ if (kcrtc->base.state->event) ++ flip_done = kcrtc->base.state->event->base.completion; ++ komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done); ++ } ++ } ++ drm_atomic_helper_commit_hw_done(state); ++} ++ + static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) + { + struct drm_device *dev = old_state->dev; +@@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state) + + drm_atomic_helper_commit_modeset_enables(dev, old_state); + +- drm_atomic_helper_commit_hw_done(old_state); ++ komeda_kms_atomic_commit_hw_done(old_state); + + drm_atomic_helper_wait_for_flip_done(dev, old_state); + +diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +index 456f3c435719..bf6e8fba5061 100644 +--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h ++++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +@@ -182,6 +182,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms); + + void komeda_crtc_handle_event(struct komeda_crtc *kcrtc, + struct komeda_events *evts); ++void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, ++ struct completion *input_flip_done); + + struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev); + void komeda_kms_detach(struct komeda_kms_dev *kms); +-- +2.35.1 + diff --git a/queue-5.19/drm-meson-explicitly-remove-aggregate-driver-at-modu.patch b/queue-5.19/drm-meson-explicitly-remove-aggregate-driver-at-modu.patch new file mode 100644 index 00000000000..5d28e4c7fc6 --- /dev/null +++ b/queue-5.19/drm-meson-explicitly-remove-aggregate-driver-at-modu.patch @@ -0,0 +1,197 @@ +From 20448a07eed742a61031b49503bc138ba4ef88e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 02:09:39 +0100 +Subject: drm/meson: explicitly remove aggregate driver at module unload time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit 8616f2a0589a80e08434212324250eb22f6a66ce ] + +Because component_master_del wasn't being called when unloading the +meson_drm module, the aggregate device would linger forever in the global +aggregate_devices list. That means when unloading and reloading the +meson_dw_hdmi module, component_add would call into +try_to_bring_up_aggregate_device and find the unbound meson_drm aggregate +device. + +This would in turn dereference some of the aggregate_device's struct +entries which point to memory automatically freed by the devres API when +unbinding the aggregate device from meson_drv_unbind, and trigger an +use-after-free bug: + +[ +0.000014] ============================================================= +[ +0.000007] BUG: KASAN: use-after-free in find_components+0x468/0x500 +[ +0.000017] Read of size 8 at addr ffff000006731688 by task modprobe/2536 +[ +0.000018] CPU: 4 PID: 2536 Comm: modprobe Tainted: G C O 5.19.0-rc6-lrmbkasan+ #1 +[ +0.000010] Hardware name: Hardkernel ODROID-N2Plus (DT) +[ +0.000008] Call trace: +[ +0.000005] dump_backtrace+0x1ec/0x280 +[ +0.000011] show_stack+0x24/0x80 +[ +0.000007] dump_stack_lvl+0x98/0xd4 +[ +0.000010] print_address_description.constprop.0+0x80/0x520 +[ +0.000011] print_report+0x128/0x260 +[ +0.000007] kasan_report+0xb8/0xfc +[ +0.000007] __asan_report_load8_noabort+0x3c/0x50 +[ +0.000009] find_components+0x468/0x500 +[ +0.000008] try_to_bring_up_aggregate_device+0x64/0x390 +[ +0.000009] __component_add+0x1dc/0x49c +[ +0.000009] component_add+0x20/0x30 +[ +0.000008] meson_dw_hdmi_probe+0x28/0x34 [meson_dw_hdmi] +[ +0.000013] platform_probe+0xd0/0x220 +[ +0.000008] really_probe+0x3ac/0xa80 +[ +0.000008] __driver_probe_device+0x1f8/0x400 +[ +0.000008] driver_probe_device+0x68/0x1b0 +[ +0.000008] __driver_attach+0x20c/0x480 +[ +0.000009] bus_for_each_dev+0x114/0x1b0 +[ +0.000007] driver_attach+0x48/0x64 +[ +0.000009] bus_add_driver+0x390/0x564 +[ +0.000007] driver_register+0x1a8/0x3e4 +[ +0.000009] __platform_driver_register+0x6c/0x94 +[ +0.000007] meson_dw_hdmi_platform_driver_init+0x30/0x1000 [meson_dw_hdmi] +[ +0.000014] do_one_initcall+0xc4/0x2b0 +[ +0.000008] do_init_module+0x154/0x570 +[ +0.000010] load_module+0x1a78/0x1ea4 +[ +0.000008] __do_sys_init_module+0x184/0x1cc +[ +0.000008] __arm64_sys_init_module+0x78/0xb0 +[ +0.000008] invoke_syscall+0x74/0x260 +[ +0.000008] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000009] do_el0_svc+0x50/0x70 +[ +0.000008] el0_svc+0x68/0x1a0 +[ +0.000009] el0t_64_sync_handler+0x11c/0x150 +[ +0.000009] el0t_64_sync+0x18c/0x190 + +[ +0.000014] Allocated by task 902: +[ +0.000007] kasan_save_stack+0x2c/0x5c +[ +0.000009] __kasan_kmalloc+0x90/0xd0 +[ +0.000007] __kmalloc_node+0x240/0x580 +[ +0.000010] memcg_alloc_slab_cgroups+0xa4/0x1ac +[ +0.000010] memcg_slab_post_alloc_hook+0xbc/0x4c0 +[ +0.000008] kmem_cache_alloc_node+0x1d0/0x490 +[ +0.000009] __alloc_skb+0x1d4/0x310 +[ +0.000010] alloc_skb_with_frags+0x8c/0x620 +[ +0.000008] sock_alloc_send_pskb+0x5ac/0x6d0 +[ +0.000010] unix_dgram_sendmsg+0x2e0/0x12f0 +[ +0.000010] sock_sendmsg+0xcc/0x110 +[ +0.000007] sock_write_iter+0x1d0/0x304 +[ +0.000008] new_sync_write+0x364/0x460 +[ +0.000007] vfs_write+0x420/0x5ac +[ +0.000008] ksys_write+0x19c/0x1f0 +[ +0.000008] __arm64_sys_write+0x78/0xb0 +[ +0.000007] invoke_syscall+0x74/0x260 +[ +0.000008] el0_svc_common.constprop.0+0x1a8/0x260 +[ +0.000009] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000008] el0t_64_sync_handler+0x11c/0x150 +[ +0.000008] el0t_64_sync+0x18c/0x190 + +[ +0.000013] Freed by task 2509: +[ +0.000008] kasan_save_stack+0x2c/0x5c +[ +0.000007] kasan_set_track+0x2c/0x40 +[ +0.000008] kasan_set_free_info+0x28/0x50 +[ +0.000008] ____kasan_slab_free+0x128/0x1d4 +[ +0.000008] __kasan_slab_free+0x18/0x24 +[ +0.000007] slab_free_freelist_hook+0x108/0x230 +[ +0.000010] kfree+0x110/0x35c +[ +0.000008] release_nodes+0xf0/0x16c +[ +0.000008] devres_release_all+0xfc/0x180 +[ +0.000008] device_unbind_cleanup+0x24/0x164 +[ +0.000008] device_release_driver_internal+0x3e8/0x5b0 +[ +0.000010] driver_detach+0xac/0x1b0 +[ +0.000008] bus_remove_driver+0x158/0x29c +[ +0.000008] driver_unregister+0x70/0xb0 +[ +0.000009] platform_driver_unregister+0x20/0x2c +[ +0.000007] 0xffff800003722d98 +[ +0.000012] __do_sys_delete_module+0x288/0x400 +[ +0.000009] __arm64_sys_delete_module+0x5c/0x80 +[ +0.000008] invoke_syscall+0x74/0x260 +[ +0.000008] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000008] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000008] el0t_64_sync_handler+0x11c/0x150 +[ +0.000009] el0t_64_sync+0x18c/0x190 + +[ +0.000013] Last potentially related work creation: +[ +0.000007] kasan_save_stack+0x2c/0x5c +[ +0.000007] __kasan_record_aux_stack+0xb8/0xf0 +[ +0.000009] kasan_record_aux_stack_noalloc+0x14/0x20 +[ +0.000008] insert_work+0x54/0x290 +[ +0.000009] __queue_work+0x48c/0xd24 +[ +0.000008] queue_work_on+0x90/0x11c +[ +0.000008] call_usermodehelper_exec+0x188/0x404 +[ +0.000010] kobject_uevent_env+0x5a8/0x794 +[ +0.000010] kobject_uevent+0x14/0x20 +[ +0.000008] driver_register+0x230/0x3e4 +[ +0.000009] __platform_driver_register+0x6c/0x94 +[ +0.000007] gxbb_driver_init+0x28/0x34 +[ +0.000010] do_one_initcall+0xc4/0x2b0 +[ +0.000008] do_initcalls+0x20c/0x24c +[ +0.000010] kernel_init_freeable+0x22c/0x278 +[ +0.000009] kernel_init+0x3c/0x170 +[ +0.000008] ret_from_fork+0x10/0x20 + +[ +0.000013] The buggy address belongs to the object at ffff000006731600 + which belongs to the cache kmalloc-256 of size 256 +[ +0.000009] The buggy address is located 136 bytes inside of + 256-byte region [ffff000006731600, ffff000006731700) + +[ +0.000015] The buggy address belongs to the physical page: +[ +0.000008] page:fffffc000019cc00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff000006730a00 pfn:0x6730 +[ +0.000011] head:fffffc000019cc00 order:2 compound_mapcount:0 compound_pincount:0 +[ +0.000008] flags: 0xffff00000010200(slab|head|node=0|zone=0|lastcpupid=0xffff) +[ +0.000016] raw: 0ffff00000010200 fffffc00000c3d08 fffffc0000ef2b08 ffff000000002680 +[ +0.000009] raw: ffff000006730a00 0000000000150014 00000001ffffffff 0000000000000000 +[ +0.000006] page dumped because: kasan: bad access detected + +[ +0.000011] Memory state around the buggy address: +[ +0.000007] ffff000006731580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ +0.000007] ffff000006731600: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] >ffff000006731680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ^ +[ +0.000006] ffff000006731700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ +0.000007] ffff000006731780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ +0.000006] ================================================================== + +Fix by adding 'remove' driver callback for meson-drm, and explicitly deleting the +aggregate device. + +Signed-off-by: Adrián Larumbe +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patchwork.freedesktop.org/patch/msgid/20220919010940.419893-3-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/meson/meson_drv.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c +index 7df149d42728..8444d90165fb 100644 +--- a/drivers/gpu/drm/meson/meson_drv.c ++++ b/drivers/gpu/drm/meson/meson_drv.c +@@ -493,6 +493,13 @@ static int meson_drv_probe(struct platform_device *pdev) + return 0; + }; + ++static int meson_drv_remove(struct platform_device *pdev) ++{ ++ component_master_del(&pdev->dev, &meson_drv_master_ops); ++ ++ return 0; ++} ++ + static struct meson_drm_match_data meson_drm_gxbb_data = { + .compat = VPU_COMPATIBLE_GXBB, + }; +@@ -530,6 +537,7 @@ static const struct dev_pm_ops meson_drv_pm_ops = { + + static struct platform_driver meson_drm_platform_driver = { + .probe = meson_drv_probe, ++ .remove = meson_drv_remove, + .shutdown = meson_drv_shutdown, + .driver = { + .name = "meson-drm", +-- +2.35.1 + diff --git a/queue-5.19/drm-meson-remove-drm-bridges-at-aggregate-driver-unb.patch b/queue-5.19/drm-meson-remove-drm-bridges-at-aggregate-driver-unb.patch new file mode 100644 index 00000000000..2ac983e86dc --- /dev/null +++ b/queue-5.19/drm-meson-remove-drm-bridges-at-aggregate-driver-unb.patch @@ -0,0 +1,283 @@ +From 4db3441152a84b015303feaee35477df1677815a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 23:28:42 +0100 +Subject: drm/meson: remove drm bridges at aggregate driver unbind time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit 09847723c12fc2753749cec3939a02ee92dac468 ] + +drm bridges added by meson_encoder_hdmi_init and meson_encoder_cvbs_init +were not manually removed at module unload time, which caused dangling +references to freed memory to remain linked in the global bridge_list. + +When loading the driver modules back in, the same functions would again +call drm_bridge_add, and when traversing the global bridge_list, would +end up peeking into freed memory. + +Once again KASAN revealed the problem: + +[ +0.000095] ============================================================= +[ +0.000008] BUG: KASAN: use-after-free in __list_add_valid+0x9c/0x120 +[ +0.000018] Read of size 8 at addr ffff00003da291f0 by task modprobe/2483 + +[ +0.000018] CPU: 3 PID: 2483 Comm: modprobe Tainted: G C O 5.19.0-rc6-lrmbkasan+ #1 +[ +0.000011] Hardware name: Hardkernel ODROID-N2Plus (DT) +[ +0.000008] Call trace: +[ +0.000006] dump_backtrace+0x1ec/0x280 +[ +0.000012] show_stack+0x24/0x80 +[ +0.000008] dump_stack_lvl+0x98/0xd4 +[ +0.000011] print_address_description.constprop.0+0x80/0x520 +[ +0.000011] print_report+0x128/0x260 +[ +0.000008] kasan_report+0xb8/0xfc +[ +0.000008] __asan_report_load8_noabort+0x3c/0x50 +[ +0.000009] __list_add_valid+0x9c/0x120 +[ +0.000009] drm_bridge_add+0x6c/0x104 [drm] +[ +0.000165] dw_hdmi_probe+0x1900/0x2360 [dw_hdmi] +[ +0.000022] meson_dw_hdmi_bind+0x520/0x814 [meson_dw_hdmi] +[ +0.000014] component_bind+0x174/0x520 +[ +0.000012] component_bind_all+0x1a8/0x38c +[ +0.000010] meson_drv_bind_master+0x5e8/0xb74 [meson_drm] +[ +0.000032] meson_drv_bind+0x20/0x2c [meson_drm] +[ +0.000027] try_to_bring_up_aggregate_device+0x19c/0x390 +[ +0.000010] component_master_add_with_match+0x1c8/0x284 +[ +0.000009] meson_drv_probe+0x274/0x280 [meson_drm] +[ +0.000026] platform_probe+0xd0/0x220 +[ +0.000009] really_probe+0x3ac/0xa80 +[ +0.000009] __driver_probe_device+0x1f8/0x400 +[ +0.000009] driver_probe_device+0x68/0x1b0 +[ +0.000009] __driver_attach+0x20c/0x480 +[ +0.000008] bus_for_each_dev+0x114/0x1b0 +[ +0.000009] driver_attach+0x48/0x64 +[ +0.000008] bus_add_driver+0x390/0x564 +[ +0.000009] driver_register+0x1a8/0x3e4 +[ +0.000009] __platform_driver_register+0x6c/0x94 +[ +0.000008] meson_drm_platform_driver_init+0x3c/0x1000 [meson_drm] +[ +0.000027] do_one_initcall+0xc4/0x2b0 +[ +0.000011] do_init_module+0x154/0x570 +[ +0.000011] load_module+0x1a78/0x1ea4 +[ +0.000008] __do_sys_init_module+0x184/0x1cc +[ +0.000009] __arm64_sys_init_module+0x78/0xb0 +[ +0.000009] invoke_syscall+0x74/0x260 +[ +0.000009] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000008] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000012] el0t_64_sync_handler+0x11c/0x150 +[ +0.000008] el0t_64_sync+0x18c/0x190 + +[ +0.000016] Allocated by task 879: +[ +0.000008] kasan_save_stack+0x2c/0x5c +[ +0.000011] __kasan_kmalloc+0x90/0xd0 +[ +0.000007] __kmalloc+0x278/0x4a0 +[ +0.000011] mpi_resize+0x13c/0x1d0 +[ +0.000011] mpi_powm+0xd24/0x1570 +[ +0.000009] rsa_enc+0x1a4/0x30c +[ +0.000009] pkcs1pad_verify+0x3f0/0x580 +[ +0.000009] public_key_verify_signature+0x7a8/0xba4 +[ +0.000010] public_key_verify_signature_2+0x40/0x60 +[ +0.000008] verify_signature+0xb4/0x114 +[ +0.000008] pkcs7_validate_trust_one.constprop.0+0x3b8/0x574 +[ +0.000009] pkcs7_validate_trust+0xb8/0x15c +[ +0.000008] verify_pkcs7_message_sig+0xec/0x1b0 +[ +0.000012] verify_pkcs7_signature+0x78/0xac +[ +0.000007] mod_verify_sig+0x110/0x190 +[ +0.000009] module_sig_check+0x114/0x1e0 +[ +0.000009] load_module+0xa0/0x1ea4 +[ +0.000008] __do_sys_init_module+0x184/0x1cc +[ +0.000008] __arm64_sys_init_module+0x78/0xb0 +[ +0.000008] invoke_syscall+0x74/0x260 +[ +0.000009] el0_svc_common.constprop.0+0x1a8/0x260 +[ +0.000008] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000009] el0t_64_sync_handler+0x11c/0x150 +[ +0.000009] el0t_64_sync+0x18c/0x190 + +[ +0.000013] Freed by task 2422: +[ +0.000008] kasan_save_stack+0x2c/0x5c +[ +0.000009] kasan_set_track+0x2c/0x40 +[ +0.000007] kasan_set_free_info+0x28/0x50 +[ +0.000009] ____kasan_slab_free+0x128/0x1d4 +[ +0.000008] __kasan_slab_free+0x18/0x24 +[ +0.000007] slab_free_freelist_hook+0x108/0x230 +[ +0.000010] kfree+0x110/0x35c +[ +0.000008] release_nodes+0xf0/0x16c +[ +0.000009] devres_release_group+0x180/0x270 +[ +0.000008] take_down_aggregate_device+0xcc/0x160 +[ +0.000010] component_del+0x18c/0x360 +[ +0.000009] meson_dw_hdmi_remove+0x28/0x40 [meson_dw_hdmi] +[ +0.000013] platform_remove+0x64/0xb0 +[ +0.000008] device_remove+0xb8/0x154 +[ +0.000009] device_release_driver_internal+0x398/0x5b0 +[ +0.000009] driver_detach+0xac/0x1b0 +[ +0.000009] bus_remove_driver+0x158/0x29c +[ +0.000008] driver_unregister+0x70/0xb0 +[ +0.000009] platform_driver_unregister+0x20/0x2c +[ +0.000007] meson_dw_hdmi_platform_driver_exit+0x1c/0x30 [meson_dw_hdmi] +[ +0.000012] __do_sys_delete_module+0x288/0x400 +[ +0.000009] __arm64_sys_delete_module+0x5c/0x80 +[ +0.000009] invoke_syscall+0x74/0x260 +[ +0.000008] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000008] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000008] el0t_64_sync_handler+0x11c/0x150 +[ +0.000009] el0t_64_sync+0x18c/0x190 + +[ +0.000013] The buggy address belongs to the object at ffff00003da29000 + which belongs to the cache kmalloc-1k of size 1024 +[ +0.000008] The buggy address is located 496 bytes inside of + 1024-byte region [ffff00003da29000, ffff00003da29400) + +[ +0.000015] The buggy address belongs to the physical page: +[ +0.000009] page:fffffc0000f68a00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3da28 +[ +0.000012] head:fffffc0000f68a00 order:3 compound_mapcount:0 compound_pincount:0 +[ +0.000009] flags: 0xffff00000010200(slab|head|node=0|zone=0|lastcpupid=0xffff) +[ +0.000019] raw: 0ffff00000010200 fffffc0000eb5c08 fffffc0000d96608 ffff000000002a80 +[ +0.000008] raw: 0000000000000000 00000000000a000a 00000001ffffffff 0000000000000000 +[ +0.000008] page dumped because: kasan: bad access detected + +[ +0.000011] Memory state around the buggy address: +[ +0.000009] ffff00003da29080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ffff00003da29100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] >ffff00003da29180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ^ +[ +0.000008] ffff00003da29200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000006] ffff00003da29280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ================================================================== + +Fix by keeping track of which encoders were initialised in the meson_drm +structure and manually removing their bridges at aggregate driver's unbind +time. + +Signed-off-by: Adrián Larumbe +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patchwork.freedesktop.org/patch/msgid/20220920222842.1053234-1-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/meson/meson_drv.c | 4 ++++ + drivers/gpu/drm/meson/meson_drv.h | 7 +++++++ + drivers/gpu/drm/meson/meson_encoder_cvbs.c | 13 +++++++++++++ + drivers/gpu/drm/meson/meson_encoder_cvbs.h | 1 + + drivers/gpu/drm/meson/meson_encoder_hdmi.c | 13 +++++++++++++ + drivers/gpu/drm/meson/meson_encoder_hdmi.h | 1 + + 6 files changed, 39 insertions(+) + +diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c +index 8444d90165fb..86b90d0f5780 100644 +--- a/drivers/gpu/drm/meson/meson_drv.c ++++ b/drivers/gpu/drm/meson/meson_drv.c +@@ -390,6 +390,10 @@ static void meson_drv_unbind(struct device *dev) + drm_atomic_helper_shutdown(drm); + free_irq(priv->vsync_irq, drm); + drm_dev_put(drm); ++ ++ meson_encoder_hdmi_remove(priv); ++ meson_encoder_cvbs_remove(priv); ++ + component_unbind_all(dev, drm); + + if (priv->afbcd.ops) +diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h +index 177dac3ca3be..c62ee358456f 100644 +--- a/drivers/gpu/drm/meson/meson_drv.h ++++ b/drivers/gpu/drm/meson/meson_drv.h +@@ -25,6 +25,12 @@ enum vpu_compatible { + VPU_COMPATIBLE_G12A = 3, + }; + ++enum { ++ MESON_ENC_CVBS = 0, ++ MESON_ENC_HDMI, ++ MESON_ENC_LAST, ++}; ++ + struct meson_drm_match_data { + enum vpu_compatible compat; + struct meson_afbcd_ops *afbcd_ops; +@@ -51,6 +57,7 @@ struct meson_drm { + struct drm_crtc *crtc; + struct drm_plane *primary_plane; + struct drm_plane *overlay_plane; ++ void *encoders[MESON_ENC_LAST]; + + const struct meson_drm_soc_limits *limits; + +diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +index 8110a6e39320..5675bc2a92cf 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c ++++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c +@@ -281,5 +281,18 @@ int meson_encoder_cvbs_init(struct meson_drm *priv) + } + drm_connector_attach_encoder(connector, &meson_encoder_cvbs->encoder); + ++ priv->encoders[MESON_ENC_CVBS] = meson_encoder_cvbs; ++ + return 0; + } ++ ++void meson_encoder_cvbs_remove(struct meson_drm *priv) ++{ ++ struct meson_encoder_cvbs *meson_encoder_cvbs; ++ ++ if (priv->encoders[MESON_ENC_CVBS]) { ++ meson_encoder_cvbs = priv->encoders[MESON_ENC_CVBS]; ++ drm_bridge_remove(&meson_encoder_cvbs->bridge); ++ drm_bridge_remove(meson_encoder_cvbs->next_bridge); ++ } ++} +diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.h b/drivers/gpu/drm/meson/meson_encoder_cvbs.h +index 61d9d183ce7f..09710fec3c66 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.h ++++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.h +@@ -25,5 +25,6 @@ struct meson_cvbs_mode { + extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT]; + + int meson_encoder_cvbs_init(struct meson_drm *priv); ++void meson_encoder_cvbs_remove(struct meson_drm *priv); + + #endif /* __MESON_VENC_CVBS_H */ +diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +index a7692584487c..af6025037ecc 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c ++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c +@@ -446,6 +446,8 @@ int meson_encoder_hdmi_init(struct meson_drm *priv) + meson_encoder_hdmi->cec_notifier = notifier; + } + ++ priv->encoders[MESON_ENC_HDMI] = meson_encoder_hdmi; ++ + dev_dbg(priv->dev, "HDMI encoder initialized\n"); + + return 0; +@@ -454,3 +456,14 @@ int meson_encoder_hdmi_init(struct meson_drm *priv) + of_node_put(remote); + return ret; + } ++ ++void meson_encoder_hdmi_remove(struct meson_drm *priv) ++{ ++ struct meson_encoder_hdmi *meson_encoder_hdmi; ++ ++ if (priv->encoders[MESON_ENC_HDMI]) { ++ meson_encoder_hdmi = priv->encoders[MESON_ENC_HDMI]; ++ drm_bridge_remove(&meson_encoder_hdmi->bridge); ++ drm_bridge_remove(meson_encoder_hdmi->next_bridge); ++ } ++} +diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.h b/drivers/gpu/drm/meson/meson_encoder_hdmi.h +index ed19494f0956..a6cd38eb5f71 100644 +--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.h ++++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.h +@@ -8,5 +8,6 @@ + #define __MESON_ENCODER_HDMI_H + + int meson_encoder_hdmi_init(struct meson_drm *priv); ++void meson_encoder_hdmi_remove(struct meson_drm *priv); + + #endif /* __MESON_ENCODER_HDMI_H */ +-- +2.35.1 + diff --git a/queue-5.19/drm-meson-reorder-driver-deinit-sequence-to-fix-use-.patch b/queue-5.19/drm-meson-reorder-driver-deinit-sequence-to-fix-use-.patch new file mode 100644 index 00000000000..ba439f465b0 --- /dev/null +++ b/queue-5.19/drm-meson-reorder-driver-deinit-sequence-to-fix-use-.patch @@ -0,0 +1,161 @@ +From 2811a8ff2a0d58bfdb122cafe3e81f9571755e25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 02:09:38 +0100 +Subject: drm/meson: reorder driver deinit sequence to fix use-after-free bug +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Adrián Larumbe + +[ Upstream commit 31c519981eb141c7ec39bfd5be25d35f02edb868 ] + +Unloading the driver triggers the following KASAN warning: + +[ +0.006275] ============================================================= +[ +0.000029] BUG: KASAN: use-after-free in __list_del_entry_valid+0xe0/0x1a0 +[ +0.000026] Read of size 8 at addr ffff000020c395e0 by task rmmod/2695 + +[ +0.000019] CPU: 5 PID: 2695 Comm: rmmod Tainted: G C O 5.19.0-rc6-lrmbkasan+ #1 +[ +0.000013] Hardware name: Hardkernel ODROID-N2Plus (DT) +[ +0.000008] Call trace: +[ +0.000007] dump_backtrace+0x1ec/0x280 +[ +0.000013] show_stack+0x24/0x80 +[ +0.000008] dump_stack_lvl+0x98/0xd4 +[ +0.000011] print_address_description.constprop.0+0x80/0x520 +[ +0.000011] print_report+0x128/0x260 +[ +0.000007] kasan_report+0xb8/0xfc +[ +0.000008] __asan_report_load8_noabort+0x3c/0x50 +[ +0.000010] __list_del_entry_valid+0xe0/0x1a0 +[ +0.000009] drm_atomic_private_obj_fini+0x30/0x200 [drm] +[ +0.000172] drm_bridge_detach+0x94/0x260 [drm] +[ +0.000145] drm_encoder_cleanup+0xa4/0x290 [drm] +[ +0.000144] drm_mode_config_cleanup+0x118/0x740 [drm] +[ +0.000143] drm_mode_config_init_release+0x1c/0x2c [drm] +[ +0.000144] drm_managed_release+0x170/0x414 [drm] +[ +0.000142] drm_dev_put.part.0+0xc0/0x124 [drm] +[ +0.000143] drm_dev_put+0x20/0x30 [drm] +[ +0.000142] meson_drv_unbind+0x1d8/0x2ac [meson_drm] +[ +0.000028] take_down_aggregate_device+0xb0/0x160 +[ +0.000016] component_del+0x18c/0x360 +[ +0.000009] meson_dw_hdmi_remove+0x28/0x40 [meson_dw_hdmi] +[ +0.000015] platform_remove+0x64/0xb0 +[ +0.000009] device_remove+0xb8/0x154 +[ +0.000009] device_release_driver_internal+0x398/0x5b0 +[ +0.000009] driver_detach+0xac/0x1b0 +[ +0.000009] bus_remove_driver+0x158/0x29c +[ +0.000009] driver_unregister+0x70/0xb0 +[ +0.000008] platform_driver_unregister+0x20/0x2c +[ +0.000008] meson_dw_hdmi_platform_driver_exit+0x1c/0x30 [meson_dw_hdmi] +[ +0.000012] __do_sys_delete_module+0x288/0x400 +[ +0.000011] __arm64_sys_delete_module+0x5c/0x80 +[ +0.000009] invoke_syscall+0x74/0x260 +[ +0.000009] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000009] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000012] el0t_64_sync_handler+0x11c/0x150 +[ +0.000008] el0t_64_sync+0x18c/0x190 + +[ +0.000018] Allocated by task 0: +[ +0.000007] (stack is not available) + +[ +0.000011] Freed by task 2695: +[ +0.000008] kasan_save_stack+0x2c/0x5c +[ +0.000011] kasan_set_track+0x2c/0x40 +[ +0.000008] kasan_set_free_info+0x28/0x50 +[ +0.000009] ____kasan_slab_free+0x128/0x1d4 +[ +0.000008] __kasan_slab_free+0x18/0x24 +[ +0.000007] slab_free_freelist_hook+0x108/0x230 +[ +0.000011] kfree+0x110/0x35c +[ +0.000008] release_nodes+0xf0/0x16c +[ +0.000009] devres_release_group+0x180/0x270 +[ +0.000008] component_unbind+0x128/0x1e0 +[ +0.000010] component_unbind_all+0x1b8/0x264 +[ +0.000009] meson_drv_unbind+0x1a0/0x2ac [meson_drm] +[ +0.000025] take_down_aggregate_device+0xb0/0x160 +[ +0.000009] component_del+0x18c/0x360 +[ +0.000009] meson_dw_hdmi_remove+0x28/0x40 [meson_dw_hdmi] +[ +0.000012] platform_remove+0x64/0xb0 +[ +0.000008] device_remove+0xb8/0x154 +[ +0.000009] device_release_driver_internal+0x398/0x5b0 +[ +0.000009] driver_detach+0xac/0x1b0 +[ +0.000009] bus_remove_driver+0x158/0x29c +[ +0.000008] driver_unregister+0x70/0xb0 +[ +0.000008] platform_driver_unregister+0x20/0x2c +[ +0.000008] meson_dw_hdmi_platform_driver_exit+0x1c/0x30 [meson_dw_hdmi] +[ +0.000011] __do_sys_delete_module+0x288/0x400 +[ +0.000010] __arm64_sys_delete_module+0x5c/0x80 +[ +0.000008] invoke_syscall+0x74/0x260 +[ +0.000008] el0_svc_common.constprop.0+0xcc/0x260 +[ +0.000008] do_el0_svc+0x50/0x70 +[ +0.000007] el0_svc+0x68/0x1a0 +[ +0.000009] el0t_64_sync_handler+0x11c/0x150 +[ +0.000009] el0t_64_sync+0x18c/0x190 + +[ +0.000014] The buggy address belongs to the object at ffff000020c39000 + which belongs to the cache kmalloc-4k of size 4096 +[ +0.000008] The buggy address is located 1504 bytes inside of + 4096-byte region [ffff000020c39000, ffff000020c3a000) + +[ +0.000016] The buggy address belongs to the physical page: +[ +0.000009] page:fffffc0000830e00 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x20c38 +[ +0.000013] head:fffffc0000830e00 order:3 compound_mapcount:0 compound_pincount:0 +[ +0.000008] flags: 0xffff00000010200(slab|head|node=0|zone=0|lastcpupid=0xffff) +[ +0.000019] raw: 0ffff00000010200 fffffc0000fd4808 fffffc0000126208 ffff000000002e80 +[ +0.000009] raw: 0000000000000000 0000000000020002 00000001ffffffff 0000000000000000 +[ +0.000008] page dumped because: kasan: bad access detected + +[ +0.000011] Memory state around the buggy address: +[ +0.000008] ffff000020c39480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ffff000020c39500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] >ffff000020c39580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ^ +[ +0.000007] ffff000020c39600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000007] ffff000020c39680: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ +0.000006] ================================================================== + +The reason this is happening is unloading meson-dw-hdmi will cause the +component API to take down the aggregate device, which in turn will cause +all devres-managed memory to be freed, including the struct dw_hdmi +allocated in dw_hdmi_probe. This struct embeds a struct drm_bridge that is +added at the end of the function, and which is later on picked up in +meson_encoder_hdmi_init. + +However, when attaching the bridge to the encoder created in +meson_encoder_hdmi_init, it's linked to the encoder's bridge chain, from +where it never leaves, even after devres_release_group is called when the +driver's components are unbound and the embedding structure freed. + +Then, when calling drm_dev_put in the aggregate driver's unbind function, +drm_bridge_detach is called for every single bridge linked to the encoder, +including the one whose memory had already been deallocated. + +Fix by calling component_unbind_all after drm_dev_put. + +Signed-off-by: Adrián Larumbe +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patchwork.freedesktop.org/patch/msgid/20220919010940.419893-2-adrian.larumbe@collabora.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/meson/meson_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c +index bd4ca11d3ff5..7df149d42728 100644 +--- a/drivers/gpu/drm/meson/meson_drv.c ++++ b/drivers/gpu/drm/meson/meson_drv.c +@@ -388,9 +388,9 @@ static void meson_drv_unbind(struct device *dev) + drm_dev_unregister(drm); + drm_kms_helper_poll_fini(drm); + drm_atomic_helper_shutdown(drm); +- component_unbind_all(dev, drm); + free_irq(priv->vsync_irq, drm); + drm_dev_put(drm); ++ component_unbind_all(dev, drm); + + if (priv->afbcd.ops) + priv->afbcd.ops->exit(priv); +-- +2.35.1 + diff --git a/queue-5.19/drm-mipi-dsi-detach-devices-when-removing-the-host.patch b/queue-5.19/drm-mipi-dsi-detach-devices-when-removing-the-host.patch new file mode 100644 index 00000000000..bd138f78250 --- /dev/null +++ b/queue-5.19/drm-mipi-dsi-detach-devices-when-removing-the-host.patch @@ -0,0 +1,41 @@ +From 99d79d7eee4714cbea0fcb76e5c6aa006fc422e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Jul 2022 19:38:31 +0200 +Subject: drm/mipi-dsi: Detach devices when removing the host + +From: Maxime Ripard + +[ Upstream commit 668a8f17b5290d04ef7343636a5588a0692731a1 ] + +Whenever the MIPI-DSI host is unregistered, the code of +mipi_dsi_host_unregister() loops over every device currently found on that +bus and will unregister it. + +However, it doesn't detach it from the bus first, which leads to all kind +of resource leaks if the host wants to perform some clean up whenever a +device is detached. + +Fixes: 068a00233969 ("drm: Add MIPI DSI bus support") +Acked-by: Thomas Zimmermann +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20220711173939.1132294-2-maxime@cerno.tech +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_mipi_dsi.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c +index c40bde96cfdf..c317ee9fa445 100644 +--- a/drivers/gpu/drm/drm_mipi_dsi.c ++++ b/drivers/gpu/drm/drm_mipi_dsi.c +@@ -346,6 +346,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) + { + struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); + ++ mipi_dsi_detach(dsi); + mipi_dsi_device_unregister(dsi); + + return 0; +-- +2.35.1 + diff --git a/queue-5.19/drm-msm-dp-correct-1.62g-link-rate-at-dp_catalog_ctr.patch b/queue-5.19/drm-msm-dp-correct-1.62g-link-rate-at-dp_catalog_ctr.patch new file mode 100644 index 00000000000..74fbad1fac9 --- /dev/null +++ b/queue-5.19/drm-msm-dp-correct-1.62g-link-rate-at-dp_catalog_ctr.patch @@ -0,0 +1,50 @@ +From 55a4fe0c5862c72c1246f4c8e3f31f1d8bc500cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 13:15:50 -0700 +Subject: drm/msm/dp: correct 1.62G link rate at dp_catalog_ctrl_config_msa() + +From: Kuogee Hsieh + +[ Upstream commit aa0bff10af1c4b92e6b56e3e1b7f81c660d3ba78 ] + +At current implementation there is an extra 0 at 1.62G link rate which +cause no correct pixel_div selected for 1.62G link rate to calculate +mvid and nvid. This patch delete the extra 0 to have mvid and nvid be +calculated correctly. + +Changes in v2: +-- fix Fixes tag's text + +Changes in v3: +-- fix misspelling of "Reviewed-by" + +Fixes: 937f941ca06f ("drm/msm/dp: Use qmp phy for DP PLL and PHY") +Signed-off-by: Kuogee Hsieh +Reviewed-by: Stephen Boyd +Reviewed-by: Abhinav Kumar +Patchwork: https://patchwork.freedesktop.org/patch/499328/ +Link: https://lore.kernel.org/r/1661372150-3764-1-git-send-email-quic_khsieh@quicinc.com +[DB: rewrapped commit message] +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/dp/dp_catalog.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c +index 7257515871a9..676279d0ca8d 100644 +--- a/drivers/gpu/drm/msm/dp/dp_catalog.c ++++ b/drivers/gpu/drm/msm/dp/dp_catalog.c +@@ -431,7 +431,7 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, + + if (rate == link_rate_hbr3) + pixel_div = 6; +- else if (rate == 1620000 || rate == 270000) ++ else if (rate == 162000 || rate == 270000) + pixel_div = 2; + else if (rate == link_rate_hbr2) + pixel_div = 4; +-- +2.35.1 + diff --git a/queue-5.19/drm-msm-dpu-index-dpu_kms-hw_vbif-using-vbif_idx.patch b/queue-5.19/drm-msm-dpu-index-dpu_kms-hw_vbif-using-vbif_idx.patch new file mode 100644 index 00000000000..77e6bf90919 --- /dev/null +++ b/queue-5.19/drm-msm-dpu-index-dpu_kms-hw_vbif-using-vbif_idx.patch @@ -0,0 +1,127 @@ +From 1c56312fece13b35479b38848e776fa7e28e80ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jun 2022 15:57:01 +0300 +Subject: drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx + +From: Dmitry Baryshkov + +[ Upstream commit 7538f80ae0d98bf51eb89eee5344aec219902d42 ] + +Remove loops over hw_vbif. Instead always VBIF's idx as an index in the +array. This fixes an error in dpu_kms_hw_init(), where we fill +dpu_kms->hw_vbif[i], but check for an error pointer at +dpu_kms->hw_vbif[vbif_idx]. + +Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Abhinav Kumar +Patchwork: https://patchwork.freedesktop.org/patch/489569/ +Link: https://lore.kernel.org/r/20220615125703.24647-1-dmitry.baryshkov@linaro.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 ++++------ + drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c | 29 +++++++++++------------- + 2 files changed, 18 insertions(+), 23 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +index 9eff6c2b1917..8902d3615ca9 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +@@ -825,12 +825,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) + _dpu_kms_mmu_destroy(dpu_kms); + + if (dpu_kms->catalog) { +- for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { +- u32 vbif_idx = dpu_kms->catalog->vbif[i].id; +- +- if ((vbif_idx < VBIF_MAX) && dpu_kms->hw_vbif[vbif_idx]) { +- dpu_hw_vbif_destroy(dpu_kms->hw_vbif[vbif_idx]); +- dpu_kms->hw_vbif[vbif_idx] = NULL; ++ for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { ++ if (dpu_kms->hw_vbif[i]) { ++ dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]); ++ dpu_kms->hw_vbif[i] = NULL; + } + } + } +@@ -1132,7 +1130,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms) + for (i = 0; i < dpu_kms->catalog->vbif_count; i++) { + u32 vbif_idx = dpu_kms->catalog->vbif[i].id; + +- dpu_kms->hw_vbif[i] = dpu_hw_vbif_init(vbif_idx, ++ dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx, + dpu_kms->vbif[vbif_idx], dpu_kms->catalog); + if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) { + rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]); +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +index 21d20373eb8b..a18fb649301c 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c +@@ -11,6 +11,14 @@ + #include "dpu_hw_vbif.h" + #include "dpu_trace.h" + ++static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif vbif_idx) ++{ ++ if (vbif_idx < ARRAY_SIZE(dpu_kms->hw_vbif)) ++ return dpu_kms->hw_vbif[vbif_idx]; ++ ++ return NULL; ++} ++ + /** + * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt + * @vbif: Pointer to hardware vbif driver +@@ -148,20 +156,15 @@ static u32 _dpu_vbif_get_ot_limit(struct dpu_hw_vbif *vbif, + void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, + struct dpu_vbif_set_ot_params *params) + { +- struct dpu_hw_vbif *vbif = NULL; ++ struct dpu_hw_vbif *vbif; + struct dpu_hw_mdp *mdp; + bool forced_on = false; + u32 ot_lim; +- int ret, i; ++ int ret; + + mdp = dpu_kms->hw_mdp; + +- for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { +- if (dpu_kms->hw_vbif[i] && +- dpu_kms->hw_vbif[i]->idx == params->vbif_idx) +- vbif = dpu_kms->hw_vbif[i]; +- } +- ++ vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); + if (!vbif || !mdp) { + DRM_DEBUG_ATOMIC("invalid arguments vbif %d mdp %d\n", + vbif != NULL, mdp != NULL); +@@ -204,7 +207,7 @@ void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms, + void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, + struct dpu_vbif_set_qos_params *params) + { +- struct dpu_hw_vbif *vbif = NULL; ++ struct dpu_hw_vbif *vbif; + struct dpu_hw_mdp *mdp; + bool forced_on = false; + const struct dpu_vbif_qos_tbl *qos_tbl; +@@ -216,13 +219,7 @@ void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms, + } + mdp = dpu_kms->hw_mdp; + +- for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) { +- if (dpu_kms->hw_vbif[i] && +- dpu_kms->hw_vbif[i]->idx == params->vbif_idx) { +- vbif = dpu_kms->hw_vbif[i]; +- break; +- } +- } ++ vbif = dpu_get_vbif(dpu_kms, params->vbif_idx); + + if (!vbif || !vbif->cap) { + DPU_ERROR("invalid vbif %d\n", params->vbif_idx); +-- +2.35.1 + diff --git a/queue-5.19/drm-msm-lookup-the-icc-paths-in-both-mdp5-dpu-and-md.patch b/queue-5.19/drm-msm-lookup-the-icc-paths-in-both-mdp5-dpu-and-md.patch new file mode 100644 index 00000000000..198668ec926 --- /dev/null +++ b/queue-5.19/drm-msm-lookup-the-icc-paths-in-both-mdp5-dpu-and-md.patch @@ -0,0 +1,130 @@ +From fab309359a1fceabd34b0dc4a37fc1e2047a2dd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Aug 2022 14:56:30 +0300 +Subject: drm/msm: lookup the ICC paths in both mdp5/dpu and mdss devices + +From: Dmitry Baryshkov + +[ Upstream commit 5ccdcecaf8f732f593e359ebfb65de96b11bae66 ] + +The commit 6874f48bb8b0 ("drm/msm: make mdp5/dpu devices master +components") changed the MDP5 driver to look for the interconnect paths +in the MDSS device rather than in the MDP5 device itself. This was left +unnoticed since on my testing devices the interconnects probably didn't +reach the sync state. + +Rather than just using the MDP5 device for ICC path lookups for the MDP5 +devices, introduce an additional helper to check both MDP5/DPU and MDSS +nodes. This will be helpful for the MDP5->DPU conversion, since the +driver will have to check both nodes. + +Fixes: 6874f48bb8b0 ("drm/msm: make mdp5/dpu devices master components") +Reported-by: Marijn Suijten +Reported-by: Yassine Oudjana +Signed-off-by: Dmitry Baryshkov +Tested-by: Marijn Suijten # On sdm630 +Tested-by: Yassine Oudjana # msm8996 +Patchwork: https://patchwork.freedesktop.org/patch/496488/ +Link: https://lore.kernel.org/r/20220805115630.506391-1-dmitry.baryshkov@linaro.org +Signed-off-by: Dmitry Baryshkov +Signed-off-by: Rob Clark +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 ++----- + drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 9 +++------ + drivers/gpu/drm/msm/msm_drv.h | 2 ++ + drivers/gpu/drm/msm/msm_io_utils.c | 22 ++++++++++++++++++++++ + 4 files changed, 29 insertions(+), 11 deletions(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +index e23e2552e802..9eff6c2b1917 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +@@ -383,12 +383,9 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms) + struct icc_path *path1; + struct drm_device *dev = dpu_kms->dev; + struct device *dpu_dev = dev->dev; +- struct device *mdss_dev = dpu_dev->parent; + +- /* Interconnects are a part of MDSS device tree binding, not the +- * MDP/DPU device. */ +- path0 = of_icc_get(mdss_dev, "mdp0-mem"); +- path1 = of_icc_get(mdss_dev, "mdp1-mem"); ++ path0 = msm_icc_get(dpu_dev, "mdp0-mem"); ++ path1 = msm_icc_get(dpu_dev, "mdp1-mem"); + + if (IS_ERR_OR_NULL(path0)) + return PTR_ERR_OR_ZERO(path0); +diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +index 3d5621a68f85..b0c372fef5d5 100644 +--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c ++++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +@@ -921,12 +921,9 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) + + static int mdp5_setup_interconnect(struct platform_device *pdev) + { +- /* Interconnects are a part of MDSS device tree binding, not the +- * MDP5 device. */ +- struct device *mdss_dev = pdev->dev.parent; +- struct icc_path *path0 = of_icc_get(mdss_dev, "mdp0-mem"); +- struct icc_path *path1 = of_icc_get(mdss_dev, "mdp1-mem"); +- struct icc_path *path_rot = of_icc_get(mdss_dev, "rotator-mem"); ++ struct icc_path *path0 = msm_icc_get(&pdev->dev, "mdp0-mem"); ++ struct icc_path *path1 = msm_icc_get(&pdev->dev, "mdp1-mem"); ++ struct icc_path *path_rot = msm_icc_get(&pdev->dev, "rotator-mem"); + + if (IS_ERR(path0)) + return PTR_ERR(path0); +diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h +index 099a67d10c3a..17e8b6571f6f 100644 +--- a/drivers/gpu/drm/msm/msm_drv.h ++++ b/drivers/gpu/drm/msm/msm_drv.h +@@ -442,6 +442,8 @@ void __iomem *msm_ioremap_size(struct platform_device *pdev, const char *name, + phys_addr_t *size); + void __iomem *msm_ioremap_quiet(struct platform_device *pdev, const char *name); + ++struct icc_path *msm_icc_get(struct device *dev, const char *name); ++ + #define msm_writel(data, addr) writel((data), (addr)) + #define msm_readl(addr) readl((addr)) + +diff --git a/drivers/gpu/drm/msm/msm_io_utils.c b/drivers/gpu/drm/msm/msm_io_utils.c +index 7b504617833a..d02cd29ce829 100644 +--- a/drivers/gpu/drm/msm/msm_io_utils.c ++++ b/drivers/gpu/drm/msm/msm_io_utils.c +@@ -5,6 +5,8 @@ + * Author: Rob Clark + */ + ++#include ++ + #include "msm_drv.h" + + /* +@@ -124,3 +126,23 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, + work->worker = worker; + kthread_init_work(&work->work, fn); + } ++ ++struct icc_path *msm_icc_get(struct device *dev, const char *name) ++{ ++ struct device *mdss_dev = dev->parent; ++ struct icc_path *path; ++ ++ path = of_icc_get(dev, name); ++ if (path) ++ return path; ++ ++ /* ++ * If there are no interconnects attached to the corresponding device ++ * node, of_icc_get() will return NULL. ++ * ++ * If the MDP5/DPU device node doesn't have interconnects, lookup the ++ * path in the parent (MDSS) device. ++ */ ++ return of_icc_get(mdss_dev, name); ++ ++} +-- +2.35.1 + diff --git a/queue-5.19/drm-msm-make-.remove-and-.shutdown-hw-shutdown-consi.patch b/queue-5.19/drm-msm-make-.remove-and-.shutdown-hw-shutdown-consi.patch new file mode 100644 index 00000000000..cce3cd97843 --- /dev/null +++ b/queue-5.19/drm-msm-make-.remove-and-.shutdown-hw-shutdown-consi.patch @@ -0,0 +1,163 @@ +From c17df6dfdf2ace88b67c2174527bd764aba46e2c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 15:46:12 +0200 +Subject: drm/msm: Make .remove and .shutdown HW shutdown consistent + +From: Javier Martinez Canillas + +[ Upstream commit 0a58d2ae572adaec8d046f8d35b40c2c32ac7468 ] + +Drivers' .remove and .shutdown callbacks are executed on different code +paths. The former is called when a device is removed from the bus, while +the latter is called at system shutdown time to quiesce the device. + +This means that some overlap exists between the two, because both have to +take care of properly shutting down the hardware. But currently the logic +used in these two callbacks isn't consistent in msm drivers, which could +lead to kernel panic. + +For example, on .remove the component is deleted and its .unbind callback +leads to the hardware being shutdown but only if the DRM device has been +marked as registered. + +That check doesn't exist in the .shutdown logic and this can lead to the +driver calling drm_atomic_helper_shutdown() for a DRM device that hasn't +been properly initialized. + +A situation like this can happen if drivers for expected sub-devices fail +to probe, since the .bind callback will never be executed. If that is the +case, drm_atomic_helper_shutdown() will attempt to take mutexes that are +only initialized if drm_mode_config_init() is called during a device bind. + +This bug was attempted to be fixed in commit 623f279c7781 ("drm/msm: fix +shutdown hook in case GPU components failed to bind"), but unfortunately +it still happens in some cases as the one mentioned above, i.e: + + systemd-shutdown[1]: Powering off. + kvm: exiting hardware virtualization + platform wifi-firmware.0: Removing from iommu group 12 + platform video-firmware.0: Removing from iommu group 10 + ------------[ cut here ]------------ + WARNING: CPU: 6 PID: 1 at drivers/gpu/drm/drm_modeset_lock.c:317 drm_modeset_lock_all_ctx+0x3c4/0x3d0 + ... + Hardware name: Google CoachZ (rev3+) (DT) + pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : drm_modeset_lock_all_ctx+0x3c4/0x3d0 + lr : drm_modeset_lock_all_ctx+0x48/0x3d0 + sp : ffff80000805bb80 + x29: ffff80000805bb80 x28: ffff327c00128000 x27: 0000000000000000 + x26: 0000000000000000 x25: 0000000000000001 x24: ffffc95d820ec030 + x23: ffff327c00bbd090 x22: ffffc95d8215eca0 x21: ffff327c039c5800 + x20: ffff327c039c5988 x19: ffff80000805bbe8 x18: 0000000000000034 + x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 + x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 + x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 + x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 + x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 + x2 : ffff327c00128000 x1 : 0000000000000000 x0 : ffff327c039c59b0 + Call trace: + drm_modeset_lock_all_ctx+0x3c4/0x3d0 + drm_atomic_helper_shutdown+0x70/0x134 + msm_drv_shutdown+0x30/0x40 + platform_shutdown+0x28/0x40 + device_shutdown+0x148/0x350 + kernel_power_off+0x38/0x80 + __do_sys_reboot+0x288/0x2c0 + __arm64_sys_reboot+0x28/0x34 + invoke_syscall+0x48/0x114 + el0_svc_common.constprop.0+0x44/0xec + do_el0_svc+0x2c/0xc0 + el0_svc+0x2c/0x84 + el0t_64_sync_handler+0x11c/0x150 + el0t_64_sync+0x18c/0x190 + ---[ end trace 0000000000000000 ]--- + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000018 + Mem abort info: + ESR = 0x0000000096000004 + EC = 0x25: DABT (current EL), IL = 32 bits + SET = 0, FnV = 0 + EA = 0, S1PTW = 0 + FSC = 0x04: level 0 translation fault + Data abort info: + ISV = 0, ISS = 0x00000004 + CM = 0, WnR = 0 + user pgtable: 4k pages, 48-bit VAs, pgdp=000000010eab1000 + [0000000000000018] pgd=0000000000000000, p4d=0000000000000000 + Internal error: Oops: 96000004 [#1] PREEMPT SMP + ... + Hardware name: Google CoachZ (rev3+) (DT) + pstate: a0400009 (NzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : ww_mutex_lock+0x28/0x32c + lr : drm_modeset_lock_all_ctx+0x1b0/0x3d0 + sp : ffff80000805bb50 + x29: ffff80000805bb50 x28: ffff327c00128000 x27: 0000000000000000 + x26: 0000000000000000 x25: 0000000000000001 x24: 0000000000000018 + x23: ffff80000805bc10 x22: ffff327c039c5ad8 x21: ffff327c039c5800 + x20: ffff80000805bbe8 x19: 0000000000000018 x18: 0000000000000034 + x17: 000000040044ffff x16: ffffc95d80cac920 x15: 0000000000000000 + x14: 0000000000000315 x13: 0000000000000315 x12: 0000000000000000 + x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 + x8 : ffff80000805bc28 x7 : 0000000000000000 x6 : 0000000000000000 + x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 + x2 : ffff327c00128000 x1 : 0000000000000000 x0 : 0000000000000018 + Call trace: + ww_mutex_lock+0x28/0x32c + drm_modeset_lock_all_ctx+0x1b0/0x3d0 + drm_atomic_helper_shutdown+0x70/0x134 + msm_drv_shutdown+0x30/0x40 + platform_shutdown+0x28/0x40 + device_shutdown+0x148/0x350 + kernel_power_off+0x38/0x80 + __do_sys_reboot+0x288/0x2c0 + __arm64_sys_reboot+0x28/0x34 + invoke_syscall+0x48/0x114 + el0_svc_common.constprop.0+0x44/0xec + do_el0_svc+0x2c/0xc0 + el0_svc+0x2c/0x84 + el0t_64_sync_handler+0x11c/0x150 + el0t_64_sync+0x18c/0x190 + Code: aa0103f4 d503201f d2800001 aa0103e3 (c8e37c02) + ---[ end trace 0000000000000000 ]--- + Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b + Kernel Offset: 0x495d77c00000 from 0xffff800008000000 + PHYS_OFFSET: 0xffffcd8500000000 + CPU features: 0x800,00c2a015,19801c82 + Memory Limit: none + ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b ]--- + +Fixes: 9d5cbf5fe46e ("drm/msm: add shutdown support for display platform_driver") +Signed-off-by: Javier Martinez Canillas +Reviewed-by: Abhinav Kumar +Link: https://patchwork.freedesktop.org/patch/msgid/20220816134612.916527-1-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/msm_drv.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c +index 7c0314d6566a..c5f931b2574c 100644 +--- a/drivers/gpu/drm/msm/msm_drv.c ++++ b/drivers/gpu/drm/msm/msm_drv.c +@@ -1169,10 +1169,15 @@ void msm_drv_shutdown(struct platform_device *pdev) + struct msm_drm_private *priv = platform_get_drvdata(pdev); + struct drm_device *drm = priv ? priv->dev : NULL; + +- if (!priv || !priv->kms) +- return; +- +- drm_atomic_helper_shutdown(drm); ++ /* ++ * Shutdown the hw if we're far enough along where things might be on. ++ * If we run this too early, we'll end up panicking in any variety of ++ * places. Since we don't register the drm device until late in ++ * msm_drm_init, drm_dev->registered is used as an indicator that the ++ * shutdown will be successful. ++ */ ++ if (drm && drm->registered) ++ drm_atomic_helper_shutdown(drm); + } + + static struct platform_driver msm_platform_driver = { +-- +2.35.1 + diff --git a/queue-5.19/drm-nouveau-nouveau_bo-fix-potential-memory-leak-in-.patch b/queue-5.19/drm-nouveau-nouveau_bo-fix-potential-memory-leak-in-.patch new file mode 100644 index 00000000000..a93a788f1d5 --- /dev/null +++ b/queue-5.19/drm-nouveau-nouveau_bo-fix-potential-memory-leak-in-.patch @@ -0,0 +1,45 @@ +From 369125dd501158d03bfaebe992f722f9173ea6ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 17:43:06 +0800 +Subject: drm/nouveau/nouveau_bo: fix potential memory leak in + nouveau_bo_alloc() + +From: Jianglei Nie + +[ Upstream commit 6dc548745d5b5102e3c53dc5097296ac270b6c69 ] + +nouveau_bo_alloc() allocates a memory chunk for "nvbo" with kzalloc(). +When some error occurs, "nvbo" should be released. But when +WARN_ON(pi < 0)) equals true, the function return ERR_PTR without +releasing the "nvbo", which will lead to a memory leak. + +We should release the "nvbo" with kfree() if WARN_ON(pi < 0)) equals true. + +Signed-off-by: Jianglei Nie +Signed-off-by: Lyude Paul +Reviewed-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20220705094306.2244103-1-niejianglei2021@163.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nouveau_bo.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c +index e29175e4b44c..07a327ad5e2a 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -281,8 +281,10 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain, + break; + } + +- if (WARN_ON(pi < 0)) ++ if (WARN_ON(pi < 0)) { ++ kfree(nvbo); + return ERR_PTR(-EINVAL); ++ } + + /* Disable compression if suitable settings couldn't be found. */ + if (nvbo->comp && !vmm->page[pi].comp) { +-- +2.35.1 + diff --git a/queue-5.19/drm-omap-dss-fix-refcount-leak-bugs.patch b/queue-5.19/drm-omap-dss-fix-refcount-leak-bugs.patch new file mode 100644 index 00000000000..3691cabeaa0 --- /dev/null +++ b/queue-5.19/drm-omap-dss-fix-refcount-leak-bugs.patch @@ -0,0 +1,51 @@ +From e7bdf42240940674fda6d0132135006b0b17cb1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 22:43:48 +0800 +Subject: drm/omap: dss: Fix refcount leak bugs + +From: Liang He + +[ Upstream commit 8b42057e62120813ebe9274f508fa785b7cab33a ] + +In dss_init_ports() and __dss_uninit_ports(), we should call +of_node_put() for the reference returned by of_graph_get_port_by_id() +in fail path or when it is not used anymore. + +Fixes: 09bffa6e5192 ("drm: omap: use common OF graph helpers") +Signed-off-by: Liang He +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20220722144348.1306569-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/omapdrm/dss/dss.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c +index 0399f3390a0a..c4febb861910 100644 +--- a/drivers/gpu/drm/omapdrm/dss/dss.c ++++ b/drivers/gpu/drm/omapdrm/dss/dss.c +@@ -1176,6 +1176,7 @@ static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports) + default: + break; + } ++ of_node_put(port); + } + } + +@@ -1208,11 +1209,13 @@ static int dss_init_ports(struct dss_device *dss) + default: + break; + } ++ of_node_put(port); + } + + return 0; + + error: ++ of_node_put(port); + __dss_uninit_ports(dss, i); + return r; + } +-- +2.35.1 + diff --git a/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-anbernic-.patch b/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-anbernic-.patch new file mode 100644 index 00000000000..aef1c602dcb --- /dev/null +++ b/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-anbernic-.patch @@ -0,0 +1,41 @@ +From af2d6240ca65da7fff9751e7d3ce34499fbbaf4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 20:24:03 +0200 +Subject: drm: panel-orientation-quirks: Add quirk for Anbernic Win600 + +From: Maya Matuszczyk + +[ Upstream commit 770e19076065e079a32f33eb11be2057c87f1cde ] + +This device is another x86 gaming handheld, and as (hopefully) there is +only one set of DMI IDs it's using DMI_EXACT_MATCH + +Signed-off-by: Maya Matuszczyk +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Link: https://patchwork.freedesktop.org/patch/msgid/20220803182402.1217293-1-maccraft123mc@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c +index d4e0f2e85548..a8681610ede7 100644 +--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c ++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c +@@ -128,6 +128,12 @@ static const struct dmi_system_id orientation_data[] = { + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, ++ }, { /* Anbernic Win600 */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Win600"), ++ }, ++ .driver_data = (void *)&lcd720x1280_rightside_up, + }, { /* Asus T100HA */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), +-- +2.35.1 + diff --git a/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-aya-neo-a.patch b/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-aya-neo-a.patch new file mode 100644 index 00000000000..e06f690174d --- /dev/null +++ b/queue-5.19/drm-panel-orientation-quirks-add-quirk-for-aya-neo-a.patch @@ -0,0 +1,55 @@ +From 3fe6362ea0fd5eb07f0032b4fbd17ec5c5d0f8b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 21:19:47 +0200 +Subject: drm: panel-orientation-quirks: Add quirk for Aya Neo Air + +From: Maya Matuszczyk + +[ Upstream commit e10ea7b9b90219da305a16b3c1252169715a807b ] + +Yet another x86 gaming handheld. + +This one has many SKUs with quite a few of DMI strings, +so let's just use a catchall, just as with Aya Neo Next. + +Signed-off-by: Maya Matuszczyk +Signed-off-by: Hans de Goede +Link: https://patchwork.freedesktop.org/patch/msgid/20220825191946.1678798-1-maccraft123mc@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_panel_orientation_quirks.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c +index a8681610ede7..2d82f236d669 100644 +--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c ++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c +@@ -103,6 +103,12 @@ static const struct drm_dmi_panel_orientation_data lcd800x1280_rightside_up = { + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, + }; + ++static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = { ++ .width = 1080, ++ .height = 1920, ++ .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP, ++}; ++ + static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = { + .width = 1200, + .height = 1920, +@@ -158,6 +164,12 @@ static const struct dmi_system_id orientation_data[] = { + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYA NEO 2021"), + }, + .driver_data = (void *)&lcd800x1280_rightside_up, ++ }, { /* AYA NEO AIR */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), ++ DMI_MATCH(DMI_BOARD_NAME, "AIR"), ++ }, ++ .driver_data = (void *)&lcd1080x1920_leftside_up, + }, { /* AYA NEO NEXT */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"), +-- +2.35.1 + diff --git a/queue-5.19/drm-pl111-add-of_node_put-when-breaking-out-of-for_e.patch b/queue-5.19/drm-pl111-add-of_node_put-when-breaking-out-of-for_e.patch new file mode 100644 index 00000000000..015b44c5d8d --- /dev/null +++ b/queue-5.19/drm-pl111-add-of_node_put-when-breaking-out-of-for_e.patch @@ -0,0 +1,41 @@ +From e4d593e0fa97e25163f9b1af3535c652657d4ec5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Jul 2022 21:15:50 +0800 +Subject: drm:pl111: Add of_node_put() when breaking out of + for_each_available_child_of_node() + +From: Liang He + +[ Upstream commit e0686dc6f2252e009c455fe99e2ce9d62a60eb47 ] + +The reference 'child' in the iteration of for_each_available_child_of_node() +is only escaped out into a local variable which is only used to check +its value. So we still need to the of_node_put() when breaking of the +for_each_available_child_of_node() which will automatically increase +and decrease the refcount. + +Fixes: ca454bd42dc2 ("drm/pl111: Support the Versatile Express") +Signed-off-by: Liang He +Reviewed-by: Rob Herring +Signed-off-by: Daniel Vetter +Link: https://patchwork.freedesktop.org/patch/msgid/20220711131550.361350-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/pl111/pl111_versatile.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c +index bdd883f4f0da..963a5d5e6987 100644 +--- a/drivers/gpu/drm/pl111/pl111_versatile.c ++++ b/drivers/gpu/drm/pl111/pl111_versatile.c +@@ -402,6 +402,7 @@ static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np, + if (of_device_is_compatible(child, "arm,pl111")) { + has_coretile_clcd = true; + ct_clcd = child; ++ of_node_put(child); + break; + } + if (of_device_is_compatible(child, "arm,hdlcd")) { +-- +2.35.1 + diff --git a/queue-5.19/drm-prevent-drm_copy_field-to-attempt-copying-a-null.patch b/queue-5.19/drm-prevent-drm_copy_field-to-attempt-copying-a-null.patch new file mode 100644 index 00000000000..a9871f49a92 --- /dev/null +++ b/queue-5.19/drm-prevent-drm_copy_field-to-attempt-copying-a-null.patch @@ -0,0 +1,87 @@ +From 95e651c37b4e0668f98602accd1941c89792d10e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 12:02:14 +0200 +Subject: drm: Prevent drm_copy_field() to attempt copying a NULL pointer + +From: Javier Martinez Canillas + +[ Upstream commit f6ee30407e883042482ad4ad30da5eaba47872ee ] + +There are some struct drm_driver fields that are required by drivers since +drm_copy_field() attempts to copy them to user-space via DRM_IOCTL_VERSION. + +But it can be possible that a driver has a bug and did not set some of the +fields, which leads to drm_copy_field() attempting to copy a NULL pointer: + +[ +10.395966] Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000000000000000 +[ +0.010955] Mem abort info: +[ +0.002835] ESR = 0x0000000096000004 +[ +0.003872] EC = 0x25: DABT (current EL), IL = 32 bits +[ +0.005395] SET = 0, FnV = 0 +[ +0.003113] EA = 0, S1PTW = 0 +[ +0.003182] FSC = 0x04: level 0 translation fault +[ +0.004964] Data abort info: +[ +0.002919] ISV = 0, ISS = 0x00000004 +[ +0.003886] CM = 0, WnR = 0 +[ +0.003040] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000115dad000 +[ +0.006536] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000 +[ +0.006925] Internal error: Oops: 96000004 [#1] SMP +... +[ +0.011113] pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ +0.007061] pc : __pi_strlen+0x14/0x150 +[ +0.003895] lr : drm_copy_field+0x30/0x1a4 +[ +0.004156] sp : ffff8000094b3a50 +[ +0.003355] x29: ffff8000094b3a50 x28: ffff8000094b3b70 x27: 0000000000000040 +[ +0.007242] x26: ffff443743c2ba00 x25: 0000000000000000 x24: 0000000000000040 +[ +0.007243] x23: ffff443743c2ba00 x22: ffff8000094b3b70 x21: 0000000000000000 +[ +0.007241] x20: 0000000000000000 x19: ffff8000094b3b90 x18: 0000000000000000 +[ +0.007241] x17: 0000000000000000 x16: 0000000000000000 x15: 0000aaab14b9af40 +[ +0.007241] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 +[ +0.007239] x11: 0000000000000000 x10: 0000000000000000 x9 : ffffa524ad67d4d8 +[ +0.007242] x8 : 0101010101010101 x7 : 7f7f7f7f7f7f7f7f x6 : 6c6e6263606e7141 +[ +0.007239] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000000 +[ +0.007241] x2 : 0000000000000000 x1 : ffff8000094b3b90 x0 : 0000000000000000 +[ +0.007240] Call trace: +[ +0.002475] __pi_strlen+0x14/0x150 +[ +0.003537] drm_version+0x84/0xac +[ +0.003448] drm_ioctl_kernel+0xa8/0x16c +[ +0.003975] drm_ioctl+0x270/0x580 +[ +0.003448] __arm64_sys_ioctl+0xb8/0xfc +[ +0.003978] invoke_syscall+0x78/0x100 +[ +0.003799] el0_svc_common.constprop.0+0x4c/0xf4 +[ +0.004767] do_el0_svc+0x38/0x4c +[ +0.003357] el0_svc+0x34/0x100 +[ +0.003185] el0t_64_sync_handler+0x11c/0x150 +[ +0.004418] el0t_64_sync+0x190/0x194 +[ +0.003716] Code: 92402c04 b200c3e8 f13fc09f 5400088c (a9400c02) +[ +0.006180] ---[ end trace 0000000000000000 ]--- + +Reported-by: Peter Robinson +Signed-off-by: Javier Martinez Canillas +Acked-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/20220705100215.572498-3-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_ioctl.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c +index e6895699e696..7f1097947731 100644 +--- a/drivers/gpu/drm/drm_ioctl.c ++++ b/drivers/gpu/drm/drm_ioctl.c +@@ -474,6 +474,12 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) + { + size_t len; + ++ /* don't attempt to copy a NULL pointer */ ++ if (WARN_ONCE(!value, "BUG: the value to copy was not set!")) { ++ *buf_len = 0; ++ return 0; ++ } ++ + /* don't overflow userbuf */ + len = strlen(value); + if (len > *buf_len) +-- +2.35.1 + diff --git a/queue-5.19/drm-use-size_t-type-for-len-variable-in-drm_copy_fie.patch b/queue-5.19/drm-use-size_t-type-for-len-variable-in-drm_copy_fie.patch new file mode 100644 index 00000000000..100f291ab8a --- /dev/null +++ b/queue-5.19/drm-use-size_t-type-for-len-variable-in-drm_copy_fie.patch @@ -0,0 +1,48 @@ +From ca654d3f1d0041e429140a6fc9ee16b19eb6b03b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 12:02:13 +0200 +Subject: drm: Use size_t type for len variable in drm_copy_field() + +From: Javier Martinez Canillas + +[ Upstream commit 94dc3471d1b2b58b3728558d0e3f264e9ce6ff59 ] + +The strlen() function returns a size_t which is an unsigned int on 32-bit +arches and an unsigned long on 64-bit arches. But in the drm_copy_field() +function, the strlen() return value is assigned to an 'int len' variable. + +Later, the len variable is passed as copy_from_user() third argument that +is an unsigned long parameter as well. + +In theory, this can lead to an integer overflow via type conversion. Since +the assignment happens to a signed int lvalue instead of a size_t lvalue. + +In practice though, that's unlikely since the values copied are set by DRM +drivers and not controlled by userspace. But using a size_t for len is the +correct thing to do anyways. + +Signed-off-by: Javier Martinez Canillas +Tested-by: Peter Robinson +Reviewed-by: Thomas Zimmermann +Link: https://patchwork.freedesktop.org/patch/msgid/20220705100215.572498-2-javierm@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/drm_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c +index 51fcf1298023..e6895699e696 100644 +--- a/drivers/gpu/drm/drm_ioctl.c ++++ b/drivers/gpu/drm/drm_ioctl.c +@@ -472,7 +472,7 @@ EXPORT_SYMBOL(drm_invalid_op); + */ + static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) + { +- int len; ++ size_t len; + + /* don't overflow userbuf */ + len = strlen(value); +-- +2.35.1 + diff --git a/queue-5.19/drm-vc4-txp-protect-device-resources.patch b/queue-5.19/drm-vc4-txp-protect-device-resources.patch new file mode 100644 index 00000000000..c8f479bfa88 --- /dev/null +++ b/queue-5.19/drm-vc4-txp-protect-device-resources.patch @@ -0,0 +1,120 @@ +From 1c61fad57e773675290342698d815fd0fb0debff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Jul 2022 19:39:23 +0200 +Subject: drm/vc4: txp: Protect device resources + +From: Maxime Ripard + +[ Upstream commit b7345c9799da578c150fde3072446e4049c39c41 ] + +Our current code now mixes some resources whose lifetime are tied to the +device (clocks, IO mappings, etc.) and some that are tied to the DRM device +(encoder, bridge). + +The device one will be freed at unbind time, but the DRM one will only be +freed when the last user of the DRM device closes its file handle. + +So we end up with a time window during which we can call the encoder hooks, +but we don't have access to the underlying resources and device. + +Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so +that we bail out if we are during that window. + +Acked-by: Thomas Zimmermann +Signed-off-by: Maxime Ripard +Link: https://lore.kernel.org/r/20220711173939.1132294-54-maxime@cerno.tech +Stable-dep-of: 84dfc46594b0 ("drm/panel: use 'select' for Ili9341 panel driver helpers") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vc4/vc4_txp.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c +index 3579d487402e..acc72fe1e113 100644 +--- a/drivers/gpu/drm/vc4/vc4_txp.c ++++ b/drivers/gpu/drm/vc4/vc4_txp.c +@@ -15,6 +15,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -275,6 +276,7 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn, + static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, + struct drm_atomic_state *state) + { ++ struct drm_device *drm = conn->dev; + struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, + conn); + struct vc4_txp *txp = connector_to_vc4_txp(conn); +@@ -282,6 +284,7 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, + struct drm_display_mode *mode; + struct drm_framebuffer *fb; + u32 ctrl; ++ int idx; + int i; + + if (WARN_ON(!conn_state->writeback_job)) +@@ -311,6 +314,9 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, + */ + ctrl |= TXP_ALPHA_INVERT; + ++ if (!drm_dev_enter(drm, &idx)) ++ return; ++ + gem = drm_fb_cma_get_gem_obj(fb, 0); + TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]); + TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]); +@@ -321,6 +327,8 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn, + TXP_WRITE(TXP_DST_CTRL, ctrl); + + drm_writeback_queue_job(&txp->connector, conn_state); ++ ++ drm_dev_exit(idx); + } + + static const struct drm_connector_helper_funcs vc4_txp_connector_helper_funcs = { +@@ -353,7 +361,12 @@ static const struct drm_connector_funcs vc4_txp_connector_funcs = { + + static void vc4_txp_encoder_disable(struct drm_encoder *encoder) + { ++ struct drm_device *drm = encoder->dev; + struct vc4_txp *txp = encoder_to_vc4_txp(encoder); ++ int idx; ++ ++ if (!drm_dev_enter(drm, &idx)) ++ return; + + if (TXP_READ(TXP_DST_CTRL) & TXP_BUSY) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); +@@ -368,6 +381,8 @@ static void vc4_txp_encoder_disable(struct drm_encoder *encoder) + } + + TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN); ++ ++ drm_dev_exit(idx); + } + + static const struct drm_encoder_helper_funcs vc4_txp_encoder_helper_funcs = { +@@ -452,6 +467,16 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data) + struct vc4_txp *txp = data; + struct vc4_crtc *vc4_crtc = &txp->base; + ++ /* ++ * We don't need to protect the register access using ++ * drm_dev_enter() there because the interrupt handler lifetime ++ * is tied to the device itself, and not to the DRM device. ++ * ++ * So when the device will be gone, one of the first thing we ++ * will be doing will be to unregister the interrupt handler, ++ * and then unregister the DRM device. drm_dev_enter() would ++ * thus always succeed if we are here. ++ */ + TXP_WRITE(TXP_DST_CTRL, TXP_READ(TXP_DST_CTRL) & ~TXP_EI); + vc4_crtc_handle_vblank(vc4_crtc); + drm_writeback_signal_completion(&txp->connector, 0); +-- +2.35.1 + diff --git a/queue-5.19/drm-vc4-vec-fix-timings-for-vec-modes.patch b/queue-5.19/drm-vc4-vec-fix-timings-for-vec-modes.patch new file mode 100644 index 00000000000..0991e43df7b --- /dev/null +++ b/queue-5.19/drm-vc4-vec-fix-timings-for-vec-modes.patch @@ -0,0 +1,54 @@ +From acbc9592f9acf5a6c7d3658b0820ef4cd2bb2e2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 15:11:42 +0200 +Subject: drm/vc4: vec: Fix timings for VEC modes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mateusz Kwiatkowski + +[ Upstream commit 30d7565be96b3946c18a1ce3fd538f7946839092 ] + +This commit fixes vertical timings of the VEC (composite output) modes +to accurately represent the 525-line ("NTSC") and 625-line ("PAL") ITU-R +standards. + +Previous timings were actually defined as 502 and 601 lines, resulting +in non-standard 62.69 Hz and 52 Hz signals being generated, +respectively. + +Signed-off-by: Mateusz Kwiatkowski +Acked-by: Noralf Trønnes +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20220728-rpi-analog-tv-properties-v2-28-459522d653a7@cerno.tech +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vc4/vc4_vec.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c +index 11fc3d6f66b1..4e2250b8fa23 100644 +--- a/drivers/gpu/drm/vc4/vc4_vec.c ++++ b/drivers/gpu/drm/vc4/vc4_vec.c +@@ -256,7 +256,7 @@ static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec) + static const struct drm_display_mode ntsc_mode = { + DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500, + 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0, +- 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0, ++ 480, 480 + 7, 480 + 7 + 6, 525, 0, + DRM_MODE_FLAG_INTERLACE) + }; + +@@ -278,7 +278,7 @@ static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec) + static const struct drm_display_mode pal_mode = { + DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500, + 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0, +- 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0, ++ 576, 576 + 4, 576 + 4 + 6, 625, 0, + DRM_MODE_FLAG_INTERLACE) + }; + +-- +2.35.1 + diff --git a/queue-5.19/drm-virtio-correct-drm_gem_shmem_get_sg_table-error-.patch b/queue-5.19/drm-virtio-correct-drm_gem_shmem_get_sg_table-error-.patch new file mode 100644 index 00000000000..d5fcccbe56b --- /dev/null +++ b/queue-5.19/drm-virtio-correct-drm_gem_shmem_get_sg_table-error-.patch @@ -0,0 +1,39 @@ +From 3fdb147a601512b010181e008ef4cbaf62e08b50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jun 2022 23:07:18 +0300 +Subject: drm/virtio: Correct drm_gem_shmem_get_sg_table() error handling + +From: Dmitry Osipenko + +[ Upstream commit 64b88afbd92fbf434759d1896a7cf705e1c00e79 ] + +Previous commit fixed checking of the ERR_PTR value returned by +drm_gem_shmem_get_sg_table(), but it missed to zero out the shmem->pages, +which will crash virtio_gpu_cleanup_object(). Add the missing zeroing of +the shmem->pages. + +Fixes: c24968734abf ("drm/virtio: Fix NULL vs IS_ERR checking in virtio_gpu_object_shmem_init") +Reviewed-by: Emil Velikov +Signed-off-by: Dmitry Osipenko +Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-2-dmitry.osipenko@collabora.com +Signed-off-by: Gerd Hoffmann +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/virtio/virtgpu_object.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c +index b38c338211aa..75a159df0af6 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_object.c ++++ b/drivers/gpu/drm/virtio/virtgpu_object.c +@@ -170,6 +170,7 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, + shmem->pages = drm_gem_shmem_get_sg_table(&bo->base); + if (IS_ERR(shmem->pages)) { + drm_gem_shmem_unpin(&bo->base); ++ shmem->pages = NULL; + return PTR_ERR(shmem->pages); + } + +-- +2.35.1 + diff --git a/queue-5.19/drm-virtio-fix-same-context-optimization.patch b/queue-5.19/drm-virtio-fix-same-context-optimization.patch new file mode 100644 index 00000000000..b923b266b0d --- /dev/null +++ b/queue-5.19/drm-virtio-fix-same-context-optimization.patch @@ -0,0 +1,38 @@ +From abacfcc29d1851bf3b97b50577acb6e30d00a199 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Aug 2022 15:40:00 -0700 +Subject: drm/virtio: Fix same-context optimization + +From: Rob Clark + +[ Upstream commit 3007dc2af6e86ac00b4daf7414142637fdf50bfa ] + +When VIRTGPU_EXECBUF_RING_IDX is used, we should be considering the +timeline that the EB if running on rather than the global driver fence +context. + +Fixes: 85c83ea915ed ("drm/virtio: implement context init: allocate an array of fence contexts") +Signed-off-by: Rob Clark +Link: http://patchwork.freedesktop.org/patch/msgid/20220812224001.2806463-1-robdclark@gmail.com +Signed-off-by: Gerd Hoffmann +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/virtio/virtgpu_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +index 9b2702116f93..3b1701607aae 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c ++++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +@@ -168,7 +168,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, + * array contains any fence from a foreign context. + */ + ret = 0; +- if (!dma_fence_match_context(in_fence, vgdev->fence_drv.context)) ++ if (!dma_fence_match_context(in_fence, fence_ctx + ring_idx)) + ret = dma_fence_wait(in_fence, true); + + dma_fence_put(in_fence); +-- +2.35.1 + diff --git a/queue-5.19/drm-virtio-set-fb_modifiers_not_supported.patch b/queue-5.19/drm-virtio-set-fb_modifiers_not_supported.patch new file mode 100644 index 00000000000..f8c1fcf2b22 --- /dev/null +++ b/queue-5.19/drm-virtio-set-fb_modifiers_not_supported.patch @@ -0,0 +1,41 @@ +From 85f2e154e1be16e51bac2cabf86ab775a7a6c31d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 12:06:01 -0700 +Subject: drm/virtio: set fb_modifiers_not_supported + +From: Chia-I Wu + +[ Upstream commit 85faca8ca0f659263b5fb2385e4c231cc075bd84 ] + +Without this, the drm core advertises LINEAR modifier which is +incorrect. + +Also userspace virgl does not support modifiers. For example, it causes +chrome on ozone/drm to fail with "Failed to create scanout buffer". + +Fixes: 2af104290da5 ("drm: introduce fb_modifiers_not_supported flag in mode_config") +Suggested-by: Shao-Chuan Lee +Signed-off-by: Chia-I Wu +Link: http://patchwork.freedesktop.org/patch/msgid/20220831190601.1295129-1-olvaffe@gmail.com +Signed-off-by: Gerd Hoffmann +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/virtio/virtgpu_display.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c +index f73352e7b832..96e71813864a 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_display.c ++++ b/drivers/gpu/drm/virtio/virtgpu_display.c +@@ -348,6 +348,8 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) + vgdev->ddev->mode_config.max_width = XRES_MAX; + vgdev->ddev->mode_config.max_height = YRES_MAX; + ++ vgdev->ddev->mode_config.fb_modifiers_not_supported = true; ++ + for (i = 0 ; i < vgdev->num_scanouts; ++i) + vgdev_output_init(vgdev, i); + +-- +2.35.1 + diff --git a/queue-5.19/drm-vmwgfx-fix-memory-leak-in-vmw_mksstat_add_ioctl.patch b/queue-5.19/drm-vmwgfx-fix-memory-leak-in-vmw_mksstat_add_ioctl.patch new file mode 100644 index 00000000000..3794d9f8c72 --- /dev/null +++ b/queue-5.19/drm-vmwgfx-fix-memory-leak-in-vmw_mksstat_add_ioctl.patch @@ -0,0 +1,38 @@ +From ea4d20f3af03326a348ef794a5bb3814f963971b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 17:47:51 -0300 +Subject: drm/vmwgfx: Fix memory leak in vmw_mksstat_add_ioctl() + +From: Rafael Mendonca + +[ Upstream commit a40c7f61d12fbd1e785e59140b9efd57127c0c33 ] + +If the copy of the description string from userspace fails, then the page +for the instance descriptor doesn't get freed before returning -EFAULT, +which leads to a memleak. + +Fixes: 7a7a933edd6c ("drm/vmwgfx: Introduce VMware mks-guest-stats") +Signed-off-by: Rafael Mendonca +Reviewed-by: Martin Krastev +Signed-off-by: Zack Rusin +Link: https://patchwork.freedesktop.org/patch/msgid/20220916204751.720716-1-rafaelmendsr@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vmwgfx/vmwgfx_msg.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +index 2aceac7856e2..089046fa21be 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c +@@ -1076,6 +1076,7 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data, + + if (desc_len < 0) { + atomic_set(&dev_priv->mksstat_user_pids[slot], 0); ++ __free_page(page); + return -EFAULT; + } + +-- +2.35.1 + diff --git a/queue-5.19/dt-bindings-clock-exynosautov9-correct-clock-numberi.patch b/queue-5.19/dt-bindings-clock-exynosautov9-correct-clock-numberi.patch new file mode 100644 index 00000000000..f324501d715 --- /dev/null +++ b/queue-5.19/dt-bindings-clock-exynosautov9-correct-clock-numberi.patch @@ -0,0 +1,103 @@ +From 80126339414d49b67afb92ec2f4e1803f3d65bbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 11:13:55 +0900 +Subject: dt-bindings: clock: exynosautov9: correct clock numbering of + peric0/c1 + +From: Chanho Park + +[ Upstream commit b6740089b740b842d5e6ff55b4b2c3bf5961c69a ] + +There are duplicated definitions of peric0 and peric1 cmu blocks. Thus, +they should be defined correctly as numerical order. + +Fixes: 680e1c8370a2 ("dt-bindings: clock: add clock binding definitions for Exynos Auto v9") +Signed-off-by: Chanho Park +Reviewed-by: Krzysztof Kozlowski +Acked-by: Chanwoo Choi +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220727021357.152421-2-chanho61.park@samsung.com +Signed-off-by: Sasha Levin +--- + .../dt-bindings/clock/samsung,exynosautov9.h | 56 +++++++++---------- + 1 file changed, 28 insertions(+), 28 deletions(-) + +diff --git a/include/dt-bindings/clock/samsung,exynosautov9.h b/include/dt-bindings/clock/samsung,exynosautov9.h +index ea9f91b4eb1a..a7db6516593f 100644 +--- a/include/dt-bindings/clock/samsung,exynosautov9.h ++++ b/include/dt-bindings/clock/samsung,exynosautov9.h +@@ -226,21 +226,21 @@ + #define CLK_GOUT_PERIC0_IPCLK_8 28 + #define CLK_GOUT_PERIC0_IPCLK_9 29 + #define CLK_GOUT_PERIC0_IPCLK_10 30 +-#define CLK_GOUT_PERIC0_IPCLK_11 30 +-#define CLK_GOUT_PERIC0_PCLK_0 31 +-#define CLK_GOUT_PERIC0_PCLK_1 32 +-#define CLK_GOUT_PERIC0_PCLK_2 33 +-#define CLK_GOUT_PERIC0_PCLK_3 34 +-#define CLK_GOUT_PERIC0_PCLK_4 35 +-#define CLK_GOUT_PERIC0_PCLK_5 36 +-#define CLK_GOUT_PERIC0_PCLK_6 37 +-#define CLK_GOUT_PERIC0_PCLK_7 38 +-#define CLK_GOUT_PERIC0_PCLK_8 39 +-#define CLK_GOUT_PERIC0_PCLK_9 40 +-#define CLK_GOUT_PERIC0_PCLK_10 41 +-#define CLK_GOUT_PERIC0_PCLK_11 42 ++#define CLK_GOUT_PERIC0_IPCLK_11 31 ++#define CLK_GOUT_PERIC0_PCLK_0 32 ++#define CLK_GOUT_PERIC0_PCLK_1 33 ++#define CLK_GOUT_PERIC0_PCLK_2 34 ++#define CLK_GOUT_PERIC0_PCLK_3 35 ++#define CLK_GOUT_PERIC0_PCLK_4 36 ++#define CLK_GOUT_PERIC0_PCLK_5 37 ++#define CLK_GOUT_PERIC0_PCLK_6 38 ++#define CLK_GOUT_PERIC0_PCLK_7 39 ++#define CLK_GOUT_PERIC0_PCLK_8 40 ++#define CLK_GOUT_PERIC0_PCLK_9 41 ++#define CLK_GOUT_PERIC0_PCLK_10 42 ++#define CLK_GOUT_PERIC0_PCLK_11 43 + +-#define PERIC0_NR_CLK 43 ++#define PERIC0_NR_CLK 44 + + /* CMU_PERIC1 */ + #define CLK_MOUT_PERIC1_BUS_USER 1 +@@ -272,21 +272,21 @@ + #define CLK_GOUT_PERIC1_IPCLK_8 28 + #define CLK_GOUT_PERIC1_IPCLK_9 29 + #define CLK_GOUT_PERIC1_IPCLK_10 30 +-#define CLK_GOUT_PERIC1_IPCLK_11 30 +-#define CLK_GOUT_PERIC1_PCLK_0 31 +-#define CLK_GOUT_PERIC1_PCLK_1 32 +-#define CLK_GOUT_PERIC1_PCLK_2 33 +-#define CLK_GOUT_PERIC1_PCLK_3 34 +-#define CLK_GOUT_PERIC1_PCLK_4 35 +-#define CLK_GOUT_PERIC1_PCLK_5 36 +-#define CLK_GOUT_PERIC1_PCLK_6 37 +-#define CLK_GOUT_PERIC1_PCLK_7 38 +-#define CLK_GOUT_PERIC1_PCLK_8 39 +-#define CLK_GOUT_PERIC1_PCLK_9 40 +-#define CLK_GOUT_PERIC1_PCLK_10 41 +-#define CLK_GOUT_PERIC1_PCLK_11 42 ++#define CLK_GOUT_PERIC1_IPCLK_11 31 ++#define CLK_GOUT_PERIC1_PCLK_0 32 ++#define CLK_GOUT_PERIC1_PCLK_1 33 ++#define CLK_GOUT_PERIC1_PCLK_2 34 ++#define CLK_GOUT_PERIC1_PCLK_3 35 ++#define CLK_GOUT_PERIC1_PCLK_4 36 ++#define CLK_GOUT_PERIC1_PCLK_5 37 ++#define CLK_GOUT_PERIC1_PCLK_6 38 ++#define CLK_GOUT_PERIC1_PCLK_7 39 ++#define CLK_GOUT_PERIC1_PCLK_8 40 ++#define CLK_GOUT_PERIC1_PCLK_9 41 ++#define CLK_GOUT_PERIC1_PCLK_10 42 ++#define CLK_GOUT_PERIC1_PCLK_11 43 + +-#define PERIC1_NR_CLK 43 ++#define PERIC1_NR_CLK 44 + + /* CMU_PERIS */ + #define CLK_MOUT_PERIS_BUS_USER 1 +-- +2.35.1 + diff --git a/queue-5.19/dt-bindings-timer-add-nomadik-mtu-binding.patch b/queue-5.19/dt-bindings-timer-add-nomadik-mtu-binding.patch new file mode 100644 index 00000000000..129279b8d06 --- /dev/null +++ b/queue-5.19/dt-bindings-timer-add-nomadik-mtu-binding.patch @@ -0,0 +1,93 @@ +From 165c5be60efde331323be294db5946a85efb27cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 26 May 2022 23:36:21 +0200 +Subject: dt-bindings: timer: Add Nomadik MTU binding + +From: Linus Walleij + +[ Upstream commit d6513a34926f4f4b331be115819702ca2a4682fb ] + +The Nomadik MTU timer has been used in devicetrees forever +but somehow we missed to add a binding for it. Fix it +by simply adding it. + +Cc: Lee Jones +Cc: devicetree@vger.kernel.org +Signed-off-by: Linus Walleij +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20220526213621.373727-1-linus.walleij@linaro.org +Signed-off-by: Daniel Lezcano +Stable-dep-of: 6c3b62d93e19 ("clocksource/drivers/arm_arch_timer: Fix handling of ARM erratum 858921") +Signed-off-by: Sasha Levin +--- + .../bindings/timer/st,nomadik-mtu.yaml | 58 +++++++++++++++++++ + 1 file changed, 58 insertions(+) + create mode 100644 Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml + +diff --git a/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml b/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml +new file mode 100644 +index 000000000000..901848d298ec +--- /dev/null ++++ b/Documentation/devicetree/bindings/timer/st,nomadik-mtu.yaml +@@ -0,0 +1,58 @@ ++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) ++# Copyright 2022 Linaro Ltd. ++%YAML 1.2 ++--- ++$id: "http://devicetree.org/schemas/timer/st,nomadik-mtu.yaml#" ++$schema: "http://devicetree.org/meta-schemas/core.yaml#" ++ ++title: ST Microelectronics Nomadik Multi-Timer Unit MTU Timer ++ ++maintainers: ++ - Linus Walleij ++ ++description: This timer is found in the ST Microelectronics Nomadik ++ SoCs STn8800, STn8810 and STn8815 as well as in ST-Ericsson DB8500. ++ ++properties: ++ compatible: ++ items: ++ - const: st,nomadik-mtu ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ clocks: ++ description: The first clock named TIMCLK clocks the actual timers and ++ the second clock clocks the digital interface to the interconnect. ++ maxItems: 2 ++ ++ clock-names: ++ items: ++ - const: timclk ++ - const: apb_pclk ++ ++required: ++ - compatible ++ - reg ++ - interrupts ++ - clocks ++ - clock-names ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ #include ++ timer@a03c6000 { ++ compatible = "st,nomadik-mtu"; ++ reg = <0xa03c6000 0x1000>; ++ interrupts = ; ++ ++ clocks = <&prcmu_clk PRCMU_TIMCLK>, <&prcc_pclk 6 6>; ++ clock-names = "timclk", "apb_pclk"; ++ }; +-- +2.35.1 + diff --git a/queue-5.19/dyndbg-drop-exported-dynamic_debug_exec_queries.patch b/queue-5.19/dyndbg-drop-exported-dynamic_debug_exec_queries.patch new file mode 100644 index 00000000000..4b1fbc15767 --- /dev/null +++ b/queue-5.19/dyndbg-drop-exported-dynamic_debug_exec_queries.patch @@ -0,0 +1,99 @@ +From d089d8dbd9f6d3a5b3b436246ee0b59721f59ddc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 15:40:46 -0600 +Subject: dyndbg: drop EXPORTed dynamic_debug_exec_queries + +From: Jim Cromie + +[ Upstream commit e26ef3af964acfea311403126acee8c56c89e26b ] + +This exported fn is unused, and will not be needed. Lets dump it. + +The export was added to let drm control pr_debugs, as part of using +them to avoid drm_debug_enabled overheads. But its better to just +implement the drm.debug bitmap interface, then its available for +everyone. + +Fixes: a2d375eda771 ("dyndbg: refine export, rename to dynamic_debug_exec_queries()") +Fixes: 4c0d77828d4f ("dyndbg: export ddebug_exec_queries") +Acked-by: Jason Baron +Acked-by: Daniel Vetter +Signed-off-by: Jim Cromie +Link: https://lore.kernel.org/r/20220904214134.408619-10-jim.cromie@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + include/linux/dynamic_debug.h | 9 --------- + lib/dynamic_debug.c | 29 ----------------------------- + 2 files changed, 38 deletions(-) + +diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h +index f30b01aa9fa4..8d9eec5f6d8b 100644 +--- a/include/linux/dynamic_debug.h ++++ b/include/linux/dynamic_debug.h +@@ -55,9 +55,6 @@ struct _ddebug { + + #if defined(CONFIG_DYNAMIC_DEBUG_CORE) + +-/* exported for module authors to exercise >control */ +-int dynamic_debug_exec_queries(const char *query, const char *modname); +- + int ddebug_add_module(struct _ddebug *tab, unsigned int n, + const char *modname); + extern int ddebug_remove_module(const char *mod_name); +@@ -221,12 +218,6 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, + rowsize, groupsize, buf, len, ascii); \ + } while (0) + +-static inline int dynamic_debug_exec_queries(const char *query, const char *modname) +-{ +- pr_warn("kernel not built with CONFIG_DYNAMIC_DEBUG_CORE\n"); +- return 0; +-} +- + #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */ + + #endif +diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c +index 4d168efcf779..c9b3d9e5d470 100644 +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -557,35 +557,6 @@ static int ddebug_exec_queries(char *query, const char *modname) + return nfound; + } + +-/** +- * dynamic_debug_exec_queries - select and change dynamic-debug prints +- * @query: query-string described in admin-guide/dynamic-debug-howto +- * @modname: string containing module name, usually &module.mod_name +- * +- * This uses the >/proc/dynamic_debug/control reader, allowing module +- * authors to modify their dynamic-debug callsites. The modname is +- * canonically struct module.mod_name, but can also be null or a +- * module-wildcard, for example: "drm*". +- */ +-int dynamic_debug_exec_queries(const char *query, const char *modname) +-{ +- int rc; +- char *qry; /* writable copy of query */ +- +- if (!query) { +- pr_err("non-null query/command string expected\n"); +- return -EINVAL; +- } +- qry = kstrndup(query, PAGE_SIZE, GFP_KERNEL); +- if (!qry) +- return -ENOMEM; +- +- rc = ddebug_exec_queries(qry, modname); +- kfree(qry); +- return rc; +-} +-EXPORT_SYMBOL_GPL(dynamic_debug_exec_queries); +- + #define PREFIX_SIZE 64 + + static int remaining(int wrote) +-- +2.35.1 + diff --git a/queue-5.19/dyndbg-fix-module.dyndbg-handling.patch b/queue-5.19/dyndbg-fix-module.dyndbg-handling.patch new file mode 100644 index 00000000000..be687549f7b --- /dev/null +++ b/queue-5.19/dyndbg-fix-module.dyndbg-handling.patch @@ -0,0 +1,52 @@ +From 46158bcb6b77e2625f804af534fb727caf6c9196 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 15:40:39 -0600 +Subject: dyndbg: fix module.dyndbg handling + +From: Jim Cromie + +[ Upstream commit 85d6b66d31c35158364058ee98fb69ab5bb6a6b1 ] + +For CONFIG_DYNAMIC_DEBUG=N, the ddebug_dyndbg_module_param_cb() +stub-fn is too permissive: + +bash-5.1# modprobe drm JUNKdyndbg +bash-5.1# modprobe drm dyndbgJUNK +[ 42.933220] dyndbg param is supported only in CONFIG_DYNAMIC_DEBUG builds +[ 42.937484] ACPI: bus type drm_connector registered + +This caused no ill effects, because unknown parameters are either +ignored by default with an "unknown parameter" warning, or ignored +because dyndbg allows its no-effect use on non-dyndbg builds. + +But since the code has an explicit feedback message, it should be +issued accurately. Fix with strcmp for exact param-name match. + +Fixes: b48420c1d301 dynamic_debug: make dynamic-debug work for module initialization +Reported-by: Rasmus Villemoes +Acked-by: Jason Baron +Acked-by: Daniel Vetter +Signed-off-by: Jim Cromie +Link: https://lore.kernel.org/r/20220904214134.408619-3-jim.cromie@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + include/linux/dynamic_debug.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h +index dce631e678dd..f30b01aa9fa4 100644 +--- a/include/linux/dynamic_debug.h ++++ b/include/linux/dynamic_debug.h +@@ -201,7 +201,7 @@ static inline int ddebug_remove_module(const char *mod) + static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, + const char *modname) + { +- if (strstr(param, "dyndbg")) { ++ if (!strcmp(param, "dyndbg")) { + /* avoid pr_warn(), which wants pr_fmt() fully defined */ + printk(KERN_WARNING "dyndbg param is supported only in " + "CONFIG_DYNAMIC_DEBUG builds\n"); +-- +2.35.1 + diff --git a/queue-5.19/dyndbg-fix-static_branch-manipulation.patch b/queue-5.19/dyndbg-fix-static_branch-manipulation.patch new file mode 100644 index 00000000000..dcf6ca78a19 --- /dev/null +++ b/queue-5.19/dyndbg-fix-static_branch-manipulation.patch @@ -0,0 +1,74 @@ +From a7d41ff1f9775d38a34176f4b2d08d8e11987dd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 15:40:38 -0600 +Subject: dyndbg: fix static_branch manipulation + +From: Jim Cromie + +[ Upstream commit ee879be38bc87f8cedc79ae2742958db6533ca59 ] + +In https://lore.kernel.org/lkml/20211209150910.GA23668@axis.com/ + +Vincent's patch commented on, and worked around, a bug toggling +static_branch's, when a 2nd PRINTK-ish flag was added. The bug +results in a premature static_branch_disable when the 1st of 2 flags +was disabled. + +The cited commit computed newflags, but then in the JUMP_LABEL block, +failed to use that result, instead using just one of the terms in it. +Using newflags instead made the code work properly. + +This is Vincents test-case, reduced. It needs the 2nd flag to +demonstrate the bug, but it's explanatory here. + +pt_test() { + echo 5 > /sys/module/dynamic_debug/verbose + + site="module tcp" # just one callsite + echo " $site =_ " > /proc/dynamic_debug/control # clear it + + # A B ~A ~B + for flg in +T +p "-T #broke here" -p; do + echo " $site $flg " > /proc/dynamic_debug/control + done; + + # A B ~B ~A + for flg in +T +p "-p #broke here" -T; do + echo " $site $flg " > /proc/dynamic_debug/control + done +} +pt_test + +Fixes: 84da83a6ffc0 dyndbg: combine flags & mask into a struct, simplify with it +CC: vincent.whitchurch@axis.com +Acked-by: Jason Baron +Acked-by: Daniel Vetter +Signed-off-by: Jim Cromie +Link: https://lore.kernel.org/r/20220904214134.408619-2-jim.cromie@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/dynamic_debug.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c +index dd7f56af9aed..a56c1286ffa4 100644 +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -211,10 +211,11 @@ static int ddebug_change(const struct ddebug_query *query, + continue; + #ifdef CONFIG_JUMP_LABEL + if (dp->flags & _DPRINTK_FLAGS_PRINT) { +- if (!(modifiers->flags & _DPRINTK_FLAGS_PRINT)) ++ if (!(newflags & _DPRINTK_FLAGS_PRINT)) + static_branch_disable(&dp->key.dd_key_true); +- } else if (modifiers->flags & _DPRINTK_FLAGS_PRINT) ++ } else if (newflags & _DPRINTK_FLAGS_PRINT) { + static_branch_enable(&dp->key.dd_key_true); ++ } + #endif + dp->flags = newflags; + v4pr_info("changed %s:%d [%s]%s =%s\n", +-- +2.35.1 + diff --git a/queue-5.19/dyndbg-let-query-modname-override-actual-module-name.patch b/queue-5.19/dyndbg-let-query-modname-override-actual-module-name.patch new file mode 100644 index 00000000000..8ed4e213fcd --- /dev/null +++ b/queue-5.19/dyndbg-let-query-modname-override-actual-module-name.patch @@ -0,0 +1,80 @@ +From 6e18ae5088ef8e4d6b4cb252744fe70bd2fb8bbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 15:40:44 -0600 +Subject: dyndbg: let query-modname override actual module name + +From: Jim Cromie + +[ Upstream commit e75ef56f74965f426dd819a41336b640ffdd8fbc ] + +dyndbg's control-parser: ddebug_parse_query(), requires that search +terms: module, func, file, lineno, are used only once in a query; a +thing cannot be named both foo and bar. + +The cited commit added an overriding module modname, taken from the +module loader, which is authoritative. So it set query.module 1st, +which disallowed its use in the query-string. + +But now, its useful to allow a module-load to enable classes across a +whole (or part of) a subsystem at once. + + # enable (dynamic-debug in) drm only + modprobe drm dyndbg="class DRM_UT_CORE +p" + + # get drm_helper too + modprobe drm dyndbg="class DRM_UT_CORE module drm* +p" + + # get everything that knows DRM_UT_CORE + modprobe drm dyndbg="class DRM_UT_CORE module * +p" + + # also for boot-args: + drm.dyndbg="class DRM_UT_CORE module * +p" + +So convert the override into a default, by filling it only when/after +the query-string omitted the module. + +NB: the query class FOO handling is forthcoming. + +Fixes: 8e59b5cfb9a6 dynamic_debug: add modname arg to exec_query callchain +Acked-by: Jason Baron +Acked-by: Daniel Vetter +Signed-off-by: Jim Cromie +Link: https://lore.kernel.org/r/20220904214134.408619-8-jim.cromie@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + lib/dynamic_debug.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c +index a56c1286ffa4..4d168efcf779 100644 +--- a/lib/dynamic_debug.c ++++ b/lib/dynamic_debug.c +@@ -384,10 +384,6 @@ static int ddebug_parse_query(char *words[], int nwords, + return -EINVAL; + } + +- if (modname) +- /* support $modname.dyndbg= */ +- query->module = modname; +- + for (i = 0; i < nwords; i += 2) { + char *keyword = words[i]; + char *arg = words[i+1]; +@@ -428,6 +424,13 @@ static int ddebug_parse_query(char *words[], int nwords, + if (rc) + return rc; + } ++ if (!query->module && modname) ++ /* ++ * support $modname.dyndbg=, when ++ * not given in the query itself ++ */ ++ query->module = modname; ++ + vpr_info_dq(query, "parsed"); + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/erofs-fix-order-max_order-warning-due-to-crafted-neg.patch b/queue-5.19/erofs-fix-order-max_order-warning-due-to-crafted-neg.patch new file mode 100644 index 00000000000..065e9e72eb9 --- /dev/null +++ b/queue-5.19/erofs-fix-order-max_order-warning-due-to-crafted-neg.patch @@ -0,0 +1,43 @@ +From 12b6ea80eb4018b9d3cce8784ac48657f5c0dfb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 10:39:48 +0800 +Subject: erofs: fix order >= MAX_ORDER warning due to crafted negative i_size + +From: Gao Xiang + +[ Upstream commit 1dd73601a1cba37a0ed5f89a8662c90191df5873 ] + +As syzbot reported [1], the root cause is that i_size field is a +signed type, and negative i_size is also less than EROFS_BLKSIZ. +As a consequence, it's handled as fast symlink unexpectedly. + +Let's fall back to the generic path to deal with such unusual i_size. + +[1] https://lore.kernel.org/r/000000000000ac8efa05e7feaa1f@google.com + +Reported-by: syzbot+f966c13b1b4fc0403b19@syzkaller.appspotmail.com +Fixes: 431339ba9042 ("staging: erofs: add inode operations") +Reviewed-by: Yue Hu +Link: https://lore.kernel.org/r/20220909023948.28925-1-hsiangkao@linux.alibaba.com +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c +index 95a403720e8c..16cf9a283557 100644 +--- a/fs/erofs/inode.c ++++ b/fs/erofs/inode.c +@@ -214,7 +214,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr, + + /* if it cannot be handled with fast symlink scheme */ + if (vi->datalayout != EROFS_INODE_FLAT_INLINE || +- inode->i_size >= EROFS_BLKSIZ) { ++ inode->i_size >= EROFS_BLKSIZ || inode->i_size < 0) { + inode->i_op = &erofs_symlink_iops; + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch b/queue-5.19/erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch new file mode 100644 index 00000000000..e2102e88db4 --- /dev/null +++ b/queue-5.19/erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch @@ -0,0 +1,40 @@ +From d387a2778fc355105731f880b0d2e28361053ef9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Sep 2022 12:34:51 +0800 +Subject: erofs: use kill_anon_super() to kill super in fscache mode + +From: Jia Zhu + +[ Upstream commit 1015c1016c231b26d4e2c9b3da65b6c043eb97a3 ] + +Use kill_anon_super() instead of generic_shutdown_super() since the +mount() in erofs fscache mode uses get_tree_nodev() and associated +anon bdev needs to be freed. + +Fixes: 9c0cc9c729657 ("erofs: add 'fsid' mount option") +Suggested-by: Jingbo Xu +Signed-off-by: Jia Zhu +Reviewed-by: Jingbo Xu +Link: https://lore.kernel.org/r/20220918043456.147-2-zhujia.zj@bytedance.com +Signed-off-by: Gao Xiang +Signed-off-by: Sasha Levin +--- + fs/erofs/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/erofs/super.c b/fs/erofs/super.c +index 95addc5c9d34..ddf8f737cfb5 100644 +--- a/fs/erofs/super.c ++++ b/fs/erofs/super.c +@@ -877,7 +877,7 @@ static void erofs_kill_sb(struct super_block *sb) + WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC); + + if (erofs_is_fscache_mode(sb)) +- generic_shutdown_super(sb); ++ kill_anon_super(sb); + else + kill_block_super(sb); + +-- +2.35.1 + diff --git a/queue-5.19/esp-choose-the-correct-inner-protocol-for-gso-on-int.patch b/queue-5.19/esp-choose-the-correct-inner-protocol-for-gso-on-int.patch new file mode 100644 index 00000000000..4cb14927427 --- /dev/null +++ b/queue-5.19/esp-choose-the-correct-inner-protocol-for-gso-on-int.patch @@ -0,0 +1,63 @@ +From 00abf19797c7694451c39df33fa690da0db18ad5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 17:16:51 +0200 +Subject: esp: choose the correct inner protocol for GSO on inter address + family tunnels + +From: Sabrina Dubroca + +[ Upstream commit 26dbd66eab8080be51759e48280da04015221e22 ] + +Commit 23c7f8d7989e ("net: Fix esp GSO on inter address family +tunnels.") is incomplete. It passes to skb_eth_gso_segment the +protocol for the outer IP version, instead of the inner IP version, so +we end up calling inet_gso_segment on an inner IPv6 packet and +ipv6_gso_segment on an inner IPv4 packet and the packets are dropped. + +This patch completes the fix by selecting the correct protocol based +on the inner mode's family. + +Fixes: c35fe4106b92 ("xfrm: Add mode handlers for IPsec on layer 2") +Signed-off-by: Sabrina Dubroca +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/ipv4/esp4_offload.c | 5 ++++- + net/ipv6/esp6_offload.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c +index 935026f4c807..170152772d33 100644 +--- a/net/ipv4/esp4_offload.c ++++ b/net/ipv4/esp4_offload.c +@@ -110,7 +110,10 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x, + struct sk_buff *skb, + netdev_features_t features) + { +- return skb_eth_gso_segment(skb, features, htons(ETH_P_IP)); ++ __be16 type = x->inner_mode.family == AF_INET6 ? htons(ETH_P_IPV6) ++ : htons(ETH_P_IP); ++ ++ return skb_eth_gso_segment(skb, features, type); + } + + static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x, +diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c +index 3a293838a91d..79d43548279c 100644 +--- a/net/ipv6/esp6_offload.c ++++ b/net/ipv6/esp6_offload.c +@@ -145,7 +145,10 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x, + struct sk_buff *skb, + netdev_features_t features) + { +- return skb_eth_gso_segment(skb, features, htons(ETH_P_IPV6)); ++ __be16 type = x->inner_mode.family == AF_INET ? htons(ETH_P_IP) ++ : htons(ETH_P_IPV6); ++ ++ return skb_eth_gso_segment(skb, features, type); + } + + static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x, +-- +2.35.1 + diff --git a/queue-5.19/eth-alx-take-rtnl_lock-on-resume.patch b/queue-5.19/eth-alx-take-rtnl_lock-on-resume.patch new file mode 100644 index 00000000000..fbfb91ac15d --- /dev/null +++ b/queue-5.19/eth-alx-take-rtnl_lock-on-resume.patch @@ -0,0 +1,78 @@ +From d91b54be3916719ed2fd6d18ae67ce895de399fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 11:12:36 -0700 +Subject: eth: alx: take rtnl_lock on resume + +From: Jakub Kicinski + +[ Upstream commit 6ad1c94e1e7e374d88f0cfd77936dddb8339aaba ] + +Zbynek reports that alx trips an rtnl assertion on resume: + + RTNL: assertion failed at net/core/dev.c (2891) + RIP: 0010:netif_set_real_num_tx_queues+0x1ac/0x1c0 + Call Trace: + + __alx_open+0x230/0x570 [alx] + alx_resume+0x54/0x80 [alx] + ? pci_legacy_resume+0x80/0x80 + dpm_run_callback+0x4a/0x150 + device_resume+0x8b/0x190 + async_resume+0x19/0x30 + async_run_entry_fn+0x30/0x130 + process_one_work+0x1e5/0x3b0 + +indeed the driver does not hold rtnl_lock during its internal close +and re-open functions during suspend/resume. Note that this is not +a huge bug as the driver implements its own locking, and does not +implement changing the number of queues, but we need to silence +the splat. + +Fixes: 4a5fe57e7751 ("alx: use fine-grained locking instead of RTNL") +Reported-and-tested-by: Zbynek Michl +Reviewed-by: Niels Dossche +Link: https://lore.kernel.org/r/20220928181236.1053043-1-kuba@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/atheros/alx/main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c +index a89b93cb4e26..d5939586c82e 100644 +--- a/drivers/net/ethernet/atheros/alx/main.c ++++ b/drivers/net/ethernet/atheros/alx/main.c +@@ -1912,11 +1912,14 @@ static int alx_suspend(struct device *dev) + + if (!netif_running(alx->dev)) + return 0; ++ ++ rtnl_lock(); + netif_device_detach(alx->dev); + + mutex_lock(&alx->mtx); + __alx_stop(alx); + mutex_unlock(&alx->mtx); ++ rtnl_unlock(); + + return 0; + } +@@ -1927,6 +1930,7 @@ static int alx_resume(struct device *dev) + struct alx_hw *hw = &alx->hw; + int err; + ++ rtnl_lock(); + mutex_lock(&alx->mtx); + alx_reset_phy(hw); + +@@ -1943,6 +1947,7 @@ static int alx_resume(struct device *dev) + + unlock: + mutex_unlock(&alx->mtx); ++ rtnl_unlock(); + return err; + } + +-- +2.35.1 + diff --git a/queue-5.19/eth-lan743x-reject-extts-for-non-pci11x1x-devices.patch b/queue-5.19/eth-lan743x-reject-extts-for-non-pci11x1x-devices.patch new file mode 100644 index 00000000000..5cf889916da --- /dev/null +++ b/queue-5.19/eth-lan743x-reject-extts-for-non-pci11x1x-devices.patch @@ -0,0 +1,50 @@ +From 78c6af18f53a22b83d8c65f58a7616452d2c1987 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 14:57:40 +0530 +Subject: eth: lan743x: reject extts for non-pci11x1x devices + +From: Raju Lakkaraju + +[ Upstream commit cb4b12071a4b68df323c339f60805834246b3e9e ] + +Remove PTP_PF_EXTTS support for non-PCI11x1x devices since they do not support +the PTP-IO Input event triggered timestamping mechanisms added + +Fixes: 60942c397af6 ("net: lan743x: Add support for PTP-IO Event Input External Timestamp (extts)") +Signed-off-by: Raju Lakkaraju +Reviewed-by: Horatiu Vultur +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan743x_ptp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/microchip/lan743x_ptp.c b/drivers/net/ethernet/microchip/lan743x_ptp.c +index 6a11e2ceb013..da3ea905adbb 100644 +--- a/drivers/net/ethernet/microchip/lan743x_ptp.c ++++ b/drivers/net/ethernet/microchip/lan743x_ptp.c +@@ -1049,6 +1049,10 @@ static int lan743x_ptpci_verify_pin_config(struct ptp_clock_info *ptp, + enum ptp_pin_function func, + unsigned int chan) + { ++ struct lan743x_ptp *lan_ptp = ++ container_of(ptp, struct lan743x_ptp, ptp_clock_info); ++ struct lan743x_adapter *adapter = ++ container_of(lan_ptp, struct lan743x_adapter, ptp); + int result = 0; + + /* Confirm the requested function is supported. Parameter +@@ -1057,7 +1061,10 @@ static int lan743x_ptpci_verify_pin_config(struct ptp_clock_info *ptp, + switch (func) { + case PTP_PF_NONE: + case PTP_PF_PEROUT: ++ break; + case PTP_PF_EXTTS: ++ if (!adapter->is_pci11x1x) ++ result = -1; + break; + case PTP_PF_PHYSYNC: + default: +-- +2.35.1 + diff --git a/queue-5.19/eth-sp7021-fix-use-after-free-bug-in-spl2sw_nvmem_ge.patch b/queue-5.19/eth-sp7021-fix-use-after-free-bug-in-spl2sw_nvmem_ge.patch new file mode 100644 index 00000000000..84c70220b9e --- /dev/null +++ b/queue-5.19/eth-sp7021-fix-use-after-free-bug-in-spl2sw_nvmem_ge.patch @@ -0,0 +1,37 @@ +From bb68184807a0405d4270ec8fe4b13cae9285682f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 01:57:25 +0800 +Subject: eth: sp7021: fix use after free bug in spl2sw_nvmem_get_mac_address + +From: Zheng Wang + +[ Upstream commit 12aece8b01507a2d357a1861f470e83621fbb6f2 ] + +This frees "mac" and tries to display its address as part of the error +message on the next line. Swap the order. + +Fixes: fd3040b9394c ("net: ethernet: Add driver for Sunplus SP7021") +Signed-off-by: Zheng Wang +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/sunplus/spl2sw_driver.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c +index 3773ce5e12cc..37711331ba0f 100644 +--- a/drivers/net/ethernet/sunplus/spl2sw_driver.c ++++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c +@@ -248,8 +248,8 @@ static int spl2sw_nvmem_get_mac_address(struct device *dev, struct device_node * + + /* Check if mac address is valid */ + if (!is_valid_ether_addr(mac)) { +- kfree(mac); + dev_info(dev, "Invalid mac address in nvmem (%pM)!\n", mac); ++ kfree(mac); + return -EINVAL; + } + +-- +2.35.1 + diff --git a/queue-5.19/eventfd-guard-wake_up-in-eventfd-fs-calls-as-well.patch b/queue-5.19/eventfd-guard-wake_up-in-eventfd-fs-calls-as-well.patch new file mode 100644 index 00000000000..d3f06ccde4c --- /dev/null +++ b/queue-5.19/eventfd-guard-wake_up-in-eventfd-fs-calls-as-well.patch @@ -0,0 +1,120 @@ +From b594ad77d85564eae0863a4dc060bbfdee1eed70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 06:59:59 -0700 +Subject: eventfd: guard wake_up in eventfd fs calls as well + +From: Dylan Yudaken + +[ Upstream commit 9f0deaa12d832f488500a5afe9b912e9b3cfc432 ] + +Guard wakeups that the user can trigger, and that may end up triggering a +call back into eventfd_signal. This is in addition to the current approach +that only guards in eventfd_signal. + +Rename in_eventfd_signal -> in_eventfd at the same time to reflect this. + +Without this there would be a deadlock in the following code using libaio: + +int main() +{ + struct io_context *ctx = NULL; + struct iocb iocb; + struct iocb *iocbs[] = { &iocb }; + int evfd; + uint64_t val = 1; + + evfd = eventfd(0, EFD_CLOEXEC); + assert(!io_setup(2, &ctx)); + io_prep_poll(&iocb, evfd, POLLIN); + io_set_eventfd(&iocb, evfd); + assert(1 == io_submit(ctx, 1, iocbs)); + write(evfd, &val, 8); +} + +Signed-off-by: Dylan Yudaken +Reviewed-by: Jens Axboe +Link: https://lore.kernel.org/r/20220816135959.1490641-1-dylany@fb.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + fs/eventfd.c | 10 +++++++--- + include/linux/eventfd.h | 2 +- + include/linux/sched.h | 2 +- + 3 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/fs/eventfd.c b/fs/eventfd.c +index 3627dd7d25db..c0ffee99ad23 100644 +--- a/fs/eventfd.c ++++ b/fs/eventfd.c +@@ -69,17 +69,17 @@ __u64 eventfd_signal(struct eventfd_ctx *ctx, __u64 n) + * it returns false, the eventfd_signal() call should be deferred to a + * safe context. + */ +- if (WARN_ON_ONCE(current->in_eventfd_signal)) ++ if (WARN_ON_ONCE(current->in_eventfd)) + return 0; + + spin_lock_irqsave(&ctx->wqh.lock, flags); +- current->in_eventfd_signal = 1; ++ current->in_eventfd = 1; + if (ULLONG_MAX - ctx->count < n) + n = ULLONG_MAX - ctx->count; + ctx->count += n; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked_poll(&ctx->wqh, EPOLLIN); +- current->in_eventfd_signal = 0; ++ current->in_eventfd = 0; + spin_unlock_irqrestore(&ctx->wqh.lock, flags); + + return n; +@@ -253,8 +253,10 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to) + __set_current_state(TASK_RUNNING); + } + eventfd_ctx_do_read(ctx, &ucnt); ++ current->in_eventfd = 1; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked_poll(&ctx->wqh, EPOLLOUT); ++ current->in_eventfd = 0; + spin_unlock_irq(&ctx->wqh.lock); + if (unlikely(copy_to_iter(&ucnt, sizeof(ucnt), to) != sizeof(ucnt))) + return -EFAULT; +@@ -301,8 +303,10 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c + } + if (likely(res > 0)) { + ctx->count += ucnt; ++ current->in_eventfd = 1; + if (waitqueue_active(&ctx->wqh)) + wake_up_locked_poll(&ctx->wqh, EPOLLIN); ++ current->in_eventfd = 0; + } + spin_unlock_irq(&ctx->wqh.lock); + +diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h +index 305d5f19093b..30eb30d6909b 100644 +--- a/include/linux/eventfd.h ++++ b/include/linux/eventfd.h +@@ -46,7 +46,7 @@ void eventfd_ctx_do_read(struct eventfd_ctx *ctx, __u64 *cnt); + + static inline bool eventfd_signal_allowed(void) + { +- return !current->in_eventfd_signal; ++ return !current->in_eventfd; + } + + #else /* CONFIG_EVENTFD */ +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 6d877c7e22ff..e02dc270fa2c 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -934,7 +934,7 @@ struct task_struct { + #endif + #ifdef CONFIG_EVENTFD + /* Recursion prevention for eventfd_signal() */ +- unsigned in_eventfd_signal:1; ++ unsigned in_eventfd:1; + #endif + #ifdef CONFIG_IOMMU_SVA + unsigned pasid_activated:1; +-- +2.35.1 + diff --git a/queue-5.19/ext2-use-kvmalloc-for-group-descriptor-array.patch b/queue-5.19/ext2-use-kvmalloc-for-group-descriptor-array.patch new file mode 100644 index 00000000000..543b95c3448 --- /dev/null +++ b/queue-5.19/ext2-use-kvmalloc-for-group-descriptor-array.patch @@ -0,0 +1,55 @@ +From 4404f41850654ce0edbba8cdcec640d4cc8f9e17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 17:29:33 +0200 +Subject: ext2: Use kvmalloc() for group descriptor array + +From: Jan Kara + +[ Upstream commit e7c7fbb9a8574ebd89cc05db49d806c7476863ad ] + +Array of group descriptor block buffers can get rather large. In theory +in can reach 1MB for perfectly valid filesystem and even more for +maliciously crafted ones. Use kvmalloc() to allocate the array to avoid +straining memory allocator with large order allocations unnecessarily. + +Reported-by: syzbot+0f2f7e65a3007d39539f@syzkaller.appspotmail.com +Signed-off-by: Jan Kara +Signed-off-by: Sasha Levin +--- + fs/ext2/super.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext2/super.c b/fs/ext2/super.c +index b3232845d0c4..f53ab39bb8e8 100644 +--- a/fs/ext2/super.c ++++ b/fs/ext2/super.c +@@ -163,7 +163,7 @@ static void ext2_put_super (struct super_block * sb) + db_count = sbi->s_gdb_count; + for (i = 0; i < db_count; i++) + brelse(sbi->s_group_desc[i]); +- kfree(sbi->s_group_desc); ++ kvfree(sbi->s_group_desc); + kfree(sbi->s_debts); + percpu_counter_destroy(&sbi->s_freeblocks_counter); + percpu_counter_destroy(&sbi->s_freeinodes_counter); +@@ -1093,7 +1093,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) + } + db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / + EXT2_DESC_PER_BLOCK(sb); +- sbi->s_group_desc = kmalloc_array(db_count, ++ sbi->s_group_desc = kvmalloc_array(db_count, + sizeof(struct buffer_head *), + GFP_KERNEL); + if (sbi->s_group_desc == NULL) { +@@ -1219,7 +1219,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) + for (i = 0; i < db_count; i++) + brelse(sbi->s_group_desc[i]); + failed_mount_group_desc: +- kfree(sbi->s_group_desc); ++ kvfree(sbi->s_group_desc); + kfree(sbi->s_debts); + failed_mount: + brelse(bh); +-- +2.35.1 + diff --git a/queue-5.19/ext4-don-t-run-ext4lazyinit-for-read-only-filesystem.patch b/queue-5.19/ext4-don-t-run-ext4lazyinit-for-read-only-filesystem.patch new file mode 100644 index 00000000000..1133042bf85 --- /dev/null +++ b/queue-5.19/ext4-don-t-run-ext4lazyinit-for-read-only-filesystem.patch @@ -0,0 +1,46 @@ +From b054276f2aa4213f27adb7d8cff91cb360adf276 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 20:24:53 -0700 +Subject: ext4: don't run ext4lazyinit for read-only filesystems + +From: Josh Triplett + +[ Upstream commit 426d15ad11419066f7042ffa8fbf1b5c21a1ecbe ] + +On a read-only filesystem, we won't invoke the block allocator, so we +don't need to prefetch the block bitmaps. + +This avoids starting and running the ext4lazyinit thread at all on a +system with no read-write ext4 filesystems (for instance, a container VM +with read-only filesystems underneath an overlayfs). + +Fixes: 21175ca434c5 ("ext4: make prefetch_block_bitmaps default") +Signed-off-by: Josh Triplett +Reviewed-by: Lukas Czerner +Link: https://lore.kernel.org/r/48b41da1498fcac3287e2e06b660680646c1c050.1659323972.git.josh@joshtriplett.org +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index fd358e5f88ff..5cacd513d0df 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3953,9 +3953,9 @@ int ext4_register_li_request(struct super_block *sb, + goto out; + } + +- if (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS) && +- (first_not_zeroed == ngroups || sb_rdonly(sb) || +- !test_opt(sb, INIT_INODE_TABLE))) ++ if (sb_rdonly(sb) || ++ (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS) && ++ (first_not_zeroed == ngroups || !test_opt(sb, INIT_INODE_TABLE)))) + goto out; + + elr = ext4_li_request_new(sb, first_not_zeroed); +-- +2.35.1 + diff --git a/queue-5.19/f2fs-fix-race-condition-on-setting-fi_no_extent-flag.patch b/queue-5.19/f2fs-fix-race-condition-on-setting-fi_no_extent-flag.patch new file mode 100644 index 00000000000..837f3498b52 --- /dev/null +++ b/queue-5.19/f2fs-fix-race-condition-on-setting-fi_no_extent-flag.patch @@ -0,0 +1,55 @@ +From 8636e920807d4ca7e5d20e9bfa9299fc6df7e8a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 12:59:17 +0800 +Subject: f2fs: fix race condition on setting FI_NO_EXTENT flag + +From: Zhang Qilong + +[ Upstream commit 07725adc55c0a414c10acb5c8c86cea34b95ddef ] + +The following scenarios exist. +process A: process B: +->f2fs_drop_extent_tree ->f2fs_update_extent_cache_range + ->f2fs_update_extent_tree_range + ->write_lock + ->set_inode_flag + ->is_inode_flag_set + ->__free_extent_tree // Shouldn't + // have been + // cleaned up + // here + ->write_lock + +In this case, the "FI_NO_EXTENT" flag is set between +f2fs_update_extent_tree_range and is_inode_flag_set +by other process. it leads to clearing the whole exten +tree which should not have happened. And we fix it by +move the setting it to the range of write_lock. + +Fixes:5f281fab9b9a3 ("f2fs: disable extent_cache for fcollapse/finsert inodes") +Signed-off-by: Zhang Qilong +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/extent_cache.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c +index 866e72b29bd5..761fd42c93f2 100644 +--- a/fs/f2fs/extent_cache.c ++++ b/fs/f2fs/extent_cache.c +@@ -804,9 +804,8 @@ void f2fs_drop_extent_tree(struct inode *inode) + if (!f2fs_may_extent_tree(inode)) + return; + +- set_inode_flag(inode, FI_NO_EXTENT); +- + write_lock(&et->lock); ++ set_inode_flag(inode, FI_NO_EXTENT); + __free_extent_tree(sbi, et); + if (et->largest.len) { + et->largest.len = 0; +-- +2.35.1 + diff --git a/queue-5.19/f2fs-fix-to-account-fs_cp_data_io-correctly.patch b/queue-5.19/f2fs-fix-to-account-fs_cp_data_io-correctly.patch new file mode 100644 index 00000000000..5945f8d4c11 --- /dev/null +++ b/queue-5.19/f2fs-fix-to-account-fs_cp_data_io-correctly.patch @@ -0,0 +1,138 @@ +From 96b3620f7c133706600357df33070010c56dae16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 21:28:46 +0800 +Subject: f2fs: fix to account FS_CP_DATA_IO correctly + +From: Chao Yu + +[ Upstream commit d80afefb17e01aa0c46a8eebc01882e0ebd8b0f6 ] + +f2fs_inode_info.cp_task was introduced for FS_CP_DATA_IO accounting +since commit b0af6d491a6b ("f2fs: add app/fs io stat"). + +However, cp_task usage coverage has been increased due to below +commits: +commit 040d2bb318d1 ("f2fs: fix to avoid deadloop if data_flush is on") +commit 186857c5a14a ("f2fs: fix potential recursive call when enabling data_flush") + +So that, if data_flush mountoption is on, when data flush was +triggered from background, the IO from data flush will be accounted +as checkpoint IO type incorrectly. + +In order to fix this issue, this patch splits cp_task into two: +a) cp_task: used for IO accounting +b) wb_task: used to avoid deadlock + +Fixes: 040d2bb318d1 ("f2fs: fix to avoid deadloop if data_flush is on") +Fixes: 186857c5a14a ("f2fs: fix potential recursive call when enabling data_flush") +Signed-off-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + fs/f2fs/checkpoint.c | 13 +++++++++---- + fs/f2fs/data.c | 4 ++-- + fs/f2fs/f2fs.h | 4 +++- + fs/f2fs/segment.c | 2 +- + 4 files changed, 15 insertions(+), 8 deletions(-) + +diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c +index 2a1930cfd513..5c77ae07150d 100644 +--- a/fs/f2fs/checkpoint.c ++++ b/fs/f2fs/checkpoint.c +@@ -1063,7 +1063,8 @@ void f2fs_remove_dirty_inode(struct inode *inode) + spin_unlock(&sbi->inode_lock[type]); + } + +-int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type) ++int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type, ++ bool from_cp) + { + struct list_head *head; + struct inode *inode; +@@ -1098,11 +1099,15 @@ int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type) + if (inode) { + unsigned long cur_ino = inode->i_ino; + +- F2FS_I(inode)->cp_task = current; ++ if (from_cp) ++ F2FS_I(inode)->cp_task = current; ++ F2FS_I(inode)->wb_task = current; + + filemap_fdatawrite(inode->i_mapping); + +- F2FS_I(inode)->cp_task = NULL; ++ F2FS_I(inode)->wb_task = NULL; ++ if (from_cp) ++ F2FS_I(inode)->cp_task = NULL; + + iput(inode); + /* We need to give cpu to another writers. */ +@@ -1231,7 +1236,7 @@ static int block_operations(struct f2fs_sb_info *sbi) + /* write all the dirty dentry pages */ + if (get_pages(sbi, F2FS_DIRTY_DENTS)) { + f2fs_unlock_all(sbi); +- err = f2fs_sync_dirty_inodes(sbi, DIR_INODE); ++ err = f2fs_sync_dirty_inodes(sbi, DIR_INODE, true); + if (err) + return err; + cond_resched(); +diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c +index f2a272613477..d3768115e3b8 100644 +--- a/fs/f2fs/data.c ++++ b/fs/f2fs/data.c +@@ -2843,7 +2843,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, + } + unlock_page(page); + if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) && +- !F2FS_I(inode)->cp_task && allow_balance) ++ !F2FS_I(inode)->wb_task && allow_balance) + f2fs_balance_fs(sbi, need_balance_fs); + + if (unlikely(f2fs_cp_error(sbi))) { +@@ -3141,7 +3141,7 @@ static inline bool __should_serialize_io(struct inode *inode, + struct writeback_control *wbc) + { + /* to avoid deadlock in path of data flush */ +- if (F2FS_I(inode)->cp_task) ++ if (F2FS_I(inode)->wb_task) + return false; + + if (!S_ISREG(inode->i_mode)) +diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h +index f9d5110bbcd8..7896cbadbcd7 100644 +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -784,6 +784,7 @@ struct f2fs_inode_info { + unsigned int clevel; /* maximum level of given file name */ + struct task_struct *task; /* lookup and create consistency */ + struct task_struct *cp_task; /* separate cp/wb IO stats*/ ++ struct task_struct *wb_task; /* indicate inode is in context of writeback */ + nid_t i_xattr_nid; /* node id that contains xattrs */ + loff_t last_disk_size; /* lastly written file size */ + spinlock_t i_size_lock; /* protect last_disk_size */ +@@ -3710,7 +3711,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi); + int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi); + void f2fs_update_dirty_folio(struct inode *inode, struct folio *folio); + void f2fs_remove_dirty_inode(struct inode *inode); +-int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type); ++int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type, ++ bool from_cp); + void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type); + u64 f2fs_get_sectors_written(struct f2fs_sb_info *sbi); + int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc); +diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c +index 52df19a0638b..b740ff81024e 100644 +--- a/fs/f2fs/segment.c ++++ b/fs/f2fs/segment.c +@@ -469,7 +469,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg) + mutex_lock(&sbi->flush_lock); + + blk_start_plug(&plug); +- f2fs_sync_dirty_inodes(sbi, FILE_INODE); ++ f2fs_sync_dirty_inodes(sbi, FILE_INODE, false); + blk_finish_plug(&plug); + + mutex_unlock(&sbi->flush_lock); +-- +2.35.1 + diff --git a/queue-5.19/firmware-google-test-spinlock-on-panic-path-to-avoid.patch b/queue-5.19/firmware-google-test-spinlock-on-panic-path-to-avoid.patch new file mode 100644 index 00000000000..0b8966dc7fc --- /dev/null +++ b/queue-5.19/firmware-google-test-spinlock-on-panic-path-to-avoid.patch @@ -0,0 +1,59 @@ +From ae3282c54ca1d690f525a992ee4ac928bd8cd2f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 17:07:55 -0300 +Subject: firmware: google: Test spinlock on panic path to avoid lockups + +From: Guilherme G. Piccoli + +[ Upstream commit 3e081438b8e639cc76ef1a5ce0c1bd8a154082c7 ] + +Currently the gsmi driver registers a panic notifier as well as +reboot and die notifiers. The callbacks registered are called in +atomic and very limited context - for instance, panic disables +preemption and local IRQs, also all secondary CPUs (not executing +the panic path) are shutdown. + +With that said, taking a spinlock in this scenario is a dangerous +invitation for lockup scenarios. So, fix that by checking if the +spinlock is free to acquire in the panic notifier callback - if not, +bail-out and avoid a potential hang. + +Fixes: 74c5b31c6618 ("driver: Google EFI SMI") +Cc: Andrew Morton +Cc: Ard Biesheuvel +Cc: David Gow +Cc: Greg Kroah-Hartman +Cc: Julius Werner +Cc: Petr Mladek +Reviewed-by: Evan Green +Signed-off-by: Guilherme G. Piccoli +Link: https://lore.kernel.org/r/20220909200755.189679-1-gpiccoli@igalia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/firmware/google/gsmi.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/firmware/google/gsmi.c b/drivers/firmware/google/gsmi.c +index adaa492c3d2d..4e2575dfeb90 100644 +--- a/drivers/firmware/google/gsmi.c ++++ b/drivers/firmware/google/gsmi.c +@@ -681,6 +681,15 @@ static struct notifier_block gsmi_die_notifier = { + static int gsmi_panic_callback(struct notifier_block *nb, + unsigned long reason, void *arg) + { ++ ++ /* ++ * Panic callbacks are executed with all other CPUs stopped, ++ * so we must not attempt to spin waiting for gsmi_dev.lock ++ * to be released. ++ */ ++ if (spin_is_locked(&gsmi_dev.lock)) ++ return NOTIFY_DONE; ++ + gsmi_shutdown_reason(GSMI_SHUTDOWN_PANIC); + return NOTIFY_DONE; + } +-- +2.35.1 + diff --git a/queue-5.19/flow_dissector-do-not-count-vlan-tags-inside-tunnel-.patch b/queue-5.19/flow_dissector-do-not-count-vlan-tags-inside-tunnel-.patch new file mode 100644 index 00000000000..65d786cd8b8 --- /dev/null +++ b/queue-5.19/flow_dissector-do-not-count-vlan-tags-inside-tunnel-.patch @@ -0,0 +1,60 @@ +From 8e55fa57a3545abf890058e2684a17bf020d84a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 15:48:08 +0800 +Subject: flow_dissector: Do not count vlan tags inside tunnel payload + +From: Qingqing Yang + +[ Upstream commit 9f87eb4246994e32a4e4ea88476b20ab3b412840 ] + +We've met the problem that when there is a vlan tag inside +GRE encapsulation, the match of num_of_vlans fails. +It is caused by the vlan tag inside GRE payload has been +counted into num_of_vlans, which is not expected. + +One example packet is like this: +Ethernet II, Src: Broadcom_68:56:07 (00:10:18:68:56:07) + Dst: Broadcom_68:56:08 (00:10:18:68:56:08) +802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 100 +Internet Protocol Version 4, Src: 192.168.1.4, Dst: 192.168.1.200 +Generic Routing Encapsulation (Transparent Ethernet bridging) +Ethernet II, Src: Broadcom_68:58:07 (00:10:18:68:58:07) + Dst: Broadcom_68:58:08 (00:10:18:68:58:08) +802.1Q Virtual LAN, PRI: 0, DEI: 0, ID: 200 +... +It should match the (num_of_vlans 1) rule, but it matches +the (num_of_vlans 2) rule. + +The vlan tags inside the GRE or other tunnel encapsulated payload +should not be taken into num_of_vlans. +The fix is to stop counting the vlan number when the encapsulation +bit is set. + +Fixes: 34951fcf26c5 ("flow_dissector: Add number of vlan tags dissector") +Signed-off-by: Qingqing Yang +Reviewed-by: Boris Sukholitko +Link: https://lore.kernel.org/r/20220919074808.136640-1-qingqing.yang@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/flow_dissector.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c +index bcba61ef5b37..ac6360433003 100644 +--- a/net/core/flow_dissector.c ++++ b/net/core/flow_dissector.c +@@ -1168,8 +1168,8 @@ bool __skb_flow_dissect(const struct net *net, + nhoff += sizeof(*vlan); + } + +- if (dissector_uses_key(flow_dissector, +- FLOW_DISSECTOR_KEY_NUM_OF_VLANS)) { ++ if (dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_NUM_OF_VLANS) && ++ !(key_control->flags & FLOW_DIS_ENCAPSULATION)) { + struct flow_dissector_key_num_of_vlans *key_nvs; + + key_nvs = skb_flow_dissector_target(flow_dissector, +-- +2.35.1 + diff --git a/queue-5.19/fortify-fix-__compiletime_strlen-under-ubsan_bounds_.patch b/queue-5.19/fortify-fix-__compiletime_strlen-under-ubsan_bounds_.patch new file mode 100644 index 00000000000..94ecff3e662 --- /dev/null +++ b/queue-5.19/fortify-fix-__compiletime_strlen-under-ubsan_bounds_.patch @@ -0,0 +1,85 @@ +From cb8555805589f687d29f8b55f9906b4c47548ba7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 13:02:26 -0700 +Subject: fortify: Fix __compiletime_strlen() under UBSAN_BOUNDS_LOCAL + +From: Kees Cook + +[ Upstream commit d07c0acb4f41cc42a0d97530946965b3e4fa68c1 ] + +With CONFIG_FORTIFY=y and CONFIG_UBSAN_LOCAL_BOUNDS=y enabled, we observe +a runtime panic while running Android's Compatibility Test Suite's (CTS) +android.hardware.input.cts.tests. This is stemming from a strlen() +call in hidinput_allocate(). + +__compiletime_strlen() is implemented in terms of __builtin_object_size(), +then does an array access to check for NUL-termination. A quirk of +__builtin_object_size() is that for strings whose values are runtime +dependent, __builtin_object_size(str, 1 or 0) returns the maximum size +of possible values when those sizes are determinable at compile time. +Example: + + static const char *v = "FOO BAR"; + static const char *y = "FOO BA"; + unsigned long x (int z) { + // Returns 8, which is: + // max(__builtin_object_size(v, 1), __builtin_object_size(y, 1)) + return __builtin_object_size(z ? v : y, 1); + } + +So when FORTIFY_SOURCE is enabled, the current implementation of +__compiletime_strlen() will try to access beyond the end of y at runtime +using the size of v. Mixed with UBSAN_LOCAL_BOUNDS we get a fault. + +hidinput_allocate() has a local C string whose value is control flow +dependent on a switch statement, so __builtin_object_size(str, 1) +evaluates to the maximum string length, making all other cases fault on +the last character check. hidinput_allocate() could be cleaned up to +avoid runtime calls to strlen() since the local variable can only have +literal values, so there's no benefit to trying to fortify the strlen +call site there. + +Perform a __builtin_constant_p() check against index 0 earlier in the +macro to filter out the control-flow-dependant case. Add a KUnit test +for checking the expected behavioral characteristics of FORTIFY_SOURCE +internals. + +Cc: Nathan Chancellor +Cc: Tom Rix +Cc: Andrew Morton +Cc: Vlastimil Babka +Cc: "Steven Rostedt (Google)" +Cc: David Gow +Cc: Yury Norov +Cc: Masami Hiramatsu +Cc: Sander Vanheule +Cc: linux-hardening@vger.kernel.org +Cc: llvm@lists.linux.dev +Reviewed-by: Nick Desaulniers +Tested-by: Android Treehugger Robot +Link: https://android-review.googlesource.com/c/kernel/common/+/2206839 +Co-developed-by: Nick Desaulniers +Signed-off-by: Nick Desaulniers +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + include/linux/fortify-string.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h +index 3b401fa0f374..fce2fb2fc962 100644 +--- a/include/linux/fortify-string.h ++++ b/include/linux/fortify-string.h +@@ -19,7 +19,8 @@ void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning(" + unsigned char *__p = (unsigned char *)(p); \ + size_t __ret = (size_t)-1; \ + size_t __p_size = __builtin_object_size(p, 1); \ +- if (__p_size != (size_t)-1) { \ ++ if (__p_size != (size_t)-1 && \ ++ __builtin_constant_p(*__p)) { \ + size_t __p_len = __p_size - 1; \ + if (__builtin_constant_p(__p[__p_len]) && \ + __p[__p_len] == '\0') \ +-- +2.35.1 + diff --git a/queue-5.19/fpga-prevent-integer-overflow-in-dfl_feature_ioctl_s.patch b/queue-5.19/fpga-prevent-integer-overflow-in-dfl_feature_ioctl_s.patch new file mode 100644 index 00000000000..960251bc6b7 --- /dev/null +++ b/queue-5.19/fpga-prevent-integer-overflow-in-dfl_feature_ioctl_s.patch @@ -0,0 +1,38 @@ +From 03b4b899564c54a2e151ff8d309141ea640ec2ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 08:18:45 +0300 +Subject: fpga: prevent integer overflow in dfl_feature_ioctl_set_irq() + +From: Dan Carpenter + +[ Upstream commit 939bc5453b8cbdde9f1e5110ce8309aedb1b501a ] + +The "hdr.count * sizeof(s32)" multiplication can overflow on 32 bit +systems leading to memory corruption. Use array_size() to fix that. + +Fixes: 322b598be4d9 ("fpga: dfl: introduce interrupt trigger setting API") +Signed-off-by: Dan Carpenter +Acked-by: Xu Yilun +Link: https://lore.kernel.org/r/YxBAtYCM38dM7yzI@kili +Signed-off-by: Xu Yilun +Signed-off-by: Sasha Levin +--- + drivers/fpga/dfl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c +index 6bff39ff21a0..eabaf495a481 100644 +--- a/drivers/fpga/dfl.c ++++ b/drivers/fpga/dfl.c +@@ -1866,7 +1866,7 @@ long dfl_feature_ioctl_set_irq(struct platform_device *pdev, + return -EINVAL; + + fds = memdup_user((void __user *)(arg + sizeof(hdr)), +- hdr.count * sizeof(s32)); ++ array_size(hdr.count, sizeof(s32))); + if (IS_ERR(fds)) + return PTR_ERR(fds); + +-- +2.35.1 + diff --git a/queue-5.19/fs-dlm-fix-race-in-lowcomms.patch b/queue-5.19/fs-dlm-fix-race-in-lowcomms.patch new file mode 100644 index 00000000000..6e69936732c --- /dev/null +++ b/queue-5.19/fs-dlm-fix-race-in-lowcomms.patch @@ -0,0 +1,95 @@ +From 49bcfa77f83965aa496af2dd9e9105024ad3723b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 15:43:13 -0400 +Subject: fs: dlm: fix race in lowcomms + +From: Alexander Aring + +[ Upstream commit 30ea3257e8766027c4d8d609dcbd256ff9a76073 ] + +This patch fixes a race between queue_work() in +_dlm_lowcomms_commit_msg() and srcu_read_unlock(). The queue_work() can +take the final reference of a dlm_msg and so msg->idx can contain +garbage which is signaled by the following warning: + +[ 676.237050] ------------[ cut here ]------------ +[ 676.237052] WARNING: CPU: 0 PID: 1060 at include/linux/srcu.h:189 dlm_lowcomms_commit_msg+0x41/0x50 +[ 676.238945] Modules linked in: dlm_locktorture torture rpcsec_gss_krb5 intel_rapl_msr intel_rapl_common iTCO_wdt iTCO_vendor_support qxl kvm_intel drm_ttm_helper vmw_vsock_virtio_transport kvm vmw_vsock_virtio_transport_common ttm irqbypass crc32_pclmul joydev crc32c_intel serio_raw drm_kms_helper vsock virtio_scsi virtio_console virtio_balloon snd_pcm drm syscopyarea sysfillrect sysimgblt snd_timer fb_sys_fops i2c_i801 lpc_ich snd i2c_smbus soundcore pcspkr +[ 676.244227] CPU: 0 PID: 1060 Comm: lock_torture_wr Not tainted 5.19.0-rc3+ #1546 +[ 676.245216] Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.16.0-2.module+el8.7.0+15506+033991b0 04/01/2014 +[ 676.246460] RIP: 0010:dlm_lowcomms_commit_msg+0x41/0x50 +[ 676.247132] Code: fe ff ff ff 75 24 48 c7 c6 bd 0f 49 bb 48 c7 c7 38 7c 01 bd e8 00 e7 ca ff 89 de 48 c7 c7 60 78 01 bd e8 42 3d cd ff 5b 5d c3 <0f> 0b eb d8 66 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 +[ 676.249253] RSP: 0018:ffffa401c18ffc68 EFLAGS: 00010282 +[ 676.249855] RAX: 0000000000000001 RBX: 00000000ffff8b76 RCX: 0000000000000006 +[ 676.250713] RDX: 0000000000000000 RSI: ffffffffbccf3a10 RDI: ffffffffbcc7b62e +[ 676.251610] RBP: ffffa401c18ffc70 R08: 0000000000000001 R09: 0000000000000001 +[ 676.252481] R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000005 +[ 676.253421] R13: ffff8b76786ec370 R14: ffff8b76786ec370 R15: ffff8b76786ec480 +[ 676.254257] FS: 0000000000000000(0000) GS:ffff8b7777800000(0000) knlGS:0000000000000000 +[ 676.255239] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 676.255897] CR2: 00005590205d88b8 CR3: 000000017656c003 CR4: 0000000000770ee0 +[ 676.256734] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 676.257567] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 676.258397] PKRU: 55555554 +[ 676.258729] Call Trace: +[ 676.259063] +[ 676.259354] dlm_midcomms_commit_mhandle+0xcc/0x110 +[ 676.259964] queue_bast+0x8b/0xb0 +[ 676.260423] grant_pending_locks+0x166/0x1b0 +[ 676.261007] _unlock_lock+0x75/0x90 +[ 676.261469] unlock_lock.isra.57+0x62/0xa0 +[ 676.262009] dlm_unlock+0x21e/0x330 +[ 676.262457] ? lock_torture_stats+0x80/0x80 [dlm_locktorture] +[ 676.263183] torture_unlock+0x5a/0x90 [dlm_locktorture] +[ 676.263815] ? preempt_count_sub+0xba/0x100 +[ 676.264361] ? complete+0x1d/0x60 +[ 676.264777] lock_torture_writer+0xb8/0x150 [dlm_locktorture] +[ 676.265555] kthread+0x10a/0x130 +[ 676.266007] ? kthread_complete_and_exit+0x20/0x20 +[ 676.266616] ret_from_fork+0x22/0x30 +[ 676.267097] +[ 676.267381] irq event stamp: 9579855 +[ 676.267824] hardirqs last enabled at (9579863): [] __up_console_sem+0x58/0x60 +[ 676.268896] hardirqs last disabled at (9579872): [] __up_console_sem+0x3d/0x60 +[ 676.270008] softirqs last enabled at (9579798): [] __do_softirq+0x349/0x4c7 +[ 676.271438] softirqs last disabled at (9579897): [] irq_exit_rcu+0xb0/0xf0 +[ 676.272796] ---[ end trace 0000000000000000 ]--- + +I reproduced this warning with dlm_locktorture test which is currently +not upstream. However this patch fix the issue by make a additional +refcount between dlm_lowcomms_new_msg() and dlm_lowcomms_commit_msg(). +In case of the race the kref_put() in dlm_lowcomms_commit_msg() will be +the final put. + +Signed-off-by: Alexander Aring +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + fs/dlm/lowcomms.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c +index 19e82f08c0e0..c80ee6a95d17 100644 +--- a/fs/dlm/lowcomms.c ++++ b/fs/dlm/lowcomms.c +@@ -1336,6 +1336,8 @@ struct dlm_msg *dlm_lowcomms_new_msg(int nodeid, int len, gfp_t allocation, + return NULL; + } + ++ /* for dlm_lowcomms_commit_msg() */ ++ kref_get(&msg->ref); + /* we assume if successful commit must called */ + msg->idx = idx; + return msg; +@@ -1375,6 +1377,8 @@ void dlm_lowcomms_commit_msg(struct dlm_msg *msg) + { + _dlm_lowcomms_commit_msg(msg); + srcu_read_unlock(&connections_srcu, msg->idx); ++ /* because dlm_lowcomms_new_msg() */ ++ kref_put(&msg->ref, dlm_msg_release); + } + #endif + +-- +2.35.1 + diff --git a/queue-5.19/fs-don-t-randomize-struct-kiocb-fields.patch b/queue-5.19/fs-don-t-randomize-struct-kiocb-fields.patch new file mode 100644 index 00000000000..433da52c1ea --- /dev/null +++ b/queue-5.19/fs-don-t-randomize-struct-kiocb-fields.patch @@ -0,0 +1,49 @@ +From f850583179b4c818114d5866487adf692a67077c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Aug 2022 15:56:33 -0700 +Subject: fs: don't randomize struct kiocb fields + +From: Keith Busch + +[ Upstream commit addebd9ac9ca0ef8b3764907bf8018e48caffc64 ] + +This is a size sensitive structure and randomizing can introduce extra +padding that breaks io_uring's fixed size expectations. There are few +fields here as it is, half of which need a fixed order to optimally +pack, so the randomization isn't providing much. + +Suggested-by: Linus Torvalds +Signed-off-by: Keith Busch +Link: https://lore.kernel.org/io-uring/b6f508ca-b1b2-5f40-7998-e4cff1cf7212@kernel.dk/ +Signed-off-by: Jens Axboe +Stable-dep-of: b000145e9907 ("io_uring/rw: defer fsnotify calls to task context") +Signed-off-by: Sasha Levin +--- + include/linux/fs.h | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 21ed10a2e1cd..1e919b7420d1 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -318,17 +318,12 @@ enum rw_hint { + + struct kiocb { + struct file *ki_filp; +- +- /* The 'ki_filp' pointer is shared in a union for aio */ +- randomized_struct_fields_start +- + loff_t ki_pos; + void (*ki_complete)(struct kiocb *iocb, long ret); + void *private; + int ki_flags; + u16 ki_ioprio; /* See linux/ioprio.h */ + struct wait_page_queue *ki_waitq; /* for async buffered IO */ +- randomized_struct_fields_end + }; + + static inline bool is_sync_kiocb(struct kiocb *kiocb) +-- +2.35.1 + diff --git a/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch b/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch new file mode 100644 index 00000000000..ac483ce2e50 --- /dev/null +++ b/queue-5.19/fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch @@ -0,0 +1,1304 @@ +From 15d10c3e27d4314c2ba2fdb4caecd290ba0b9795 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 12:32:06 -0700 +Subject: fscrypt: stop using keyrings subsystem for fscrypt_master_key + +From: Eric Biggers + +[ Upstream commit d7e7b9af104c7b389a0c21eb26532511bce4b510 ] + +The approach of fs/crypto/ internally managing the fscrypt_master_key +structs as the payloads of "struct key" objects contained in a +"struct key" keyring has outlived its usefulness. The original idea was +to simplify the code by reusing code from the keyrings subsystem. +However, several issues have arisen that can't easily be resolved: + +- When a master key struct is destroyed, blk_crypto_evict_key() must be + called on any per-mode keys embedded in it. (This started being the + case when inline encryption support was added.) Yet, the keyrings + subsystem can arbitrarily delay the destruction of keys, even past the + time the filesystem was unmounted. Therefore, currently there is no + easy way to call blk_crypto_evict_key() when a master key is + destroyed. Currently, this is worked around by holding an extra + reference to the filesystem's request_queue(s). But it was overlooked + that the request_queue reference is *not* guaranteed to pin the + corresponding blk_crypto_profile too; for device-mapper devices that + support inline crypto, it doesn't. This can cause a use-after-free. + +- When the last inode that was using an incompletely-removed master key + is evicted, the master key removal is completed by removing the key + struct from the keyring. Currently this is done via key_invalidate(). + Yet, key_invalidate() takes the key semaphore. This can deadlock when + called from the shrinker, since in fscrypt_ioctl_add_key(), memory is + allocated with GFP_KERNEL under the same semaphore. + +- More generally, the fact that the keyrings subsystem can arbitrarily + delay the destruction of keys (via garbage collection delay, or via + random processes getting temporary key references) is undesirable, as + it means we can't strictly guarantee that all secrets are ever wiped. + +- Doing the master key lookups via the keyrings subsystem results in the + key_permission LSM hook being called. fscrypt doesn't want this, as + all access control for encrypted files is designed to happen via the + files themselves, like any other files. The workaround which SELinux + users are using is to change their SELinux policy to grant key search + access to all domains. This works, but it is an odd extra step that + shouldn't really have to be done. + +The fix for all these issues is to change the implementation to what I +should have done originally: don't use the keyrings subsystem to keep +track of the filesystem's fscrypt_master_key structs. Instead, just +store them in a regular kernel data structure, and rework the reference +counting, locking, and lifetime accordingly. Retain support for +RCU-mode key lookups by using a hash table. Replace fscrypt_sb_free() +with fscrypt_sb_delete(), which releases the keys synchronously and runs +a bit earlier during unmount, so that block devices are still available. + +A side effect of this patch is that neither the master keys themselves +nor the filesystem keyrings will be listed in /proc/keys anymore. +("Master key users" and the master key users keyrings will still be +listed.) However, this was mostly an implementation detail, and it was +intended just for debugging purposes. I don't know of anyone using it. + +This patch does *not* change how "master key users" (->mk_users) works; +that still uses the keyrings subsystem. That is still needed for key +quotas, and changing that isn't necessary to solve the issues listed +above. If we decide to change that too, it would be a separate patch. + +I've marked this as fixing the original commit that added the fscrypt +keyring, but as noted above the most important issue that this patch +fixes wasn't introduced until the addition of inline encryption support. + +Fixes: 22d94f493bfb ("fscrypt: add FS_IOC_ADD_ENCRYPTION_KEY ioctl") +Signed-off-by: Eric Biggers +Link: https://lore.kernel.org/r/20220901193208.138056-2-ebiggers@kernel.org +Signed-off-by: Sasha Levin +--- + fs/crypto/fscrypt_private.h | 71 ++++-- + fs/crypto/hooks.c | 10 +- + fs/crypto/keyring.c | 486 +++++++++++++++++++----------------- + fs/crypto/keysetup.c | 81 +++--- + fs/crypto/policy.c | 8 +- + fs/super.c | 2 +- + include/linux/fs.h | 2 +- + include/linux/fscrypt.h | 4 +- + 8 files changed, 353 insertions(+), 311 deletions(-) + +diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h +index 6b4c8094cc7b..731a9a34ec21 100644 +--- a/fs/crypto/fscrypt_private.h ++++ b/fs/crypto/fscrypt_private.h +@@ -225,7 +225,7 @@ struct fscrypt_info { + * will be NULL if the master key was found in a process-subscribed + * keyring rather than in the filesystem-level keyring. + */ +- struct key *ci_master_key; ++ struct fscrypt_master_key *ci_master_key; + + /* + * Link in list of inodes that were unlocked with the master key. +@@ -439,6 +439,40 @@ struct fscrypt_master_key_secret { + */ + struct fscrypt_master_key { + ++ /* ++ * Back-pointer to the super_block of the filesystem to which this ++ * master key has been added. Only valid if ->mk_active_refs > 0. ++ */ ++ struct super_block *mk_sb; ++ ++ /* ++ * Link in ->mk_sb->s_master_keys->key_hashtable. ++ * Only valid if ->mk_active_refs > 0. ++ */ ++ struct hlist_node mk_node; ++ ++ /* Semaphore that protects ->mk_secret and ->mk_users */ ++ struct rw_semaphore mk_sem; ++ ++ /* ++ * Active and structural reference counts. An active ref guarantees ++ * that the struct continues to exist, continues to be in the keyring ++ * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g. ++ * ->mk_direct_keys) that have been prepared continue to exist. ++ * A structural ref only guarantees that the struct continues to exist. ++ * ++ * There is one active ref associated with ->mk_secret being present, ++ * and one active ref for each inode in ->mk_decrypted_inodes. ++ * ++ * There is one structural ref associated with the active refcount being ++ * nonzero. Finding a key in the keyring also takes a structural ref, ++ * which is then held temporarily while the key is operated on. ++ */ ++ refcount_t mk_active_refs; ++ refcount_t mk_struct_refs; ++ ++ struct rcu_head mk_rcu_head; ++ + /* + * The secret key material. After FS_IOC_REMOVE_ENCRYPTION_KEY is + * executed, this is wiped and no new inodes can be unlocked with this +@@ -447,7 +481,10 @@ struct fscrypt_master_key { + * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or + * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again. + * +- * Locking: protected by this master key's key->sem. ++ * While ->mk_secret is present, one ref in ->mk_active_refs is held. ++ * ++ * Locking: protected by ->mk_sem. The manipulation of ->mk_active_refs ++ * associated with this field is protected by ->mk_sem as well. + */ + struct fscrypt_master_key_secret mk_secret; + +@@ -468,22 +505,12 @@ struct fscrypt_master_key { + * + * This is NULL for v1 policy keys; those can only be added by root. + * +- * Locking: in addition to this keyring's own semaphore, this is +- * protected by this master key's key->sem, so we can do atomic +- * search+insert. It can also be searched without taking any locks, but +- * in that case the returned key may have already been removed. ++ * Locking: protected by ->mk_sem. (We don't just rely on the keyrings ++ * subsystem semaphore ->mk_users->sem, as we need support for atomic ++ * search+insert along with proper synchronization with ->mk_secret.) + */ + struct key *mk_users; + +- /* +- * Length of ->mk_decrypted_inodes, plus one if mk_secret is present. +- * Once this goes to 0, the master key is removed from ->s_master_keys. +- * The 'struct fscrypt_master_key' will continue to live as long as the +- * 'struct key' whose payload it is, but we won't let this reference +- * count rise again. +- */ +- refcount_t mk_refcount; +- + /* + * List of inodes that were unlocked using this key. This allows the + * inodes to be evicted efficiently if the key is removed. +@@ -509,10 +536,10 @@ static inline bool + is_master_key_secret_present(const struct fscrypt_master_key_secret *secret) + { + /* +- * The READ_ONCE() is only necessary for fscrypt_drop_inode() and +- * fscrypt_key_describe(). These run in atomic context, so they can't +- * take the key semaphore and thus 'secret' can change concurrently +- * which would be a data race. But they only need to know whether the ++ * The READ_ONCE() is only necessary for fscrypt_drop_inode(). ++ * fscrypt_drop_inode() runs in atomic context, so it can't take the key ++ * semaphore and thus 'secret' can change concurrently which would be a ++ * data race. But fscrypt_drop_inode() only need to know whether the + * secret *was* present at the time of check, so READ_ONCE() suffices. + */ + return READ_ONCE(secret->size) != 0; +@@ -541,7 +568,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec) + return 0; + } + +-struct key * ++void fscrypt_put_master_key(struct fscrypt_master_key *mk); ++ ++void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk); ++ ++struct fscrypt_master_key * + fscrypt_find_master_key(struct super_block *sb, + const struct fscrypt_key_specifier *mk_spec); + +diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c +index af74599ae1cf..be5c650e4957 100644 +--- a/fs/crypto/hooks.c ++++ b/fs/crypto/hooks.c +@@ -5,8 +5,6 @@ + * Encryption hooks for higher-level filesystem operations. + */ + +-#include +- + #include "fscrypt_private.h" + + /** +@@ -142,7 +140,6 @@ int fscrypt_prepare_setflags(struct inode *inode, + unsigned int oldflags, unsigned int flags) + { + struct fscrypt_info *ci; +- struct key *key; + struct fscrypt_master_key *mk; + int err; + +@@ -158,14 +155,13 @@ int fscrypt_prepare_setflags(struct inode *inode, + ci = inode->i_crypt_info; + if (ci->ci_policy.version != FSCRYPT_POLICY_V2) + return -EINVAL; +- key = ci->ci_master_key; +- mk = key->payload.data[0]; +- down_read(&key->sem); ++ mk = ci->ci_master_key; ++ down_read(&mk->mk_sem); + if (is_master_key_secret_present(&mk->mk_secret)) + err = fscrypt_derive_dirhash_key(ci, mk); + else + err = -ENOKEY; +- up_read(&key->sem); ++ up_read(&mk->mk_sem); + return err; + } + return 0; +diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c +index caee9f8620dd..9b98d6a576e6 100644 +--- a/fs/crypto/keyring.c ++++ b/fs/crypto/keyring.c +@@ -18,6 +18,7 @@ + * information about these ioctls. + */ + ++#include + #include + #include + #include +@@ -25,6 +26,18 @@ + + #include "fscrypt_private.h" + ++/* The master encryption keys for a filesystem (->s_master_keys) */ ++struct fscrypt_keyring { ++ /* ++ * Lock that protects ->key_hashtable. It does *not* protect the ++ * fscrypt_master_key structs themselves. ++ */ ++ spinlock_t lock; ++ ++ /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */ ++ struct hlist_head key_hashtable[128]; ++}; ++ + static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret) + { + fscrypt_destroy_hkdf(&secret->hkdf); +@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst, + memzero_explicit(src, sizeof(*src)); + } + +-static void free_master_key(struct fscrypt_master_key *mk) ++static void fscrypt_free_master_key(struct rcu_head *head) ++{ ++ struct fscrypt_master_key *mk = ++ container_of(head, struct fscrypt_master_key, mk_rcu_head); ++ /* ++ * The master key secret and any embedded subkeys should have already ++ * been wiped when the last active reference to the fscrypt_master_key ++ * struct was dropped; doing it here would be unnecessarily late. ++ * Nevertheless, use kfree_sensitive() in case anything was missed. ++ */ ++ kfree_sensitive(mk); ++} ++ ++void fscrypt_put_master_key(struct fscrypt_master_key *mk) ++{ ++ if (!refcount_dec_and_test(&mk->mk_struct_refs)) ++ return; ++ /* ++ * No structural references left, so free ->mk_users, and also free the ++ * fscrypt_master_key struct itself after an RCU grace period ensures ++ * that concurrent keyring lookups can no longer find it. ++ */ ++ WARN_ON(refcount_read(&mk->mk_active_refs) != 0); ++ key_put(mk->mk_users); ++ mk->mk_users = NULL; ++ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key); ++} ++ ++void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk) + { ++ struct super_block *sb = mk->mk_sb; ++ struct fscrypt_keyring *keyring = sb->s_master_keys; + size_t i; + +- wipe_master_key_secret(&mk->mk_secret); ++ if (!refcount_dec_and_test(&mk->mk_active_refs)) ++ return; ++ /* ++ * No active references left, so complete the full removal of this ++ * fscrypt_master_key struct by removing it from the keyring and ++ * destroying any subkeys embedded in it. ++ */ ++ ++ spin_lock(&keyring->lock); ++ hlist_del_rcu(&mk->mk_node); ++ spin_unlock(&keyring->lock); ++ ++ /* ++ * ->mk_active_refs == 0 implies that ->mk_secret is not present and ++ * that ->mk_decrypted_inodes is empty. ++ */ ++ WARN_ON(is_master_key_secret_present(&mk->mk_secret)); ++ WARN_ON(!list_empty(&mk->mk_decrypted_inodes)); + + for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { + fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]); + fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]); + fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]); + } ++ memzero_explicit(&mk->mk_ino_hash_key, ++ sizeof(mk->mk_ino_hash_key)); ++ mk->mk_ino_hash_key_initialized = false; + +- key_put(mk->mk_users); +- kfree_sensitive(mk); ++ /* Drop the structural ref associated with the active refs. */ ++ fscrypt_put_master_key(mk); + } + + static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec) +@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec) + return master_key_spec_len(spec) != 0; + } + +-static int fscrypt_key_instantiate(struct key *key, +- struct key_preparsed_payload *prep) +-{ +- key->payload.data[0] = (struct fscrypt_master_key *)prep->data; +- return 0; +-} +- +-static void fscrypt_key_destroy(struct key *key) +-{ +- free_master_key(key->payload.data[0]); +-} +- +-static void fscrypt_key_describe(const struct key *key, struct seq_file *m) +-{ +- seq_puts(m, key->description); +- +- if (key_is_positive(key)) { +- const struct fscrypt_master_key *mk = key->payload.data[0]; +- +- if (!is_master_key_secret_present(&mk->mk_secret)) +- seq_puts(m, ": secret removed"); +- } +-} +- +-/* +- * Type of key in ->s_master_keys. Each key of this type represents a master +- * key which has been added to the filesystem. Its payload is a +- * 'struct fscrypt_master_key'. The "." prefix in the key type name prevents +- * users from adding keys of this type via the keyrings syscalls rather than via +- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY. +- */ +-static struct key_type key_type_fscrypt = { +- .name = "._fscrypt", +- .instantiate = fscrypt_key_instantiate, +- .destroy = fscrypt_key_destroy, +- .describe = fscrypt_key_describe, +-}; +- + static int fscrypt_user_key_instantiate(struct key *key, + struct key_preparsed_payload *prep) + { +@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = { + .describe = fscrypt_user_key_describe, + }; + +-/* Search ->s_master_keys or ->mk_users */ +-static struct key *search_fscrypt_keyring(struct key *keyring, +- struct key_type *type, +- const char *description) +-{ +- /* +- * We need to mark the keyring reference as "possessed" so that we +- * acquire permission to search it, via the KEY_POS_SEARCH permission. +- */ +- key_ref_t keyref = make_key_ref(keyring, true /* possessed */); +- +- keyref = keyring_search(keyref, type, description, false); +- if (IS_ERR(keyref)) { +- if (PTR_ERR(keyref) == -EAGAIN || /* not found */ +- PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */ +- keyref = ERR_PTR(-ENOKEY); +- return ERR_CAST(keyref); +- } +- return key_ref_to_ptr(keyref); +-} +- +-#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \ +- (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id)) +- +-#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1) +- + #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \ + (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \ + CONST_STRLEN("-users") + 1) +@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring, + #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \ + (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1) + +-static void format_fs_keyring_description( +- char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE], +- const struct super_block *sb) +-{ +- sprintf(description, "fscrypt-%s", sb->s_id); +-} +- +-static void format_mk_description( +- char description[FSCRYPT_MK_DESCRIPTION_SIZE], +- const struct fscrypt_key_specifier *mk_spec) +-{ +- sprintf(description, "%*phN", +- master_key_spec_len(mk_spec), (u8 *)&mk_spec->u); +-} +- + static void format_mk_users_keyring_description( + char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE], + const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) +@@ -199,20 +183,15 @@ static void format_mk_user_description( + /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */ + static int allocate_filesystem_keyring(struct super_block *sb) + { +- char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE]; +- struct key *keyring; ++ struct fscrypt_keyring *keyring; + + if (sb->s_master_keys) + return 0; + +- format_fs_keyring_description(description, sb); +- keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, +- current_cred(), KEY_POS_SEARCH | +- KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); +- if (IS_ERR(keyring)) +- return PTR_ERR(keyring); +- ++ keyring = kzalloc(sizeof(*keyring), GFP_KERNEL); ++ if (!keyring) ++ return -ENOMEM; ++ spin_lock_init(&keyring->lock); + /* + * Pairs with the smp_load_acquire() in fscrypt_find_master_key(). + * I.e., here we publish ->s_master_keys with a RELEASE barrier so that +@@ -222,21 +201,75 @@ static int allocate_filesystem_keyring(struct super_block *sb) + return 0; + } + +-void fscrypt_sb_free(struct super_block *sb) ++/* ++ * This is called at unmount time to release all encryption keys that have been ++ * added to the filesystem, along with the keyring that contains them. ++ * ++ * Note that besides clearing and freeing memory, this might need to evict keys ++ * from the keyslots of an inline crypto engine. Therefore, this must be called ++ * while the filesystem's underlying block device(s) are still available. ++ */ ++void fscrypt_sb_delete(struct super_block *sb) + { +- key_put(sb->s_master_keys); ++ struct fscrypt_keyring *keyring = sb->s_master_keys; ++ size_t i; ++ ++ if (!keyring) ++ return; ++ ++ for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) { ++ struct hlist_head *bucket = &keyring->key_hashtable[i]; ++ struct fscrypt_master_key *mk; ++ struct hlist_node *tmp; ++ ++ hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) { ++ /* ++ * Since all inodes were already evicted, every key ++ * remaining in the keyring should have an empty inode ++ * list, and should only still be in the keyring due to ++ * the single active ref associated with ->mk_secret. ++ * There should be no structural refs beyond the one ++ * associated with the active ref. ++ */ ++ WARN_ON(refcount_read(&mk->mk_active_refs) != 1); ++ WARN_ON(refcount_read(&mk->mk_struct_refs) != 1); ++ WARN_ON(!is_master_key_secret_present(&mk->mk_secret)); ++ wipe_master_key_secret(&mk->mk_secret); ++ fscrypt_put_master_key_activeref(mk); ++ } ++ } ++ kfree_sensitive(keyring); + sb->s_master_keys = NULL; + } + ++static struct hlist_head * ++fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring, ++ const struct fscrypt_key_specifier *mk_spec) ++{ ++ /* ++ * Since key specifiers should be "random" values, it is sufficient to ++ * use a trivial hash function that just takes the first several bits of ++ * the key specifier. ++ */ ++ unsigned long i = get_unaligned((unsigned long *)&mk_spec->u); ++ ++ return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)]; ++} ++ + /* +- * Find the specified master key in ->s_master_keys. +- * Returns ERR_PTR(-ENOKEY) if not found. ++ * Find the specified master key struct in ->s_master_keys and take a structural ++ * ref to it. The structural ref guarantees that the key struct continues to ++ * exist, but it does *not* guarantee that ->s_master_keys continues to contain ++ * the key struct. The structural ref needs to be dropped by ++ * fscrypt_put_master_key(). Returns NULL if the key struct is not found. + */ +-struct key *fscrypt_find_master_key(struct super_block *sb, +- const struct fscrypt_key_specifier *mk_spec) ++struct fscrypt_master_key * ++fscrypt_find_master_key(struct super_block *sb, ++ const struct fscrypt_key_specifier *mk_spec) + { +- struct key *keyring; +- char description[FSCRYPT_MK_DESCRIPTION_SIZE]; ++ struct fscrypt_keyring *keyring; ++ struct hlist_head *bucket; ++ struct fscrypt_master_key *mk; + + /* + * Pairs with the smp_store_release() in allocate_filesystem_keyring(). +@@ -246,10 +279,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb, + */ + keyring = smp_load_acquire(&sb->s_master_keys); + if (keyring == NULL) +- return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */ +- +- format_mk_description(description, mk_spec); +- return search_fscrypt_keyring(keyring, &key_type_fscrypt, description); ++ return NULL; /* No keyring yet, so no keys yet. */ ++ ++ bucket = fscrypt_mk_hash_bucket(keyring, mk_spec); ++ rcu_read_lock(); ++ switch (mk_spec->type) { ++ case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR: ++ hlist_for_each_entry_rcu(mk, bucket, mk_node) { ++ if (mk->mk_spec.type == ++ FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR && ++ memcmp(mk->mk_spec.u.descriptor, ++ mk_spec->u.descriptor, ++ FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 && ++ refcount_inc_not_zero(&mk->mk_struct_refs)) ++ goto out; ++ } ++ break; ++ case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER: ++ hlist_for_each_entry_rcu(mk, bucket, mk_node) { ++ if (mk->mk_spec.type == ++ FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER && ++ memcmp(mk->mk_spec.u.identifier, ++ mk_spec->u.identifier, ++ FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 && ++ refcount_inc_not_zero(&mk->mk_struct_refs)) ++ goto out; ++ } ++ break; ++ } ++ mk = NULL; ++out: ++ rcu_read_unlock(); ++ return mk; + } + + static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk) +@@ -277,17 +338,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk) + static struct key *find_master_key_user(struct fscrypt_master_key *mk) + { + char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; ++ key_ref_t keyref; + + format_mk_user_description(description, mk->mk_spec.u.identifier); +- return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user, +- description); ++ ++ /* ++ * We need to mark the keyring reference as "possessed" so that we ++ * acquire permission to search it, via the KEY_POS_SEARCH permission. ++ */ ++ keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/), ++ &key_type_fscrypt_user, description, false); ++ if (IS_ERR(keyref)) { ++ if (PTR_ERR(keyref) == -EAGAIN || /* not found */ ++ PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */ ++ keyref = ERR_PTR(-ENOKEY); ++ return ERR_CAST(keyref); ++ } ++ return key_ref_to_ptr(keyref); + } + + /* + * Give the current user a "key" in ->mk_users. This charges the user's quota + * and marks the master key as added by the current user, so that it cannot be +- * removed by another user with the key. Either the master key's key->sem must +- * be held for write, or the master key must be still undergoing initialization. ++ * removed by another user with the key. Either ->mk_sem must be held for ++ * write, or the master key must be still undergoing initialization. + */ + static int add_master_key_user(struct fscrypt_master_key *mk) + { +@@ -309,7 +383,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk) + + /* + * Remove the current user's "key" from ->mk_users. +- * The master key's key->sem must be held for write. ++ * ->mk_sem must be held for write. + * + * Returns 0 if removed, -ENOKEY if not found, or another -errno code. + */ +@@ -327,63 +401,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk) + } + + /* +- * Allocate a new fscrypt_master_key which contains the given secret, set it as +- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key' +- * into the given keyring. Synchronized by fscrypt_add_key_mutex. ++ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and ++ * insert it into sb->s_master_keys. + */ +-static int add_new_master_key(struct fscrypt_master_key_secret *secret, +- const struct fscrypt_key_specifier *mk_spec, +- struct key *keyring) ++static int add_new_master_key(struct super_block *sb, ++ struct fscrypt_master_key_secret *secret, ++ const struct fscrypt_key_specifier *mk_spec) + { ++ struct fscrypt_keyring *keyring = sb->s_master_keys; + struct fscrypt_master_key *mk; +- char description[FSCRYPT_MK_DESCRIPTION_SIZE]; +- struct key *key; + int err; + + mk = kzalloc(sizeof(*mk), GFP_KERNEL); + if (!mk) + return -ENOMEM; + ++ mk->mk_sb = sb; ++ init_rwsem(&mk->mk_sem); ++ refcount_set(&mk->mk_struct_refs, 1); + mk->mk_spec = *mk_spec; + +- move_master_key_secret(&mk->mk_secret, secret); +- +- refcount_set(&mk->mk_refcount, 1); /* secret is present */ + INIT_LIST_HEAD(&mk->mk_decrypted_inodes); + spin_lock_init(&mk->mk_decrypted_inodes_lock); + + if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + err = allocate_master_key_users_keyring(mk); + if (err) +- goto out_free_mk; ++ goto out_put; + err = add_master_key_user(mk); + if (err) +- goto out_free_mk; ++ goto out_put; + } + +- /* +- * Note that we don't charge this key to anyone's quota, since when +- * ->mk_users is in use those keys are charged instead, and otherwise +- * (when ->mk_users isn't in use) only root can add these keys. +- */ +- format_mk_description(description, mk_spec); +- key = key_alloc(&key_type_fscrypt, description, +- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), +- KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW, +- KEY_ALLOC_NOT_IN_QUOTA, NULL); +- if (IS_ERR(key)) { +- err = PTR_ERR(key); +- goto out_free_mk; +- } +- err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL); +- key_put(key); +- if (err) +- goto out_free_mk; ++ move_master_key_secret(&mk->mk_secret, secret); ++ refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */ + ++ spin_lock(&keyring->lock); ++ hlist_add_head_rcu(&mk->mk_node, ++ fscrypt_mk_hash_bucket(keyring, mk_spec)); ++ spin_unlock(&keyring->lock); + return 0; + +-out_free_mk: +- free_master_key(mk); ++out_put: ++ fscrypt_put_master_key(mk); + return err; + } + +@@ -392,42 +452,34 @@ static int add_new_master_key(struct fscrypt_master_key_secret *secret, + static int add_existing_master_key(struct fscrypt_master_key *mk, + struct fscrypt_master_key_secret *secret) + { +- struct key *mk_user; +- bool rekey; + int err; + + /* + * If the current user is already in ->mk_users, then there's nothing to +- * do. (Not applicable for v1 policy keys, which have NULL ->mk_users.) ++ * do. Otherwise, we need to add the user to ->mk_users. (Neither is ++ * applicable for v1 policy keys, which have NULL ->mk_users.) + */ + if (mk->mk_users) { +- mk_user = find_master_key_user(mk); ++ struct key *mk_user = find_master_key_user(mk); ++ + if (mk_user != ERR_PTR(-ENOKEY)) { + if (IS_ERR(mk_user)) + return PTR_ERR(mk_user); + key_put(mk_user); + return 0; + } +- } +- +- /* If we'll be re-adding ->mk_secret, try to take the reference. */ +- rekey = !is_master_key_secret_present(&mk->mk_secret); +- if (rekey && !refcount_inc_not_zero(&mk->mk_refcount)) +- return KEY_DEAD; +- +- /* Add the current user to ->mk_users, if applicable. */ +- if (mk->mk_users) { + err = add_master_key_user(mk); +- if (err) { +- if (rekey && refcount_dec_and_test(&mk->mk_refcount)) +- return KEY_DEAD; ++ if (err) + return err; +- } + } + + /* Re-add the secret if needed. */ +- if (rekey) ++ if (!is_master_key_secret_present(&mk->mk_secret)) { ++ if (!refcount_inc_not_zero(&mk->mk_active_refs)) ++ return KEY_DEAD; + move_master_key_secret(&mk->mk_secret, secret); ++ } ++ + return 0; + } + +@@ -436,38 +488,36 @@ static int do_add_master_key(struct super_block *sb, + const struct fscrypt_key_specifier *mk_spec) + { + static DEFINE_MUTEX(fscrypt_add_key_mutex); +- struct key *key; ++ struct fscrypt_master_key *mk; + int err; + + mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ +-retry: +- key = fscrypt_find_master_key(sb, mk_spec); +- if (IS_ERR(key)) { +- err = PTR_ERR(key); +- if (err != -ENOKEY) +- goto out_unlock; ++ ++ mk = fscrypt_find_master_key(sb, mk_spec); ++ if (!mk) { + /* Didn't find the key in ->s_master_keys. Add it. */ + err = allocate_filesystem_keyring(sb); +- if (err) +- goto out_unlock; +- err = add_new_master_key(secret, mk_spec, sb->s_master_keys); ++ if (!err) ++ err = add_new_master_key(sb, secret, mk_spec); + } else { + /* + * Found the key in ->s_master_keys. Re-add the secret if + * needed, and add the user to ->mk_users if needed. + */ +- down_write(&key->sem); +- err = add_existing_master_key(key->payload.data[0], secret); +- up_write(&key->sem); ++ down_write(&mk->mk_sem); ++ err = add_existing_master_key(mk, secret); ++ up_write(&mk->mk_sem); + if (err == KEY_DEAD) { +- /* Key being removed or needs to be removed */ +- key_invalidate(key); +- key_put(key); +- goto retry; ++ /* ++ * We found a key struct, but it's already been fully ++ * removed. Ignore the old struct and add a new one. ++ * fscrypt_add_key_mutex means we don't need to worry ++ * about concurrent adds. ++ */ ++ err = add_new_master_key(sb, secret, mk_spec); + } +- key_put(key); ++ fscrypt_put_master_key(mk); + } +-out_unlock: + mutex_unlock(&fscrypt_add_key_mutex); + return err; + } +@@ -771,19 +821,19 @@ int fscrypt_verify_key_added(struct super_block *sb, + const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) + { + struct fscrypt_key_specifier mk_spec; +- struct key *key, *mk_user; + struct fscrypt_master_key *mk; ++ struct key *mk_user; + int err; + + mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; + memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE); + +- key = fscrypt_find_master_key(sb, &mk_spec); +- if (IS_ERR(key)) { +- err = PTR_ERR(key); ++ mk = fscrypt_find_master_key(sb, &mk_spec); ++ if (!mk) { ++ err = -ENOKEY; + goto out; + } +- mk = key->payload.data[0]; ++ down_read(&mk->mk_sem); + mk_user = find_master_key_user(mk); + if (IS_ERR(mk_user)) { + err = PTR_ERR(mk_user); +@@ -791,7 +841,8 @@ int fscrypt_verify_key_added(struct super_block *sb, + key_put(mk_user); + err = 0; + } +- key_put(key); ++ up_read(&mk->mk_sem); ++ fscrypt_put_master_key(mk); + out: + if (err == -ENOKEY && capable(CAP_FOWNER)) + err = 0; +@@ -953,11 +1004,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_remove_key_arg __user *uarg = _uarg; + struct fscrypt_remove_key_arg arg; +- struct key *key; + struct fscrypt_master_key *mk; + u32 status_flags = 0; + int err; +- bool dead; ++ bool inodes_remain; + + if (copy_from_user(&arg, uarg, sizeof(arg))) + return -EFAULT; +@@ -977,12 +1027,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) + return -EACCES; + + /* Find the key being removed. */ +- key = fscrypt_find_master_key(sb, &arg.key_spec); +- if (IS_ERR(key)) +- return PTR_ERR(key); +- mk = key->payload.data[0]; +- +- down_write(&key->sem); ++ mk = fscrypt_find_master_key(sb, &arg.key_spec); ++ if (!mk) ++ return -ENOKEY; ++ down_write(&mk->mk_sem); + + /* If relevant, remove current user's (or all users) claim to the key */ + if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { +@@ -991,7 +1039,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) + else + err = remove_master_key_user(mk); + if (err) { +- up_write(&key->sem); ++ up_write(&mk->mk_sem); + goto out_put_key; + } + if (mk->mk_users->keys.nr_leaves_on_tree != 0) { +@@ -1003,26 +1051,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) + status_flags |= + FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS; + err = 0; +- up_write(&key->sem); ++ up_write(&mk->mk_sem); + goto out_put_key; + } + } + + /* No user claims remaining. Go ahead and wipe the secret. */ +- dead = false; ++ err = -ENOKEY; + if (is_master_key_secret_present(&mk->mk_secret)) { + wipe_master_key_secret(&mk->mk_secret); +- dead = refcount_dec_and_test(&mk->mk_refcount); +- } +- up_write(&key->sem); +- if (dead) { +- /* +- * No inodes reference the key, and we wiped the secret, so the +- * key object is free to be removed from the keyring. +- */ +- key_invalidate(key); ++ fscrypt_put_master_key_activeref(mk); + err = 0; +- } else { ++ } ++ inodes_remain = refcount_read(&mk->mk_active_refs) > 0; ++ up_write(&mk->mk_sem); ++ ++ if (inodes_remain) { + /* Some inodes still reference this key; try to evict them. */ + err = try_to_lock_encrypted_files(sb, mk); + if (err == -EBUSY) { +@@ -1038,7 +1082,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) + * has been fully removed including all files locked. + */ + out_put_key: +- key_put(key); ++ fscrypt_put_master_key(mk); + if (err == 0) + err = put_user(status_flags, &uarg->removal_status_flags); + return err; +@@ -1085,7 +1129,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) + { + struct super_block *sb = file_inode(filp)->i_sb; + struct fscrypt_get_key_status_arg arg; +- struct key *key; + struct fscrypt_master_key *mk; + int err; + +@@ -1102,19 +1145,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) + arg.user_count = 0; + memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved)); + +- key = fscrypt_find_master_key(sb, &arg.key_spec); +- if (IS_ERR(key)) { +- if (key != ERR_PTR(-ENOKEY)) +- return PTR_ERR(key); ++ mk = fscrypt_find_master_key(sb, &arg.key_spec); ++ if (!mk) { + arg.status = FSCRYPT_KEY_STATUS_ABSENT; + err = 0; + goto out; + } +- mk = key->payload.data[0]; +- down_read(&key->sem); ++ down_read(&mk->mk_sem); + + if (!is_master_key_secret_present(&mk->mk_secret)) { +- arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED; ++ arg.status = refcount_read(&mk->mk_active_refs) > 0 ? ++ FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED : ++ FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */; + err = 0; + goto out_release_key; + } +@@ -1136,8 +1178,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) + } + err = 0; + out_release_key: +- up_read(&key->sem); +- key_put(key); ++ up_read(&mk->mk_sem); ++ fscrypt_put_master_key(mk); + out: + if (!err && copy_to_user(uarg, &arg, sizeof(arg))) + err = -EFAULT; +@@ -1149,13 +1191,9 @@ int __init fscrypt_init_keyring(void) + { + int err; + +- err = register_key_type(&key_type_fscrypt); +- if (err) +- return err; +- + err = register_key_type(&key_type_fscrypt_user); + if (err) +- goto err_unregister_fscrypt; ++ return err; + + err = register_key_type(&key_type_fscrypt_provisioning); + if (err) +@@ -1165,7 +1203,5 @@ int __init fscrypt_init_keyring(void) + + err_unregister_fscrypt_user: + unregister_key_type(&key_type_fscrypt_user); +-err_unregister_fscrypt: +- unregister_key_type(&key_type_fscrypt); + return err; + } +diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c +index c35711896bd4..f8f8f41c1de9 100644 +--- a/fs/crypto/keysetup.c ++++ b/fs/crypto/keysetup.c +@@ -9,7 +9,6 @@ + */ + + #include +-#include + #include + + #include "fscrypt_private.h" +@@ -152,6 +151,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key) + { + crypto_free_skcipher(prep_key->tfm); + fscrypt_destroy_inline_crypt_key(prep_key); ++ memzero_explicit(prep_key, sizeof(*prep_key)); + } + + /* Given a per-file encryption key, set up the file's crypto transform object */ +@@ -405,20 +405,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk, + /* + * Find the master key, then set up the inode's actual encryption key. + * +- * If the master key is found in the filesystem-level keyring, then the +- * corresponding 'struct key' is returned in *master_key_ret with its semaphore +- * read-locked. This is needed to ensure that only one task links the +- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create +- * an fscrypt_info for the same inode), and to synchronize the master key being +- * removed with a new inode starting to use it. ++ * If the master key is found in the filesystem-level keyring, then it is ++ * returned in *mk_ret with its semaphore read-locked. This is needed to ensure ++ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as ++ * multiple tasks may race to create an fscrypt_info for the same inode), and to ++ * synchronize the master key being removed with a new inode starting to use it. + */ + static int setup_file_encryption_key(struct fscrypt_info *ci, + bool need_dirhash_key, +- struct key **master_key_ret) ++ struct fscrypt_master_key **mk_ret) + { +- struct key *key; +- struct fscrypt_master_key *mk = NULL; + struct fscrypt_key_specifier mk_spec; ++ struct fscrypt_master_key *mk; + int err; + + err = fscrypt_select_encryption_impl(ci); +@@ -429,11 +427,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, + if (err) + return err; + +- key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); +- if (IS_ERR(key)) { +- if (key != ERR_PTR(-ENOKEY) || +- ci->ci_policy.version != FSCRYPT_POLICY_V1) +- return PTR_ERR(key); ++ mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec); ++ if (!mk) { ++ if (ci->ci_policy.version != FSCRYPT_POLICY_V1) ++ return -ENOKEY; + + /* + * As a legacy fallback for v1 policies, search for the key in +@@ -443,9 +440,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, + */ + return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci); + } +- +- mk = key->payload.data[0]; +- down_read(&key->sem); ++ down_read(&mk->mk_sem); + + /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */ + if (!is_master_key_secret_present(&mk->mk_secret)) { +@@ -473,18 +468,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci, + if (err) + goto out_release_key; + +- *master_key_ret = key; ++ *mk_ret = mk; + return 0; + + out_release_key: +- up_read(&key->sem); +- key_put(key); ++ up_read(&mk->mk_sem); ++ fscrypt_put_master_key(mk); + return err; + } + + static void put_crypt_info(struct fscrypt_info *ci) + { +- struct key *key; ++ struct fscrypt_master_key *mk; + + if (!ci) + return; +@@ -494,24 +489,18 @@ static void put_crypt_info(struct fscrypt_info *ci) + else if (ci->ci_owns_key) + fscrypt_destroy_prepared_key(&ci->ci_enc_key); + +- key = ci->ci_master_key; +- if (key) { +- struct fscrypt_master_key *mk = key->payload.data[0]; +- ++ mk = ci->ci_master_key; ++ if (mk) { + /* + * Remove this inode from the list of inodes that were unlocked +- * with the master key. +- * +- * In addition, if we're removing the last inode from a key that +- * already had its secret removed, invalidate the key so that it +- * gets removed from ->s_master_keys. ++ * with the master key. In addition, if we're removing the last ++ * inode from a master key struct that already had its secret ++ * removed, then complete the full removal of the struct. + */ + spin_lock(&mk->mk_decrypted_inodes_lock); + list_del(&ci->ci_master_key_link); + spin_unlock(&mk->mk_decrypted_inodes_lock); +- if (refcount_dec_and_test(&mk->mk_refcount)) +- key_invalidate(key); +- key_put(key); ++ fscrypt_put_master_key_activeref(mk); + } + memzero_explicit(ci, sizeof(*ci)); + kmem_cache_free(fscrypt_info_cachep, ci); +@@ -525,7 +514,7 @@ fscrypt_setup_encryption_info(struct inode *inode, + { + struct fscrypt_info *crypt_info; + struct fscrypt_mode *mode; +- struct key *master_key = NULL; ++ struct fscrypt_master_key *mk = NULL; + int res; + + res = fscrypt_initialize(inode->i_sb->s_cop->flags); +@@ -548,8 +537,7 @@ fscrypt_setup_encryption_info(struct inode *inode, + WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE); + crypt_info->ci_mode = mode; + +- res = setup_file_encryption_key(crypt_info, need_dirhash_key, +- &master_key); ++ res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk); + if (res) + goto out; + +@@ -564,12 +552,9 @@ fscrypt_setup_encryption_info(struct inode *inode, + * We won the race and set ->i_crypt_info to our crypt_info. + * Now link it into the master key's inode list. + */ +- if (master_key) { +- struct fscrypt_master_key *mk = +- master_key->payload.data[0]; +- +- refcount_inc(&mk->mk_refcount); +- crypt_info->ci_master_key = key_get(master_key); ++ if (mk) { ++ crypt_info->ci_master_key = mk; ++ refcount_inc(&mk->mk_active_refs); + spin_lock(&mk->mk_decrypted_inodes_lock); + list_add(&crypt_info->ci_master_key_link, + &mk->mk_decrypted_inodes); +@@ -579,9 +564,9 @@ fscrypt_setup_encryption_info(struct inode *inode, + } + res = 0; + out: +- if (master_key) { +- up_read(&master_key->sem); +- key_put(master_key); ++ if (mk) { ++ up_read(&mk->mk_sem); ++ fscrypt_put_master_key(mk); + } + put_crypt_info(crypt_info); + return res; +@@ -746,7 +731,6 @@ EXPORT_SYMBOL(fscrypt_free_inode); + int fscrypt_drop_inode(struct inode *inode) + { + const struct fscrypt_info *ci = fscrypt_get_info(inode); +- const struct fscrypt_master_key *mk; + + /* + * If ci is NULL, then the inode doesn't have an encryption key set up +@@ -756,7 +740,6 @@ int fscrypt_drop_inode(struct inode *inode) + */ + if (!ci || !ci->ci_master_key) + return 0; +- mk = ci->ci_master_key->payload.data[0]; + + /* + * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes +@@ -775,6 +758,6 @@ int fscrypt_drop_inode(struct inode *inode) + * then the thread removing the key will either evict the inode itself + * or will correctly detect that it wasn't evicted due to the race. + */ +- return !is_master_key_secret_present(&mk->mk_secret); ++ return !is_master_key_secret_present(&ci->ci_master_key->mk_secret); + } + EXPORT_SYMBOL_GPL(fscrypt_drop_inode); +diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c +index 5f858cee1e3b..ad21498f77bb 100644 +--- a/fs/crypto/policy.c ++++ b/fs/crypto/policy.c +@@ -713,12 +713,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data) + * delayed key setup that requires the inode number. + */ + if (ci->ci_policy.version == FSCRYPT_POLICY_V2 && +- (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) { +- const struct fscrypt_master_key *mk = +- ci->ci_master_key->payload.data[0]; +- +- fscrypt_hash_inode_number(ci, mk); +- } ++ (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) ++ fscrypt_hash_inode_number(ci, ci->ci_master_key); + + return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data); + } +diff --git a/fs/super.c b/fs/super.c +index 60f57c7bc0a6..9ac1e71f5150 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -291,7 +291,6 @@ static void __put_super(struct super_block *s) + WARN_ON(s->s_inode_lru.node); + WARN_ON(!list_empty(&s->s_mounts)); + security_sb_free(s); +- fscrypt_sb_free(s); + put_user_ns(s->s_user_ns); + kfree(s->s_subtype); + call_rcu(&s->rcu, destroy_super_rcu); +@@ -451,6 +450,7 @@ void generic_shutdown_super(struct super_block *sb) + evict_inodes(sb); + /* only nonzero refcount inodes can have marks */ + fsnotify_sb_delete(sb); ++ fscrypt_sb_delete(sb); + security_sb_delete(sb); + + if (sb->s_dio_done_wq) { +diff --git a/include/linux/fs.h b/include/linux/fs.h +index fb19f532c76c..21ed10a2e1cd 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1455,7 +1455,7 @@ struct super_block { + const struct xattr_handler **s_xattr; + #ifdef CONFIG_FS_ENCRYPTION + const struct fscrypt_operations *s_cop; +- struct key *s_master_keys; /* master crypto keys in use */ ++ struct fscrypt_keyring *s_master_keys; /* master crypto keys in use */ + #endif + #ifdef CONFIG_FS_VERITY + const struct fsverity_operations *s_vop; +diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h +index e60d57c99cb6..4737075c7426 100644 +--- a/include/linux/fscrypt.h ++++ b/include/linux/fscrypt.h +@@ -311,7 +311,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy) + } + + /* keyring.c */ +-void fscrypt_sb_free(struct super_block *sb); ++void fscrypt_sb_delete(struct super_block *sb); + int fscrypt_ioctl_add_key(struct file *filp, void __user *arg); + int fscrypt_add_test_dummy_key(struct super_block *sb, + const struct fscrypt_dummy_policy *dummy_policy); +@@ -521,7 +521,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy) + } + + /* keyring.c */ +-static inline void fscrypt_sb_free(struct super_block *sb) ++static inline void fscrypt_sb_delete(struct super_block *sb) + { + } + +-- +2.35.1 + diff --git a/queue-5.19/fsi-core-check-error-number-after-calling-ida_simple.patch b/queue-5.19/fsi-core-check-error-number-after-calling-ida_simple.patch new file mode 100644 index 00000000000..5d6c3401ec4 --- /dev/null +++ b/queue-5.19/fsi-core-check-error-number-after-calling-ida_simple.patch @@ -0,0 +1,41 @@ +From 632acc456ee9335dc33447b6823789e588b2ddcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jan 2022 15:34:11 +0800 +Subject: fsi: core: Check error number after calling ida_simple_get + +From: Jiasheng Jiang + +[ Upstream commit 35af9fb49bc5c6d61ef70b501c3a56fe161cce3e ] + +If allocation fails, the ida_simple_get() will return error number. +So master->idx could be error number and be used in dev_set_name(). +Therefore, it should be better to check it and return error if fails, +like the ida_simple_get() in __fsi_get_new_minor(). + +Fixes: 09aecfab93b8 ("drivers/fsi: Add fsi master definition") +Signed-off-by: Jiasheng Jiang +Reviewed-by: Eddie James +Link: https://lore.kernel.org/r/20220111073411.614138-1-jiasheng@iscas.ac.cn +Signed-off-by: Joel Stanley +Signed-off-by: Sasha Levin +--- + drivers/fsi/fsi-core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c +index 3a7b78e36701..5858e6339a10 100644 +--- a/drivers/fsi/fsi-core.c ++++ b/drivers/fsi/fsi-core.c +@@ -1314,6 +1314,9 @@ int fsi_master_register(struct fsi_master *master) + + mutex_init(&master->scan_lock); + master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL); ++ if (master->idx < 0) ++ return master->idx; ++ + dev_set_name(&master->dev, "fsi%d", master->idx); + master->dev.class = &fsi_master_class; + +-- +2.35.1 + diff --git a/queue-5.19/fsi-master-ast-cf-fix-missing-of_node_put-in-fsi_mas.patch b/queue-5.19/fsi-master-ast-cf-fix-missing-of_node_put-in-fsi_mas.patch new file mode 100644 index 00000000000..002ee651ac0 --- /dev/null +++ b/queue-5.19/fsi-master-ast-cf-fix-missing-of_node_put-in-fsi_mas.patch @@ -0,0 +1,43 @@ +From 7d46d14b71a5847c8ec56d13aaed719592f93fdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Apr 2022 08:59:11 +0000 +Subject: fsi: master-ast-cf: Fix missing of_node_put in fsi_master_acf_probe + +From: Lv Ruyi + +[ Upstream commit 182d98e00e4745fe253cb0c24c63bbac253464a2 ] + +of_parse_phandle returns node pointer with refcount incremented, use +of_node_put() on it when done. + +Reported-by: Zeal Robot +Signed-off-by: Lv Ruyi +Link: https://lore.kernel.org/r/20220407085911.2491719-1-lv.ruyi@zte.com.cn +Signed-off-by: Joel Stanley +Signed-off-by: Sasha Levin +--- + drivers/fsi/fsi-master-ast-cf.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c +index 24292acdbaf8..5f608ef8b53c 100644 +--- a/drivers/fsi/fsi-master-ast-cf.c ++++ b/drivers/fsi/fsi-master-ast-cf.c +@@ -1324,12 +1324,14 @@ static int fsi_master_acf_probe(struct platform_device *pdev) + } + master->cvic = devm_of_iomap(&pdev->dev, np, 0, NULL); + if (IS_ERR(master->cvic)) { ++ of_node_put(np); + rc = PTR_ERR(master->cvic); + dev_err(&pdev->dev, "Error %d mapping CVIC\n", rc); + goto err_free; + } + rc = of_property_read_u32(np, "copro-sw-interrupts", + &master->cvic_sw_irq); ++ of_node_put(np); + if (rc) { + dev_err(&pdev->dev, "Can't find coprocessor SW interrupt\n"); + goto err_free; +-- +2.35.1 + diff --git a/queue-5.19/fsi-occ-prevent-use-after-free.patch b/queue-5.19/fsi-occ-prevent-use-after-free.patch new file mode 100644 index 00000000000..80c428c4d17 --- /dev/null +++ b/queue-5.19/fsi-occ-prevent-use-after-free.patch @@ -0,0 +1,84 @@ +From 4f840dad109072469b35ac97f473befa384476a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 May 2022 14:44:24 -0500 +Subject: fsi: occ: Prevent use after free + +From: Eddie James + +[ Upstream commit d3e1e24604031b0d83b6c2d38f54eeea265cfcc0 ] + +Use get_device and put_device in the open and close functions to +make sure the device doesn't get freed while a file descriptor is +open. +Also, lock around the freeing of the device buffer and check the +buffer before using it in the submit function. + +Signed-off-by: Eddie James +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220513194424.53468-1-eajames@linux.ibm.com +Signed-off-by: Joel Stanley +Signed-off-by: Sasha Levin +--- + drivers/fsi/fsi-occ.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c +index c9cc75fbdfb9..28c176d038a2 100644 +--- a/drivers/fsi/fsi-occ.c ++++ b/drivers/fsi/fsi-occ.c +@@ -94,6 +94,7 @@ static int occ_open(struct inode *inode, struct file *file) + client->occ = occ; + mutex_init(&client->lock); + file->private_data = client; ++ get_device(occ->dev); + + /* We allocate a 1-page buffer, make sure it all fits */ + BUILD_BUG_ON((OCC_CMD_DATA_BYTES + 3) > PAGE_SIZE); +@@ -197,6 +198,7 @@ static int occ_release(struct inode *inode, struct file *file) + { + struct occ_client *client = file->private_data; + ++ put_device(client->occ->dev); + free_page((unsigned long)client->buffer); + kfree(client); + +@@ -493,12 +495,19 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, + for (i = 1; i < req_len - 2; ++i) + checksum += byte_request[i]; + +- mutex_lock(&occ->occ_lock); ++ rc = mutex_lock_interruptible(&occ->occ_lock); ++ if (rc) ++ return rc; + + occ->client_buffer = response; + occ->client_buffer_size = user_resp_len; + occ->client_response_size = 0; + ++ if (!occ->buffer) { ++ rc = -ENOENT; ++ goto done; ++ } ++ + /* + * Get a sequence number and update the counter. Avoid a sequence + * number of 0 which would pass the response check below even if the +@@ -671,10 +680,13 @@ static int occ_remove(struct platform_device *pdev) + { + struct occ *occ = platform_get_drvdata(pdev); + +- kvfree(occ->buffer); +- + misc_deregister(&occ->mdev); + ++ mutex_lock(&occ->occ_lock); ++ kvfree(occ->buffer); ++ occ->buffer = NULL; ++ mutex_unlock(&occ->occ_lock); ++ + device_for_each_child(&pdev->dev, NULL, occ_unregister_child); + + ida_simple_remove(&occ_ida, occ->idx); +-- +2.35.1 + diff --git a/queue-5.19/gpu-lontium-lt9611-fix-null-pointer-dereference-in-l.patch b/queue-5.19/gpu-lontium-lt9611-fix-null-pointer-dereference-in-l.patch new file mode 100644 index 00000000000..661e9be0025 --- /dev/null +++ b/queue-5.19/gpu-lontium-lt9611-fix-null-pointer-dereference-in-l.patch @@ -0,0 +1,48 @@ +From 09ef58f74329eaa3b2e3ae464851445f8861a7dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 15:31:19 +0800 +Subject: gpu: lontium-lt9611: Fix NULL pointer dereference in + lt9611_connector_init() + +From: Zeng Jingxiang + +[ Upstream commit ef8886f321c5dab8124b9153d25afa2a71d05323 ] + +A NULL check for bridge->encoder shows that it may be NULL, but it +already been dereferenced on all paths leading to the check. +812 if (!bridge->encoder) { + +Dereference the pointer bridge->encoder. +810 drm_connector_attach_encoder(<9611->connector, bridge->encoder); + +Signed-off-by: Zeng Jingxiang +Signed-off-by: Robert Foss +Link: https://patchwork.freedesktop.org/patch/msgid/20220727073119.1578972-1-zengjx95@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/lontium-lt9611.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c +index c0b182d1374e..7f688ebd36eb 100644 +--- a/drivers/gpu/drm/bridge/lontium-lt9611.c ++++ b/drivers/gpu/drm/bridge/lontium-lt9611.c +@@ -807,13 +807,14 @@ static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt961 + + drm_connector_helper_add(<9611->connector, + <9611_bridge_connector_helper_funcs); +- drm_connector_attach_encoder(<9611->connector, bridge->encoder); + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + ++ drm_connector_attach_encoder(<9611->connector, bridge->encoder); ++ + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/habanalabs-ignore-eeprom-errors-during-boot.patch b/queue-5.19/habanalabs-ignore-eeprom-errors-during-boot.patch new file mode 100644 index 00000000000..fa4d6555f03 --- /dev/null +++ b/queue-5.19/habanalabs-ignore-eeprom-errors-during-boot.patch @@ -0,0 +1,74 @@ +From d03b18f15be259ab18212e2b9659cdfffd316de5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 16:23:56 +0300 +Subject: habanalabs: ignore EEPROM errors during boot + +From: Ofir Bitton + +[ Upstream commit d155df4f628a5312a485235aa8cc5ba78e11ea65 ] + +EEPROM errors reported by firmware are basically warnings and +should not fail the boot process. + +Signed-off-by: Ofir Bitton +Reviewed-by: Oded Gabbay +Signed-off-by: Oded Gabbay +Signed-off-by: Sasha Levin +--- + drivers/misc/habanalabs/common/firmware_if.c | 9 +++++++++ + drivers/misc/habanalabs/include/common/hl_boot_if.h | 5 +++++ + 2 files changed, 14 insertions(+) + +diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c +index 828a36af5b14..bb1b2d6213a5 100644 +--- a/drivers/misc/habanalabs/common/firmware_if.c ++++ b/drivers/misc/habanalabs/common/firmware_if.c +@@ -521,6 +521,15 @@ static bool fw_report_boot_dev0(struct hl_device *hdev, u32 err_val, + dev_dbg(hdev->dev, "Device status0 %#x\n", sts_val); + + /* All warnings should go here in order not to reach the unknown error validation */ ++ if (err_val & CPU_BOOT_ERR0_EEPROM_FAIL) { ++ dev_warn(hdev->dev, ++ "Device boot warning - EEPROM failure detected, default settings applied\n"); ++ /* This is a warning so we don't want it to disable the ++ * device ++ */ ++ err_val &= ~CPU_BOOT_ERR0_EEPROM_FAIL; ++ } ++ + if (err_val & CPU_BOOT_ERR0_DRAM_SKIPPED) { + dev_warn(hdev->dev, + "Device boot warning - Skipped DRAM initialization\n"); +diff --git a/drivers/misc/habanalabs/include/common/hl_boot_if.h b/drivers/misc/habanalabs/include/common/hl_boot_if.h +index 15f91ae9de6e..d4858e636fa9 100644 +--- a/drivers/misc/habanalabs/include/common/hl_boot_if.h ++++ b/drivers/misc/habanalabs/include/common/hl_boot_if.h +@@ -34,6 +34,7 @@ enum cpu_boot_err { + CPU_BOOT_ERR_BINNING_FAIL = 19, + CPU_BOOT_ERR_TPM_FAIL = 20, + CPU_BOOT_ERR_TMP_THRESH_INIT_FAIL = 21, ++ CPU_BOOT_ERR_EEPROM_FAIL = 22, + CPU_BOOT_ERR_ENABLED = 31, + CPU_BOOT_ERR_SCND_EN = 63, + CPU_BOOT_ERR_LAST = 64 /* we have 2 registers of 32 bits */ +@@ -115,6 +116,9 @@ enum cpu_boot_err { + * CPU_BOOT_ERR0_TMP_THRESH_INIT_FAIL Failed to set threshold for tmperature + * sensor. + * ++ * CPU_BOOT_ERR_EEPROM_FAIL Failed reading EEPROM data. Defaults ++ * are used. ++ * + * CPU_BOOT_ERR0_ENABLED Error registers enabled. + * This is a main indication that the + * running FW populates the error +@@ -139,6 +143,7 @@ enum cpu_boot_err { + #define CPU_BOOT_ERR0_BINNING_FAIL (1 << CPU_BOOT_ERR_BINNING_FAIL) + #define CPU_BOOT_ERR0_TPM_FAIL (1 << CPU_BOOT_ERR_TPM_FAIL) + #define CPU_BOOT_ERR0_TMP_THRESH_INIT_FAIL (1 << CPU_BOOT_ERR_TMP_THRESH_INIT_FAIL) ++#define CPU_BOOT_ERR0_EEPROM_FAIL (1 << CPU_BOOT_ERR_EEPROM_FAIL) + #define CPU_BOOT_ERR0_ENABLED (1 << CPU_BOOT_ERR_ENABLED) + #define CPU_BOOT_ERR1_ENABLED (1 << CPU_BOOT_ERR_ENABLED) + +-- +2.35.1 + diff --git a/queue-5.19/habanalabs-remove-some-f-w-descriptor-validations.patch b/queue-5.19/habanalabs-remove-some-f-w-descriptor-validations.patch new file mode 100644 index 00000000000..a1885a36b05 --- /dev/null +++ b/queue-5.19/habanalabs-remove-some-f-w-descriptor-validations.patch @@ -0,0 +1,108 @@ +From eaffb37f1c6afab5fbab2aae632df719a3ea83ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 13:01:03 +0300 +Subject: habanalabs: remove some f/w descriptor validations + +From: farah kassabri + +[ Upstream commit 6b9b9e244fdd0d6c5ee21b7b9d74282d9e43733a ] + +To be forward-backward compatible with the firmware in the initial +communication during preboot, we need to remove the validation of the +header size. This will allow us to add more fields to the +lkd_fw_comms_desc structure. + +Instead of the validation of the header size, we just print warning +when some mismatch in descriptor has been revealed, and we calculate +the CRC base on descriptor size reported by the firmware instead of +calculating it ourselves. + +Signed-off-by: farah kassabri +Reviewed-by: Oded Gabbay +Signed-off-by: Oded Gabbay +Signed-off-by: Sasha Levin +--- + drivers/misc/habanalabs/common/firmware_if.c | 43 +++++++------------- + 1 file changed, 14 insertions(+), 29 deletions(-) + +diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c +index bb1b2d6213a5..1758b7187fb4 100644 +--- a/drivers/misc/habanalabs/common/firmware_if.c ++++ b/drivers/misc/habanalabs/common/firmware_if.c +@@ -1799,50 +1799,36 @@ static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, + u64 addr; + int rc; + +- if (le32_to_cpu(fw_desc->header.magic) != HL_COMMS_DESC_MAGIC) { +- dev_err(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", ++ if (le32_to_cpu(fw_desc->header.magic) != HL_COMMS_DESC_MAGIC) ++ dev_warn(hdev->dev, "Invalid magic for dynamic FW descriptor (%x)\n", + fw_desc->header.magic); +- return -EIO; +- } + +- if (fw_desc->header.version != HL_COMMS_DESC_VER) { +- dev_err(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", ++ if (fw_desc->header.version != HL_COMMS_DESC_VER) ++ dev_warn(hdev->dev, "Invalid version for dynamic FW descriptor (%x)\n", + fw_desc->header.version); +- return -EIO; +- } + + /* +- * calc CRC32 of data without header. ++ * Calc CRC32 of data without header. use the size of the descriptor ++ * reported by firmware, without calculating it ourself, to allow adding ++ * more fields to the lkd_fw_comms_desc structure. + * note that no alignment/stride address issues here as all structures +- * are 64 bit padded ++ * are 64 bit padded. + */ +- data_size = sizeof(struct lkd_fw_comms_desc) - +- sizeof(struct comms_desc_header); + data_ptr = (u8 *)fw_desc + sizeof(struct comms_desc_header); +- +- if (le16_to_cpu(fw_desc->header.size) != data_size) { +- dev_err(hdev->dev, +- "Invalid descriptor size 0x%x, expected size 0x%zx\n", +- le16_to_cpu(fw_desc->header.size), data_size); +- return -EIO; +- } ++ data_size = le16_to_cpu(fw_desc->header.size); + + data_crc32 = hl_fw_compat_crc32(data_ptr, data_size); +- + if (data_crc32 != le32_to_cpu(fw_desc->header.crc32)) { +- dev_err(hdev->dev, +- "CRC32 mismatch for dynamic FW descriptor (%x:%x)\n", +- data_crc32, fw_desc->header.crc32); ++ dev_err(hdev->dev, "CRC32 mismatch for dynamic FW descriptor (%x:%x)\n", ++ data_crc32, fw_desc->header.crc32); + return -EIO; + } + + /* find memory region to which to copy the image */ + addr = le64_to_cpu(fw_desc->img_addr); + region_id = hl_get_pci_memory_region(hdev, addr); +- if ((region_id != PCI_REGION_SRAM) && +- ((region_id != PCI_REGION_DRAM))) { +- dev_err(hdev->dev, +- "Invalid region to copy FW image address=%llx\n", addr); ++ if ((region_id != PCI_REGION_SRAM) && ((region_id != PCI_REGION_DRAM))) { ++ dev_err(hdev->dev, "Invalid region to copy FW image address=%llx\n", addr); + return -EIO; + } + +@@ -1859,8 +1845,7 @@ static int hl_fw_dynamic_validate_descriptor(struct hl_device *hdev, + fw_loader->dynamic_loader.fw_image_size, + region); + if (rc) { +- dev_err(hdev->dev, +- "invalid mem transfer request for FW image\n"); ++ dev_err(hdev->dev, "invalid mem transfer request for FW image\n"); + return rc; + } + +-- +2.35.1 + diff --git a/queue-5.19/hid-nintendo-check-analog-user-calibration-for-plaus.patch b/queue-5.19/hid-nintendo-check-analog-user-calibration-for-plaus.patch new file mode 100644 index 00000000000..5287a0185a3 --- /dev/null +++ b/queue-5.19/hid-nintendo-check-analog-user-calibration-for-plaus.patch @@ -0,0 +1,127 @@ +From 308263c076ad96fafc99e91c73264110c819c75d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 10:55:57 +0000 +Subject: HID: nintendo: check analog user calibration for plausibility + +From: Johnothan King + +[ Upstream commit 50503e360eeb968a3d00234c9cc4057d774c3e9a ] + +Arne Wendt writes: + Cheap clone controllers may (falsely) report as having a user + calibration for the analog sticks in place, but return + wrong/impossible values for the actual calibration data. + In the present case at mine, the controller reports having a + user calibration in place and successfully executes the read + commands. The reported user calibration however is + min = center = max = 0. + + This pull request addresses problems of this kind by checking the + provided user calibration-data for plausibility (min < center < max) + and falling back to the default values if implausible. + +I'll note that I was experiencing a crash because of this bug when using +the GuliKit KingKong 2 controller. The crash manifests as a divide by +zero error in the kernel logs: +kernel: divide error: 0000 [#1] PREEMPT SMP NOPTI + +Link: https://github.com/nicman23/dkms-hid-nintendo/pull/25 +Link: https://github.com/DanielOgorchock/linux/issues/36 +Co-authored-by: Arne Wendt +Signed-off-by: Johnothan King +Signed-off-by: Benjamin Tissoires +Link: https://lore.kernel.org/r/gvpL2G6VwXGJPvxX5KRiu9pVjvTivgayug_jdKDY6zfuAaAqncP9BkKLosjwUXNlgVVTMfJSKfwPF1K79cKAkwGComyC21vCV3q9B3EXNkE=@protonmail.com +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-nintendo.c | 55 +++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 25 deletions(-) + +diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c +index f33a03c96ba6..cce324887952 100644 +--- a/drivers/hid/hid-nintendo.c ++++ b/drivers/hid/hid-nintendo.c +@@ -761,12 +761,31 @@ static int joycon_read_stick_calibration(struct joycon_ctlr *ctlr, u16 cal_addr, + cal_y->max = cal_y->center + y_max_above; + cal_y->min = cal_y->center - y_min_below; + +- return 0; ++ /* check if calibration values are plausible */ ++ if (cal_x->min >= cal_x->center || cal_x->center >= cal_x->max || ++ cal_y->min >= cal_y->center || cal_y->center >= cal_y->max) ++ ret = -EINVAL; ++ ++ return ret; + } + + static const u16 DFLT_STICK_CAL_CEN = 2000; + static const u16 DFLT_STICK_CAL_MAX = 3500; + static const u16 DFLT_STICK_CAL_MIN = 500; ++static void joycon_use_default_calibration(struct hid_device *hdev, ++ struct joycon_stick_cal *cal_x, ++ struct joycon_stick_cal *cal_y, ++ const char *stick, int ret) ++{ ++ hid_warn(hdev, ++ "Failed to read %s stick cal, using defaults; e=%d\n", ++ stick, ret); ++ ++ cal_x->center = cal_y->center = DFLT_STICK_CAL_CEN; ++ cal_x->max = cal_y->max = DFLT_STICK_CAL_MAX; ++ cal_x->min = cal_y->min = DFLT_STICK_CAL_MIN; ++} ++ + static int joycon_request_calibration(struct joycon_ctlr *ctlr) + { + u16 left_stick_addr = JC_CAL_FCT_DATA_LEFT_ADDR; +@@ -794,38 +813,24 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr) + &ctlr->left_stick_cal_x, + &ctlr->left_stick_cal_y, + true); +- if (ret) { +- hid_warn(ctlr->hdev, +- "Failed to read left stick cal, using dflts; e=%d\n", +- ret); +- +- ctlr->left_stick_cal_x.center = DFLT_STICK_CAL_CEN; +- ctlr->left_stick_cal_x.max = DFLT_STICK_CAL_MAX; +- ctlr->left_stick_cal_x.min = DFLT_STICK_CAL_MIN; + +- ctlr->left_stick_cal_y.center = DFLT_STICK_CAL_CEN; +- ctlr->left_stick_cal_y.max = DFLT_STICK_CAL_MAX; +- ctlr->left_stick_cal_y.min = DFLT_STICK_CAL_MIN; +- } ++ if (ret) ++ joycon_use_default_calibration(ctlr->hdev, ++ &ctlr->left_stick_cal_x, ++ &ctlr->left_stick_cal_y, ++ "left", ret); + + /* read the right stick calibration data */ + ret = joycon_read_stick_calibration(ctlr, right_stick_addr, + &ctlr->right_stick_cal_x, + &ctlr->right_stick_cal_y, + false); +- if (ret) { +- hid_warn(ctlr->hdev, +- "Failed to read right stick cal, using dflts; e=%d\n", +- ret); +- +- ctlr->right_stick_cal_x.center = DFLT_STICK_CAL_CEN; +- ctlr->right_stick_cal_x.max = DFLT_STICK_CAL_MAX; +- ctlr->right_stick_cal_x.min = DFLT_STICK_CAL_MIN; + +- ctlr->right_stick_cal_y.center = DFLT_STICK_CAL_CEN; +- ctlr->right_stick_cal_y.max = DFLT_STICK_CAL_MAX; +- ctlr->right_stick_cal_y.min = DFLT_STICK_CAL_MIN; +- } ++ if (ret) ++ joycon_use_default_calibration(ctlr->hdev, ++ &ctlr->right_stick_cal_x, ++ &ctlr->right_stick_cal_y, ++ "right", ret); + + hid_dbg(ctlr->hdev, "calibration:\n" + "l_x_c=%d l_x_max=%d l_x_min=%d\n" +-- +2.35.1 + diff --git a/queue-5.19/hid-roccat-fix-use-after-free-in-roccat_read.patch b/queue-5.19/hid-roccat-fix-use-after-free-in-roccat_read.patch new file mode 100644 index 00000000000..e78a851506d --- /dev/null +++ b/queue-5.19/hid-roccat-fix-use-after-free-in-roccat_read.patch @@ -0,0 +1,108 @@ +From 368b4e3f9f29dee8d6124e101975bd2265824c1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 12:31:15 -0700 +Subject: HID: roccat: Fix use-after-free in roccat_read() + +From: Hyunwoo Kim + +[ Upstream commit cacdb14b1c8d3804a3a7d31773bc7569837b71a4 ] + +roccat_report_event() is responsible for registering +roccat-related reports in struct roccat_device. + +int roccat_report_event(int minor, u8 const *data) +{ + struct roccat_device *device; + struct roccat_reader *reader; + struct roccat_report *report; + uint8_t *new_value; + + device = devices[minor]; + + new_value = kmemdup(data, device->report_size, GFP_ATOMIC); + if (!new_value) + return -ENOMEM; + + report = &device->cbuf[device->cbuf_end]; + + /* passing NULL is safe */ + kfree(report->value); + ... + +The registered report is stored in the struct roccat_device member +"struct roccat_report cbuf[ROCCAT_CBUF_SIZE];". +If more reports are received than the "ROCCAT_CBUF_SIZE" value, +kfree() the saved report from cbuf[0] and allocates a new reprot. +Since there is no lock when this kfree() is performed, +kfree() can be performed even while reading the saved report. + +static ssize_t roccat_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct roccat_reader *reader = file->private_data; + struct roccat_device *device = reader->device; + struct roccat_report *report; + ssize_t retval = 0, len; + DECLARE_WAITQUEUE(wait, current); + + mutex_lock(&device->cbuf_lock); + + ... + + report = &device->cbuf[reader->cbuf_start]; + /* + * If report is larger than requested amount of data, rest of report + * is lost! + */ + len = device->report_size > count ? count : device->report_size; + + if (copy_to_user(buffer, report->value, len)) { + retval = -EFAULT; + goto exit_unlock; + } + ... + +The roccat_read() function receives the device->cbuf report and +delivers it to the user through copy_to_user(). +If the N+ROCCAT_CBUF_SIZE th report is received while copying of +the Nth report->value is in progress, the pointer that copy_to_user() +is working on is kfree()ed and UAF read may occur. (race condition) + +Since the device node of this driver does not set separate permissions, +this is not a security vulnerability, but because it is used for +requesting screen display of profile or dpi settings, +a user using the roccat device can apply udev to this device node or +There is a possibility to use it by giving. + +Signed-off-by: Hyunwoo Kim +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-roccat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c +index 26373b82fe81..6da80e442fdd 100644 +--- a/drivers/hid/hid-roccat.c ++++ b/drivers/hid/hid-roccat.c +@@ -257,6 +257,8 @@ int roccat_report_event(int minor, u8 const *data) + if (!new_value) + return -ENOMEM; + ++ mutex_lock(&device->cbuf_lock); ++ + report = &device->cbuf[device->cbuf_end]; + + /* passing NULL is safe */ +@@ -276,6 +278,8 @@ int roccat_report_event(int minor, u8 const *data) + reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; + } + ++ mutex_unlock(&device->cbuf_lock); ++ + wake_up_interruptible(&device->wait); + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/hid-topre-add-driver-fixing-report-descriptor.patch b/queue-5.19/hid-topre-add-driver-fixing-report-descriptor.patch new file mode 100644 index 00000000000..ea7911b5786 --- /dev/null +++ b/queue-5.19/hid-topre-add-driver-fixing-report-descriptor.patch @@ -0,0 +1,139 @@ +From 7d19228b866f40098942fd1a466702f2282eb74d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Sep 2022 20:36:13 -0400 +Subject: hid: topre: Add driver fixing report descriptor + +From: Harry Stern + +[ Upstream commit a109d5c45b3d6728b9430716b915afbe16eef27c ] + +The Topre REALFORCE R2 firmware incorrectly reports that interface +descriptor number 1, input report descriptor 2's events are array events +rather than variable events. That particular report descriptor is used +to report keypresses when there are more than 6 keys held at a time. +This bug prevents events from this interface from being registered +properly, so only 6 keypresses (from a different interface) can be +registered at once, rather than full n-key rollover. + +This commit fixes the bug by setting the correct value in a report_fixup +function. + +The original bug report can be found here: +Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/804 + +Thanks to Benjamin Tissoires for diagnosing the issue with the report +descriptor. + +Signed-off-by: Harry Stern +Signed-off-by: Benjamin Tissoires +Link: https://lore.kernel.org/r/20220911003614.297613-1-harry@harrystern.net +Signed-off-by: Sasha Levin +--- + drivers/hid/Kconfig | 6 +++++ + drivers/hid/Makefile | 1 + + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/hid-topre.c | 49 +++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 59 insertions(+) + create mode 100644 drivers/hid/hid-topre.c + +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 70da5931082f..37734fce88e4 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -1141,6 +1141,12 @@ config HID_TOPSEED + Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic + CLLRCMCE remote control. + ++config HID_TOPRE ++ tristate "Topre REALFORCE keyboards" ++ depends on HID ++ help ++ Say Y for N-key rollover support on Topre REALFORCE R2 108 key keyboards. ++ + config HID_THINGM + tristate "ThingM blink(1) USB RGB LED" + depends on HID +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index cac2cbe26d11..7870a3c9d802 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -123,6 +123,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o + obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o + obj-$(CONFIG_HID_TIVO) += hid-tivo.o + obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o ++obj-$(CONFIG_HID_TOPRE) += hid-topre.o + obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o + obj-$(CONFIG_HID_U2FZERO) += hid-u2fzero.o + hid-uclogic-objs := hid-uclogic-core.o \ +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index bc550e884f37..28cf838c8399 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -1231,6 +1231,9 @@ + #define USB_DEVICE_ID_TIVO_SLIDE 0x1201 + #define USB_DEVICE_ID_TIVO_SLIDE_PRO 0x1203 + ++#define USB_VENDOR_ID_TOPRE 0x0853 ++#define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148 ++ + #define USB_VENDOR_ID_TOPSEED 0x0766 + #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 + +diff --git a/drivers/hid/hid-topre.c b/drivers/hid/hid-topre.c +new file mode 100644 +index 000000000000..88a91cdad5f8 +--- /dev/null ++++ b/drivers/hid/hid-topre.c +@@ -0,0 +1,49 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * HID driver for Topre REALFORCE Keyboards ++ * ++ * Copyright (c) 2022 Harry Stern ++ * ++ * Based on the hid-macally driver ++ */ ++ ++#include ++#include ++ ++#include "hid-ids.h" ++ ++MODULE_AUTHOR("Harry Stern "); ++MODULE_DESCRIPTION("REALFORCE R2 Keyboard driver"); ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Fix the REALFORCE R2's non-boot interface's report descriptor to match the ++ * events it's actually sending. It claims to send array events but is instead ++ * sending variable events. ++ */ ++static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 && ++ rdesc[71] == 0x81 && rdesc[72] == 0x00) { ++ hid_info(hdev, ++ "fixing up Topre REALFORCE keyboard report descriptor\n"); ++ rdesc[72] = 0x02; ++ } ++ return rdesc; ++} ++ ++static const struct hid_device_id topre_id_table[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, ++ USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, topre_id_table); ++ ++static struct hid_driver topre_driver = { ++ .name = "topre", ++ .id_table = topre_id_table, ++ .report_fixup = topre_report_fixup, ++}; ++ ++module_hid_driver(topre_driver); +-- +2.35.1 + diff --git a/queue-5.19/hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch b/queue-5.19/hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch new file mode 100644 index 00000000000..dc4da14146b --- /dev/null +++ b/queue-5.19/hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch @@ -0,0 +1,44 @@ +From 0734d00e6249659bfdc657de1e5b4b4d2d29a95a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 16:27:06 +0200 +Subject: HID: uclogic: Fix warning in uclogic_rdesc_template_apply +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit 609174edeb758d1e2d713e7ab4e09ea8d45aa4f7 ] + +Building with Sparse enabled prints this warning: + + warning: incorrect type in assignment (different base types) + expected signed int x + got restricted __le32 [usertype] + +Cast the return value of cpu_to_le32() to fix the warning. + +Fixes: 08177f4 ("HID: uclogic: merge hid-huion driver in hid-uclogic") +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-uclogic-rdesc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c +index 7126fba80968..b6aeff442982 100644 +--- a/drivers/hid/hid-uclogic-rdesc.c ++++ b/drivers/hid/hid-uclogic-rdesc.c +@@ -1009,7 +1009,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, + if (memcmp(p, pen_head, sizeof(pen_head)) == 0 && + p[sizeof(pen_head)] < param_num) { + v = param_list[p[sizeof(pen_head)]]; +- put_unaligned(cpu_to_le32(v), (s32 *)p); ++ put_unaligned((__force u32)cpu_to_le32(v), (s32 *)p); + p += sizeof(pen_head) + 1; + } else { + p++; +-- +2.35.1 + diff --git a/queue-5.19/hid-uclogic-make-template-placeholder-ids-generic.patch b/queue-5.19/hid-uclogic-make-template-placeholder-ids-generic.patch new file mode 100644 index 00000000000..34d49c6df65 --- /dev/null +++ b/queue-5.19/hid-uclogic-make-template-placeholder-ids-generic.patch @@ -0,0 +1,132 @@ +From 8b9e9150f602e98a2d4cedd7d58f7539f8139939 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jun 2022 13:39:11 +0200 +Subject: HID: uclogic: Make template placeholder IDs generic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit 76e645be7ebecbf39ab2edd949ea7f1757f58900 ] + +Up until now, the report descriptor template parameter IDs were only +used with pen report descriptors and they were named accordingly. + +Rename the enum and the total number of IDs to make them interface +agnostic. + +Refactor, no functional changes. + +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Stable-dep-of: 609174edeb75 ("HID: uclogic: Fix warning in uclogic_rdesc_template_apply") +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-uclogic-params.c | 4 ++-- + drivers/hid/hid-uclogic-rdesc.c | 14 +++++++------- + drivers/hid/hid-uclogic-rdesc.h | 10 +++++----- + 3 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c +index db838f16282d..b43142f98a8b 100644 +--- a/drivers/hid/hid-uclogic-params.c ++++ b/drivers/hid/hid-uclogic-params.c +@@ -234,7 +234,7 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, + const int len = 12; + s32 resolution; + /* Pen report descriptor template parameters */ +- s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; ++ s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + __u8 *desc_ptr = NULL; + + /* Check arguments */ +@@ -379,7 +379,7 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, + size_t i; + s32 resolution; + /* Pen report descriptor template parameters */ +- s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; ++ s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + __u8 *desc_ptr = NULL; + + /* Check arguments */ +diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c +index 13f9ce73f1b1..7126fba80968 100644 +--- a/drivers/hid/hid-uclogic-rdesc.c ++++ b/drivers/hid/hid-uclogic-rdesc.c +@@ -979,7 +979,7 @@ const size_t uclogic_rdesc_xppen_deco01_frame_size = + * uclogic_rdesc_template_apply() - apply report descriptor parameters to a + * report descriptor template, creating a report descriptor. Copies the + * template over to the new report descriptor and replaces every occurrence of +- * UCLOGIC_RDESC_PH_HEAD, followed by an index byte, with the value from the ++ * UCLOGIC_RDESC_PEN_PH_HEAD, followed by an index byte, with the value from the + * parameter list at that index. + * + * @template_ptr: Pointer to the template buffer. +@@ -996,7 +996,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, + const s32 *param_list, + size_t param_num) + { +- static const __u8 head[] = {UCLOGIC_RDESC_PH_HEAD}; ++ static const __u8 pen_head[] = {UCLOGIC_RDESC_PEN_PH_HEAD}; + __u8 *rdesc_ptr; + __u8 *p; + s32 v; +@@ -1005,12 +1005,12 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, + if (rdesc_ptr == NULL) + return NULL; + +- for (p = rdesc_ptr; p + sizeof(head) < rdesc_ptr + template_size;) { +- if (memcmp(p, head, sizeof(head)) == 0 && +- p[sizeof(head)] < param_num) { +- v = param_list[p[sizeof(head)]]; ++ for (p = rdesc_ptr; p + sizeof(pen_head) < rdesc_ptr + template_size;) { ++ if (memcmp(p, pen_head, sizeof(pen_head)) == 0 && ++ p[sizeof(pen_head)] < param_num) { ++ v = param_list[p[sizeof(pen_head)]]; + put_unaligned(cpu_to_le32(v), (s32 *)p); +- p += sizeof(head) + 1; ++ p += sizeof(pen_head) + 1; + } else { + p++; + } +diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h +index 0c6e95e8bde7..9d37090c39d1 100644 +--- a/drivers/hid/hid-uclogic-rdesc.h ++++ b/drivers/hid/hid-uclogic-rdesc.h +@@ -81,7 +81,7 @@ extern __u8 uclogic_rdesc_twha60_fixed1_arr[]; + extern const size_t uclogic_rdesc_twha60_fixed1_size; + + /* Report descriptor template placeholder head */ +-#define UCLOGIC_RDESC_PH_HEAD 0xFE, 0xED, 0x1D ++#define UCLOGIC_RDESC_PEN_PH_HEAD 0xFE, 0xED, 0x1D + + /* Apply report descriptor parameters to a report descriptor template */ + extern __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, +@@ -89,19 +89,19 @@ extern __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, + const s32 *param_list, + size_t param_num); + +-/* Pen report descriptor template placeholder IDs */ +-enum uclogic_rdesc_pen_ph_id { ++/* Report descriptor template placeholder IDs */ ++enum uclogic_rdesc_ph_id { + UCLOGIC_RDESC_PEN_PH_ID_X_LM, + UCLOGIC_RDESC_PEN_PH_ID_X_PM, + UCLOGIC_RDESC_PEN_PH_ID_Y_LM, + UCLOGIC_RDESC_PEN_PH_ID_Y_PM, + UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM, +- UCLOGIC_RDESC_PEN_PH_ID_NUM ++ UCLOGIC_RDESC_PH_ID_NUM + }; + + /* Report descriptor pen template placeholder */ + #define UCLOGIC_RDESC_PEN_PH(_ID) \ +- UCLOGIC_RDESC_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID ++ UCLOGIC_RDESC_PEN_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID + + /* Report ID for v1 pen reports */ + #define UCLOGIC_RDESC_V1_PEN_ID 0x07 +-- +2.35.1 + diff --git a/queue-5.19/hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch b/queue-5.19/hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch new file mode 100644 index 00000000000..9e44e1c4628 --- /dev/null +++ b/queue-5.19/hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch @@ -0,0 +1,36 @@ +From 008ee30ad4d6ade84a3d5354a2c21800f9d3cb99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Apr 2022 08:52:32 +0000 +Subject: HSI: omap_ssi: Fix refcount leak in ssi_probe + +From: Miaoqian Lin + +[ Upstream commit 9a2ea132df860177b33c9fd421b26c4e9a0a9396 ] + +When returning or breaking early from a +for_each_available_child_of_node() loop, we need to explicitly call +of_node_put() on the child node to possibly release the node. + +Fixes: b209e047bc74 ("HSI: Introduce OMAP SSI driver") +Signed-off-by: Miaoqian Lin +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/controllers/omap_ssi_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c +index 44a3f5660c10..eb9820158318 100644 +--- a/drivers/hsi/controllers/omap_ssi_core.c ++++ b/drivers/hsi/controllers/omap_ssi_core.c +@@ -524,6 +524,7 @@ static int ssi_probe(struct platform_device *pd) + if (!childpdev) { + err = -ENODEV; + dev_err(&pd->dev, "failed to create ssi controller port\n"); ++ of_node_put(child); + goto out3; + } + } +-- +2.35.1 + diff --git a/queue-5.19/hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch b/queue-5.19/hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch new file mode 100644 index 00000000000..4030ead58fa --- /dev/null +++ b/queue-5.19/hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch @@ -0,0 +1,55 @@ +From 7af17391281d1475ff6864ad492cc88ae677c7b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 12:12:27 +0200 +Subject: HSI: omap_ssi_port: Fix dma_map_sg error check + +From: Jack Wang + +[ Upstream commit 551e325bbd3fb8b5a686ac1e6cf76e5641461cf2 ] + +dma_map_sg return 0 on error, in case of error return -EIO +to caller. + +Cc: Sebastian Reichel +Cc: linux-kernel@vger.kernel.org (open list) +Fixes: b209e047bc74 ("HSI: Introduce OMAP SSI driver") +Signed-off-by: Jack Wang +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/controllers/omap_ssi_port.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c +index a0cb5be246e1..b9495b720f1b 100644 +--- a/drivers/hsi/controllers/omap_ssi_port.c ++++ b/drivers/hsi/controllers/omap_ssi_port.c +@@ -230,10 +230,10 @@ static int ssi_start_dma(struct hsi_msg *msg, int lch) + if (msg->ttype == HSI_MSG_READ) { + err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, + DMA_FROM_DEVICE); +- if (err < 0) { ++ if (!err) { + dev_dbg(&ssi->device, "DMA map SG failed !\n"); + pm_runtime_put_autosuspend(omap_port->pdev); +- return err; ++ return -EIO; + } + csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT | + SSI_SRC_SINGLE_ACCESS0 | SSI_SRC_PERIPHERAL_PORT | +@@ -247,10 +247,10 @@ static int ssi_start_dma(struct hsi_msg *msg, int lch) + } else { + err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, + DMA_TO_DEVICE); +- if (err < 0) { ++ if (!err) { + dev_dbg(&ssi->device, "DMA map SG failed !\n"); + pm_runtime_put_autosuspend(omap_port->pdev); +- return err; ++ return -EIO; + } + csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT | + SSI_DST_SINGLE_ACCESS0 | SSI_DST_PERIPHERAL_PORT | +-- +2.35.1 + diff --git a/queue-5.19/hsi-ssi_protocol-fix-potential-resource-leak-in-ssip.patch b/queue-5.19/hsi-ssi_protocol-fix-potential-resource-leak-in-ssip.patch new file mode 100644 index 00000000000..26c9d32a73e --- /dev/null +++ b/queue-5.19/hsi-ssi_protocol-fix-potential-resource-leak-in-ssip.patch @@ -0,0 +1,37 @@ +From 3f927749c5e8f100c7d1a0d5cacb05ae7e5aa2ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 15:48:01 +0800 +Subject: HSI: ssi_protocol: fix potential resource leak in ssip_pn_open() + +From: Jianglei Nie + +[ Upstream commit b28dbcb379e6a7f80262c2732a57681b1ee548ca ] + +ssip_pn_open() claims the HSI client's port with hsi_claim_port(). When +hsi_register_port_event() gets some error and returns a negetive value, +the HSI client's port should be released with hsi_release_port(). + +Fix it by calling hsi_release_port() when hsi_register_port_event() fails. + +Signed-off-by: Jianglei Nie +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/hsi/clients/ssi_protocol.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c +index 21f11a5b965b..49ffd808d17f 100644 +--- a/drivers/hsi/clients/ssi_protocol.c ++++ b/drivers/hsi/clients/ssi_protocol.c +@@ -931,6 +931,7 @@ static int ssip_pn_open(struct net_device *dev) + if (err < 0) { + dev_err(&cl->device, "Register HSI port event failed (%d)\n", + err); ++ hsi_release_port(cl); + return err; + } + dev_dbg(&cl->device, "Configuring SSI port\n"); +-- +2.35.1 + diff --git a/queue-5.19/hwmon-occ-retry-for-checksum-failure.patch b/queue-5.19/hwmon-occ-retry-for-checksum-failure.patch new file mode 100644 index 00000000000..7192e37785f --- /dev/null +++ b/queue-5.19/hwmon-occ-retry-for-checksum-failure.patch @@ -0,0 +1,68 @@ +From 91ef12a12fa4ab31bc6551b2f4ad77b2962afb50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Apr 2022 10:49:56 -0500 +Subject: hwmon (occ): Retry for checksum failure + +From: Eddie James + +[ Upstream commit dbed963ed62c4c2b8870a02c8b7dcb0c2af3ee0b ] + +Due to the OCC communication design with a shared SRAM area, +checkum errors are expected due to corrupted buffer from OCC +communications with other system components. Therefore, retry +the command twice in the event of a checksum failure. + +Signed-off-by: Eddie James +Acked-by: Guenter Roeck +Link: https://lore.kernel.org/r/20220426154956.27205-3-eajames@linux.ibm.com +Signed-off-by: Joel Stanley +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/p9_sbe.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c +index a91937e28e12..775147f31cb1 100644 +--- a/drivers/hwmon/occ/p9_sbe.c ++++ b/drivers/hwmon/occ/p9_sbe.c +@@ -14,6 +14,8 @@ + + #include "common.h" + ++#define OCC_CHECKSUM_RETRIES 3 ++ + struct p9_sbe_occ { + struct occ occ; + bool sbe_error; +@@ -81,18 +83,23 @@ static bool p9_sbe_occ_save_ffdc(struct p9_sbe_occ *ctx, const void *resp, + static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd, size_t len, + void *resp, size_t resp_len) + { ++ size_t original_resp_len = resp_len; + struct p9_sbe_occ *ctx = to_p9_sbe_occ(occ); +- int rc; ++ int rc, i; + +- rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len); +- if (rc < 0) { ++ for (i = 0; i < OCC_CHECKSUM_RETRIES; ++i) { ++ rc = fsi_occ_submit(ctx->sbe, cmd, len, resp, &resp_len); ++ if (rc >= 0) ++ break; + if (resp_len) { + if (p9_sbe_occ_save_ffdc(ctx, resp, resp_len)) + sysfs_notify(&occ->bus_dev->kobj, NULL, + bin_attr_ffdc.attr.name); ++ return rc; + } +- +- return rc; ++ if (rc != -EBADE) ++ return rc; ++ resp_len = original_resp_len; + } + + switch (((struct occ_response *)resp)->return_status) { +-- +2.35.1 + diff --git a/queue-5.19/hwmon-pmbus-mp2888-fix-sensors-readouts-for-mps-mult.patch b/queue-5.19/hwmon-pmbus-mp2888-fix-sensors-readouts-for-mps-mult.patch new file mode 100644 index 00000000000..83f8cf499b6 --- /dev/null +++ b/queue-5.19/hwmon-pmbus-mp2888-fix-sensors-readouts-for-mps-mult.patch @@ -0,0 +1,81 @@ +From f6db584ce2769975c2cfa8121f658e261f50a160 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 15:16:42 +0300 +Subject: hwmon: (pmbus/mp2888) Fix sensors readouts for MPS Multi-phase mp2888 + controller + +From: Oleksandr Shamray + +[ Upstream commit 525dd5aed67a2f4f7278116fb92a24e6a53e2622 ] + +Fix scale factors for reading MPS Multi-phase mp2888 controller. +Fixed sensors: + - PIN/POUT: based on vendor documentation, set bscale factor 0.5W/LSB + - IOUT: based on vendor documentation, set scale factor 0.25 A/LSB + +Fixes: e4db7719d037 ("hwmon: (pmbus) Add support for MPS Multi-phase mp2888 controller") +Signed-off-by: Oleksandr Shamray +Reviewed-by: Vadim Pasternak +Link: https://lore.kernel.org/r/20220929121642.63051-1-oleksandrs@nvidia.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/pmbus/mp2888.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c +index 8ecd4adfef40..24e5194706cf 100644 +--- a/drivers/hwmon/pmbus/mp2888.c ++++ b/drivers/hwmon/pmbus/mp2888.c +@@ -34,7 +34,7 @@ struct mp2888_data { + int curr_sense_gain; + }; + +-#define to_mp2888_data(x) container_of(x, struct mp2888_data, info) ++#define to_mp2888_data(x) container_of(x, struct mp2888_data, info) + + static int mp2888_read_byte_data(struct i2c_client *client, int page, int reg) + { +@@ -109,7 +109,7 @@ mp2888_read_phase(struct i2c_client *client, struct mp2888_data *data, int page, + * - Kcs is the DrMOS current sense gain of power stage, which is obtained from the + * register MP2888_MFR_VR_CONFIG1, bits 13-12 with the following selection of DrMOS + * (data->curr_sense_gain): +- * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. ++ * 00b - 8.5µA/A, 01b - 9.7µA/A, 1b - 10µA/A, 11b - 5µA/A. + * - Rcs is the internal phase current sense resistor. This parameter depends on hardware + * assembly. By default it is set to 1kΩ. In case of different assembly, user should + * scale this parameter by dividing it by Rcs. +@@ -118,10 +118,9 @@ mp2888_read_phase(struct i2c_client *client, struct mp2888_data *data, int page, + * because sampling of current occurrence of bit weight has a big deviation, especially for + * light load. + */ +- ret = DIV_ROUND_CLOSEST(ret * 100 - 9800, data->curr_sense_gain); +- ret = (data->phase_curr_resolution) ? ret * 2 : ret; ++ ret = DIV_ROUND_CLOSEST(ret * 200 - 19600, data->curr_sense_gain); + /* Scale according to total current resolution. */ +- ret = (data->total_curr_resolution) ? ret * 8 : ret * 4; ++ ret = (data->total_curr_resolution) ? ret * 2 : ret; + return ret; + } + +@@ -212,7 +211,7 @@ static int mp2888_read_word_data(struct i2c_client *client, int page, int phase, + ret = pmbus_read_word_data(client, page, phase, reg); + if (ret < 0) + return ret; +- ret = data->total_curr_resolution ? ret * 2 : ret; ++ ret = data->total_curr_resolution ? ret : DIV_ROUND_CLOSEST(ret, 2); + break; + case PMBUS_POUT_OP_WARN_LIMIT: + ret = pmbus_read_word_data(client, page, phase, reg); +@@ -223,7 +222,7 @@ static int mp2888_read_word_data(struct i2c_client *client, int page, int phase, + * set 1. Actual power is reported with 0.5W or 1W respectively resolution. Scaling + * is needed to match both. + */ +- ret = data->total_curr_resolution ? ret * 4 : ret * 2; ++ ret = data->total_curr_resolution ? ret * 2 : ret; + break; + /* + * The below registers are not implemented by device or implemented not according to the +-- +2.35.1 + diff --git a/queue-5.19/hwmon-sht4x-do-not-overflow-clamping-operation-on-32.patch b/queue-5.19/hwmon-sht4x-do-not-overflow-clamping-operation-on-32.patch new file mode 100644 index 00000000000..0c96d04f943 --- /dev/null +++ b/queue-5.19/hwmon-sht4x-do-not-overflow-clamping-operation-on-32.patch @@ -0,0 +1,38 @@ +From d0781c07cd0e18786837a18f700509b19ceea3ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 12:11:51 +0200 +Subject: hwmon: (sht4x) do not overflow clamping operation on 32-bit platforms + +From: Jason A. Donenfeld + +[ Upstream commit f9c0cf8f26de367c58e48b02b1cdb9c377626e6f ] + +On 32-bit platforms, long is 32 bits, so (long)UINT_MAX is less than +(long)SHT4X_MIN_POLL_INTERVAL, which means the clamping operation is +bogus. Fix this by clamping at INT_MAX, so that the upperbound is the +same on all platforms. + +Signed-off-by: Jason A. Donenfeld +Link: https://lore.kernel.org/r/20220924101151.4168414-1-Jason@zx2c4.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/sht4x.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c +index c19df3ade48e..13ac2d8f22c7 100644 +--- a/drivers/hwmon/sht4x.c ++++ b/drivers/hwmon/sht4x.c +@@ -129,7 +129,7 @@ static int sht4x_read_values(struct sht4x_data *data) + + static ssize_t sht4x_interval_write(struct sht4x_data *data, long val) + { +- data->update_interval = clamp_val(val, SHT4X_MIN_POLL_INTERVAL, UINT_MAX); ++ data->update_interval = clamp_val(val, SHT4X_MIN_POLL_INTERVAL, INT_MAX); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/hwrng-arm-smccc-trng-fix-no_entropy-handling.patch b/queue-5.19/hwrng-arm-smccc-trng-fix-no_entropy-handling.patch new file mode 100644 index 00000000000..45678874495 --- /dev/null +++ b/queue-5.19/hwrng-arm-smccc-trng-fix-no_entropy-handling.patch @@ -0,0 +1,48 @@ +From ebb79ee0c1ca5feb3c37a0ea872b3c8af87d374a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 20:04:18 +0000 +Subject: hwrng: arm-smccc-trng - fix NO_ENTROPY handling + +From: James Cowgill + +[ Upstream commit 042b4b169c6fb9d4df268d66282d7302dd73d37b ] + +The SMCCC_RET_TRNG_NO_ENTROPY switch arm is never used because the +NO_ENTROPY return value is negative and negative values are handled +above the switch by immediately returning. + +Fix by handling errors using a default arm in the switch. + +Fixes: 0888d04b47a1 ("hwrng: Add Arm SMCCC TRNG based driver") +Signed-off-by: James Cowgill +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/char/hw_random/arm_smccc_trng.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/hw_random/arm_smccc_trng.c b/drivers/char/hw_random/arm_smccc_trng.c +index b24ac39a903b..e34c3ea692b6 100644 +--- a/drivers/char/hw_random/arm_smccc_trng.c ++++ b/drivers/char/hw_random/arm_smccc_trng.c +@@ -71,8 +71,6 @@ static int smccc_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) + MAX_BITS_PER_CALL); + + arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND, bits, &res); +- if ((int)res.a0 < 0) +- return (int)res.a0; + + switch ((int)res.a0) { + case SMCCC_RET_SUCCESS: +@@ -88,6 +86,8 @@ static int smccc_trng_read(struct hwrng *rng, void *data, size_t max, bool wait) + return copied; + cond_resched(); + break; ++ default: ++ return -EIO; + } + } + +-- +2.35.1 + diff --git a/queue-5.19/hwrng-imx-rngc-moving-irq-handler-registering-after-.patch b/queue-5.19/hwrng-imx-rngc-moving-irq-handler-registering-after-.patch new file mode 100644 index 00000000000..393976c0707 --- /dev/null +++ b/queue-5.19/hwrng-imx-rngc-moving-irq-handler-registering-after-.patch @@ -0,0 +1,61 @@ +From 497a943c0074d715ec932e914a778c451fdd30fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 13:19:03 +0200 +Subject: hwrng: imx-rngc - Moving IRQ handler registering after + imx_rngc_irq_mask_clear() + +From: Kshitiz Varshney + +[ Upstream commit 10a2199caf437e893d9027d97700b3c6010048b7 ] + +Issue: +While servicing interrupt, if the IRQ happens to be because of a SEED_DONE +due to a previous boot stage, you end up completing the completion +prematurely, hence causing kernel to crash while booting. + +Fix: +Moving IRQ handler registering after imx_rngc_irq_mask_clear() + +Fixes: 1d5449445bd0 (hwrng: mx-rngc - add a driver for Freescale RNGC) +Signed-off-by: Kshitiz Varshney +Signed-off-by: Herbert Xu +Signed-off-by: Sasha Levin +--- + drivers/char/hw_random/imx-rngc.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c +index e32c52c10d4d..1d7ce7443586 100644 +--- a/drivers/char/hw_random/imx-rngc.c ++++ b/drivers/char/hw_random/imx-rngc.c +@@ -264,13 +264,6 @@ static int imx_rngc_probe(struct platform_device *pdev) + if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) + return -ENODEV; + +- ret = devm_request_irq(&pdev->dev, +- irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); +- if (ret) { +- dev_err(rngc->dev, "Can't get interrupt working.\n"); +- return ret; +- } +- + init_completion(&rngc->rng_op_done); + + rngc->rng.name = pdev->name; +@@ -284,6 +277,13 @@ static int imx_rngc_probe(struct platform_device *pdev) + + imx_rngc_irq_mask_clear(rngc); + ++ ret = devm_request_irq(&pdev->dev, ++ irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); ++ if (ret) { ++ dev_err(rngc->dev, "Can't get interrupt working.\n"); ++ return ret; ++ } ++ + if (self_test) { + ret = imx_rngc_self_test(rngc); + if (ret) { +-- +2.35.1 + diff --git a/queue-5.19/hwrng-imx-rngc-use-devm_clk_get_enabled.patch b/queue-5.19/hwrng-imx-rngc-use-devm_clk_get_enabled.patch new file mode 100644 index 00000000000..75d5aefcf69 --- /dev/null +++ b/queue-5.19/hwrng-imx-rngc-use-devm_clk_get_enabled.patch @@ -0,0 +1,106 @@ +From 1e26bece8e6111830df4efb829632bee9f4eab77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 21:37:42 +0200 +Subject: hwrng: imx-rngc - use devm_clk_get_enabled + +From: Martin Kaiser + +[ Upstream commit 6a2bc448423cea44e7dba0f72d7c82ae04ab201e ] + +Use the new devm_clk_get_enabled function to get our clock. + +We don't have to disable and unprepare the clock ourselves any more in +error paths and in the remove function. + +Signed-off-by: Martin Kaiser +Signed-off-by: Herbert Xu +Stable-dep-of: 10a2199caf43 ("hwrng: imx-rngc - Moving IRQ handler registering after imx_rngc_irq_mask_clear()") +Signed-off-by: Sasha Levin +--- + drivers/char/hw_random/imx-rngc.c | 25 ++++++------------------- + 1 file changed, 6 insertions(+), 19 deletions(-) + +diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c +index b05d676ca814..e32c52c10d4d 100644 +--- a/drivers/char/hw_random/imx-rngc.c ++++ b/drivers/char/hw_random/imx-rngc.c +@@ -245,7 +245,7 @@ static int imx_rngc_probe(struct platform_device *pdev) + if (IS_ERR(rngc->base)) + return PTR_ERR(rngc->base); + +- rngc->clk = devm_clk_get(&pdev->dev, NULL); ++ rngc->clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(rngc->clk)) { + dev_err(&pdev->dev, "Can not get rng_clk\n"); + return PTR_ERR(rngc->clk); +@@ -255,26 +255,20 @@ static int imx_rngc_probe(struct platform_device *pdev) + if (irq < 0) + return irq; + +- ret = clk_prepare_enable(rngc->clk); +- if (ret) +- return ret; +- + ver_id = readl(rngc->base + RNGC_VER_ID); + rng_type = ver_id >> RNGC_TYPE_SHIFT; + /* + * This driver supports only RNGC and RNGB. (There's a different + * driver for RNGA.) + */ +- if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) { +- ret = -ENODEV; +- goto err; +- } ++ if (rng_type != RNGC_TYPE_RNGC && rng_type != RNGC_TYPE_RNGB) ++ return -ENODEV; + + ret = devm_request_irq(&pdev->dev, + irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); + if (ret) { + dev_err(rngc->dev, "Can't get interrupt working.\n"); +- goto err; ++ return ret; + } + + init_completion(&rngc->rng_op_done); +@@ -294,14 +288,14 @@ static int imx_rngc_probe(struct platform_device *pdev) + ret = imx_rngc_self_test(rngc); + if (ret) { + dev_err(rngc->dev, "self test failed\n"); +- goto err; ++ return ret; + } + } + + ret = hwrng_register(&rngc->rng); + if (ret) { + dev_err(&pdev->dev, "hwrng registration failed\n"); +- goto err; ++ return ret; + } + + dev_info(&pdev->dev, +@@ -309,11 +303,6 @@ static int imx_rngc_probe(struct platform_device *pdev) + rng_type == RNGC_TYPE_RNGB ? 'B' : 'C', + (ver_id >> RNGC_VER_MAJ_SHIFT) & 0xff, ver_id & 0xff); + return 0; +- +-err: +- clk_disable_unprepare(rngc->clk); +- +- return ret; + } + + static int __exit imx_rngc_remove(struct platform_device *pdev) +@@ -322,8 +311,6 @@ static int __exit imx_rngc_remove(struct platform_device *pdev) + + hwrng_unregister(&rngc->rng); + +- clk_disable_unprepare(rngc->clk); +- + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/i2c-designware-pci-group-amd-navi-quirk-parts-togeth.patch b/queue-5.19/i2c-designware-pci-group-amd-navi-quirk-parts-togeth.patch new file mode 100644 index 00000000000..47967a01390 --- /dev/null +++ b/queue-5.19/i2c-designware-pci-group-amd-navi-quirk-parts-togeth.patch @@ -0,0 +1,97 @@ +From daeaa2c5439fa79e5ab2720e50ea7bc3db88d06b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 12:42:14 +0300 +Subject: i2c: designware-pci: Group AMD NAVI quirk parts together + +From: Andy Shevchenko + +[ Upstream commit 65769162ae4b7f2d82e54998be446226b05fcd8f ] + +The code is ogranized in a way that all related parts +to the certain platform quirk go together. This is not +the case for AMD NAVI. Shuffle code to make it happen. + +While at it, drop the frequency definition and use +hard coded value as it's done for other platforms and +add a comment to the PCI ID list. + +Signed-off-by: Andy Shevchenko +Acked-by: Jarkko Nikula +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-designware-pcidrv.c | 30 +++++++++++----------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c +index 608e61209455..ca368482b246 100644 +--- a/drivers/i2c/busses/i2c-designware-pcidrv.c ++++ b/drivers/i2c/busses/i2c-designware-pcidrv.c +@@ -27,7 +27,6 @@ + #include "i2c-ccgx-ucsi.h" + + #define DRIVER_NAME "i2c-designware-pci" +-#define AMD_CLK_RATE_HZ 100000 + + enum dw_pci_ctl_id_t { + medfield, +@@ -100,11 +99,6 @@ static u32 mfld_get_clk_rate_khz(struct dw_i2c_dev *dev) + return 25000; + } + +-static u32 navi_amd_get_clk_rate_khz(struct dw_i2c_dev *dev) +-{ +- return AMD_CLK_RATE_HZ; +-} +- + static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) + { + struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev); +@@ -126,15 +120,6 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) + return -ENODEV; + } + +-static int navi_amd_setup(struct pci_dev *pdev, struct dw_pci_controller *c) +-{ +- struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev); +- +- dev->flags |= MODEL_AMD_NAVI_GPU; +- dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; +- return 0; +-} +- + static int mrfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) + { + /* +@@ -159,6 +144,20 @@ static u32 ehl_get_clk_rate_khz(struct dw_i2c_dev *dev) + return 100000; + } + ++static u32 navi_amd_get_clk_rate_khz(struct dw_i2c_dev *dev) ++{ ++ return 100000; ++} ++ ++static int navi_amd_setup(struct pci_dev *pdev, struct dw_pci_controller *c) ++{ ++ struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev); ++ ++ dev->flags |= MODEL_AMD_NAVI_GPU; ++ dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; ++ return 0; ++} ++ + static struct dw_pci_controller dw_pci_controllers[] = { + [medfield] = { + .bus_num = -1, +@@ -389,6 +388,7 @@ static const struct pci_device_id i2_designware_pci_ids[] = { + { PCI_VDEVICE(INTEL, 0x4bbe), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bbf), elkhartlake }, + { PCI_VDEVICE(INTEL, 0x4bc0), elkhartlake }, ++ /* AMD NAVI */ + { PCI_VDEVICE(ATI, 0x7314), navi_amd }, + { PCI_VDEVICE(ATI, 0x73a4), navi_amd }, + { PCI_VDEVICE(ATI, 0x73e4), navi_amd }, +-- +2.35.1 + diff --git a/queue-5.19/i2c-mlxbf-support-lock-mechanism.patch b/queue-5.19/i2c-mlxbf-support-lock-mechanism.patch new file mode 100644 index 00000000000..8f841f8380a --- /dev/null +++ b/queue-5.19/i2c-mlxbf-support-lock-mechanism.patch @@ -0,0 +1,121 @@ +From 47df84569ff25ec2aa258d475e076781fa72c3d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 15:45:04 -0400 +Subject: i2c: mlxbf: support lock mechanism + +From: Asmaa Mnebhi + +[ Upstream commit 86067ccfa1424a26491542d6f6d7546d40b61a10 ] + +Linux is not the only entity using the BlueField I2C busses so +support a lock mechanism provided by hardware to avoid issues +when multiple entities are trying to access the same bus. + +The lock is acquired whenever written explicitely or the lock +register is read. So make sure it is always released at the end +of a successful or failed transaction. + +Fixes: b5b5b32081cd206b (i2c: mlxbf: I2C SMBus driver for Mellanox BlueField SoC) +Reviewed-by: Khalil Blaiech +Signed-off-by: Asmaa Mnebhi +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-mlxbf.c | 44 ++++++++++++++++++++++++++++++---- + 1 file changed, 39 insertions(+), 5 deletions(-) + +diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c +index ad5efd7497d1..0e840eba4fd6 100644 +--- a/drivers/i2c/busses/i2c-mlxbf.c ++++ b/drivers/i2c/busses/i2c-mlxbf.c +@@ -306,6 +306,7 @@ static u64 mlxbf_i2c_corepll_frequency; + * exact. + */ + #define MLXBF_I2C_SMBUS_TIMEOUT (300 * 1000) /* 300ms */ ++#define MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT (300 * 1000) /* 300ms */ + + /* Encapsulates timing parameters. */ + struct mlxbf_i2c_timings { +@@ -514,6 +515,25 @@ static bool mlxbf_smbus_master_wait_for_idle(struct mlxbf_i2c_priv *priv) + return false; + } + ++/* ++ * wait for the lock to be released before acquiring it. ++ */ ++static bool mlxbf_i2c_smbus_master_lock(struct mlxbf_i2c_priv *priv) ++{ ++ if (mlxbf_smbus_poll(priv->smbus->io, MLXBF_I2C_SMBUS_MASTER_GW, ++ MLXBF_I2C_MASTER_LOCK_BIT, true, ++ MLXBF_I2C_SMBUS_LOCK_POLL_TIMEOUT)) ++ return true; ++ ++ return false; ++} ++ ++static void mlxbf_i2c_smbus_master_unlock(struct mlxbf_i2c_priv *priv) ++{ ++ /* Clear the gw to clear the lock */ ++ writel(0, priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_GW); ++} ++ + static bool mlxbf_i2c_smbus_transaction_success(u32 master_status, + u32 cause_status) + { +@@ -705,10 +725,19 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + slave = request->slave & GENMASK(6, 0); + addr = slave << 1; + +- /* First of all, check whether the HW is idle. */ +- if (WARN_ON(!mlxbf_smbus_master_wait_for_idle(priv))) ++ /* ++ * Try to acquire the smbus gw lock before any reads of the GW register since ++ * a read sets the lock. ++ */ ++ if (WARN_ON(!mlxbf_i2c_smbus_master_lock(priv))) + return -EBUSY; + ++ /* Check whether the HW is idle */ ++ if (WARN_ON(!mlxbf_smbus_master_wait_for_idle(priv))) { ++ ret = -EBUSY; ++ goto out_unlock; ++ } ++ + /* Set first byte. */ + data_desc[data_idx++] = addr; + +@@ -732,8 +761,10 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + write_en = 1; + write_len += operation->length; + if (data_idx + operation->length > +- MLXBF_I2C_MASTER_DATA_DESC_SIZE) +- return -ENOBUFS; ++ MLXBF_I2C_MASTER_DATA_DESC_SIZE) { ++ ret = -ENOBUFS; ++ goto out_unlock; ++ } + memcpy(data_desc + data_idx, + operation->buffer, operation->length); + data_idx += operation->length; +@@ -765,7 +796,7 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + ret = mlxbf_i2c_smbus_enable(priv, slave, write_len, block_en, + pec_en, 0); + if (ret) +- return ret; ++ goto out_unlock; + } + + if (read_en) { +@@ -792,6 +823,9 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv, + priv->smbus->io + MLXBF_I2C_SMBUS_MASTER_FSM); + } + ++out_unlock: ++ mlxbf_i2c_smbus_master_unlock(priv); ++ + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.19/ia64-export-memory_add_physaddr_to_nid-to-fix-cxl-bu.patch b/queue-5.19/ia64-export-memory_add_physaddr_to_nid-to-fix-cxl-bu.patch new file mode 100644 index 00000000000..2956cdaa0fa --- /dev/null +++ b/queue-5.19/ia64-export-memory_add_physaddr_to_nid-to-fix-cxl-bu.patch @@ -0,0 +1,46 @@ +From a2e6c328d48a94d51ad6961d4cda2820f99b35eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 10 Sep 2022 18:26:16 -0700 +Subject: ia64: export memory_add_physaddr_to_nid to fix cxl build error + +From: Randy Dunlap + +[ Upstream commit 97c318bfbe84efded246e80428054f300042f110 ] + +cxl_pmem.ko uses memory_add_physaddr_to_nid() but ia64 does not export it, +so this causes a build error: + +ERROR: modpost: "memory_add_physaddr_to_nid" [drivers/cxl/cxl_pmem.ko] undefined! + +Fix this by exporting that function. + +Fixes: 8c2676a5870a ("hot-add-mem x86_64: memory_add_physaddr_to_nid node fixup") +Reported-by: kernel test robot +Signed-off-by: Randy Dunlap +Cc: Dan Williams +Cc: Ben Widawsky +Cc: Jonathan Cameron +Cc: linux-ia64@vger.kernel.org +Cc: Arnd Bergmann +Cc: Keith Mannthey +Cc: Andrew Morton +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/ia64/mm/numa.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c +index d6579ec3ea32..4c7b1f50e3b7 100644 +--- a/arch/ia64/mm/numa.c ++++ b/arch/ia64/mm/numa.c +@@ -75,5 +75,6 @@ int memory_add_physaddr_to_nid(u64 addr) + return 0; + return nid; + } ++EXPORT_SYMBOL(memory_add_physaddr_to_nid); + #endif + #endif +-- +2.35.1 + diff --git a/queue-5.19/iavf-fix-race-between-iavf_close-and-iavf_reset_task.patch b/queue-5.19/iavf-fix-race-between-iavf_close-and-iavf_reset_task.patch new file mode 100644 index 00000000000..2a72c424d8b --- /dev/null +++ b/queue-5.19/iavf-fix-race-between-iavf_close-and-iavf_reset_task.patch @@ -0,0 +1,294 @@ +From 5aa3e3d1bd0293c60c29e4c6d1a2af1b0acc5cc6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 13:32:33 +0200 +Subject: iavf: Fix race between iavf_close and iavf_reset_task + +From: Michal Jaron + +[ Upstream commit 11c12adcbc1598d91e73ab6ddfa41d25a01478ed ] + +During stress tests with adding VF to namespace and changing vf's +trust there was a race between iavf_reset_task and iavf_close. +Sometimes when IAVF_FLAG_AQ_DISABLE_QUEUES from iavf_close was sent +to PF after reset and before IAVF_AQ_GET_CONFIG was sent then PF +returns error IAVF_NOT_SUPPORTED to disable queues request and +following requests. There is need to get_config before other +aq_required will be send but iavf_close clears all flags, if +get_config was not sent before iavf_close, then it will not be send +at all. + +In case when IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS was sent before +IAVF_FLAG_AQ_DISABLE_QUEUES then there was rtnl_lock deadlock +between iavf_close and iavf_adminq_task until iavf_close timeouts +and disable queues was sent after iavf_close ends. + +There was also a problem with sending delete/add filters. +Sometimes when filters was not yet added to PF and in +iavf_close all filters was set to remove there might be a try +to remove nonexistent filters on PF. + +Add aq_required_tmp to save aq_required flags and send them after +disable_queues will be handled. Clear flags given to iavf_down +different than IAVF_FLAG_AQ_GET_CONFIG as this flag is necessary +to sent other aq_required. Remove some flags that we don't +want to send as we are in iavf_close and we want to disable +interface. Remove filters which was not yet sent and send del +filters flags only when there are filters to remove. + +Signed-off-by: Michal Jaron +Signed-off-by: Mateusz Palczewski +Tested-by: Konrad Jankowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/iavf/iavf_main.c | 177 ++++++++++++++++---- + 1 file changed, 141 insertions(+), 36 deletions(-) + +diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c +index 981c43b204ff..d3822c264642 100644 +--- a/drivers/net/ethernet/intel/iavf/iavf_main.c ++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c +@@ -1184,66 +1184,138 @@ static void iavf_up_complete(struct iavf_adapter *adapter) + } + + /** +- * iavf_down - Shutdown the connection processing ++ * iavf_clear_mac_vlan_filters - Remove mac and vlan filters not sent to PF ++ * yet and mark other to be removed. + * @adapter: board private structure +- * +- * Expects to be called while holding the __IAVF_IN_CRITICAL_TASK bit lock. + **/ +-void iavf_down(struct iavf_adapter *adapter) ++static void iavf_clear_mac_vlan_filters(struct iavf_adapter *adapter) + { +- struct net_device *netdev = adapter->netdev; +- struct iavf_vlan_filter *vlf; +- struct iavf_cloud_filter *cf; +- struct iavf_fdir_fltr *fdir; +- struct iavf_mac_filter *f; +- struct iavf_adv_rss *rss; +- +- if (adapter->state <= __IAVF_DOWN_PENDING) +- return; +- +- netif_carrier_off(netdev); +- netif_tx_disable(netdev); +- adapter->link_up = false; +- iavf_napi_disable_all(adapter); +- iavf_irq_disable(adapter); ++ struct iavf_vlan_filter *vlf, *vlftmp; ++ struct iavf_mac_filter *f, *ftmp; + + spin_lock_bh(&adapter->mac_vlan_list_lock); +- + /* clear the sync flag on all filters */ + __dev_uc_unsync(adapter->netdev, NULL); + __dev_mc_unsync(adapter->netdev, NULL); + + /* remove all MAC filters */ +- list_for_each_entry(f, &adapter->mac_filter_list, list) { +- f->remove = true; ++ list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, ++ list) { ++ if (f->add) { ++ list_del(&f->list); ++ kfree(f); ++ } else { ++ f->remove = true; ++ } + } + + /* remove all VLAN filters */ +- list_for_each_entry(vlf, &adapter->vlan_filter_list, list) { +- vlf->remove = true; ++ list_for_each_entry_safe(vlf, vlftmp, &adapter->vlan_filter_list, ++ list) { ++ if (vlf->add) { ++ list_del(&vlf->list); ++ kfree(vlf); ++ } else { ++ vlf->remove = true; ++ } + } +- + spin_unlock_bh(&adapter->mac_vlan_list_lock); ++} ++ ++/** ++ * iavf_clear_cloud_filters - Remove cloud filters not sent to PF yet and ++ * mark other to be removed. ++ * @adapter: board private structure ++ **/ ++static void iavf_clear_cloud_filters(struct iavf_adapter *adapter) ++{ ++ struct iavf_cloud_filter *cf, *cftmp; + + /* remove all cloud filters */ + spin_lock_bh(&adapter->cloud_filter_list_lock); +- list_for_each_entry(cf, &adapter->cloud_filter_list, list) { +- cf->del = true; ++ list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, ++ list) { ++ if (cf->add) { ++ list_del(&cf->list); ++ kfree(cf); ++ adapter->num_cloud_filters--; ++ } else { ++ cf->del = true; ++ } + } + spin_unlock_bh(&adapter->cloud_filter_list_lock); ++} ++ ++/** ++ * iavf_clear_fdir_filters - Remove fdir filters not sent to PF yet and mark ++ * other to be removed. ++ * @adapter: board private structure ++ **/ ++static void iavf_clear_fdir_filters(struct iavf_adapter *adapter) ++{ ++ struct iavf_fdir_fltr *fdir, *fdirtmp; + + /* remove all Flow Director filters */ + spin_lock_bh(&adapter->fdir_fltr_lock); +- list_for_each_entry(fdir, &adapter->fdir_list_head, list) { +- fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST; ++ list_for_each_entry_safe(fdir, fdirtmp, &adapter->fdir_list_head, ++ list) { ++ if (fdir->state == IAVF_FDIR_FLTR_ADD_REQUEST) { ++ list_del(&fdir->list); ++ kfree(fdir); ++ adapter->fdir_active_fltr--; ++ } else { ++ fdir->state = IAVF_FDIR_FLTR_DEL_REQUEST; ++ } + } + spin_unlock_bh(&adapter->fdir_fltr_lock); ++} ++ ++/** ++ * iavf_clear_adv_rss_conf - Remove adv rss conf not sent to PF yet and mark ++ * other to be removed. ++ * @adapter: board private structure ++ **/ ++static void iavf_clear_adv_rss_conf(struct iavf_adapter *adapter) ++{ ++ struct iavf_adv_rss *rss, *rsstmp; + + /* remove all advance RSS configuration */ + spin_lock_bh(&adapter->adv_rss_lock); +- list_for_each_entry(rss, &adapter->adv_rss_list_head, list) +- rss->state = IAVF_ADV_RSS_DEL_REQUEST; ++ list_for_each_entry_safe(rss, rsstmp, &adapter->adv_rss_list_head, ++ list) { ++ if (rss->state == IAVF_ADV_RSS_ADD_REQUEST) { ++ list_del(&rss->list); ++ kfree(rss); ++ } else { ++ rss->state = IAVF_ADV_RSS_DEL_REQUEST; ++ } ++ } + spin_unlock_bh(&adapter->adv_rss_lock); ++} ++ ++/** ++ * iavf_down - Shutdown the connection processing ++ * @adapter: board private structure ++ * ++ * Expects to be called while holding the __IAVF_IN_CRITICAL_TASK bit lock. ++ **/ ++void iavf_down(struct iavf_adapter *adapter) ++{ ++ struct net_device *netdev = adapter->netdev; ++ ++ if (adapter->state <= __IAVF_DOWN_PENDING) ++ return; ++ ++ netif_carrier_off(netdev); ++ netif_tx_disable(netdev); ++ adapter->link_up = false; ++ iavf_napi_disable_all(adapter); ++ iavf_irq_disable(adapter); ++ ++ iavf_clear_mac_vlan_filters(adapter); ++ iavf_clear_cloud_filters(adapter); ++ iavf_clear_fdir_filters(adapter); ++ iavf_clear_adv_rss_conf(adapter); + + if (!(adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)) { + /* cancel any current operation */ +@@ -1252,11 +1324,16 @@ void iavf_down(struct iavf_adapter *adapter) + * here for this to complete. The watchdog is still running + * and it will take care of this. + */ +- adapter->aq_required = IAVF_FLAG_AQ_DEL_MAC_FILTER; +- adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER; +- adapter->aq_required |= IAVF_FLAG_AQ_DEL_CLOUD_FILTER; +- adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER; +- adapter->aq_required |= IAVF_FLAG_AQ_DEL_ADV_RSS_CFG; ++ if (!list_empty(&adapter->mac_filter_list)) ++ adapter->aq_required |= IAVF_FLAG_AQ_DEL_MAC_FILTER; ++ if (!list_empty(&adapter->vlan_filter_list)) ++ adapter->aq_required |= IAVF_FLAG_AQ_DEL_VLAN_FILTER; ++ if (!list_empty(&adapter->cloud_filter_list)) ++ adapter->aq_required |= IAVF_FLAG_AQ_DEL_CLOUD_FILTER; ++ if (!list_empty(&adapter->fdir_list_head)) ++ adapter->aq_required |= IAVF_FLAG_AQ_DEL_FDIR_FILTER; ++ if (!list_empty(&adapter->adv_rss_list_head)) ++ adapter->aq_required |= IAVF_FLAG_AQ_DEL_ADV_RSS_CFG; + adapter->aq_required |= IAVF_FLAG_AQ_DISABLE_QUEUES; + } + +@@ -4082,6 +4159,7 @@ static int iavf_open(struct net_device *netdev) + static int iavf_close(struct net_device *netdev) + { + struct iavf_adapter *adapter = netdev_priv(netdev); ++ u64 aq_to_restore; + int status; + + mutex_lock(&adapter->crit_lock); +@@ -4094,6 +4172,29 @@ static int iavf_close(struct net_device *netdev) + set_bit(__IAVF_VSI_DOWN, adapter->vsi.state); + if (CLIENT_ENABLED(adapter)) + adapter->flags |= IAVF_FLAG_CLIENT_NEEDS_CLOSE; ++ /* We cannot send IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS before ++ * IAVF_FLAG_AQ_DISABLE_QUEUES because in such case there is rtnl ++ * deadlock with adminq_task() until iavf_close timeouts. We must send ++ * IAVF_FLAG_AQ_GET_CONFIG before IAVF_FLAG_AQ_DISABLE_QUEUES to make ++ * disable queues possible for vf. Give only necessary flags to ++ * iavf_down and save other to set them right before iavf_close() ++ * returns, when IAVF_FLAG_AQ_DISABLE_QUEUES will be already sent and ++ * iavf will be in DOWN state. ++ */ ++ aq_to_restore = adapter->aq_required; ++ adapter->aq_required &= IAVF_FLAG_AQ_GET_CONFIG; ++ ++ /* Remove flags which we do not want to send after close or we want to ++ * send before disable queues. ++ */ ++ aq_to_restore &= ~(IAVF_FLAG_AQ_GET_CONFIG | ++ IAVF_FLAG_AQ_ENABLE_QUEUES | ++ IAVF_FLAG_AQ_CONFIGURE_QUEUES | ++ IAVF_FLAG_AQ_ADD_VLAN_FILTER | ++ IAVF_FLAG_AQ_ADD_MAC_FILTER | ++ IAVF_FLAG_AQ_ADD_CLOUD_FILTER | ++ IAVF_FLAG_AQ_ADD_FDIR_FILTER | ++ IAVF_FLAG_AQ_ADD_ADV_RSS_CFG); + + iavf_down(adapter); + iavf_change_state(adapter, __IAVF_DOWN_PENDING); +@@ -4117,6 +4218,10 @@ static int iavf_close(struct net_device *netdev) + msecs_to_jiffies(500)); + if (!status) + netdev_warn(netdev, "Device resources not yet released\n"); ++ ++ mutex_lock(&adapter->crit_lock); ++ adapter->aq_required |= aq_to_restore; ++ mutex_unlock(&adapter->crit_lock); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/ib-rdmavt-add-__init-__exit-annotations-to-module-in.patch b/queue-5.19/ib-rdmavt-add-__init-__exit-annotations-to-module-in.patch new file mode 100644 index 00000000000..bd638fc3235 --- /dev/null +++ b/queue-5.19/ib-rdmavt-add-__init-__exit-annotations-to-module-in.patch @@ -0,0 +1,45 @@ +From 90c19f0c76d7edd9e5c09d5cc2dca6401d3a3104 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 17:14:57 +0800 +Subject: IB/rdmavt: Add __init/__exit annotations to module init/exit funcs + +From: Xiu Jianfeng + +[ Upstream commit 78657a445ca7603024348781c921f8ecaee10a49 ] + +Add missing __init/__exit annotations to module init/exit funcs. + +Fixes: 0194621b2253 ("IB/rdmavt: Create module framework and handle driver registration") +Link: https://lore.kernel.org/r/20220924091457.52446-1-xiujianfeng@huawei.com +Signed-off-by: Xiu Jianfeng +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rdmavt/vt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/sw/rdmavt/vt.c b/drivers/infiniband/sw/rdmavt/vt.c +index 59481ae39505..d61f8de7f21c 100644 +--- a/drivers/infiniband/sw/rdmavt/vt.c ++++ b/drivers/infiniband/sw/rdmavt/vt.c +@@ -15,7 +15,7 @@ + MODULE_LICENSE("Dual BSD/GPL"); + MODULE_DESCRIPTION("RDMA Verbs Transport Library"); + +-static int rvt_init(void) ++static int __init rvt_init(void) + { + int ret = rvt_driver_cq_init(); + +@@ -26,7 +26,7 @@ static int rvt_init(void) + } + module_init(rvt_init); + +-static void rvt_cleanup(void) ++static void __exit rvt_cleanup(void) + { + rvt_cq_exit(); + } +-- +2.35.1 + diff --git a/queue-5.19/ib-set-iova-length-on-ib_mr-in-core-uverbs-layers.patch b/queue-5.19/ib-set-iova-length-on-ib_mr-in-core-uverbs-layers.patch new file mode 100644 index 00000000000..9684a79a937 --- /dev/null +++ b/queue-5.19/ib-set-iova-length-on-ib_mr-in-core-uverbs-layers.patch @@ -0,0 +1,93 @@ +From d27fd5ab442cffc6baf3c44c77d075da8ca0f333 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 17:08:43 +0900 +Subject: IB: Set IOVA/LENGTH on IB_MR in core/uverbs layers + +From: Daisuke Matsuda + +[ Upstream commit 241f9a27e0fc0eaf23e3d52c8450f10648cd11f1 ] + +Set 'iova' and 'length' on ib_mr in ib_uverbs and ib_core layers to let all +drivers have the members filled. Also, this commit removes redundancy in +the respective drivers. + +Previously, commit 04c0a5fcfcf65 ("IB/uverbs: Set IOVA on IB MR in uverbs +layer") changed to set 'iova', but seems to have missed 'length' and the +ib_core layer at that time. + +Fixes: 04c0a5fcfcf65 ("IB/uverbs: Set IOVA on IB MR in uverbs layer") +Signed-off-by: Daisuke Matsuda +Link: https://lore.kernel.org/r/20220921080844.1616883-1-matsuda-daisuke@fujitsu.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/uverbs_cmd.c | 5 ++++- + drivers/infiniband/core/verbs.c | 2 ++ + drivers/infiniband/hw/hns/hns_roce_mr.c | 1 - + drivers/infiniband/hw/mlx4/mr.c | 1 - + 4 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c +index 046376bd68e2..4796f6a8828c 100644 +--- a/drivers/infiniband/core/uverbs_cmd.c ++++ b/drivers/infiniband/core/uverbs_cmd.c +@@ -739,6 +739,7 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) + mr->uobject = uobj; + atomic_inc(&pd->usecnt); + mr->iova = cmd.hca_va; ++ mr->length = cmd.length; + + rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR); + rdma_restrack_set_name(&mr->res, NULL); +@@ -861,8 +862,10 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs) + mr->pd = new_pd; + atomic_inc(&new_pd->usecnt); + } +- if (cmd.flags & IB_MR_REREG_TRANS) ++ if (cmd.flags & IB_MR_REREG_TRANS) { + mr->iova = cmd.hca_va; ++ mr->length = cmd.length; ++ } + } + + memset(&resp, 0, sizeof(resp)); +diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c +index e54b3f1b730e..f8964c8cf0ad 100644 +--- a/drivers/infiniband/core/verbs.c ++++ b/drivers/infiniband/core/verbs.c +@@ -2149,6 +2149,8 @@ struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + mr->pd = pd; + mr->dm = NULL; + atomic_inc(&pd->usecnt); ++ mr->iova = virt_addr; ++ mr->length = length; + + rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR); + rdma_restrack_parent_name(&mr->res, &pd->res); +diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c +index 867972c2a894..dedfa56f5773 100644 +--- a/drivers/infiniband/hw/hns/hns_roce_mr.c ++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c +@@ -249,7 +249,6 @@ struct ib_mr *hns_roce_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + goto err_alloc_pbl; + + mr->ibmr.rkey = mr->ibmr.lkey = mr->key; +- mr->ibmr.length = length; + + return &mr->ibmr; + +diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c +index 04a67b481608..a40bf58bcdd3 100644 +--- a/drivers/infiniband/hw/mlx4/mr.c ++++ b/drivers/infiniband/hw/mlx4/mr.c +@@ -439,7 +439,6 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, + goto err_mr; + + mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; +- mr->ibmr.length = length; + mr->ibmr.page_size = 1U << shift; + + return &mr->ibmr; +-- +2.35.1 + diff --git a/queue-5.19/ice-set-tx_tstamps-when-creating-new-tx-rings-via-et.patch b/queue-5.19/ice-set-tx_tstamps-when-creating-new-tx-rings-via-et.patch new file mode 100644 index 00000000000..85a501de877 --- /dev/null +++ b/queue-5.19/ice-set-tx_tstamps-when-creating-new-tx-rings-via-et.patch @@ -0,0 +1,38 @@ +From 29f9e8c77dd6d69074955741b6d95b0c9c887d48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 16:15:57 -0700 +Subject: ice: set tx_tstamps when creating new Tx rings via ethtool + +From: Jacob Keller + +[ Upstream commit b3b173745c8cab1e24d6821488b60abed3acb24d ] + +When the user changes the number of queues via ethtool, the driver +allocates new rings. This allocation did not initialize tx_tstamps. This +results in the tx_tstamps field being zero (due to kcalloc allocation), and +would result in a NULL pointer dereference when attempting a transmit +timestamp on the new ring. + +Signed-off-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/ice/ice_ethtool.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c +index 4efa5e5846e0..4dfdec11ddc1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -2826,6 +2826,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, + tx_rings[i].count = new_tx_cnt; + tx_rings[i].desc = NULL; + tx_rings[i].tx_buf = NULL; ++ tx_rings[i].tx_tstamps = &pf->ptp.port.tx; + err = ice_setup_tx_ring(&tx_rings[i]); + if (err) { + while (i--) +-- +2.35.1 + diff --git a/queue-5.19/iio-abi-fix-wrong-format-of-differential-capacitance.patch b/queue-5.19/iio-abi-fix-wrong-format-of-differential-capacitance.patch new file mode 100644 index 00000000000..84f1112de0e --- /dev/null +++ b/queue-5.19/iio-abi-fix-wrong-format-of-differential-capacitance.patch @@ -0,0 +1,36 @@ +From a4ccf2ee2795f9ea2ac3186da40667b8a490f968 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Jun 2022 13:29:23 +0100 +Subject: iio: ABI: Fix wrong format of differential capacitance channel ABI. + +From: Jonathan Cameron + +[ Upstream commit 1efc41035f1841acf0af2bab153158e27ce94f10 ] + +in_ only occurs once in these attributes. + +Fixes: 0baf29d658c7 ("staging:iio:documentation Add abi docs for capacitance adcs.") +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20220626122938.582107-3-jic23@kernel.org +Signed-off-by: Sasha Levin +--- + Documentation/ABI/testing/sysfs-bus-iio | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio +index d4ccc68fdcf0..b19ff517e5d6 100644 +--- a/Documentation/ABI/testing/sysfs-bus-iio ++++ b/Documentation/ABI/testing/sysfs-bus-iio +@@ -188,7 +188,7 @@ Description: + Raw capacitance measurement from channel Y. Units after + application of scale and offset are nanofarads. + +-What: /sys/.../iio:deviceX/in_capacitanceY-in_capacitanceZ_raw ++What: /sys/.../iio:deviceX/in_capacitanceY-capacitanceZ_raw + KernelVersion: 3.2 + Contact: linux-iio@vger.kernel.org + Description: +-- +2.35.1 + diff --git a/queue-5.19/iio-adc-at91-sama5d2_adc-check-return-status-for-pre.patch b/queue-5.19/iio-adc-at91-sama5d2_adc-check-return-status-for-pre.patch new file mode 100644 index 00000000000..3b6926dc2d6 --- /dev/null +++ b/queue-5.19/iio-adc-at91-sama5d2_adc-check-return-status-for-pre.patch @@ -0,0 +1,53 @@ +From d02918b0782912e12b3017530ac375e163e48b17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 13:28:38 +0300 +Subject: iio: adc: at91-sama5d2_adc: check return status for pressure and + touch + +From: Claudiu Beznea + +[ Upstream commit d84ace944a3b24529798dbae1340dea098473155 ] + +Check return status of at91_adc_read_position() and +at91_adc_read_pressure() in at91_adc_read_info_raw(). + +Fixes: 6794e23fa3fe ("iio: adc: at91-sama5d2_adc: add support for oversampling resolution") +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20220803102855.2191070-3-claudiu.beznea@microchip.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/at91-sama5d2_adc.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index 32b6f157b803..c3301c749164 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -1544,8 +1544,10 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + *val = tmp_val; + mutex_unlock(&st->lock); + iio_device_release_direct_mode(indio_dev); ++ if (ret > 0) ++ ret = at91_adc_adjust_val_osr(st, val); + +- return at91_adc_adjust_val_osr(st, val); ++ return ret; + } + if (chan->type == IIO_PRESSURE) { + ret = iio_device_claim_direct_mode(indio_dev); +@@ -1558,8 +1560,10 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + *val = tmp_val; + mutex_unlock(&st->lock); + iio_device_release_direct_mode(indio_dev); ++ if (ret > 0) ++ ret = at91_adc_adjust_val_osr(st, val); + +- return at91_adc_adjust_val_osr(st, val); ++ return ret; + } + + /* in this case we have a voltage channel */ +-- +2.35.1 + diff --git a/queue-5.19/iio-adc-at91-sama5d2_adc-disable-prepare-buffer-on-s.patch b/queue-5.19/iio-adc-at91-sama5d2_adc-disable-prepare-buffer-on-s.patch new file mode 100644 index 00000000000..7319b39334f --- /dev/null +++ b/queue-5.19/iio-adc-at91-sama5d2_adc-disable-prepare-buffer-on-s.patch @@ -0,0 +1,62 @@ +From d236843305ce19016addd334fda159c7f145af61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 13:28:40 +0300 +Subject: iio: adc: at91-sama5d2_adc: disable/prepare buffer on suspend/resume + +From: Claudiu Beznea + +[ Upstream commit 808175e21d9b7f866eda742e8970f27b78afe5db ] + +In case triggered buffers are enabled while system is suspended they will +not work anymore after resume. For this call at91_adc_buffer_postdisable() +on suspend and at91_adc_buffer_prepare() on resume. On tests it has been +seen that at91_adc_buffer_postdisable() call is not necessary but it has +been kept because it also does the book keeping for DMA. On resume path +there is no need to call at91_adc_configure_touch() as it is embedded in +at91_adc_buffer_prepare(). + +Fixes: 073c662017f2f ("iio: adc: at91-sama5d2_adc: add support for DMA") +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20220803102855.2191070-5-claudiu.beznea@microchip.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/at91-sama5d2_adc.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index 40a95d2fd5c8..2c087d52f164 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -2116,6 +2116,9 @@ static __maybe_unused int at91_adc_suspend(struct device *dev) + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct at91_adc_state *st = iio_priv(indio_dev); + ++ if (iio_buffer_enabled(indio_dev)) ++ at91_adc_buffer_postdisable(indio_dev); ++ + /* + * Do a sofware reset of the ADC before we go to suspend. + * this will ensure that all pins are free from being muxed by the ADC +@@ -2159,14 +2162,11 @@ static __maybe_unused int at91_adc_resume(struct device *dev) + if (!iio_buffer_enabled(indio_dev)) + return 0; + +- /* check if we are enabling triggered buffer or the touchscreen */ +- if (at91_adc_current_chan_is_touch(indio_dev)) +- return at91_adc_configure_touch(st, true); +- else +- return at91_adc_configure_trigger(st->trig, true); ++ ret = at91_adc_buffer_prepare(indio_dev); ++ if (ret) ++ goto vref_disable_resume; + +- /* not needed but more explicit */ +- return 0; ++ return at91_adc_configure_trigger(st->trig, true); + + vref_disable_resume: + regulator_disable(st->vref); +-- +2.35.1 + diff --git a/queue-5.19/iio-adc-at91-sama5d2_adc-fix-at91_sama5d2_mr_trackti.patch b/queue-5.19/iio-adc-at91-sama5d2_adc-fix-at91_sama5d2_mr_trackti.patch new file mode 100644 index 00000000000..c6fbca4d6e2 --- /dev/null +++ b/queue-5.19/iio-adc-at91-sama5d2_adc-fix-at91_sama5d2_mr_trackti.patch @@ -0,0 +1,38 @@ +From 48858c2509c1dd4af13c3354e75b343c3c961fd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 13:28:37 +0300 +Subject: iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX + +From: Claudiu Beznea + +[ Upstream commit bb73d5d9164c57c4bb916739a98e5cd8e0a5ed8c ] + +All ADC HW versions handled by this driver (SAMA5D2, SAM9X60, SAMA7G5) +have MR.TRACKTIM on 4 bits. Fix AT91_SAMA5D2_MR_TRACKTIM_MAX to reflect +this. + +Fixes: 27e177190891 ("iio:adc:at91_adc8xx: introduce new atmel adc driver") +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20220803102855.2191070-2-claudiu.beznea@microchip.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/at91-sama5d2_adc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index b764823ce57e..32b6f157b803 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -77,7 +77,7 @@ struct at91_adc_reg_layout { + #define AT91_SAMA5D2_MR_ANACH BIT(23) + /* Tracking Time */ + #define AT91_SAMA5D2_MR_TRACKTIM(v) ((v) << 24) +-#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xff ++#define AT91_SAMA5D2_MR_TRACKTIM_MAX 0xf + /* Transfer Time */ + #define AT91_SAMA5D2_MR_TRANSFER(v) ((v) << 28) + #define AT91_SAMA5D2_MR_TRANSFER_MAX 0x3 +-- +2.35.1 + diff --git a/queue-5.19/iio-adc-at91-sama5d2_adc-lock-around-oversampling-an.patch b/queue-5.19/iio-adc-at91-sama5d2_adc-lock-around-oversampling-an.patch new file mode 100644 index 00000000000..9be1f5bebc6 --- /dev/null +++ b/queue-5.19/iio-adc-at91-sama5d2_adc-lock-around-oversampling-an.patch @@ -0,0 +1,79 @@ +From 55f0dfc56cd0d1fe304c938f952b13d5d782dc3e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 13:28:39 +0300 +Subject: iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq + +From: Claudiu Beznea + +[ Upstream commit 9780a23ed5a0a0a63683e078f576719a98d4fb70 ] + +.read_raw()/.write_raw() could be called asynchronously from user space +or other in kernel drivers. Without locking on st->lock these could be +called asynchronously while there is a conversion in progress. Read will +be harmless but changing registers while conversion is in progress may +lead to inconsistent results. Thus, to avoid this lock st->lock. + +Fixes: 27e177190891 ("iio:adc:at91_adc8xx: introduce new atmel adc driver") +Fixes: 6794e23fa3fe ("iio: adc: at91-sama5d2_adc: add support for oversampling resolution") +Signed-off-by: Claudiu Beznea +Link: https://lore.kernel.org/r/20220803102855.2191070-4-claudiu.beznea@microchip.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/adc/at91-sama5d2_adc.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c +index c3301c749164..40a95d2fd5c8 100644 +--- a/drivers/iio/adc/at91-sama5d2_adc.c ++++ b/drivers/iio/adc/at91-sama5d2_adc.c +@@ -1542,10 +1542,10 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + ret = at91_adc_read_position(st, chan->channel, + &tmp_val); + *val = tmp_val; +- mutex_unlock(&st->lock); +- iio_device_release_direct_mode(indio_dev); + if (ret > 0) + ret = at91_adc_adjust_val_osr(st, val); ++ mutex_unlock(&st->lock); ++ iio_device_release_direct_mode(indio_dev); + + return ret; + } +@@ -1558,10 +1558,10 @@ static int at91_adc_read_info_raw(struct iio_dev *indio_dev, + ret = at91_adc_read_pressure(st, chan->channel, + &tmp_val); + *val = tmp_val; +- mutex_unlock(&st->lock); +- iio_device_release_direct_mode(indio_dev); + if (ret > 0) + ret = at91_adc_adjust_val_osr(st, val); ++ mutex_unlock(&st->lock); ++ iio_device_release_direct_mode(indio_dev); + + return ret; + } +@@ -1650,16 +1650,20 @@ static int at91_adc_write_raw(struct iio_dev *indio_dev, + /* if no change, optimize out */ + if (val == st->oversampling_ratio) + return 0; ++ mutex_lock(&st->lock); + st->oversampling_ratio = val; + /* update ratio */ + at91_adc_config_emr(st); ++ mutex_unlock(&st->lock); + return 0; + case IIO_CHAN_INFO_SAMP_FREQ: + if (val < st->soc_info.min_sample_rate || + val > st->soc_info.max_sample_rate) + return -EINVAL; + ++ mutex_lock(&st->lock); + at91_adc_setup_samp_freq(indio_dev, val); ++ mutex_unlock(&st->lock); + return 0; + default: + return -EINVAL; +-- +2.35.1 + diff --git a/queue-5.19/iio-directly-use-ida_alloc-free.patch b/queue-5.19/iio-directly-use-ida_alloc-free.patch new file mode 100644 index 00000000000..fe49d43dc50 --- /dev/null +++ b/queue-5.19/iio-directly-use-ida_alloc-free.patch @@ -0,0 +1,87 @@ +From ed717de59dd86eedcc05544515e2362ad31826e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 May 2022 09:17:39 +0000 +Subject: iio: Directly use ida_alloc()/free() + +From: keliu + +[ Upstream commit 319dbcd84fd2676afb2bcfee575fbc1fce474ec3 ] + +Use ida_alloc()/ida_free() instead of deprecated +ida_simple_get()/ida_simple_remove() . + +Signed-off-by: keliu +Link: https://lore.kernel.org/r/20220527091739.2949426-1-liuke94@huawei.com +Signed-off-by: Jonathan Cameron +Stable-dep-of: 2bc9cd66eb25 ("iio: Use per-device lockdep class for mlock") +Signed-off-by: Sasha Levin +--- + drivers/iio/industrialio-core.c | 6 +++--- + drivers/iio/industrialio-trigger.c | 6 +++--- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c +index ed36851d646b..21ca028b3666 100644 +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -1647,7 +1647,7 @@ static void iio_dev_release(struct device *device) + + iio_device_detach_buffers(indio_dev); + +- ida_simple_remove(&iio_ida, iio_dev_opaque->id); ++ ida_free(&iio_ida, iio_dev_opaque->id); + kfree(iio_dev_opaque); + } + +@@ -1689,7 +1689,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) + mutex_init(&iio_dev_opaque->info_exist_lock); + INIT_LIST_HEAD(&iio_dev_opaque->channel_attr_list); + +- iio_dev_opaque->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); ++ iio_dev_opaque->id = ida_alloc(&iio_ida, GFP_KERNEL); + if (iio_dev_opaque->id < 0) { + /* cannot use a dev_err as the name isn't available */ + pr_err("failed to get device id\n"); +@@ -1698,7 +1698,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) + } + + if (dev_set_name(&indio_dev->dev, "iio:device%d", iio_dev_opaque->id)) { +- ida_simple_remove(&iio_ida, iio_dev_opaque->id); ++ ida_free(&iio_ida, iio_dev_opaque->id); + kfree(iio_dev_opaque); + return NULL; + } +diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c +index 585b6cef8fcc..1e43e93b5816 100644 +--- a/drivers/iio/industrialio-trigger.c ++++ b/drivers/iio/industrialio-trigger.c +@@ -71,7 +71,7 @@ int __iio_trigger_register(struct iio_trigger *trig_info, + + trig_info->owner = this_mod; + +- trig_info->id = ida_simple_get(&iio_trigger_ida, 0, 0, GFP_KERNEL); ++ trig_info->id = ida_alloc(&iio_trigger_ida, GFP_KERNEL); + if (trig_info->id < 0) + return trig_info->id; + +@@ -98,7 +98,7 @@ int __iio_trigger_register(struct iio_trigger *trig_info, + mutex_unlock(&iio_trigger_list_lock); + device_del(&trig_info->dev); + error_unregister_id: +- ida_simple_remove(&iio_trigger_ida, trig_info->id); ++ ida_free(&iio_trigger_ida, trig_info->id); + return ret; + } + EXPORT_SYMBOL(__iio_trigger_register); +@@ -109,7 +109,7 @@ void iio_trigger_unregister(struct iio_trigger *trig_info) + list_del(&trig_info->list); + mutex_unlock(&iio_trigger_list_lock); + +- ida_simple_remove(&iio_trigger_ida, trig_info->id); ++ ida_free(&iio_trigger_ida, trig_info->id); + /* Possible issue in here */ + device_del(&trig_info->dev); + } +-- +2.35.1 + diff --git a/queue-5.19/iio-inkern-fix-return-value-in-devm_of_iio_channel_g.patch b/queue-5.19/iio-inkern-fix-return-value-in-devm_of_iio_channel_g.patch new file mode 100644 index 00000000000..5ec5e563390 --- /dev/null +++ b/queue-5.19/iio-inkern-fix-return-value-in-devm_of_iio_channel_g.patch @@ -0,0 +1,46 @@ +From 6137966fdcf3ab66c9f5af3ab9a4c4b8b01f3e6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Jul 2022 14:28:50 +0200 +Subject: iio: inkern: fix return value in devm_of_iio_channel_get_by_name() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nuno Sá + +[ Upstream commit 9e878dbc0e8322f8b2f5ab0093c1e89926362dbe ] + +of_iio_channel_get_by_name() can either return NULL or an error pointer +so that only doing IS_ERR() is not enough. Fix it by checking the NULL +pointer case and return -ENODEV in that case. Note this is done like this +so that users of the function (which only check for error pointers) do +not need to be changed. This is not ideal since we are losing error codes +and as such, in a follow up change, things will be unified so that +of_iio_channel_get_by_name() only returns error codes. + +Fixes: 6e39b145cef7 ("iio: provide of_iio_channel_get_by_name() and devm_ version it") +Signed-off-by: Nuno Sá +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20220715122903.332535-3-nuno.sa@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/inkern.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c +index 9d87057794fc..87fd2a0d44f2 100644 +--- a/drivers/iio/inkern.c ++++ b/drivers/iio/inkern.c +@@ -412,6 +412,8 @@ struct iio_channel *devm_of_iio_channel_get_by_name(struct device *dev, + channel = of_iio_channel_get_by_name(np, channel_name); + if (IS_ERR(channel)) + return channel; ++ if (!channel) ++ return ERR_PTR(-ENODEV); + + ret = devm_add_action_or_reset(dev, devm_iio_channel_free, channel); + if (ret) +-- +2.35.1 + diff --git a/queue-5.19/iio-inkern-only-release-the-device-node-when-done-wi.patch b/queue-5.19/iio-inkern-only-release-the-device-node-when-done-wi.patch new file mode 100644 index 00000000000..c2fbf393138 --- /dev/null +++ b/queue-5.19/iio-inkern-only-release-the-device-node-when-done-wi.patch @@ -0,0 +1,60 @@ +From f1895f3196575fc5124fdbeefcdc22607584f31d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Jul 2022 14:28:49 +0200 +Subject: iio: inkern: only release the device node when done with it +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Nuno Sá + +[ Upstream commit 79c3e84874c7d14f04ad58313b64955a0d2e9437 ] + +'of_node_put()' can potentially release the memory pointed to by +'iiospec.np' which would leave us with an invalid pointer (and we would +still pass it in 'of_xlate()'). Note that it is not guaranteed for the +of_node lifespan to be attached to the device (to which is attached) +lifespan so that there is (even though very unlikely) the possibility +for the node to be freed while the device is still around. Thus, as there +are indeed some of_xlate users which do access the node, a race is indeed +possible. + +As such, we can only release the node after we are done with it. + +Fixes: 17d82b47a215d ("iio: Add OF support") +Signed-off-by: Nuno Sá +Link: https://lore.kernel.org/r/20220715122903.332535-2-nuno.sa@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/inkern.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c +index df74765d33dc..9d87057794fc 100644 +--- a/drivers/iio/inkern.c ++++ b/drivers/iio/inkern.c +@@ -165,9 +165,10 @@ static int __of_iio_channel_get(struct iio_channel *channel, + + idev = bus_find_device(&iio_bus_type, NULL, iiospec.np, + iio_dev_node_match); +- of_node_put(iiospec.np); +- if (idev == NULL) ++ if (idev == NULL) { ++ of_node_put(iiospec.np); + return -EPROBE_DEFER; ++ } + + indio_dev = dev_to_iio_dev(idev); + channel->indio_dev = indio_dev; +@@ -175,6 +176,7 @@ static int __of_iio_channel_get(struct iio_channel *channel, + index = indio_dev->info->of_xlate(indio_dev, &iiospec); + else + index = __of_iio_simple_xlate(indio_dev, &iiospec); ++ of_node_put(iiospec.np); + if (index < 0) + goto err_put; + channel->channel = &indio_dev->channels[index]; +-- +2.35.1 + diff --git a/queue-5.19/iio-magnetometer-yas530-change-data-type-of-hard_off.patch b/queue-5.19/iio-magnetometer-yas530-change-data-type-of-hard_off.patch new file mode 100644 index 00000000000..cc9d273e16d --- /dev/null +++ b/queue-5.19/iio-magnetometer-yas530-change-data-type-of-hard_off.patch @@ -0,0 +1,43 @@ +From 160ad2e6de3c5f11b44374c80574bf2be58e5328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Aug 2022 23:54:06 +0200 +Subject: iio: magnetometer: yas530: Change data type of hard_offsets to signed + +From: Jakob Hauser + +[ Upstream commit e137fafc8985cf152a4bb6f18ae83ebb06816df1 ] + +The "hard_offsets" are currently unsigned u8 but they should be signed as they +can get negative. They are signed in function yas5xx_meaure_offsets() and in the +Yamaha drivers [1][2]. + +[1] https://github.com/NovaFusion/android_kernel_samsung_golden/blob/cm-12.1/drivers/sensor/compass/yas.h#L156 +[2] https://github.com/msm8916-mainline/android_kernel_qcom_msm8916/blob/GT-I9195I/drivers/iio/magnetometer/yas_mag_drv-yas532.c#L91 + +Fixes: de8860b1ed47 ("iio: magnetometer: Add driver for Yamaha YAS530") +Signed-off-by: Jakob Hauser +Reviewed-by: Linus Walleij +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/40f052bf6491457d0c5c0ed4c3534dc6fa251c3c.1660337264.git.jahau@rocketmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/magnetometer/yamaha-yas530.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c +index b2bc637150bf..40192aa46b04 100644 +--- a/drivers/iio/magnetometer/yamaha-yas530.c ++++ b/drivers/iio/magnetometer/yamaha-yas530.c +@@ -132,7 +132,7 @@ struct yas5xx { + unsigned int version; + char name[16]; + struct yas5xx_calibration calibration; +- u8 hard_offsets[3]; ++ s8 hard_offsets[3]; + struct iio_mount_matrix orientation; + struct regmap *map; + struct regulator_bulk_data regs[2]; +-- +2.35.1 + diff --git a/queue-5.19/iio-use-per-device-lockdep-class-for-mlock.patch b/queue-5.19/iio-use-per-device-lockdep-class-for-mlock.patch new file mode 100644 index 00000000000..cce9ec00ace --- /dev/null +++ b/queue-5.19/iio-use-per-device-lockdep-class-for-mlock.patch @@ -0,0 +1,111 @@ +From e19912f64dba225e3c4d69acaf0ae10e9d66ea36 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 11:18:40 +0200 +Subject: iio: Use per-device lockdep class for mlock + +From: Vincent Whitchurch + +[ Upstream commit 2bc9cd66eb25d0fefbb081421d6586495e25840e ] + +If an IIO driver uses callbacks from another IIO driver and calls +iio_channel_start_all_cb() from one of its buffer setup ops, then +lockdep complains due to the lock nesting, as in the below example with +lmp91000. + +Since the locks are being taken on different IIO devices, there is no +actual deadlock. Fix the warning by telling lockdep to use a different +class for each iio_device. + + ============================================ + WARNING: possible recursive locking detected + -------------------------------------------- + python3/23 is trying to acquire lock: + (&indio_dev->mlock){+.+.}-{3:3}, at: iio_update_buffers + + but task is already holding lock: + (&indio_dev->mlock){+.+.}-{3:3}, at: enable_store + + other info that might help us debug this: + Possible unsafe locking scenario: + + CPU0 + ---- + lock(&indio_dev->mlock); + lock(&indio_dev->mlock); + + *** DEADLOCK *** + + May be due to missing lock nesting notation + + 5 locks held by python3/23: + #0: (sb_writers#5){.+.+}-{0:0}, at: ksys_write + #1: (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter + #2: (kn->active#14){.+.+}-{0:0}, at: kernfs_fop_write_iter + #3: (&indio_dev->mlock){+.+.}-{3:3}, at: enable_store + #4: (&iio_dev_opaque->info_exist_lock){+.+.}-{3:3}, at: iio_update_buffers + + Call Trace: + __mutex_lock + iio_update_buffers + iio_channel_start_all_cb + lmp91000_buffer_postenable + __iio_update_buffers + enable_store + +Fixes: 67e17300dc1d76 ("iio: potentiostat: add LMP91000 support") +Signed-off-by: Vincent Whitchurch +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20220829091840.2791846-1-vincent.whitchurch@axis.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + drivers/iio/industrialio-core.c | 5 +++++ + include/linux/iio/iio-opaque.h | 2 ++ + 2 files changed, 7 insertions(+) + +diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c +index 21ca028b3666..30a8bd927d7f 100644 +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -1647,6 +1647,8 @@ static void iio_dev_release(struct device *device) + + iio_device_detach_buffers(indio_dev); + ++ lockdep_unregister_key(&iio_dev_opaque->mlock_key); ++ + ida_free(&iio_ida, iio_dev_opaque->id); + kfree(iio_dev_opaque); + } +@@ -1706,6 +1708,9 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv) + INIT_LIST_HEAD(&iio_dev_opaque->buffer_list); + INIT_LIST_HEAD(&iio_dev_opaque->ioctl_handlers); + ++ lockdep_register_key(&iio_dev_opaque->mlock_key); ++ lockdep_set_class(&indio_dev->mlock, &iio_dev_opaque->mlock_key); ++ + return indio_dev; + } + EXPORT_SYMBOL(iio_device_alloc); +diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h +index 6b3586b3f952..d1f8b30a7c8b 100644 +--- a/include/linux/iio/iio-opaque.h ++++ b/include/linux/iio/iio-opaque.h +@@ -11,6 +11,7 @@ + * checked by device drivers but should be considered + * read-only as this is a core internal bit + * @driver_module: used to make it harder to undercut users ++ * @mlock_key: lockdep class for iio_dev lock + * @info_exist_lock: lock to prevent use during removal + * @trig_readonly: mark the current trigger immutable + * @event_interface: event chrdevs associated with interrupt lines +@@ -42,6 +43,7 @@ struct iio_dev_opaque { + int currentmode; + int id; + struct module *driver_module; ++ struct lock_class_key mlock_key; + struct mutex info_exist_lock; + bool trig_readonly; + struct iio_event_interface *event_interface; +-- +2.35.1 + diff --git a/queue-5.19/ima-fix-blocking-of-security.ima-xattrs-of-unsupport.patch b/queue-5.19/ima-fix-blocking-of-security.ima-xattrs-of-unsupport.patch new file mode 100644 index 00000000000..68a39c6ea28 --- /dev/null +++ b/queue-5.19/ima-fix-blocking-of-security.ima-xattrs-of-unsupport.patch @@ -0,0 +1,60 @@ +From 4c14ebfea843c1532d392364f579e64aa521b6f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Aug 2022 17:18:42 -0400 +Subject: ima: fix blocking of security.ima xattrs of unsupported algorithms + +From: Mimi Zohar + +[ Upstream commit 5926586f291b53cb8a0c9631fc19489be1186e2d ] + +Limit validating the hash algorithm to just security.ima xattr, not +the security.evm xattr or any of the protected EVM security xattrs, +nor posix acls. + +Fixes: 50f742dd9147 ("IMA: block writes of the security.ima xattr with unsupported algorithms") +Reported-by: Christian Brauner +Acked-by: Christian Brauner (Microsoft) +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/ima_appraise.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c +index bde74fcecee3..3e0fbbd99534 100644 +--- a/security/integrity/ima/ima_appraise.c ++++ b/security/integrity/ima/ima_appraise.c +@@ -750,22 +750,26 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, + const struct evm_ima_xattr_data *xvalue = xattr_value; + int digsig = 0; + int result; ++ int err; + + result = ima_protect_xattr(dentry, xattr_name, xattr_value, + xattr_value_len); + if (result == 1) { + if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) + return -EINVAL; ++ ++ err = validate_hash_algo(dentry, xvalue, xattr_value_len); ++ if (err) ++ return err; ++ + digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG); + } else if (!strcmp(xattr_name, XATTR_NAME_EVM) && xattr_value_len > 0) { + digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG); + } + if (result == 1 || evm_revalidate_status(xattr_name)) { +- result = validate_hash_algo(dentry, xvalue, xattr_value_len); +- if (result) +- return result; +- + ima_reset_appraise_flags(d_backing_inode(dentry), digsig); ++ if (result == 1) ++ result = 0; + } + return result; + } +-- +2.35.1 + diff --git a/queue-5.19/iomap-iomap-fix-memory-corruption-when-recording-err.patch b/queue-5.19/iomap-iomap-fix-memory-corruption-when-recording-err.patch new file mode 100644 index 00000000000..1b1fd840eb1 --- /dev/null +++ b/queue-5.19/iomap-iomap-fix-memory-corruption-when-recording-err.patch @@ -0,0 +1,143 @@ +From c5df7cf26f09f93ac1d3a95c0130bfd3d3e1512f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 17:02:32 -0700 +Subject: iomap: iomap: fix memory corruption when recording errors during + writeback + +From: Darrick J. Wong + +[ Upstream commit 3d5f3ba1ac28059bdf7000cae2403e4e984308d2 ] + +Every now and then I see this crash on arm64: + +Unable to handle kernel NULL pointer dereference at virtual address 00000000000000f8 +Buffer I/O error on dev dm-0, logical block 8733687, async page read +Mem abort info: + ESR = 0x0000000096000006 + 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 +user pgtable: 64k pages, 42-bit VAs, pgdp=0000000139750000 +[00000000000000f8] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000, pmd=0000000000000000 +Internal error: Oops: 96000006 [#1] PREEMPT SMP +Buffer I/O error on dev dm-0, logical block 8733688, async page read +Dumping ftrace buffer: +Buffer I/O error on dev dm-0, logical block 8733689, async page read + (ftrace buffer empty) +XFS (dm-0): log I/O error -5 +Modules linked in: dm_thin_pool dm_persistent_data +XFS (dm-0): Metadata I/O Error (0x1) detected at xfs_trans_read_buf_map+0x1ec/0x590 [xfs] (fs/xfs/xfs_trans_buf.c:296). + dm_bio_prison +XFS (dm-0): Please unmount the filesystem and rectify the problem(s) +XFS (dm-0): xfs_imap_lookup: xfs_ialloc_read_agi() returned error -5, agno 0 + dm_bufio dm_log_writes xfs nft_chain_nat xt_REDIRECT nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip6t_REJECT +potentially unexpected fatal signal 6. + nf_reject_ipv6 +potentially unexpected fatal signal 6. + ipt_REJECT nf_reject_ipv4 +CPU: 1 PID: 122166 Comm: fsstress Tainted: G W 6.0.0-rc5-djwa #rc5 3004c9f1de887ebae86015f2677638ce51ee7 + rpcsec_gss_krb5 auth_rpcgss xt_tcpudp ip_set_hash_ip ip_set_hash_net xt_set nft_compat ip_set_hash_mac ip_set nf_tables +Hardware name: QEMU KVM Virtual Machine, BIOS 1.5.1 06/16/2021 +pstate: 60001000 (nZCv daif -PAN -UAO -TCO -DIT +SSBS BTYPE=--) + ip_tables +pc : 000003fd6d7df200 + x_tables +lr : 000003fd6d7df1ec + overlay nfsv4 +CPU: 0 PID: 54031 Comm: u4:3 Tainted: G W 6.0.0-rc5-djwa #rc5 3004c9f1de887ebae86015f2677638ce51ee7405 +Hardware name: QEMU KVM Virtual Machine, BIOS 1.5.1 06/16/2021 +Workqueue: writeback wb_workfn +sp : 000003ffd9522fd0 + (flush-253:0) +pstate: 60401005 (nZCv daif +PAN -UAO -TCO -DIT +SSBS BTYPE=--) +pc : errseq_set+0x1c/0x100 +x29: 000003ffd9522fd0 x28: 0000000000000023 x27: 000002acefeb6780 +x26: 0000000000000005 x25: 0000000000000001 x24: 0000000000000000 +x23: 00000000ffffffff x22: 0000000000000005 +lr : __filemap_set_wb_err+0x24/0xe0 + x21: 0000000000000006 +sp : fffffe000f80f760 +x29: fffffe000f80f760 x28: 0000000000000003 x27: fffffe000f80f9f8 +x26: 0000000002523000 x25: 00000000fffffffb x24: fffffe000f80f868 +x23: fffffe000f80fbb0 x22: fffffc0180c26a78 x21: 0000000002530000 +x20: 0000000000000000 x19: 0000000000000000 x18: 0000000000000000 + +x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 +x14: 0000000000000001 x13: 0000000000470af3 x12: fffffc0058f70000 +x11: 0000000000000040 x10: 0000000000001b20 x9 : fffffe000836b288 +x8 : fffffc00eb9fd480 x7 : 0000000000f83659 x6 : 0000000000000000 +x5 : 0000000000000869 x4 : 0000000000000005 x3 : 00000000000000f8 +x20: 000003fd6d740020 x19: 000000000001dd36 x18: 0000000000000001 +x17: 000003fd6d78704c x16: 0000000000000001 x15: 000002acfac87668 +x2 : 0000000000000ffa x1 : 00000000fffffffb x0 : 00000000000000f8 +Call trace: + errseq_set+0x1c/0x100 + __filemap_set_wb_err+0x24/0xe0 + iomap_do_writepage+0x5e4/0xd5c + write_cache_pages+0x208/0x674 + iomap_writepages+0x34/0x60 + xfs_vm_writepages+0x8c/0xcc [xfs 7a861f39c43631f15d3a5884246ba5035d4ca78b] +x14: 0000000000000000 x13: 2064656e72757465 x12: 0000000000002180 +x11: 000003fd6d8a82d0 x10: 0000000000000000 x9 : 000003fd6d8ae288 +x8 : 0000000000000083 x7 : 00000000ffffffff x6 : 00000000ffffffee +x5 : 00000000fbad2887 x4 : 000003fd6d9abb58 x3 : 000003fd6d740020 +x2 : 0000000000000006 x1 : 000000000001dd36 x0 : 0000000000000000 +CPU: 1 PID: 122167 Comm: fsstress Tainted: G W 6.0.0-rc5-djwa #rc5 3004c9f1de887ebae86015f2677638ce51ee7 + do_writepages+0x90/0x1c4 + __writeback_single_inode+0x4c/0x4ac +Hardware name: QEMU KVM Virtual Machine, BIOS 1.5.1 06/16/2021 + writeback_sb_inodes+0x214/0x4ac + wb_writeback+0xf4/0x3b0 +pstate: 60001000 (nZCv daif -PAN -UAO -TCO -DIT +SSBS BTYPE=--) + wb_workfn+0xfc/0x580 + process_one_work+0x1e8/0x480 +pc : 000003fd6d7df200 + worker_thread+0x78/0x430 + +This crash is a result of iomap_writepage_map encountering some sort of +error during writeback and wanting to set that error code in the file +mapping so that fsync will report it. Unfortunately, the code +dereferences folio->mapping after unlocking the folio, which means that +another thread could have removed the page from the page cache +(writeback doesn't hold the invalidation lock) and give it to somebody +else. + +At best we crash the system like above; at worst, we corrupt memory or +set an error on some other unsuspecting file while failing to record the +problems with *this* file. Regardless, fix the problem by reporting the +error to the inode mapping. + +NOTE: Commit 598ecfbaa742 lifted the XFS writeback code to iomap, so +this fix should be backported to XFS in the 4.6-5.4 kernels in addition +to iomap in the 5.5-5.19 kernels. + +Fixes: e735c0079465 ("iomap: Convert iomap_add_to_ioend() to take a folio") # 5.17 onward +Fixes: 598ecfbaa742 ("iomap: lift the xfs writeback code to iomap") # 5.5-5.16, needs backporting +Fixes: 150d5be09ce4 ("xfs: remove xfs_cancel_ioend") # 4.6-5.4, needs backporting +Signed-off-by: Darrick J. Wong +Reviewed-by: Matthew Wilcox (Oracle) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index d2a9f699e17e..f2f102dd5e6b 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -1412,7 +1412,7 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc, + if (!count) + folio_end_writeback(folio); + done: +- mapping_set_error(folio->mapping, error); ++ mapping_set_error(inode->i_mapping, error); + return error; + } + +-- +2.35.1 + diff --git a/queue-5.19/iommu-arm-smmu-v3-make-default-domain-type-of-hisili.patch b/queue-5.19/iommu-arm-smmu-v3-make-default-domain-type-of-hisili.patch new file mode 100644 index 00000000000..f07ea2d6669 --- /dev/null +++ b/queue-5.19/iommu-arm-smmu-v3-make-default-domain-type-of-hisili.patch @@ -0,0 +1,66 @@ +From 1a511d0266782078bd46151effbc344984dd4141 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 19:44:10 +0800 +Subject: iommu/arm-smmu-v3: Make default domain type of HiSilicon PTT device + to identity + +From: Yicong Yang + +[ Upstream commit 24b6c7798a0122012ca848ea0d25e973334266b0 ] + +The DMA operations of HiSilicon PTT device can only work properly with +identical mappings. So add a quirk for the device to force the domain +as passthrough. + +Acked-by: Will Deacon +Signed-off-by: Yicong Yang +Reviewed-by: John Garry +Link: https://lore.kernel.org/r/20220816114414.4092-2-yangyicong@huawei.com +Signed-off-by: Mathieu Poirier +Signed-off-by: Sasha Levin +--- + drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +index 88817a3376ef..e119ff8396c9 100644 +--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c ++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +@@ -2839,6 +2839,26 @@ static int arm_smmu_dev_disable_feature(struct device *dev, + } + } + ++/* ++ * HiSilicon PCIe tune and trace device can be used to trace TLP headers on the ++ * PCIe link and save the data to memory by DMA. The hardware is restricted to ++ * use identity mapping only. ++ */ ++#define IS_HISI_PTT_DEVICE(pdev) ((pdev)->vendor == PCI_VENDOR_ID_HUAWEI && \ ++ (pdev)->device == 0xa12e) ++ ++static int arm_smmu_def_domain_type(struct device *dev) ++{ ++ if (dev_is_pci(dev)) { ++ struct pci_dev *pdev = to_pci_dev(dev); ++ ++ if (IS_HISI_PTT_DEVICE(pdev)) ++ return IOMMU_DOMAIN_IDENTITY; ++ } ++ ++ return 0; ++} ++ + static struct iommu_ops arm_smmu_ops = { + .capable = arm_smmu_capable, + .domain_alloc = arm_smmu_domain_alloc, +@@ -2856,6 +2876,7 @@ static struct iommu_ops arm_smmu_ops = { + .sva_unbind = arm_smmu_sva_unbind, + .sva_get_pasid = arm_smmu_sva_get_pasid, + .page_response = arm_smmu_page_response, ++ .def_domain_type = arm_smmu_def_domain_type, + .pgsize_bitmap = -1UL, /* Restricted during device attach */ + .owner = THIS_MODULE, + .default_domain_ops = &(const struct iommu_domain_ops) { +-- +2.35.1 + diff --git a/queue-5.19/iommu-iova-fix-module-config-properly.patch b/queue-5.19/iommu-iova-fix-module-config-properly.patch new file mode 100644 index 00000000000..59f30e27bbb --- /dev/null +++ b/queue-5.19/iommu-iova-fix-module-config-properly.patch @@ -0,0 +1,43 @@ +From fc95324077e314a39b69aeb4df1a1d2f986dd757 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 12:47:20 +0100 +Subject: iommu/iova: Fix module config properly + +From: Robin Murphy + +[ Upstream commit 4f58330fcc8482aa90674e1f40f601e82f18ed4a ] + +IOMMU_IOVA is intended to be an optional library for users to select as +and when they desire. Since it can be a module now, this means that +built-in code which has chosen not to select it should not fail to link +if it happens to have selected as a module by someone else. Replace +IS_ENABLED() with IS_REACHABLE() to do the right thing. + +CC: Thierry Reding +Reported-by: John Garry +Fixes: 15bbdec3931e ("iommu: Make the iova library a module") +Signed-off-by: Robin Murphy +Reviewed-by: Thierry Reding +Link: https://lore.kernel.org/r/548c2f683ca379aface59639a8f0cccc3a1ac050.1663069227.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + include/linux/iova.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/iova.h b/include/linux/iova.h +index 320a70e40233..f1dba47cfc97 100644 +--- a/include/linux/iova.h ++++ b/include/linux/iova.h +@@ -75,7 +75,7 @@ static inline unsigned long iova_pfn(struct iova_domain *iovad, dma_addr_t iova) + return iova >> iova_shift(iovad); + } + +-#if IS_ENABLED(CONFIG_IOMMU_IOVA) ++#if IS_REACHABLE(CONFIG_IOMMU_IOVA) + int iova_cache_get(void); + void iova_cache_put(void); + +-- +2.35.1 + diff --git a/queue-5.19/iommu-omap-fix-buffer-overflow-in-debugfs.patch b/queue-5.19/iommu-omap-fix-buffer-overflow-in-debugfs.patch new file mode 100644 index 00000000000..5bbeee17c57 --- /dev/null +++ b/queue-5.19/iommu-omap-fix-buffer-overflow-in-debugfs.patch @@ -0,0 +1,53 @@ +From 4572fb7b7a0b4dcaf89f32fe6941f5890f675554 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Aug 2022 17:32:39 +0300 +Subject: iommu/omap: Fix buffer overflow in debugfs + +From: Dan Carpenter + +[ Upstream commit 184233a5202786b20220acd2d04ddf909ef18f29 ] + +There are two issues here: + +1) The "len" variable needs to be checked before the very first write. + Otherwise if omap2_iommu_dump_ctx() with "bytes" less than 32 it is a + buffer overflow. +2) The snprintf() function returns the number of bytes that *would* have + been copied if there were enough space. But we want to know the + number of bytes which were *actually* copied so use scnprintf() + instead. + +Fixes: bd4396f09a4a ("iommu/omap: Consolidate OMAP IOMMU modules") +Signed-off-by: Dan Carpenter +Reviewed-by: Robin Murphy +Reviewed-by: Laurent Pinchart +Link: https://lore.kernel.org/r/YuvYh1JbE3v+abd5@kili +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/omap-iommu-debug.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c +index a99afb5d9011..259f65291d90 100644 +--- a/drivers/iommu/omap-iommu-debug.c ++++ b/drivers/iommu/omap-iommu-debug.c +@@ -32,12 +32,12 @@ static inline bool is_omap_iommu_detached(struct omap_iommu *obj) + ssize_t bytes; \ + const char *str = "%20s: %08x\n"; \ + const int maxcol = 32; \ +- bytes = snprintf(p, maxcol, str, __stringify(name), \ ++ if (len < maxcol) \ ++ goto out; \ ++ bytes = scnprintf(p, maxcol, str, __stringify(name), \ + iommu_read_reg(obj, MMU_##name)); \ + p += bytes; \ + len -= bytes; \ +- if (len < maxcol) \ +- goto out; \ + } while (0) + + static ssize_t +-- +2.35.1 + diff --git a/queue-5.19/ipc-mqueue-fix-possible-memory-leak-in-init_mqueue_f.patch b/queue-5.19/ipc-mqueue-fix-possible-memory-leak-in-init_mqueue_f.patch new file mode 100644 index 00000000000..77c59c30569 --- /dev/null +++ b/queue-5.19/ipc-mqueue-fix-possible-memory-leak-in-init_mqueue_f.patch @@ -0,0 +1,40 @@ +From c83978001b135a271a33b949a1f6717919a6ab66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Jul 2022 14:23:01 +0800 +Subject: ipc: mqueue: fix possible memory leak in init_mqueue_fs() + +From: Hangyu Hua + +[ Upstream commit c579d60f0d0cd87552f64fdebe68b5d941d20309 ] + +commit db7cfc380900 ("ipc: Free mq_sysctls if ipc namespace creation +failed") + +Here's a similar memory leak to the one fixed by the patch above. +retire_mq_sysctls need to be called when init_mqueue_fs fails after +setup_mq_sysctls. + +Fixes: dc55e35f9e81 ("ipc: Store mqueue sysctls in the ipc namespace") +Signed-off-by: Hangyu Hua +Link: https://lkml.kernel.org/r/20220715062301.19311-1-hbh25y@gmail.com +Signed-off-by: Eric W. Biederman +Signed-off-by: Sasha Levin +--- + ipc/mqueue.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ipc/mqueue.c b/ipc/mqueue.c +index 12ad7860bb88..83370fef8879 100644 +--- a/ipc/mqueue.c ++++ b/ipc/mqueue.c +@@ -1746,6 +1746,7 @@ static int __init init_mqueue_fs(void) + unregister_filesystem(&mqueue_fs_type); + out_sysctl: + kmem_cache_destroy(mqueue_inode_cachep); ++ retire_mq_sysctls(&init_ipc_ns); + return error; + } + +-- +2.35.1 + diff --git a/queue-5.19/kbuild-remove-the-target-in-signal-traps-when-interr.patch b/queue-5.19/kbuild-remove-the-target-in-signal-traps-when-interr.patch new file mode 100644 index 00000000000..de77d937217 --- /dev/null +++ b/queue-5.19/kbuild-remove-the-target-in-signal-traps-when-interr.patch @@ -0,0 +1,172 @@ +From 5d8208bcb258b38624d0cba584fbac48ff892cae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 7 Aug 2022 09:48:09 +0900 +Subject: kbuild: remove the target in signal traps when interrupted + +From: Masahiro Yamada + +[ Upstream commit a7f3257da8a86b96fb9bf1bba40ae0bbd7f1885a ] + +When receiving some signal, GNU Make automatically deletes the target if +it has already been changed by the interrupted recipe. + +If the target is possibly incomplete due to interruption, it must be +deleted so that it will be remade from scratch on the next run of make. +Otherwise, the target would remain corrupted permanently because its +timestamp had already been updated. + +Thanks to this behavior of Make, you can stop the build any time by +pressing Ctrl-C, and just run 'make' to resume it. + +Kbuild also relies on this feature, but it is equivalently important +for any build systems that make decisions based on timestamps (if you +want to support Ctrl-C reliably). + +However, this does not always work as claimed; Make immediately dies +with Ctrl-C if its stderr goes into a pipe. + + [Test Makefile] + + foo: + echo hello > $@ + sleep 3 + echo world >> $@ + + [Test Result] + + $ make # hit Ctrl-C + echo hello > foo + sleep 3 + ^Cmake: *** Deleting file 'foo' + make: *** [Makefile:3: foo] Interrupt + + $ make 2>&1 | cat # hit Ctrl-C + echo hello > foo + sleep 3 + ^C$ # 'foo' is often left-over + +The reason is because SIGINT is sent to the entire process group. +In this example, SIGINT kills 'cat', and 'make' writes the message to +the closed pipe, then dies with SIGPIPE before cleaning the target. + +A typical bad scenario (as reported by [1], [2]) is to save build log +by using the 'tee' command: + + $ make 2>&1 | tee log + +This can be problematic for any build systems based on Make, so I hope +it will be fixed in GNU Make. The maintainer of GNU Make stated this is +a long-standing issue and difficult to fix [3]. It has not been fixed +yet as of writing. + +So, we cannot rely on Make cleaning the target. We can do it by +ourselves, in signal traps. + +As far as I understand, Make takes care of SIGHUP, SIGINT, SIGQUIT, and +SITERM for the target removal. I added the traps for them, and also for +SIGPIPE just in case cmd_* rule prints something to stdout or stderr +(but I did not observe an actual case where SIGPIPE was triggered). + +[Note 1] + +The trap handler might be worth explaining. + + rm -f $@; trap - $(sig); kill -s $(sig) $$ + +This lets the shell kill itself by the signal it caught, so the parent +process can tell the child has exited on the signal. Generally, this is +a proper manner for handling signals, in case the calling program (like +Bash) may monitor WIFSIGNALED() and WTERMSIG() for WCE although this may +not be a big deal here because GNU Make handles SIGHUP, SIGINT, SIGQUIT +in WUE and SIGTERM in IUE. + + IUE - Immediate Unconditional Exit + WUE - Wait and Unconditional Exit + WCE - Wait and Cooperative Exit + +For details, see "Proper handling of SIGINT/SIGQUIT" [4]. + +[Note 2] + +Reverting 392885ee82d3 ("kbuild: let fixdep directly write to .*.cmd +files") would directly address [1], but it only saves if_changed_dep. +As reported in [2], all commands that use redirection can potentially +leave an empty (i.e. broken) target. + +[Note 3] + +Another (even safer) approach might be to always write to a temporary +file, and rename it to $@ at the end of the recipe. + + > $(tmp-target) + mv $(tmp-target) $@ + +It would require a lot of Makefile changes, and result in ugly code, +so I did not take it. + +[Note 4] + +A little more thoughts about a pattern rule with multiple targets (or +a grouped target). + + %.x %.y: %.z + + +When interrupted, GNU Make deletes both %.x and %.y, while this solution +only deletes $@. Probably, this is not a big deal. The next run of make +will execute the rule again to create $@ along with the other files. + +[1]: https://lore.kernel.org/all/YLeot94yAaM4xbMY@gmail.com/ +[2]: https://lore.kernel.org/all/20220510221333.2770571-1-robh@kernel.org/ +[3]: https://lists.gnu.org/archive/html/help-make/2021-06/msg00001.html +[4]: https://www.cons.org/cracauer/sigint.html + +Fixes: 392885ee82d3 ("kbuild: let fixdep directly write to .*.cmd files") +Reported-by: Ingo Molnar +Reported-by: Rob Herring +Signed-off-by: Masahiro Yamada +Tested-by: Ingo Molnar +Reviewed-by: Nicolas Schier +Signed-off-by: Sasha Levin +--- + scripts/Kbuild.include | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include +index ece44b735061..2bc08ace38a3 100644 +--- a/scripts/Kbuild.include ++++ b/scripts/Kbuild.include +@@ -100,8 +100,29 @@ echo-cmd = $(if $($(quiet)cmd_$(1)),\ + quiet_redirect := + silent_redirect := exec >/dev/null; + ++# Delete the target on interruption ++# ++# GNU Make automatically deletes the target if it has already been changed by ++# the interrupted recipe. So, you can safely stop the build by Ctrl-C (Make ++# will delete incomplete targets), and resume it later. ++# ++# However, this does not work when the stderr is piped to another program, like ++# $ make >&2 | tee log ++# Make dies with SIGPIPE before cleaning the targets. ++# ++# To address it, we clean the target in signal traps. ++# ++# Make deletes the target when it catches SIGHUP, SIGINT, SIGQUIT, SIGTERM. ++# So, we cover them, and also SIGPIPE just in case. ++# ++# Of course, this is unneeded for phony targets. ++delete-on-interrupt = \ ++ $(if $(filter-out $(PHONY), $@), \ ++ $(foreach sig, HUP INT QUIT TERM PIPE, \ ++ trap 'rm -f $@; trap - $(sig); kill -s $(sig) $$$$' $(sig);)) ++ + # printing commands +-cmd = @set -e; $(echo-cmd) $($(quiet)redirect) $(cmd_$(1)) ++cmd = @set -e; $(echo-cmd) $($(quiet)redirect) $(delete-on-interrupt) $(cmd_$(1)) + + ### + # if_changed - execute command if any prerequisite is newer than +-- +2.35.1 + diff --git a/queue-5.19/kbuild-rpm-pkg-fix-breakage-when-v-1-is-used.patch b/queue-5.19/kbuild-rpm-pkg-fix-breakage-when-v-1-is-used.patch new file mode 100644 index 00000000000..e94a604ab51 --- /dev/null +++ b/queue-5.19/kbuild-rpm-pkg-fix-breakage-when-v-1-is-used.patch @@ -0,0 +1,55 @@ +From 33c95543c72907eaa78f43ab4314e8f5daa34883 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 14:41:12 +0200 +Subject: kbuild: rpm-pkg: fix breakage when V=1 is used + +From: Janis Schoetterl-Glausch + +[ Upstream commit 2e07005f4813a9ff6e895787e0c2d1fea859b033 ] + +Doing make V=1 binrpm-pkg results in: + + Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.EgV6qJ + + umask 022 + + cd . + + /bin/rm -rf /home/scgl/rpmbuild/BUILDROOT/kernel-6.0.0_rc5+-1.s390x + + /bin/mkdir -p /home/scgl/rpmbuild/BUILDROOT + + /bin/mkdir /home/scgl/rpmbuild/BUILDROOT/kernel-6.0.0_rc5+-1.s390x + + mkdir -p /home/scgl/rpmbuild/BUILDROOT/kernel-6.0.0_rc5+-1.s390x/boot + + make -f ./Makefile image_name + + cp test -e include/generated/autoconf.h -a -e include/config/auto.conf || ( \ echo >&2; \ echo >&2 " ERROR: Kernel configuration is invalid."; \ echo >&2 " include/generated/autoconf.h or include/config/auto.conf are missing.";\ echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ echo >&2 ; \ /bin/false) arch/s390/boot/bzImage /home/scgl/rpmbuild/BUILDROOT/kernel-6.0.0_rc5+-1.s390x/boot/vmlinuz-6.0.0-rc5+ + cp: invalid option -- 'e' + Try 'cp --help' for more information. + error: Bad exit status from /var/tmp/rpm-tmp.EgV6qJ (%install) + +Because the make call to get the image name is verbose and prints +additional information. + +Fixes: 993bdde94547 ("kbuild: add image_name to no-sync-config-targets") +Signed-off-by: Janis Schoetterl-Glausch +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/package/mkspec | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/package/mkspec b/scripts/package/mkspec +index 7c477ca7dc98..951cc60e5a90 100755 +--- a/scripts/package/mkspec ++++ b/scripts/package/mkspec +@@ -85,10 +85,10 @@ $S + mkdir -p %{buildroot}/boot + %ifarch ia64 + mkdir -p %{buildroot}/boot/efi +- cp \$($MAKE image_name) %{buildroot}/boot/efi/vmlinuz-$KERNELRELEASE ++ cp \$($MAKE -s image_name) %{buildroot}/boot/efi/vmlinuz-$KERNELRELEASE + ln -s efi/vmlinuz-$KERNELRELEASE %{buildroot}/boot/ + %else +- cp \$($MAKE image_name) %{buildroot}/boot/vmlinuz-$KERNELRELEASE ++ cp \$($MAKE -s image_name) %{buildroot}/boot/vmlinuz-$KERNELRELEASE + %endif + $M $MAKE %{?_smp_mflags} INSTALL_MOD_PATH=%{buildroot} modules_install + $MAKE %{?_smp_mflags} INSTALL_HDR_PATH=%{buildroot}/usr headers_install +-- +2.35.1 + diff --git a/queue-5.19/kselftest-arm64-fix-validatation-termination-record-.patch b/queue-5.19/kselftest-arm64-fix-validatation-termination-record-.patch new file mode 100644 index 00000000000..af16e39deb8 --- /dev/null +++ b/queue-5.19/kselftest-arm64-fix-validatation-termination-record-.patch @@ -0,0 +1,47 @@ +From 1af5d245a8a8080a458bc702206e1afd4a6327c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 17:06:56 +0100 +Subject: kselftest/arm64: Fix validatation termination record after + EXTRA_CONTEXT + +From: Mark Brown + +[ Upstream commit 5c152c2f66f9368394b89ac90dc7483476ef7b88 ] + +When arm64 signal context data overflows the base struct sigcontext it gets +placed in an extra buffer pointed to by a record of type EXTRA_CONTEXT in +the base struct sigcontext which is required to be the last record in the +base struct sigframe. The current validation code attempts to check this +by using GET_RESV_NEXT_HEAD() to step forward from the current record to +the next but that is a macro which assumes it is being provided with a +struct _aarch64_ctx and uses the size there to skip forward to the next +record. Instead validate_extra_context() passes it a struct extra_context +which has a separate size field. This compiles but results in us trying +to validate a termination record in completely the wrong place, at best +failing validation and at worst just segfaulting. Fix this by passing +the struct _aarch64_ctx we meant to into the macro. + +Signed-off-by: Mark Brown +Link: https://lore.kernel.org/r/20220829160703.874492-4-broonie@kernel.org +Signed-off-by: Catalin Marinas +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/arm64/signal/testcases/testcases.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c +index 84c36bee4d82..d98828cb542b 100644 +--- a/tools/testing/selftests/arm64/signal/testcases/testcases.c ++++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c +@@ -33,7 +33,7 @@ bool validate_extra_context(struct extra_context *extra, char **err) + return false; + + fprintf(stderr, "Validating EXTRA...\n"); +- term = GET_RESV_NEXT_HEAD(extra); ++ term = GET_RESV_NEXT_HEAD(&extra->head); + if (!term || term->magic || term->size) { + *err = "Missing terminator after EXTRA context"; + return false; +-- +2.35.1 + diff --git a/queue-5.19/kvm-fix-memoryleak-in-kvm_init.patch b/queue-5.19/kvm-fix-memoryleak-in-kvm_init.patch new file mode 100644 index 00000000000..b55f3eb11be --- /dev/null +++ b/queue-5.19/kvm-fix-memoryleak-in-kvm_init.patch @@ -0,0 +1,51 @@ +From e7c08126135755d19a80390659f07d911eb6b9ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 14:34:14 +0800 +Subject: KVM: fix memoryleak in kvm_init() + +From: Miaohe Lin + +[ Upstream commit 5a2a961be2ad6a16eb388a80442443b353c11d16 ] + +When alloc_cpumask_var_node() fails for a certain cpu, there might be some +allocated cpumasks for percpu cpu_kick_mask. We should free these cpumasks +or memoryleak will occur. + +Fixes: baff59ccdc65 ("KVM: Pre-allocate cpumasks for kvm_make_all_cpus_request_except()") +Signed-off-by: Miaohe Lin +Link: https://lore.kernel.org/r/20220823063414.59778-1-linmiaohe@huawei.com +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + virt/kvm/kvm_main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index c56861ed0e38..4afa94f55d7e 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -5783,7 +5783,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, + + r = kvm_async_pf_init(); + if (r) +- goto out_free_5; ++ goto out_free_4; + + kvm_chardev_ops.owner = module; + +@@ -5807,10 +5807,9 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, + + out_unreg: + kvm_async_pf_deinit(); +-out_free_5: ++out_free_4: + for_each_possible_cpu(cpu) + free_cpumask_var(per_cpu(cpu_kick_mask, cpu)); +-out_free_4: + kmem_cache_destroy(kvm_vcpu_cache); + out_free_3: + unregister_reboot_notifier(&kvm_reboot_notifier); +-- +2.35.1 + diff --git a/queue-5.19/kvm-nvmx-ignore-sipi-that-arrives-in-l2-when-vcpu-is.patch b/queue-5.19/kvm-nvmx-ignore-sipi-that-arrives-in-l2-when-vcpu-is.patch new file mode 100644 index 00000000000..f1d3f0aa75f --- /dev/null +++ b/queue-5.19/kvm-nvmx-ignore-sipi-that-arrives-in-l2-when-vcpu-is.patch @@ -0,0 +1,47 @@ +From f0fb08f9b370a8b01dde14a520c007b0adbacff4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 23:15:57 +0000 +Subject: KVM: nVMX: Ignore SIPI that arrives in L2 when vCPU is not in WFS + +From: Sean Christopherson + +[ Upstream commit c2086eca86585bfd8132dd91e802497a202185c8 ] + +Fall through to handling other pending exception/events for L2 if SIPI +is pending while the CPU is not in Wait-for-SIPI. KVM correctly ignores +the event, but incorrectly returns immediately, e.g. a SIPI coincident +with another event could lead to KVM incorrectly routing the event to L1 +instead of L2. + +Fixes: bf0cd88ce363 ("KVM: x86: emulate wait-for-SIPI and SIPI-VMExit") +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-11-seanjc@google.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx/nested.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index 3bf00684f6cc..fdf31c7f61e5 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -3944,10 +3944,12 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + return -EBUSY; + + clear_bit(KVM_APIC_SIPI, &apic->pending_events); +- if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) ++ if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { + nested_vmx_vmexit(vcpu, EXIT_REASON_SIPI_SIGNAL, 0, + apic->sipi_vector & 0xFFUL); +- return 0; ++ return 0; ++ } ++ /* Fallthrough, the SIPI is completely ignored. */ + } + + /* +-- +2.35.1 + diff --git a/queue-5.19/kvm-nvmx-prioritize-tss-t-flag-dbs-over-monitor-trap.patch b/queue-5.19/kvm-nvmx-prioritize-tss-t-flag-dbs-over-monitor-trap.patch new file mode 100644 index 00000000000..beee8e1d82a --- /dev/null +++ b/queue-5.19/kvm-nvmx-prioritize-tss-t-flag-dbs-over-monitor-trap.patch @@ -0,0 +1,58 @@ +From a9eb67021e41d9cfe3c92a21906c40d55d0c546d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 23:15:54 +0000 +Subject: KVM: nVMX: Prioritize TSS T-flag #DBs over Monitor Trap Flag + +From: Sean Christopherson + +[ Upstream commit b9d44f9091ac6c325fc2f7b7671b462fb36abbed ] + +Service TSS T-flag #DBs prior to pending MTFs, as such #DBs are higher +priority than MTF. KVM itself doesn't emulate TSS #DBs, and any such +exceptions injected from L1 will be handled by hardware (or morphed to +a fault-like exception if injection fails), but theoretically userspace +could pend a TSS T-flag #DB in conjunction with a pending MTF. + +Note, there's no known use case this fixes, it's purely to be technically +correct with respect to Intel's SDM. + +Cc: Oliver Upton +Cc: Peter Shier +Fixes: 5ef8acbdd687 ("KVM: nVMX: Emulate MTF when performing instruction emulation") +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-8-seanjc@google.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx/nested.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index c669a892e386..3bf00684f6cc 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -3951,15 +3951,17 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + } + + /* +- * Process any exceptions that are not debug traps before MTF. ++ * Process exceptions that are higher priority than Monitor Trap Flag: ++ * fault-like exceptions, TSS T flag #DB (not emulated by KVM, but ++ * could theoretically come in from userspace), and ICEBP (INT1). + * + * Note that only a pending nested run can block a pending exception. + * Otherwise an injected NMI/interrupt should either be + * lost or delivered to the nested hypervisor in the IDT_VECTORING_INFO, + * while delivering the pending exception. + */ +- +- if (vcpu->arch.exception.pending && !vmx_get_pending_dbg_trap(vcpu)) { ++ if (vcpu->arch.exception.pending && ++ !(vmx_get_pending_dbg_trap(vcpu) & ~DR6_BT)) { + if (vmx->nested.nested_run_pending) + return -EBUSY; + if (!nested_vmx_check_exception(vcpu, &exit_qual)) +-- +2.35.1 + diff --git a/queue-5.19/kvm-nvmx-treat-general-detect-db-dr7.gd-1-as-fault-l.patch b/queue-5.19/kvm-nvmx-treat-general-detect-db-dr7.gd-1-as-fault-l.patch new file mode 100644 index 00000000000..c11f60ab0da --- /dev/null +++ b/queue-5.19/kvm-nvmx-treat-general-detect-db-dr7.gd-1-as-fault-l.patch @@ -0,0 +1,95 @@ +From 0366dd2c26cb455888fdbe1332c30b100c4d2972 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 23:15:53 +0000 +Subject: KVM: nVMX: Treat General Detect #DB (DR7.GD=1) as fault-like + +From: Sean Christopherson + +[ Upstream commit 8d178f460772ecdee8e6d72389b43a8d35a14ff5 ] + +Exclude General Detect #DBs, which have fault-like behavior but also have +a non-zero payload (DR6.BD=1), from nVMX's handling of pending debug +traps. Opportunistically rewrite the comment to better document what is +being checked, i.e. "has a non-zero payload" vs. "has a payload", and to +call out the many caveats surrounding #DBs that KVM dodges one way or +another. + +Cc: Oliver Upton +Cc: Peter Shier +Fixes: 684c0422da71 ("KVM: nVMX: Handle pending #DB when injecting INIT VM-exit") +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-7-seanjc@google.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx/nested.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index b98b8cede264..c669a892e386 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -3865,16 +3865,29 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu, + } + + /* +- * Returns true if a debug trap is pending delivery. ++ * Returns true if a debug trap is (likely) pending delivery. Infer the class ++ * of a #DB (trap-like vs. fault-like) from the exception payload (to-be-DR6). ++ * Using the payload is flawed because code breakpoints (fault-like) and data ++ * breakpoints (trap-like) set the same bits in DR6 (breakpoint detected), i.e. ++ * this will return false positives if a to-be-injected code breakpoint #DB is ++ * pending (from KVM's perspective, but not "pending" across an instruction ++ * boundary). ICEBP, a.k.a. INT1, is also not reflected here even though it ++ * too is trap-like. + * +- * In KVM, debug traps bear an exception payload. As such, the class of a #DB +- * exception may be inferred from the presence of an exception payload. ++ * KVM "works" despite these flaws as ICEBP isn't currently supported by the ++ * emulator, Monitor Trap Flag is not marked pending on intercepted #DBs (the ++ * #DB has already happened), and MTF isn't marked pending on code breakpoints ++ * from the emulator (because such #DBs are fault-like and thus don't trigger ++ * actions that fire on instruction retire). + */ +-static inline bool vmx_pending_dbg_trap(struct kvm_vcpu *vcpu) ++static inline unsigned long vmx_get_pending_dbg_trap(struct kvm_vcpu *vcpu) + { +- return vcpu->arch.exception.pending && +- vcpu->arch.exception.nr == DB_VECTOR && +- vcpu->arch.exception.payload; ++ if (!vcpu->arch.exception.pending || ++ vcpu->arch.exception.nr != DB_VECTOR) ++ return 0; ++ ++ /* General Detect #DBs are always fault-like. */ ++ return vcpu->arch.exception.payload & ~DR6_BD; + } + + /* +@@ -3886,9 +3899,10 @@ static inline bool vmx_pending_dbg_trap(struct kvm_vcpu *vcpu) + */ + static void nested_vmx_update_pending_dbg(struct kvm_vcpu *vcpu) + { +- if (vmx_pending_dbg_trap(vcpu)) +- vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, +- vcpu->arch.exception.payload); ++ unsigned long pending_dbg = vmx_get_pending_dbg_trap(vcpu); ++ ++ if (pending_dbg) ++ vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, pending_dbg); + } + + static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu) +@@ -3945,7 +3959,7 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + * while delivering the pending exception. + */ + +- if (vcpu->arch.exception.pending && !vmx_pending_dbg_trap(vcpu)) { ++ if (vcpu->arch.exception.pending && !vmx_get_pending_dbg_trap(vcpu)) { + if (vmx->nested.nested_run_pending) + return -EBUSY; + if (!nested_vmx_check_exception(vcpu, &exit_qual)) +-- +2.35.1 + diff --git a/queue-5.19/kvm-nvmx-unconditionally-clear-mtf_pending-on-nested.patch b/queue-5.19/kvm-nvmx-unconditionally-clear-mtf_pending-on-nested.patch new file mode 100644 index 00000000000..08e2d27b6e9 --- /dev/null +++ b/queue-5.19/kvm-nvmx-unconditionally-clear-mtf_pending-on-nested.patch @@ -0,0 +1,99 @@ +From 9ea6c2253e8ab6eade6c4ed6a411f4004c7630d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 23:15:58 +0000 +Subject: KVM: nVMX: Unconditionally clear mtf_pending on nested VM-Exit + +From: Sean Christopherson + +[ Upstream commit 593a5c2e3c12a2f65967739267093255c47e9fe0 ] + +Clear mtf_pending on nested VM-Exit instead of handling the clear on a +case-by-case basis in vmx_check_nested_events(). The pending MTF should +never survive nested VM-Exit, as it is a property of KVM's run of the +current L2, i.e. should never affect the next L2 run by L1. In practice, +this is likely a nop as getting to L1 with nested_run_pending is +impossible, and KVM doesn't correctly handle morphing a pending exception +that occurs on a prior injected exception (need for re-injected exception +being the other case where MTF isn't cleared). However, KVM will +hopefully soon correctly deal with a pending exception on top of an +injected exception. + +Add a TODO to document that KVM has an inversion priority bug between +SMIs and MTF (and trap-like #DBS), and that KVM also doesn't properly +save/restore MTF across SMI/RSM. + +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-12-seanjc@google.com +Signed-off-by: Paolo Bonzini +Stable-dep-of: 7709aba8f716 ("KVM: x86: Morph pending exceptions to pending VM-Exits at queue time") +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx/nested.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index fdf31c7f61e5..deed076c7e2d 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -3917,16 +3917,8 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + unsigned long exit_qual; + bool block_nested_events = + vmx->nested.nested_run_pending || kvm_event_needs_reinjection(vcpu); +- bool mtf_pending = vmx->nested.mtf_pending; + struct kvm_lapic *apic = vcpu->arch.apic; + +- /* +- * Clear the MTF state. If a higher priority VM-exit is delivered first, +- * this state is discarded. +- */ +- if (!block_nested_events) +- vmx->nested.mtf_pending = false; +- + if (lapic_in_kernel(vcpu) && + test_bit(KVM_APIC_INIT, &apic->pending_events)) { + if (block_nested_events) +@@ -3935,6 +3927,9 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + clear_bit(KVM_APIC_INIT, &apic->pending_events); + if (vcpu->arch.mp_state != KVM_MP_STATE_INIT_RECEIVED) + nested_vmx_vmexit(vcpu, EXIT_REASON_INIT_SIGNAL, 0, 0); ++ ++ /* MTF is discarded if the vCPU is in WFS. */ ++ vmx->nested.mtf_pending = false; + return 0; + } + +@@ -3957,6 +3952,11 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + * fault-like exceptions, TSS T flag #DB (not emulated by KVM, but + * could theoretically come in from userspace), and ICEBP (INT1). + * ++ * TODO: SMIs have higher priority than MTF and trap-like #DBs (except ++ * for TSS T flag #DBs). KVM also doesn't save/restore pending MTF ++ * across SMI/RSM as it should; that needs to be addressed in order to ++ * prioritize SMI over MTF and trap-like #DBs. ++ * + * Note that only a pending nested run can block a pending exception. + * Otherwise an injected NMI/interrupt should either be + * lost or delivered to the nested hypervisor in the IDT_VECTORING_INFO, +@@ -3972,7 +3972,7 @@ static int vmx_check_nested_events(struct kvm_vcpu *vcpu) + return 0; + } + +- if (mtf_pending) { ++ if (vmx->nested.mtf_pending) { + if (block_nested_events) + return -EBUSY; + nested_vmx_update_pending_dbg(vcpu); +@@ -4571,6 +4571,9 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason, + struct vcpu_vmx *vmx = to_vmx(vcpu); + struct vmcs12 *vmcs12 = get_vmcs12(vcpu); + ++ /* Pending MTF traps are discarded on VM-Exit. */ ++ vmx->nested.mtf_pending = false; ++ + /* trying to cancel vmlaunch/vmresume is a bug */ + WARN_ON_ONCE(vmx->nested.nested_run_pending); + +-- +2.35.1 + diff --git a/queue-5.19/kvm-ppc-book3s-hv-fix-decrementer-migration.patch b/queue-5.19/kvm-ppc-book3s-hv-fix-decrementer-migration.patch new file mode 100644 index 00000000000..6e3490e3a3b --- /dev/null +++ b/queue-5.19/kvm-ppc-book3s-hv-fix-decrementer-migration.patch @@ -0,0 +1,83 @@ +From 6c2e077ec0af1ba4a510348435f126f38d89c356 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 19:25:17 -0300 +Subject: KVM: PPC: Book3S HV: Fix decrementer migration + +From: Fabiano Rosas + +[ Upstream commit 0a5bfb824a6ea35e54b7e5ac6f881beea5e309d2 ] + +We used to have a workaround[1] for a hang during migration that was +made ineffective when we converted the decrementer expiry to be +relative to guest timebase. + +The point of the workaround was that in the absence of an explicit +decrementer expiry value provided by userspace during migration, KVM +needs to initialize dec_expires to a value that will result in an +expired decrementer after subtracting the current guest timebase. That +stops the vcpu from hanging after migration due to a decrementer +that's too large. + +If the dec_expires is now relative to guest timebase, its +initialization needs to be guest timebase-relative as well, otherwise +we end up with a decrementer expiry that is still larger than the +guest timebase. + +1- https://git.kernel.org/torvalds/c/5855564c8ab2 + +Fixes: 3c1a4322bba7 ("KVM: PPC: Book3S HV: Change dec_expires to be relative to guest timebase") +Signed-off-by: Fabiano Rosas +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220816222517.1916391-1-farosas@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv.c | 18 ++++++++++++++++-- + arch/powerpc/kvm/powerpc.c | 1 - + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index e08fb3124dca..fcec1b0982b7 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -2517,10 +2517,24 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, + r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len); + break; + case KVM_REG_PPC_TB_OFFSET: ++ { + /* round up to multiple of 2^24 */ +- vcpu->arch.vcore->tb_offset = +- ALIGN(set_reg_val(id, *val), 1UL << 24); ++ u64 tb_offset = ALIGN(set_reg_val(id, *val), 1UL << 24); ++ ++ /* ++ * Now that we know the timebase offset, update the ++ * decrementer expiry with a guest timebase value. If ++ * the userspace does not set DEC_EXPIRY, this ensures ++ * a migrated vcpu at least starts with an expired ++ * decrementer, which is better than a large one that ++ * causes a hang. ++ */ ++ if (!vcpu->arch.dec_expires && tb_offset) ++ vcpu->arch.dec_expires = get_tb() + tb_offset; ++ ++ vcpu->arch.vcore->tb_offset = tb_offset; + break; ++ } + case KVM_REG_PPC_LPCR: + kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true); + break; +diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c +index 191992fcb2c2..7152291775c6 100644 +--- a/arch/powerpc/kvm/powerpc.c ++++ b/arch/powerpc/kvm/powerpc.c +@@ -785,7 +785,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) + + hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); + vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; +- vcpu->arch.dec_expires = get_tb(); + + #ifdef CONFIG_KVM_EXIT_TIMING + mutex_init(&vcpu->arch.exit_timing_lock); +-- +2.35.1 + diff --git a/queue-5.19/kvm-ppc-book3s-hv-p9-clear-vcpu-cpu-fields-before-en.patch b/queue-5.19/kvm-ppc-book3s-hv-p9-clear-vcpu-cpu-fields-before-en.patch new file mode 100644 index 00000000000..f0441c71ddd --- /dev/null +++ b/queue-5.19/kvm-ppc-book3s-hv-p9-clear-vcpu-cpu-fields-before-en.patch @@ -0,0 +1,54 @@ +From 9ecb5f8faf8703fe5cdf5240383c65bba337d6c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 23:25:41 +1000 +Subject: KVM: PPC: Book3S HV P9: Clear vcpu cpu fields before enabling host + irqs + +From: Nicholas Piggin + +[ Upstream commit bc91c04bfff7cdf676011b97bb21b2861d7b21c9 ] + +On guest entry, vcpu->cpu and vcpu->arch.thread_cpu are set after +disabling host irqs. On guest exit there is a window whre tick time +accounting briefly enables irqs before these fields are cleared. + +Move them up to ensure they are cleared before host irqs are run. +This is possibly not a problem, but is more symmetric and makes the +fields less surprising. + +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220908132545.4085849-1-npiggin@gmail.com +Stable-dep-of: 1a5486b3c351 ("KVM: PPC: Book3S HV P9: Restore stolen time logging in dtl") +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 6a17896f0b5c..8b7e6915cb2d 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4616,6 +4616,9 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + + set_irq_happened(trap); + ++ vcpu->cpu = -1; ++ vcpu->arch.thread_cpu = -1; ++ + context_tracking_guest_exit(); + if (!vtime_accounting_enabled_this_cpu()) { + powerpc_local_irq_pmu_restore(flags); +@@ -4631,9 +4634,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + } + vtime_account_guest_exit(); + +- vcpu->cpu = -1; +- vcpu->arch.thread_cpu = -1; +- + powerpc_local_irq_pmu_restore(flags); + + preempt_enable(); +-- +2.35.1 + diff --git a/queue-5.19/kvm-ppc-book3s-hv-p9-fix-irq-disabling-in-tick-accou.patch b/queue-5.19/kvm-ppc-book3s-hv-p9-fix-irq-disabling-in-tick-accou.patch new file mode 100644 index 00000000000..9d4197af558 --- /dev/null +++ b/queue-5.19/kvm-ppc-book3s-hv-p9-fix-irq-disabling-in-tick-accou.patch @@ -0,0 +1,48 @@ +From cc20831a4c4f82e1476b5ffff896ce9ca43dfb6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 23:25:42 +1000 +Subject: KVM: PPC: Book3S HV P9: Fix irq disabling in tick accounting + +From: Nicholas Piggin + +[ Upstream commit c953f7500b65f2b157d1eb468ca8b86328834cce ] + +kvmhv_run_single_vcpu() disables PMIs as well as Linux irqs, +however the tick time accounting code enables and disables irqs and +not PMIs within this region. By chance this might not actually cause +a bug, but it is clearly an incorrect use of the APIs. + +Fixes: 2251fbe76395e ("KVM: PPC: Book3S HV P9: Improve mtmsrd scheduling by delaying MSR[EE] disable") +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220908132545.4085849-2-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index fcec1b0982b7..6a17896f0b5c 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -4618,7 +4618,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + + context_tracking_guest_exit(); + if (!vtime_accounting_enabled_this_cpu()) { +- local_irq_enable(); ++ powerpc_local_irq_pmu_restore(flags); + /* + * Service IRQs here before vtime_account_guest_exit() so any + * ticks that occurred while running the guest are accounted to +@@ -4627,7 +4627,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + * interrupts here, which has the problem that it accounts + * interrupt processing overhead to the host. + */ +- local_irq_disable(); ++ powerpc_local_irq_pmu_save(flags); + } + vtime_account_guest_exit(); + +-- +2.35.1 + diff --git a/queue-5.19/kvm-ppc-book3s-hv-p9-restore-stolen-time-logging-in-.patch b/queue-5.19/kvm-ppc-book3s-hv-p9-restore-stolen-time-logging-in-.patch new file mode 100644 index 00000000000..b858f4aebd1 --- /dev/null +++ b/queue-5.19/kvm-ppc-book3s-hv-p9-restore-stolen-time-logging-in-.patch @@ -0,0 +1,150 @@ +From 5d38ae700dbf0f9e10752c47f1d90561ff45a6d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 23:25:44 +1000 +Subject: KVM: PPC: Book3S HV P9: Restore stolen time logging in dtl + +From: Nicholas Piggin + +[ Upstream commit 1a5486b3c3517aa1f608a10003ade4da122cb175 ] + +Stolen time logging in dtl was removed from the P9 path, so guests had +no stolen time accounting. Add it back in a simpler way that still +avoids locks and per-core accounting code. + +Fixes: ecb6a7207f92 ("KVM: PPC: Book3S HV P9: Remove most of the vcore logic") +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220908132545.4085849-4-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kvm/book3s_hv.c | 49 +++++++++++++++++++++++++++++++++--- + 1 file changed, 45 insertions(+), 4 deletions(-) + +diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c +index 8b7e6915cb2d..a6893e67315f 100644 +--- a/arch/powerpc/kvm/book3s_hv.c ++++ b/arch/powerpc/kvm/book3s_hv.c +@@ -249,6 +249,7 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) + + /* + * We use the vcpu_load/put functions to measure stolen time. ++ * + * Stolen time is counted as time when either the vcpu is able to + * run as part of a virtual core, but the task running the vcore + * is preempted or sleeping, or when the vcpu needs something done +@@ -278,6 +279,12 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) + * lock. The stolen times are measured in units of timebase ticks. + * (Note that the != TB_NIL checks below are purely defensive; + * they should never fail.) ++ * ++ * The POWER9 path is simpler, one vcpu per virtual core so the ++ * former case does not exist. If a vcpu is preempted when it is ++ * BUSY_IN_HOST and not ceded or otherwise blocked, then accumulate ++ * the stolen cycles in busy_stolen. RUNNING is not a preemptible ++ * state in the P9 path. + */ + + static void kvmppc_core_start_stolen(struct kvmppc_vcore *vc, u64 tb) +@@ -311,8 +318,14 @@ static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu) + unsigned long flags; + u64 now; + +- if (cpu_has_feature(CPU_FTR_ARCH_300)) ++ if (cpu_has_feature(CPU_FTR_ARCH_300)) { ++ if (vcpu->arch.busy_preempt != TB_NIL) { ++ WARN_ON_ONCE(vcpu->arch.state != KVMPPC_VCPU_BUSY_IN_HOST); ++ vc->stolen_tb += mftb() - vcpu->arch.busy_preempt; ++ vcpu->arch.busy_preempt = TB_NIL; ++ } + return; ++ } + + now = mftb(); + +@@ -340,8 +353,21 @@ static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu) + unsigned long flags; + u64 now; + +- if (cpu_has_feature(CPU_FTR_ARCH_300)) ++ if (cpu_has_feature(CPU_FTR_ARCH_300)) { ++ /* ++ * In the P9 path, RUNNABLE is not preemptible ++ * (nor takes host interrupts) ++ */ ++ WARN_ON_ONCE(vcpu->arch.state == KVMPPC_VCPU_RUNNABLE); ++ /* ++ * Account stolen time when preempted while the vcpu task is ++ * running in the kernel (but not in qemu, which is INACTIVE). ++ */ ++ if (task_is_running(current) && ++ vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST) ++ vcpu->arch.busy_preempt = mftb(); + return; ++ } + + now = mftb(); + +@@ -740,6 +766,18 @@ static void __kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, + vcpu->arch.dtl.dirty = true; + } + ++static void kvmppc_create_dtl_entry_p9(struct kvm_vcpu *vcpu, ++ struct kvmppc_vcore *vc, ++ u64 now) ++{ ++ unsigned long stolen; ++ ++ stolen = vc->stolen_tb - vcpu->arch.stolen_logged; ++ vcpu->arch.stolen_logged = vc->stolen_tb; ++ ++ __kvmppc_create_dtl_entry(vcpu, vc->pcpu, now, stolen); ++} ++ + static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, + struct kvmppc_vcore *vc) + { +@@ -4521,7 +4559,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + vc = vcpu->arch.vcore; + vcpu->arch.ceded = 0; + vcpu->arch.run_task = current; +- vcpu->arch.state = KVMPPC_VCPU_RUNNABLE; + vcpu->arch.last_inst = KVM_INST_FETCH_FAILED; + + /* See if the MMU is ready to go */ +@@ -4548,6 +4585,8 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + /* flags save not required, but irq_pmu has no disable/enable API */ + powerpc_local_irq_pmu_save(flags); + ++ vcpu->arch.state = KVMPPC_VCPU_RUNNABLE; ++ + if (signal_pending(current)) + goto sigpend; + if (need_resched() || !kvm->arch.mmu_ready) +@@ -4592,7 +4631,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + + tb = mftb(); + +- __kvmppc_create_dtl_entry(vcpu, pcpu, tb + vc->tb_offset, 0); ++ kvmppc_create_dtl_entry_p9(vcpu, vc, tb + vc->tb_offset); + + trace_kvm_guest_enter(vcpu); + +@@ -4618,6 +4657,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + + vcpu->cpu = -1; + vcpu->arch.thread_cpu = -1; ++ vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; + + context_tracking_guest_exit(); + if (!vtime_accounting_enabled_this_cpu()) { +@@ -4695,6 +4735,7 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit, + out: + vcpu->cpu = -1; + vcpu->arch.thread_cpu = -1; ++ vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST; + powerpc_local_irq_pmu_restore(flags); + preempt_enable(); + goto done; +-- +2.35.1 + diff --git a/queue-5.19/kvm-vmx-inject-pf-on-encls-as-emulated-pf.patch b/queue-5.19/kvm-vmx-inject-pf-on-encls-as-emulated-pf.patch new file mode 100644 index 00000000000..9c91441f0ed --- /dev/null +++ b/queue-5.19/kvm-vmx-inject-pf-on-encls-as-emulated-pf.patch @@ -0,0 +1,41 @@ +From 4fe019fe7893139a13d889d1b7e47c16bdad6944 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 23:15:59 +0000 +Subject: KVM: VMX: Inject #PF on ENCLS as "emulated" #PF + +From: Sean Christopherson + +[ Upstream commit bfcb08a0b9e99b959814a329fabace22c3df046d ] + +Treat #PFs that occur during emulation of ENCLS as, wait for it, emulated +page faults. Practically speaking, this is a glorified nop as the +exception is never of the nested flavor, and it's extremely unlikely the +guest is relying on the side effect of an implicit INVLPG on the faulting +address. + +Fixes: 70210c044b4e ("KVM: VMX: Add SGX ENCLS[ECREATE] handler to enforce CPUID restrictions") +Signed-off-by: Sean Christopherson +Reviewed-by: Maxim Levitsky +Link: https://lore.kernel.org/r/20220830231614.3580124-13-seanjc@google.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx/sgx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c +index d1cc7244bede..6ea06dff5000 100644 +--- a/arch/x86/kvm/vmx/sgx.c ++++ b/arch/x86/kvm/vmx/sgx.c +@@ -129,7 +129,7 @@ static int sgx_inject_fault(struct kvm_vcpu *vcpu, gva_t gva, int trapnr) + ex.address = gva; + ex.error_code_valid = true; + ex.nested_page_fault = false; +- kvm_inject_page_fault(vcpu, &ex); ++ kvm_inject_emulated_page_fault(vcpu, &ex); + } else { + kvm_inject_gp(vcpu, 0); + } +-- +2.35.1 + diff --git a/queue-5.19/kvm-x86-add-dedicated-helper-to-get-cpuid-entry-with.patch b/queue-5.19/kvm-x86-add-dedicated-helper-to-get-cpuid-entry-with.patch new file mode 100644 index 00000000000..f825e83352e --- /dev/null +++ b/queue-5.19/kvm-x86-add-dedicated-helper-to-get-cpuid-entry-with.patch @@ -0,0 +1,461 @@ +From ccd062539a30ac0fec3f59438aaf8715b11e280d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Jul 2022 02:06:45 +0200 +Subject: KVM: x86: Add dedicated helper to get CPUID entry with significant + index + +From: Sean Christopherson + +[ Upstream commit 277ad7d58611b455662f2e3f7bd24ce5bfeb2fdc ] + +Add a second CPUID helper, kvm_find_cpuid_entry_index(), to handle KVM +queries for CPUID leaves whose index _may_ be significant, and drop the +index param from the existing kvm_find_cpuid_entry(). Add a WARN in the +inner helper, cpuid_entry2_find(), to detect attempts to retrieve a CPUID +entry whose index is significant without explicitly providing an index. + +Using an explicit magic number and letting callers omit the index avoids +confusion by eliminating the myriad cases where KVM specifies '0' as a +dummy value. + +Suggested-by: Paolo Bonzini +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +Stable-dep-of: 3be29eb7b525 ("KVM: x86: Report error when setting CPUID if Hyper-V allocation fails") +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/cpuid.c | 80 +++++++++++++++++++++++++++--------- + arch/x86/kvm/cpuid.h | 16 ++++---- + arch/x86/kvm/hyperv.c | 8 ++-- + arch/x86/kvm/svm/svm.c | 2 +- + arch/x86/kvm/vmx/pmu_intel.c | 4 +- + arch/x86/kvm/vmx/sgx.c | 8 ++-- + arch/x86/kvm/vmx/vmx.c | 6 +-- + arch/x86/kvm/x86.c | 2 +- + 8 files changed, 84 insertions(+), 42 deletions(-) + +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index cb14441cee37..797348378006 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -67,9 +67,17 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted) + #define F feature_bit + #define SF(name) (boot_cpu_has(X86_FEATURE_##name) ? F(name) : 0) + ++/* ++ * Magic value used by KVM when querying userspace-provided CPUID entries and ++ * doesn't care about the CPIUD index because the index of the function in ++ * question is not significant. Note, this magic value must have at least one ++ * bit set in bits[63:32] and must be consumed as a u64 by cpuid_entry2_find() ++ * to avoid false positives when processing guest CPUID input. ++ */ ++#define KVM_CPUID_INDEX_NOT_SIGNIFICANT -1ull + + static inline struct kvm_cpuid_entry2 *cpuid_entry2_find( +- struct kvm_cpuid_entry2 *entries, int nent, u32 function, u32 index) ++ struct kvm_cpuid_entry2 *entries, int nent, u32 function, u64 index) + { + struct kvm_cpuid_entry2 *e; + int i; +@@ -77,9 +85,31 @@ static inline struct kvm_cpuid_entry2 *cpuid_entry2_find( + for (i = 0; i < nent; i++) { + e = &entries[i]; + +- if (e->function == function && +- (!(e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) || e->index == index)) ++ if (e->function != function) ++ continue; ++ ++ /* ++ * If the index isn't significant, use the first entry with a ++ * matching function. It's userspace's responsibilty to not ++ * provide "duplicate" entries in all cases. ++ */ ++ if (!(e->flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX) || e->index == index) ++ return e; ++ ++ ++ /* ++ * Similarly, use the first matching entry if KVM is doing a ++ * lookup (as opposed to emulating CPUID) for a function that's ++ * architecturally defined as not having a significant index. ++ */ ++ if (index == KVM_CPUID_INDEX_NOT_SIGNIFICANT) { ++ /* ++ * Direct lookups from KVM should not diverge from what ++ * KVM defines internally (the architectural behavior). ++ */ ++ WARN_ON_ONCE(cpuid_function_is_indexed(function)); + return e; ++ } + } + + return NULL; +@@ -96,7 +126,8 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu, + * The existing code assumes virtual address is 48-bit or 57-bit in the + * canonical address checks; exit if it is ever changed. + */ +- best = cpuid_entry2_find(entries, nent, 0x80000008, 0); ++ best = cpuid_entry2_find(entries, nent, 0x80000008, ++ KVM_CPUID_INDEX_NOT_SIGNIFICANT); + if (best) { + int vaddr_bits = (best->eax & 0xff00) >> 8; + +@@ -151,7 +182,7 @@ static void kvm_update_kvm_cpuid_base(struct kvm_vcpu *vcpu) + vcpu->arch.kvm_cpuid_base = 0; + + for_each_possible_hypervisor_cpuid_base(function) { +- entry = kvm_find_cpuid_entry(vcpu, function, 0); ++ entry = kvm_find_cpuid_entry(vcpu, function); + + if (entry) { + u32 signature[3]; +@@ -177,7 +208,8 @@ static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_vcpu *v + if (!base) + return NULL; + +- return cpuid_entry2_find(entries, nent, base | KVM_CPUID_FEATURES, 0); ++ return cpuid_entry2_find(entries, nent, base | KVM_CPUID_FEATURES, ++ KVM_CPUID_INDEX_NOT_SIGNIFICANT); + } + + static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu) +@@ -219,7 +251,7 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e + struct kvm_cpuid_entry2 *best; + u64 guest_supported_xcr0 = cpuid_get_supported_xcr0(entries, nent); + +- best = cpuid_entry2_find(entries, nent, 1, 0); ++ best = cpuid_entry2_find(entries, nent, 1, KVM_CPUID_INDEX_NOT_SIGNIFICANT); + if (best) { + /* Update OSXSAVE bit */ + if (boot_cpu_has(X86_FEATURE_XSAVE)) +@@ -250,7 +282,7 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e + best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT); + + if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)) { +- best = cpuid_entry2_find(entries, nent, 0x1, 0); ++ best = cpuid_entry2_find(entries, nent, 0x1, KVM_CPUID_INDEX_NOT_SIGNIFICANT); + if (best) + cpuid_entry_change(best, X86_FEATURE_MWAIT, + vcpu->arch.ia32_misc_enable_msr & +@@ -284,7 +316,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) + struct kvm_lapic *apic = vcpu->arch.apic; + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 1, 0); ++ best = kvm_find_cpuid_entry(vcpu, 1); + if (best && apic) { + if (cpuid_entry_has(best, X86_FEATURE_TSC_DEADLINE_TIMER)) + apic->lapic_timer.timer_mode_mask = 3 << 17; +@@ -330,10 +362,10 @@ int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0x80000000, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x80000000); + if (!best || best->eax < 0x80000008) + goto not_found; +- best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x80000008); + if (best) + return best->eax & 0xff; + not_found: +@@ -1316,12 +1348,20 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, + return r; + } + +-struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, +- u32 function, u32 index) ++struct kvm_cpuid_entry2 *kvm_find_cpuid_entry_index(struct kvm_vcpu *vcpu, ++ u32 function, u32 index) + { + return cpuid_entry2_find(vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent, + function, index); + } ++EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry_index); ++ ++struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, ++ u32 function) ++{ ++ return cpuid_entry2_find(vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent, ++ function, KVM_CPUID_INDEX_NOT_SIGNIFICANT); ++} + EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry); + + /* +@@ -1358,7 +1398,7 @@ get_out_of_range_cpuid_entry(struct kvm_vcpu *vcpu, u32 *fn_ptr, u32 index) + struct kvm_cpuid_entry2 *basic, *class; + u32 function = *fn_ptr; + +- basic = kvm_find_cpuid_entry(vcpu, 0, 0); ++ basic = kvm_find_cpuid_entry(vcpu, 0); + if (!basic) + return NULL; + +@@ -1367,11 +1407,11 @@ get_out_of_range_cpuid_entry(struct kvm_vcpu *vcpu, u32 *fn_ptr, u32 index) + return NULL; + + if (function >= 0x40000000 && function <= 0x4fffffff) +- class = kvm_find_cpuid_entry(vcpu, function & 0xffffff00, 0); ++ class = kvm_find_cpuid_entry(vcpu, function & 0xffffff00); + else if (function >= 0xc0000000) +- class = kvm_find_cpuid_entry(vcpu, 0xc0000000, 0); ++ class = kvm_find_cpuid_entry(vcpu, 0xc0000000); + else +- class = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0); ++ class = kvm_find_cpuid_entry(vcpu, function & 0x80000000); + + if (class && function <= class->eax) + return NULL; +@@ -1389,7 +1429,7 @@ get_out_of_range_cpuid_entry(struct kvm_vcpu *vcpu, u32 *fn_ptr, u32 index) + * the effective CPUID entry is the max basic leaf. Note, the index of + * the original requested leaf is observed! + */ +- return kvm_find_cpuid_entry(vcpu, basic->eax, index); ++ return kvm_find_cpuid_entry_index(vcpu, basic->eax, index); + } + + bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, +@@ -1399,7 +1439,7 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, + struct kvm_cpuid_entry2 *entry; + bool exact, used_max_basic = false; + +- entry = kvm_find_cpuid_entry(vcpu, function, index); ++ entry = kvm_find_cpuid_entry_index(vcpu, function, index); + exact = !!entry; + + if (!entry && !exact_only) { +@@ -1428,7 +1468,7 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx, + * exists. EDX can be copied from any existing index. + */ + if (function == 0xb || function == 0x1f) { +- entry = kvm_find_cpuid_entry(vcpu, function, 1); ++ entry = kvm_find_cpuid_entry_index(vcpu, function, 1); + if (entry) { + *ecx = index & 0xff; + *edx = entry->edx; +diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h +index 8a770b481d9d..d45ac1a14f7d 100644 +--- a/arch/x86/kvm/cpuid.h ++++ b/arch/x86/kvm/cpuid.h +@@ -13,8 +13,10 @@ void kvm_set_cpu_caps(void); + + void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu); + void kvm_update_pv_runtime(struct kvm_vcpu *vcpu); ++struct kvm_cpuid_entry2 *kvm_find_cpuid_entry_index(struct kvm_vcpu *vcpu, ++ u32 function, u32 index); + struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, +- u32 function, u32 index); ++ u32 function); + int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, + struct kvm_cpuid_entry2 __user *entries, + unsigned int type); +@@ -76,7 +78,7 @@ static __always_inline u32 *guest_cpuid_get_register(struct kvm_vcpu *vcpu, + const struct cpuid_reg cpuid = x86_feature_cpuid(x86_feature); + struct kvm_cpuid_entry2 *entry; + +- entry = kvm_find_cpuid_entry(vcpu, cpuid.function, cpuid.index); ++ entry = kvm_find_cpuid_entry_index(vcpu, cpuid.function, cpuid.index); + if (!entry) + return NULL; + +@@ -109,7 +111,7 @@ static inline bool guest_cpuid_is_amd_or_hygon(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0); + return best && + (is_guest_vendor_amd(best->ebx, best->ecx, best->edx) || + is_guest_vendor_hygon(best->ebx, best->ecx, best->edx)); +@@ -119,7 +121,7 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0); + return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx); + } + +@@ -127,7 +129,7 @@ static inline int guest_cpuid_family(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0x1, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x1); + if (!best) + return -1; + +@@ -138,7 +140,7 @@ static inline int guest_cpuid_model(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0x1, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x1); + if (!best) + return -1; + +@@ -149,7 +151,7 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu) + { + struct kvm_cpuid_entry2 *best; + +- best = kvm_find_cpuid_entry(vcpu, 0x1, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x1); + if (!best) + return -1; + +diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c +index e2e95a6fccfd..ed804447589c 100644 +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -1992,7 +1992,7 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + struct kvm_cpuid_entry2 *entry; + struct kvm_vcpu_hv *hv_vcpu; + +- entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE, 0); ++ entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE); + if (entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX) { + vcpu->arch.hyperv_enabled = true; + } else { +@@ -2005,7 +2005,7 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + + hv_vcpu = to_hv_vcpu(vcpu); + +- entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES, 0); ++ entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES); + if (entry) { + hv_vcpu->cpuid_cache.features_eax = entry->eax; + hv_vcpu->cpuid_cache.features_ebx = entry->ebx; +@@ -2016,7 +2016,7 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + hv_vcpu->cpuid_cache.features_edx = 0; + } + +- entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_ENLIGHTMENT_INFO, 0); ++ entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_ENLIGHTMENT_INFO); + if (entry) { + hv_vcpu->cpuid_cache.enlightenments_eax = entry->eax; + hv_vcpu->cpuid_cache.enlightenments_ebx = entry->ebx; +@@ -2025,7 +2025,7 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + hv_vcpu->cpuid_cache.enlightenments_ebx = 0; + } + +- entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES, 0); ++ entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES); + if (entry) + hv_vcpu->cpuid_cache.syndbg_cap_eax = entry->eax; + else +diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c +index 92b30b4937fc..274343f70eb9 100644 +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -4058,7 +4058,7 @@ static void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) + + /* For sev guests, the memory encryption bit is not reserved in CR3. */ + if (sev_guest(vcpu->kvm)) { +- best = kvm_find_cpuid_entry(vcpu, 0x8000001F, 0); ++ best = kvm_find_cpuid_entry(vcpu, 0x8000001F); + if (best) + vcpu->arch.reserved_gpa_bits &= ~(1UL << (best->ebx & 0x3f)); + } +diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c +index a9280ebf78f5..c8ca47221ae5 100644 +--- a/arch/x86/kvm/vmx/pmu_intel.c ++++ b/arch/x86/kvm/vmx/pmu_intel.c +@@ -495,7 +495,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) + pmu->global_ovf_ctrl_mask = ~0ull; + pmu->fixed_ctr_ctrl_mask = ~0ull; + +- entry = kvm_find_cpuid_entry(vcpu, 0xa, 0); ++ entry = kvm_find_cpuid_entry(vcpu, 0xa); + if (!entry || !vcpu->kvm->arch.enable_pmu) + return; + eax.full = entry->eax; +@@ -541,7 +541,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) + pmu->global_ovf_ctrl_mask &= + ~MSR_CORE_PERF_GLOBAL_OVF_CTRL_TRACE_TOPA_PMI; + +- entry = kvm_find_cpuid_entry(vcpu, 7, 0); ++ entry = kvm_find_cpuid_entry_index(vcpu, 7, 0); + if (entry && + (boot_cpu_has(X86_FEATURE_HLE) || boot_cpu_has(X86_FEATURE_RTM)) && + (entry->ebx & (X86_FEATURE_HLE|X86_FEATURE_RTM))) { +diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c +index 35e7ec91ae86..d1cc7244bede 100644 +--- a/arch/x86/kvm/vmx/sgx.c ++++ b/arch/x86/kvm/vmx/sgx.c +@@ -148,8 +148,8 @@ static int __handle_encls_ecreate(struct kvm_vcpu *vcpu, + u8 max_size_log2; + int trapnr, ret; + +- sgx_12_0 = kvm_find_cpuid_entry(vcpu, 0x12, 0); +- sgx_12_1 = kvm_find_cpuid_entry(vcpu, 0x12, 1); ++ sgx_12_0 = kvm_find_cpuid_entry_index(vcpu, 0x12, 0); ++ sgx_12_1 = kvm_find_cpuid_entry_index(vcpu, 0x12, 1); + if (!sgx_12_0 || !sgx_12_1) { + kvm_prepare_emulation_failure_exit(vcpu); + return 0; +@@ -431,7 +431,7 @@ static bool sgx_intercept_encls_ecreate(struct kvm_vcpu *vcpu) + if (!vcpu->kvm->arch.sgx_provisioning_allowed) + return true; + +- guest_cpuid = kvm_find_cpuid_entry(vcpu, 0x12, 0); ++ guest_cpuid = kvm_find_cpuid_entry_index(vcpu, 0x12, 0); + if (!guest_cpuid) + return true; + +@@ -439,7 +439,7 @@ static bool sgx_intercept_encls_ecreate(struct kvm_vcpu *vcpu) + if (guest_cpuid->ebx != ebx || guest_cpuid->edx != edx) + return true; + +- guest_cpuid = kvm_find_cpuid_entry(vcpu, 0x12, 1); ++ guest_cpuid = kvm_find_cpuid_entry_index(vcpu, 0x12, 1); + if (!guest_cpuid) + return true; + +diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c +index 98526e708f32..c02803d9f7e7 100644 +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -7319,7 +7319,7 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu) + vmx->nested.msrs.cr4_fixed1 |= (_cr4_mask); \ + } while (0) + +- entry = kvm_find_cpuid_entry(vcpu, 0x1, 0); ++ entry = kvm_find_cpuid_entry(vcpu, 0x1); + cr4_fixed1_update(X86_CR4_VME, edx, feature_bit(VME)); + cr4_fixed1_update(X86_CR4_PVI, edx, feature_bit(VME)); + cr4_fixed1_update(X86_CR4_TSD, edx, feature_bit(TSC)); +@@ -7335,7 +7335,7 @@ static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu) + cr4_fixed1_update(X86_CR4_PCIDE, ecx, feature_bit(PCID)); + cr4_fixed1_update(X86_CR4_OSXSAVE, ecx, feature_bit(XSAVE)); + +- entry = kvm_find_cpuid_entry(vcpu, 0x7, 0); ++ entry = kvm_find_cpuid_entry_index(vcpu, 0x7, 0); + cr4_fixed1_update(X86_CR4_FSGSBASE, ebx, feature_bit(FSGSBASE)); + cr4_fixed1_update(X86_CR4_SMEP, ebx, feature_bit(SMEP)); + cr4_fixed1_update(X86_CR4_SMAP, ebx, feature_bit(SMAP)); +@@ -7370,7 +7370,7 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu) + int i; + + for (i = 0; i < PT_CPUID_LEAVES; i++) { +- best = kvm_find_cpuid_entry(vcpu, 0x14, i); ++ best = kvm_find_cpuid_entry_index(vcpu, 0x14, i); + if (!best) + return; + vmx->pt_desc.caps[CPUID_EAX + i*PT_CPUID_REGS_NUM] = best->eax; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 8c2815151864..8304600d388a 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -11550,7 +11550,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) + * i.e. it's impossible for kvm_find_cpuid_entry() to find a valid entry + * on RESET. But, go through the motions in case that's ever remedied. + */ +- cpuid_0x1 = kvm_find_cpuid_entry(vcpu, 1, 0); ++ cpuid_0x1 = kvm_find_cpuid_entry(vcpu, 1); + kvm_rdx_write(vcpu, cpuid_0x1 ? cpuid_0x1->eax : 0x600); + + static_call(kvm_x86_vcpu_reset)(vcpu, init_event); +-- +2.35.1 + diff --git a/queue-5.19/kvm-x86-check-for-existing-hyper-v-vcpu-in-kvm_hv_vc.patch b/queue-5.19/kvm-x86-check-for-existing-hyper-v-vcpu-in-kvm_hv_vc.patch new file mode 100644 index 00000000000..27077233b0a --- /dev/null +++ b/queue-5.19/kvm-x86-check-for-existing-hyper-v-vcpu-in-kvm_hv_vc.patch @@ -0,0 +1,101 @@ +From 19d8fd74cc7e93d4039147d85cb66be92adbb285 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:37:08 +0200 +Subject: KVM: x86: Check for existing Hyper-V vCPU in kvm_hv_vcpu_init() + +From: Sean Christopherson + +[ Upstream commit 1cac8d9f6bd25df3713103e44e2d9ca0c2e03c33 ] + +When potentially allocating/initializing the Hyper-V vCPU struct, check +for an existing instance in kvm_hv_vcpu_init() instead of requiring +callers to perform the check. Relying on callers to do the check is +risky as it's all too easy for KVM to overwrite vcpu->arch.hyperv and +leak memory, and it adds additional burden on callers without much +benefit. + +No functional change intended. + +Signed-off-by: Sean Christopherson +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Sean Christopherson +Reviewed-by: Wei Liu +Link: https://lore.kernel.org/r/20220830133737.1539624-5-vkuznets@redhat.com +Signed-off-by: Paolo Bonzini +Stable-dep-of: 3be29eb7b525 ("KVM: x86: Report error when setting CPUID if Hyper-V allocation fails") +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/hyperv.c | 27 ++++++++++++--------------- + 1 file changed, 12 insertions(+), 15 deletions(-) + +diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c +index 611c349a08bf..8aadd31ed058 100644 +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -936,9 +936,12 @@ static void stimer_init(struct kvm_vcpu_hv_stimer *stimer, int timer_index) + + static int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) + { +- struct kvm_vcpu_hv *hv_vcpu; ++ struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); + int i; + ++ if (hv_vcpu) ++ return 0; ++ + hv_vcpu = kzalloc(sizeof(struct kvm_vcpu_hv), GFP_KERNEL_ACCOUNT); + if (!hv_vcpu) + return -ENOMEM; +@@ -962,11 +965,9 @@ int kvm_hv_activate_synic(struct kvm_vcpu *vcpu, bool dont_zero_synic_pages) + struct kvm_vcpu_hv_synic *synic; + int r; + +- if (!to_hv_vcpu(vcpu)) { +- r = kvm_hv_vcpu_init(vcpu); +- if (r) +- return r; +- } ++ r = kvm_hv_vcpu_init(vcpu); ++ if (r) ++ return r; + + synic = to_hv_synic(vcpu); + +@@ -1660,10 +1661,8 @@ int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host) + if (!host && !vcpu->arch.hyperv_enabled) + return 1; + +- if (!to_hv_vcpu(vcpu)) { +- if (kvm_hv_vcpu_init(vcpu)) +- return 1; +- } ++ if (kvm_hv_vcpu_init(vcpu)) ++ return 1; + + if (kvm_hv_msr_partition_wide(msr)) { + int r; +@@ -1683,10 +1682,8 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host) + if (!host && !vcpu->arch.hyperv_enabled) + return 1; + +- if (!to_hv_vcpu(vcpu)) { +- if (kvm_hv_vcpu_init(vcpu)) +- return 1; +- } ++ if (kvm_hv_vcpu_init(vcpu)) ++ return 1; + + if (kvm_hv_msr_partition_wide(msr)) { + int r; +@@ -2000,7 +1997,7 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + return; + } + +- if (!to_hv_vcpu(vcpu) && kvm_hv_vcpu_init(vcpu)) ++ if (kvm_hv_vcpu_init(vcpu)) + return; + + hv_vcpu = to_hv_vcpu(vcpu); +-- +2.35.1 + diff --git a/queue-5.19/kvm-x86-mmu-fix-memoryleak-in-kvm_mmu_vendor_module_.patch b/queue-5.19/kvm-x86-mmu-fix-memoryleak-in-kvm_mmu_vendor_module_.patch new file mode 100644 index 00000000000..03793a1d670 --- /dev/null +++ b/queue-5.19/kvm-x86-mmu-fix-memoryleak-in-kvm_mmu_vendor_module_.patch @@ -0,0 +1,44 @@ +From a85d47c2abf7acaa00f87b7ef6b444931736428d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 14:32:37 +0800 +Subject: KVM: x86/mmu: fix memoryleak in kvm_mmu_vendor_module_init() + +From: Miaohe Lin + +[ Upstream commit d7c9bfb9caaffd496ae44b258ec7c793677d3eeb ] + +When register_shrinker() fails, KVM doesn't release the percpu counter +kvm_total_used_mmu_pages leading to memoryleak. Fix this issue by calling +percpu_counter_destroy() when register_shrinker() fails. + +Fixes: ab271bd4dfd5 ("x86: kvm: propagate register_shrinker return code") +Signed-off-by: Miaohe Lin +Link: https://lore.kernel.org/r/20220823063237.47299-1-linmiaohe@huawei.com +[sean: tweak shortlog and changelog] +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/mmu/mmu.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c +index aa1ba803659c..3011c32ec79e 100644 +--- a/arch/x86/kvm/mmu/mmu.c ++++ b/arch/x86/kvm/mmu/mmu.c +@@ -6292,10 +6292,12 @@ int kvm_mmu_vendor_module_init(void) + + ret = register_shrinker(&mmu_shrinker); + if (ret) +- goto out; ++ goto out_shrinker; + + return 0; + ++out_shrinker: ++ percpu_counter_destroy(&kvm_total_used_mmu_pages); + out: + mmu_destroy_caches(); + return ret; +-- +2.35.1 + diff --git a/queue-5.19/kvm-x86-report-error-when-setting-cpuid-if-hyper-v-a.patch b/queue-5.19/kvm-x86-report-error-when-setting-cpuid-if-hyper-v-a.patch new file mode 100644 index 00000000000..de5cbd4f125 --- /dev/null +++ b/queue-5.19/kvm-x86-report-error-when-setting-cpuid-if-hyper-v-a.patch @@ -0,0 +1,173 @@ +From ba1f6aa447184d0452a84bd87b2dc6b2d06ee99b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:37:09 +0200 +Subject: KVM: x86: Report error when setting CPUID if Hyper-V allocation fails + +From: Sean Christopherson + +[ Upstream commit 3be29eb7b5251a772e2033761a9b67981fdfb0f7 ] + +Return -ENOMEM back to userspace if allocating the Hyper-V vCPU struct +fails when enabling Hyper-V in guest CPUID. Silently ignoring failure +means that KVM will not have an up-to-date CPUID cache if allocating the +struct succeeds later on, e.g. when activating SynIC. + +Rejecting the CPUID operation also guarantess that vcpu->arch.hyperv is +non-NULL if hyperv_enabled is true, which will allow for additional +cleanup, e.g. in the eVMCS code. + +Note, the initialization needs to be done before CPUID is set, and more +subtly before kvm_check_cpuid(), which potentially enables dynamic +XFEATURES. Sadly, there's no easy way to avoid exposing Hyper-V details +to CPUID or vice versa. Expose kvm_hv_vcpu_init() and the Hyper-V CPUID +signature to CPUID instead of exposing cpuid_entry2_find() outside of +CPUID code. It's hard to envision kvm_hv_vcpu_init() being misused, +whereas cpuid_entry2_find() absolutely shouldn't be used outside of core +CPUID code. + +Fixes: 10d7bf1e46dc ("KVM: x86: hyper-v: Cache guest CPUID leaves determining features availability") +Signed-off-by: Sean Christopherson +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Sean Christopherson +Link: https://lore.kernel.org/r/20220830133737.1539624-6-vkuznets@redhat.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/cpuid.c | 18 +++++++++++++++++- + arch/x86/kvm/hyperv.c | 30 ++++++++++++++---------------- + arch/x86/kvm/hyperv.h | 6 +++++- + 3 files changed, 36 insertions(+), 18 deletions(-) + +diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c +index 797348378006..1c9863f5b4f6 100644 +--- a/arch/x86/kvm/cpuid.c ++++ b/arch/x86/kvm/cpuid.c +@@ -311,6 +311,15 @@ void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) + } + EXPORT_SYMBOL_GPL(kvm_update_cpuid_runtime); + ++static bool kvm_cpuid_has_hyperv(struct kvm_cpuid_entry2 *entries, int nent) ++{ ++ struct kvm_cpuid_entry2 *entry; ++ ++ entry = cpuid_entry2_find(entries, nent, HYPERV_CPUID_INTERFACE, ++ KVM_CPUID_INDEX_NOT_SIGNIFICANT); ++ return entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX; ++} ++ + static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) + { + struct kvm_lapic *apic = vcpu->arch.apic; +@@ -346,7 +355,8 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) + vcpu->arch.cr4_guest_rsvd_bits = + __cr4_reserved_bits(guest_cpuid_has, vcpu); + +- kvm_hv_set_cpuid(vcpu); ++ kvm_hv_set_cpuid(vcpu, kvm_cpuid_has_hyperv(vcpu->arch.cpuid_entries, ++ vcpu->arch.cpuid_nent)); + + /* Invoke the vendor callback only after the above state is updated. */ + static_call(kvm_x86_vcpu_after_set_cpuid)(vcpu); +@@ -409,6 +419,12 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2, + return 0; + } + ++ if (kvm_cpuid_has_hyperv(e2, nent)) { ++ r = kvm_hv_vcpu_init(vcpu); ++ if (r) ++ return r; ++ } ++ + r = kvm_check_cpuid(vcpu, e2, nent); + if (r) + return r; +diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c +index 8aadd31ed058..bf4729e8cc80 100644 +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -38,9 +38,6 @@ + #include "irq.h" + #include "fpu.h" + +-/* "Hv#1" signature */ +-#define HYPERV_CPUID_SIGNATURE_EAX 0x31237648 +- + #define KVM_HV_MAX_SPARSE_VCPU_SET_BITS DIV_ROUND_UP(KVM_MAX_VCPUS, 64) + + static void stimer_mark_pending(struct kvm_vcpu_hv_stimer *stimer, +@@ -934,7 +931,7 @@ static void stimer_init(struct kvm_vcpu_hv_stimer *stimer, int timer_index) + stimer_prepare_msg(stimer); + } + +-static int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) ++int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) + { + struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); + int i; +@@ -1984,26 +1981,27 @@ static u64 kvm_hv_send_ipi(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) + return HV_STATUS_SUCCESS; + } + +-void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) ++void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu, bool hyperv_enabled) + { ++ struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); + struct kvm_cpuid_entry2 *entry; +- struct kvm_vcpu_hv *hv_vcpu; + +- entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE); +- if (entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX) { +- vcpu->arch.hyperv_enabled = true; +- } else { +- vcpu->arch.hyperv_enabled = false; +- return; +- } ++ vcpu->arch.hyperv_enabled = hyperv_enabled; + +- if (kvm_hv_vcpu_init(vcpu)) ++ if (!hv_vcpu) { ++ /* ++ * KVM should have already allocated kvm_vcpu_hv if Hyper-V is ++ * enabled in CPUID. ++ */ ++ WARN_ON_ONCE(vcpu->arch.hyperv_enabled); + return; +- +- hv_vcpu = to_hv_vcpu(vcpu); ++ } + + memset(&hv_vcpu->cpuid_cache, 0, sizeof(hv_vcpu->cpuid_cache)); + ++ if (!vcpu->arch.hyperv_enabled) ++ return; ++ + entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES); + if (entry) { + hv_vcpu->cpuid_cache.features_eax = entry->eax; +diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h +index da2737f2a956..1030b1b50552 100644 +--- a/arch/x86/kvm/hyperv.h ++++ b/arch/x86/kvm/hyperv.h +@@ -23,6 +23,9 @@ + + #include + ++/* "Hv#1" signature */ ++#define HYPERV_CPUID_SIGNATURE_EAX 0x31237648 ++ + /* + * The #defines related to the synthetic debugger are required by KDNet, but + * they are not documented in the Hyper-V TLFS because the synthetic debugger +@@ -141,7 +144,8 @@ void kvm_hv_request_tsc_page_update(struct kvm *kvm); + + void kvm_hv_init_vm(struct kvm *kvm); + void kvm_hv_destroy_vm(struct kvm *kvm); +-void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu); ++int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu); ++void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu, bool hyperv_enabled); + int kvm_hv_set_enforce_cpuid(struct kvm_vcpu *vcpu, bool enforce); + int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct kvm_hyperv_eventfd *args); + int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, +-- +2.35.1 + diff --git a/queue-5.19/kvm-x86-zero-out-entire-hyper-v-cpuid-cache-before-p.patch b/queue-5.19/kvm-x86-zero-out-entire-hyper-v-cpuid-cache-before-p.patch new file mode 100644 index 00000000000..74e3cedcea1 --- /dev/null +++ b/queue-5.19/kvm-x86-zero-out-entire-hyper-v-cpuid-cache-before-p.patch @@ -0,0 +1,69 @@ +From 994fa71e277e5d39f09d28b42e6549b905750238 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:37:07 +0200 +Subject: KVM: x86: Zero out entire Hyper-V CPUID cache before processing + entries + +From: Vitaly Kuznetsov + +[ Upstream commit ce2196b831b1e9f8982b2904fc3e8658cc0e6573 ] + +Wipe the whole 'hv_vcpu->cpuid_cache' with memset() instead of having to +zero each particular member when the corresponding CPUID entry was not +found. + +No functional change intended. + +Signed-off-by: Vitaly Kuznetsov +[sean: split to separate patch] +Signed-off-by: Sean Christopherson +Reviewed-by: Wei Liu +Link: https://lore.kernel.org/r/20220830133737.1539624-4-vkuznets@redhat.com +Signed-off-by: Paolo Bonzini +Stable-dep-of: 3be29eb7b525 ("KVM: x86: Report error when setting CPUID if Hyper-V allocation fails") +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/hyperv.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c +index ed804447589c..611c349a08bf 100644 +--- a/arch/x86/kvm/hyperv.c ++++ b/arch/x86/kvm/hyperv.c +@@ -2005,31 +2005,24 @@ void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu) + + hv_vcpu = to_hv_vcpu(vcpu); + ++ memset(&hv_vcpu->cpuid_cache, 0, sizeof(hv_vcpu->cpuid_cache)); ++ + entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_FEATURES); + if (entry) { + hv_vcpu->cpuid_cache.features_eax = entry->eax; + hv_vcpu->cpuid_cache.features_ebx = entry->ebx; + hv_vcpu->cpuid_cache.features_edx = entry->edx; +- } else { +- hv_vcpu->cpuid_cache.features_eax = 0; +- hv_vcpu->cpuid_cache.features_ebx = 0; +- hv_vcpu->cpuid_cache.features_edx = 0; + } + + entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_ENLIGHTMENT_INFO); + if (entry) { + hv_vcpu->cpuid_cache.enlightenments_eax = entry->eax; + hv_vcpu->cpuid_cache.enlightenments_ebx = entry->ebx; +- } else { +- hv_vcpu->cpuid_cache.enlightenments_eax = 0; +- hv_vcpu->cpuid_cache.enlightenments_ebx = 0; + } + + entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES); + if (entry) + hv_vcpu->cpuid_cache.syndbg_cap_eax = entry->eax; +- else +- hv_vcpu->cpuid_cache.syndbg_cap_eax = 0; + } + + int kvm_hv_set_enforce_cpuid(struct kvm_vcpu *vcpu, bool enforce) +-- +2.35.1 + diff --git a/queue-5.19/leds-lm3601x-don-t-use-mutex-after-it-was-destroyed.patch b/queue-5.19/leds-lm3601x-don-t-use-mutex-after-it-was-destroyed.patch new file mode 100644 index 00000000000..c6ba6bdefed --- /dev/null +++ b/queue-5.19/leds-lm3601x-don-t-use-mutex-after-it-was-destroyed.patch @@ -0,0 +1,41 @@ +From 4fe05d42d312afed568c2d5bbe85a397276f4adc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 10:02:27 +0200 +Subject: leds: lm3601x: Don't use mutex after it was destroyed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 32f7eed0c763a9b89f6b357ec54b48398fc7b99e ] + +The mutex might still be in use until the devm cleanup callback +devm_led_classdev_flash_release() is called. This only happens some time +after lm3601x_remove() completed. + +Fixes: e63a744871a3 ("leds: lm3601x: Convert class registration to device managed") +Acked-by: Pavel Machek +Signed-off-by: Uwe Kleine-König +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/leds/flash/leds-lm3601x.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/leds/flash/leds-lm3601x.c b/drivers/leds/flash/leds-lm3601x.c +index d0e1d4814042..3d1272748201 100644 +--- a/drivers/leds/flash/leds-lm3601x.c ++++ b/drivers/leds/flash/leds-lm3601x.c +@@ -444,8 +444,6 @@ static int lm3601x_remove(struct i2c_client *client) + { + struct lm3601x_led *led = i2c_get_clientdata(client); + +- mutex_destroy(&led->lock); +- + return regmap_update_bits(led->regmap, LM3601X_ENABLE_REG, + LM3601X_ENABLE_MASK, + LM3601X_MODE_STANDBY); +-- +2.35.1 + diff --git a/queue-5.19/libbpf-do-not-require-executable-permission-for-shar.patch b/queue-5.19/libbpf-do-not-require-executable-permission-for-shar.patch new file mode 100644 index 00000000000..2527f8986f7 --- /dev/null +++ b/queue-5.19/libbpf-do-not-require-executable-permission-for-shar.patch @@ -0,0 +1,61 @@ +From 72ab021346f9098a7e3b5f5cf19ba084a6d7e3c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Aug 2022 18:20:21 +0800 +Subject: libbpf: Do not require executable permission for shared libraries + +From: Hengqi Chen + +[ Upstream commit 9e32084ef1c33a87a736d6ce3fcb95b60dac9aa1 ] + +Currently, resolve_full_path() requires executable permission for both +programs and shared libraries. This causes failures on distos like Debian +since the shared libraries are not installed executable and Linux is not +requiring shared libraries to have executable permissions. Let's remove +executable permission check for shared libraries. + +Reported-by: Goro Fuji +Signed-off-by: Hengqi Chen +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20220806102021.3867130-1-hengqi.chen@gmail.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index f179100d2a61..37b4c8784bfa 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -11211,15 +11211,17 @@ static const char *arch_specific_lib_paths(void) + static int resolve_full_path(const char *file, char *result, size_t result_sz) + { + const char *search_paths[3] = {}; +- int i; ++ int i, perm; + + if (str_has_sfx(file, ".so") || strstr(file, ".so.")) { + search_paths[0] = getenv("LD_LIBRARY_PATH"); + search_paths[1] = "/usr/lib64:/usr/lib"; + search_paths[2] = arch_specific_lib_paths(); ++ perm = R_OK; + } else { + search_paths[0] = getenv("PATH"); + search_paths[1] = "/usr/bin:/usr/sbin"; ++ perm = R_OK | X_OK; + } + + for (i = 0; i < ARRAY_SIZE(search_paths); i++) { +@@ -11238,8 +11240,8 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz) + if (!seg_len) + continue; + snprintf(result, result_sz, "%.*s/%s", seg_len, s, file); +- /* ensure it is an executable file/link */ +- if (access(result, R_OK | X_OK) < 0) ++ /* ensure it has required permissions */ ++ if (access(result, perm) < 0) + continue; + pr_debug("resolved '%s' to '%s'\n", file, result); + return 0; +-- +2.35.1 + diff --git a/queue-5.19/libbpf-fix-crash-if-sec-freplace-programs-don-t-have.patch b/queue-5.19/libbpf-fix-crash-if-sec-freplace-programs-don-t-have.patch new file mode 100644 index 00000000000..fb077203c6d --- /dev/null +++ b/queue-5.19/libbpf-fix-crash-if-sec-freplace-programs-don-t-have.patch @@ -0,0 +1,64 @@ +From 0be94f1fb1ca6e96e09481dd9f2b28e773986fbc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 12:30:52 -0700 +Subject: libbpf: Fix crash if SEC("freplace") programs don't have + attach_prog_fd set + +From: Andrii Nakryiko + +[ Upstream commit 749c202cb6ea40f4d7ac95c4a1217a7b506f43a8 ] + +Fix SIGSEGV caused by libbpf trying to find attach type in vmlinux BTF +for freplace programs. It's wrong to search in vmlinux BTF and libbpf +doesn't even mark vmlinux BTF as required for freplace programs. So +trying to search anything in obj->vmlinux_btf might cause NULL +dereference if nothing else in BPF object requires vmlinux BTF. + +Instead, error out if freplace (EXT) program doesn't specify +attach_prog_fd during at the load time. + +Fixes: 91abb4a6d79d ("libbpf: Support attachment of BPF tracing programs to kernel modules") +Signed-off-by: Andrii Nakryiko +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20220909193053.577111-3-andrii@kernel.org +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c +index 266357b1dca1..f179100d2a61 100644 +--- a/tools/lib/bpf/libbpf.c ++++ b/tools/lib/bpf/libbpf.c +@@ -9598,11 +9598,15 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac + int err = 0; + + /* BPF program's BTF ID */ +- if (attach_prog_fd) { ++ if (prog->type == BPF_PROG_TYPE_EXT || attach_prog_fd) { ++ if (!attach_prog_fd) { ++ pr_warn("prog '%s': attach program FD is not set\n", prog->name); ++ return -EINVAL; ++ } + err = libbpf_find_prog_btf_id(attach_name, attach_prog_fd); + if (err < 0) { +- pr_warn("failed to find BPF program (FD %d) BTF ID for '%s': %d\n", +- attach_prog_fd, attach_name, err); ++ pr_warn("prog '%s': failed to find BPF program (FD %d) BTF ID for '%s': %d\n", ++ prog->name, attach_prog_fd, attach_name, err); + return err; + } + *btf_obj_fd = 0; +@@ -9619,7 +9623,8 @@ static int libbpf_find_attach_btf_id(struct bpf_program *prog, const char *attac + err = find_kernel_btf_id(prog->obj, attach_name, attach_type, btf_obj_fd, btf_type_id); + } + if (err) { +- pr_warn("failed to find kernel BTF type ID of '%s': %d\n", attach_name, err); ++ pr_warn("prog '%s': failed to find kernel BTF type ID of '%s': %d\n", ++ prog->name, attach_name, err); + return err; + } + return 0; +-- +2.35.1 + diff --git a/queue-5.19/libbpf-fix-null-pointer-exception-in-api-btf_dump__d.patch b/queue-5.19/libbpf-fix-null-pointer-exception-in-api-btf_dump__d.patch new file mode 100644 index 00000000000..79cc5b0de7d --- /dev/null +++ b/queue-5.19/libbpf-fix-null-pointer-exception-in-api-btf_dump__d.patch @@ -0,0 +1,40 @@ +From 9db8e342e53ae8e4c3f81e529dc9423679863bd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 16:48:09 +0800 +Subject: libbpf: Fix NULL pointer exception in API btf_dump__dump_type_data + +From: Xin Liu + +[ Upstream commit 7620bffbf72cd66a5d18e444a143b5b5989efa87 ] + +We found that function btf_dump__dump_type_data can be called by the +user as an API, but in this function, the `opts` parameter may be used +as a null pointer.This causes `opts->indent_str` to trigger a NULL +pointer exception. + +Fixes: 2ce8450ef5a3 ("libbpf: add bpf_object__open_{file, mem} w/ extensible opts") +Signed-off-by: Xin Liu +Signed-off-by: Weibin Kong +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20220917084809.30770-1-liuxin350@huawei.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 6b1bc1f43728..9bad1d00f363 100644 +--- a/tools/lib/bpf/btf_dump.c ++++ b/tools/lib/bpf/btf_dump.c +@@ -2325,7 +2325,7 @@ int btf_dump__dump_type_data(struct btf_dump *d, __u32 id, + d->typed_dump->indent_lvl = OPTS_GET(opts, indent_level, 0); + + /* default indent string is a tab */ +- if (!opts->indent_str) ++ if (!OPTS_GET(opts, indent_str, NULL)) + d->typed_dump->indent_str[0] = '\t'; + else + libbpf_strlcpy(d->typed_dump->indent_str, opts->indent_str, +-- +2.35.1 + diff --git a/queue-5.19/libbpf-fix-overrun-in-netlink-attribute-iteration.patch b/queue-5.19/libbpf-fix-overrun-in-netlink-attribute-iteration.patch new file mode 100644 index 00000000000..d927702f33b --- /dev/null +++ b/queue-5.19/libbpf-fix-overrun-in-netlink-attribute-iteration.patch @@ -0,0 +1,38 @@ +From 804e8b72dae4def8d6bb59131c471e72a4c9248e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 17:07:08 +0800 +Subject: libbpf: Fix overrun in netlink attribute iteration + +From: Xin Liu + +[ Upstream commit 51e05a8cf8eb34da7473823b7f236a77adfef0b4 ] + +I accidentally found that a change in commit 1045b03e07d8 ("netlink: fix +overrun in attribute iteration") was not synchronized to the function +`nla_ok` in tools/lib/bpf/nlattr.c, I think it is necessary to modify, +this patch will do it. + +Signed-off-by: Xin Liu +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20220930090708.62394-1-liuxin350@huawei.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/nlattr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/nlattr.c b/tools/lib/bpf/nlattr.c +index f57e77a6e40f..3900d052ed19 100644 +--- a/tools/lib/bpf/nlattr.c ++++ b/tools/lib/bpf/nlattr.c +@@ -32,7 +32,7 @@ static struct nlattr *nla_next(const struct nlattr *nla, int *remaining) + + static int nla_ok(const struct nlattr *nla, int remaining) + { +- return remaining >= sizeof(*nla) && ++ return remaining >= (int)sizeof(*nla) && + nla->nla_len >= sizeof(*nla) && + nla->nla_len <= remaining; + } +-- +2.35.1 + diff --git a/queue-5.19/libbpf-initialize-err-in-probe_map_create.patch b/queue-5.19/libbpf-initialize-err-in-probe_map_create.patch new file mode 100644 index 00000000000..874435133d8 --- /dev/null +++ b/queue-5.19/libbpf-initialize-err-in-probe_map_create.patch @@ -0,0 +1,43 @@ +From 0457975144700445431d089a2d8eac38aa31f523 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 19:51:09 -0700 +Subject: libbpf: Initialize err in probe_map_create + +From: Florian Fainelli + +[ Upstream commit 3045f42a64324d339125a8a1a1763bb9e1e08300 ] + +GCC-11 warns about the possibly unitialized err variable in +probe_map_create: + +libbpf_probes.c: In function 'probe_map_create': +libbpf_probes.c:361:38: error: 'err' may be used uninitialized in this function [-Werror=maybe-uninitialized] + 361 | return fd < 0 && err == exp_err ? 1 : 0; + | ~~~~^~~~~~~~~~ + +Fixes: 878d8def0603 ("libbpf: Rework feature-probing APIs") +Signed-off-by: Florian Fainelli +Signed-off-by: Andrii Nakryiko +Acked-by: Jiri Olsa +Link: https://lore.kernel.org/bpf/20220801025109.1206633-1-f.fainelli@gmail.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/libbpf_probes.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c +index 97b06cede56f..6cf44e61815d 100644 +--- a/tools/lib/bpf/libbpf_probes.c ++++ b/tools/lib/bpf/libbpf_probes.c +@@ -247,7 +247,7 @@ static int probe_map_create(enum bpf_map_type map_type, __u32 ifindex) + LIBBPF_OPTS(bpf_map_create_opts, opts); + int key_size, value_size, max_entries; + __u32 btf_key_type_id = 0, btf_value_type_id = 0; +- int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err; ++ int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err = 0; + + opts.map_ifindex = ifindex; + +-- +2.35.1 + diff --git a/queue-5.19/linux-export-use-inline-assembler-to-populate-symbol.patch b/queue-5.19/linux-export-use-inline-assembler-to-populate-symbol.patch new file mode 100644 index 00000000000..9ad1deea325 --- /dev/null +++ b/queue-5.19/linux-export-use-inline-assembler-to-populate-symbol.patch @@ -0,0 +1,52 @@ +From 9eae22109a0dab6310527f5a198a41abdacee058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 15:29:53 +0900 +Subject: linux/export: use inline assembler to populate symbol CRCs + +From: Masahiro Yamada + +[ Upstream commit f3304ecd7f060db1d4197fbdce5a503259f770d3 ] + +Since commit 7b4537199a4a ("kbuild: link symbol CRCs at final link, +removing CONFIG_MODULE_REL_CRCS"), the module versioning on the +(non-upstreamed-yet) kvx Linux port is broken due to unexpected padding +for __crc_* symbols. The kvx GCC adds padding so u32 gets 8-byte +alignment instead of 4. + +I do not know if this happens for upstream architectures in general, +but any compiler has the freedom to insert padding for faster access. + +Use the inline assembler to directly specify the wanted data layout. +This is how we previously did before the breakage. + +Link: https://lore.kernel.org/lkml/20220817161438.32039-1-ysionneau@kalray.eu/ +Link: https://lore.kernel.org/linux-kbuild/31ce5305-a76b-13d7-ea55-afca82c46cf2@kalray.eu/ +Fixes: 7b4537199a4a ("kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS") +Reported-by: Yann Sionneau +Signed-off-by: Masahiro Yamada +Tested-by: Yann Sionneau +Signed-off-by: Sasha Levin +--- + include/linux/export-internal.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/include/linux/export-internal.h b/include/linux/export-internal.h +index c2b1d4fd5987..fe7e6ba918f1 100644 +--- a/include/linux/export-internal.h ++++ b/include/linux/export-internal.h +@@ -10,8 +10,10 @@ + #include + #include + +-/* __used is needed to keep __crc_* for LTO */ + #define SYMBOL_CRC(sym, crc, sec) \ +- u32 __section("___kcrctab" sec "+" #sym) __used __crc_##sym = crc ++ asm(".section \"___kcrctab" sec "+" #sym "\",\"a\"" "\n" \ ++ "__crc_" #sym ":" "\n" \ ++ ".long " #crc "\n" \ ++ ".previous" "\n") + + #endif /* __LINUX_EXPORT_INTERNAL_H__ */ +-- +2.35.1 + diff --git a/queue-5.19/locks-fix-toctou-race-when-granting-write-lease.patch b/queue-5.19/locks-fix-toctou-race-when-granting-write-lease.patch new file mode 100644 index 00000000000..39cc4c933f6 --- /dev/null +++ b/queue-5.19/locks-fix-toctou-race-when-granting-write-lease.patch @@ -0,0 +1,114 @@ +From 66677444ce0dca10ab7847242d84cc9856836579 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 17:53:17 +0300 +Subject: locks: fix TOCTOU race when granting write lease + +From: Amir Goldstein + +[ Upstream commit d6da19c9cace63290ccfccb1fc35151ffefc0bec ] + +Thread A trying to acquire a write lease checks the value of i_readcount +and i_writecount in check_conflicting_open() to verify that its own fd +is the only fd referencing the file. + +Thread B trying to open the file for read will call break_lease() in +do_dentry_open() before incrementing i_readcount, which leaves a small +window where thread A can acquire the write lease and then thread B +completes the open of the file for read without breaking the write lease +that was acquired by thread A. + +Fix this race by incrementing i_readcount before checking for existing +leases, same as the case with i_writecount. + +Use a helper put_file_access() to decrement i_readcount or i_writecount +in do_dentry_open() and __fput(). + +Fixes: 387e3746d01c ("locks: eliminate false positive conflicts for write lease") +Reviewed-by: Jeff Layton +Signed-off-by: Amir Goldstein +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + fs/file_table.c | 7 +------ + fs/internal.h | 10 ++++++++++ + fs/open.c | 11 ++++------- + 3 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/fs/file_table.c b/fs/file_table.c +index 5424e3a8df5f..543a501b0247 100644 +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -321,12 +321,7 @@ static void __fput(struct file *file) + } + fops_put(file->f_op); + put_pid(file->f_owner.pid); +- if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) +- i_readcount_dec(inode); +- if (mode & FMODE_WRITER) { +- put_write_access(inode); +- __mnt_drop_write(mnt); +- } ++ put_file_access(file); + dput(dentry); + if (unlikely(mode & FMODE_NEED_UNMOUNT)) + dissolve_on_fput(mnt); +diff --git a/fs/internal.h b/fs/internal.h +index 3e206d3e317c..4372d67a3753 100644 +--- a/fs/internal.h ++++ b/fs/internal.h +@@ -102,6 +102,16 @@ extern void chroot_fs_refs(const struct path *, const struct path *); + extern struct file *alloc_empty_file(int, const struct cred *); + extern struct file *alloc_empty_file_noaccount(int, const struct cred *); + ++static inline void put_file_access(struct file *file) ++{ ++ if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { ++ i_readcount_dec(file->f_inode); ++ } else if (file->f_mode & FMODE_WRITER) { ++ put_write_access(file->f_inode); ++ __mnt_drop_write(file->f_path.mnt); ++ } ++} ++ + /* + * super.c + */ +diff --git a/fs/open.c b/fs/open.c +index 1d57fbde2feb..5874258b54bd 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -810,7 +810,9 @@ static int do_dentry_open(struct file *f, + return 0; + } + +- if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) { ++ if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { ++ i_readcount_inc(inode); ++ } else if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) { + error = get_write_access(inode); + if (unlikely(error)) + goto cleanup_file; +@@ -850,8 +852,6 @@ static int do_dentry_open(struct file *f, + goto cleanup_all; + } + f->f_mode |= FMODE_OPENED; +- if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) +- i_readcount_inc(inode); + if ((f->f_mode & FMODE_READ) && + likely(f->f_op->read || f->f_op->read_iter)) + f->f_mode |= FMODE_CAN_READ; +@@ -902,10 +902,7 @@ static int do_dentry_open(struct file *f, + if (WARN_ON_ONCE(error > 0)) + error = -EINVAL; + fops_put(f->f_op); +- if (f->f_mode & FMODE_WRITER) { +- put_write_access(inode); +- __mnt_drop_write(f->f_path.mnt); +- } ++ put_file_access(f); + cleanup_file: + path_put(&f->f_path); + f->f_path.mnt = NULL; +-- +2.35.1 + diff --git a/queue-5.19/mailbox-bcm-ferxrm-mailbox-fix-error-check-for-dma_m.patch b/queue-5.19/mailbox-bcm-ferxrm-mailbox-fix-error-check-for-dma_m.patch new file mode 100644 index 00000000000..dff793364d6 --- /dev/null +++ b/queue-5.19/mailbox-bcm-ferxrm-mailbox-fix-error-check-for-dma_m.patch @@ -0,0 +1,47 @@ +From 3e3fd64cd0045ef12d60b8fcee1bef23078d6b68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 12:13:35 +0200 +Subject: mailbox: bcm-ferxrm-mailbox: Fix error check for dma_map_sg + +From: Jack Wang + +[ Upstream commit 6b207ce8a96a71e966831e3a13c38143ba9a73c1 ] + +dma_map_sg return 0 on error, fix the error check, and return -EIO +to caller. + +Fixes: dbc049eee730 ("mailbox: Add driver for Broadcom FlexRM ring manager") +Signed-off-by: Jack Wang +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/bcm-flexrm-mailbox.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/bcm-flexrm-mailbox.c b/drivers/mailbox/bcm-flexrm-mailbox.c +index 22acb51531cb..658e47b21933 100644 +--- a/drivers/mailbox/bcm-flexrm-mailbox.c ++++ b/drivers/mailbox/bcm-flexrm-mailbox.c +@@ -632,15 +632,15 @@ static int flexrm_spu_dma_map(struct device *dev, struct brcm_message *msg) + + rc = dma_map_sg(dev, msg->spu.src, sg_nents(msg->spu.src), + DMA_TO_DEVICE); +- if (rc < 0) +- return rc; ++ if (!rc) ++ return -EIO; + + rc = dma_map_sg(dev, msg->spu.dst, sg_nents(msg->spu.dst), + DMA_FROM_DEVICE); +- if (rc < 0) { ++ if (!rc) { + dma_unmap_sg(dev, msg->spu.src, sg_nents(msg->spu.src), + DMA_TO_DEVICE); +- return rc; ++ return -EIO; + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.19/mailbox-mpfs-account-for-mbox-offsets-while-sending.patch b/queue-5.19/mailbox-mpfs-account-for-mbox-offsets-while-sending.patch new file mode 100644 index 00000000000..9db4dd8e292 --- /dev/null +++ b/queue-5.19/mailbox-mpfs-account-for-mbox-offsets-while-sending.patch @@ -0,0 +1,60 @@ +From 4cb17dc9765d35c7bfda768fcf27fb9ada107ba6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 08:08:12 +0100 +Subject: mailbox: mpfs: account for mbox offsets while sending + +From: Conor Dooley + +[ Upstream commit 0d1aadfe10ba17ebdeb96abb9638eb0f623f9b55 ] + +The mailbox offset is not only used for receiving messages, but it is +also used by messages sent to the system controller by Linux that have a +payload, such as the "digital signature service". It is also overloaded +by certain other services (reprogramming of the FPGA fabric, see Link:) +to have a meaning other than the offset the system controller should +read from. +When the driver was written, no such services of the latter type were +in use & those of the former used an offset of zero so this has gone +un-noticed. + +Link: https://www.microsemi.com/document-portal/doc_download/1245815-polarfire-fpga-and-polarfire-soc-fpga-system-services-user-guide # Section 5.2 +Fixes: 83d7b1560810 ("mbox: add polarfire soc system controller mailbox") +Signed-off-by: Conor Dooley +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-mpfs.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c +index e432a8f0d148..cfacb3f320a6 100644 +--- a/drivers/mailbox/mailbox-mpfs.c ++++ b/drivers/mailbox/mailbox-mpfs.c +@@ -100,21 +100,20 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data) + + for (index = 0; index < (msg->cmd_data_size / 4); index++) + writel_relaxed(word_buf[index], +- mbox->mbox_base + index * 0x4); ++ mbox->mbox_base + msg->mbox_offset + index * 0x4); + if (extra_bits) { + u8 i; + u8 byte_off = ALIGN_DOWN(msg->cmd_data_size, 4); + u8 *byte_buf = msg->cmd_data + byte_off; + +- val = readl_relaxed(mbox->mbox_base + index * 0x4); ++ val = readl_relaxed(mbox->mbox_base + msg->mbox_offset + index * 0x4); + + for (i = 0u; i < extra_bits; i++) { + val &= ~(0xffu << (i * 8u)); + val |= (byte_buf[i] << (i * 8u)); + } + +- writel_relaxed(val, +- mbox->mbox_base + index * 0x4); ++ writel_relaxed(val, mbox->mbox_base + msg->mbox_offset + index * 0x4); + } + } + +-- +2.35.1 + diff --git a/queue-5.19/mailbox-mpfs-fix-handling-of-the-reg-property.patch b/queue-5.19/mailbox-mpfs-fix-handling-of-the-reg-property.patch new file mode 100644 index 00000000000..a0b39f84b5e --- /dev/null +++ b/queue-5.19/mailbox-mpfs-fix-handling-of-the-reg-property.patch @@ -0,0 +1,113 @@ +From 5c8a1e71760aef09dc6a72baf61dd08db8329d99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 08:08:11 +0100 +Subject: mailbox: mpfs: fix handling of the reg property + +From: Conor Dooley + +[ Upstream commit 2e10289d1f304f5082a4dda55a677b72b3bdb581 ] + +The "data" region of the PolarFire SoC's system controller mailbox is +not one continuous register space - the system controller's QSPI sits +between the control and data registers. Split the "data" reg into two +parts: "data" & "control". Optionally get the "data" register address +from the 3rd reg property in the devicetree & fall back to using the +old base + MAILBOX_REG_OFFSET that the current code uses. + +Fixes: 83d7b1560810 ("mbox: add polarfire soc system controller mailbox") +Signed-off-by: Conor Dooley +Signed-off-by: Jassi Brar +Signed-off-by: Sasha Levin +--- + drivers/mailbox/mailbox-mpfs.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/drivers/mailbox/mailbox-mpfs.c b/drivers/mailbox/mailbox-mpfs.c +index 4e34854d1238..e432a8f0d148 100644 +--- a/drivers/mailbox/mailbox-mpfs.c ++++ b/drivers/mailbox/mailbox-mpfs.c +@@ -62,6 +62,7 @@ struct mpfs_mbox { + struct mbox_controller controller; + struct device *dev; + int irq; ++ void __iomem *ctrl_base; + void __iomem *mbox_base; + void __iomem *int_reg; + struct mbox_chan chans[1]; +@@ -73,7 +74,7 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox) + { + u32 status; + +- status = readl_relaxed(mbox->mbox_base + SERVICES_SR_OFFSET); ++ status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); + + return status & SCB_STATUS_BUSY_MASK; + } +@@ -99,14 +100,13 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data) + + for (index = 0; index < (msg->cmd_data_size / 4); index++) + writel_relaxed(word_buf[index], +- mbox->mbox_base + MAILBOX_REG_OFFSET + index * 0x4); ++ mbox->mbox_base + index * 0x4); + if (extra_bits) { + u8 i; + u8 byte_off = ALIGN_DOWN(msg->cmd_data_size, 4); + u8 *byte_buf = msg->cmd_data + byte_off; + +- val = readl_relaxed(mbox->mbox_base + +- MAILBOX_REG_OFFSET + index * 0x4); ++ val = readl_relaxed(mbox->mbox_base + index * 0x4); + + for (i = 0u; i < extra_bits; i++) { + val &= ~(0xffu << (i * 8u)); +@@ -114,14 +114,14 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data) + } + + writel_relaxed(val, +- mbox->mbox_base + MAILBOX_REG_OFFSET + index * 0x4); ++ mbox->mbox_base + index * 0x4); + } + } + + opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu)); + tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK; + tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK; +- writel_relaxed(tx_trigger, mbox->mbox_base + SERVICES_CR_OFFSET); ++ writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET); + + return 0; + } +@@ -141,7 +141,7 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan) + if (!mpfs_mbox_busy(mbox)) { + for (i = 0; i < num_words; i++) { + response->resp_msg[i] = +- readl_relaxed(mbox->mbox_base + MAILBOX_REG_OFFSET ++ readl_relaxed(mbox->mbox_base + + mbox->resp_offset + i * 0x4); + } + } +@@ -200,14 +200,18 @@ static int mpfs_mbox_probe(struct platform_device *pdev) + if (!mbox) + return -ENOMEM; + +- mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); +- if (IS_ERR(mbox->mbox_base)) +- return PTR_ERR(mbox->mbox_base); ++ mbox->ctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); ++ if (IS_ERR(mbox->ctrl_base)) ++ return PTR_ERR(mbox->ctrl_base); + + mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, ®s); + if (IS_ERR(mbox->int_reg)) + return PTR_ERR(mbox->int_reg); + ++ mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 2, ®s); ++ if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs ++ mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET; ++ + mbox->irq = platform_get_irq(pdev, 0); + if (mbox->irq < 0) + return mbox->irq; +-- +2.35.1 + diff --git a/queue-5.19/md-raid5-ensure-stripe_fill-happens-on-non-read-io-w.patch b/queue-5.19/md-raid5-ensure-stripe_fill-happens-on-non-read-io-w.patch new file mode 100644 index 00000000000..4b08c243b79 --- /dev/null +++ b/queue-5.19/md-raid5-ensure-stripe_fill-happens-on-non-read-io-w.patch @@ -0,0 +1,48 @@ +From 9895d10789b86defaf5f2d5d0fb168f8556a459f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 09:46:27 -0600 +Subject: md/raid5: Ensure stripe_fill happens on non-read IO with journal + +From: Logan Gunthorpe + +[ Upstream commit e2eed85bc75138a9eeb63863d20f8904ac42a577 ] + +When doing degrade/recover tests using the journal a kernel BUG +is hit at drivers/md/raid5.c:4381 in handle_parity_checks5(): + + BUG_ON(!test_bit(R5_UPTODATE, &dev->flags)); + +This was found to occur because handle_stripe_fill() was skipped +for stripes in the journal due to a condition in that function. +Thus blocks were not fetched and R5_UPTODATE was not set when +the code reached handle_parity_checks5(). + +To fix this, don't skip handle_stripe_fill() unless the stripe is +for read. + +Fixes: 07e83364845e ("md/r5cache: shift complex rmw from read path to write path") +Link: https://lore.kernel.org/linux-raid/e05c4239-41a9-d2f7-3cfa-4aa9d2cea8c1@deltatee.com/ +Suggested-by: Song Liu +Signed-off-by: Logan Gunthorpe +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid5.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index 1c1310d539f2..d6cad962669a 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -3951,7 +3951,7 @@ static void handle_stripe_fill(struct stripe_head *sh, + * back cache (prexor with orig_page, and then xor with + * page) in the read path + */ +- if (s->injournal && s->failed) { ++ if (s->to_read && s->injournal && s->failed) { + if (test_bit(STRIPE_R5C_CACHING, &sh->state)) + r5c_make_stripe_write_out(sh); + goto out; +-- +2.35.1 + diff --git a/queue-5.19/md-raid5-remove-unnecessary-bio_put-in-raid5_read_on.patch b/queue-5.19/md-raid5-remove-unnecessary-bio_put-in-raid5_read_on.patch new file mode 100644 index 00000000000..02ebd6fbbd4 --- /dev/null +++ b/queue-5.19/md-raid5-remove-unnecessary-bio_put-in-raid5_read_on.patch @@ -0,0 +1,116 @@ +From ed513bbe3682d464f96bb4d576fb742ec26bf1b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 10:15:14 -0600 +Subject: md/raid5: Remove unnecessary bio_put() in raid5_read_one_chunk() + +From: David Sloan + +[ Upstream commit c66a6f41e09ad386fd2cce22b9cded837bbbc704 ] + +When running chunk-sized reads on disks with badblocks duplicate bio +free/puts are observed: + + ============================================================================= + BUG bio-200 (Not tainted): Object already free + ----------------------------------------------------------------------------- + Allocated in mempool_alloc_slab+0x17/0x20 age=3 cpu=2 pid=7504 + __slab_alloc.constprop.0+0x5a/0xb0 + kmem_cache_alloc+0x31e/0x330 + mempool_alloc_slab+0x17/0x20 + mempool_alloc+0x100/0x2b0 + bio_alloc_bioset+0x181/0x460 + do_mpage_readpage+0x776/0xd00 + mpage_readahead+0x166/0x320 + blkdev_readahead+0x15/0x20 + read_pages+0x13f/0x5f0 + page_cache_ra_unbounded+0x18d/0x220 + force_page_cache_ra+0x181/0x1c0 + page_cache_sync_ra+0x65/0xb0 + filemap_get_pages+0x1df/0xaf0 + filemap_read+0x1e1/0x700 + blkdev_read_iter+0x1e5/0x330 + vfs_read+0x42a/0x570 + Freed in mempool_free_slab+0x17/0x20 age=3 cpu=2 pid=7504 + kmem_cache_free+0x46d/0x490 + mempool_free_slab+0x17/0x20 + mempool_free+0x66/0x190 + bio_free+0x78/0x90 + bio_put+0x100/0x1a0 + raid5_make_request+0x2259/0x2450 + md_handle_request+0x402/0x600 + md_submit_bio+0xd9/0x120 + __submit_bio+0x11f/0x1b0 + submit_bio_noacct_nocheck+0x204/0x480 + submit_bio_noacct+0x32e/0xc70 + submit_bio+0x98/0x1a0 + mpage_readahead+0x250/0x320 + blkdev_readahead+0x15/0x20 + read_pages+0x13f/0x5f0 + page_cache_ra_unbounded+0x18d/0x220 + Slab 0xffffea000481b600 objects=21 used=0 fp=0xffff8881206d8940 flags=0x17ffffc0010201(locked|slab|head|node=0|zone=2|lastcpupid=0x1fffff) + CPU: 0 PID: 34525 Comm: kworker/u24:2 Not tainted 6.0.0-rc2-localyes-265166-gf11c5343fa3f #143 + Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014 + Workqueue: raid5wq raid5_do_work + Call Trace: + + dump_stack_lvl+0x5a/0x78 + dump_stack+0x10/0x16 + print_trailer+0x158/0x165 + object_err+0x35/0x50 + free_debug_processing.cold+0xb7/0xbe + __slab_free+0x1ae/0x330 + kmem_cache_free+0x46d/0x490 + mempool_free_slab+0x17/0x20 + mempool_free+0x66/0x190 + bio_free+0x78/0x90 + bio_put+0x100/0x1a0 + mpage_end_io+0x36/0x150 + bio_endio+0x2fd/0x360 + md_end_io_acct+0x7e/0x90 + bio_endio+0x2fd/0x360 + handle_failed_stripe+0x960/0xb80 + handle_stripe+0x1348/0x3760 + handle_active_stripes.constprop.0+0x72a/0xaf0 + raid5_do_work+0x177/0x330 + process_one_work+0x616/0xb20 + worker_thread+0x2bd/0x6f0 + kthread+0x179/0x1b0 + ret_from_fork+0x22/0x30 + + +The double free is caused by an unnecessary bio_put() in the +if(is_badblock(...)) error path in raid5_read_one_chunk(). + +The error path was moved ahead of bio_alloc_clone() in c82aa1b76787c +("md/raid5: move checking badblock before clone bio in +raid5_read_one_chunk"). The previous code checked and freed align_bio +which required a bio_put. After the move that is no longer needed as +raid_bio is returned to the control of the common io path which +performs its own endio resulting in a double free on bad device blocks. + +Fixes: c82aa1b76787c ("md/raid5: move checking badblock before clone bio in raid5_read_one_chunk") +Signed-off-by: David Sloan +Signed-off-by: Logan Gunthorpe +Reviewed-by: Christoph Hellwig +Acked-by: Guoqing Jiang +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid5.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index d6cad962669a..f498bd4af8c2 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -5446,7 +5446,6 @@ static int raid5_read_one_chunk(struct mddev *mddev, struct bio *raid_bio) + + if (is_badblock(rdev, sector, bio_sectors(raid_bio), &first_bad, + &bad_sectors)) { +- bio_put(raid_bio); + rdev_dec_pending(rdev, mddev); + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/md-raid5-wait-for-md_sb_change_pending-in-raid5d.patch b/queue-5.19/md-raid5-wait-for-md_sb_change_pending-in-raid5d.patch new file mode 100644 index 00000000000..41a277dff98 --- /dev/null +++ b/queue-5.19/md-raid5-wait-for-md_sb_change_pending-in-raid5d.patch @@ -0,0 +1,145 @@ +From 9829743663b1245e99103b5157614f60b5943c4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 10:28:37 -0600 +Subject: md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d + +From: Logan Gunthorpe + +[ Upstream commit 5e2cf333b7bd5d3e62595a44d598a254c697cd74 ] + +A complicated deadlock exists when using the journal and an elevated +group_thrtead_cnt. It was found with loop devices, but its not clear +whether it can be seen with real disks. The deadlock can occur simply +by writing data with an fio script. + +When the deadlock occurs, multiple threads will hang in different ways: + + 1) The group threads will hang in the blk-wbt code with bios waiting to + be submitted to the block layer: + + io_schedule+0x70/0xb0 + rq_qos_wait+0x153/0x210 + wbt_wait+0x115/0x1b0 + io_schedule+0x70/0xb0 + rq_qos_wait+0x153/0x210 + wbt_wait+0x115/0x1b0 + __rq_qos_throttle+0x38/0x60 + blk_mq_submit_bio+0x589/0xcd0 + wbt_wait+0x115/0x1b0 + __rq_qos_throttle+0x38/0x60 + blk_mq_submit_bio+0x589/0xcd0 + __submit_bio+0xe6/0x100 + submit_bio_noacct_nocheck+0x42e/0x470 + submit_bio_noacct+0x4c2/0xbb0 + ops_run_io+0x46b/0x1a30 + handle_stripe+0xcd3/0x36b0 + handle_active_stripes.constprop.0+0x6f6/0xa60 + raid5_do_work+0x177/0x330 + + Or: + io_schedule+0x70/0xb0 + rq_qos_wait+0x153/0x210 + wbt_wait+0x115/0x1b0 + __rq_qos_throttle+0x38/0x60 + blk_mq_submit_bio+0x589/0xcd0 + __submit_bio+0xe6/0x100 + submit_bio_noacct_nocheck+0x42e/0x470 + submit_bio_noacct+0x4c2/0xbb0 + flush_deferred_bios+0x136/0x170 + raid5_do_work+0x262/0x330 + + 2) The r5l_reclaim thread will hang in the same way, submitting a + bio to the block layer: + + io_schedule+0x70/0xb0 + rq_qos_wait+0x153/0x210 + wbt_wait+0x115/0x1b0 + __rq_qos_throttle+0x38/0x60 + blk_mq_submit_bio+0x589/0xcd0 + __submit_bio+0xe6/0x100 + submit_bio_noacct_nocheck+0x42e/0x470 + submit_bio_noacct+0x4c2/0xbb0 + submit_bio+0x3f/0xf0 + md_super_write+0x12f/0x1b0 + md_update_sb.part.0+0x7c6/0xff0 + md_update_sb+0x30/0x60 + r5l_do_reclaim+0x4f9/0x5e0 + r5l_reclaim_thread+0x69/0x30b + + However, before hanging, the MD_SB_CHANGE_PENDING flag will be + set for sb_flags in r5l_write_super_and_discard_space(). This + flag will never be cleared because the submit_bio() call never + returns. + + 3) Due to the MD_SB_CHANGE_PENDING flag being set, handle_stripe() + will do no processing on any pending stripes and re-set + STRIPE_HANDLE. This will cause the raid5d thread to enter an + infinite loop, constantly trying to handle the same stripes + stuck in the queue. + + The raid5d thread has a blk_plug that holds a number of bios + that are also stuck waiting seeing the thread is in a loop + that never schedules. These bios have been accounted for by + blk-wbt thus preventing the other threads above from + continuing when they try to submit bios. --Deadlock. + +To fix this, add the same wait_event() that is used in raid5_do_work() +to raid5d() such that if MD_SB_CHANGE_PENDING is set, the thread will +schedule and wait until the flag is cleared. The schedule action will +flush the plug which will allow the r5l_reclaim thread to continue, +thus preventing the deadlock. + +However, md_check_recovery() calls can also clear MD_SB_CHANGE_PENDING +from the same thread and can thus deadlock if the thread is put to +sleep. So avoid waiting if md_check_recovery() is being called in the +loop. + +It's not clear when the deadlock was introduced, but the similar +wait_event() call in raid5_do_work() was added in 2017 by this +commit: + + 16d997b78b15 ("md/raid5: simplfy delaying of writes while metadata + is updated.") + +Link: https://lore.kernel.org/r/7f3b87b6-b52a-f737-51d7-a4eec5c44112@deltatee.com +Signed-off-by: Logan Gunthorpe +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid5.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c +index f498bd4af8c2..cdb5ae435b78 100644 +--- a/drivers/md/raid5.c ++++ b/drivers/md/raid5.c +@@ -36,6 +36,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -6552,7 +6553,18 @@ static void raid5d(struct md_thread *thread) + spin_unlock_irq(&conf->device_lock); + md_check_recovery(mddev); + spin_lock_irq(&conf->device_lock); ++ ++ /* ++ * Waiting on MD_SB_CHANGE_PENDING below may deadlock ++ * seeing md_check_recovery() is needed to clear ++ * the flag when using mdmon. ++ */ ++ continue; + } ++ ++ wait_event_lock_irq(mddev->sb_wait, ++ !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags), ++ conf->device_lock); + } + pr_debug("%d stripes handled\n", handled); + +-- +2.35.1 + diff --git a/queue-5.19/md-replace-snprintf-with-scnprintf.patch b/queue-5.19/md-replace-snprintf-with-scnprintf.patch new file mode 100644 index 00000000000..b8e8be13707 --- /dev/null +++ b/queue-5.19/md-replace-snprintf-with-scnprintf.patch @@ -0,0 +1,71 @@ +From 34a34c70ada57a31ae6fb831da1a073c32d213a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 11:51:04 -0700 +Subject: md: Replace snprintf with scnprintf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Saurabh Sengar + +[ Upstream commit 1727fd5015d8f93474148f94e34cda5aa6ad4a43 ] + +Current code produces a warning as shown below when total characters +in the constituent block device names plus the slashes exceeds 200. +snprintf() returns the number of characters generated from the given +input, which could cause the expression “200 – len” to wrap around +to a large positive number. Fix this by using scnprintf() instead, +which returns the actual number of characters written into the buffer. + +[ 1513.267938] ------------[ cut here ]------------ +[ 1513.267943] WARNING: CPU: 15 PID: 37247 at /lib/vsprintf.c:2509 vsnprintf+0x2c8/0x510 +[ 1513.267944] Modules linked in: +[ 1513.267969] CPU: 15 PID: 37247 Comm: mdadm Not tainted 5.4.0-1085-azure #90~18.04.1-Ubuntu +[ 1513.267969] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 05/09/2022 +[ 1513.267971] RIP: 0010:vsnprintf+0x2c8/0x510 +<-snip-> +[ 1513.267982] Call Trace: +[ 1513.267986] snprintf+0x45/0x70 +[ 1513.267990] ? disk_name+0x71/0xa0 +[ 1513.267993] dump_zones+0x114/0x240 [raid0] +[ 1513.267996] ? _cond_resched+0x19/0x40 +[ 1513.267998] raid0_run+0x19e/0x270 [raid0] +[ 1513.268000] md_run+0x5e0/0xc50 +[ 1513.268003] ? security_capable+0x3f/0x60 +[ 1513.268005] do_md_run+0x19/0x110 +[ 1513.268006] md_ioctl+0x195e/0x1f90 +[ 1513.268007] blkdev_ioctl+0x91f/0x9f0 +[ 1513.268010] block_ioctl+0x3d/0x50 +[ 1513.268012] do_vfs_ioctl+0xa9/0x640 +[ 1513.268014] ? __fput+0x162/0x260 +[ 1513.268016] ksys_ioctl+0x75/0x80 +[ 1513.268017] __x64_sys_ioctl+0x1a/0x20 +[ 1513.268019] do_syscall_64+0x5e/0x200 +[ 1513.268021] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: 766038846e875 ("md/raid0: replace printk() with pr_*()") +Reviewed-by: Michael Kelley +Acked-by: Guoqing Jiang +Signed-off-by: Saurabh Sengar +Signed-off-by: Song Liu +Signed-off-by: Sasha Levin +--- + drivers/md/raid0.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c +index 78addfe4a0c9..857c49399c28 100644 +--- a/drivers/md/raid0.c ++++ b/drivers/md/raid0.c +@@ -47,7 +47,7 @@ static void dump_zones(struct mddev *mddev) + int len = 0; + + for (k = 0; k < conf->strip_zone[j].nb_dev; k++) +- len += snprintf(line+len, 200-len, "%s%pg", k?"/":"", ++ len += scnprintf(line+len, 200-len, "%s%pg", k?"/":"", + conf->devlist[j * raid_disks + k]->bdev); + pr_debug("md: zone%d=[%s]\n", j, line); + +-- +2.35.1 + diff --git a/queue-5.19/media-amphion-adjust-the-encoder-s-value-range-of-go.patch b/queue-5.19/media-amphion-adjust-the-encoder-s-value-range-of-go.patch new file mode 100644 index 00000000000..b85ad6f4789 --- /dev/null +++ b/queue-5.19/media-amphion-adjust-the-encoder-s-value-range-of-go.patch @@ -0,0 +1,39 @@ +From 0471f29e716d939b084d01bfac99a63e237900eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Jul 2022 09:38:00 +0200 +Subject: media: amphion: adjust the encoder's value range of gop size + +From: Ming Qian + +[ Upstream commit 996f4e89fabe44ab9ac0aabb0697aeecbe717eca ] + +adjust the value range of gop size from [0, 65535] to [1, 8000]. +when the gop size is set to a too large value, +it may affect the encoded picture quality. +so constrain it to a reasonable range. + +Fixes: 0401e659c1f92 ("media: amphion: add v4l2 m2m vpu encoder stateful driver") +Signed-off-by: Ming Qian +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/amphion/venc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c +index 43d61d82f58c..0f21a181c1de 100644 +--- a/drivers/media/platform/amphion/venc.c ++++ b/drivers/media/platform/amphion/venc.c +@@ -644,7 +644,7 @@ static int venc_ctrl_init(struct vpu_inst *inst) + BITRATE_DEFAULT_PEAK); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, +- V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30); ++ V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 8000, 1, 30); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_B_FRAMES, 0, 4, 1, 0); +-- +2.35.1 + diff --git a/queue-5.19/media-amphion-don-t-change-the-colorspace-reported-b.patch b/queue-5.19/media-amphion-don-t-change-the-colorspace-reported-b.patch new file mode 100644 index 00000000000..656caf78a83 --- /dev/null +++ b/queue-5.19/media-amphion-don-t-change-the-colorspace-reported-b.patch @@ -0,0 +1,60 @@ +From 6f686c55bb87ef667daae3ad3123a9129eacf4d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Jul 2022 05:02:29 +0200 +Subject: media: amphion: don't change the colorspace reported by decoder. + +From: Ming Qian + +[ Upstream commit 61c2698ee60630c6a7d2e99850fa81ff6450270a ] + +decoder will report the colorspace information +which is parsed from the sequence header, +if they are unspecified, just let application to determine it, +don't change it in driver. + +Fixes: 6de8d628df6ef ("media: amphion: add v4l2 m2m vpu decoder stateful driver") +Signed-off-by: Ming Qian +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/amphion/vdec.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c +index 44dbca0fe17f..6d6842ff12e2 100644 +--- a/drivers/media/platform/amphion/vdec.c ++++ b/drivers/media/platform/amphion/vdec.c +@@ -808,14 +808,6 @@ static void vdec_init_fmt(struct vpu_inst *inst) + inst->cap_format.field = V4L2_FIELD_NONE; + else + inst->cap_format.field = V4L2_FIELD_SEQ_TB; +- if (vdec->codec_info.color_primaries == V4L2_COLORSPACE_DEFAULT) +- vdec->codec_info.color_primaries = V4L2_COLORSPACE_REC709; +- if (vdec->codec_info.transfer_chars == V4L2_XFER_FUNC_DEFAULT) +- vdec->codec_info.transfer_chars = V4L2_XFER_FUNC_709; +- if (vdec->codec_info.matrix_coeffs == V4L2_YCBCR_ENC_DEFAULT) +- vdec->codec_info.matrix_coeffs = V4L2_YCBCR_ENC_709; +- if (vdec->codec_info.full_range == V4L2_QUANTIZATION_DEFAULT) +- vdec->codec_info.full_range = V4L2_QUANTIZATION_LIM_RANGE; + } + + static void vdec_init_crop(struct vpu_inst *inst) +@@ -1556,6 +1548,14 @@ static int vdec_get_debug_info(struct vpu_inst *inst, char *str, u32 size, u32 i + vdec->codec_info.frame_rate.numerator, + vdec->codec_info.frame_rate.denominator); + break; ++ case 9: ++ num = scnprintf(str, size, "colorspace: %d, %d, %d, %d (%d)\n", ++ vdec->codec_info.color_primaries, ++ vdec->codec_info.transfer_chars, ++ vdec->codec_info.matrix_coeffs, ++ vdec->codec_info.full_range, ++ vdec->codec_info.vui_present); ++ break; + default: + break; + } +-- +2.35.1 + diff --git a/queue-5.19/media-amphion-fix-a-bug-that-vpu-core-may-not-resume.patch b/queue-5.19/media-amphion-fix-a-bug-that-vpu-core-may-not-resume.patch new file mode 100644 index 00000000000..8926dc7bec5 --- /dev/null +++ b/queue-5.19/media-amphion-fix-a-bug-that-vpu-core-may-not-resume.patch @@ -0,0 +1,264 @@ +From db92528c3a17ffc424090bc2f6cc7b22ee9e3033 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 05:18:21 +0200 +Subject: media: amphion: fix a bug that vpu core may not resume after suspend + +From: Ming Qian + +[ Upstream commit 0202a665bf17fbe98fed954944aabbcb4f14a4cc ] + +driver will enable the vpu core when request the first instance +on the core. +one vpu core can only support 8 streaming instances in the same +time, the instance won't be added to core's list before streamon. + +so the actual instance count may be greater then the number in +the core's list. + +in pm resume callback, driver will resume the core immediately if +core's list is not empty. +but this check is not accurate, +if suspend during one instance is requested, but not streamon, +then after suspend, the core won't be resume, and led to instance failure. + +use the request_count instead of the core's list to check +whether is the core needed to resume immediately after suspend. + +And it can make the pm suspend and resume callback more clear. + +Fixes: 9f599f351e86 ("media: amphion: add vpu core driver") +Signed-off-by: Ming Qian +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/amphion/vpu.h | 1 - + drivers/media/platform/amphion/vpu_core.c | 84 ++++++++++++----------- + drivers/media/platform/amphion/vpu_core.h | 1 + + drivers/media/platform/amphion/vpu_dbg.c | 9 ++- + 4 files changed, 51 insertions(+), 44 deletions(-) + +diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h +index f914de6ed81e..beac0309ca8d 100644 +--- a/drivers/media/platform/amphion/vpu.h ++++ b/drivers/media/platform/amphion/vpu.h +@@ -119,7 +119,6 @@ struct vpu_mbox { + enum vpu_core_state { + VPU_CORE_DEINIT = 0, + VPU_CORE_ACTIVE, +- VPU_CORE_SNAPSHOT, + VPU_CORE_HANG + }; + +diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c +index 51a764713159..21a416b8e483 100644 +--- a/drivers/media/platform/amphion/vpu_core.c ++++ b/drivers/media/platform/amphion/vpu_core.c +@@ -89,7 +89,7 @@ static int vpu_core_boot_done(struct vpu_core *core) + core->supported_instance_count = min(core->supported_instance_count, count); + } + core->fw_version = fw_version; +- core->state = VPU_CORE_ACTIVE; ++ vpu_core_set_state(core, VPU_CORE_ACTIVE); + + return 0; + } +@@ -172,10 +172,26 @@ int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf) + return __vpu_alloc_dma(core->dev, buf); + } + +-static void vpu_core_check_hang(struct vpu_core *core) ++void vpu_core_set_state(struct vpu_core *core, enum vpu_core_state state) + { +- if (core->hang_mask) +- core->state = VPU_CORE_HANG; ++ if (state != core->state) ++ vpu_trace(core->dev, "vpu core state change from %d to %d\n", core->state, state); ++ core->state = state; ++ if (core->state == VPU_CORE_DEINIT) ++ core->hang_mask = 0; ++} ++ ++static void vpu_core_update_state(struct vpu_core *core) ++{ ++ if (!vpu_iface_get_power_state(core)) { ++ if (core->request_count) ++ vpu_core_set_state(core, VPU_CORE_HANG); ++ else ++ vpu_core_set_state(core, VPU_CORE_DEINIT); ++ ++ } else if (core->state == VPU_CORE_ACTIVE && core->hang_mask) { ++ vpu_core_set_state(core, VPU_CORE_HANG); ++ } + } + + static struct vpu_core *vpu_core_find_proper_by_type(struct vpu_dev *vpu, u32 type) +@@ -188,11 +204,13 @@ static struct vpu_core *vpu_core_find_proper_by_type(struct vpu_dev *vpu, u32 ty + dev_dbg(c->dev, "instance_mask = 0x%lx, state = %d\n", c->instance_mask, c->state); + if (c->type != type) + continue; ++ mutex_lock(&c->lock); ++ vpu_core_update_state(c); ++ mutex_unlock(&c->lock); + if (c->state == VPU_CORE_DEINIT) { + core = c; + break; + } +- vpu_core_check_hang(c); + if (c->state != VPU_CORE_ACTIVE) + continue; + if (c->request_count < request_count) { +@@ -412,6 +430,12 @@ int vpu_inst_register(struct vpu_inst *inst) + } + + mutex_lock(&core->lock); ++ if (core->state != VPU_CORE_ACTIVE) { ++ dev_err(core->dev, "vpu core is not active, state = %d\n", core->state); ++ ret = -EINVAL; ++ goto exit; ++ } ++ + if (inst->id >= 0 && inst->id < core->supported_instance_count) + goto exit; + +@@ -453,7 +477,7 @@ int vpu_inst_unregister(struct vpu_inst *inst) + vpu_core_release_instance(core, inst->id); + inst->id = VPU_INST_NULL_ID; + } +- vpu_core_check_hang(core); ++ vpu_core_update_state(core); + if (core->state == VPU_CORE_HANG && !core->instance_mask) { + int err; + +@@ -462,7 +486,7 @@ int vpu_inst_unregister(struct vpu_inst *inst) + err = vpu_core_sw_reset(core); + mutex_lock(&core->lock); + if (!err) { +- core->state = VPU_CORE_ACTIVE; ++ vpu_core_set_state(core, VPU_CORE_ACTIVE); + core->hang_mask = 0; + } + } +@@ -612,7 +636,7 @@ static int vpu_core_probe(struct platform_device *pdev) + mutex_init(&core->cmd_lock); + init_completion(&core->cmp); + init_waitqueue_head(&core->ack_wq); +- core->state = VPU_CORE_DEINIT; ++ vpu_core_set_state(core, VPU_CORE_DEINIT); + + core->res = of_device_get_match_data(dev); + if (!core->res) +@@ -761,33 +785,18 @@ static int __maybe_unused vpu_core_resume(struct device *dev) + mutex_lock(&core->lock); + pm_runtime_resume_and_get(dev); + vpu_core_get_vpu(core); +- if (core->state != VPU_CORE_SNAPSHOT) +- goto exit; + +- if (!vpu_iface_get_power_state(core)) { +- if (!list_empty(&core->instances)) { ++ if (core->request_count) { ++ if (!vpu_iface_get_power_state(core)) + ret = vpu_core_boot(core, false); +- if (ret) { +- dev_err(core->dev, "%s boot fail\n", __func__); +- core->state = VPU_CORE_DEINIT; +- goto exit; +- } +- } else { +- core->state = VPU_CORE_DEINIT; +- } +- } else { +- if (!list_empty(&core->instances)) { ++ else + ret = vpu_core_sw_reset(core); +- if (ret) { +- dev_err(core->dev, "%s sw_reset fail\n", __func__); +- core->state = VPU_CORE_HANG; +- goto exit; +- } ++ if (ret) { ++ dev_err(core->dev, "resume fail\n"); ++ vpu_core_set_state(core, VPU_CORE_HANG); + } +- core->state = VPU_CORE_ACTIVE; + } +- +-exit: ++ vpu_core_update_state(core); + pm_runtime_put_sync(dev); + mutex_unlock(&core->lock); + +@@ -801,18 +810,11 @@ static int __maybe_unused vpu_core_suspend(struct device *dev) + int ret = 0; + + mutex_lock(&core->lock); +- if (core->state == VPU_CORE_ACTIVE) { +- if (!list_empty(&core->instances)) { +- ret = vpu_core_snapshot(core); +- if (ret) { +- mutex_unlock(&core->lock); +- return ret; +- } +- } +- +- core->state = VPU_CORE_SNAPSHOT; +- } ++ if (core->request_count) ++ ret = vpu_core_snapshot(core); + mutex_unlock(&core->lock); ++ if (ret) ++ return ret; + + vpu_core_cancel_work(core); + +diff --git a/drivers/media/platform/amphion/vpu_core.h b/drivers/media/platform/amphion/vpu_core.h +index 00a662997da4..65b562642603 100644 +--- a/drivers/media/platform/amphion/vpu_core.h ++++ b/drivers/media/platform/amphion/vpu_core.h +@@ -11,5 +11,6 @@ u32 csr_readl(struct vpu_core *core, u32 reg); + int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf); + void vpu_free_dma(struct vpu_buffer *buf); + struct vpu_inst *vpu_core_find_instance(struct vpu_core *core, u32 index); ++void vpu_core_set_state(struct vpu_core *core, enum vpu_core_state state); + + #endif +diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c +index da62bd718fb8..ad41060ce46e 100644 +--- a/drivers/media/platform/amphion/vpu_dbg.c ++++ b/drivers/media/platform/amphion/vpu_dbg.c +@@ -15,6 +15,7 @@ + #include + #include "vpu.h" + #include "vpu_defs.h" ++#include "vpu_core.h" + #include "vpu_helpers.h" + #include "vpu_cmds.h" + #include "vpu_rpc.h" +@@ -233,6 +234,10 @@ static int vpu_dbg_core(struct seq_file *s, void *data) + if (seq_write(s, str, num)) + return 0; + ++ num = scnprintf(str, sizeof(str), "power %s\n", ++ vpu_iface_get_power_state(core) ? "on" : "off"); ++ if (seq_write(s, str, num)) ++ return 0; + num = scnprintf(str, sizeof(str), "state = %d\n", core->state); + if (seq_write(s, str, num)) + return 0; +@@ -346,10 +351,10 @@ static ssize_t vpu_dbg_core_write(struct file *file, + + pm_runtime_resume_and_get(core->dev); + mutex_lock(&core->lock); +- if (core->state != VPU_CORE_DEINIT && !core->instance_mask) { ++ if (vpu_iface_get_power_state(core) && !core->request_count) { + dev_info(core->dev, "reset\n"); + if (!vpu_core_sw_reset(core)) { +- core->state = VPU_CORE_ACTIVE; ++ vpu_core_set_state(core, VPU_CORE_ACTIVE); + core->hang_mask = 0; + } + } +-- +2.35.1 + diff --git a/queue-5.19/media-amphion-insert-picture-startcode-after-seek-fo.patch b/queue-5.19/media-amphion-insert-picture-startcode-after-seek-fo.patch new file mode 100644 index 00000000000..9d26abdba91 --- /dev/null +++ b/queue-5.19/media-amphion-insert-picture-startcode-after-seek-fo.patch @@ -0,0 +1,46 @@ +From 2c04b8a12faa133398912c761df87b26a257f29a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Jul 2022 09:15:49 +0200 +Subject: media: amphion: insert picture startcode after seek for vc1g format + +From: Ming Qian + +[ Upstream commit f7fd6c318c8a5d06bf3fe611f30763d62eaaf7f0 ] + +For format vc1, the amphion vpu requires driver to +help insert some custom startcode before sequence and frame. +the startcode is different for vc1l and vc1g format. + +But the sequence startcode is only needed at the beginning, +and it's not expected after seek. +driver need to treat the codec header and the first frame after seek +as a normal frame, and insert picture startcode for it. + +In previous patch, I just fix it for vc1l format, +and should fix the similar issue for vc1g too. + +Fixes: e670f5d672ef (media: amphion: only insert the first sequence startcode for vc1l format) +Signed-off-by: Ming Qian +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/amphion/vpu_malone.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/platform/amphion/vpu_malone.c b/drivers/media/platform/amphion/vpu_malone.c +index 542bbe361bd8..10553dd93c29 100644 +--- a/drivers/media/platform/amphion/vpu_malone.c ++++ b/drivers/media/platform/amphion/vpu_malone.c +@@ -1277,7 +1277,7 @@ static int vpu_malone_insert_scode_vc1_g_pic(struct malone_scode_t *scode) + vbuf = to_vb2_v4l2_buffer(scode->vb); + data = vb2_plane_vaddr(scode->vb, 0); + +- if (vbuf->sequence == 0 || vpu_vb_is_codecconfig(vbuf)) ++ if (scode->inst->total_input_count == 0 || vpu_vb_is_codecconfig(vbuf)) + return 0; + if (MALONE_VC1_CONTAIN_NAL(*data)) + return 0; +-- +2.35.1 + diff --git a/queue-5.19/media-cx88-fix-a-null-ptr-deref-bug-in-buffer_prepar.patch b/queue-5.19/media-cx88-fix-a-null-ptr-deref-bug-in-buffer_prepar.patch new file mode 100644 index 00000000000..6344b438d10 --- /dev/null +++ b/queue-5.19/media-cx88-fix-a-null-ptr-deref-bug-in-buffer_prepar.patch @@ -0,0 +1,141 @@ +From c24254d58e1bf39da09eeb65ec3d47221c8611de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 04:23:38 +0200 +Subject: media: cx88: Fix a null-ptr-deref bug in buffer_prepare() + +From: Zheyu Ma + +[ Upstream commit 2b064d91440b33fba5b452f2d1b31f13ae911d71 ] + +When the driver calls cx88_risc_buffer() to prepare the buffer, the +function call may fail, resulting in a empty buffer and null-ptr-deref +later in buffer_queue(). + +The following log can reveal it: + +[ 41.822762] general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN PTI +[ 41.824488] KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] +[ 41.828027] RIP: 0010:buffer_queue+0xc2/0x500 +[ 41.836311] Call Trace: +[ 41.836945] __enqueue_in_driver+0x141/0x360 +[ 41.837262] vb2_start_streaming+0x62/0x4a0 +[ 41.838216] vb2_core_streamon+0x1da/0x2c0 +[ 41.838516] __vb2_init_fileio+0x981/0xbc0 +[ 41.839141] __vb2_perform_fileio+0xbf9/0x1120 +[ 41.840072] vb2_fop_read+0x20e/0x400 +[ 41.840346] v4l2_read+0x215/0x290 +[ 41.840603] vfs_read+0x162/0x4c0 + +Fix this by checking the return value of cx88_risc_buffer() + +[hverkuil: fix coding style issues] + +Signed-off-by: Zheyu Ma +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/pci/cx88/cx88-vbi.c | 9 +++--- + drivers/media/pci/cx88/cx88-video.c | 43 +++++++++++++++-------------- + 2 files changed, 26 insertions(+), 26 deletions(-) + +diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c +index a075788c64d4..469aeaa725ad 100644 +--- a/drivers/media/pci/cx88/cx88-vbi.c ++++ b/drivers/media/pci/cx88/cx88-vbi.c +@@ -144,11 +144,10 @@ static int buffer_prepare(struct vb2_buffer *vb) + return -EINVAL; + vb2_set_plane_payload(vb, 0, size); + +- cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl, +- 0, VBI_LINE_LENGTH * lines, +- VBI_LINE_LENGTH, 0, +- lines); +- return 0; ++ return cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl, ++ 0, VBI_LINE_LENGTH * lines, ++ VBI_LINE_LENGTH, 0, ++ lines); + } + + static void buffer_finish(struct vb2_buffer *vb) +diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c +index d3729be89252..b509c2a03852 100644 +--- a/drivers/media/pci/cx88/cx88-video.c ++++ b/drivers/media/pci/cx88/cx88-video.c +@@ -431,6 +431,7 @@ static int queue_setup(struct vb2_queue *q, + + static int buffer_prepare(struct vb2_buffer *vb) + { ++ int ret; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct cx8800_dev *dev = vb->vb2_queue->drv_priv; + struct cx88_core *core = dev->core; +@@ -445,35 +446,35 @@ static int buffer_prepare(struct vb2_buffer *vb) + + switch (core->field) { + case V4L2_FIELD_TOP: +- cx88_risc_buffer(dev->pci, &buf->risc, +- sgt->sgl, 0, UNSET, +- buf->bpl, 0, core->height); ++ ret = cx88_risc_buffer(dev->pci, &buf->risc, ++ sgt->sgl, 0, UNSET, ++ buf->bpl, 0, core->height); + break; + case V4L2_FIELD_BOTTOM: +- cx88_risc_buffer(dev->pci, &buf->risc, +- sgt->sgl, UNSET, 0, +- buf->bpl, 0, core->height); ++ ret = cx88_risc_buffer(dev->pci, &buf->risc, ++ sgt->sgl, UNSET, 0, ++ buf->bpl, 0, core->height); + break; + case V4L2_FIELD_SEQ_TB: +- cx88_risc_buffer(dev->pci, &buf->risc, +- sgt->sgl, +- 0, buf->bpl * (core->height >> 1), +- buf->bpl, 0, +- core->height >> 1); ++ ret = cx88_risc_buffer(dev->pci, &buf->risc, ++ sgt->sgl, ++ 0, buf->bpl * (core->height >> 1), ++ buf->bpl, 0, ++ core->height >> 1); + break; + case V4L2_FIELD_SEQ_BT: +- cx88_risc_buffer(dev->pci, &buf->risc, +- sgt->sgl, +- buf->bpl * (core->height >> 1), 0, +- buf->bpl, 0, +- core->height >> 1); ++ ret = cx88_risc_buffer(dev->pci, &buf->risc, ++ sgt->sgl, ++ buf->bpl * (core->height >> 1), 0, ++ buf->bpl, 0, ++ core->height >> 1); + break; + case V4L2_FIELD_INTERLACED: + default: +- cx88_risc_buffer(dev->pci, &buf->risc, +- sgt->sgl, 0, buf->bpl, +- buf->bpl, buf->bpl, +- core->height >> 1); ++ ret = cx88_risc_buffer(dev->pci, &buf->risc, ++ sgt->sgl, 0, buf->bpl, ++ buf->bpl, buf->bpl, ++ core->height >> 1); + break; + } + dprintk(2, +@@ -481,7 +482,7 @@ static int buffer_prepare(struct vb2_buffer *vb) + buf, buf->vb.vb2_buf.index, __func__, + core->width, core->height, dev->fmt->depth, dev->fmt->fourcc, + (unsigned long)buf->risc.dma); +- return 0; ++ return ret; + } + + static void buffer_finish(struct vb2_buffer *vb) +-- +2.35.1 + diff --git a/queue-5.19/media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch b/queue-5.19/media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch new file mode 100644 index 00000000000..2e5b9f4b436 --- /dev/null +++ b/queue-5.19/media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch @@ -0,0 +1,38 @@ +From a0b6c897113826ca69f9f59da1d327a9801e16a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Jul 2022 16:30:03 +0200 +Subject: media: exynos4-is: fimc-is: Add of_node_put() when breaking out of + loop + +From: Liang He + +[ Upstream commit 211f8304fa21aaedc2c247f0c9d6c7f1aaa61ad7 ] + +In fimc_is_register_subdevs(), we need to call of_node_put() for +the reference 'i2c_bus' when breaking out of the +for_each_compatible_node() which has increased the refcount. + +Fixes: 9a761e436843 ("[media] exynos4-is: Add Exynos4x12 FIMC-IS driver") +Signed-off-by: Liang He +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/samsung/exynos4-is/fimc-is.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/media/platform/samsung/exynos4-is/fimc-is.c b/drivers/media/platform/samsung/exynos4-is/fimc-is.c +index e3072d69c49f..a7704ff069d6 100644 +--- a/drivers/media/platform/samsung/exynos4-is/fimc-is.c ++++ b/drivers/media/platform/samsung/exynos4-is/fimc-is.c +@@ -213,6 +213,7 @@ static int fimc_is_register_subdevs(struct fimc_is *is) + + if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) { + of_node_put(child); ++ of_node_put(i2c_bus); + return ret; + } + index++; +-- +2.35.1 + diff --git a/queue-5.19/media-meson-vdec-add-missing-clk_disable_unprepare-o.patch b/queue-5.19/media-meson-vdec-add-missing-clk_disable_unprepare-o.patch new file mode 100644 index 00000000000..6b2ab9860d9 --- /dev/null +++ b/queue-5.19/media-meson-vdec-add-missing-clk_disable_unprepare-o.patch @@ -0,0 +1,47 @@ +From aa2fb877d1c7956226b33bcf71503ebc3006e8a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 08:57:53 +0200 +Subject: media: meson: vdec: add missing clk_disable_unprepare on error in + vdec_hevc_start() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Xu Qiang + +[ Upstream commit 4029372233e13e281f8c387f279f9f064ced3810 ] + +Add the missing clk_disable_unprepare() before return +from vdec_hevc_start() in the error handling case. + +Fixes: 823a7300340e (“media: meson: vdec: add common HEVC decoder support”) +Signed-off-by: Xu Qiang +Reviewed-by: Neil Armstrong +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/staging/media/meson/vdec/vdec_hevc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/staging/media/meson/vdec/vdec_hevc.c b/drivers/staging/media/meson/vdec/vdec_hevc.c +index 9530e580e57a..afced435c907 100644 +--- a/drivers/staging/media/meson/vdec/vdec_hevc.c ++++ b/drivers/staging/media/meson/vdec/vdec_hevc.c +@@ -167,8 +167,12 @@ static int vdec_hevc_start(struct amvdec_session *sess) + + clk_set_rate(core->vdec_hevc_clk, 666666666); + ret = clk_prepare_enable(core->vdec_hevc_clk); +- if (ret) ++ if (ret) { ++ if (core->platform->revision == VDEC_REVISION_G12A || ++ core->platform->revision == VDEC_REVISION_SM1) ++ clk_disable_unprepare(core->vdec_hevcf_clk); + return ret; ++ } + + if (core->platform->revision == VDEC_REVISION_SM1) + regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, +-- +2.35.1 + diff --git a/queue-5.19/media-platform-fix-some-double-free-in-meson-ge2d-an.patch b/queue-5.19/media-platform-fix-some-double-free-in-meson-ge2d-an.patch new file mode 100644 index 00000000000..e3ddcd39af6 --- /dev/null +++ b/queue-5.19/media-platform-fix-some-double-free-in-meson-ge2d-an.patch @@ -0,0 +1,71 @@ +From 9be694ef5bfed4b264b0bf80c89e41e42eda3dc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 10:58:19 +0200 +Subject: media: platform: fix some double free in meson-ge2d and mtk-jpeg and + s5p-mfc + +From: Hangyu Hua + +[ Upstream commit c65c3f3a2cbf21ed429d9b9c725bdb5dc6abf4cf ] + +video_unregister_device will release device internally. There is no need to +call video_device_release after video_unregister_device. + +Signed-off-by: Hangyu Hua +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/amlogic/meson-ge2d/ge2d.c | 1 - + drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c | 1 - + drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c | 3 +-- + 3 files changed, 1 insertion(+), 4 deletions(-) + +diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c +index 5e7b319f300d..142d421a8d76 100644 +--- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c ++++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c +@@ -1030,7 +1030,6 @@ static int ge2d_remove(struct platform_device *pdev) + + video_unregister_device(ge2d->vfd); + v4l2_m2m_release(ge2d->m2m_dev); +- video_device_release(ge2d->vfd); + v4l2_device_unregister(&ge2d->v4l2_dev); + clk_disable_unprepare(ge2d->clk); + +diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +index bc5b0a0168ec..6aa73f1cde18 100644 +--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c ++++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c +@@ -1411,7 +1411,6 @@ static int mtk_jpeg_remove(struct platform_device *pdev) + + pm_runtime_disable(&pdev->dev); + video_unregister_device(jpeg->vdev); +- video_device_release(jpeg->vdev); + v4l2_m2m_release(jpeg->m2m_dev); + v4l2_device_unregister(&jpeg->v4l2_dev); + +diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +index 761341934925..f85d1eebafac 100644 +--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c ++++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c +@@ -1399,6 +1399,7 @@ static int s5p_mfc_probe(struct platform_device *pdev) + /* Deinit MFC if probe had failed */ + err_enc_reg: + video_unregister_device(dev->vfd_dec); ++ dev->vfd_dec = NULL; + err_dec_reg: + video_device_release(dev->vfd_enc); + err_enc_alloc: +@@ -1444,8 +1445,6 @@ static int s5p_mfc_remove(struct platform_device *pdev) + + video_unregister_device(dev->vfd_enc); + video_unregister_device(dev->vfd_dec); +- video_device_release(dev->vfd_enc); +- video_device_release(dev->vfd_dec); + v4l2_device_unregister(&dev->v4l2_dev); + s5p_mfc_unconfigure_dma_memory(dev); + +-- +2.35.1 + diff --git a/queue-5.19/media-tm6000-fix-unused-value-in-vidioc_try_fmt_vid_.patch b/queue-5.19/media-tm6000-fix-unused-value-in-vidioc_try_fmt_vid_.patch new file mode 100644 index 00000000000..de95e8b98ae --- /dev/null +++ b/queue-5.19/media-tm6000-fix-unused-value-in-vidioc_try_fmt_vid_.patch @@ -0,0 +1,46 @@ +From d11aa69d6362d17ea9b53bb0517cc00243a49428 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 18:12:36 +0800 +Subject: media: tm6000: Fix unused value in vidioc_try_fmt_vid_cap() + +From: Zeng Jingxiang + +[ Upstream commit d682869daa23938b5e8919db45c4b5b227749712 ] + +Coverity warns of an unused value: + +assigned_value: Assign the value of the variable f->fmt.pix.field +to field here, but that stored value is overwritten. +before it can be used. +919 field = f->fmt.pix.field; +920 + +value_overwrite: Overwriting previous write to field with +the value of V4L2_FIELD_INTERLACED. +921 field = V4L2_FIELD_INTERLACED; + +Fixes: ed57256f6fe8 ("[media] tm6000: fix G/TRY_FMT") +Signed-off-by: Zeng Jingxiang +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/tm6000/tm6000-video.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c +index d855a19551f3..e06ed21edbdd 100644 +--- a/drivers/media/usb/tm6000/tm6000-video.c ++++ b/drivers/media/usb/tm6000/tm6000-video.c +@@ -916,8 +916,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, + return -EINVAL; + } + +- field = f->fmt.pix.field; +- + field = V4L2_FIELD_INTERLACED; + + tm6000_get_std_res(dev); +-- +2.35.1 + diff --git a/queue-5.19/media-uvcvideo-fix-memory-leak-in-uvc_gpio_parse.patch b/queue-5.19/media-uvcvideo-fix-memory-leak-in-uvc_gpio_parse.patch new file mode 100644 index 00000000000..e485f97c4d5 --- /dev/null +++ b/queue-5.19/media-uvcvideo-fix-memory-leak-in-uvc_gpio_parse.patch @@ -0,0 +1,58 @@ +From 4f1ecf71c6c37f5cd7136bfae283ee56ebfbe522 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Jan 2022 18:04:39 +0100 +Subject: media: uvcvideo: Fix memory leak in uvc_gpio_parse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit f0f078457f18f10696888f8d0e6aba9deb9cde92 ] + +Previously the unit buffer was allocated before checking the IRQ for +privacy GPIO. In case of error, the unit buffer was leaked. + +Allocate the unit buffer after the IRQ to avoid it. + +Addresses-Coverity-ID: 1474639 ("Resource leak") + +Fixes: 2886477ff987 ("media: uvcvideo: Implement UVC_EXT_GPIO_UNIT") +Signed-off-by: José Expósito +Reviewed-by: Ricardo Ribalda +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_driver.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c +index 6c86faecbea2..28ee45e879ff 100644 +--- a/drivers/media/usb/uvc/uvc_driver.c ++++ b/drivers/media/usb/uvc/uvc_driver.c +@@ -1538,10 +1538,6 @@ static int uvc_gpio_parse(struct uvc_device *dev) + if (IS_ERR_OR_NULL(gpio_privacy)) + return PTR_ERR_OR_ZERO(gpio_privacy); + +- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); +- if (!unit) +- return -ENOMEM; +- + irq = gpiod_to_irq(gpio_privacy); + if (irq < 0) { + if (irq != EPROBE_DEFER) +@@ -1550,6 +1546,10 @@ static int uvc_gpio_parse(struct uvc_device *dev) + return irq; + } + ++ unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1); ++ if (!unit) ++ return -ENOMEM; ++ + unit->gpio.gpio_privacy = gpio_privacy; + unit->gpio.irq = irq; + unit->gpio.bControlSize = 1; +-- +2.35.1 + diff --git a/queue-5.19/media-uvcvideo-use-entity-get_cur-in-uvc_ctrl_set.patch b/queue-5.19/media-uvcvideo-use-entity-get_cur-in-uvc_ctrl_set.patch new file mode 100644 index 00000000000..ad88a35f8a8 --- /dev/null +++ b/queue-5.19/media-uvcvideo-use-entity-get_cur-in-uvc_ctrl_set.patch @@ -0,0 +1,134 @@ +From 43b3863c0b1168faf910c781c31c9fa484de75e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Jul 2022 10:53:31 +0200 +Subject: media: uvcvideo: Use entity get_cur in uvc_ctrl_set + +From: Yunke Cao + +[ Upstream commit 5f36851c36b30f713f588ed2b60aa7b4512e2c76 ] + +Entity controls should get_cur using an entity-defined function +instead of via a query. Fix this in uvc_ctrl_set. + +Fixes: 65900c581d01 ("media: uvcvideo: Allow entity-defined get_info and get_cur") +Signed-off-by: Yunke Cao +Reviewed-by: Ricardo Ribalda +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/usb/uvc/uvc_ctrl.c | 83 ++++++++++++++++++-------------- + 1 file changed, 46 insertions(+), 37 deletions(-) + +diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c +index 0e78233fc8a0..44071040d764 100644 +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -963,36 +963,56 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping, + return value; + } + +-static int __uvc_ctrl_get(struct uvc_video_chain *chain, +- struct uvc_control *ctrl, struct uvc_control_mapping *mapping, +- s32 *value) ++static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain, ++ struct uvc_control *ctrl) + { ++ u8 *data; + int ret; + +- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) +- return -EACCES; ++ if (ctrl->loaded) ++ return 0; + +- if (!ctrl->loaded) { +- if (ctrl->entity->get_cur) { +- ret = ctrl->entity->get_cur(chain->dev, +- ctrl->entity, +- ctrl->info.selector, +- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), +- ctrl->info.size); +- } else { +- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, +- ctrl->entity->id, +- chain->dev->intfnum, +- ctrl->info.selector, +- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), +- ctrl->info.size); +- } +- if (ret < 0) +- return ret; ++ data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); + ++ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { ++ memset(data, 0, ctrl->info.size); + ctrl->loaded = 1; ++ ++ return 0; + } + ++ if (ctrl->entity->get_cur) ++ ret = ctrl->entity->get_cur(chain->dev, ctrl->entity, ++ ctrl->info.selector, data, ++ ctrl->info.size); ++ else ++ ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ++ ctrl->entity->id, chain->dev->intfnum, ++ ctrl->info.selector, data, ++ ctrl->info.size); ++ ++ if (ret < 0) ++ return ret; ++ ++ ctrl->loaded = 1; ++ ++ return ret; ++} ++ ++static int __uvc_ctrl_get(struct uvc_video_chain *chain, ++ struct uvc_control *ctrl, ++ struct uvc_control_mapping *mapping, ++ s32 *value) ++{ ++ int ret; ++ ++ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) ++ return -EACCES; ++ ++ ret = __uvc_ctrl_load_cur(chain, ctrl); ++ if (ret < 0) ++ return ret; ++ + *value = __uvc_ctrl_get_value(mapping, + uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT)); + +@@ -1783,21 +1803,10 @@ int uvc_ctrl_set(struct uvc_fh *handle, + * needs to be loaded from the device to perform the read-modify-write + * operation. + */ +- if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) { +- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) { +- memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), +- 0, ctrl->info.size); +- } else { +- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, +- ctrl->entity->id, chain->dev->intfnum, +- ctrl->info.selector, +- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), +- ctrl->info.size); +- if (ret < 0) +- return ret; +- } +- +- ctrl->loaded = 1; ++ if ((ctrl->info.size * 8) != mapping->size) { ++ ret = __uvc_ctrl_load_cur(chain, ctrl); ++ if (ret < 0) ++ return ret; + } + + /* Backup the current value in case we need to rollback later. */ +-- +2.35.1 + diff --git a/queue-5.19/media-xilinx-vipp-fix-refcount-leak-in-xvip_graph_dm.patch b/queue-5.19/media-xilinx-vipp-fix-refcount-leak-in-xvip_graph_dm.patch new file mode 100644 index 00000000000..b3a4854ab69 --- /dev/null +++ b/queue-5.19/media-xilinx-vipp-fix-refcount-leak-in-xvip_graph_dm.patch @@ -0,0 +1,56 @@ +From fa25210daaf4fb4514994946da733489d51f87c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jun 2022 06:25:14 +0200 +Subject: media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init + +From: Miaoqian Lin + +[ Upstream commit 1c78f19c3a0ea312a8178a6bfd8934eb93e9b10a ] + +of_get_child_by_name() returns a node pointer with refcount +incremented, we should use of_node_put() on it when not need anymore. +Add missing of_node_put() to avoid refcount leak. + +Fixes: df3305156f98 ("[media] v4l: xilinx: Add Xilinx Video IP core") +Signed-off-by: Miaoqian Lin +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/xilinx/xilinx-vipp.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c +index f34f8b077e03..0a16c218a50a 100644 +--- a/drivers/media/platform/xilinx/xilinx-vipp.c ++++ b/drivers/media/platform/xilinx/xilinx-vipp.c +@@ -471,7 +471,7 @@ static int xvip_graph_dma_init(struct xvip_composite_device *xdev) + { + struct device_node *ports; + struct device_node *port; +- int ret; ++ int ret = 0; + + ports = of_get_child_by_name(xdev->dev->of_node, "ports"); + if (ports == NULL) { +@@ -481,13 +481,14 @@ static int xvip_graph_dma_init(struct xvip_composite_device *xdev) + + for_each_child_of_node(ports, port) { + ret = xvip_graph_dma_init_one(xdev, port); +- if (ret < 0) { ++ if (ret) { + of_node_put(port); +- return ret; ++ break; + } + } + +- return 0; ++ of_node_put(ports); ++ return ret; + } + + static void xvip_graph_cleanup(struct xvip_composite_device *xdev) +-- +2.35.1 + diff --git a/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_get_ddr_timing.patch b/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_get_ddr_timing.patch new file mode 100644 index 00000000000..0a80e676145 --- /dev/null +++ b/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_get_ddr_timing.patch @@ -0,0 +1,37 @@ +From be4c28177b175d8b401acebc297aad9ea1472531 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jul 2022 16:56:39 +0800 +Subject: memory: of: Fix refcount leak bug in of_get_ddr_timings() + +From: Liang He + +[ Upstream commit 05215fb32010d4afb68fbdbb4d237df6e2d4567b ] + +We should add the of_node_put() when breaking out of +for_each_child_of_node() as it will automatically increase +and decrease the refcount. + +Fixes: e6b42eb6a66c ("memory: emif: add device tree support to emif driver") +Signed-off-by: Liang He +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220719085640.1210583-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/memory/of_memory.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c +index dbdf87bc0b78..8e2ef4bf6b17 100644 +--- a/drivers/memory/of_memory.c ++++ b/drivers/memory/of_memory.c +@@ -134,6 +134,7 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr, + for_each_child_of_node(np_ddr, np_tim) { + if (of_device_is_compatible(np_tim, tim_compat)) { + if (of_do_get_timings(np_tim, &timings[i])) { ++ of_node_put(np_tim); + devm_kfree(dev, timings); + goto default_timings; + } +-- +2.35.1 + diff --git a/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_lpddr3_get_ddr.patch b/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_lpddr3_get_ddr.patch new file mode 100644 index 00000000000..89bac403406 --- /dev/null +++ b/queue-5.19/memory-of-fix-refcount-leak-bug-in-of_lpddr3_get_ddr.patch @@ -0,0 +1,37 @@ +From f54d90e4bd3b09c8ba29f9cb8fb147f52c438cc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Jul 2022 16:56:40 +0800 +Subject: memory: of: Fix refcount leak bug in of_lpddr3_get_ddr_timings() + +From: Liang He + +[ Upstream commit 48af14fb0eaa63d9aa68f59fb0b205ec55a95636 ] + +We should add the of_node_put() when breaking out of +for_each_child_of_node() as it will automatically increase +and decrease the refcount. + +Fixes: 976897dd96db ("memory: Extend of_memory with LPDDR3 support") +Signed-off-by: Liang He +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220719085640.1210583-2-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/memory/of_memory.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c +index 8e2ef4bf6b17..fcd20d85d385 100644 +--- a/drivers/memory/of_memory.c ++++ b/drivers/memory/of_memory.c +@@ -285,6 +285,7 @@ const struct lpddr3_timings + if (of_device_is_compatible(np_tim, tim_compat)) { + if (of_lpddr3_do_get_timings(np_tim, &timings[i])) { + devm_kfree(dev, timings); ++ of_node_put(np_tim); + goto default_timings; + } + i++; +-- +2.35.1 + diff --git a/queue-5.19/memory-pl353-smc-fix-refcount-leak-bug-in-pl353_smc_.patch b/queue-5.19/memory-pl353-smc-fix-refcount-leak-bug-in-pl353_smc_.patch new file mode 100644 index 00000000000..a5c77fce63b --- /dev/null +++ b/queue-5.19/memory-pl353-smc-fix-refcount-leak-bug-in-pl353_smc_.patch @@ -0,0 +1,41 @@ +From 08012e1f87fa1ef5db289c39dd3134dc884393a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Jul 2022 11:13:24 +0800 +Subject: memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe() + +From: Liang He + +[ Upstream commit 61b3c876c1cbdb1efd1f52a1f348580e6e14efb6 ] + +The break of for_each_available_child_of_node() needs a +corresponding of_node_put() when the reference 'child' is not +used anymore. Here we do not need to call of_node_put() in +fail path as '!match' means no break. + +While the of_platform_device_create() will created a new +reference by 'child' but it has considered the refcounting. + +Fixes: fee10bd22678 ("memory: pl353: Add driver for arm pl353 static memory controller") +Signed-off-by: Liang He +Signed-off-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20220716031324.447680-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/memory/pl353-smc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c +index f84b98278745..d39ee7d06665 100644 +--- a/drivers/memory/pl353-smc.c ++++ b/drivers/memory/pl353-smc.c +@@ -122,6 +122,7 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) + } + + of_platform_device_create(child, NULL, &adev->dev); ++ of_node_put(child); + + return 0; + +-- +2.35.1 + diff --git a/queue-5.19/mfd-da9061-fix-failed-to-set-two-wire-bus-mode.patch b/queue-5.19/mfd-da9061-fix-failed-to-set-two-wire-bus-mode.patch new file mode 100644 index 00000000000..443f415f5fb --- /dev/null +++ b/queue-5.19/mfd-da9061-fix-failed-to-set-two-wire-bus-mode.patch @@ -0,0 +1,44 @@ +From 47cc392239237da0572a43c94aae39ff7ee4f47e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 11:20:04 +0200 +Subject: mfd: da9061: Fix Failed to set Two-Wire Bus Mode. + +From: Jens Hillenstedt + +[ Upstream commit 834382ea32865a4bdeae83ec2dcb9321dc9489f2 ] + +In da9062_i2c_probe() regmap_clear_bits() tries to access CONFIG_J +register. As CONFIG_J is not present in da9061_aa_writeable_ranges[] probe +of da9061 fails: + + da9062 2-0058: Entering I2C mode! + da9062 2-0058: Failed to set Two-Wire Bus Mode. + da9062: probe of 2-0058 failed with error -5 + +Add CONFIG_J register to da9061_aa_writeable_ranges[]. + +Fixes: 5c6f0f456351 ("mfd: da9062: Support SMBus and I2C mode") +Signed-off-by: Jens Hillenstedt +Reviewed-by: Adam Ward +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20220915092004.168744-1-jens.hillenstedt@ise.de +Signed-off-by: Sasha Levin +--- + drivers/mfd/da9062-core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c +index 2774b2cbaea6..c2acdbcd5d6b 100644 +--- a/drivers/mfd/da9062-core.c ++++ b/drivers/mfd/da9062-core.c +@@ -453,6 +453,7 @@ static const struct regmap_range da9061_aa_writeable_ranges[] = { + regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B), + regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B), + regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B), ++ regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J), + regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19), + }; + +-- +2.35.1 + diff --git a/queue-5.19/mfd-fsl-imx25-fix-an-error-handling-path-in-mx25_tsa.patch b/queue-5.19/mfd-fsl-imx25-fix-an-error-handling-path-in-mx25_tsa.patch new file mode 100644 index 00000000000..109c8198d1d --- /dev/null +++ b/queue-5.19/mfd-fsl-imx25-fix-an-error-handling-path-in-mx25_tsa.patch @@ -0,0 +1,82 @@ +From 7b9ea4b7af1ff3aefc4fafd2dc57baed2e28fb9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 14:06:23 +0200 +Subject: mfd: fsl-imx25: Fix an error handling path in mx25_tsadc_setup_irq() + +From: Christophe JAILLET + +[ Upstream commit 3fa9e4cfb55da512ebfd57336fde468830719298 ] + +If devm_of_platform_populate() fails, some resources need to be +released. + +Introduce a mx25_tsadc_unset_irq() function that undoes +mx25_tsadc_setup_irq() and call it both from the new error handling path +of the probe and in the remove function. + +Fixes: a55196eff6d6 ("mfd: fsl-imx25: Use devm_of_platform_populate()") +Signed-off-by: Christophe JAILLET +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/d404e04828fc06bcfddf81f9f3e9b4babbe35415.1659269156.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/mfd/fsl-imx25-tsadc.c | 32 ++++++++++++++++++++++++-------- + 1 file changed, 24 insertions(+), 8 deletions(-) + +diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c +index 37e5e02a1d05..85f7982d26d2 100644 +--- a/drivers/mfd/fsl-imx25-tsadc.c ++++ b/drivers/mfd/fsl-imx25-tsadc.c +@@ -84,6 +84,19 @@ static int mx25_tsadc_setup_irq(struct platform_device *pdev, + return 0; + } + ++static int mx25_tsadc_unset_irq(struct platform_device *pdev) ++{ ++ struct mx25_tsadc *tsadc = platform_get_drvdata(pdev); ++ int irq = platform_get_irq(pdev, 0); ++ ++ if (irq) { ++ irq_set_chained_handler_and_data(irq, NULL, NULL); ++ irq_domain_remove(tsadc->domain); ++ } ++ ++ return 0; ++} ++ + static void mx25_tsadc_setup_clk(struct platform_device *pdev, + struct mx25_tsadc *tsadc) + { +@@ -171,18 +184,21 @@ static int mx25_tsadc_probe(struct platform_device *pdev) + + platform_set_drvdata(pdev, tsadc); + +- return devm_of_platform_populate(dev); ++ ret = devm_of_platform_populate(dev); ++ if (ret) ++ goto err_irq; ++ ++ return 0; ++ ++err_irq: ++ mx25_tsadc_unset_irq(pdev); ++ ++ return ret; + } + + static int mx25_tsadc_remove(struct platform_device *pdev) + { +- struct mx25_tsadc *tsadc = platform_get_drvdata(pdev); +- int irq = platform_get_irq(pdev, 0); +- +- if (irq) { +- irq_set_chained_handler_and_data(irq, NULL, NULL); +- irq_domain_remove(tsadc->domain); +- } ++ mx25_tsadc_unset_irq(pdev); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/mfd-fsl-imx25-fix-check-for-platform_get_irq-errors.patch b/queue-5.19/mfd-fsl-imx25-fix-check-for-platform_get_irq-errors.patch new file mode 100644 index 00000000000..5a38c67323a --- /dev/null +++ b/queue-5.19/mfd-fsl-imx25-fix-check-for-platform_get_irq-errors.patch @@ -0,0 +1,49 @@ +From 32d357885cca74e64c07d877a257233f5de2c15e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 13:53:05 +0300 +Subject: mfd: fsl-imx25: Fix check for platform_get_irq() errors + +From: Dan Carpenter + +[ Upstream commit 75db7907355ca5e2ff606e9dd3e86b6c3a455fe2 ] + +The mx25_tsadc_remove() function assumes all non-zero returns are success +but the platform_get_irq() function returns negative on error and +positive non-zero values on success. It never returns zero, but if it +did then treat that as a success. + +Fixes: 18f773937968 ("mfd: fsl-imx25: Clean up irq settings during removal") +Signed-off-by: Dan Carpenter +Reviewed-by: Martin Kaiser +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/YvTfkbVQWYKMKS/t@kili +Signed-off-by: Sasha Levin +--- + drivers/mfd/fsl-imx25-tsadc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/fsl-imx25-tsadc.c b/drivers/mfd/fsl-imx25-tsadc.c +index 85f7982d26d2..823595bcc9b7 100644 +--- a/drivers/mfd/fsl-imx25-tsadc.c ++++ b/drivers/mfd/fsl-imx25-tsadc.c +@@ -69,7 +69,7 @@ static int mx25_tsadc_setup_irq(struct platform_device *pdev, + int irq; + + irq = platform_get_irq(pdev, 0); +- if (irq <= 0) ++ if (irq < 0) + return irq; + + tsadc->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops, +@@ -89,7 +89,7 @@ static int mx25_tsadc_unset_irq(struct platform_device *pdev) + struct mx25_tsadc *tsadc = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); + +- if (irq) { ++ if (irq >= 0) { + irq_set_chained_handler_and_data(irq, NULL, NULL); + irq_domain_remove(tsadc->domain); + } +-- +2.35.1 + diff --git a/queue-5.19/mfd-intel_soc_pmic-fix-an-error-handling-path-in-int.patch b/queue-5.19/mfd-intel_soc_pmic-fix-an-error-handling-path-in-int.patch new file mode 100644 index 00000000000..d6ec8625413 --- /dev/null +++ b/queue-5.19/mfd-intel_soc_pmic-fix-an-error-handling-path-in-int.patch @@ -0,0 +1,42 @@ +From 756665e98c40c319627ad62b2edb909181431e01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 14:42:02 +0300 +Subject: mfd: intel_soc_pmic: Fix an error handling path in + intel_soc_pmic_i2c_probe() + +From: Christophe JAILLET + +[ Upstream commit 48749cabba109397b4e7dd556e85718ec0ec114d ] + +The commit in Fixes: has added a pwm_add_table() call in the probe() and +a pwm_remove_table() call in the remove(), but forget to update the error +handling path of the probe. + +Add the missing pwm_remove_table() call. + +Fixes: a3aa9a93df9f ("mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM") +Signed-off-by: Christophe JAILLET +Signed-off-by: Andy Shevchenko +Reviewed-by: Hans de Goede +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20220801114211.36267-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Sasha Levin +--- + drivers/mfd/intel_soc_pmic_core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c +index 5e8c94e008ed..85d070bce0e2 100644 +--- a/drivers/mfd/intel_soc_pmic_core.c ++++ b/drivers/mfd/intel_soc_pmic_core.c +@@ -77,6 +77,7 @@ static int intel_soc_pmic_i2c_probe(struct i2c_client *i2c, + return 0; + + err_del_irq_chip: ++ pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); + regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_irq_.patch b/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_irq_.patch new file mode 100644 index 00000000000..c8011fc02ea --- /dev/null +++ b/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_irq_.patch @@ -0,0 +1,48 @@ +From 81005abfaad2fd0dffacec44e1de5e5212d55662 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 11:55:38 +0200 +Subject: mfd: lp8788: Fix an error handling path in lp8788_irq_init() and + lp8788_irq_init() + +From: Christophe JAILLET + +[ Upstream commit 557244f6284f30613f2d61f14b579303165876c3 ] + +In lp8788_irq_init(), if an error occurs after a successful +irq_domain_add_linear() call, it must be undone by a corresponding +irq_domain_remove() call. + +irq_domain_remove() should also be called in lp8788_irq_exit() for the same +reason. + +Fixes: eea6b7cc53aa ("mfd: Add lp8788 mfd driver") +Signed-off-by: Christophe JAILLET +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/bcd5a72c9c1c383dd6324680116426e32737655a.1659261275.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/mfd/lp8788-irq.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/mfd/lp8788-irq.c b/drivers/mfd/lp8788-irq.c +index 348439a3fbbd..39006297f3d2 100644 +--- a/drivers/mfd/lp8788-irq.c ++++ b/drivers/mfd/lp8788-irq.c +@@ -175,6 +175,7 @@ int lp8788_irq_init(struct lp8788 *lp, int irq) + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "lp8788-irq", irqd); + if (ret) { ++ irq_domain_remove(lp->irqdm); + dev_err(lp->dev, "failed to create a thread for IRQ_N\n"); + return ret; + } +@@ -188,4 +189,6 @@ void lp8788_irq_exit(struct lp8788 *lp) + { + if (lp->irq) + free_irq(lp->irq, lp->irqdm); ++ if (lp->irqdm) ++ irq_domain_remove(lp->irqdm); + } +-- +2.35.1 + diff --git a/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_prob.patch b/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_prob.patch new file mode 100644 index 00000000000..624dcc7c56a --- /dev/null +++ b/queue-5.19/mfd-lp8788-fix-an-error-handling-path-in-lp8788_prob.patch @@ -0,0 +1,50 @@ +From 46148bd8cd3032ef5cea0109fc487d03bf610175 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 11:55:27 +0200 +Subject: mfd: lp8788: Fix an error handling path in lp8788_probe() + +From: Christophe JAILLET + +[ Upstream commit becfdcd75126b20b8ec10066c5e85b34f8994ad5 ] + +Should an error occurs in mfd_add_devices(), some resources need to be +released, as already done in the .remove() function. + +Add an error handling path and a lp8788_irq_exit() call to undo a previous +lp8788_irq_init(). + +Fixes: eea6b7cc53aa ("mfd: Add lp8788 mfd driver") +Signed-off-by: Christophe JAILLET +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/18398722da9df9490722d853e4797350189ae79b.1659261275.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Sasha Levin +--- + drivers/mfd/lp8788.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/mfd/lp8788.c b/drivers/mfd/lp8788.c +index c223d2c6a363..998e8cc408a0 100644 +--- a/drivers/mfd/lp8788.c ++++ b/drivers/mfd/lp8788.c +@@ -195,8 +195,16 @@ static int lp8788_probe(struct i2c_client *cl, const struct i2c_device_id *id) + if (ret) + return ret; + +- return mfd_add_devices(lp->dev, -1, lp8788_devs, +- ARRAY_SIZE(lp8788_devs), NULL, 0, NULL); ++ ret = mfd_add_devices(lp->dev, -1, lp8788_devs, ++ ARRAY_SIZE(lp8788_devs), NULL, 0, NULL); ++ if (ret) ++ goto err_exit_irq; ++ ++ return 0; ++ ++err_exit_irq: ++ lp8788_irq_exit(lp); ++ return ret; + } + + static int lp8788_remove(struct i2c_client *cl) +-- +2.35.1 + diff --git a/queue-5.19/mfd-sm501-add-check-for-platform_driver_register.patch b/queue-5.19/mfd-sm501-add-check-for-platform_driver_register.patch new file mode 100644 index 00000000000..5ca19b0d094 --- /dev/null +++ b/queue-5.19/mfd-sm501-add-check-for-platform_driver_register.patch @@ -0,0 +1,43 @@ +From 0bf9fe7419d9ea80e98441cf0c6e1d67cc67c5f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 17:11:12 +0800 +Subject: mfd: sm501: Add check for platform_driver_register() + +From: Jiasheng Jiang + +[ Upstream commit 8325a6c24ad78b8c1acc3c42b098ee24105d68e5 ] + +As platform_driver_register() can return error numbers, +it should be better to check platform_driver_register() +and deal with the exception. + +Fixes: b6d6454fdb66 ("[PATCH] mfd: SM501 core driver") +Signed-off-by: Jiasheng Jiang +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20220913091112.1739138-1-jiasheng@iscas.ac.cn +Signed-off-by: Sasha Levin +--- + drivers/mfd/sm501.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c +index bc0a2c38653e..3ac4508a6742 100644 +--- a/drivers/mfd/sm501.c ++++ b/drivers/mfd/sm501.c +@@ -1720,7 +1720,12 @@ static struct platform_driver sm501_plat_driver = { + + static int __init sm501_base_init(void) + { +- platform_driver_register(&sm501_plat_driver); ++ int ret; ++ ++ ret = platform_driver_register(&sm501_plat_driver); ++ if (ret < 0) ++ return ret; ++ + return pci_register_driver(&sm501_pci_driver); + } + +-- +2.35.1 + diff --git a/queue-5.19/micrel-ksz8851-fixes-struct-pointer-issue.patch b/queue-5.19/micrel-ksz8851-fixes-struct-pointer-issue.patch new file mode 100644 index 00000000000..bb7b826ef8b --- /dev/null +++ b/queue-5.19/micrel-ksz8851-fixes-struct-pointer-issue.patch @@ -0,0 +1,54 @@ +From 59bfff0a5c6ec472dc15cedff5632ba68ab808d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 16:39:32 -0500 +Subject: micrel: ksz8851: fixes struct pointer issue + +From: Jerry Ray + +[ Upstream commit fef5de753ff01887cfa50990532c3890fccb9338 ] + +Issue found during code review. This bug has no impact as long as the +ks8851_net structure is the first element of the ks8851_net_spi structure. +As long as the offset to the ks8851_net struct is zero, the container_of() +macro is subtracting 0 and therefore no damage done. But if the +ks8851_net_spi struct is ever modified such that the ks8851_net struct +within it is no longer the first element of the struct, then the bug would +manifest itself and cause problems. + +struct ks8851_net is contained within ks8851_net_spi. +ks is contained within kss. +kss is the priv_data of the netdev structure. + +Signed-off-by: Jerry Ray +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/micrel/ks8851_spi.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c +index 82d55fc27edc..70bc7253454f 100644 +--- a/drivers/net/ethernet/micrel/ks8851_spi.c ++++ b/drivers/net/ethernet/micrel/ks8851_spi.c +@@ -413,7 +413,8 @@ static int ks8851_probe_spi(struct spi_device *spi) + + spi->bits_per_word = 8; + +- ks = netdev_priv(netdev); ++ kss = netdev_priv(netdev); ++ ks = &kss->ks8851; + + ks->lock = ks8851_lock_spi; + ks->unlock = ks8851_unlock_spi; +@@ -433,8 +434,6 @@ static int ks8851_probe_spi(struct spi_device *spi) + IRQ_RXPSI) /* RX process stop */ + ks->rc_ier = STD_IRQ; + +- kss = to_ks8851_spi(ks); +- + kss->spidev = spi; + mutex_init(&kss->lock); + INIT_WORK(&kss->tx_work, ks8851_tx_work); +-- +2.35.1 + diff --git a/queue-5.19/mips-bcm47xx-cast-memcmp-of-function-to-void.patch b/queue-5.19/mips-bcm47xx-cast-memcmp-of-function-to-void.patch new file mode 100644 index 00000000000..c55f56304df --- /dev/null +++ b/queue-5.19/mips-bcm47xx-cast-memcmp-of-function-to-void.patch @@ -0,0 +1,62 @@ +From 781e8e729b1fcaa39ac3dd2982e76aeab9f8df10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 16:05:56 -0700 +Subject: MIPS: BCM47XX: Cast memcmp() of function to (void *) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kees Cook + +[ Upstream commit 0dedcf6e3301836eb70cfa649052e7ce4fcd13ba ] + +Clang is especially sensitive about argument type matching when using +__overloaded functions (like memcmp(), etc). Help it see that function +pointers are just "void *". Avoids this error: + +arch/mips/bcm47xx/prom.c:89:8: error: no matching function for call to 'memcmp' + if (!memcmp(prom_init, prom_init + mem, 32)) + ^~~~~~ +include/linux/string.h:156:12: note: candidate function not viable: no known conversion from 'void (void)' to 'const void *' for 1st argument extern int memcmp(const void *,const void *,__kernel_size_t); + +Cc: Hauke Mehrtens +Cc: "Rafał Miłecki" +Cc: Thomas Bogendoerfer +Cc: linux-mips@vger.kernel.org +Cc: Nathan Chancellor +Cc: Nick Desaulniers +Cc: llvm@lists.linux.dev +Reported-by: kernel test robot +Link: https://lore.kernel.org/lkml/202209080652.sz2d68e5-lkp@intel.com +Signed-off-by: Kees Cook +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/bcm47xx/prom.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/mips/bcm47xx/prom.c b/arch/mips/bcm47xx/prom.c +index 0a63721d0fbf..5a33d6b48d77 100644 +--- a/arch/mips/bcm47xx/prom.c ++++ b/arch/mips/bcm47xx/prom.c +@@ -86,7 +86,7 @@ static __init void prom_init_mem(void) + pr_debug("Assume 128MB RAM\n"); + break; + } +- if (!memcmp(prom_init, prom_init + mem, 32)) ++ if (!memcmp((void *)prom_init, (void *)prom_init + mem, 32)) + break; + } + lowmem = mem; +@@ -159,7 +159,7 @@ void __init bcm47xx_prom_highmem_init(void) + + off = EXTVBASE + __pa(off); + for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) { +- if (!memcmp(prom_init, (void *)(off + extmem), 16)) ++ if (!memcmp((void *)prom_init, (void *)(off + extmem), 16)) + break; + } + extmem -= lowmem; +-- +2.35.1 + diff --git a/queue-5.19/mips-dts-ralink-mt7621-fix-external-phy-on-gb-pc2.patch b/queue-5.19/mips-dts-ralink-mt7621-fix-external-phy-on-gb-pc2.patch new file mode 100644 index 00000000000..6adbdeec941 --- /dev/null +++ b/queue-5.19/mips-dts-ralink-mt7621-fix-external-phy-on-gb-pc2.patch @@ -0,0 +1,47 @@ +From a49485ab2d4f78eaaa43315e056ccca0c77c9ff5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 20:25:55 +0300 +Subject: mips: dts: ralink: mt7621: fix external phy on GB-PC2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arınç ÜNAL + +[ Upstream commit 247825f991b34440f9b9d4fe607502435a42ac7b ] + +The address of the external phy on the mdio bus is 5. Update the devicetree +for GB-PC2 accordingly. + +Fixes: 5bc148649cf3 ("staging: mt7621-dts: fix GB-PC2 devicetree") +Signed-off-by: Arınç ÜNAL +Reviewed-by: Sergio Paracuellos +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts +index a6201a119a1f..5bdc63187e77 100644 +--- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts ++++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts +@@ -83,12 +83,12 @@ + + &gmac1 { + status = "okay"; +- phy-handle = <ðphy7>; ++ phy-handle = <ðphy5>; + }; + + &mdio { +- ethphy7: ethernet-phy@7 { +- reg = <7>; ++ ethphy5: ethernet-phy@5 { ++ reg = <5>; + phy-mode = "rgmii-rxid"; + }; + }; +-- +2.35.1 + diff --git a/queue-5.19/mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch b/queue-5.19/mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch new file mode 100644 index 00000000000..86beebec6c6 --- /dev/null +++ b/queue-5.19/mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch @@ -0,0 +1,141 @@ +From 5a6c845da58a3a6aa0ed2831604bbcc0c514047c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 11:29:17 +0800 +Subject: MIPS: SGI-IP27: Fix platform-device leak in bridge_platform_create() + +From: Lin Yujun + +[ Upstream commit 11bec9cba4de06b3c0e9e4041453c2caaa1cbec1 ] + +In error case in bridge_platform_create after calling +platform_device_add()/platform_device_add_data()/ +platform_device_add_resources(), release the failed +'pdev' or it will be leak, call platform_device_put() +to fix this problem. + +Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd', +use platform_device_unregister() to release sgi_w1 +resources when xtalk-bridge registration fails. + +Fixes: 5dc76a96e95a ("MIPS: PCI: use information from 1-wire PROM for IOC3 detection") +Signed-off-by: Lin Yujun +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/sgi-ip27/ip27-xtalk.c | 70 +++++++++++++++++++++++---------- + 1 file changed, 50 insertions(+), 20 deletions(-) + +diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c +index e762886d1dda..5143d1cf8984 100644 +--- a/arch/mips/sgi-ip27/ip27-xtalk.c ++++ b/arch/mips/sgi-ip27/ip27-xtalk.c +@@ -27,15 +27,18 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) + { + struct xtalk_bridge_platform_data *bd; + struct sgi_w1_platform_data *wd; +- struct platform_device *pdev; ++ struct platform_device *pdev_wd; ++ struct platform_device *pdev_bd; + struct resource w1_res; + unsigned long offset; + + offset = NODE_OFFSET(nasid); + + wd = kzalloc(sizeof(*wd), GFP_KERNEL); +- if (!wd) +- goto no_mem; ++ if (!wd) { ++ pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); ++ return; ++ } + + snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx", + offset + (widget << SWIN_SIZE_BITS)); +@@ -46,24 +49,35 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) + w1_res.end = w1_res.start + 3; + w1_res.flags = IORESOURCE_MEM; + +- pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); +- if (!pdev) { +- kfree(wd); +- goto no_mem; ++ pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); ++ if (!pdev_wd) { ++ pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); ++ goto err_kfree_wd; ++ } ++ if (platform_device_add_resources(pdev_wd, &w1_res, 1)) { ++ pr_warn("xtalk:n%d/%x bridge failed to add platform resources.\n", nasid, widget); ++ goto err_put_pdev_wd; ++ } ++ if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) { ++ pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget); ++ goto err_put_pdev_wd; ++ } ++ if (platform_device_add(pdev_wd)) { ++ pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget); ++ goto err_put_pdev_wd; + } +- platform_device_add_resources(pdev, &w1_res, 1); +- platform_device_add_data(pdev, wd, sizeof(*wd)); + /* platform_device_add_data() duplicates the data */ + kfree(wd); +- platform_device_add(pdev); + + bd = kzalloc(sizeof(*bd), GFP_KERNEL); +- if (!bd) +- goto no_mem; +- pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); +- if (!pdev) { +- kfree(bd); +- goto no_mem; ++ if (!bd) { ++ pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); ++ goto err_unregister_pdev_wd; ++ } ++ pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); ++ if (!pdev_bd) { ++ pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); ++ goto err_kfree_bd; + } + + +@@ -84,15 +98,31 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid) + bd->io.flags = IORESOURCE_IO; + bd->io_offset = offset; + +- platform_device_add_data(pdev, bd, sizeof(*bd)); ++ if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) { ++ pr_warn("xtalk:n%d/%x bridge failed to add platform data.\n", nasid, widget); ++ goto err_put_pdev_bd; ++ } ++ if (platform_device_add(pdev_bd)) { ++ pr_warn("xtalk:n%d/%x bridge failed to add platform device.\n", nasid, widget); ++ goto err_put_pdev_bd; ++ } + /* platform_device_add_data() duplicates the data */ + kfree(bd); +- platform_device_add(pdev); + pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget); + return; + +-no_mem: +- pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget); ++err_put_pdev_bd: ++ platform_device_put(pdev_bd); ++err_kfree_bd: ++ kfree(bd); ++err_unregister_pdev_wd: ++ platform_device_unregister(pdev_wd); ++ return; ++err_put_pdev_wd: ++ platform_device_put(pdev_wd); ++err_kfree_wd: ++ kfree(wd); ++ return; + } + + static int probe_one_port(nasid_t nasid, int widget, int masterwid) +-- +2.35.1 + diff --git a/queue-5.19/mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch b/queue-5.19/mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch new file mode 100644 index 00000000000..59d451e17e7 --- /dev/null +++ b/queue-5.19/mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch @@ -0,0 +1,138 @@ +From 9f9bd4921ce9a5792228f4c7150caa247ca53cdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 11:28:07 +0800 +Subject: MIPS: SGI-IP30: Fix platform-device leak in bridge_platform_create() + +From: Lin Yujun + +[ Upstream commit 1e6d11fe72e311c1989991ee318d239f650fa318 ] + +In error case in bridge_platform_create after calling +platform_device_add()/platform_device_add_data()/ +platform_device_add_resources(), release the failed +'pdev' or it will be leak, call platform_device_put() +to fix this problem. + +Besides, 'pdev' is divided into 'pdev_wd' and 'pdev_bd', +use platform_device_unregister() to release sgi_w1 +resources when xtalk-bridge registration fails. + +Fixes: fd27234f24ae ("MIPS: add support for SGI Octane (IP30)") +Signed-off-by: Lin Yujun +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/sgi-ip30/ip30-xtalk.c | 70 +++++++++++++++++++++++---------- + 1 file changed, 50 insertions(+), 20 deletions(-) + +diff --git a/arch/mips/sgi-ip30/ip30-xtalk.c b/arch/mips/sgi-ip30/ip30-xtalk.c +index 8129524421cb..7ceb2b23ea1c 100644 +--- a/arch/mips/sgi-ip30/ip30-xtalk.c ++++ b/arch/mips/sgi-ip30/ip30-xtalk.c +@@ -40,12 +40,15 @@ static void bridge_platform_create(int widget, int masterwid) + { + struct xtalk_bridge_platform_data *bd; + struct sgi_w1_platform_data *wd; +- struct platform_device *pdev; ++ struct platform_device *pdev_wd; ++ struct platform_device *pdev_bd; + struct resource w1_res; + + wd = kzalloc(sizeof(*wd), GFP_KERNEL); +- if (!wd) +- goto no_mem; ++ if (!wd) { ++ pr_warn("xtalk:%x bridge create out of memory\n", widget); ++ return; ++ } + + snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx", + IP30_SWIN_BASE(widget)); +@@ -56,24 +59,35 @@ static void bridge_platform_create(int widget, int masterwid) + w1_res.end = w1_res.start + 3; + w1_res.flags = IORESOURCE_MEM; + +- pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); +- if (!pdev) { +- kfree(wd); +- goto no_mem; ++ pdev_wd = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); ++ if (!pdev_wd) { ++ pr_warn("xtalk:%x bridge create out of memory\n", widget); ++ goto err_kfree_wd; ++ } ++ if (platform_device_add_resources(pdev_wd, &w1_res, 1)) { ++ pr_warn("xtalk:%x bridge failed to add platform resources.\n", widget); ++ goto err_put_pdev_wd; ++ } ++ if (platform_device_add_data(pdev_wd, wd, sizeof(*wd))) { ++ pr_warn("xtalk:%x bridge failed to add platform data.\n", widget); ++ goto err_put_pdev_wd; ++ } ++ if (platform_device_add(pdev_wd)) { ++ pr_warn("xtalk:%x bridge failed to add platform device.\n", widget); ++ goto err_put_pdev_wd; + } +- platform_device_add_resources(pdev, &w1_res, 1); +- platform_device_add_data(pdev, wd, sizeof(*wd)); + /* platform_device_add_data() duplicates the data */ + kfree(wd); +- platform_device_add(pdev); + + bd = kzalloc(sizeof(*bd), GFP_KERNEL); +- if (!bd) +- goto no_mem; +- pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); +- if (!pdev) { +- kfree(bd); +- goto no_mem; ++ if (!bd) { ++ pr_warn("xtalk:%x bridge create out of memory\n", widget); ++ goto err_unregister_pdev_wd; ++ } ++ pdev_bd = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); ++ if (!pdev_bd) { ++ pr_warn("xtalk:%x bridge create out of memory\n", widget); ++ goto err_kfree_bd; + } + + bd->bridge_addr = IP30_RAW_SWIN_BASE(widget); +@@ -93,15 +107,31 @@ static void bridge_platform_create(int widget, int masterwid) + bd->io.flags = IORESOURCE_IO; + bd->io_offset = IP30_SWIN_BASE(widget); + +- platform_device_add_data(pdev, bd, sizeof(*bd)); ++ if (platform_device_add_data(pdev_bd, bd, sizeof(*bd))) { ++ pr_warn("xtalk:%x bridge failed to add platform data.\n", widget); ++ goto err_put_pdev_bd; ++ } ++ if (platform_device_add(pdev_bd)) { ++ pr_warn("xtalk:%x bridge failed to add platform device.\n", widget); ++ goto err_put_pdev_bd; ++ } + /* platform_device_add_data() duplicates the data */ + kfree(bd); +- platform_device_add(pdev); + pr_info("xtalk:%x bridge widget\n", widget); + return; + +-no_mem: +- pr_warn("xtalk:%x bridge create out of memory\n", widget); ++err_put_pdev_bd: ++ platform_device_put(pdev_bd); ++err_kfree_bd: ++ kfree(bd); ++err_unregister_pdev_wd: ++ platform_device_unregister(pdev_wd); ++ return; ++err_put_pdev_wd: ++ platform_device_put(pdev_wd); ++err_kfree_wd: ++ kfree(wd); ++ return; + } + + static unsigned int __init xbow_widget_active(s8 wid) +-- +2.35.1 + diff --git a/queue-5.19/misc-ocxl-fix-possible-refcount-leak-in-afu_ioctl.patch b/queue-5.19/misc-ocxl-fix-possible-refcount-leak-in-afu_ioctl.patch new file mode 100644 index 00000000000..0ecada86d11 --- /dev/null +++ b/queue-5.19/misc-ocxl-fix-possible-refcount-leak-in-afu_ioctl.patch @@ -0,0 +1,38 @@ +From e72b1b7bc1d13cbdc187eba324b7bb0193baff6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 16:26:00 +0800 +Subject: misc: ocxl: fix possible refcount leak in afu_ioctl() + +From: Hangyu Hua + +[ Upstream commit c3b69ba5114c860d730870c03ab4ee45276e5e35 ] + +eventfd_ctx_put need to be called to put the refcount that gotten by +eventfd_ctx_fdget when ocxl_irq_set_handler fails. + +Fixes: 060146614643 ("ocxl: move event_fd handling to frontend") +Acked-by: Frederic Barrat +Signed-off-by: Hangyu Hua +Link: https://lore.kernel.org/r/20220824082600.36159-1-hbh25y@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/misc/ocxl/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c +index 6777c419a8da..d46dba2df5a1 100644 +--- a/drivers/misc/ocxl/file.c ++++ b/drivers/misc/ocxl/file.c +@@ -257,6 +257,8 @@ static long afu_ioctl(struct file *file, unsigned int cmd, + if (IS_ERR(ev_ctx)) + return PTR_ERR(ev_ctx); + rc = ocxl_irq_set_handler(ctx, irq_id, irq_handler, irq_free, ev_ctx); ++ if (rc) ++ eventfd_ctx_put(ev_ctx); + break; + + case OCXL_IOCTL_GET_METADATA: +-- +2.35.1 + diff --git a/queue-5.19/misdn-fix-use-after-free-bugs-in-l1oip-timer-handler.patch b/queue-5.19/misdn-fix-use-after-free-bugs-in-l1oip-timer-handler.patch new file mode 100644 index 00000000000..378c3149aca --- /dev/null +++ b/queue-5.19/misdn-fix-use-after-free-bugs-in-l1oip-timer-handler.patch @@ -0,0 +1,97 @@ +From 411008af088fd9898554bdb1d3edc4d1eb01b923 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 21:39:38 +0800 +Subject: mISDN: fix use-after-free bugs in l1oip timer handlers + +From: Duoming Zhou + +[ Upstream commit 2568a7e0832ee30b0a351016d03062ab4e0e0a3f ] + +The l1oip_cleanup() traverses the l1oip_ilist and calls +release_card() to cleanup module and stack. However, +release_card() calls del_timer() to delete the timers +such as keep_tl and timeout_tl. If the timer handler is +running, the del_timer() will not stop it and result in +UAF bugs. One of the processes is shown below: + + (cleanup routine) | (timer handler) +release_card() | l1oip_timeout() + ... | + del_timer() | ... + ... | + kfree(hc) //FREE | + | hc->timeout_on = 0 //USE + +Fix by calling del_timer_sync() in release_card(), which +makes sure the timer handlers have finished before the +resources, such as l1oip and so on, have been deallocated. + +What's more, the hc->workq and hc->socket_thread can kick +those timers right back in. We add a bool flag to show +if card is released. Then, check this flag in hc->workq +and hc->socket_thread. + +Fixes: 3712b42d4b1b ("Add layer1 over IP support") +Signed-off-by: Duoming Zhou +Reviewed-by: Leon Romanovsky +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/isdn/mISDN/l1oip.h | 1 + + drivers/isdn/mISDN/l1oip_core.c | 13 +++++++------ + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/drivers/isdn/mISDN/l1oip.h b/drivers/isdn/mISDN/l1oip.h +index 7ea10db20e3a..48133d022812 100644 +--- a/drivers/isdn/mISDN/l1oip.h ++++ b/drivers/isdn/mISDN/l1oip.h +@@ -59,6 +59,7 @@ struct l1oip { + int bundle; /* bundle channels in one frm */ + int codec; /* codec to use for transmis. */ + int limit; /* limit number of bchannels */ ++ bool shutdown; /* if card is released */ + + /* timer */ + struct timer_list keep_tl; +diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c +index 2c40412466e6..a77195e378b7 100644 +--- a/drivers/isdn/mISDN/l1oip_core.c ++++ b/drivers/isdn/mISDN/l1oip_core.c +@@ -275,7 +275,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, + p = frame; + + /* restart timer */ +- if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ)) ++ if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ) && !hc->shutdown) + mod_timer(&hc->keep_tl, jiffies + L1OIP_KEEPALIVE * HZ); + else + hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE * HZ; +@@ -601,7 +601,9 @@ l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) + goto multiframe; + + /* restart timer */ +- if (time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || !hc->timeout_on) { ++ if ((time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || ++ !hc->timeout_on) && ++ !hc->shutdown) { + hc->timeout_on = 1; + mod_timer(&hc->timeout_tl, jiffies + L1OIP_TIMEOUT * HZ); + } else /* only adjust timer */ +@@ -1232,11 +1234,10 @@ release_card(struct l1oip *hc) + { + int ch; + +- if (timer_pending(&hc->keep_tl)) +- del_timer(&hc->keep_tl); ++ hc->shutdown = true; + +- if (timer_pending(&hc->timeout_tl)) +- del_timer(&hc->timeout_tl); ++ del_timer_sync(&hc->keep_tl); ++ del_timer_sync(&hc->timeout_tl); + + cancel_work_sync(&hc->workq); + +-- +2.35.1 + diff --git a/queue-5.19/mmc-au1xmmc-fix-an-error-handling-path-in-au1xmmc_pr.patch b/queue-5.19/mmc-au1xmmc-fix-an-error-handling-path-in-au1xmmc_pr.patch new file mode 100644 index 00000000000..da9951fa5b6 --- /dev/null +++ b/queue-5.19/mmc-au1xmmc-fix-an-error-handling-path-in-au1xmmc_pr.patch @@ -0,0 +1,41 @@ +From 3fb42e2d2f169409dfa6f5bb0cc5818b7ddc30ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 09:33:57 +0200 +Subject: mmc: au1xmmc: Fix an error handling path in au1xmmc_probe() + +From: Christophe JAILLET + +[ Upstream commit 5cbedf52608cc3cbc1c2a9a861fb671620427a20 ] + +If clk_prepare_enable() fails, there is no point in calling +clk_disable_unprepare() in the error handling path. + +Move the out_clk label at the right place. + +Fixes: b6507596dfd6 ("MIPS: Alchemy: au1xmmc: use clk framework") +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/21d99886d07fa7fcbec74992657dabad98c935c4.1661412818.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/au1xmmc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c +index a9a0837153d8..c88b039dc9fb 100644 +--- a/drivers/mmc/host/au1xmmc.c ++++ b/drivers/mmc/host/au1xmmc.c +@@ -1097,8 +1097,9 @@ static int au1xmmc_probe(struct platform_device *pdev) + if (host->platdata && host->platdata->cd_setup && + !(mmc->caps & MMC_CAP_NEEDS_POLL)) + host->platdata->cd_setup(mmc, 0); +-out_clk: ++ + clk_disable_unprepare(host->clk); ++out_clk: + clk_put(host->clk); + out_irq: + free_irq(host->irq, host); +-- +2.35.1 + diff --git a/queue-5.19/mmc-wmt-sdmmc-fix-an-error-handling-path-in-wmt_mci_.patch b/queue-5.19/mmc-wmt-sdmmc-fix-an-error-handling-path-in-wmt_mci_.patch new file mode 100644 index 00000000000..5175a90d103 --- /dev/null +++ b/queue-5.19/mmc-wmt-sdmmc-fix-an-error-handling-path-in-wmt_mci_.patch @@ -0,0 +1,48 @@ +From a44fc4fc83d43f9e795d3ccf2aabf108f9a83e8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 21:06:40 +0200 +Subject: mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe() + +From: Christophe JAILLET + +[ Upstream commit cb58188ad90a61784a56a64f5107faaf2ad323e7 ] + +A dma_free_coherent() call is missing in the error handling path of the +probe, as already done in the remove function. + +Fixes: 3a96dff0f828 ("mmc: SD/MMC Host Controller for Wondermedia WM8505/WM8650") +Signed-off-by: Christophe JAILLET +Reviewed-by: Dan Carpenter +Link: https://lore.kernel.org/r/53fc6ffa5d1c428fefeae7d313cf4a669c3a1e98.1663873255.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Ulf Hansson +Signed-off-by: Sasha Levin +--- + drivers/mmc/host/wmt-sdmmc.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c +index 163ac9df8cca..9b5c503e3a3f 100644 +--- a/drivers/mmc/host/wmt-sdmmc.c ++++ b/drivers/mmc/host/wmt-sdmmc.c +@@ -846,7 +846,7 @@ static int wmt_mci_probe(struct platform_device *pdev) + if (IS_ERR(priv->clk_sdmmc)) { + dev_err(&pdev->dev, "Error getting clock\n"); + ret = PTR_ERR(priv->clk_sdmmc); +- goto fail5; ++ goto fail5_and_a_half; + } + + ret = clk_prepare_enable(priv->clk_sdmmc); +@@ -863,6 +863,9 @@ static int wmt_mci_probe(struct platform_device *pdev) + return 0; + fail6: + clk_put(priv->clk_sdmmc); ++fail5_and_a_half: ++ dma_free_coherent(&pdev->dev, mmc->max_blk_count * 16, ++ priv->dma_desc_buffer, priv->dma_desc_device_addr); + fail5: + free_irq(dma_irq, priv); + fail4: +-- +2.35.1 + diff --git a/queue-5.19/module-tracking-keep-a-record-of-tainted-unloaded-mo.patch b/queue-5.19/module-tracking-keep-a-record-of-tainted-unloaded-mo.patch new file mode 100644 index 00000000000..5319230573e --- /dev/null +++ b/queue-5.19/module-tracking-keep-a-record-of-tainted-unloaded-mo.patch @@ -0,0 +1,39 @@ +From 0ca45e4948b1c3b6ff2cf4b1718ce4e7ff60f49d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Oct 2022 14:38:12 +0100 +Subject: module: tracking: Keep a record of tainted unloaded modules only + +From: Aaron Tomlin + +[ Upstream commit 47cc75aa92837a9d3f15157d6272ff285585d75d ] + +This ensures that no module record/or entry is added to the +unloaded_tainted_modules list if it does not carry a taint. + +Reported-by: Alexey Dobriyan +Fixes: 99bd9956551b ("module: Introduce module unload taint tracking") +Signed-off-by: Aaron Tomlin +Acked-by: Luis Chamberlain +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/module/tracking.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/kernel/module/tracking.c b/kernel/module/tracking.c +index 7f8133044d09..af52cabfe632 100644 +--- a/kernel/module/tracking.c ++++ b/kernel/module/tracking.c +@@ -21,6 +21,9 @@ int try_add_tainted_module(struct module *mod) + + module_assert_mutex_or_preempt(); + ++ if (!mod->taints) ++ goto out; ++ + list_for_each_entry_rcu(mod_taint, &unloaded_tainted_modules, list, + lockdep_is_held(&module_mutex)) { + if (!strcmp(mod_taint->name, mod->name) && +-- +2.35.1 + diff --git a/queue-5.19/mtd-devices-docg3-check-the-return-value-of-devm_ior.patch b/queue-5.19/mtd-devices-docg3-check-the-return-value-of-devm_ior.patch new file mode 100644 index 00000000000..e350bbd5b93 --- /dev/null +++ b/queue-5.19/mtd-devices-docg3-check-the-return-value-of-devm_ior.patch @@ -0,0 +1,46 @@ +From 1422d36c6e2c3b834fe716b59c697c63cd6cb458 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 17:16:44 +0800 +Subject: mtd: devices: docg3: check the return value of devm_ioremap() in the + probe + +From: William Dean + +[ Upstream commit 26e784433e6c65735cd6d93a8db52531970d9a60 ] + +The function devm_ioremap() in docg3_probe() can fail, so +its return value should be checked. + +Fixes: 82402aeb8c81e ("mtd: docg3: Use devm_*() functions") +Reported-by: Hacash Robot +Signed-off-by: William Dean +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220722091644.2937953-1-williamsukatube@163.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/devices/docg3.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c +index 5b0ae5ddad74..27c08f22dec8 100644 +--- a/drivers/mtd/devices/docg3.c ++++ b/drivers/mtd/devices/docg3.c +@@ -1974,9 +1974,14 @@ static int __init docg3_probe(struct platform_device *pdev) + dev_err(dev, "No I/O memory resource defined\n"); + return ret; + } +- base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE); + + ret = -ENOMEM; ++ base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE); ++ if (!base) { ++ dev_err(dev, "devm_ioremap dev failed\n"); ++ return ret; ++ } ++ + cascade = devm_kcalloc(dev, DOC_MAX_NBFLOORS, sizeof(*cascade), + GFP_KERNEL); + if (!cascade) +-- +2.35.1 + diff --git a/queue-5.19/mtd-rawnand-fsl_elbc-fix-none-ecc-mode.patch b/queue-5.19/mtd-rawnand-fsl_elbc-fix-none-ecc-mode.patch new file mode 100644 index 00000000000..5c268cd8b76 --- /dev/null +++ b/queue-5.19/mtd-rawnand-fsl_elbc-fix-none-ecc-mode.patch @@ -0,0 +1,98 @@ +From 5157c683179fb08376545551ea7c62b70da95550 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Jul 2022 20:43:28 +0200 +Subject: mtd: rawnand: fsl_elbc: Fix none ECC mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 049e43b9fd8fd2966940485da163d67e96ee3fea ] + +Commit f6424c22aa36 ("mtd: rawnand: fsl_elbc: Make SW ECC work") added +support for specifying ECC mode via DTS and skipping autodetection. + +But it broke explicit specification of HW ECC mode in DTS as correct +settings for HW ECC mode are applied only when NONE mode or nothing was +specified in DTS file. + +Also it started aliasing NONE mode to be same as when ECC mode was not +specified and disallowed usage of ON_DIE mode. + +Fix all these issues. Use autodetection of ECC mode only in case when mode +was really not specified in DTS file by checking that ecc value is invalid. +Set HW ECC settings either when HW ECC was specified in DTS or it was +autodetected. And do not fail when ON_DIE mode is set. + +Fixes: f6424c22aa36 ("mtd: rawnand: fsl_elbc: Make SW ECC work") +Signed-off-by: Pali Rohár +Reviewed-by: Marek Behún +Reviewed-by: Marek Behún +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220707184328.3845-1-pali@kernel.org +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/fsl_elbc_nand.c | 28 ++++++++++++++++------------ + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c +index aab93b9e6052..a18d121396aa 100644 +--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c ++++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c +@@ -726,36 +726,40 @@ static int fsl_elbc_attach_chip(struct nand_chip *chip) + struct fsl_lbc_regs __iomem *lbc = ctrl->regs; + unsigned int al; + +- switch (chip->ecc.engine_type) { + /* + * if ECC was not chosen in DT, decide whether to use HW or SW ECC from + * CS Base Register + */ +- case NAND_ECC_ENGINE_TYPE_NONE: ++ if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) { + /* If CS Base Register selects full hardware ECC then use it */ + if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == + BR_DECC_CHK_GEN) { +- chip->ecc.read_page = fsl_elbc_read_page; +- chip->ecc.write_page = fsl_elbc_write_page; +- chip->ecc.write_subpage = fsl_elbc_write_subpage; +- + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; +- mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); +- chip->ecc.size = 512; +- chip->ecc.bytes = 3; +- chip->ecc.strength = 1; + } else { + /* otherwise fall back to default software ECC */ + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; + chip->ecc.algo = NAND_ECC_ALGO_HAMMING; + } ++ } ++ ++ switch (chip->ecc.engine_type) { ++ /* if HW ECC was chosen, setup ecc and oob layout */ ++ case NAND_ECC_ENGINE_TYPE_ON_HOST: ++ chip->ecc.read_page = fsl_elbc_read_page; ++ chip->ecc.write_page = fsl_elbc_write_page; ++ chip->ecc.write_subpage = fsl_elbc_write_subpage; ++ mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); ++ chip->ecc.size = 512; ++ chip->ecc.bytes = 3; ++ chip->ecc.strength = 1; + break; + +- /* if SW ECC was chosen in DT, we do not need to set anything here */ ++ /* if none or SW ECC was chosen, we do not need to set anything here */ ++ case NAND_ECC_ENGINE_TYPE_NONE: + case NAND_ECC_ENGINE_TYPE_SOFT: ++ case NAND_ECC_ENGINE_TYPE_ON_DIE: + break; + +- /* should we also implement *_ECC_ENGINE_CONTROLLER to do as above? */ + default: + return -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.19/mtd-rawnand-intel-don-t-re-define-nand_data_iface_ch.patch b/queue-5.19/mtd-rawnand-intel-don-t-re-define-nand_data_iface_ch.patch new file mode 100644 index 00000000000..dade0be7c9a --- /dev/null +++ b/queue-5.19/mtd-rawnand-intel-don-t-re-define-nand_data_iface_ch.patch @@ -0,0 +1,38 @@ +From 3fe8296de501c453d1def2b9ba3a3d17b1499614 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Jul 2022 01:12:24 +0200 +Subject: mtd: rawnand: intel: Don't re-define NAND_DATA_IFACE_CHECK_ONLY + +From: Martin Blumenstingl + +[ Upstream commit ebe0cd60fcffd499f8020fde9b3b74acba9c22af ] + +NAND_DATA_IFACE_CHECK_ONLY is already defined in +include/linux/mtd/rawnand.h which is also included by the driver. Drop +the re-definition from the intel-nand-controller driver. + +Fixes: 0b1039f016e8a3 ("mtd: rawnand: Add NAND controller support on Intel LGM SoC") +Signed-off-by: Martin Blumenstingl +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220702231227.1579176-6-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/intel-nand-controller.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c +index 056835fd4562..3df16d5ecae8 100644 +--- a/drivers/mtd/nand/raw/intel-nand-controller.c ++++ b/drivers/mtd/nand/raw/intel-nand-controller.c +@@ -100,8 +100,6 @@ + + #define HSNAND_ECC_OFFSET 0x008 + +-#define NAND_DATA_IFACE_CHECK_ONLY -1 +- + #define MAX_CS 2 + + #define USEC_PER_SEC 1000000L +-- +2.35.1 + diff --git a/queue-5.19/mtd-rawnand-intel-read-the-chip-select-line-from-the.patch b/queue-5.19/mtd-rawnand-intel-read-the-chip-select-line-from-the.patch new file mode 100644 index 00000000000..988f6bd715f --- /dev/null +++ b/queue-5.19/mtd-rawnand-intel-read-the-chip-select-line-from-the.patch @@ -0,0 +1,68 @@ +From 9a476092bc8aa952ae3ba1a8c9b19e9db1a15c95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Jul 2022 01:12:22 +0200 +Subject: mtd: rawnand: intel: Read the chip-select line from the correct OF + node + +From: Martin Blumenstingl + +[ Upstream commit bfc618fcc3f167ad082053e81e9d664e724c6288 ] + +The chip select has to be read from the flash node which is a child node +of the NAND controller. + +Fixes: 0b1039f016e8a3 ("mtd: rawnand: Add NAND controller support on Intel LGM SoC") +Signed-off-by: Martin Blumenstingl +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220702231227.1579176-4-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/intel-nand-controller.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c +index e91b879b32bd..3df3f32423f9 100644 +--- a/drivers/mtd/nand/raw/intel-nand-controller.c ++++ b/drivers/mtd/nand/raw/intel-nand-controller.c +@@ -16,6 +16,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -580,6 +581,7 @@ static int ebu_nand_probe(struct platform_device *pdev) + { + struct device *dev = &pdev->dev; + struct ebu_nand_controller *ebu_host; ++ struct device_node *chip_np; + struct nand_chip *nand; + struct mtd_info *mtd; + struct resource *res; +@@ -604,7 +606,12 @@ static int ebu_nand_probe(struct platform_device *pdev) + if (IS_ERR(ebu_host->hsnand)) + return PTR_ERR(ebu_host->hsnand); + +- ret = device_property_read_u32(dev, "reg", &cs); ++ chip_np = of_get_next_child(dev->of_node, NULL); ++ if (!chip_np) ++ return dev_err_probe(dev, -EINVAL, ++ "Could not find child node for the NAND chip\n"); ++ ++ ret = of_property_read_u32(chip_np, "reg", &cs); + if (ret) { + dev_err(dev, "failed to get chip select: %d\n", ret); + return ret; +@@ -660,7 +667,7 @@ static int ebu_nand_probe(struct platform_device *pdev) + writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN, + ebu_host->ebu + EBU_ADDR_SEL(cs)); + +- nand_set_flash_node(&ebu_host->chip, dev->of_node); ++ nand_set_flash_node(&ebu_host->chip, chip_np); + + mtd = nand_to_mtd(&ebu_host->chip); + if (!mtd->name) { +-- +2.35.1 + diff --git a/queue-5.19/mtd-rawnand-intel-remove-undocumented-compatible-str.patch b/queue-5.19/mtd-rawnand-intel-remove-undocumented-compatible-str.patch new file mode 100644 index 00000000000..1cfc72bb807 --- /dev/null +++ b/queue-5.19/mtd-rawnand-intel-remove-undocumented-compatible-str.patch @@ -0,0 +1,37 @@ +From f425f907c07d595d518327d86f5af5cb6684b775 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Jul 2022 01:12:23 +0200 +Subject: mtd: rawnand: intel: Remove undocumented compatible string + +From: Martin Blumenstingl + +[ Upstream commit 68c02ebaa34d41063ccbbc789a352537ddc3cd8a ] + +The "intel,nand-controller" compatible string is not part of the +dt-bindings. Remove it from the driver as it's not supposed to be used +without any documentation for it. + +Fixes: 0b1039f016e8a3 ("mtd: rawnand: Add NAND controller support on Intel LGM SoC") +Signed-off-by: Martin Blumenstingl +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/20220702231227.1579176-5-martin.blumenstingl@googlemail.com +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/intel-nand-controller.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c +index 3df3f32423f9..056835fd4562 100644 +--- a/drivers/mtd/nand/raw/intel-nand-controller.c ++++ b/drivers/mtd/nand/raw/intel-nand-controller.c +@@ -723,7 +723,6 @@ static int ebu_nand_remove(struct platform_device *pdev) + } + + static const struct of_device_id ebu_nand_match[] = { +- { .compatible = "intel,nand-controller" }, + { .compatible = "intel,lgm-ebunand" }, + {} + }; +-- +2.35.1 + diff --git a/queue-5.19/mtd-rawnand-meson-fix-bit-map-use-in-meson_nfc_ecc_c.patch b/queue-5.19/mtd-rawnand-meson-fix-bit-map-use-in-meson_nfc_ecc_c.patch new file mode 100644 index 00000000000..4b7b01e6193 --- /dev/null +++ b/queue-5.19/mtd-rawnand-meson-fix-bit-map-use-in-meson_nfc_ecc_c.patch @@ -0,0 +1,49 @@ +From 5e8755f4151529d249132022429dd29319b953dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jul 2022 10:12:12 +0300 +Subject: mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct() + +From: Dan Carpenter + +[ Upstream commit 3e4ad3212cf22687410b1e8f4e68feec50646113 ] + +The meson_nfc_ecc_correct() function accidentally does a right shift +instead of a left shift so it only works for BIT(0). Also use +BIT_ULL() because "correct_bitmap" is a u64 and we want to avoid +shift wrapping bugs. + +Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller") +Signed-off-by: Dan Carpenter +Acked-by: Liang Yang +Signed-off-by: Miquel Raynal +Link: https://lore.kernel.org/linux-mtd/YuI2zF1hP65+LE7r@kili +Signed-off-by: Sasha Levin +--- + drivers/mtd/nand/raw/meson_nand.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c +index 032180183339..b97adeee4cc1 100644 +--- a/drivers/mtd/nand/raw/meson_nand.c ++++ b/drivers/mtd/nand/raw/meson_nand.c +@@ -454,7 +454,7 @@ static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips, + if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) { + mtd->ecc_stats.corrected += ECC_ERR_CNT(*info); + *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info)); +- *correct_bitmap |= 1 >> i; ++ *correct_bitmap |= BIT_ULL(i); + continue; + } + if ((nand->options & NAND_NEED_SCRAMBLING) && +@@ -800,7 +800,7 @@ static int meson_nfc_read_page_hwecc(struct nand_chip *nand, u8 *buf, + u8 *data = buf + i * ecc->size; + u8 *oob = nand->oob_poi + i * (ecc->bytes + 2); + +- if (correct_bitmap & (1 << i)) ++ if (correct_bitmap & BIT_ULL(i)) + continue; + ret = nand_check_erased_ecc_chunk(data, ecc->size, + oob, ecc->bytes + 2, +-- +2.35.1 + diff --git a/queue-5.19/nbd-fix-hung-when-signal-interrupts-nbd_start_device.patch b/queue-5.19/nbd-fix-hung-when-signal-interrupts-nbd_start_device.patch new file mode 100644 index 00000000000..cf0ccd5e7ff --- /dev/null +++ b/queue-5.19/nbd-fix-hung-when-signal-interrupts-nbd_start_device.patch @@ -0,0 +1,69 @@ +From ad3484c76e845b05251f91ef00768d7c9decc8c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 01:35:02 +0900 +Subject: nbd: Fix hung when signal interrupts nbd_start_device_ioctl() + +From: Shigeru Yoshida + +[ Upstream commit 1de7c3cf48fc41cd95adb12bd1ea9033a917798a ] + +syzbot reported hung task [1]. The following program is a simplified +version of the reproducer: + +int main(void) +{ + int sv[2], fd; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) + return 1; + if ((fd = open("/dev/nbd0", 0)) < 0) + return 1; + if (ioctl(fd, NBD_SET_SIZE_BLOCKS, 0x81) < 0) + return 1; + if (ioctl(fd, NBD_SET_SOCK, sv[0]) < 0) + return 1; + if (ioctl(fd, NBD_DO_IT) < 0) + return 1; + return 0; +} + +When signal interrupt nbd_start_device_ioctl() waiting the condition +atomic_read(&config->recv_threads) == 0, the task can hung because it +waits the completion of the inflight IOs. + +This patch fixes the issue by clearing queue, not just shutdown, when +signal interrupt nbd_start_device_ioctl(). + +Link: https://syzkaller.appspot.com/bug?id=7d89a3ffacd2b83fdd39549bc4d8e0a89ef21239 [1] +Reported-by: syzbot+38e6c55d4969a14c1534@syzkaller.appspotmail.com +Signed-off-by: Shigeru Yoshida +Reviewed-by: Josef Bacik +Link: https://lore.kernel.org/r/20220907163502.577561-1-syoshida@redhat.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + drivers/block/nbd.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c +index 20e9c53eec53..3a3680b3c4fe 100644 +--- a/drivers/block/nbd.c ++++ b/drivers/block/nbd.c +@@ -1414,10 +1414,12 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd) + mutex_unlock(&nbd->config_lock); + ret = wait_event_interruptible(config->recv_wq, + atomic_read(&config->recv_threads) == 0); +- if (ret) ++ if (ret) { + sock_shutdown(nbd); +- flush_workqueue(nbd->recv_workq); ++ nbd_clear_que(nbd); ++ } + ++ flush_workqueue(nbd->recv_workq); + mutex_lock(&nbd->config_lock); + nbd_bdev_reset(nbd); + /* user requested, ignore socket errors */ +-- +2.35.1 + diff --git a/queue-5.19/net-ax88796c-fix-return-type-of-ax88796c_start_xmit.patch b/queue-5.19/net-ax88796c-fix-return-type-of-ax88796c_start_xmit.patch new file mode 100644 index 00000000000..6f013952b03 --- /dev/null +++ b/queue-5.19/net-ax88796c-fix-return-type-of-ax88796c_start_xmit.patch @@ -0,0 +1,46 @@ +From cac43e35ff792fad716456df12c9177bd257f388 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 12:40:30 -0700 +Subject: net: ax88796c: Fix return type of ax88796c_start_xmit + +From: Nathan Huckleberry + +[ Upstream commit fcb7c210a24209ea8f6f32593580b57f52382ec2 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of ax88796c_start_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Acked-by: Lukasz Stelmach +Link: https://lore.kernel.org/r/20220912194031.808425-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/asix/ax88796c_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c +index 6ba5b024a7be..f1d610efd69e 100644 +--- a/drivers/net/ethernet/asix/ax88796c_main.c ++++ b/drivers/net/ethernet/asix/ax88796c_main.c +@@ -381,7 +381,7 @@ static int ax88796c_hard_xmit(struct ax88796c_device *ax_local) + return 1; + } + +-static int ++static netdev_tx_t + ax88796c_start_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); +-- +2.35.1 + diff --git a/queue-5.19/net-axienet-switch-to-64-bit-rx-tx-statistics.patch b/queue-5.19/net-axienet-switch-to-64-bit-rx-tx-statistics.patch new file mode 100644 index 00000000000..db0c951793c --- /dev/null +++ b/queue-5.19/net-axienet-switch-to-64-bit-rx-tx-statistics.patch @@ -0,0 +1,142 @@ +From 57f89f6817badba78e34573516fc134815ce9b57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 17:39:01 -0600 +Subject: net: axienet: Switch to 64-bit RX/TX statistics + +From: Robert Hancock + +[ Upstream commit cb45a8bf4693965e89d115cd2c510f12bc127c37 ] + +The RX and TX byte/packet statistics in this driver could be overflowed +relatively quickly on a 32-bit platform. Switch these stats to use the +u64_stats infrastructure to avoid this. + +Signed-off-by: Robert Hancock +Link: https://lore.kernel.org/r/20220829233901.3429419-1-robert.hancock@calian.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xilinx/xilinx_axienet.h | 12 ++++++ + .../net/ethernet/xilinx/xilinx_axienet_main.c | 37 +++++++++++++++++-- + 2 files changed, 45 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h +index f2e2261b4b7d..8ff4333de2ad 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h +@@ -402,6 +402,9 @@ struct axidma_bd { + * @rx_bd_num: Size of RX buffer descriptor ring + * @rx_bd_ci: Stores the index of the Rx buffer descriptor in the ring being + * accessed currently. ++ * @rx_packets: RX packet count for statistics ++ * @rx_bytes: RX byte count for statistics ++ * @rx_stat_sync: Synchronization object for RX stats + * @napi_tx: NAPI TX control structure + * @tx_dma_cr: Nominal content of TX DMA control register + * @tx_bd_v: Virtual address of the TX buffer descriptor ring +@@ -411,6 +414,9 @@ struct axidma_bd { + * complete. Only updated at runtime by TX NAPI poll. + * @tx_bd_tail: Stores the index of the next Tx buffer descriptor in the ring + * to be populated. ++ * @tx_packets: TX packet count for statistics ++ * @tx_bytes: TX byte count for statistics ++ * @tx_stat_sync: Synchronization object for TX stats + * @dma_err_task: Work structure to process Axi DMA errors + * @tx_irq: Axidma TX IRQ number + * @rx_irq: Axidma RX IRQ number +@@ -458,6 +464,9 @@ struct axienet_local { + dma_addr_t rx_bd_p; + u32 rx_bd_num; + u32 rx_bd_ci; ++ u64_stats_t rx_packets; ++ u64_stats_t rx_bytes; ++ struct u64_stats_sync rx_stat_sync; + + struct napi_struct napi_tx; + u32 tx_dma_cr; +@@ -466,6 +475,9 @@ struct axienet_local { + u32 tx_bd_num; + u32 tx_bd_ci; + u32 tx_bd_tail; ++ u64_stats_t tx_packets; ++ u64_stats_t tx_bytes; ++ struct u64_stats_sync tx_stat_sync; + + struct work_struct dma_err_task; + +diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +index 1760930ec0c4..9262988d26a3 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c ++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +@@ -752,8 +752,10 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget) + if (lp->tx_bd_ci >= lp->tx_bd_num) + lp->tx_bd_ci %= lp->tx_bd_num; + +- ndev->stats.tx_packets += packets; +- ndev->stats.tx_bytes += size; ++ u64_stats_update_begin(&lp->tx_stat_sync); ++ u64_stats_add(&lp->tx_packets, packets); ++ u64_stats_add(&lp->tx_bytes, size); ++ u64_stats_update_end(&lp->tx_stat_sync); + + /* Matches barrier in axienet_start_xmit */ + smp_mb(); +@@ -984,8 +986,10 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget) + cur_p = &lp->rx_bd_v[lp->rx_bd_ci]; + } + +- lp->ndev->stats.rx_packets += packets; +- lp->ndev->stats.rx_bytes += size; ++ u64_stats_update_begin(&lp->rx_stat_sync); ++ u64_stats_add(&lp->rx_packets, packets); ++ u64_stats_add(&lp->rx_bytes, size); ++ u64_stats_update_end(&lp->rx_stat_sync); + + if (tail_p) + axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p); +@@ -1292,10 +1296,32 @@ static int axienet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) + return phylink_mii_ioctl(lp->phylink, rq, cmd); + } + ++static void ++axienet_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) ++{ ++ struct axienet_local *lp = netdev_priv(dev); ++ unsigned int start; ++ ++ netdev_stats_to_stats64(stats, &dev->stats); ++ ++ do { ++ start = u64_stats_fetch_begin_irq(&lp->rx_stat_sync); ++ stats->rx_packets = u64_stats_read(&lp->rx_packets); ++ stats->rx_bytes = u64_stats_read(&lp->rx_bytes); ++ } while (u64_stats_fetch_retry_irq(&lp->rx_stat_sync, start)); ++ ++ do { ++ start = u64_stats_fetch_begin_irq(&lp->tx_stat_sync); ++ stats->tx_packets = u64_stats_read(&lp->tx_packets); ++ stats->tx_bytes = u64_stats_read(&lp->tx_bytes); ++ } while (u64_stats_fetch_retry_irq(&lp->tx_stat_sync, start)); ++} ++ + static const struct net_device_ops axienet_netdev_ops = { + .ndo_open = axienet_open, + .ndo_stop = axienet_stop, + .ndo_start_xmit = axienet_start_xmit, ++ .ndo_get_stats64 = axienet_get_stats64, + .ndo_change_mtu = axienet_change_mtu, + .ndo_set_mac_address = netdev_set_mac_address, + .ndo_validate_addr = eth_validate_addr, +@@ -1850,6 +1876,9 @@ static int axienet_probe(struct platform_device *pdev) + lp->rx_bd_num = RX_BD_NUM_DEFAULT; + lp->tx_bd_num = TX_BD_NUM_DEFAULT; + ++ u64_stats_init(&lp->rx_stat_sync); ++ u64_stats_init(&lp->tx_stat_sync); ++ + netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll, NAPI_POLL_WEIGHT); + netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll, NAPI_POLL_WEIGHT); + +-- +2.35.1 + diff --git a/queue-5.19/net-broadcom-fix-return-type-for-implementation-of.patch b/queue-5.19/net-broadcom-fix-return-type-for-implementation-of.patch new file mode 100644 index 00000000000..9938d853b57 --- /dev/null +++ b/queue-5.19/net-broadcom-fix-return-type-for-implementation-of.patch @@ -0,0 +1,41 @@ +From 93afc1e877b88f4630e47edd04b4d2e7978b05e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 15:54:07 +0800 +Subject: net: broadcom: Fix return type for implementation of + +From: GUO Zihua + +[ Upstream commit 12f7bd252221d4f9e000e20530e50129241e3a67 ] + +Since Linux now supports CFI, it will be a good idea to fix mismatched +return type for implementation of hooks. Otherwise this might get +cought out by CFI and cause a panic. + +bcm4908_enet_start_xmit() would return either NETDEV_TX_BUSY or +NETDEV_TX_OK, so change the return type to netdev_tx_t directly. + +Signed-off-by: GUO Zihua +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20220902075407.52358-1-guozihua@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bcm4908_enet.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c +index c131d8118489..e5e17a182f9d 100644 +--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c ++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c +@@ -507,7 +507,7 @@ static int bcm4908_enet_stop(struct net_device *netdev) + return 0; + } + +-static int bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netdev) ++static netdev_tx_t bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netdev) + { + struct bcm4908_enet *enet = netdev_priv(netdev); + struct bcm4908_enet_dma_ring *ring = &enet->tx_ring; +-- +2.35.1 + diff --git a/queue-5.19/net-davicom-fix-return-type-of-dm9000_start_xmit.patch b/queue-5.19/net-davicom-fix-return-type-of-dm9000_start_xmit.patch new file mode 100644 index 00000000000..3328e6dc949 --- /dev/null +++ b/queue-5.19/net-davicom-fix-return-type-of-dm9000_start_xmit.patch @@ -0,0 +1,46 @@ +From 8064409f20f54def0b2345f3c8f4ac5857afe4a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 12:47:19 -0700 +Subject: net: davicom: Fix return type of dm9000_start_xmit + +From: Nathan Huckleberry + +[ Upstream commit 0191580b000d50089a0b351f7cdbec4866e3d0d2 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of dm9000_start_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Reviewed-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20220912194722.809525-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/davicom/dm9000.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c +index 0985ab216566..186a5e0a7862 100644 +--- a/drivers/net/ethernet/davicom/dm9000.c ++++ b/drivers/net/ethernet/davicom/dm9000.c +@@ -1012,7 +1012,7 @@ static void dm9000_send_packet(struct net_device *dev, + * Hardware start transmission. + * Send a packet to media from the upper layer. + */ +-static int ++static netdev_tx_t + dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + unsigned long flags; +-- +2.35.1 + diff --git a/queue-5.19/net-ethernet-litex-fix-return-type-of-liteeth_start_.patch b/queue-5.19/net-ethernet-litex-fix-return-type-of-liteeth_start_.patch new file mode 100644 index 00000000000..3f2195c6e2b --- /dev/null +++ b/queue-5.19/net-ethernet-litex-fix-return-type-of-liteeth_start_.patch @@ -0,0 +1,48 @@ +From 44ff5a66271ba06f2e8d5988d285fa592f6a5c2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 12:53:07 -0700 +Subject: net: ethernet: litex: Fix return type of liteeth_start_xmit + +From: Nathan Huckleberry + +[ Upstream commit 40662333dd7c64664247a6138bc33f3974e3a331 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of liteeth_start_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Reviewed-by: Nathan Chancellor +Acked-by: Gabriel Somlo +Link: https://lore.kernel.org/r/20220912195307.812229-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/litex/litex_liteeth.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/litex/litex_liteeth.c b/drivers/net/ethernet/litex/litex_liteeth.c +index fdd99f0de424..35f24e0f0934 100644 +--- a/drivers/net/ethernet/litex/litex_liteeth.c ++++ b/drivers/net/ethernet/litex/litex_liteeth.c +@@ -152,7 +152,8 @@ static int liteeth_stop(struct net_device *netdev) + return 0; + } + +-static int liteeth_start_xmit(struct sk_buff *skb, struct net_device *netdev) ++static netdev_tx_t liteeth_start_xmit(struct sk_buff *skb, ++ struct net_device *netdev) + { + struct liteeth *priv = netdev_priv(netdev); + void __iomem *txbuffer; +-- +2.35.1 + diff --git a/queue-5.19/net-ethernet-ti-davinci_emac-fix-return-type-of-emac.patch b/queue-5.19/net-ethernet-ti-davinci_emac-fix-return-type-of-emac.patch new file mode 100644 index 00000000000..2cd8286deb1 --- /dev/null +++ b/queue-5.19/net-ethernet-ti-davinci_emac-fix-return-type-of-emac.patch @@ -0,0 +1,46 @@ +From 65258e4595585c7e38690b0c4366bec8f5a0d447 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 12:50:19 -0700 +Subject: net: ethernet: ti: davinci_emac: Fix return type of emac_dev_xmit + +From: Nathan Huckleberry + +[ Upstream commit 5972ca946098487c5155fe13654743f9010f5ed5 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of emac_dev_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Reviewed-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20220912195023.810319-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/davinci_emac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c +index 2a3e4e842fa5..e203a5984f03 100644 +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -949,7 +949,7 @@ static void emac_tx_handler(void *token, int len, int status) + * + * Returns success(NETDEV_TX_OK) or error code (typically out of desc's) + */ +-static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) ++static netdev_tx_t emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) + { + struct device *emac_dev = &ndev->dev; + int ret_code; +-- +2.35.1 + diff --git a/queue-5.19/net-ethernet-ti-davinci_mdio-add-workaround-for-erra.patch b/queue-5.19/net-ethernet-ti-davinci_mdio-add-workaround-for-erra.patch new file mode 100644 index 00000000000..99b1409ffff --- /dev/null +++ b/queue-5.19/net-ethernet-ti-davinci_mdio-add-workaround-for-erra.patch @@ -0,0 +1,399 @@ +From d4b5f191f2d41070e0bee9958694ab5486d1f881 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Aug 2022 15:14:06 +0530 +Subject: net: ethernet: ti: davinci_mdio: Add workaround for errata i2329 + +From: Ravi Gunasekaran + +[ Upstream commit d04807b80691c6041ca8e3dcf1870d1bf1082c22 ] + +On the CPSW and ICSS peripherals, there is a possibility that the MDIO +interface returns corrupt data on MDIO reads or writes incorrect data +on MDIO writes. There is also a possibility for the MDIO interface to +become unavailable until the next peripheral reset. + +The workaround is to configure the MDIO in manual mode and disable the +MDIO state machine and emulate the MDIO protocol by reading and writing +appropriate fields in MDIO_MANUAL_IF_REG register of the MDIO controller +to manipulate the MDIO clock and data pins. + +More details about the errata i2329 and the workaround is available in: +https://www.ti.com/lit/er/sprz487a/sprz487a.pdf + +Add implementation to disable MDIO state machine, configure MDIO in manual +mode and achieve MDIO read and writes via MDIO Bitbanging + +Signed-off-by: Ravi Gunasekaran +Reported-by: kernel test robot +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/davinci_mdio.c | 242 +++++++++++++++++++++++-- + 1 file changed, 231 insertions(+), 11 deletions(-) + +diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c +index ea3772618043..946b9753ccfb 100644 +--- a/drivers/net/ethernet/ti/davinci_mdio.c ++++ b/drivers/net/ethernet/ti/davinci_mdio.c +@@ -26,6 +26,8 @@ + #include + #include + #include ++#include ++#include + + /* + * This timeout definition is a worst-case ultra defensive measure against +@@ -41,6 +43,7 @@ + + struct davinci_mdio_of_param { + int autosuspend_delay_ms; ++ bool manual_mode; + }; + + struct davinci_mdio_regs { +@@ -49,6 +52,15 @@ struct davinci_mdio_regs { + #define CONTROL_IDLE BIT(31) + #define CONTROL_ENABLE BIT(30) + #define CONTROL_MAX_DIV (0xffff) ++#define CONTROL_CLKDIV GENMASK(15, 0) ++ ++#define MDIO_MAN_MDCLK_O BIT(2) ++#define MDIO_MAN_OE BIT(1) ++#define MDIO_MAN_PIN BIT(0) ++#define MDIO_MANUALMODE BIT(31) ++ ++#define MDIO_PIN 0 ++ + + u32 alive; + u32 link; +@@ -59,7 +71,9 @@ struct davinci_mdio_regs { + u32 userintmasked; + u32 userintmaskset; + u32 userintmaskclr; +- u32 __reserved_1[20]; ++ u32 manualif; ++ u32 poll; ++ u32 __reserved_1[18]; + + struct { + u32 access; +@@ -79,6 +93,7 @@ static const struct mdio_platform_data default_pdata = { + + struct davinci_mdio_data { + struct mdio_platform_data pdata; ++ struct mdiobb_ctrl bb_ctrl; + struct davinci_mdio_regs __iomem *regs; + struct clk *clk; + struct device *dev; +@@ -90,6 +105,7 @@ struct davinci_mdio_data { + */ + bool skip_scan; + u32 clk_div; ++ bool manual_mode; + }; + + static void davinci_mdio_init_clk(struct davinci_mdio_data *data) +@@ -128,9 +144,122 @@ static void davinci_mdio_enable(struct davinci_mdio_data *data) + writel(data->clk_div | CONTROL_ENABLE, &data->regs->control); + } + +-static int davinci_mdio_reset(struct mii_bus *bus) ++static void davinci_mdio_disable(struct davinci_mdio_data *data) ++{ ++ u32 reg; ++ ++ /* Disable MDIO state machine */ ++ reg = readl(&data->regs->control); ++ ++ reg &= ~CONTROL_CLKDIV; ++ reg |= data->clk_div; ++ ++ reg &= ~CONTROL_ENABLE; ++ writel(reg, &data->regs->control); ++} ++ ++static void davinci_mdio_enable_manual_mode(struct davinci_mdio_data *data) ++{ ++ u32 reg; ++ /* set manual mode */ ++ reg = readl(&data->regs->poll); ++ reg |= MDIO_MANUALMODE; ++ writel(reg, &data->regs->poll); ++} ++ ++static void davinci_set_mdc(struct mdiobb_ctrl *ctrl, int level) ++{ ++ struct davinci_mdio_data *data; ++ u32 reg; ++ ++ data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl); ++ reg = readl(&data->regs->manualif); ++ ++ if (level) ++ reg |= MDIO_MAN_MDCLK_O; ++ else ++ reg &= ~MDIO_MAN_MDCLK_O; ++ ++ writel(reg, &data->regs->manualif); ++} ++ ++static void davinci_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output) ++{ ++ struct davinci_mdio_data *data; ++ u32 reg; ++ ++ data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl); ++ reg = readl(&data->regs->manualif); ++ ++ if (output) ++ reg |= MDIO_MAN_OE; ++ else ++ reg &= ~MDIO_MAN_OE; ++ ++ writel(reg, &data->regs->manualif); ++} ++ ++static void davinci_set_mdio_data(struct mdiobb_ctrl *ctrl, int value) ++{ ++ struct davinci_mdio_data *data; ++ u32 reg; ++ ++ data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl); ++ reg = readl(&data->regs->manualif); ++ ++ if (value) ++ reg |= MDIO_MAN_PIN; ++ else ++ reg &= ~MDIO_MAN_PIN; ++ ++ writel(reg, &data->regs->manualif); ++} ++ ++static int davinci_get_mdio_data(struct mdiobb_ctrl *ctrl) ++{ ++ struct davinci_mdio_data *data; ++ unsigned long reg; ++ ++ data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl); ++ reg = readl(&data->regs->manualif); ++ return test_bit(MDIO_PIN, ®); ++} ++ ++static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg) ++{ ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(bus->parent); ++ if (ret < 0) ++ return ret; ++ ++ ret = mdiobb_read(bus, phy, reg); ++ ++ pm_runtime_mark_last_busy(bus->parent); ++ pm_runtime_put_autosuspend(bus->parent); ++ ++ return ret; ++} ++ ++static int davinci_mdiobb_write(struct mii_bus *bus, int phy, int reg, ++ u16 val) ++{ ++ int ret; ++ ++ ret = pm_runtime_resume_and_get(bus->parent); ++ if (ret < 0) ++ return ret; ++ ++ ret = mdiobb_write(bus, phy, reg, val); ++ ++ pm_runtime_mark_last_busy(bus->parent); ++ pm_runtime_put_autosuspend(bus->parent); ++ ++ return ret; ++} ++ ++static int davinci_mdio_common_reset(struct davinci_mdio_data *data) + { +- struct davinci_mdio_data *data = bus->priv; + u32 phy_mask, ver; + int ret; + +@@ -138,6 +267,11 @@ static int davinci_mdio_reset(struct mii_bus *bus) + if (ret < 0) + return ret; + ++ if (data->manual_mode) { ++ davinci_mdio_disable(data); ++ davinci_mdio_enable_manual_mode(data); ++ } ++ + /* wait for scan logic to settle */ + msleep(PHY_MAX_ADDR * data->access_time); + +@@ -171,6 +305,23 @@ static int davinci_mdio_reset(struct mii_bus *bus) + return 0; + } + ++static int davinci_mdio_reset(struct mii_bus *bus) ++{ ++ struct davinci_mdio_data *data = bus->priv; ++ ++ return davinci_mdio_common_reset(data); ++} ++ ++static int davinci_mdiobb_reset(struct mii_bus *bus) ++{ ++ struct mdiobb_ctrl *ctrl = bus->priv; ++ struct davinci_mdio_data *data; ++ ++ data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl); ++ ++ return davinci_mdio_common_reset(data); ++} ++ + /* wait until hardware is ready for another user access */ + static inline int wait_for_user_access(struct davinci_mdio_data *data) + { +@@ -318,6 +469,28 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data, + return 0; + } + ++struct k3_mdio_soc_data { ++ bool manual_mode; ++}; ++ ++static const struct k3_mdio_soc_data am65_mdio_soc_data = { ++ .manual_mode = true, ++}; ++ ++static const struct soc_device_attribute k3_mdio_socinfo[] = { ++ { .family = "AM62X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, ++ { .family = "AM64X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, ++ { .family = "AM64X", .revision = "SR2.0", .data = &am65_mdio_soc_data }, ++ { .family = "AM65X", .revision = "SR1.0", .data = &am65_mdio_soc_data }, ++ { .family = "AM65X", .revision = "SR2.0", .data = &am65_mdio_soc_data }, ++ { .family = "J7200", .revision = "SR1.0", .data = &am65_mdio_soc_data }, ++ { .family = "J7200", .revision = "SR2.0", .data = &am65_mdio_soc_data }, ++ { .family = "J721E", .revision = "SR1.0", .data = &am65_mdio_soc_data }, ++ { .family = "J721E", .revision = "SR2.0", .data = &am65_mdio_soc_data }, ++ { .family = "J721S2", .revision = "SR1.0", .data = &am65_mdio_soc_data}, ++ { /* sentinel */ }, ++}; ++ + #if IS_ENABLED(CONFIG_OF) + static const struct davinci_mdio_of_param of_cpsw_mdio_data = { + .autosuspend_delay_ms = 100, +@@ -331,6 +504,14 @@ static const struct of_device_id davinci_mdio_of_mtable[] = { + MODULE_DEVICE_TABLE(of, davinci_mdio_of_mtable); + #endif + ++static const struct mdiobb_ops davinci_mdiobb_ops = { ++ .owner = THIS_MODULE, ++ .set_mdc = davinci_set_mdc, ++ .set_mdio_dir = davinci_set_mdio_dir, ++ .set_mdio_data = davinci_set_mdio_data, ++ .get_mdio_data = davinci_get_mdio_data, ++}; ++ + static int davinci_mdio_probe(struct platform_device *pdev) + { + struct mdio_platform_data *pdata = dev_get_platdata(&pdev->dev); +@@ -345,7 +526,26 @@ static int davinci_mdio_probe(struct platform_device *pdev) + if (!data) + return -ENOMEM; + +- data->bus = devm_mdiobus_alloc(dev); ++ data->manual_mode = false; ++ data->bb_ctrl.ops = &davinci_mdiobb_ops; ++ ++ if (IS_ENABLED(CONFIG_OF) && dev->of_node) { ++ const struct soc_device_attribute *soc_match_data; ++ ++ soc_match_data = soc_device_match(k3_mdio_socinfo); ++ if (soc_match_data && soc_match_data->data) { ++ const struct k3_mdio_soc_data *socdata = ++ soc_match_data->data; ++ ++ data->manual_mode = socdata->manual_mode; ++ } ++ } ++ ++ if (data->manual_mode) ++ data->bus = alloc_mdio_bitbang(&data->bb_ctrl); ++ else ++ data->bus = devm_mdiobus_alloc(dev); ++ + if (!data->bus) { + dev_err(dev, "failed to alloc mii bus\n"); + return -ENOMEM; +@@ -371,11 +571,20 @@ static int davinci_mdio_probe(struct platform_device *pdev) + } + + data->bus->name = dev_name(dev); +- data->bus->read = davinci_mdio_read; +- data->bus->write = davinci_mdio_write; +- data->bus->reset = davinci_mdio_reset; ++ ++ if (data->manual_mode) { ++ data->bus->read = davinci_mdiobb_read; ++ data->bus->write = davinci_mdiobb_write; ++ data->bus->reset = davinci_mdiobb_reset; ++ ++ dev_info(dev, "Configuring MDIO in manual mode\n"); ++ } else { ++ data->bus->read = davinci_mdio_read; ++ data->bus->write = davinci_mdio_write; ++ data->bus->reset = davinci_mdio_reset; ++ data->bus->priv = data; ++ } + data->bus->parent = dev; +- data->bus->priv = data; + + data->clk = devm_clk_get(dev, "fck"); + if (IS_ERR(data->clk)) { +@@ -433,9 +642,13 @@ static int davinci_mdio_remove(struct platform_device *pdev) + { + struct davinci_mdio_data *data = platform_get_drvdata(pdev); + +- if (data->bus) ++ if (data->bus) { + mdiobus_unregister(data->bus); + ++ if (data->manual_mode) ++ free_mdio_bitbang(data->bus); ++ } ++ + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); + +@@ -452,7 +665,9 @@ static int davinci_mdio_runtime_suspend(struct device *dev) + ctrl = readl(&data->regs->control); + ctrl &= ~CONTROL_ENABLE; + writel(ctrl, &data->regs->control); +- wait_for_idle(data); ++ ++ if (!data->manual_mode) ++ wait_for_idle(data); + + return 0; + } +@@ -461,7 +676,12 @@ static int davinci_mdio_runtime_resume(struct device *dev) + { + struct davinci_mdio_data *data = dev_get_drvdata(dev); + +- davinci_mdio_enable(data); ++ if (data->manual_mode) { ++ davinci_mdio_disable(data); ++ davinci_mdio_enable_manual_mode(data); ++ } else { ++ davinci_mdio_enable(data); ++ } + return 0; + } + #endif +-- +2.35.1 + diff --git a/queue-5.19/net-fs_enet-fix-wrong-check-in-do_pd_setup.patch b/queue-5.19/net-fs_enet-fix-wrong-check-in-do_pd_setup.patch new file mode 100644 index 00000000000..9cd09ea2986 --- /dev/null +++ b/queue-5.19/net-fs_enet-fix-wrong-check-in-do_pd_setup.patch @@ -0,0 +1,36 @@ +From 36f3f7b49484726ee037cc27b9f68b08957cdda0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 13:55:13 +0000 +Subject: net: fs_enet: Fix wrong check in do_pd_setup + +From: Zheng Yongjun + +[ Upstream commit ec3f06b542a960806a81345042e4eee3f8c5dec4 ] + +Should check of_iomap return value 'fep->fec.fecp' instead of 'fep->fcc.fccp' + +Fixes: 976de6a8c304 ("fs_enet: Be an of_platform device when CONFIG_PPC_CPM_NEW_BINDING is set.") +Signed-off-by: Zheng Yongjun +Reviewed-by: Christophe Leroy +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fs_enet/mac-fec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +index 99fe2c210d0f..61f4b6e50d29 100644 +--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c ++++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c +@@ -98,7 +98,7 @@ static int do_pd_setup(struct fs_enet_private *fep) + return -EINVAL; + + fep->fec.fecp = of_iomap(ofdev->dev.of_node, 0); +- if (!fep->fcc.fccp) ++ if (!fep->fec.fecp) + return -EINVAL; + + return 0; +-- +2.35.1 + diff --git a/queue-5.19/net-ftmac100-fix-endianness-related-issues-from-spar.patch b/queue-5.19/net-ftmac100-fix-endianness-related-issues-from-spar.patch new file mode 100644 index 00000000000..cf1b4a2aa04 --- /dev/null +++ b/queue-5.19/net-ftmac100-fix-endianness-related-issues-from-spar.patch @@ -0,0 +1,67 @@ +From fd780c91840165db69c765de4c5f67105a89d460 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 14:37:49 +0300 +Subject: net: ftmac100: fix endianness-related issues from 'sparse' + +From: Sergei Antonov + +[ Upstream commit 9df696b3b3a4c96c3219eb87c7bf03fb50e490b8 ] + +Sparse found a number of endianness-related issues of these kinds: + +.../ftmac100.c:192:32: warning: restricted __le32 degrades to integer + +.../ftmac100.c:208:23: warning: incorrect type in assignment (different base types) +.../ftmac100.c:208:23: expected unsigned int rxdes0 +.../ftmac100.c:208:23: got restricted __le32 [usertype] + +.../ftmac100.c:249:23: warning: invalid assignment: &= +.../ftmac100.c:249:23: left side has type unsigned int +.../ftmac100.c:249:23: right side has type restricted __le32 + +.../ftmac100.c:527:16: warning: cast to restricted __le32 + +Change type of some fields from 'unsigned int' to '__le32' to fix it. + +Signed-off-by: Sergei Antonov +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20220902113749.1408562-1-saproj@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/faraday/ftmac100.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/faraday/ftmac100.h b/drivers/net/ethernet/faraday/ftmac100.h +index fe986f1673fc..8af32f9070f4 100644 +--- a/drivers/net/ethernet/faraday/ftmac100.h ++++ b/drivers/net/ethernet/faraday/ftmac100.h +@@ -122,9 +122,9 @@ + * Transmit descriptor, aligned to 16 bytes + */ + struct ftmac100_txdes { +- unsigned int txdes0; +- unsigned int txdes1; +- unsigned int txdes2; /* TXBUF_BADR */ ++ __le32 txdes0; ++ __le32 txdes1; ++ __le32 txdes2; /* TXBUF_BADR */ + unsigned int txdes3; /* not used by HW */ + } __attribute__ ((aligned(16))); + +@@ -143,9 +143,9 @@ struct ftmac100_txdes { + * Receive descriptor, aligned to 16 bytes + */ + struct ftmac100_rxdes { +- unsigned int rxdes0; +- unsigned int rxdes1; +- unsigned int rxdes2; /* RXBUF_BADR */ ++ __le32 rxdes0; ++ __le32 rxdes1; ++ __le32 rxdes2; /* RXBUF_BADR */ + unsigned int rxdes3; /* not used by HW */ + } __attribute__ ((aligned(16))); + +-- +2.35.1 + diff --git a/queue-5.19/net-ieee802154-reject-zero-sized-raw_sendmsg.patch b/queue-5.19/net-ieee802154-reject-zero-sized-raw_sendmsg.patch new file mode 100644 index 00000000000..0aff11b3249 --- /dev/null +++ b/queue-5.19/net-ieee802154-reject-zero-sized-raw_sendmsg.patch @@ -0,0 +1,40 @@ +From 5a08e21648bfb90647669e53b99b82bb4f9fd738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Oct 2022 01:43:44 +0900 +Subject: net/ieee802154: reject zero-sized raw_sendmsg() + +From: Tetsuo Handa + +[ Upstream commit 3a4d061c699bd3eedc80dc97a4b2a2e1af83c6f5 ] + +syzbot is hitting skb_assert_len() warning at raw_sendmsg() for ieee802154 +socket. What commit dc633700f00f726e ("net/af_packet: check len when +min_header_len equals to 0") does also applies to ieee802154 socket. + +Link: https://syzkaller.appspot.com/bug?extid=5ea725c25d06fb9114c4 +Reported-by: syzbot +Fixes: fd1894224407c484 ("bpf: Don't redirect packets with invalid pkt_len") +Signed-off-by: Tetsuo Handa +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ieee802154/socket.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c +index 7889e1ef7fad..cbd0e2ac4ffe 100644 +--- a/net/ieee802154/socket.c ++++ b/net/ieee802154/socket.c +@@ -251,6 +251,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + return -EOPNOTSUPP; + } + ++ if (!size) ++ return -EINVAL; ++ + lock_sock(sk); + if (!sk->sk_bound_dev_if) + dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); +-- +2.35.1 + diff --git a/queue-5.19/net-if-sock-is-dead-don-t-access-sock-s-sk_wq-in-sk_.patch b/queue-5.19/net-if-sock-is-dead-don-t-access-sock-s-sk_wq-in-sk_.patch new file mode 100644 index 00000000000..ed284eca051 --- /dev/null +++ b/queue-5.19/net-if-sock-is-dead-don-t-access-sock-s-sk_wq-in-sk_.patch @@ -0,0 +1,107 @@ +From 9891429cb130b110523f47c8fffbd206e0cf5884 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Aug 2022 21:37:54 +0800 +Subject: net: If sock is dead don't access sock's sk_wq in + sk_stream_wait_memory + +From: Liu Jian + +[ Upstream commit 3f8ef65af927db247418d4e1db49164d7a158fc5 ] + +Fixes the below NULL pointer dereference: + + [...] + [ 14.471200] Call Trace: + [ 14.471562] + [ 14.471882] lock_acquire+0x245/0x2e0 + [ 14.472416] ? remove_wait_queue+0x12/0x50 + [ 14.473014] ? _raw_spin_lock_irqsave+0x17/0x50 + [ 14.473681] _raw_spin_lock_irqsave+0x3d/0x50 + [ 14.474318] ? remove_wait_queue+0x12/0x50 + [ 14.474907] remove_wait_queue+0x12/0x50 + [ 14.475480] sk_stream_wait_memory+0x20d/0x340 + [ 14.476127] ? do_wait_intr_irq+0x80/0x80 + [ 14.476704] do_tcp_sendpages+0x287/0x600 + [ 14.477283] tcp_bpf_push+0xab/0x260 + [ 14.477817] tcp_bpf_sendmsg_redir+0x297/0x500 + [ 14.478461] ? __local_bh_enable_ip+0x77/0xe0 + [ 14.479096] tcp_bpf_send_verdict+0x105/0x470 + [ 14.479729] tcp_bpf_sendmsg+0x318/0x4f0 + [ 14.480311] sock_sendmsg+0x2d/0x40 + [ 14.480822] ____sys_sendmsg+0x1b4/0x1c0 + [ 14.481390] ? copy_msghdr_from_user+0x62/0x80 + [ 14.482048] ___sys_sendmsg+0x78/0xb0 + [ 14.482580] ? vmf_insert_pfn_prot+0x91/0x150 + [ 14.483215] ? __do_fault+0x2a/0x1a0 + [ 14.483738] ? do_fault+0x15e/0x5d0 + [ 14.484246] ? __handle_mm_fault+0x56b/0x1040 + [ 14.484874] ? lock_is_held_type+0xdf/0x130 + [ 14.485474] ? find_held_lock+0x2d/0x90 + [ 14.486046] ? __sys_sendmsg+0x41/0x70 + [ 14.486587] __sys_sendmsg+0x41/0x70 + [ 14.487105] ? intel_pmu_drain_pebs_core+0x350/0x350 + [ 14.487822] do_syscall_64+0x34/0x80 + [ 14.488345] entry_SYSCALL_64_after_hwframe+0x63/0xcd + [...] + +The test scenario has the following flow: + +thread1 thread2 +----------- --------------- + tcp_bpf_sendmsg + tcp_bpf_send_verdict + tcp_bpf_sendmsg_redir sock_close + tcp_bpf_push_locked __sock_release + tcp_bpf_push //inet_release + do_tcp_sendpages sock->ops->release + sk_stream_wait_memory // tcp_close + sk_wait_event sk->sk_prot->close + release_sock(__sk); + *** + lock_sock(sk); + __tcp_close + sock_orphan(sk) + sk->sk_wq = NULL + release_sock + **** + lock_sock(__sk); + remove_wait_queue(sk_sleep(sk), &wait); + sk_sleep(sk) + //NULL pointer dereference + &rcu_dereference_raw(sk->sk_wq)->wait + +While waiting for memory in thread1, the socket is released with its wait +queue because thread2 has closed it. This caused by tcp_bpf_send_verdict +didn't increase the f_count of psock->sk_redir->sk_socket->file in thread1. + +We should check if SOCK_DEAD flag is set on wakeup in sk_stream_wait_memory +before accessing the wait queue. + +Suggested-by: Jakub Sitnicki +Signed-off-by: Liu Jian +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Cc: Eric Dumazet +Link: https://lore.kernel.org/bpf/20220823133755.314697-2-liujian56@huawei.com +Signed-off-by: Sasha Levin +--- + net/core/stream.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/core/stream.c b/net/core/stream.c +index 06b36c730ce8..2ee82115b919 100644 +--- a/net/core/stream.c ++++ b/net/core/stream.c +@@ -159,7 +159,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) + *timeo_p = current_timeo; + } + out: +- remove_wait_queue(sk_sleep(sk), &wait); ++ if (!sock_flag(sk, SOCK_DEAD)) ++ remove_wait_queue(sk_sleep(sk), &wait); + return err; + + do_error: +-- +2.35.1 + diff --git a/queue-5.19/net-korina-fix-return-type-of-korina_send_packet.patch b/queue-5.19/net-korina-fix-return-type-of-korina_send_packet.patch new file mode 100644 index 00000000000..f94a9190f97 --- /dev/null +++ b/queue-5.19/net-korina-fix-return-type-of-korina_send_packet.patch @@ -0,0 +1,47 @@ +From 2f39d2299a1e11c7766ac6f8519cf10e6e502236 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 14:43:40 -0700 +Subject: net: korina: Fix return type of korina_send_packet + +From: Nathan Huckleberry + +[ Upstream commit 106c67ce46f3c82dd276e983668a91d6ed631173 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of korina_send_packet should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Reviewed-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20220912214344.928925-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/korina.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c +index df9a8eefa007..eec6a9ec528b 100644 +--- a/drivers/net/ethernet/korina.c ++++ b/drivers/net/ethernet/korina.c +@@ -416,7 +416,8 @@ static void korina_abort_rx(struct net_device *dev) + } + + /* transmit packet */ +-static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t korina_send_packet(struct sk_buff *skb, ++ struct net_device *dev) + { + struct korina_private *lp = netdev_priv(dev); + u32 chain_prev, chain_next; +-- +2.35.1 + diff --git a/queue-5.19/net-lan966x-fix-return-type-of-lan966x_port_xmit.patch b/queue-5.19/net-lan966x-fix-return-type-of-lan966x_port_xmit.patch new file mode 100644 index 00000000000..8ccbb7d4287 --- /dev/null +++ b/queue-5.19/net-lan966x-fix-return-type-of-lan966x_port_xmit.patch @@ -0,0 +1,47 @@ +From 0b5505f5d6537071494291ede2c9fffc2d80392f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 11:27:03 -0700 +Subject: net: lan966x: Fix return type of lan966x_port_xmit + +From: Nathan Huckleberry + +[ Upstream commit 450a580fc4b5e7f7fb8d9b1a0208bf0d1efc53a8 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of lan966x_port_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Reviewed-by: Nathan Chancellor +Link: https://lore.kernel.org/r/20220929182704.64438-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +index d928b75f3780..be40c6d3ec68 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +@@ -344,7 +344,8 @@ static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp) + IFH_POS_TIMESTAMP, IFH_LEN * 4, PACK, 0); + } + +-static int lan966x_port_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb, ++ struct net_device *dev) + { + struct lan966x_port *port = netdev_priv(dev); + struct lan966x *lan966x = port->lan966x; +-- +2.35.1 + diff --git a/queue-5.19/net-lantiq_etop-fix-return-type-for-implementation-o.patch b/queue-5.19/net-lantiq_etop-fix-return-type-for-implementation-o.patch new file mode 100644 index 00000000000..b8e1bb73913 --- /dev/null +++ b/queue-5.19/net-lantiq_etop-fix-return-type-for-implementation-o.patch @@ -0,0 +1,41 @@ +From 75ba2142b00260e8491750b6738e06570e450ed5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 16:15:21 +0800 +Subject: net: lantiq_etop: Fix return type for implementation of + ndo_start_xmit + +From: GUO Zihua + +[ Upstream commit c8ef3c94bda0e21123202d057d4a299698fa0ed9 ] + +Since Linux now supports CFI, it will be a good idea to fix mismatched +return type for implementation of hooks. Otherwise this might get +cought out by CFI and cause a panic. + +ltq_etop_tx() would return either NETDEV_TX_BUSY or NETDEV_TX_OK, so +change the return type to netdev_tx_t directly. + +Signed-off-by: GUO Zihua +Link: https://lore.kernel.org/r/20220902081521.59867-1-guozihua@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/lantiq_etop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c +index 7cedbe1fdfd7..59aab4086dcc 100644 +--- a/drivers/net/ethernet/lantiq_etop.c ++++ b/drivers/net/ethernet/lantiq_etop.c +@@ -470,7 +470,7 @@ ltq_etop_stop(struct net_device *dev) + return 0; + } + +-static int ++static netdev_tx_t + ltq_etop_tx(struct sk_buff *skb, struct net_device *dev) + { + int queue = skb_get_queue_mapping(skb); +-- +2.35.1 + diff --git a/queue-5.19/net-mvpp2-fix-mvpp2-debugfs-leak.patch b/queue-5.19/net-mvpp2-fix-mvpp2-debugfs-leak.patch new file mode 100644 index 00000000000..06c7330c18e --- /dev/null +++ b/queue-5.19/net-mvpp2-fix-mvpp2-debugfs-leak.patch @@ -0,0 +1,108 @@ +From 53315293125809d274649291a9d75d41c7d2af0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Oct 2022 17:19:27 +0100 +Subject: net: mvpp2: fix mvpp2 debugfs leak + +From: Russell King (Oracle) + +[ Upstream commit 0152dfee235e87660f52a117fc9f70dc55956bb4 ] + +When mvpp2 is unloaded, the driver specific debugfs directory is not +removed, which technically leads to a memory leak. However, this +directory is only created when the first device is probed, so the +hardware is present. Removing the module is only something a developer +would to when e.g. testing out changes, so the module would be +reloaded. So this memory leak is minor. + +The original attempt in commit fe2c9c61f668 ("net: mvpp2: debugfs: fix +memory leak when using debugfs_lookup()") that was labelled as a memory +leak fix was not, it fixed a refcount leak, but in doing so created a +problem when the module is reloaded - the directory already exists, but +mvpp2_root is NULL, so we lose all debugfs entries. This fix has been +reverted. + +This is the alternative fix, where we remove the offending directory +whenever the driver is unloaded. + +Fixes: 21da57a23125 ("net: mvpp2: add a debugfs interface for the Header Parser") +Signed-off-by: Russell King (Oracle) +Reviewed-by: Greg Kroah-Hartman +Reviewed-by: Marcin Wojtas +Link: https://lore.kernel.org/r/E1ofOAB-00CzkG-UO@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 1 + + drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c | 10 ++++++++-- + drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 13 ++++++++++++- + 3 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +index ad73a488fc5f..11e603686a27 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +@@ -1530,6 +1530,7 @@ u32 mvpp2_read(struct mvpp2 *priv, u32 offset); + void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name); + + void mvpp2_dbgfs_cleanup(struct mvpp2 *priv); ++void mvpp2_dbgfs_exit(void); + + void mvpp23_rx_fifo_fc_en(struct mvpp2 *priv, int port, bool en); + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c +index 4a3baa7e0142..75e83ea2a926 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c +@@ -691,6 +691,13 @@ static int mvpp2_dbgfs_port_init(struct dentry *parent, + return 0; + } + ++static struct dentry *mvpp2_root; ++ ++void mvpp2_dbgfs_exit(void) ++{ ++ debugfs_remove(mvpp2_root); ++} ++ + void mvpp2_dbgfs_cleanup(struct mvpp2 *priv) + { + debugfs_remove_recursive(priv->dbgfs_dir); +@@ -700,10 +707,9 @@ void mvpp2_dbgfs_cleanup(struct mvpp2 *priv) + + void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name) + { +- struct dentry *mvpp2_dir, *mvpp2_root; ++ struct dentry *mvpp2_dir; + int ret, i; + +- mvpp2_root = debugfs_lookup(MVPP2_DRIVER_NAME, NULL); + if (!mvpp2_root) + mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL); + +diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +index b84128b549b4..eaa51cd7456b 100644 +--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c ++++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +@@ -7706,7 +7706,18 @@ static struct platform_driver mvpp2_driver = { + }, + }; + +-module_platform_driver(mvpp2_driver); ++static int __init mvpp2_driver_init(void) ++{ ++ return platform_driver_register(&mvpp2_driver); ++} ++module_init(mvpp2_driver_init); ++ ++static void __exit mvpp2_driver_exit(void) ++{ ++ platform_driver_unregister(&mvpp2_driver); ++ mvpp2_dbgfs_exit(); ++} ++module_exit(mvpp2_driver_exit); + + MODULE_DESCRIPTION("Marvell PPv2 Ethernet Driver - www.marvell.com"); + MODULE_AUTHOR("Marcin Wojtas "); +-- +2.35.1 + diff --git a/queue-5.19/net-next-fix-ip_unicast_if-option-behavior-for-conne.patch b/queue-5.19/net-next-fix-ip_unicast_if-option-behavior-for-conne.patch new file mode 100644 index 00000000000..c092a577029 --- /dev/null +++ b/queue-5.19/net-next-fix-ip_unicast_if-option-behavior-for-conne.patch @@ -0,0 +1,221 @@ +From 00236b561113d7370fbbaae97a773290ffe40409 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 13:18:51 +0200 +Subject: net-next: Fix IP_UNICAST_IF option behavior for connected sockets + +From: Richard Gobert + +[ Upstream commit 0e4d354762cefd3e16b4cff8988ff276e45effc4 ] + +The IP_UNICAST_IF socket option is used to set the outgoing interface +for outbound packets. + +The IP_UNICAST_IF socket option was added as it was needed by the +Wine project, since no other existing option (SO_BINDTODEVICE socket +option, IP_PKTINFO socket option or the bind function) provided the +needed characteristics needed by the IP_UNICAST_IF socket option. [1] +The IP_UNICAST_IF socket option works well for unconnected sockets, +that is, the interface specified by the IP_UNICAST_IF socket option +is taken into consideration in the route lookup process when a packet +is being sent. However, for connected sockets, the outbound interface +is chosen when connecting the socket, and in the route lookup process +which is done when a packet is being sent, the interface specified by +the IP_UNICAST_IF socket option is being ignored. + +This inconsistent behavior was reported and discussed in an issue +opened on systemd's GitHub project [2]. Also, a bug report was +submitted in the kernel's bugzilla [3]. + +To understand the problem in more detail, we can look at what happens +for UDP packets over IPv4 (The same analysis was done separately in +the referenced systemd issue). +When a UDP packet is sent the udp_sendmsg function gets called and +the following happens: + +1. The oif member of the struct ipcm_cookie ipc (which stores the +output interface of the packet) is initialized by the ipcm_init_sk +function to inet->sk.sk_bound_dev_if (the device set by the +SO_BINDTODEVICE socket option). + +2. If the IP_PKTINFO socket option was set, the oif member gets +overridden by the call to the ip_cmsg_send function. + +3. If no output interface was selected yet, the interface specified +by the IP_UNICAST_IF socket option is used. + +4. If the socket is connected and no destination address is +specified in the send function, the struct ipcm_cookie ipc is not +taken into consideration and the cached route, that was calculated in +the connect function is being used. + +Thus, for a connected socket, the IP_UNICAST_IF sockopt isn't taken +into consideration. + +This patch corrects the behavior of the IP_UNICAST_IF socket option +for connect()ed sockets by taking into consideration the +IP_UNICAST_IF sockopt when connecting the socket. + +In order to avoid reconnecting the socket, this option is still +ignored when applied on an already connected socket until connect() +is called again by the Richard Gobert. + +Change the __ip4_datagram_connect function, which is called during +socket connection, to take into consideration the interface set by +the IP_UNICAST_IF socket option, in a similar way to what is done in +the udp_sendmsg function. + +[1] https://lore.kernel.org/netdev/1328685717.4736.4.camel@edumazet-laptop/T/ +[2] https://github.com/systemd/systemd/issues/11935#issuecomment-618691018 +[3] https://bugzilla.kernel.org/show_bug.cgi?id=210255 + +Signed-off-by: Richard Gobert +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20220829111554.GA1771@debian +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/datagram.c | 2 ++ + tools/testing/selftests/net/fcnal-test.sh | 30 +++++++++++++++++++++++ + tools/testing/selftests/net/nettest.c | 16 ++++++++++-- + 3 files changed, 46 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index ffd57523331f..405a8c2aea64 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -42,6 +42,8 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len + oif = inet->mc_index; + if (!saddr) + saddr = inet->mc_addr; ++ } else if (!oif) { ++ oif = inet->uc_index; + } + fl4 = &inet->cork.fl.u.ip4; + rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, oif, +diff --git a/tools/testing/selftests/net/fcnal-test.sh b/tools/testing/selftests/net/fcnal-test.sh +index 03b586760164..31c3b6ebd388 100755 +--- a/tools/testing/selftests/net/fcnal-test.sh ++++ b/tools/testing/selftests/net/fcnal-test.sh +@@ -1466,6 +1466,13 @@ ipv4_udp_novrf() + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP} + log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF" + ++ log_start ++ run_cmd_nsb nettest -D -s & ++ sleep 1 ++ run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP} -U ++ log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF, with connect()" ++ ++ + log_start + show_hint "Should fail 'Connection refused'" + run_cmd nettest -D -r ${a} +@@ -1525,6 +1532,13 @@ ipv4_udp_novrf() + run_cmd nettest -D -d ${NSA_DEV} -S -r ${a} + log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection" + ++ log_start ++ run_cmd nettest -s -D & ++ sleep 1 ++ run_cmd nettest -D -d ${NSA_DEV} -S -r ${a} -U ++ log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection, with connect()" ++ ++ + # IPv4 with device bind has really weird behavior - it overrides the + # fib lookup, generates an rtable and tries to send the packet. This + # causes failures for local traffic at different places +@@ -1550,6 +1564,15 @@ ipv4_udp_novrf() + sleep 1 + run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S + log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection" ++ ++ log_start ++ show_hint "Should fail since addresses on loopback are out of device scope" ++ run_cmd nettest -D -s & ++ sleep 1 ++ run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -U ++ log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection, with connect()" ++ ++ + done + + a=${NSA_IP} +@@ -3157,6 +3180,13 @@ ipv6_udp_novrf() + sleep 1 + run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S + log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection" ++ ++ log_start ++ show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope" ++ run_cmd nettest -6 -D -s & ++ sleep 1 ++ run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S -U ++ log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection, with connect()" + done + + a=${NSA_IP6} +diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c +index d9a6fd2cd9d3..7900fa98eccb 100644 +--- a/tools/testing/selftests/net/nettest.c ++++ b/tools/testing/selftests/net/nettest.c +@@ -127,6 +127,9 @@ struct sock_args { + + /* ESP in UDP encap test */ + int use_xfrm; ++ ++ /* use send() and connect() instead of sendto */ ++ int datagram_connect; + }; + + static int server_mode; +@@ -979,6 +982,11 @@ static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args) + log_err_errno("write failed sending msg to peer"); + return 1; + } ++ } else if (args->datagram_connect) { ++ if (send(sd, msg, msglen, 0) < 0) { ++ log_err_errno("send failed sending msg to peer"); ++ return 1; ++ } + } else if (args->ifindex && args->use_cmsg) { + if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version)) + return 1; +@@ -1659,7 +1667,7 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args) + if (args->has_local_ip && bind_socket(sd, args)) + goto err; + +- if (args->type != SOCK_STREAM) ++ if (args->type != SOCK_STREAM && !args->datagram_connect) + goto out; + + if (args->password && tcp_md5sig(sd, addr, alen, args)) +@@ -1854,7 +1862,7 @@ static int ipc_parent(int cpid, int fd, struct sock_args *args) + return client_status; + } + +-#define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SCi6xL:0:1:2:3:Fbqf" ++#define GETOPT_STR "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf" + #define OPT_FORCE_BIND_KEY_IFINDEX 1001 + #define OPT_NO_BIND_KEY_IFINDEX 1002 + +@@ -1891,6 +1899,7 @@ static void print_usage(char *prog) + " -I dev bind socket to given device name - server mode\n" + " -S use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n" + " to set device binding\n" ++ " -U Use connect() and send() for datagram sockets\n" + " -f bind socket with the IP[V6]_FREEBIND option\n" + " -C use cmsg and IP_PKTINFO to specify device binding\n" + "\n" +@@ -2074,6 +2083,9 @@ int main(int argc, char *argv[]) + case 'x': + args.use_xfrm = 1; + break; ++ case 'U': ++ args.datagram_connect = 1; ++ break; + default: + print_usage(argv[0]); + return 1; +-- +2.35.1 + diff --git a/queue-5.19/net-prestera-acl-add-check-for-kmemdup.patch b/queue-5.19/net-prestera-acl-add-check-for-kmemdup.patch new file mode 100644 index 00000000000..6b618389b82 --- /dev/null +++ b/queue-5.19/net-prestera-acl-add-check-for-kmemdup.patch @@ -0,0 +1,88 @@ +From 6d55ee028b0496c20aa1b86d42378fcc61be5743 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 12:48:43 +0800 +Subject: net: prestera: acl: Add check for kmemdup + +From: Jiasheng Jiang + +[ Upstream commit 9e6fd874c7bb47b6a4295abc4c81b2f41b97e970 ] + +As the kemdup could return NULL, it should be better to check the return +value and return error if fails. +Moreover, the return value of prestera_acl_ruleset_keymask_set() should +be checked by cascade. + +Fixes: 604ba230902d ("net: prestera: flower template support") +Signed-off-by: Jiasheng Jiang +Reviewed-by: Taras Chornyi +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/prestera/prestera_acl.c | 8 ++++++-- + drivers/net/ethernet/marvell/prestera/prestera_acl.h | 4 ++-- + drivers/net/ethernet/marvell/prestera/prestera_flower.c | 6 +++++- + 3 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/prestera/prestera_acl.c b/drivers/net/ethernet/marvell/prestera/prestera_acl.c +index 3a141f2db812..c0d4ddc18f87 100644 +--- a/drivers/net/ethernet/marvell/prestera/prestera_acl.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_acl.c +@@ -162,10 +162,14 @@ prestera_acl_ruleset_create(struct prestera_acl *acl, + return ERR_PTR(err); + } + +-void prestera_acl_ruleset_keymask_set(struct prestera_acl_ruleset *ruleset, +- void *keymask) ++int prestera_acl_ruleset_keymask_set(struct prestera_acl_ruleset *ruleset, ++ void *keymask) + { + ruleset->keymask = kmemdup(keymask, ACL_KEYMASK_SIZE, GFP_KERNEL); ++ if (!ruleset->keymask) ++ return -ENOMEM; ++ ++ return 0; + } + + int prestera_acl_ruleset_offload(struct prestera_acl_ruleset *ruleset) +diff --git a/drivers/net/ethernet/marvell/prestera/prestera_acl.h b/drivers/net/ethernet/marvell/prestera/prestera_acl.h +index f963e1e0c0f0..21dbfe4fe5b8 100644 +--- a/drivers/net/ethernet/marvell/prestera/prestera_acl.h ++++ b/drivers/net/ethernet/marvell/prestera/prestera_acl.h +@@ -185,8 +185,8 @@ struct prestera_acl_ruleset * + prestera_acl_ruleset_lookup(struct prestera_acl *acl, + struct prestera_flow_block *block, + u32 chain_index); +-void prestera_acl_ruleset_keymask_set(struct prestera_acl_ruleset *ruleset, +- void *keymask); ++int prestera_acl_ruleset_keymask_set(struct prestera_acl_ruleset *ruleset, ++ void *keymask); + bool prestera_acl_ruleset_is_offload(struct prestera_acl_ruleset *ruleset); + int prestera_acl_ruleset_offload(struct prestera_acl_ruleset *ruleset); + void prestera_acl_ruleset_put(struct prestera_acl_ruleset *ruleset); +diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c +index 4d93ad6a284c..553413248823 100644 +--- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c ++++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c +@@ -428,7 +428,9 @@ int prestera_flower_tmplt_create(struct prestera_flow_block *block, + } + + /* preserve keymask/template to this ruleset */ +- prestera_acl_ruleset_keymask_set(ruleset, rule.re_key.match.mask); ++ err = prestera_acl_ruleset_keymask_set(ruleset, rule.re_key.match.mask); ++ if (err) ++ goto err_ruleset_keymask_set; + + /* skip error, as it is not possible to reject template operation, + * so, keep the reference to the ruleset for rules to be added +@@ -444,6 +446,8 @@ int prestera_flower_tmplt_create(struct prestera_flow_block *block, + list_add_rcu(&template->list, &block->template_list); + return 0; + ++err_ruleset_keymask_set: ++ prestera_acl_ruleset_put(ruleset); + err_ruleset_get: + kfree(template); + err_malloc: +-- +2.35.1 + diff --git a/queue-5.19/net-rds-don-t-hold-sock-lock-when-cancelling-work-fr.patch b/queue-5.19/net-rds-don-t-hold-sock-lock-when-cancelling-work-fr.patch new file mode 100644 index 00000000000..da16af08fa7 --- /dev/null +++ b/queue-5.19/net-rds-don-t-hold-sock-lock-when-cancelling-work-fr.patch @@ -0,0 +1,54 @@ +From 6271f1d6385d17281f2bfd0c166805d0831195a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 00:25:37 +0900 +Subject: net: rds: don't hold sock lock when cancelling work from + rds_tcp_reset_callbacks() + +From: Tetsuo Handa + +[ Upstream commit a91b750fd6629354460282bbf5146c01b05c4859 ] + +syzbot is reporting lockdep warning at rds_tcp_reset_callbacks() [1], for +commit ac3615e7f3cffe2a ("RDS: TCP: Reduce code duplication in +rds_tcp_reset_callbacks()") added cancel_delayed_work_sync() into a section +protected by lock_sock() without realizing that rds_send_xmit() might call +lock_sock(). + +We don't need to protect cancel_delayed_work_sync() using lock_sock(), for +even if rds_{send,recv}_worker() re-queued this work while __flush_work() + from cancel_delayed_work_sync() was waiting for this work to complete, +retried rds_{send,recv}_worker() is no-op due to the absence of RDS_CONN_UP +bit. + +Link: https://syzkaller.appspot.com/bug?extid=78c55c7bc6f66e53dce2 [1] +Reported-by: syzbot +Co-developed-by: Hillf Danton +Signed-off-by: Hillf Danton +Signed-off-by: Tetsuo Handa +Tested-by: syzbot +Fixes: ac3615e7f3cffe2a ("RDS: TCP: Reduce code duplication in rds_tcp_reset_callbacks()") +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/rds/tcp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index 73ee2771093d..d0ff413f697c 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -166,10 +166,10 @@ void rds_tcp_reset_callbacks(struct socket *sock, + */ + atomic_set(&cp->cp_state, RDS_CONN_RESETTING); + wait_event(cp->cp_waitq, !test_bit(RDS_IN_XMIT, &cp->cp_flags)); +- lock_sock(osock->sk); + /* reset receive side state for rds_tcp_data_recv() for osock */ + cancel_delayed_work_sync(&cp->cp_send_w); + cancel_delayed_work_sync(&cp->cp_recv_w); ++ lock_sock(osock->sk); + if (tc->t_tinc) { + rds_inc_put(&tc->t_tinc->ti_inc); + tc->t_tinc = NULL; +-- +2.35.1 + diff --git a/queue-5.19/net-sched-cls_u32-avoid-memcpy-false-positive-warnin.patch b/queue-5.19/net-sched-cls_u32-avoid-memcpy-false-positive-warnin.patch new file mode 100644 index 00000000000..6baf6864064 --- /dev/null +++ b/queue-5.19/net-sched-cls_u32-avoid-memcpy-false-positive-warnin.patch @@ -0,0 +1,52 @@ +From e75ebf2da7e0d366f10032c7b4c33039e62edb41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 08:37:01 -0700 +Subject: net: sched: cls_u32: Avoid memcpy() false-positive warning + +From: Kees Cook + +[ Upstream commit 7cba18332e3635aaae60e4e7d4e52849de50d91b ] + +To work around a misbehavior of the compiler's ability to see into +composite flexible array structs (as detailed in the coming memcpy() +hardening series[1]), use unsafe_memcpy(), as the sizing, +bounds-checking, and allocation are all very tightly coupled here. +This silences the false-positive reported by syzbot: + + memcpy: detected field-spanning write (size 80) of single field "&n->sel" at net/sched/cls_u32.c:1043 (size 16) + +[1] https://lore.kernel.org/linux-hardening/20220901065914.1417829-2-keescook@chromium.org + +Cc: Cong Wang +Cc: Jiri Pirko +Reported-by: syzbot+a2c4601efc75848ba321@syzkaller.appspotmail.com +Link: https://lore.kernel.org/lkml/000000000000a96c0b05e97f0444@google.com/ +Signed-off-by: Kees Cook +Reviewed-by: Jamal Hadi Salim +Link: https://lore.kernel.org/r/20220927153700.3071688-1-keescook@chromium.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/cls_u32.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c +index 4d27300c287c..5f33472aad36 100644 +--- a/net/sched/cls_u32.c ++++ b/net/sched/cls_u32.c +@@ -1040,7 +1040,11 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, + } + #endif + +- memcpy(&n->sel, s, sel_size); ++ unsafe_memcpy(&n->sel, s, sel_size, ++ /* A composite flex-array structure destination, ++ * which was correctly sized with struct_size(), ++ * bounds-checked against nla_len(), and allocated ++ * above. */); + RCU_INIT_POINTER(n->ht_up, ht); + n->handle = handle; + n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0; +-- +2.35.1 + diff --git a/queue-5.19/net-sparx5-fix-function-return-type-to-match-actual-.patch b/queue-5.19/net-sparx5-fix-function-return-type-to-match-actual-.patch new file mode 100644 index 00000000000..2417ad8ac55 --- /dev/null +++ b/queue-5.19/net-sparx5-fix-function-return-type-to-match-actual-.patch @@ -0,0 +1,57 @@ +From 91ef38e3e1813ce32dd40e8cc6af2bcadea20504 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 08:58:15 +0200 +Subject: net: sparx5: fix function return type to match actual type + +From: Casper Andersson + +[ Upstream commit 75554fe00f941c3c3d9344e88708093a14d2b4b8 ] + +Function returns error integer, not bool. + +Does not have any impact on functionality. + +Reported-by: Dan Carpenter +Signed-off-by: Casper Andersson +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20220906065815.3856323-1-casper.casan@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c | 4 ++-- + drivers/net/ethernet/microchip/sparx5/sparx5_main.h | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c b/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c +index a5837dbe0c7e..4af285918ea2 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c +@@ -186,8 +186,8 @@ bool sparx5_mact_getnext(struct sparx5 *sparx5, + return ret == 0; + } + +-bool sparx5_mact_find(struct sparx5 *sparx5, +- const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2) ++int sparx5_mact_find(struct sparx5 *sparx5, ++ const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2) + { + int ret; + u32 cfg2; +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +index b197129044b5..d071ac3b7106 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +@@ -307,8 +307,8 @@ int sparx5_mact_learn(struct sparx5 *sparx5, int port, + const unsigned char mac[ETH_ALEN], u16 vid); + bool sparx5_mact_getnext(struct sparx5 *sparx5, + unsigned char mac[ETH_ALEN], u16 *vid, u32 *pcfg2); +-bool sparx5_mact_find(struct sparx5 *sparx5, +- const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2); ++int sparx5_mact_find(struct sparx5 *sparx5, ++ const unsigned char mac[ETH_ALEN], u16 vid, u32 *pcfg2); + int sparx5_mact_forget(struct sparx5 *sparx5, + const unsigned char mac[ETH_ALEN], u16 vid); + int sparx5_add_mact_entry(struct sparx5 *sparx5, +-- +2.35.1 + diff --git a/queue-5.19/net-sparx5-fix-return-type-of-sparx5_port_xmit_impl.patch b/queue-5.19/net-sparx5-fix-return-type-of-sparx5_port_xmit_impl.patch new file mode 100644 index 00000000000..27083703459 --- /dev/null +++ b/queue-5.19/net-sparx5-fix-return-type-of-sparx5_port_xmit_impl.patch @@ -0,0 +1,65 @@ +From 646ee410cdea4c6b41795ddefd254ac98498b0d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 11:19:47 -0700 +Subject: net: sparx5: Fix return type of sparx5_port_xmit_impl + +From: Nathan Huckleberry + +[ Upstream commit 73ea735073599430818e89b8901452287a15a718 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of sparx5_port_xmit_impl should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/microchip/sparx5/sparx5_main.h | 2 +- + drivers/net/ethernet/microchip/sparx5/sparx5_packet.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +index d071ac3b7106..705d8852078f 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +@@ -291,7 +291,7 @@ struct frame_info { + void sparx5_xtr_flush(struct sparx5 *sparx5, u8 grp); + void sparx5_ifh_parse(u32 *ifh, struct frame_info *info); + irqreturn_t sparx5_xtr_handler(int irq, void *_priv); +-int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev); ++netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev); + int sparx5_manual_injection_mode(struct sparx5 *sparx5); + void sparx5_port_inj_timer_setup(struct sparx5_port *port); + +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +index 21844beba72d..83c16ca5b30f 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c +@@ -222,13 +222,13 @@ static int sparx5_inject(struct sparx5 *sparx5, + return NETDEV_TX_OK; + } + +-int sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev) ++netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev) + { + struct net_device_stats *stats = &dev->stats; + struct sparx5_port *port = netdev_priv(dev); + struct sparx5 *sparx5 = port->sparx5; + u32 ifh[IFH_LEN]; +- int ret; ++ netdev_tx_t ret; + + memset(ifh, 0, IFH_LEN * 4); + sparx5_set_port_ifh(ifh, port->portno); +-- +2.35.1 + diff --git a/queue-5.19/net-sunplus-fix-return-type-for-implementation-of-nd.patch b/queue-5.19/net-sunplus-fix-return-type-for-implementation-of-nd.patch new file mode 100644 index 00000000000..304c0f8ab22 --- /dev/null +++ b/queue-5.19/net-sunplus-fix-return-type-for-implementation-of-nd.patch @@ -0,0 +1,41 @@ +From d3ee0e9f09230550b01882b04728b4defa41f9dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 16:15:50 +0800 +Subject: net: sunplus: Fix return type for implementation of ndo_start_xmit + +From: GUO Zihua + +[ Upstream commit 7b620e156097028e4c9b6481a84ec1e1e72877ca ] + +Since Linux now supports CFI, it will be a good idea to fix mismatched +return type for implementation of hooks. Otherwise this might get +cought out by CFI and cause a panic. + +spl2sw_ethernet_start_xmit() would return either NETDEV_TX_BUSY or +NETDEV_TX_OK, so change the return type to netdev_tx_t directly. + +Signed-off-by: GUO Zihua +Link: https://lore.kernel.org/r/20220902081550.60095-1-guozihua@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/sunplus/spl2sw_driver.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/sunplus/spl2sw_driver.c b/drivers/net/ethernet/sunplus/spl2sw_driver.c +index 37711331ba0f..41c2cc9d1f1c 100644 +--- a/drivers/net/ethernet/sunplus/spl2sw_driver.c ++++ b/drivers/net/ethernet/sunplus/spl2sw_driver.c +@@ -62,7 +62,8 @@ static int spl2sw_ethernet_stop(struct net_device *ndev) + return 0; + } + +-static int spl2sw_ethernet_start_xmit(struct sk_buff *skb, struct net_device *ndev) ++static netdev_tx_t spl2sw_ethernet_start_xmit(struct sk_buff *skb, ++ struct net_device *ndev) + { + struct spl2sw_mac *mac = netdev_priv(ndev); + struct spl2sw_common *comm = mac->comm; +-- +2.35.1 + diff --git a/queue-5.19/net-wwan-iosm-call-mutex_init-before-locking-it.patch b/queue-5.19/net-wwan-iosm-call-mutex_init-before-locking-it.patch new file mode 100644 index 00000000000..4d7831137f8 --- /dev/null +++ b/queue-5.19/net-wwan-iosm-call-mutex_init-before-locking-it.patch @@ -0,0 +1,50 @@ +From 8484b06aa0ad97f0b147f6517571946f36fa2469 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 13:57:13 +0300 +Subject: net: wwan: iosm: Call mutex_init before locking it + +From: Maxim Mikityanskiy + +[ Upstream commit ba0fbdb95da5ddd8db457ce6ba09d16dd979a294 ] + +wwan_register_ops calls wwan_create_default_link, which ends up in the +ipc_wwan_newlink callback that locks ipc_wwan->if_mutex. However, this +mutex is not yet initialized by that point. Fix it by moving mutex_init +above the wwan_register_ops call. This also makes the order of +operations in ipc_wwan_init symmetric to ipc_wwan_deinit. + +Fixes: 83068395bbfc ("net: iosm: create default link via WWAN core") +Signed-off-by: Maxim Mikityanskiy +Reviewed-by: M Chetan Kumar +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/iosm/iosm_ipc_wwan.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c +index 27151148c782..4712f01a7e33 100644 +--- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c +@@ -323,15 +323,16 @@ struct iosm_wwan *ipc_wwan_init(struct iosm_imem *ipc_imem, struct device *dev) + ipc_wwan->dev = dev; + ipc_wwan->ipc_imem = ipc_imem; + ++ mutex_init(&ipc_wwan->if_mutex); ++ + /* WWAN core will create a netdev for the default IP MUX channel */ + if (wwan_register_ops(ipc_wwan->dev, &iosm_wwan_ops, ipc_wwan, + IP_MUX_SESSION_DEFAULT)) { ++ mutex_destroy(&ipc_wwan->if_mutex); + kfree(ipc_wwan); + return NULL; + } + +- mutex_init(&ipc_wwan->if_mutex); +- + return ipc_wwan; + } + +-- +2.35.1 + diff --git a/queue-5.19/net-wwan-iosm-fix-return-type-of-ipc_wwan_link_trans.patch b/queue-5.19/net-wwan-iosm-fix-return-type-of-ipc_wwan_link_trans.patch new file mode 100644 index 00000000000..82ca9544350 --- /dev/null +++ b/queue-5.19/net-wwan-iosm-fix-return-type-of-ipc_wwan_link_trans.patch @@ -0,0 +1,48 @@ +From e0c008bacabdd4c43c297459e3022fdfcc6b4880 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 14:44:55 -0700 +Subject: net: wwan: iosm: Fix return type of ipc_wwan_link_transmit + +From: Nathan Huckleberry + +[ Upstream commit 0c9441c430104dcf2cd066aae74dbeefb9f9e1bf ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of ipc_wwan_link_transmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Acked-by: Sergey Ryazanov +Link: https://lore.kernel.org/r/20220912214455.929028-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/iosm/iosm_ipc_wwan.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c +index 4712f01a7e33..2f1f8b5d5b59 100644 +--- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c ++++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c +@@ -103,8 +103,8 @@ static int ipc_wwan_link_stop(struct net_device *netdev) + } + + /* Transmit a packet */ +-static int ipc_wwan_link_transmit(struct sk_buff *skb, +- struct net_device *netdev) ++static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, ++ struct net_device *netdev) + { + struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); + struct iosm_wwan *ipc_wwan = priv->ipc_wwan; +-- +2.35.1 + diff --git a/queue-5.19/net-wwan-t7xx-fix-return-type-of-t7xx_ccmni_start_xm.patch b/queue-5.19/net-wwan-t7xx-fix-return-type-of-t7xx_ccmni_start_xm.patch new file mode 100644 index 00000000000..a37303c35c8 --- /dev/null +++ b/queue-5.19/net-wwan-t7xx-fix-return-type-of-t7xx_ccmni_start_xm.patch @@ -0,0 +1,46 @@ +From 1a3272862d28ab330ed7b2eec84fa560776bf955 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 14:45:10 -0700 +Subject: net: wwan: t7xx: Fix return type of t7xx_ccmni_start_xmit + +From: Nathan Huckleberry + +[ Upstream commit 73c99e26036529e633a0f2d628ad7ddff6594668 ] + +The ndo_start_xmit field in net_device_ops is expected to be of type +netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev). + +The mismatched return type breaks forward edge kCFI since the underlying +function definition does not match the function hook definition. + +The return type of t7xx_ccmni_start_xmit should be changed from int to +netdev_tx_t. + +Reported-by: Dan Carpenter +Link: https://github.com/ClangBuiltLinux/linux/issues/1703 +Cc: llvm@lists.linux.dev +Signed-off-by: Nathan Huckleberry +Acked-by: Sergey Ryazanov +Link: https://lore.kernel.org/r/20220912214510.929070-1-nhuck@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/wwan/t7xx/t7xx_netdev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wwan/t7xx/t7xx_netdev.c b/drivers/net/wwan/t7xx/t7xx_netdev.c +index c6b6547f2c6f..f71d3bc3b237 100644 +--- a/drivers/net/wwan/t7xx/t7xx_netdev.c ++++ b/drivers/net/wwan/t7xx/t7xx_netdev.c +@@ -74,7 +74,7 @@ static int t7xx_ccmni_send_packet(struct t7xx_ccmni *ccmni, struct sk_buff *skb, + return 0; + } + +-static int t7xx_ccmni_start_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t t7xx_ccmni_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct t7xx_ccmni *ccmni = wwan_netdev_drvpriv(dev); + int skb_len = skb->len; +-- +2.35.1 + diff --git a/queue-5.19/net-xscale-fix-return-type-for-implementation-of-ndo.patch b/queue-5.19/net-xscale-fix-return-type-for-implementation-of-ndo.patch new file mode 100644 index 00000000000..66ade71db95 --- /dev/null +++ b/queue-5.19/net-xscale-fix-return-type-for-implementation-of-ndo.patch @@ -0,0 +1,40 @@ +From 316cabae6bcfc7b42e23a82e93c379128967d74a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 16:16:12 +0800 +Subject: net: xscale: Fix return type for implementation of ndo_start_xmit + +From: GUO Zihua + +[ Upstream commit 0dbaf0fa62329d9fe452d9041a707a33f6274f1f ] + +Since Linux now supports CFI, it will be a good idea to fix mismatched +return type for implementation of hooks. Otherwise this might get +cought out by CFI and cause a panic. + +eth_xmit() would return either NETDEV_TX_BUSY or NETDEV_TX_OK, so +change the return type to netdev_tx_t directly. + +Signed-off-by: GUO Zihua +Link: https://lore.kernel.org/r/20220902081612.60405-1-guozihua@huawei.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/xscale/ixp4xx_eth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c +index 89770c2e0ffb..92a59c3e18bf 100644 +--- a/drivers/net/ethernet/xscale/ixp4xx_eth.c ++++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c +@@ -840,7 +840,7 @@ static void eth_txdone_irq(void *unused) + } + } + +-static int eth_xmit(struct sk_buff *skb, struct net_device *dev) ++static netdev_tx_t eth_xmit(struct sk_buff *skb, struct net_device *dev) + { + struct port *port = netdev_priv(dev); + unsigned int txreadyq = port->plat->txreadyq; +-- +2.35.1 + diff --git a/queue-5.19/netfilter-conntrack-fix-the-gc-rescheduling-delay.patch b/queue-5.19/netfilter-conntrack-fix-the-gc-rescheduling-delay.patch new file mode 100644 index 00000000000..9ed4dc5fa36 --- /dev/null +++ b/queue-5.19/netfilter-conntrack-fix-the-gc-rescheduling-delay.patch @@ -0,0 +1,111 @@ +From 88a74b5cdf54bd892c7579794a3cf36d7c438ec0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 11:29:40 +0200 +Subject: netfilter: conntrack: fix the gc rescheduling delay + +From: Antoine Tenart + +[ Upstream commit 95eabdd207024312876d0ebed90b4c977e050e85 ] + +Commit 2cfadb761d3d ("netfilter: conntrack: revisit gc autotuning") +changed the eviction rescheduling to the use average expiry of scanned +entries (within 1-60s) by doing: + + for (...) { + expires = clamp(nf_ct_expires(tmp), ...); + next_run += expires; + next_run /= 2; + } + +The issue is the above will make the average ('next_run' here) more +dependent on the last expiration values than the firsts (for sets > 2). +Depending on the expiration values used to compute the average, the +result can be quite different than what's expected. To fix this we can +do the following: + + for (...) { + expires = clamp(nf_ct_expires(tmp), ...); + next_run += (expires - next_run) / ++count; + } + +Fixes: 2cfadb761d3d ("netfilter: conntrack: revisit gc autotuning") +Cc: Florian Westphal +Signed-off-by: Antoine Tenart +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_core.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 369aeabb94fe..6fdbffc85222 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -67,6 +67,7 @@ struct conntrack_gc_work { + struct delayed_work dwork; + u32 next_bucket; + u32 avg_timeout; ++ u32 count; + u32 start_time; + bool exiting; + bool early_drop; +@@ -1468,6 +1469,7 @@ static void gc_worker(struct work_struct *work) + unsigned int expired_count = 0; + unsigned long next_run; + s32 delta_time; ++ long count; + + gc_work = container_of(work, struct conntrack_gc_work, dwork.work); + +@@ -1477,10 +1479,12 @@ static void gc_worker(struct work_struct *work) + + if (i == 0) { + gc_work->avg_timeout = GC_SCAN_INTERVAL_INIT; ++ gc_work->count = 1; + gc_work->start_time = start_time; + } + + next_run = gc_work->avg_timeout; ++ count = gc_work->count; + + end_time = start_time + GC_SCAN_MAX_DURATION; + +@@ -1500,8 +1504,8 @@ static void gc_worker(struct work_struct *work) + + hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[i], hnnode) { + struct nf_conntrack_net *cnet; +- unsigned long expires; + struct net *net; ++ long expires; + + tmp = nf_ct_tuplehash_to_ctrack(h); + +@@ -1515,6 +1519,7 @@ static void gc_worker(struct work_struct *work) + + gc_work->next_bucket = i; + gc_work->avg_timeout = next_run; ++ gc_work->count = count; + + delta_time = nfct_time_stamp - gc_work->start_time; + +@@ -1530,8 +1535,8 @@ static void gc_worker(struct work_struct *work) + } + + expires = clamp(nf_ct_expires(tmp), GC_SCAN_INTERVAL_MIN, GC_SCAN_INTERVAL_CLAMP); ++ expires = (expires - (long)next_run) / ++count; + next_run += expires; +- next_run /= 2u; + + if (nf_conntrack_max95 == 0 || gc_worker_skip_ct(tmp)) + continue; +@@ -1572,6 +1577,7 @@ static void gc_worker(struct work_struct *work) + delta_time = nfct_time_stamp - end_time; + if (delta_time > 0 && i < hashsz) { + gc_work->avg_timeout = next_run; ++ gc_work->count = count; + gc_work->next_bucket = i; + next_run = 0; + goto early_exit; +-- +2.35.1 + diff --git a/queue-5.19/netfilter-conntrack-revisit-the-gc-initial-reschedul.patch b/queue-5.19/netfilter-conntrack-revisit-the-gc-initial-reschedul.patch new file mode 100644 index 00000000000..2d7ce84543e --- /dev/null +++ b/queue-5.19/netfilter-conntrack-revisit-the-gc-initial-reschedul.patch @@ -0,0 +1,65 @@ +From 393eeb713a0e506aa86b2380716498fb78f8b8dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 11:29:41 +0200 +Subject: netfilter: conntrack: revisit the gc initial rescheduling bias + +From: Antoine Tenart + +[ Upstream commit 2aa192757005f130b2dd3547dda6e462e761199f ] + +The previous commit changed the way the rescheduling delay is computed +which has a side effect: the bias is now represented as much as the +other entries in the rescheduling delay which makes the logic to kick in +only with very large sets, as the initial interval is very large +(INT_MAX). + +Revisit the GC initial bias to allow more frequent GC for smaller sets +while still avoiding wakeups when a machine is mostly idle. We're moving +from a large initial value to pretending we have 100 entries expiring at +the upper bound. This way only a few entries having a small timeout +won't impact much the rescheduling delay and non-idle machines will have +enough entries to lower the delay when needed. This also improves +readability as the initial bias is now linked to what is computed +instead of being an arbitrary large value. + +Fixes: 2cfadb761d3d ("netfilter: conntrack: revisit gc autotuning") +Suggested-by: Florian Westphal +Signed-off-by: Antoine Tenart +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_conntrack_core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c +index 6fdbffc85222..8ef19f033773 100644 +--- a/net/netfilter/nf_conntrack_core.c ++++ b/net/netfilter/nf_conntrack_core.c +@@ -86,10 +86,12 @@ static DEFINE_MUTEX(nf_conntrack_mutex); + /* clamp timeouts to this value (TCP unacked) */ + #define GC_SCAN_INTERVAL_CLAMP (300ul * HZ) + +-/* large initial bias so that we don't scan often just because we have +- * three entries with a 1s timeout. ++/* Initial bias pretending we have 100 entries at the upper bound so we don't ++ * wakeup often just because we have three entries with a 1s timeout while still ++ * allowing non-idle machines to wakeup more often when needed. + */ +-#define GC_SCAN_INTERVAL_INIT INT_MAX ++#define GC_SCAN_INITIAL_COUNT 100 ++#define GC_SCAN_INTERVAL_INIT GC_SCAN_INTERVAL_MAX + + #define GC_SCAN_MAX_DURATION msecs_to_jiffies(10) + #define GC_SCAN_EXPIRED_MAX (64000u / HZ) +@@ -1479,7 +1481,7 @@ static void gc_worker(struct work_struct *work) + + if (i == 0) { + gc_work->avg_timeout = GC_SCAN_INTERVAL_INIT; +- gc_work->count = 1; ++ gc_work->count = GC_SCAN_INITIAL_COUNT; + gc_work->start_time = start_time; + } + +-- +2.35.1 + diff --git a/queue-5.19/netfilter-nft_fib-fix-for-rpath-check-with-vrf-devic.patch b/queue-5.19/netfilter-nft_fib-fix-for-rpath-check-with-vrf-devic.patch new file mode 100644 index 00000000000..4bc844d42a1 --- /dev/null +++ b/queue-5.19/netfilter-nft_fib-fix-for-rpath-check-with-vrf-devic.patch @@ -0,0 +1,64 @@ +From 1464c42b72a554a845cf607ce5acbd8a49de5737 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 13:07:31 +0200 +Subject: netfilter: nft_fib: Fix for rpath check with VRF devices + +From: Phil Sutter + +[ Upstream commit 2a8a7c0eaa8747c16aa4a48d573aa920d5c00a5c ] + +Analogous to commit b575b24b8eee3 ("netfilter: Fix rpfilter +dropping vrf packets by mistake") but for nftables fib expression: +Add special treatment of VRF devices so that typical reverse path +filtering via 'fib saddr . iif oif' expression works as expected. + +Fixes: f6d0cbcf09c50 ("netfilter: nf_tables: add fib expression") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/ipv4/netfilter/nft_fib_ipv4.c | 3 +++ + net/ipv6/netfilter/nft_fib_ipv6.c | 6 +++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/netfilter/nft_fib_ipv4.c b/net/ipv4/netfilter/nft_fib_ipv4.c +index b75cac69bd7e..7ade04ff972d 100644 +--- a/net/ipv4/netfilter/nft_fib_ipv4.c ++++ b/net/ipv4/netfilter/nft_fib_ipv4.c +@@ -83,6 +83,9 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs, + else + oif = NULL; + ++ if (priv->flags & NFTA_FIB_F_IIF) ++ fl4.flowi4_oif = l3mdev_master_ifindex_rcu(oif); ++ + if (nft_hook(pkt) == NF_INET_PRE_ROUTING && + nft_fib_is_loopback(pkt->skb, nft_in(pkt))) { + nft_fib_store_result(dest, priv, nft_in(pkt)); +diff --git a/net/ipv6/netfilter/nft_fib_ipv6.c b/net/ipv6/netfilter/nft_fib_ipv6.c +index 8970d0b4faeb..1d7e520d9966 100644 +--- a/net/ipv6/netfilter/nft_fib_ipv6.c ++++ b/net/ipv6/netfilter/nft_fib_ipv6.c +@@ -41,6 +41,9 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv, + if (ipv6_addr_type(&fl6->daddr) & IPV6_ADDR_LINKLOCAL) { + lookup_flags |= RT6_LOOKUP_F_IFACE; + fl6->flowi6_oif = get_ifindex(dev ? dev : pkt->skb->dev); ++ } else if ((priv->flags & NFTA_FIB_F_IIF) && ++ (netif_is_l3_master(dev) || netif_is_l3_slave(dev))) { ++ fl6->flowi6_oif = dev->ifindex; + } + + if (ipv6_addr_type(&fl6->saddr) & IPV6_ADDR_UNICAST) +@@ -197,7 +200,8 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs, + if (rt->rt6i_flags & (RTF_REJECT | RTF_ANYCAST | RTF_LOCAL)) + goto put_rt_err; + +- if (oif && oif != rt->rt6i_idev->dev) ++ if (oif && oif != rt->rt6i_idev->dev && ++ l3mdev_master_ifindex_rcu(rt->rt6i_idev->dev) != oif->ifindex) + goto put_rt_err; + + nft_fib_store_result(dest, priv, rt->rt6i_idev->dev); +-- +2.35.1 + diff --git a/queue-5.19/netlink-bounds-check-struct-nlmsgerr-creation.patch b/queue-5.19/netlink-bounds-check-struct-nlmsgerr-creation.patch new file mode 100644 index 00000000000..432466a0183 --- /dev/null +++ b/queue-5.19/netlink-bounds-check-struct-nlmsgerr-creation.patch @@ -0,0 +1,81 @@ +From c206ca228f9a8b60b3f0ba74a86d2df71f7f77d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 21:37:49 -0700 +Subject: netlink: Bounds-check struct nlmsgerr creation + +From: Kees Cook + +[ Upstream commit 710d21fdff9a98d621cd4e64167f3ef8af4e2fd1 ] + +In preparation for FORTIFY_SOURCE doing bounds-check on memcpy(), +switch from __nlmsg_put to nlmsg_put(), and explain the bounds check +for dealing with the memcpy() across a composite flexible array struct. +Avoids this future run-time warning: + + memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" at net/netlink/af_netlink.c:2447 (size 16) + +Cc: Jakub Kicinski +Cc: Pablo Neira Ayuso +Cc: Jozsef Kadlecsik +Cc: Florian Westphal +Cc: "David S. Miller" +Cc: Eric Dumazet +Cc: Paolo Abeni +Cc: syzbot +Cc: netfilter-devel@vger.kernel.org +Cc: coreteam@netfilter.org +Cc: netdev@vger.kernel.org +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20220901071336.1418572-1-keescook@chromium.org +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/netfilter/ipset/ip_set_core.c | 8 +++++--- + net/netlink/af_netlink.c | 8 +++++--- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index 16ae92054baa..6b31746f9be3 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1719,11 +1719,13 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb, + skb2 = nlmsg_new(payload, GFP_KERNEL); + if (!skb2) + return -ENOMEM; +- rep = __nlmsg_put(skb2, NETLINK_CB(skb).portid, +- nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); ++ rep = nlmsg_put(skb2, NETLINK_CB(skb).portid, ++ nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); + errmsg = nlmsg_data(rep); + errmsg->error = ret; +- memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); ++ unsafe_memcpy(&errmsg->msg, nlh, nlh->nlmsg_len, ++ /* Bounds checked by the skb layer. */); ++ + cmdattr = (void *)&errmsg->msg + min_len; + + ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr, +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 0cd91f813a3b..d8d3ed2096a3 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2440,11 +2440,13 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + return; + } + +- rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, +- NLMSG_ERROR, payload, flags); ++ rep = nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, ++ NLMSG_ERROR, payload, flags); + errmsg = nlmsg_data(rep); + errmsg->error = err; +- memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); ++ unsafe_memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ++ ? nlh->nlmsg_len : sizeof(*nlh), ++ /* Bounds checked by the skb layer. */); + + if (nlk_has_extack && extack) { + if (extack->_msg) { +-- +2.35.1 + diff --git a/queue-5.19/nfsd-fix-a-memory-leak-in-an-error-handling-path.patch b/queue-5.19/nfsd-fix-a-memory-leak-in-an-error-handling-path.patch new file mode 100644 index 00000000000..28c3d0abb8d --- /dev/null +++ b/queue-5.19/nfsd-fix-a-memory-leak-in-an-error-handling-path.patch @@ -0,0 +1,40 @@ +From 6012bcee84fbdb73353c5412133a80ceec73d600 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 07:27:04 +0200 +Subject: nfsd: Fix a memory leak in an error handling path + +From: Christophe JAILLET + +[ Upstream commit fd1ef88049de09bc70d60b549992524cfc0e66ff ] + +If this memdup_user() call fails, the memory allocated in a previous call +a few lines above should be freed. Otherwise it leaks. + +Fixes: 6ee95d1c8991 ("nfsd: add support for upcall version 2") +Signed-off-by: Christophe JAILLET +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4recover.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c +index c634483d85d2..8f24485e0f04 100644 +--- a/fs/nfsd/nfs4recover.c ++++ b/fs/nfsd/nfs4recover.c +@@ -815,8 +815,10 @@ __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, + princhash.data = memdup_user( + &ci->cc_princhash.cp_data, + princhashlen); +- if (IS_ERR_OR_NULL(princhash.data)) ++ if (IS_ERR_OR_NULL(princhash.data)) { ++ kfree(name.data); + return -EFAULT; ++ } + princhash.len = princhashlen; + } else + princhash.len = 0; +-- +2.35.1 + diff --git a/queue-5.19/nfsd-fix-handling-of-oversized-nfsv4-compound-reques.patch b/queue-5.19/nfsd-fix-handling-of-oversized-nfsv4-compound-reques.patch new file mode 100644 index 00000000000..5893b1c1e90 --- /dev/null +++ b/queue-5.19/nfsd-fix-handling-of-oversized-nfsv4-compound-reques.patch @@ -0,0 +1,125 @@ +From f68c8c7658898b25fe19d7186969004288e82137 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 15:33:32 -0400 +Subject: NFSD: Fix handling of oversized NFSv4 COMPOUND requests + +From: Chuck Lever + +[ Upstream commit 7518a3dc5ea249d4112156ce71b8b184eb786151 ] + +If an NFS server returns NFS4ERR_RESOURCE on the first operation in +an NFSv4 COMPOUND, there's no way for a client to know where the +problem is and then simplify the compound to make forward progress. + +So instead, make NFSD process as many operations in an oversized +COMPOUND as it can and then return NFS4ERR_RESOURCE on the first +operation it did not process. + +pynfs NFSv4.0 COMP6 exercises this case, but checks only for the +COMPOUND status code, not whether the server has processed any +of the operations. + +pynfs NFSv4.1 SEQ6 and SEQ7 exercise the NFSv4.1 case, which detects +too many operations per COMPOUND by checking against the limits +negotiated when the session was created. + +Suggested-by: Bruce Fields +Fixes: 0078117c6d91 ("nfsd: return RESOURCE not GARBAGE_ARGS on too many ops") +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4proc.c | 19 +++++++++++++------ + fs/nfsd/nfs4xdr.c | 12 +++--------- + fs/nfsd/xdr4.h | 3 ++- + 3 files changed, 18 insertions(+), 16 deletions(-) + +diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c +index 3895eb52d2b1..c12e66cc58a2 100644 +--- a/fs/nfsd/nfs4proc.c ++++ b/fs/nfsd/nfs4proc.c +@@ -2663,9 +2663,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) + status = nfserr_minor_vers_mismatch; + if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0) + goto out; +- status = nfserr_resource; +- if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND) +- goto out; + + status = nfs41_check_op_ordering(args); + if (status) { +@@ -2678,10 +2675,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) + + rqstp->rq_lease_breaker = (void **)&cstate->clp; + +- trace_nfsd_compound(rqstp, args->opcnt); ++ trace_nfsd_compound(rqstp, args->client_opcnt); + while (!status && resp->opcnt < args->opcnt) { + op = &args->ops[resp->opcnt++]; + ++ if (unlikely(resp->opcnt == NFSD_MAX_OPS_PER_COMPOUND)) { ++ /* If there are still more operations to process, ++ * stop here and report NFS4ERR_RESOURCE. */ ++ if (cstate->minorversion == 0 && ++ args->client_opcnt > resp->opcnt) { ++ op->status = nfserr_resource; ++ goto encode_op; ++ } ++ } ++ + /* + * The XDR decode routines may have pre-set op->status; + * for example, if there is a miscellaneous XDR error +@@ -2757,8 +2764,8 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) + status = op->status; + } + +- trace_nfsd_compound_status(args->opcnt, resp->opcnt, status, +- nfsd4_op_name(op->opnum)); ++ trace_nfsd_compound_status(args->client_opcnt, resp->opcnt, ++ status, nfsd4_op_name(op->opnum)); + + nfsd4_cstate_clear_replay(cstate); + nfsd4_increment_op_stats(op->opnum); +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 2acea7792bb2..eef98e3f4ae5 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -2347,16 +2347,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) + + if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0) + return false; +- if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0) ++ if (xdr_stream_decode_u32(argp->xdr, &argp->client_opcnt) < 0) + return false; +- +- /* +- * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS +- * here, so we return success at the xdr level so that +- * nfsd4_proc can handle this is an NFS-level error. +- */ +- if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND) +- return true; ++ argp->opcnt = min_t(u32, argp->client_opcnt, ++ NFSD_MAX_OPS_PER_COMPOUND); + + if (argp->opcnt > ARRAY_SIZE(argp->iops)) { + argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); +diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h +index 7b744011f2d3..77286e8c9ab0 100644 +--- a/fs/nfsd/xdr4.h ++++ b/fs/nfsd/xdr4.h +@@ -689,9 +689,10 @@ struct nfsd4_compoundargs { + struct svcxdr_tmpbuf *to_free; + struct svc_rqst *rqstp; + +- u32 taglen; + char * tag; ++ u32 taglen; + u32 minorversion; ++ u32 client_opcnt; + u32 opcnt; + struct nfsd4_op *ops; + struct nfsd4_op iops[8]; +-- +2.35.1 + diff --git a/queue-5.19/nfsd-fix-use-after-free-on-source-server-when-doing-.patch b/queue-5.19/nfsd-fix-use-after-free-on-source-server-when-doing-.patch new file mode 100644 index 00000000000..b05f384dc5b --- /dev/null +++ b/queue-5.19/nfsd-fix-use-after-free-on-source-server-when-doing-.patch @@ -0,0 +1,79 @@ +From fd02c27de6369fab6b4b9929d838647e4b5c63ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 10:59:16 -0700 +Subject: NFSD: fix use-after-free on source server when doing inter-server + copy + +From: Dai Ngo + +[ Upstream commit 019805fea91599b22dfa62ffb29c022f35abeb06 ] + +Use-after-free occurred when the laundromat tried to free expired +cpntf_state entry on the s2s_cp_stateids list after inter-server +copy completed. The sc_cp_list that the expired copy state was +inserted on was already freed. + +When COPY completes, the Linux client normally sends LOCKU(lock_state x), +FREE_STATEID(lock_state x) and CLOSE(open_state y) to the source server. +The nfs4_put_stid call from nfsd4_free_stateid cleans up the copy state +from the s2s_cp_stateids list before freeing the lock state's stid. + +However, sometimes the CLOSE was sent before the FREE_STATEID request. +When this happens, the nfsd4_close_open_stateid call from nfsd4_close +frees all lock states on its st_locks list without cleaning up the copy +state on the sc_cp_list list. When the time the FREE_STATEID arrives the +server returns BAD_STATEID since the lock state was freed. This causes +the use-after-free error to occur when the laundromat tries to free +the expired cpntf_state. + +This patch adds a call to nfs4_free_cpntf_statelist in +nfsd4_close_open_stateid to clean up the copy state before calling +free_ol_stateid_reaplist to free the lock state's stid on the reaplist. + +Signed-off-by: Dai Ngo +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4state.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c +index 9409a0dc1b76..c16646f9db31 100644 +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -1049,6 +1049,7 @@ static struct nfs4_ol_stateid * nfs4_alloc_open_stateid(struct nfs4_client *clp) + + static void nfs4_free_deleg(struct nfs4_stid *stid) + { ++ WARN_ON(!list_empty(&stid->sc_cp_list)); + kmem_cache_free(deleg_slab, stid); + atomic_long_dec(&num_delegations); + } +@@ -1463,6 +1464,7 @@ static void nfs4_free_ol_stateid(struct nfs4_stid *stid) + release_all_access(stp); + if (stp->st_stateowner) + nfs4_put_stateowner(stp->st_stateowner); ++ WARN_ON(!list_empty(&stid->sc_cp_list)); + kmem_cache_free(stateid_slab, stid); + } + +@@ -6608,6 +6610,7 @@ static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) + struct nfs4_client *clp = s->st_stid.sc_client; + bool unhashed; + LIST_HEAD(reaplist); ++ struct nfs4_ol_stateid *stp; + + spin_lock(&clp->cl_lock); + unhashed = unhash_open_stateid(s, &reaplist); +@@ -6616,6 +6619,8 @@ static void nfsd4_close_open_stateid(struct nfs4_ol_stateid *s) + if (unhashed) + put_ol_stateid_locked(s, &reaplist); + spin_unlock(&clp->cl_lock); ++ list_for_each_entry(stp, &reaplist, st_locks) ++ nfs4_free_cpntf_statelist(clp->net, &stp->st_stid); + free_ol_stateid_reaplist(&reaplist); + } else { + spin_unlock(&clp->cl_lock); +-- +2.35.1 + diff --git a/queue-5.19/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch b/queue-5.19/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch new file mode 100644 index 00000000000..eed6e23980c --- /dev/null +++ b/queue-5.19/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch @@ -0,0 +1,43 @@ +From 8c8c46032847bdaafe43e8315a1bba005df68f25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 15:10:05 -0400 +Subject: NFSD: Protect against send buffer overflow in NFSv2 READDIR + +From: Chuck Lever + +[ Upstream commit 00b4492686e0497fdb924a9d4c8f6f99377e176c ] + +Restore the previous limit on the @count argument to prevent a +buffer overflow attack. + +Fixes: 53b1119a6e50 ("NFSD: Fix READDIR buffer overflow") +Signed-off-by: Chuck Lever +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfsproc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c +index 16cde315f454..f65eba938a57 100644 +--- a/fs/nfsd/nfsproc.c ++++ b/fs/nfsd/nfsproc.c +@@ -557,12 +557,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp, + struct xdr_buf *buf = &resp->dirlist; + struct xdr_stream *xdr = &resp->xdr; + +- count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp)); +- + memset(buf, 0, sizeof(*buf)); + + /* Reserve room for the NULL ptr & eof flag (-2 words) */ +- buf->buflen = count - XDR_UNIT * 2; ++ buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), (u32)PAGE_SIZE); ++ buf->buflen -= XDR_UNIT * 2; + buf->pages = rqstp->rq_next_page; + rqstp->rq_next_page++; + +-- +2.35.1 + diff --git a/queue-5.19/nfsd-return-nfserr_serverfault-if-splice_ok-but-buf-.patch b/queue-5.19/nfsd-return-nfserr_serverfault-if-splice_ok-but-buf-.patch new file mode 100644 index 00000000000..77e31cfc33a --- /dev/null +++ b/queue-5.19/nfsd-return-nfserr_serverfault-if-splice_ok-but-buf-.patch @@ -0,0 +1,37 @@ +From b00ba65a7510ff066fd66475dcf3f96781a49675 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 14:01:50 -0400 +Subject: NFSD: Return nfserr_serverfault if splice_ok but buf->pages have data + +From: Anna Schumaker + +[ Upstream commit 06981d560606ac48d61e5f4fff6738b925c93173 ] + +This was discussed with Chuck as part of this patch set. Returning +nfserr_resource was decided to not be the best error message here, and +he suggested changing to nfserr_serverfault instead. + +Signed-off-by: Anna Schumaker +Link: https://lore.kernel.org/linux-nfs/20220907195259.926736-1-anna@kernel.org/T/#t +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4xdr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index eef98e3f4ae5..1e5822d00043 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -3995,7 +3995,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, + if (resp->xdr->buf->page_len && + test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) { + WARN_ON_ONCE(1); +- return nfserr_resource; ++ return nfserr_serverfault; + } + xdr_commit_encode(xdr); + +-- +2.35.1 + diff --git a/queue-5.19/ntfs3-rework-xattr-handlers-and-switch-to-posix-acl-.patch b/queue-5.19/ntfs3-rework-xattr-handlers-and-switch-to-posix-acl-.patch new file mode 100644 index 00000000000..4e08b127cdf --- /dev/null +++ b/queue-5.19/ntfs3-rework-xattr-handlers-and-switch-to-posix-acl-.patch @@ -0,0 +1,189 @@ +From c8dc0375d50677eb24e2040e2479b65859ae64c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 14:38:40 +0200 +Subject: ntfs3: rework xattr handlers and switch to POSIX ACL VFS helpers + +From: Christian Brauner + +[ Upstream commit a26aa12384158116c0d80d50e0bdc7b3323551e2 ] + +The xattr code in ntfs3 is currently a bit confused. For example, it +defines a POSIX ACL i_op->set_acl() method but instead of relying on the +generic POSIX ACL VFS helpers it defines its own set of xattr helpers +with the consequence that i_op->set_acl() is currently dead code. + +Switch ntfs3 to rely on the VFS POSIX ACL xattr handlers. Also remove +i_op->{g,s}et_acl() methods from symlink inode operations. Symlinks +don't support xattrs. + +This is a preliminary change for the following patches which move +handling idmapped mounts directly in posix_acl_xattr_set(). + +This survives POSIX ACL xfstests. + +Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") +Signed-off-by: Christian Brauner (Microsoft) +Reviewed-by: Seth Forshee (DigitalOcean) > +Signed-off-by: Sasha Levin +--- + fs/ntfs3/inode.c | 2 - + fs/ntfs3/xattr.c | 102 +++-------------------------------------------- + 2 files changed, 6 insertions(+), 98 deletions(-) + +diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c +index 803ff4c63c31..3b94ad22d9c0 100644 +--- a/fs/ntfs3/inode.c ++++ b/fs/ntfs3/inode.c +@@ -1941,8 +1941,6 @@ const struct inode_operations ntfs_link_inode_operations = { + .setattr = ntfs3_setattr, + .listxattr = ntfs_listxattr, + .permission = ntfs_permission, +- .get_acl = ntfs_get_acl, +- .set_acl = ntfs_set_acl, + }; + + const struct address_space_operations ntfs_aops = { +diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c +index e3d443ccb9be..19ce48726b00 100644 +--- a/fs/ntfs3/xattr.c ++++ b/fs/ntfs3/xattr.c +@@ -625,67 +625,6 @@ int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, + return ntfs_set_acl_ex(mnt_userns, inode, acl, type, false); + } + +-static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, +- struct inode *inode, int type, void *buffer, +- size_t size) +-{ +- struct posix_acl *acl; +- int err; +- +- if (!(inode->i_sb->s_flags & SB_POSIXACL)) { +- ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); +- return -EOPNOTSUPP; +- } +- +- acl = ntfs_get_acl(inode, type, false); +- if (IS_ERR(acl)) +- return PTR_ERR(acl); +- +- if (!acl) +- return -ENODATA; +- +- err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); +- posix_acl_release(acl); +- +- return err; +-} +- +-static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns, +- struct inode *inode, int type, const void *value, +- size_t size) +-{ +- struct posix_acl *acl; +- int err; +- +- if (!(inode->i_sb->s_flags & SB_POSIXACL)) { +- ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); +- return -EOPNOTSUPP; +- } +- +- if (!inode_owner_or_capable(mnt_userns, inode)) +- return -EPERM; +- +- if (!value) { +- acl = NULL; +- } else { +- acl = posix_acl_from_xattr(&init_user_ns, value, size); +- if (IS_ERR(acl)) +- return PTR_ERR(acl); +- +- if (acl) { +- err = posix_acl_valid(&init_user_ns, acl); +- if (err) +- goto release_and_out; +- } +- } +- +- err = ntfs_set_acl(mnt_userns, inode, acl, type); +- +-release_and_out: +- posix_acl_release(acl); +- return err; +-} +- + /* + * ntfs_init_acl - Initialize the ACLs of a new inode. + * +@@ -852,23 +791,6 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de, + goto out; + } + +-#ifdef CONFIG_NTFS3_FS_POSIX_ACL +- if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && +- !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, +- sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || +- (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && +- !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, +- sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { +- /* TODO: init_user_ns? */ +- err = ntfs_xattr_get_acl( +- &init_user_ns, inode, +- name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 +- ? ACL_TYPE_ACCESS +- : ACL_TYPE_DEFAULT, +- buffer, size); +- goto out; +- } +-#endif + /* Deal with NTFS extended attribute. */ + err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL); + +@@ -981,22 +903,6 @@ static noinline int ntfs_setxattr(const struct xattr_handler *handler, + goto out; + } + +-#ifdef CONFIG_NTFS3_FS_POSIX_ACL +- if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && +- !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, +- sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || +- (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && +- !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, +- sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { +- err = ntfs_xattr_set_acl( +- mnt_userns, inode, +- name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 +- ? ACL_TYPE_ACCESS +- : ACL_TYPE_DEFAULT, +- value, size); +- goto out; +- } +-#endif + /* Deal with NTFS extended attribute. */ + err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); + +@@ -1086,7 +992,7 @@ static bool ntfs_xattr_user_list(struct dentry *dentry) + } + + // clang-format off +-static const struct xattr_handler ntfs_xattr_handler = { ++static const struct xattr_handler ntfs_other_xattr_handler = { + .prefix = "", + .get = ntfs_getxattr, + .set = ntfs_setxattr, +@@ -1094,7 +1000,11 @@ static const struct xattr_handler ntfs_xattr_handler = { + }; + + const struct xattr_handler *ntfs_xattr_handlers[] = { +- &ntfs_xattr_handler, ++#ifdef CONFIG_NTFS3_FS_POSIX_ACL ++ &posix_acl_access_xattr_handler, ++ &posix_acl_default_xattr_handler, ++#endif ++ &ntfs_other_xattr_handler, + NULL, + }; + // clang-format on +-- +2.35.1 + diff --git a/queue-5.19/nvme-copy-firmware_rev-on-each-init.patch b/queue-5.19/nvme-copy-firmware_rev-on-each-init.patch new file mode 100644 index 00000000000..463bc6d2abf --- /dev/null +++ b/queue-5.19/nvme-copy-firmware_rev-on-each-init.patch @@ -0,0 +1,48 @@ +From a3fc6cfe92e8934a4e93cec128d2830d9021ee2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 12:45:08 -0700 +Subject: nvme: copy firmware_rev on each init + +From: Keith Busch + +[ Upstream commit a8eb6c1ba48bddea82e8d74cbe6e119f006be97d ] + +The firmware revision can change on after a reset so copy the most +recent info each time instead of just the first time, otherwise the +sysfs firmware_rev entry may contain stale data. + +Reported-by: Jeff Lien +Signed-off-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Chao Leng +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 47fd9d528c83..698e65883d82 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -2796,7 +2796,6 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id) + nvme_init_subnqn(subsys, ctrl, id); + memcpy(subsys->serial, id->sn, sizeof(subsys->serial)); + memcpy(subsys->model, id->mn, sizeof(subsys->model)); +- memcpy(subsys->firmware_rev, id->fr, sizeof(subsys->firmware_rev)); + subsys->vendor_id = le16_to_cpu(id->vid); + subsys->cmic = id->cmic; + +@@ -3015,6 +3014,8 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl) + ctrl->quirks |= core_quirks[i].quirks; + } + } ++ memcpy(ctrl->subsys->firmware_rev, id->fr, ++ sizeof(ctrl->subsys->firmware_rev)); + + if (force_apst && (ctrl->quirks & NVME_QUIRK_NO_DEEPEST_PS)) { + dev_warn(ctrl->device, "forcibly allowing all power states due to nvme_core.force_apst -- use at your own risk\n"); +-- +2.35.1 + diff --git a/queue-5.19/nvme-handle-effects-after-freeing-the-request.patch b/queue-5.19/nvme-handle-effects-after-freeing-the-request.patch new file mode 100644 index 00000000000..90df9462f3e --- /dev/null +++ b/queue-5.19/nvme-handle-effects-after-freeing-the-request.patch @@ -0,0 +1,159 @@ +From 6b9975eb3b9200651fe23590555eb4876d771bf2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 12:36:46 -0700 +Subject: nvme: handle effects after freeing the request + +From: Keith Busch + +[ Upstream commit bc8fb906b0ff9339b4286698cb7cd9cd5b8c53eb ] + +If a reset occurs after the scan work attempts to issue a command, the +reset may quisce the admin queue, which blocks the scan work's command +from dispatching. The scan work will not be able to complete while the +queue is quiesced. + +Meanwhile, the reset work will cancel all outstanding admin tags and +wait until all requests have transitioned to idle, which includes the +passthrough request. But the passthrough request won't be set to idle +until after the scan_work flushes, so we're deadlocked. + +Fix this by handling the end effects after the request has been freed. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216354 +Reported-by: Jonathan Derrick +Signed-off-by: Keith Busch +Reviewed-by: Sagi Grimberg +Reviewed-by: Chao Leng +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/core.c | 17 ++++++----------- + drivers/nvme/host/ioctl.c | 9 ++++++++- + drivers/nvme/host/nvme.h | 4 +++- + drivers/nvme/target/passthru.c | 7 ++++++- + 4 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 326ad33537ed..47fd9d528c83 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1089,8 +1089,8 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, + return effects; + } + +-static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, +- struct nvme_command *cmd, int status) ++void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, ++ struct nvme_command *cmd, int status) + { + if (effects & NVME_CMD_EFFECTS_CSE_MASK) { + nvme_unfreeze(ctrl); +@@ -1126,21 +1126,16 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, + break; + } + } ++EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU); + +-int nvme_execute_passthru_rq(struct request *rq) ++int nvme_execute_passthru_rq(struct request *rq, u32 *effects) + { + struct nvme_command *cmd = nvme_req(rq)->cmd; + struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl; + struct nvme_ns *ns = rq->q->queuedata; +- u32 effects; +- int ret; + +- effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode); +- ret = nvme_execute_rq(rq, false); +- if (effects) /* nothing to be done for zero cmd effects */ +- nvme_passthru_end(ctrl, effects, cmd, ret); +- +- return ret; ++ *effects = nvme_passthru_start(ctrl, ns, cmd->common.opcode); ++ return nvme_execute_rq(rq, false); + } + EXPORT_SYMBOL_NS_GPL(nvme_execute_passthru_rq, NVME_TARGET_PASSTHRU); + +diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c +index a2e89db1cd63..15a60e1f290a 100644 +--- a/drivers/nvme/host/ioctl.c ++++ b/drivers/nvme/host/ioctl.c +@@ -136,9 +136,11 @@ static int nvme_submit_user_cmd(struct request_queue *q, + unsigned bufflen, void __user *meta_buffer, unsigned meta_len, + u32 meta_seed, u64 *result, unsigned timeout, bool vec) + { ++ struct nvme_ctrl *ctrl; + struct request *req; + void *meta = NULL; + struct bio *bio; ++ u32 effects; + int ret; + + req = nvme_alloc_user_request(q, cmd, ubuffer, bufflen, meta_buffer, +@@ -147,8 +149,9 @@ static int nvme_submit_user_cmd(struct request_queue *q, + return PTR_ERR(req); + + bio = req->bio; ++ ctrl = nvme_req(req)->ctrl; + +- ret = nvme_execute_passthru_rq(req); ++ ret = nvme_execute_passthru_rq(req, &effects); + + if (result) + *result = le64_to_cpu(nvme_req(req)->result.u64); +@@ -158,6 +161,10 @@ static int nvme_submit_user_cmd(struct request_queue *q, + if (bio) + blk_rq_unmap_user(bio); + blk_mq_free_request(req); ++ ++ if (effects) ++ nvme_passthru_end(ctrl, effects, cmd, ret); ++ + return ret; + } + +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index 5558f8812157..e154e2304203 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -994,7 +994,9 @@ static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl) + + u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, + u8 opcode); +-int nvme_execute_passthru_rq(struct request *rq); ++int nvme_execute_passthru_rq(struct request *rq, u32 *effects); ++void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, ++ struct nvme_command *cmd, int status); + struct nvme_ctrl *nvme_ctrl_from_file(struct file *file); + struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid); + void nvme_put_ns(struct nvme_ns *ns); +diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c +index 6f39a29828b1..94d3153bae54 100644 +--- a/drivers/nvme/target/passthru.c ++++ b/drivers/nvme/target/passthru.c +@@ -215,9 +215,11 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) + { + struct nvmet_req *req = container_of(w, struct nvmet_req, p.work); + struct request *rq = req->p.rq; ++ struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl; ++ u32 effects; + int status; + +- status = nvme_execute_passthru_rq(rq); ++ status = nvme_execute_passthru_rq(rq, &effects); + + if (status == NVME_SC_SUCCESS && + req->cmd->common.opcode == nvme_admin_identify) { +@@ -238,6 +240,9 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) + req->cqe->result = nvme_req(rq)->result; + nvmet_req_complete(req, status); + blk_mq_free_request(rq); ++ ++ if (effects) ++ nvme_passthru_end(ctrl, effects, req->cmd, status); + } + + static void nvmet_passthru_req_done(struct request *rq, +-- +2.35.1 + diff --git a/queue-5.19/nvmet-don-t-look-at-the-request_queue-in-nvmet_bdev_.patch b/queue-5.19/nvmet-don-t-look-at-the-request_queue-in-nvmet_bdev_.patch new file mode 100644 index 00000000000..bcaf6a38772 --- /dev/null +++ b/queue-5.19/nvmet-don-t-look-at-the-request_queue-in-nvmet_bdev_.patch @@ -0,0 +1,56 @@ +From aff72de372e9dbc6d7b66ce7c80d72890c36d667 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 10:26:26 +0200 +Subject: nvmet: don't look at the request_queue in nvmet_bdev_set_limits + +From: Christoph Hellwig + +[ Upstream commit 84fe64f898913ef69f70a8d91aea613b5722b63b ] + +nvmet is a consumer of the block layer and should not directly look at +the request_queue. Use the bdev_ helpers to retrieve the device limits +instead. + +Signed-off-by: Christoph Hellwig +Reviewed-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/io-cmd-bdev.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c +index 27a72504d31c..521fe9469e08 100644 +--- a/drivers/nvme/target/io-cmd-bdev.c ++++ b/drivers/nvme/target/io-cmd-bdev.c +@@ -12,11 +12,9 @@ + + void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id) + { +- const struct queue_limits *ql = &bdev_get_queue(bdev)->limits; +- /* Number of logical blocks per physical block. */ +- const u32 lpp = ql->physical_block_size / ql->logical_block_size; + /* Logical blocks per physical block, 0's based. */ +- const __le16 lpp0b = to0based(lpp); ++ const __le16 lpp0b = to0based(bdev_physical_block_size(bdev) / ++ bdev_logical_block_size(bdev)); + + /* + * For NVMe 1.2 and later, bit 1 indicates that the fields NAWUN, +@@ -42,11 +40,12 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id) + /* NPWA = Namespace Preferred Write Alignment. 0's based */ + id->npwa = id->npwg; + /* NPDG = Namespace Preferred Deallocate Granularity. 0's based */ +- id->npdg = to0based(ql->discard_granularity / ql->logical_block_size); ++ id->npdg = to0based(bdev_discard_granularity(bdev) / ++ bdev_logical_block_size(bdev)); + /* NPDG = Namespace Preferred Deallocate Alignment */ + id->npda = id->npdg; + /* NOWS = Namespace Optimal Write Size */ +- id->nows = to0based(ql->io_opt / ql->logical_block_size); ++ id->nows = to0based(bdev_io_opt(bdev) / bdev_logical_block_size(bdev)); + } + + void nvmet_bdev_ns_disable(struct nvmet_ns *ns) +-- +2.35.1 + diff --git a/queue-5.19/nvmet-tcp-add-bounds-check-on-transfer-tag.patch b/queue-5.19/nvmet-tcp-add-bounds-check-on-transfer-tag.patch new file mode 100644 index 00000000000..78a1421cf75 --- /dev/null +++ b/queue-5.19/nvmet-tcp-add-bounds-check-on-transfer-tag.patch @@ -0,0 +1,47 @@ +From 7da1d10df185214d78043fe3f60b8517465ce00b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 00:06:49 +0530 +Subject: nvmet-tcp: add bounds check on Transfer Tag + +From: Varun Prakash + +[ Upstream commit b6a545ffa2c192b1e6da4a7924edac5ba9f4ea2b ] + +ttag is used as an index to get cmd in nvmet_tcp_handle_h2c_data_pdu(), +add a bounds check to avoid out-of-bounds access. + +Signed-off-by: Varun Prakash +Reviewed-by: Sagi Grimberg +Signed-off-by: Christoph Hellwig +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/tcp.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c +index a3694a32f6d5..7dcf88cde189 100644 +--- a/drivers/nvme/target/tcp.c ++++ b/drivers/nvme/target/tcp.c +@@ -935,10 +935,17 @@ static int nvmet_tcp_handle_h2c_data_pdu(struct nvmet_tcp_queue *queue) + struct nvme_tcp_data_pdu *data = &queue->pdu.data; + struct nvmet_tcp_cmd *cmd; + +- if (likely(queue->nr_cmds)) ++ if (likely(queue->nr_cmds)) { ++ if (unlikely(data->ttag >= queue->nr_cmds)) { ++ pr_err("queue %d: received out of bound ttag %u, nr_cmds %u\n", ++ queue->idx, data->ttag, queue->nr_cmds); ++ nvmet_tcp_fatal_error(queue); ++ return -EPROTO; ++ } + cmd = &queue->cmds[data->ttag]; +- else ++ } else { + cmd = &queue->connect; ++ } + + if (le32_to_cpu(data->data_offset) != cmd->rbytes_done) { + pr_err("ttag %u unexpected data offset %u (expected %u)\n", +-- +2.35.1 + diff --git a/queue-5.19/objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch b/queue-5.19/objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch new file mode 100644 index 00000000000..5b169a58a8d --- /dev/null +++ b/queue-5.19/objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch @@ -0,0 +1,54 @@ +From 88684fab2b5b30bd165d9ff7abeed12cce8c60d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 14:54:58 -0700 +Subject: objtool: Preserve special st_shndx indexes in elf_update_symbol + +From: Sami Tolvanen + +[ Upstream commit 5141d3a06b2da1731ac82091298b766a1f95d3d8 ] + +elf_update_symbol fails to preserve the special st_shndx values +between [SHN_LORESERVE, SHN_HIRESERVE], which results in it +converting SHN_ABS entries into SHN_UNDEF, for example. Explicitly +check for the special indexes and ensure these symbols are not +marked undefined. + +Fixes: ead165fa1042 ("objtool: Fix symbol creation") +Signed-off-by: Sami Tolvanen +Acked-by: Peter Zijlstra (Intel) +Tested-by: Peter Zijlstra (Intel) +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20220908215504.3686827-17-samitolvanen@google.com +Signed-off-by: Sasha Levin +--- + tools/objtool/elf.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c +index c25e957c1e52..7e24b09b1163 100644 +--- a/tools/objtool/elf.c ++++ b/tools/objtool/elf.c +@@ -619,6 +619,11 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, + Elf64_Xword entsize = symtab->sh.sh_entsize; + int max_idx, idx = sym->idx; + Elf_Scn *s, *t = NULL; ++ bool is_special_shndx = sym->sym.st_shndx >= SHN_LORESERVE && ++ sym->sym.st_shndx != SHN_XINDEX; ++ ++ if (is_special_shndx) ++ shndx = sym->sym.st_shndx; + + s = elf_getscn(elf->elf, symtab->idx); + if (!s) { +@@ -704,7 +709,7 @@ static int elf_update_symbol(struct elf *elf, struct section *symtab, + } + + /* setup extended section index magic and write the symbol */ +- if (shndx >= SHN_UNDEF && shndx < SHN_LORESERVE) { ++ if ((shndx >= SHN_UNDEF && shndx < SHN_LORESERVE) || is_special_shndx) { + sym->sym.st_shndx = shndx; + if (!shndx_data) + shndx = 0; +-- +2.35.1 + diff --git a/queue-5.19/once-add-do_once_slow-for-sleepable-contexts.patch b/queue-5.19/once-add-do_once_slow-for-sleepable-contexts.patch new file mode 100644 index 00000000000..1c28cc05c2c --- /dev/null +++ b/queue-5.19/once-add-do_once_slow-for-sleepable-contexts.patch @@ -0,0 +1,149 @@ +From 1bca56bdfb16be18f3fcd6a3ab52413645a2bcb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 13:51:02 -0700 +Subject: once: add DO_ONCE_SLOW() for sleepable contexts + +From: Eric Dumazet + +[ Upstream commit 62c07983bef9d3e78e71189441e1a470f0d1e653 ] + +Christophe Leroy reported a ~80ms latency spike +happening at first TCP connect() time. + +This is because __inet_hash_connect() uses get_random_once() +to populate a perturbation table which became quite big +after commit 4c2c8f03a5ab ("tcp: increase source port perturb table to 2^16") + +get_random_once() uses DO_ONCE(), which block hard irqs for the duration +of the operation. + +This patch adds DO_ONCE_SLOW() which uses a mutex instead of a spinlock +for operations where we prefer to stay in process context. + +Then __inet_hash_connect() can use get_random_slow_once() +to populate its perturbation table. + +Fixes: 4c2c8f03a5ab ("tcp: increase source port perturb table to 2^16") +Fixes: 190cc82489f4 ("tcp: change source port randomizarion at connect() time") +Reported-by: Christophe Leroy +Link: https://lore.kernel.org/netdev/CANn89iLAEYBaoYajy0Y9UmGFff5GPxDUoG-ErVB2jDdRNQ5Tug@mail.gmail.com/T/#t +Signed-off-by: Eric Dumazet +Cc: Willy Tarreau +Tested-by: Christophe Leroy +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/once.h | 28 ++++++++++++++++++++++++++++ + lib/once.c | 30 ++++++++++++++++++++++++++++++ + net/ipv4/inet_hashtables.c | 4 ++-- + 3 files changed, 60 insertions(+), 2 deletions(-) + +diff --git a/include/linux/once.h b/include/linux/once.h +index f54523052bbc..aebc038e79e5 100644 +--- a/include/linux/once.h ++++ b/include/linux/once.h +@@ -5,10 +5,18 @@ + #include + #include + ++/* Helpers used from arbitrary contexts. ++ * Hard irqs are blocked, be cautious. ++ */ + bool __do_once_start(bool *done, unsigned long *flags); + void __do_once_done(bool *done, struct static_key_true *once_key, + unsigned long *flags, struct module *mod); + ++/* Variant for process contexts only. */ ++bool __do_once_slow_start(bool *done); ++void __do_once_slow_done(bool *done, struct static_key_true *once_key, ++ struct module *mod); ++ + /* Call a function exactly once. The idea of DO_ONCE() is to perform + * a function call such as initialization of random seeds, etc, only + * once, where DO_ONCE() can live in the fast-path. After @func has +@@ -52,9 +60,29 @@ void __do_once_done(bool *done, struct static_key_true *once_key, + ___ret; \ + }) + ++/* Variant of DO_ONCE() for process/sleepable contexts. */ ++#define DO_ONCE_SLOW(func, ...) \ ++ ({ \ ++ bool ___ret = false; \ ++ static bool __section(".data.once") ___done = false; \ ++ static DEFINE_STATIC_KEY_TRUE(___once_key); \ ++ if (static_branch_unlikely(&___once_key)) { \ ++ ___ret = __do_once_slow_start(&___done); \ ++ if (unlikely(___ret)) { \ ++ func(__VA_ARGS__); \ ++ __do_once_slow_done(&___done, &___once_key, \ ++ THIS_MODULE); \ ++ } \ ++ } \ ++ ___ret; \ ++ }) ++ + #define get_random_once(buf, nbytes) \ + DO_ONCE(get_random_bytes, (buf), (nbytes)) + #define get_random_once_wait(buf, nbytes) \ + DO_ONCE(get_random_bytes_wait, (buf), (nbytes)) \ + ++#define get_random_slow_once(buf, nbytes) \ ++ DO_ONCE_SLOW(get_random_bytes, (buf), (nbytes)) ++ + #endif /* _LINUX_ONCE_H */ +diff --git a/lib/once.c b/lib/once.c +index 59149bf3bfb4..351f66aad310 100644 +--- a/lib/once.c ++++ b/lib/once.c +@@ -66,3 +66,33 @@ void __do_once_done(bool *done, struct static_key_true *once_key, + once_disable_jump(once_key, mod); + } + EXPORT_SYMBOL(__do_once_done); ++ ++static DEFINE_MUTEX(once_mutex); ++ ++bool __do_once_slow_start(bool *done) ++ __acquires(once_mutex) ++{ ++ mutex_lock(&once_mutex); ++ if (*done) { ++ mutex_unlock(&once_mutex); ++ /* Keep sparse happy by restoring an even lock count on ++ * this mutex. In case we return here, we don't call into ++ * __do_once_done but return early in the DO_ONCE_SLOW() macro. ++ */ ++ __acquire(once_mutex); ++ return false; ++ } ++ ++ return true; ++} ++EXPORT_SYMBOL(__do_once_slow_start); ++ ++void __do_once_slow_done(bool *done, struct static_key_true *once_key, ++ struct module *mod) ++ __releases(once_mutex) ++{ ++ *done = true; ++ mutex_unlock(&once_mutex); ++ once_disable_jump(once_key, mod); ++} ++EXPORT_SYMBOL(__do_once_slow_done); +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index b9d995b5ce24..f5950a7172d6 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -729,8 +729,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row, + if (likely(remaining > 1)) + remaining &= ~1U; + +- net_get_random_once(table_perturb, +- INET_TABLE_PERTURB_SIZE * sizeof(*table_perturb)); ++ get_random_slow_once(table_perturb, ++ INET_TABLE_PERTURB_SIZE * sizeof(*table_perturb)); + index = port_offset & (INET_TABLE_PERTURB_SIZE - 1); + + offset = READ_ONCE(table_perturb[index]) + (port_offset >> 32); +-- +2.35.1 + diff --git a/queue-5.19/openvswitch-fix-double-reporting-of-drops-in-dropwat.patch b/queue-5.19/openvswitch-fix-double-reporting-of-drops-in-dropwat.patch new file mode 100644 index 00000000000..5779b9fbb26 --- /dev/null +++ b/queue-5.19/openvswitch-fix-double-reporting-of-drops-in-dropwat.patch @@ -0,0 +1,52 @@ +From 087715526478353787d5b5cc089834cb0f05c684 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Aug 2022 11:06:34 -0400 +Subject: openvswitch: Fix double reporting of drops in dropwatch + +From: Mike Pattrick + +[ Upstream commit 1100248a5c5ccd57059eb8d02ec077e839a23826 ] + +Frames sent to userspace can be reported as dropped in +ovs_dp_process_packet, however, if they are dropped in the netlink code +then netlink_attachskb will report the same frame as dropped. + +This patch checks for error codes which indicate that the frame has +already been freed. + +Signed-off-by: Mike Pattrick +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2109946 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/openvswitch/datapath.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index 6c9d153afbee..b68ba3c72519 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -252,10 +252,17 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key) + + upcall.mru = OVS_CB(skb)->mru; + error = ovs_dp_upcall(dp, skb, key, &upcall, 0); +- if (unlikely(error)) +- kfree_skb(skb); +- else ++ switch (error) { ++ case 0: ++ case -EAGAIN: ++ case -ERESTARTSYS: ++ case -EINTR: + consume_skb(skb); ++ break; ++ default: ++ kfree_skb(skb); ++ break; ++ } + stats_counter = &stats->n_missed; + goto out; + } +-- +2.35.1 + diff --git a/queue-5.19/openvswitch-fix-overreporting-of-drops-in-dropwatch.patch b/queue-5.19/openvswitch-fix-overreporting-of-drops-in-dropwatch.patch new file mode 100644 index 00000000000..302d512d769 --- /dev/null +++ b/queue-5.19/openvswitch-fix-overreporting-of-drops-in-dropwatch.patch @@ -0,0 +1,42 @@ +From b3acd142be7dd950144cee86f2652f34190add96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Aug 2022 11:06:35 -0400 +Subject: openvswitch: Fix overreporting of drops in dropwatch + +From: Mike Pattrick + +[ Upstream commit c21ab2afa2c64896a7f0e3cbc6845ec63dcfad2e ] + +Currently queue_userspace_packet will call kfree_skb for all frames, +whether or not an error occurred. This can result in a single dropped +frame being reported as multiple drops in dropwatch. This functions +caller may also call kfree_skb in case of an error. This patch will +consume the skbs instead and allow caller's to use kfree_skb. + +Signed-off-by: Mike Pattrick +Link: https://bugzilla.redhat.com/show_bug.cgi?id=2109957 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/openvswitch/datapath.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c +index b68ba3c72519..93c596e3b22b 100644 +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -558,8 +558,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, + out: + if (err) + skb_tx_error(skb); +- kfree_skb(user_skb); +- kfree_skb(nskb); ++ consume_skb(user_skb); ++ consume_skb(nskb); ++ + return err; + } + +-- +2.35.1 + diff --git a/queue-5.19/phy-amlogic-phy-meson-axg-mipi-pcie-analog-hold-refe.patch b/queue-5.19/phy-amlogic-phy-meson-axg-mipi-pcie-analog-hold-refe.patch new file mode 100644 index 00000000000..44f08b94fca --- /dev/null +++ b/queue-5.19/phy-amlogic-phy-meson-axg-mipi-pcie-analog-hold-refe.patch @@ -0,0 +1,51 @@ +From 219d181253c6d9f8e9e5c39deb9c71e3c8fff720 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 17:35:06 +0800 +Subject: phy: amlogic: phy-meson-axg-mipi-pcie-analog: Hold reference returned + by of_get_parent() + +From: Liang He + +[ Upstream commit c4c349be07aeec5f397a349046dc5fc0f2657691 ] + +As the of_get_parent() will increase the refcount of the node->parent +and the reference will be discarded, so we should hold the reference +with which we can decrease the refcount when done. + +Fixes: 8eff8b4e22d9 ("phy: amlogic: phy-meson-axg-mipi-pcie-analog: add support for MIPI DSI analog") +Signed-off-by: Liang He + +Link: https://lore.kernel.org/r/20220915093506.4009456-1-windhl@126.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c +index 1027ece6ca12..a3e1108b736d 100644 +--- a/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c ++++ b/drivers/phy/amlogic/phy-meson-axg-mipi-pcie-analog.c +@@ -197,7 +197,7 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev) + struct phy_provider *phy; + struct device *dev = &pdev->dev; + struct phy_axg_mipi_pcie_analog_priv *priv; +- struct device_node *np = dev->of_node; ++ struct device_node *np = dev->of_node, *parent_np; + struct regmap *map; + int ret; + +@@ -206,7 +206,9 @@ static int phy_axg_mipi_pcie_analog_probe(struct platform_device *pdev) + return -ENOMEM; + + /* Get the hhi system controller node */ +- map = syscon_node_to_regmap(of_get_parent(dev->of_node)); ++ parent_np = of_get_parent(dev->of_node); ++ map = syscon_node_to_regmap(parent_np); ++ of_node_put(parent_np); + if (IS_ERR(map)) { + dev_err(dev, + "failed to get HHI regmap\n"); +-- +2.35.1 + diff --git a/queue-5.19/phy-phy-mtk-tphy-fix-the-phy-type-setting-issue.patch b/queue-5.19/phy-phy-mtk-tphy-fix-the-phy-type-setting-issue.patch new file mode 100644 index 00000000000..3ba3002ccbd --- /dev/null +++ b/queue-5.19/phy-phy-mtk-tphy-fix-the-phy-type-setting-issue.patch @@ -0,0 +1,50 @@ +From a4c8817dd806088e678a56b3db4e1e453dd2afda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 14:07:46 +0800 +Subject: phy: phy-mtk-tphy: fix the phy type setting issue + +From: Chunfeng Yun + +[ Upstream commit 931c05a8cb1be029ef2fbc1e4af313d4cb297c47 ] + +The PHY type is not set if the index is non zero, prepare type +value according to the index, like as mask value. + +Fixes: 39099a443358 ("phy: phy-mtk-tphy: support type switch by pericfg") +Signed-off-by: Chunfeng Yun +Reviewed-by: AngeloGioacchino Del Regno +Link: https://lore.kernel.org/r/20220914060746.10004-7-chunfeng.yun@mediatek.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/mediatek/phy-mtk-tphy.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c +index 8ee7682b8e93..bdffc21858f6 100644 +--- a/drivers/phy/mediatek/phy-mtk-tphy.c ++++ b/drivers/phy/mediatek/phy-mtk-tphy.c +@@ -906,7 +906,7 @@ static int phy_type_syscon_get(struct mtk_phy_instance *instance, + static int phy_type_set(struct mtk_phy_instance *instance) + { + int type; +- u32 mask; ++ u32 offset; + + if (!instance->type_sw) + return 0; +@@ -929,8 +929,9 @@ static int phy_type_set(struct mtk_phy_instance *instance) + return 0; + } + +- mask = RG_PHY_SW_TYPE << (instance->type_sw_index * BITS_PER_BYTE); +- regmap_update_bits(instance->type_sw, instance->type_sw_reg, mask, type); ++ offset = instance->type_sw_index * BITS_PER_BYTE; ++ regmap_update_bits(instance->type_sw, instance->type_sw_reg, ++ RG_PHY_SW_TYPE << offset, type << offset); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-combo-disable-runtime-pm-on-unbind.patch b/queue-5.19/phy-qcom-qmp-combo-disable-runtime-pm-on-unbind.patch new file mode 100644 index 00000000000..2a9b05d19fe --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-combo-disable-runtime-pm-on-unbind.patch @@ -0,0 +1,53 @@ +From 9863d4b2251a7403c77d8988179cd9557eafd01c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 13:07:13 +0200 +Subject: phy: qcom-qmp-combo: disable runtime PM on unbind + +From: Johan Hovold + +[ Upstream commit 4382d518d1887e62234560ea08a0203d11d28cc1 ] + +Make sure to disable runtime PM also on driver unbind. + +Fixes: ac0d239936bd ("phy: qcom-qmp: Add support for runtime PM"). +Signed-off-by: Johan Hovold +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220907110728.19092-2-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +index c7309e981bfb..dcf8a8764e17 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -6273,7 +6273,9 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + return -ENOMEM; + + pm_runtime_set_active(dev); +- pm_runtime_enable(dev); ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return ret; + /* + * Prevent runtime pm from being ON by default. Users can enable + * it using power/control in sysfs. +@@ -6323,13 +6325,10 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + 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; + } +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-combo-fix-memleak-on-probe-deferral.patch b/queue-5.19/phy-qcom-qmp-combo-fix-memleak-on-probe-deferral.patch new file mode 100644 index 00000000000..e6d9a6467d6 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-combo-fix-memleak-on-probe-deferral.patch @@ -0,0 +1,92 @@ +From 3d2e817d37ed7023bfa9d63f89e01a08cd424551 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:33 +0200 +Subject: phy: qcom-qmp-combo: fix memleak on probe deferral + +From: Johan Hovold + +[ Upstream commit 2de8a325b1084330ae500380cc27edc39f488c30 ] + +Switch to using the device-managed of_iomap helper to avoid leaking +memory on probe deferral and driver unbind. + +Note that this helper checks for already reserved regions and may fail +if there are multiple devices claiming the same memory. + +Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-5-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 32 ++++++++++++----------- + 1 file changed, 17 insertions(+), 15 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +index dcf8a8764e17..5606b25ea229 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -5919,17 +5919,17 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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->tx = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(qphy->tx)) ++ return PTR_ERR(qphy->tx); + +- qphy->rx = of_iomap(np, 1); +- if (!qphy->rx) +- return -ENOMEM; ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (IS_ERR(qphy->rx)) ++ return PTR_ERR(qphy->rx); + +- qphy->pcs = of_iomap(np, 2); +- if (!qphy->pcs) +- return -ENOMEM; ++ qphy->pcs = devm_of_iomap(dev, np, 2, NULL); ++ if (IS_ERR(qphy->pcs)) ++ return PTR_ERR(qphy->pcs); + + /* + * If this is a dual-lane PHY, then there should be registers for the +@@ -5938,9 +5938,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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) { ++ qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); ++ qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); ++ if (IS_ERR(qphy->tx2) || IS_ERR(qphy->rx2)) { + dev_warn(dev, + "Underspecified device tree, falling back to legacy register regions\n"); + +@@ -5950,15 +5950,17 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; + + } else { +- qphy->pcs_misc = of_iomap(np, 5); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); + } + + } else { +- qphy->pcs_misc = of_iomap(np, 3); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); + } + +- if (!qphy->pcs_misc) ++ if (IS_ERR(qphy->pcs_misc)) { + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ qphy->pcs_misc = NULL; ++ } + + /* + * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch b/queue-5.19/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch new file mode 100644 index 00000000000..b7277414ca4 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch @@ -0,0 +1,31819 @@ +From 35af982d7abf31b8639715cd41a66776fce34a3e 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: 4382d518d188 ("phy: qcom-qmp-combo: disable runtime PM on unbind") +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.19/phy-qcom-qmp-pcie-add-pcs_misc-sanity-check.patch b/queue-5.19/phy-qcom-qmp-pcie-add-pcs_misc-sanity-check.patch new file mode 100644 index 00000000000..4cff09700a9 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-add-pcs_misc-sanity-check.patch @@ -0,0 +1,45 @@ +From e76a9db1efb6df3b986fe5aeaa3ffb4afade71d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:30 +0200 +Subject: phy: qcom-qmp-pcie: add pcs_misc sanity check + +From: Johan Hovold + +[ Upstream commit ecd5507e72ea03659dc2cc3e4393fbf8f4e2e02a ] + +Make sure that the (otherwise) optional pcs_misc IO region has been +provided in case the configuration specifies a corresponding +initialisation table to avoid crashing with malformed device trees. + +Note that the related debug message is now superfluous as the region is +only used when the configuration has a pcs_misc table. + +Fixes: 421c9a0e9731 ("phy: qcom: qmp: Add SDM845 PCIe QMP PHY support") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-2-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +index 38fd0c5c3797..77f861bad8da 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -5966,8 +5966,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + of_device_is_compatible(dev->of_node, "qcom,ipq6018-qmp-pcie-phy")) + qphy->pcs_misc = qphy->pcs + 0x400; + +- if (!qphy->pcs_misc) +- dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ if (!qphy->pcs_misc) { ++ if (cfg->pcs_misc_tbl || cfg->pcs_misc_tbl_sec) ++ return -EINVAL; ++ } + + /* + * Get PHY's Pipe clock, if any. USB3 and PCIe are PIPE3 +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-change-symbol-prefix-to-qcom_qmp_p.patch b/queue-5.19/phy-qcom-qmp-pcie-change-symbol-prefix-to-qcom_qmp_p.patch new file mode 100644 index 00000000000..2950826f6c4 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-change-symbol-prefix-to-qcom_qmp_p.patch @@ -0,0 +1,503 @@ +From 38f818a53a7d3adf97c066407b413373d8af26a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:42 +0300 +Subject: phy: qcom-qmp-pcie: change symbol prefix to qcom_qmp_phy_pcie_msm8996 + +From: Dmitry Baryshkov + +[ Upstream commit 2abf0c8e61a900a77f2262f54596973db572cabb ] + +Change all symbol names to start with qcom_qmp_phy_pcie_msm8996_ rather +than old qcom_qmp_phy_. + +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-10-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: 1f69ededf8e8 ("phy: qcom-qmp-pcie-msm8996: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 158 +++++++++--------- + 1 file changed, 79 insertions(+), 79 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +index 260e534b5607..1741a5675f9a 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -474,7 +474,7 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { + .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, + }; + +-static void qcom_qmp_phy_configure_lane(void __iomem *base, ++static void qcom_qmp_phy_pcie_msm8996_configure_lane(void __iomem *base, + const unsigned int *regs, + const struct qmp_phy_init_tbl tbl[], + int num, +@@ -497,15 +497,15 @@ static void qcom_qmp_phy_configure_lane(void __iomem *base, + } + } + +-static void qcom_qmp_phy_configure(void __iomem *base, ++static void qcom_qmp_phy_pcie_msm8996_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); ++ qcom_qmp_phy_pcie_msm8996_configure_lane(base, regs, tbl, num, 0xff); + } + +-static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -515,30 +515,30 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) + int serdes_tbl_num = cfg->serdes_tbl_num; + int ret; + +- qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, + cfg->serdes_tbl_rbr, + cfg->serdes_tbl_rbr_num); + break; + case 2700: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr, + cfg->serdes_tbl_hbr_num); + break; + case 5400: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr2, + cfg->serdes_tbl_hbr2_num); + break; + case 8100: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr3, + cfg->serdes_tbl_hbr3_num); + break; +@@ -602,7 +602,7 @@ static int qcom_qmp_dp_phy_calibrate(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++static int qcom_qmp_phy_pcie_msm8996_com_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -697,7 +697,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) + return ret; + } + +-static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -732,7 +732,7 @@ static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) + return 0; + } + +-static int qcom_qmp_phy_init(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_init(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; +@@ -767,7 +767,7 @@ static int qcom_qmp_phy_init(struct phy *phy) + return ret; + } + +- ret = qcom_qmp_phy_com_init(qphy); ++ ret = qcom_qmp_phy_pcie_msm8996_com_init(qphy); + if (ret) + return ret; + +@@ -777,7 +777,7 @@ static int qcom_qmp_phy_init(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_power_on(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; +@@ -790,7 +790,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + unsigned int mask, val, ready; + int ret; + +- qcom_qmp_phy_serdes_init(qphy); ++ qcom_qmp_phy_pcie_msm8996_serdes_init(qphy); + + if (cfg->has_lane_rst) { + ret = reset_control_deassert(qphy->lane_rst); +@@ -808,18 +808,18 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + } + + /* Tx, Rx, and PCS configurations */ +- qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_configure_lane(qphy->tx2, cfg->regs, + cfg->tx_tbl_sec, + cfg->tx_tbl_num_sec, 2); + } +@@ -828,17 +828,17 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + if (cfg->type == PHY_TYPE_DP) + cfg->configure_dp_tx(qphy); + +- qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_configure_lane(qphy->rx2, cfg->regs, + cfg->rx_tbl_sec, + cfg->rx_tbl_num_sec, 2); + } +@@ -847,9 +847,9 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + 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); ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, + cfg->pcs_tbl_num_sec); + } + +@@ -857,10 +857,10 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + if (ret) + goto err_disable_pipe_clk; + +- qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ qcom_qmp_phy_pcie_msm8996_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, ++ qcom_qmp_phy_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, + cfg->pcs_misc_tbl_num_sec); + + /* +@@ -908,7 +908,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + return ret; + } + +-static int qcom_qmp_phy_power_off(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -939,7 +939,7 @@ static int qcom_qmp_phy_power_off(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_exit(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_exit(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -947,37 +947,37 @@ static int qcom_qmp_phy_exit(struct phy *phy) + if (cfg->has_lane_rst) + reset_control_assert(qphy->lane_rst); + +- qcom_qmp_phy_com_exit(qphy); ++ qcom_qmp_phy_pcie_msm8996_com_exit(qphy); + + return 0; + } + +-static int qcom_qmp_phy_enable(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_enable(struct phy *phy) + { + int ret; + +- ret = qcom_qmp_phy_init(phy); ++ ret = qcom_qmp_phy_pcie_msm8996_init(phy); + if (ret) + return ret; + +- ret = qcom_qmp_phy_power_on(phy); ++ ret = qcom_qmp_phy_pcie_msm8996_power_on(phy); + if (ret) +- qcom_qmp_phy_exit(phy); ++ qcom_qmp_phy_pcie_msm8996_exit(phy); + + return ret; + } + +-static int qcom_qmp_phy_disable(struct phy *phy) ++static int qcom_qmp_phy_pcie_msm8996_disable(struct phy *phy) + { + int ret; + +- ret = qcom_qmp_phy_power_off(phy); ++ ret = qcom_qmp_phy_pcie_msm8996_power_off(phy); + if (ret) + return ret; +- return qcom_qmp_phy_exit(phy); ++ return qcom_qmp_phy_pcie_msm8996_exit(phy); + } + +-static int qcom_qmp_phy_set_mode(struct phy *phy, ++static int qcom_qmp_phy_pcie_msm8996_set_mode(struct phy *phy, + enum phy_mode mode, int submode) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); +@@ -987,7 +987,7 @@ static int qcom_qmp_phy_set_mode(struct phy *phy, + return 0; + } + +-static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++static void qcom_qmp_phy_pcie_msm8996_enable_autonomous_mode(struct qmp_phy *qphy) + { + const struct qmp_phy_cfg *cfg = qphy->cfg; + void __iomem *pcs = qphy->pcs; +@@ -1016,7 +1016,7 @@ static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) + qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); + } + +-static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++static void qcom_qmp_phy_pcie_msm8996_disable_autonomous_mode(struct qmp_phy *qphy) + { + const struct qmp_phy_cfg *cfg = qphy->cfg; + void __iomem *pcs = qphy->pcs; +@@ -1034,7 +1034,7 @@ static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) + 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) ++static int __maybe_unused qcom_qmp_phy_pcie_msm8996_runtime_suspend(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct qmp_phy *qphy = qmp->phys[0]; +@@ -1051,7 +1051,7 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + return 0; + } + +- qcom_qmp_phy_enable_autonomous_mode(qphy); ++ qcom_qmp_phy_pcie_msm8996_enable_autonomous_mode(qphy); + + clk_disable_unprepare(qphy->pipe_clk); + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); +@@ -1059,7 +1059,7 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + return 0; + } + +-static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++static int __maybe_unused qcom_qmp_phy_pcie_msm8996_runtime_resume(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct qmp_phy *qphy = qmp->phys[0]; +@@ -1088,12 +1088,12 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) + return ret; + } + +- qcom_qmp_phy_disable_autonomous_mode(qphy); ++ qcom_qmp_phy_pcie_msm8996_disable_autonomous_mode(qphy); + + return 0; + } + +-static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int num = cfg->num_vregs; +@@ -1109,7 +1109,7 @@ static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg * + 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) ++static int qcom_qmp_phy_pcie_msm8996_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int i; +@@ -1134,7 +1134,7 @@ static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg + return 0; + } + +-static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++static int qcom_qmp_phy_pcie_msm8996_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int num = cfg->num_clks; +@@ -1402,28 +1402,28 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, + 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, ++static const struct phy_ops qcom_qmp_phy_pcie_msm8996_gen_ops = { ++ .init = qcom_qmp_phy_pcie_msm8996_enable, ++ .exit = qcom_qmp_phy_pcie_msm8996_disable, ++ .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, + .owner = THIS_MODULE, + }; + +-static const struct phy_ops qcom_qmp_phy_dp_ops = { +- .init = qcom_qmp_phy_init, ++static const struct phy_ops qcom_qmp_phy_pcie_msm8996_dp_ops = { ++ .init = qcom_qmp_phy_pcie_msm8996_init, + .configure = qcom_qmp_dp_phy_configure, +- .power_on = qcom_qmp_phy_power_on, ++ .power_on = qcom_qmp_phy_pcie_msm8996_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, ++ .power_off = qcom_qmp_phy_pcie_msm8996_power_off, ++ .exit = qcom_qmp_phy_pcie_msm8996_exit, ++ .set_mode = qcom_qmp_phy_pcie_msm8996_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, ++ .power_on = qcom_qmp_phy_pcie_msm8996_enable, ++ .power_off = qcom_qmp_phy_pcie_msm8996_disable, ++ .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, + .owner = THIS_MODULE, + }; + +@@ -1433,7 +1433,7 @@ static void qcom_qmp_reset_control_put(void *data) + } + + static +-int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++int qcom_qmp_phy_pcie_msm8996_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); +@@ -1535,9 +1535,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + 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; ++ ops = &qcom_qmp_phy_pcie_msm8996_dp_ops; + else +- ops = &qcom_qmp_phy_gen_ops; ++ ops = &qcom_qmp_phy_pcie_msm8996_gen_ops; + + generic_phy = devm_phy_create(dev, np, ops); + if (IS_ERR(generic_phy)) { +@@ -1555,21 +1555,21 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + return 0; + } + +-static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++static const struct of_device_id qcom_qmp_phy_pcie_msm8996_of_match_table[] = { + { + .compatible = "qcom,msm8996-qmp-pcie-phy", + .data = &msm8996_pciephy_cfg, + }, + { }, + }; +-MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_msm8996_of_match_table); + +-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 const struct dev_pm_ops qcom_qmp_phy_pcie_msm8996_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_pcie_msm8996_runtime_suspend, ++ qcom_qmp_phy_pcie_msm8996_runtime_resume, NULL) + }; + +-static int qcom_qmp_phy_probe(struct platform_device *pdev) ++static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + { + struct qcom_qmp *qmp; + struct device *dev = &pdev->dev; +@@ -1623,15 +1623,15 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + + mutex_init(&qmp->phy_mutex); + +- ret = qcom_qmp_phy_clk_init(dev, cfg); ++ ret = qcom_qmp_phy_pcie_msm8996_clk_init(dev, cfg); + if (ret) + return ret; + +- ret = qcom_qmp_phy_reset_init(dev, cfg); ++ ret = qcom_qmp_phy_pcie_msm8996_reset_init(dev, cfg); + if (ret) + return ret; + +- ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ ret = qcom_qmp_phy_pcie_msm8996_vreg_init(dev, cfg); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get regulator supplies: %d\n", +@@ -1667,7 +1667,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + } + + /* Create per-lane phy */ +- ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ ret = qcom_qmp_phy_pcie_msm8996_create(dev, child, id, serdes, cfg); + if (ret) { + dev_err(dev, "failed to create lane%d phy, %d\n", + id, ret); +@@ -1710,16 +1710,16 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + return ret; + } + +-static struct platform_driver qcom_qmp_phy_driver = { +- .probe = qcom_qmp_phy_probe, ++static struct platform_driver qcom_qmp_phy_pcie_msm8996_driver = { ++ .probe = qcom_qmp_phy_pcie_msm8996_probe, + .driver = { + .name = "qcom-qmp-msm8996-pcie-phy", +- .pm = &qcom_qmp_phy_pm_ops, +- .of_match_table = qcom_qmp_phy_of_match_table, ++ .pm = &qcom_qmp_phy_pcie_msm8996_pm_ops, ++ .of_match_table = qcom_qmp_phy_pcie_msm8996_of_match_table, + }, + }; + +-module_platform_driver(qcom_qmp_phy_driver); ++module_platform_driver(qcom_qmp_phy_pcie_msm8996_driver); + + MODULE_AUTHOR("Vivek Gautam "); + MODULE_DESCRIPTION("Qualcomm QMP MSM8996 PCIe PHY driver"); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-fix-memleak-on-probe-deferral.patch b/queue-5.19/phy-qcom-qmp-pcie-fix-memleak-on-probe-deferral.patch new file mode 100644 index 00000000000..e1b62327779 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-fix-memleak-on-probe-deferral.patch @@ -0,0 +1,97 @@ +From 57a6d32f9ec59f5bbcc4ca48997c0d618e56e6c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:31 +0200 +Subject: phy: qcom-qmp-pcie: fix memleak on probe deferral + +From: Johan Hovold + +[ Upstream commit 4be26f695ffa458b065b7942dbff9393bf0836ea ] + +Switch to using the device-managed of_iomap helper to avoid leaking +memory on probe deferral and driver unbind. + +Note that this helper checks for already reserved regions and may fail +if there are multiple devices claiming the same memory. + +Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-3-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 34 ++++++++++++------------ + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +index 77f861bad8da..7073af57345b 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -5924,17 +5924,17 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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->tx = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(qphy->tx)) ++ return PTR_ERR(qphy->tx); + +- qphy->rx = of_iomap(np, 1); +- if (!qphy->rx) +- return -ENOMEM; ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (IS_ERR(qphy->rx)) ++ return PTR_ERR(qphy->rx); + +- qphy->pcs = of_iomap(np, 2); +- if (!qphy->pcs) +- return -ENOMEM; ++ qphy->pcs = devm_of_iomap(dev, np, 2, NULL); ++ if (IS_ERR(qphy->pcs)) ++ return PTR_ERR(qphy->pcs); + + /* + * If this is a dual-lane PHY, then there should be registers for the +@@ -5943,9 +5943,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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) { ++ qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); ++ qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); ++ if (IS_ERR(qphy->tx2) || IS_ERR(qphy->rx2)) { + dev_warn(dev, + "Underspecified device tree, falling back to legacy register regions\n"); + +@@ -5955,20 +5955,20 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; + + } else { +- qphy->pcs_misc = of_iomap(np, 5); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); + } + + } else { +- qphy->pcs_misc = of_iomap(np, 3); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); + } + +- if (!qphy->pcs_misc && ++ if (IS_ERR(qphy->pcs_misc) && + of_device_is_compatible(dev->of_node, "qcom,ipq6018-qmp-pcie-phy")) + qphy->pcs_misc = qphy->pcs + 0x400; + +- if (!qphy->pcs_misc) { ++ if (IS_ERR(qphy->pcs_misc)) { + if (cfg->pcs_misc_tbl || cfg->pcs_misc_tbl_sec) +- return -EINVAL; ++ return PTR_ERR(qphy->pcs_misc); + } + + /* +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-fix-resource-mapping-for-sdm845-qh.patch b/queue-5.19/phy-qcom-qmp-pcie-fix-resource-mapping-for-sdm845-qh.patch new file mode 100644 index 00000000000..f823afd430f --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-fix-resource-mapping-for-sdm845-qh.patch @@ -0,0 +1,44 @@ +From 29e2136a16b8e2c58a0e414c1a6345e3419b5fd4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 20:25:14 +0300 +Subject: phy: qcom-qmp-pcie: fix resource mapping for SDM845 QHP PHY + +From: Dmitry Baryshkov + +[ Upstream commit 0a40891b83f257b25a2b983758f72f6813f361cb ] + +On SDM845 one of PCIe PHYs (the QHP one) has the same region for TX and +RX registers. Since the commit 4be26f695ffa ("phy: qcom-qmp-pcie: fix +memleak on probe deferral") added checking that resources are not +allocated beforehand, this PHY can not be probed anymore. Fix this by +skipping the map of ->rx resource on the QHP PHY and assign it manually. + +Fixes: 4be26f695ffa ("phy: qcom-qmp-pcie: fix memleak on probe deferral") +Signed-off-by: Dmitry Baryshkov +Reviewed-by: Johan Hovold +Link: https://lore.kernel.org/r/20220926172514.880776-1-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +index 7073af57345b..154712af5410 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -5928,7 +5928,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + if (IS_ERR(qphy->tx)) + return PTR_ERR(qphy->tx); + +- qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (of_device_is_compatible(dev->of_node, "qcom,sdm845-qhp-pcie-phy")) ++ qphy->rx = qphy->tx; ++ else ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); + if (IS_ERR(qphy->rx)) + return PTR_ERR(qphy->rx); + +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-msm8996-cleanup-the-driver.patch b/queue-5.19/phy-qcom-qmp-pcie-msm8996-cleanup-the-driver.patch new file mode 100644 index 00000000000..7b16ab82f23 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-msm8996-cleanup-the-driver.patch @@ -0,0 +1,498 @@ +From 3b828d873fbd03c408add672dbb48fcb8a908793 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:54 +0300 +Subject: phy: qcom-qmp-pcie-msm8996: cleanup the driver + +From: Dmitry Baryshkov + +[ Upstream commit 4856865b0dec88570edfbdf3e9c3b551923c0768 ] + +Remove the conditionals and options that are not used by the MSM8996 +PCIe PHY device. Hardcode has_lane_rst and has_phy_com_ctrl as this is +the case for this PHY. + +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-22-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: 1f69ededf8e8 ("phy: qcom-qmp-pcie-msm8996: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 268 +++--------------- + 1 file changed, 41 insertions(+), 227 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +index 02e5ae7fa213..51da3a3a199e 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -266,22 +266,6 @@ struct qmp_phy_cfg { + 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; +@@ -301,28 +285,11 @@ struct qmp_phy_cfg { + /* 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; + }; + + /** +@@ -334,17 +301,12 @@ struct qmp_phy_combo_cfg { + * @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; +@@ -353,30 +315,18 @@ struct qmp_phy { + 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 +@@ -385,11 +335,9 @@ struct qmp_phy_dp_clks { + * @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; +@@ -399,8 +347,6 @@ struct qcom_qmp { + + struct mutex phy_mutex; + int init_count; +- +- struct reset_control *ufs_reset; + }; + + static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) +@@ -467,8 +413,6 @@ static const struct qmp_phy_cfg msm8996_pciephy_cfg = { + .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, +@@ -512,6 +456,8 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) + void __iomem *serdes = qphy->serdes; + const struct qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; + int serdes_tbl_num = cfg->serdes_tbl_num; ++ void __iomem *status; ++ unsigned int mask, val; + int ret; + + qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); +@@ -519,24 +465,20 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) + qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, + cfg->serdes_tbl_num_sec); + +- 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); ++ 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; ++ 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; +- } ++ 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; +@@ -547,8 +489,6 @@ static int qcom_qmp_phy_pcie_msm8996_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); +@@ -586,41 +526,8 @@ static int qcom_qmp_phy_pcie_msm8996_com_init(struct qmp_phy *qphy) + 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); +- } ++ qphy_setbits(serdes, cfg->regs[QPHY_COM_POWER_DOWN_CONTROL], ++ SW_PWRDN); + + mutex_unlock(&qmp->phy_mutex); + +@@ -650,15 +557,12 @@ static int qcom_qmp_phy_pcie_msm8996_com_exit(struct qmp_phy *qphy) + 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); +- } ++ 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]); +@@ -676,37 +580,9 @@ static int qcom_qmp_phy_pcie_msm8996_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_pcie_msm8996_com_init(qphy); + if (ret) + return ret; +@@ -729,13 +605,11 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + + qcom_qmp_phy_pcie_msm8996_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 = 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); +@@ -751,40 +625,17 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + qcom_qmp_phy_pcie_msm8996_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_pcie_msm8996_configure_lane(qphy->tx2, cfg->regs, +- cfg->tx_tbl, cfg->tx_tbl_num, 2); +- if (cfg->tx_tbl_sec) +- qcom_qmp_phy_pcie_msm8996_configure_lane(qphy->tx2, cfg->regs, +- cfg->tx_tbl_sec, +- cfg->tx_tbl_num_sec, 2); +- } +- + qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 1); + if (cfg->rx_tbl_sec) + qcom_qmp_phy_pcie_msm8996_configure_lane(rx, cfg->regs, + cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); + +- if (cfg->is_dual_lane_phy) { +- qcom_qmp_phy_pcie_msm8996_configure_lane(qphy->rx2, cfg->regs, +- cfg->rx_tbl, cfg->rx_tbl_num, 2); +- if (cfg->rx_tbl_sec) +- qcom_qmp_phy_pcie_msm8996_configure_lane(qphy->rx2, cfg->regs, +- cfg->rx_tbl_sec, +- cfg->rx_tbl_num_sec, 2); +- } +- + qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); + if (cfg->pcs_tbl_sec) + qcom_qmp_phy_pcie_msm8996_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_pcie_msm8996_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, + cfg->pcs_misc_tbl_num); + if (cfg->pcs_misc_tbl_sec) +@@ -801,8 +652,8 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); + + /* Pull PHY out of reset state */ +- if (!cfg->no_pcs_sw_reset) +- qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], 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); + +@@ -822,8 +673,7 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + err_disable_pipe_clk: + clk_disable_unprepare(qphy->pipe_clk); + err_reset_lane: +- if (cfg->has_lane_rst) +- reset_control_assert(qphy->lane_rst); ++ reset_control_assert(qphy->lane_rst); + + return ret; + } +@@ -836,8 +686,7 @@ static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) + clk_disable_unprepare(qphy->pipe_clk); + + /* PHY reset */ +- if (!cfg->no_pcs_sw_reset) +- qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], 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); +@@ -857,10 +706,8 @@ static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) + static int qcom_qmp_phy_pcie_msm8996_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); ++ reset_control_assert(qphy->lane_rst); + + qcom_qmp_phy_pcie_msm8996_com_exit(qphy); + +@@ -1065,31 +912,7 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, + 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); +- } ++ qphy->pcs_misc = of_iomap(np, 3); + + if (!qphy->pcs_misc) + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); +@@ -1117,18 +940,16 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, + } + + /* 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; ++ 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; + + generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_msm8996_ops); + if (IS_ERR(generic_phy)) { +@@ -1183,13 +1004,6 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + if (IS_ERR(serdes)) + return PTR_ERR(serdes); + +- /* per PHY dp_com; if PHY has dp_com control block */ +- if (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); +- } +- + expected_phys = cfg->nlanes; + + mutex_init(&qmp->phy_mutex); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-all-compatibles-excep.patch b/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-all-compatibles-excep.patch new file mode 100644 index 00000000000..491c1861cec --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-all-compatibles-excep.patch @@ -0,0 +1,5162 @@ +From dc16242e5bc1317afb604f62f473936adba6fc37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:36 +0300 +Subject: phy: qcom-qmp-pcie-msm8996: drop all compatibles except + msm8996-pcie-phy + +From: Dmitry Baryshkov + +[ Upstream commit 9fc8fa59ef1038714a9b86259f515373a7380169 ] + +Drop support for all compatibles from the new qmp-pcie driver except the +qcom,msm8996-qmp-pcie-phy. This PHY differs from the rest of PCIe PHYs, +so it warrants a separate device driver. + +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-4-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: 1f69ededf8e8 ("phy: qcom-qmp-pcie-msm8996: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 5024 +---------------- + 1 file changed, 200 insertions(+), 4824 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +index c7309e981bfb..260e534b5607 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -141,18 +141,6 @@ enum qphy_reg_layout { + 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, +@@ -169,176 +157,6 @@ static const unsigned int pciephy_regs_layout[QPHY_LAYOUT_SIZE] = { + [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), +@@ -417,4078 +235,243 @@ static const struct qmp_phy_init_tbl msm8996_pcie_pcs_tbl[] = { + 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), ++struct qmp_phy; + +- 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), ++/* 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; + +- QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG4, 0x00), +-}; ++ /* 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; + +-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), +-}; ++ /* 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; + +-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), +-}; ++ /* 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); + +-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), +-}; ++ /* 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; + +-static const struct qmp_phy_init_tbl sdm845_qhp_pcie_rx_tbl[] = { +-}; ++ /* array of registers with different offsets */ ++ const unsigned int *regs; + +-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), +-}; ++ 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; + +-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), +-}; ++ /* 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; + +-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), +-}; ++ /* 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; + +-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), ++ /* true, if PCS block has no separate SW_RESET register */ ++ bool no_pcs_sw_reset; + }; + +-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), ++struct qmp_phy_combo_cfg { ++ const struct qmp_phy_cfg *usb_cfg; ++ const struct qmp_phy_cfg *dp_cfg; + }; + +-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 */ ++/** ++ * 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; + }; + +-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, ++struct qmp_phy_dp_clks { ++ struct qmp_phy *qphy; ++ struct clk_hw dp_link_hw; ++ struct clk_hw dp_pixel_hw; ++}; + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, ++/** ++ * 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; + +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, +-}; ++ struct clk_bulk_data *clks; ++ struct reset_control **resets; ++ struct regulator_bulk_data *vregs; + +-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, ++ struct qmp_phy **phys; + +- .start_ctrl = SERDES_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, ++ struct mutex phy_mutex; ++ int init_count; + +- .is_dual_lane_phy = true, ++ struct reset_control *ufs_reset; + }; + +-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, ++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, ++ reg = readl(base + offset); ++ reg |= val; ++ writel(reg, base + offset); + +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++ /* ensure that above write is through */ ++ readl(base + offset); ++} + +- .has_phy_dp_com_ctrl = true, +- .is_dual_lane_phy = true, +-}; ++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) ++{ ++ u32 reg; + +-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, ++ reg = readl(base + offset); ++ reg &= ~val; ++ writel(reg, base + offset); + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, +- .phy_status = PHYSTATUS, ++ /* ensure that above write is through */ ++ readl(base + offset); ++} + +- .has_pwrdn_delay = true, +- .pwrdn_delay_min = POWER_DOWN_DELAY_US_MIN, +- .pwrdn_delay_max = POWER_DOWN_DELAY_US_MAX, ++/* list of clocks required by phy */ ++static const char * const msm8996_phy_clk_l[] = { ++ "aux", "cfg_ahb", "ref", + }; + +-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, ++/* list of resets */ ++static const char * const msm8996_pciephy_reset_l[] = { ++ "phy", "common", "cfg", + }; + +-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 */ ++/* list of regulators */ ++static const char * const qmp_phy_vreg_l[] = { ++ "vdda-phy", "vdda-pll", + }; + +-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 msm8996_pciephy_cfg = { ++ .type = PHY_TYPE_PCIE, ++ .nlanes = 3, + +-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), ++ .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 = qcm2290_usb3phy_regs_layout, ++ .regs = pciephy_regs_layout, + +- .start_ctrl = SERDES_START | PCS_START, +- .pwrdn_ctrl = SW_PWRDN, ++ .start_ctrl = PCS_START | PLL_READY_GATE_EN, ++ .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, ++ .mask_com_pcs_ready = PCS_READY, + .phy_status = PHYSTATUS, + +- .is_dual_lane_phy = true, ++ .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 void qcom_qmp_phy_configure_lane(void __iomem *base, +@@ -4589,457 +572,10 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) + 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; +@@ -6021,161 +1557,13 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + + 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) +@@ -6206,20 +1594,8 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + + /* 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 */ +- } ++ if (!cfg) ++ return -EINVAL; + + /* per PHY serdes; usually located at base address */ + usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); +@@ -6337,7 +1713,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + static struct platform_driver qcom_qmp_phy_driver = { + .probe = qcom_qmp_phy_probe, + .driver = { +- .name = "qcom-qmp-phy", ++ .name = "qcom-qmp-msm8996-pcie-phy", + .pm = &qcom_qmp_phy_pm_ops, + .of_match_table = qcom_qmp_phy_of_match_table, + }, +@@ -6346,5 +1722,5 @@ static struct platform_driver qcom_qmp_phy_driver = { + module_platform_driver(qcom_qmp_phy_driver); + + MODULE_AUTHOR("Vivek Gautam "); +-MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_DESCRIPTION("Qualcomm QMP MSM8996 PCIe PHY driver"); + MODULE_LICENSE("GPL v2"); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-support-for-non-pcie-.patch b/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-support-for-non-pcie-.patch new file mode 100644 index 00000000000..294037e1420 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-msm8996-drop-support-for-non-pcie-.patch @@ -0,0 +1,712 @@ +From 371db0d7df1cd9161af64e3a99e49c1b2502d130 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:49 +0300 +Subject: phy: qcom-qmp-pcie-msm8996: drop support for non-PCIe PHY types + +From: Dmitry Baryshkov + +[ Upstream commit f575ac2d64e7cedb2d70acd5baa359da216cf718 ] + +Drop remaining support for PHY types other than PCIe. + +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-17-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: 1f69ededf8e8 ("phy: qcom-qmp-pcie-msm8996: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 532 ++---------------- + 1 file changed, 43 insertions(+), 489 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +index 1741a5675f9a..02e5ae7fa213 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -510,7 +510,6 @@ static int qcom_qmp_phy_pcie_msm8996_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; +@@ -520,35 +519,6 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) + qcom_qmp_phy_pcie_msm8996_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_pcie_msm8996_configure(serdes, cfg->regs, +- cfg->serdes_tbl_rbr, +- cfg->serdes_tbl_rbr_num); +- break; +- case 2700: +- qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, +- cfg->serdes_tbl_hbr, +- cfg->serdes_tbl_hbr_num); +- break; +- case 5400: +- qcom_qmp_phy_pcie_msm8996_configure(serdes, cfg->regs, +- cfg->serdes_tbl_hbr2, +- cfg->serdes_tbl_hbr2_num); +- break; +- case 8100: +- qcom_qmp_phy_pcie_msm8996_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; +@@ -572,36 +542,6 @@ static int qcom_qmp_phy_pcie_msm8996_serdes_init(struct qmp_phy *qphy) + return 0; + } + +-/* +- * We need to calibrate the aux setting here as many times +- * as the caller tries +- */ +-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_pcie_msm8996_com_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; +@@ -771,9 +711,6 @@ static int qcom_qmp_phy_pcie_msm8996_init(struct phy *phy) + if (ret) + return ret; + +- if (cfg->type == PHY_TYPE_DP) +- cfg->dp_aux_init(qphy); +- + return 0; + } + +@@ -824,10 +761,6 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + 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_pcie_msm8996_configure_lane(rx, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 1); + if (cfg->rx_tbl_sec) +@@ -843,15 +776,10 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + 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_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); +- if (cfg->pcs_tbl_sec) +- qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, +- cfg->pcs_tbl_num_sec); +- } ++ qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_pcie_msm8996_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); + + ret = reset_control_deassert(qmp->ufs_reset); + if (ret) +@@ -867,36 +795,28 @@ static int qcom_qmp_phy_pcie_msm8996_power_on(struct phy *phy) + * 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); ++ 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; +- } ++ /* 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); + +- 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; +- } ++ 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: +@@ -915,25 +835,20 @@ static int qcom_qmp_phy_pcie_msm8996_power_off(struct phy *phy) + + 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); ++ /* 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); ++ /* 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); +- } ++ /* 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; +@@ -987,112 +902,6 @@ static int qcom_qmp_phy_pcie_msm8996_set_mode(struct phy *phy, + return 0; + } + +-static void qcom_qmp_phy_pcie_msm8996_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_pcie_msm8996_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_pcie_msm8996_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_pcie_msm8996_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_pcie_msm8996_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_pcie_msm8996_disable_autonomous_mode(qphy); +- +- return 0; +-} +- + static int qcom_qmp_phy_pcie_msm8996_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); +@@ -1210,223 +1019,13 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) + 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_pcie_msm8996_gen_ops = { ++static const struct phy_ops qcom_qmp_phy_pcie_msm8996_ops = { + .init = qcom_qmp_phy_pcie_msm8996_enable, + .exit = qcom_qmp_phy_pcie_msm8996_disable, + .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, + .owner = THIS_MODULE, + }; + +-static const struct phy_ops qcom_qmp_phy_pcie_msm8996_dp_ops = { +- .init = qcom_qmp_phy_pcie_msm8996_init, +- .configure = qcom_qmp_dp_phy_configure, +- .power_on = qcom_qmp_phy_pcie_msm8996_power_on, +- .calibrate = qcom_qmp_dp_phy_calibrate, +- .power_off = qcom_qmp_phy_pcie_msm8996_power_off, +- .exit = qcom_qmp_phy_pcie_msm8996_exit, +- .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, +- .owner = THIS_MODULE, +-}; +- +-static const struct phy_ops qcom_qmp_pcie_ufs_ops = { +- .power_on = qcom_qmp_phy_pcie_msm8996_enable, +- .power_off = qcom_qmp_phy_pcie_msm8996_disable, +- .set_mode = qcom_qmp_phy_pcie_msm8996_set_mode, +- .owner = THIS_MODULE, +-}; +- + static void qcom_qmp_reset_control_put(void *data) + { + reset_control_put(data); +@@ -1439,7 +1038,6 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, + 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; + +@@ -1532,14 +1130,7 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, + 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_pcie_msm8996_dp_ops; +- else +- ops = &qcom_qmp_phy_pcie_msm8996_gen_ops; +- +- generic_phy = devm_phy_create(dev, np, ops); ++ generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_pcie_msm8996_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + dev_err(dev, "failed to create qphy %d\n", ret); +@@ -1564,11 +1155,6 @@ static const struct of_device_id qcom_qmp_phy_pcie_msm8996_of_match_table[] = { + }; + MODULE_DEVICE_TABLE(of, qcom_qmp_phy_pcie_msm8996_of_match_table); + +-static const struct dev_pm_ops qcom_qmp_phy_pcie_msm8996_pm_ops = { +- SET_RUNTIME_PM_OPS(qcom_qmp_phy_pcie_msm8996_runtime_suspend, +- qcom_qmp_phy_pcie_msm8996_runtime_resume, NULL) +-}; +- + static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + { + struct qcom_qmp *qmp; +@@ -1576,12 +1162,7 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + 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; + +@@ -1598,28 +1179,18 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + return -EINVAL; + + /* per PHY serdes; usually located at base address */ +- usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ 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) { ++ if (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; +- } ++ expected_phys = cfg->nlanes; + + mutex_init(&qmp->phy_mutex); + +@@ -1658,14 +1229,6 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + + 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_pcie_msm8996_create(dev, child, id, serdes, cfg); + if (ret) { +@@ -1678,21 +1241,13 @@ static int qcom_qmp_phy_pcie_msm8996_probe(struct platform_device *pdev) + * 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; +- } ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; + } ++ + id++; + } + +@@ -1714,7 +1269,6 @@ static struct platform_driver qcom_qmp_phy_pcie_msm8996_driver = { + .probe = qcom_qmp_phy_pcie_msm8996_probe, + .driver = { + .name = "qcom-qmp-msm8996-pcie-phy", +- .pm = &qcom_qmp_phy_pcie_msm8996_pm_ops, + .of_match_table = qcom_qmp_phy_pcie_msm8996_of_match_table, + }, + }; +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-msm8996-fix-memleak-on-probe-defer.patch b/queue-5.19/phy-qcom-qmp-pcie-msm8996-fix-memleak-on-probe-defer.patch new file mode 100644 index 00000000000..1e9a4d5a775 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-msm8996-fix-memleak-on-probe-defer.patch @@ -0,0 +1,64 @@ +From 9a9dcc3b4ba4c15bd9de5303f4b8a98253b7b377 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:32 +0200 +Subject: phy: qcom-qmp-pcie-msm8996: fix memleak on probe deferral + +From: Johan Hovold + +[ Upstream commit 1f69ededf8e80c42352e7f1c165a003614de9cc2 ] + +Switch to using the device-managed of_iomap helper to avoid leaking +memory on probe deferral and driver unbind. + +Note that this helper checks for already reserved regions and may fail +if there are multiple devices claiming the same memory. + +Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-4-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + .../phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c | 23 +++++++++---------- + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +index 51da3a3a199e..9caad14aacde 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +@@ -900,21 +900,20 @@ int qcom_qmp_phy_pcie_msm8996_create(struct device *dev, struct device_node *np, + * 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->tx = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(qphy->tx)) ++ return PTR_ERR(qphy->tx); + +- qphy->pcs = of_iomap(np, 2); +- if (!qphy->pcs) +- return -ENOMEM; ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (IS_ERR(qphy->rx)) ++ return PTR_ERR(qphy->rx); + +- qphy->pcs_misc = of_iomap(np, 3); ++ qphy->pcs = devm_of_iomap(dev, np, 2, NULL); ++ if (IS_ERR(qphy->pcs)) ++ return PTR_ERR(qphy->pcs); + +- if (!qphy->pcs_misc) ++ qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); ++ if (IS_ERR(qphy->pcs_misc)) + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + + /* +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-pcie-split-pcs_misc-region-for-ipq6018-.patch b/queue-5.19/phy-qcom-qmp-pcie-split-pcs_misc-region-for-ipq6018-.patch new file mode 100644 index 00000000000..08942fded3d --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-pcie-split-pcs_misc-region-for-ipq6018-.patch @@ -0,0 +1,102 @@ +From 471b3d6c110674e8322d72eedb0f7065e6364d5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Jul 2022 12:42:56 +0300 +Subject: phy: qcom-qmp-pcie: split pcs_misc region for ipq6018 pcie gen3 + +From: Dmitry Baryshkov + +[ Upstream commit af6643242d3ac9c90674c5ba8dbddb01ffc37f29 ] + +Follow the example of other PCIe PHYs and use separate pcs_misc region +to access PCS_PCIE_* resources. + +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220705094320.1313312-5-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: ecd5507e72ea ("phy: qcom-qmp-pcie: add pcs_misc sanity check") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 9 +++++++ + drivers/phy/qualcomm/phy-qcom-qmp.h | 32 ++++++++++++------------ + 2 files changed, 25 insertions(+), 16 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +index c7309e981bfb..38fd0c5c3797 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +@@ -735,6 +735,9 @@ static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_tbl[] = { + 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), ++}; ++ ++static const struct qmp_phy_init_tbl ipq6018_pcie_pcs_misc_tbl[] = { + 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), +@@ -3549,6 +3552,8 @@ static const struct qmp_phy_cfg ipq6018_pciephy_cfg = { + .rx_tbl_num = ARRAY_SIZE(ipq6018_pcie_rx_tbl), + .pcs_tbl = ipq6018_pcie_pcs_tbl, + .pcs_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_tbl), ++ .pcs_misc_tbl = ipq6018_pcie_pcs_misc_tbl, ++ .pcs_misc_tbl_num = ARRAY_SIZE(ipq6018_pcie_pcs_misc_tbl), + .clk_list = ipq8074_pciephy_clk_l, + .num_clks = ARRAY_SIZE(ipq8074_pciephy_clk_l), + .reset_list = ipq8074_pciephy_reset_l, +@@ -5957,6 +5962,10 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + qphy->pcs_misc = of_iomap(np, 3); + } + ++ if (!qphy->pcs_misc && ++ of_device_is_compatible(dev->of_node, "qcom,ipq6018-qmp-pcie-phy")) ++ qphy->pcs_misc = qphy->pcs + 0x400; ++ + if (!qphy->pcs_misc) + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h +index b9a91520439c..8b7a61f0ea2f 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp.h ++++ b/drivers/phy/qualcomm/phy-qcom-qmp.h +@@ -121,22 +121,22 @@ + + /* QMP V2 PHY for PCIE gen3 ports - PCS Misc registers */ + +-#define PCS_PCIE_POWER_STATE_CONFIG2 0x40c +-#define PCS_PCIE_POWER_STATE_CONFIG4 0x414 +-#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x41c +-#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x440 +-#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x444 +-#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x448 +-#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x44c +-#define PCS_PCIE_OSC_DTCT_CONFIG2 0x45c +-#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x478 +-#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x480 +-#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x484 +-#define PCS_PCIE_OSC_DTCT_ACTIONS 0x490 +-#define PCS_PCIE_EQ_CONFIG1 0x4a0 +-#define PCS_PCIE_EQ_CONFIG2 0x4a4 +-#define PCS_PCIE_PRESET_P10_PRE 0x4bc +-#define PCS_PCIE_PRESET_P10_POST 0x4e0 ++#define PCS_PCIE_POWER_STATE_CONFIG2 0x00c ++#define PCS_PCIE_POWER_STATE_CONFIG4 0x014 ++#define PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x01c ++#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x040 ++#define PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x044 ++#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x048 ++#define PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x04c ++#define PCS_PCIE_OSC_DTCT_CONFIG2 0x05c ++#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x078 ++#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x080 ++#define PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x084 ++#define PCS_PCIE_OSC_DTCT_ACTIONS 0x090 ++#define PCS_PCIE_EQ_CONFIG1 0x0a0 ++#define PCS_PCIE_EQ_CONFIG2 0x0a4 ++#define PCS_PCIE_PRESET_P10_PRE 0x0bc ++#define PCS_PCIE_PRESET_P10_POST 0x0e0 + + /* Only for QMP V2 PHY - QSERDES COM registers */ + #define QSERDES_COM_BG_TIMER 0x00c +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-ufs-fix-memleak-on-probe-deferral.patch b/queue-5.19/phy-qcom-qmp-ufs-fix-memleak-on-probe-deferral.patch new file mode 100644 index 00000000000..11716967489 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-ufs-fix-memleak-on-probe-deferral.patch @@ -0,0 +1,89 @@ +From 0808e3bf5c7202e8d4bd37f3529719a26de2638b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:34 +0200 +Subject: phy: qcom-qmp-ufs: fix memleak on probe deferral + +From: Johan Hovold + +[ Upstream commit ef74a97f0df8758efe4476b4645961286aa86f0d ] + +Switch to using the device-managed of_iomap helper to avoid leaking +memory on probe deferral and driver unbind. + +Note that this helper checks for already reserved regions and may fail +if there are multiple devices claiming the same memory. + +Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-6-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-ufs.c | 30 ++++++++++++------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +index c7309e981bfb..66a89fbacb33 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-ufs.c +@@ -5919,17 +5919,17 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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->tx = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(qphy->tx)) ++ return PTR_ERR(qphy->tx); + +- qphy->rx = of_iomap(np, 1); +- if (!qphy->rx) +- return -ENOMEM; ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (IS_ERR(qphy->rx)) ++ return PTR_ERR(qphy->rx); + +- qphy->pcs = of_iomap(np, 2); +- if (!qphy->pcs) +- return -ENOMEM; ++ qphy->pcs = devm_of_iomap(dev, np, 2, NULL); ++ if (IS_ERR(qphy->pcs)) ++ return PTR_ERR(qphy->pcs); + + /* + * If this is a dual-lane PHY, then there should be registers for the +@@ -5938,9 +5938,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + * 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) { ++ qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); ++ qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); ++ if (IS_ERR(qphy->tx2) || IS_ERR(qphy->rx2)) { + dev_warn(dev, + "Underspecified device tree, falling back to legacy register regions\n"); + +@@ -5950,14 +5950,14 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; + + } else { +- qphy->pcs_misc = of_iomap(np, 5); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); + } + + } else { +- qphy->pcs_misc = of_iomap(np, 3); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); + } + +- if (!qphy->pcs_misc) ++ if (IS_ERR(qphy->pcs_misc)) + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + + /* +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-change-symbol-prefix-to-qcom_qmp_ph.patch b/queue-5.19/phy-qcom-qmp-usb-change-symbol-prefix-to-qcom_qmp_ph.patch new file mode 100644 index 00000000000..c5a31418bbf --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-change-symbol-prefix-to-qcom_qmp_ph.patch @@ -0,0 +1,504 @@ +From 415cfc3be11a04f19005462d879e525f4697780c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:44 +0300 +Subject: phy: qcom-qmp-usb: change symbol prefix to qcom_qmp_phy_usb + +From: Dmitry Baryshkov + +[ Upstream commit 09b492a379402395f646c6db2e16cdac1fc2229d ] + +Change all symbol names to start with qcom_qmp_phy_usb_ rather than old +qcom_qmp_phy_ + +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-12-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 158 ++++++++++++------------ + 1 file changed, 79 insertions(+), 79 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index e147182afea7..2ae13b4485b6 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -2023,7 +2023,7 @@ static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = { + .is_dual_lane_phy = true, + }; + +-static void qcom_qmp_phy_configure_lane(void __iomem *base, ++static void qcom_qmp_phy_usb_configure_lane(void __iomem *base, + const unsigned int *regs, + const struct qmp_phy_init_tbl tbl[], + int num, +@@ -2046,15 +2046,15 @@ static void qcom_qmp_phy_configure_lane(void __iomem *base, + } + } + +-static void qcom_qmp_phy_configure(void __iomem *base, ++static void qcom_qmp_phy_usb_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); ++ qcom_qmp_phy_usb_configure_lane(base, regs, tbl, num, 0xff); + } + +-static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) ++static int qcom_qmp_phy_usb_serdes_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -2064,30 +2064,30 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) + int serdes_tbl_num = cfg->serdes_tbl_num; + int ret; + +- qcom_qmp_phy_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_configure(serdes, cfg->regs, + cfg->serdes_tbl_rbr, + cfg->serdes_tbl_rbr_num); + break; + case 2700: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_usb_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr, + cfg->serdes_tbl_hbr_num); + break; + case 5400: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_usb_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr2, + cfg->serdes_tbl_hbr2_num); + break; + case 8100: +- qcom_qmp_phy_configure(serdes, cfg->regs, ++ qcom_qmp_phy_usb_configure(serdes, cfg->regs, + cfg->serdes_tbl_hbr3, + cfg->serdes_tbl_hbr3_num); + break; +@@ -2147,7 +2147,7 @@ static int qcom_qmp_dp_phy_calibrate(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) ++static int qcom_qmp_phy_usb_com_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -2242,7 +2242,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy) + return ret; + } + +-static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) ++static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -2277,7 +2277,7 @@ static int qcom_qmp_phy_com_exit(struct qmp_phy *qphy) + return 0; + } + +-static int qcom_qmp_phy_init(struct phy *phy) ++static int qcom_qmp_phy_usb_init(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; +@@ -2312,7 +2312,7 @@ static int qcom_qmp_phy_init(struct phy *phy) + return ret; + } + +- ret = qcom_qmp_phy_com_init(qphy); ++ ret = qcom_qmp_phy_usb_com_init(qphy); + if (ret) + return ret; + +@@ -2322,7 +2322,7 @@ static int qcom_qmp_phy_init(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_power_on(struct phy *phy) ++static int qcom_qmp_phy_usb_power_on(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + struct qcom_qmp *qmp = qphy->qmp; +@@ -2335,7 +2335,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + unsigned int mask, val, ready; + int ret; + +- qcom_qmp_phy_serdes_init(qphy); ++ qcom_qmp_phy_usb_serdes_init(qphy); + + if (cfg->has_lane_rst) { + ret = reset_control_deassert(qphy->lane_rst); +@@ -2353,18 +2353,18 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + } + + /* Tx, Rx, and PCS configurations */ +- qcom_qmp_phy_configure_lane(tx, cfg->regs, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_configure_lane(qphy->tx2, cfg->regs, + cfg->tx_tbl_sec, + cfg->tx_tbl_num_sec, 2); + } +@@ -2373,17 +2373,17 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + if (cfg->type == PHY_TYPE_DP) + cfg->configure_dp_tx(qphy); + +- qcom_qmp_phy_configure_lane(rx, cfg->regs, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_configure_lane(qphy->rx2, cfg->regs, + cfg->rx_tbl_sec, + cfg->rx_tbl_num_sec, 2); + } +@@ -2392,9 +2392,9 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + 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); ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, + cfg->pcs_tbl_num_sec); + } + +@@ -2402,10 +2402,10 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + if (ret) + goto err_disable_pipe_clk; + +- qcom_qmp_phy_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, ++ qcom_qmp_phy_usb_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, ++ qcom_qmp_phy_usb_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, + cfg->pcs_misc_tbl_num_sec); + + /* +@@ -2453,7 +2453,7 @@ static int qcom_qmp_phy_power_on(struct phy *phy) + return ret; + } + +-static int qcom_qmp_phy_power_off(struct phy *phy) ++static int qcom_qmp_phy_usb_power_off(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -2484,7 +2484,7 @@ static int qcom_qmp_phy_power_off(struct phy *phy) + return 0; + } + +-static int qcom_qmp_phy_exit(struct phy *phy) ++static int qcom_qmp_phy_usb_exit(struct phy *phy) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); + const struct qmp_phy_cfg *cfg = qphy->cfg; +@@ -2492,37 +2492,37 @@ static int qcom_qmp_phy_exit(struct phy *phy) + if (cfg->has_lane_rst) + reset_control_assert(qphy->lane_rst); + +- qcom_qmp_phy_com_exit(qphy); ++ qcom_qmp_phy_usb_com_exit(qphy); + + return 0; + } + +-static int qcom_qmp_phy_enable(struct phy *phy) ++static int qcom_qmp_phy_usb_enable(struct phy *phy) + { + int ret; + +- ret = qcom_qmp_phy_init(phy); ++ ret = qcom_qmp_phy_usb_init(phy); + if (ret) + return ret; + +- ret = qcom_qmp_phy_power_on(phy); ++ ret = qcom_qmp_phy_usb_power_on(phy); + if (ret) +- qcom_qmp_phy_exit(phy); ++ qcom_qmp_phy_usb_exit(phy); + + return ret; + } + +-static int qcom_qmp_phy_disable(struct phy *phy) ++static int qcom_qmp_phy_usb_disable(struct phy *phy) + { + int ret; + +- ret = qcom_qmp_phy_power_off(phy); ++ ret = qcom_qmp_phy_usb_power_off(phy); + if (ret) + return ret; +- return qcom_qmp_phy_exit(phy); ++ return qcom_qmp_phy_usb_exit(phy); + } + +-static int qcom_qmp_phy_set_mode(struct phy *phy, ++static int qcom_qmp_phy_usb_set_mode(struct phy *phy, + enum phy_mode mode, int submode) + { + struct qmp_phy *qphy = phy_get_drvdata(phy); +@@ -2532,7 +2532,7 @@ static int qcom_qmp_phy_set_mode(struct phy *phy, + return 0; + } + +-static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) ++static void qcom_qmp_phy_usb_enable_autonomous_mode(struct qmp_phy *qphy) + { + const struct qmp_phy_cfg *cfg = qphy->cfg; + void __iomem *pcs = qphy->pcs; +@@ -2561,7 +2561,7 @@ static void qcom_qmp_phy_enable_autonomous_mode(struct qmp_phy *qphy) + qphy_clrbits(pcs_misc, QPHY_V3_PCS_MISC_CLAMP_ENABLE, CLAMP_EN); + } + +-static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) ++static void qcom_qmp_phy_usb_disable_autonomous_mode(struct qmp_phy *qphy) + { + const struct qmp_phy_cfg *cfg = qphy->cfg; + void __iomem *pcs = qphy->pcs; +@@ -2579,7 +2579,7 @@ static void qcom_qmp_phy_disable_autonomous_mode(struct qmp_phy *qphy) + 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) ++static int __maybe_unused qcom_qmp_phy_usb_runtime_suspend(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct qmp_phy *qphy = qmp->phys[0]; +@@ -2596,7 +2596,7 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + return 0; + } + +- qcom_qmp_phy_enable_autonomous_mode(qphy); ++ qcom_qmp_phy_usb_enable_autonomous_mode(qphy); + + clk_disable_unprepare(qphy->pipe_clk); + clk_bulk_disable_unprepare(cfg->num_clks, qmp->clks); +@@ -2604,7 +2604,7 @@ static int __maybe_unused qcom_qmp_phy_runtime_suspend(struct device *dev) + return 0; + } + +-static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) ++static int __maybe_unused qcom_qmp_phy_usb_runtime_resume(struct device *dev) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct qmp_phy *qphy = qmp->phys[0]; +@@ -2633,12 +2633,12 @@ static int __maybe_unused qcom_qmp_phy_runtime_resume(struct device *dev) + return ret; + } + +- qcom_qmp_phy_disable_autonomous_mode(qphy); ++ qcom_qmp_phy_usb_disable_autonomous_mode(qphy); + + return 0; + } + +-static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++static int qcom_qmp_phy_usb_vreg_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int num = cfg->num_vregs; +@@ -2654,7 +2654,7 @@ static int qcom_qmp_phy_vreg_init(struct device *dev, const struct qmp_phy_cfg * + 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) ++static int qcom_qmp_phy_usb_reset_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int i; +@@ -2679,7 +2679,7 @@ static int qcom_qmp_phy_reset_init(struct device *dev, const struct qmp_phy_cfg + return 0; + } + +-static int qcom_qmp_phy_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) ++static int qcom_qmp_phy_usb_clk_init(struct device *dev, const struct qmp_phy_cfg *cfg) + { + struct qcom_qmp *qmp = dev_get_drvdata(dev); + int num = cfg->num_clks; +@@ -2947,28 +2947,28 @@ static int phy_dp_clks_register(struct qcom_qmp *qmp, struct qmp_phy *qphy, + 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, ++static const struct phy_ops qcom_qmp_phy_usb_gen_ops = { ++ .init = qcom_qmp_phy_usb_enable, ++ .exit = qcom_qmp_phy_usb_disable, ++ .set_mode = qcom_qmp_phy_usb_set_mode, + .owner = THIS_MODULE, + }; + +-static const struct phy_ops qcom_qmp_phy_dp_ops = { +- .init = qcom_qmp_phy_init, ++static const struct phy_ops qcom_qmp_phy_usb_dp_ops = { ++ .init = qcom_qmp_phy_usb_init, + .configure = qcom_qmp_dp_phy_configure, +- .power_on = qcom_qmp_phy_power_on, ++ .power_on = qcom_qmp_phy_usb_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, ++ .power_off = qcom_qmp_phy_usb_power_off, ++ .exit = qcom_qmp_phy_usb_exit, ++ .set_mode = qcom_qmp_phy_usb_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, ++ .power_on = qcom_qmp_phy_usb_enable, ++ .power_off = qcom_qmp_phy_usb_disable, ++ .set_mode = qcom_qmp_phy_usb_set_mode, + .owner = THIS_MODULE, + }; + +@@ -2978,7 +2978,7 @@ static void qcom_qmp_reset_control_put(void *data) + } + + static +-int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, ++int qcom_qmp_phy_usb_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); +@@ -3080,9 +3080,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + 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; ++ ops = &qcom_qmp_phy_usb_dp_ops; + else +- ops = &qcom_qmp_phy_gen_ops; ++ ops = &qcom_qmp_phy_usb_gen_ops; + + generic_phy = devm_phy_create(dev, np, ops); + if (IS_ERR(generic_phy)) { +@@ -3100,7 +3100,7 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id, + return 0; + } + +-static const struct of_device_id qcom_qmp_phy_of_match_table[] = { ++static const struct of_device_id qcom_qmp_phy_usb_of_match_table[] = { + { + .compatible = "qcom,ipq8074-qmp-usb3-phy", + .data = &ipq8074_usb3phy_cfg, +@@ -3158,14 +3158,14 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { + }, + { }, + }; +-MODULE_DEVICE_TABLE(of, qcom_qmp_phy_of_match_table); ++MODULE_DEVICE_TABLE(of, qcom_qmp_phy_usb_of_match_table); + +-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 const struct dev_pm_ops qcom_qmp_phy_usb_pm_ops = { ++ SET_RUNTIME_PM_OPS(qcom_qmp_phy_usb_runtime_suspend, ++ qcom_qmp_phy_usb_runtime_resume, NULL) + }; + +-static int qcom_qmp_phy_probe(struct platform_device *pdev) ++static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) + { + struct qcom_qmp *qmp; + struct device *dev = &pdev->dev; +@@ -3219,15 +3219,15 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + + mutex_init(&qmp->phy_mutex); + +- ret = qcom_qmp_phy_clk_init(dev, cfg); ++ ret = qcom_qmp_phy_usb_clk_init(dev, cfg); + if (ret) + return ret; + +- ret = qcom_qmp_phy_reset_init(dev, cfg); ++ ret = qcom_qmp_phy_usb_reset_init(dev, cfg); + if (ret) + return ret; + +- ret = qcom_qmp_phy_vreg_init(dev, cfg); ++ ret = qcom_qmp_phy_usb_vreg_init(dev, cfg); + if (ret) { + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get regulator supplies: %d\n", +@@ -3265,7 +3265,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + } + + /* Create per-lane phy */ +- ret = qcom_qmp_phy_create(dev, child, id, serdes, cfg); ++ ret = qcom_qmp_phy_usb_create(dev, child, id, serdes, cfg); + if (ret) { + dev_err(dev, "failed to create lane%d phy, %d\n", + id, ret); +@@ -3305,16 +3305,16 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + return ret; + } + +-static struct platform_driver qcom_qmp_phy_driver = { +- .probe = qcom_qmp_phy_probe, ++static struct platform_driver qcom_qmp_phy_usb_driver = { ++ .probe = qcom_qmp_phy_usb_probe, + .driver = { + .name = "qcom-qmp-usb-phy", +- .pm = &qcom_qmp_phy_pm_ops, +- .of_match_table = qcom_qmp_phy_of_match_table, ++ .pm = &qcom_qmp_phy_usb_pm_ops, ++ .of_match_table = qcom_qmp_phy_usb_of_match_table, + }, + }; + +-module_platform_driver(qcom_qmp_phy_driver); ++module_platform_driver(qcom_qmp_phy_usb_driver); + + MODULE_AUTHOR("Vivek Gautam "); + MODULE_DESCRIPTION("Qualcomm QMP USB PHY driver"); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-clean-up-pipe-clock-handling.patch b/queue-5.19/phy-qcom-qmp-usb-clean-up-pipe-clock-handling.patch new file mode 100644 index 00000000000..ba60ac7ea1f --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-clean-up-pipe-clock-handling.patch @@ -0,0 +1,55 @@ +From 470836adcc5d63a5822fb7f66b448622c6d719c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jun 2022 13:33:14 +0200 +Subject: phy: qcom-qmp-usb: clean up pipe clock handling + +From: Johan Hovold + +[ Upstream commit 5d5b7d509ff85675779caeafcffa8086d7094339 ] + +Clean up the pipe clock handling by using dev_err_probe() to handle +probe deferral and dropping the obsolete comment that claimed that the +pipe clock was optional for some other PHY types. + +Signed-off-by: Johan Hovold +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220623113314.29761-4-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 15 ++------------- + 1 file changed, 2 insertions(+), 13 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index 9e752fce638d..687f1a534837 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -2566,22 +2566,11 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + 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)) { +- 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; ++ return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), ++ "failed to get lane%d pipe clock\n", id); + } + + generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_usb_ops); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-cleanup-the-driver.patch b/queue-5.19/phy-qcom-qmp-usb-cleanup-the-driver.patch new file mode 100644 index 00000000000..c789d7600c9 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-cleanup-the-driver.patch @@ -0,0 +1,433 @@ +From 513001e2e6b2735216509359a35f8f4f2590549c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:56 +0300 +Subject: phy: qcom-qmp-usb: cleanup the driver + +From: Dmitry Baryshkov + +[ Upstream commit faf83af5d59498509eb84015453073fd5e85231e ] + +Remove the conditionals and options that are not used by any of USB PHY +devices. + +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-24-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 214 ++---------------------- + 1 file changed, 11 insertions(+), 203 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index 55785dcd47e0..9e752fce638d 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -1359,40 +1359,12 @@ struct qmp_phy_cfg { + /* 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; +@@ -1409,14 +1381,9 @@ struct qmp_phy_cfg { + + 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 */ +@@ -1427,14 +1394,6 @@ struct qmp_phy_cfg { + 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; + }; + + /** +@@ -1452,11 +1411,7 @@ struct qmp_phy_combo_cfg { + * @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; +@@ -1471,17 +1426,7 @@ struct qmp_phy { + 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; + }; + + /** +@@ -1497,7 +1442,6 @@ struct qmp_phy_dp_clks { + * @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; +@@ -1511,8 +1455,6 @@ struct qcom_qmp { + + struct mutex phy_mutex; + int init_count; +- +- struct reset_control *ufs_reset; + }; + + static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) +@@ -2056,37 +1998,12 @@ static void qcom_qmp_phy_usb_configure(void __iomem *base, + + static int qcom_qmp_phy_usb_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 qmp_phy_init_tbl *serdes_tbl = cfg->serdes_tbl; + int serdes_tbl_num = cfg->serdes_tbl_num; +- int ret; + + qcom_qmp_phy_usb_configure(serdes, cfg->regs, serdes_tbl, serdes_tbl_num); +- if (cfg->serdes_tbl_sec) +- qcom_qmp_phy_usb_configure(serdes, cfg->regs, cfg->serdes_tbl_sec, +- cfg->serdes_tbl_num_sec); +- +- 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; + } +@@ -2095,7 +2012,6 @@ static int qcom_qmp_phy_usb_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; +@@ -2158,18 +2074,13 @@ static int qcom_qmp_phy_usb_com_init(struct qmp_phy *qphy) + 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); +- } ++ 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); + +@@ -2190,7 +2101,6 @@ static int qcom_qmp_phy_usb_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); +@@ -2199,16 +2109,6 @@ static int qcom_qmp_phy_usb_com_exit(struct qmp_phy *qphy) + 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]); + +@@ -2225,37 +2125,9 @@ static int qcom_qmp_phy_usb_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_usb_com_init(qphy); + if (ret) + return ret; +@@ -2271,82 +2143,45 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) + 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_usb_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; ++ return ret; + } + + /* Tx, Rx, and PCS configurations */ + qcom_qmp_phy_usb_configure_lane(tx, cfg->regs, + cfg->tx_tbl, cfg->tx_tbl_num, 1); +- if (cfg->tx_tbl_sec) +- qcom_qmp_phy_usb_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_usb_configure_lane(qphy->tx2, cfg->regs, + cfg->tx_tbl, cfg->tx_tbl_num, 2); +- if (cfg->tx_tbl_sec) +- qcom_qmp_phy_usb_configure_lane(qphy->tx2, cfg->regs, +- cfg->tx_tbl_sec, +- cfg->tx_tbl_num_sec, 2); + } + + qcom_qmp_phy_usb_configure_lane(rx, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 1); +- if (cfg->rx_tbl_sec) +- qcom_qmp_phy_usb_configure_lane(rx, cfg->regs, +- cfg->rx_tbl_sec, cfg->rx_tbl_num_sec, 1); + + if (cfg->is_dual_lane_phy) { + qcom_qmp_phy_usb_configure_lane(qphy->rx2, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 2); +- if (cfg->rx_tbl_sec) +- qcom_qmp_phy_usb_configure_lane(qphy->rx2, cfg->regs, +- cfg->rx_tbl_sec, +- cfg->rx_tbl_num_sec, 2); + } + + /* Configure link rate, swing, etc. */ + qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); +- if (cfg->pcs_tbl_sec) +- qcom_qmp_phy_usb_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_usb_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl, +- cfg->pcs_misc_tbl_num); +- if (cfg->pcs_misc_tbl_sec) +- qcom_qmp_phy_usb_configure(pcs_misc, cfg->regs, cfg->pcs_misc_tbl_sec, +- cfg->pcs_misc_tbl_num_sec); + + if (cfg->has_pwrdn_delay) + usleep_range(cfg->pwrdn_delay_min, cfg->pwrdn_delay_max); + + /* Pull PHY out of reset state */ +- if (!cfg->no_pcs_sw_reset) +- qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], 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); + +@@ -2365,9 +2200,6 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) + + 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; + } +@@ -2380,8 +2212,7 @@ static int qcom_qmp_phy_usb_power_off(struct phy *phy) + clk_disable_unprepare(qphy->pipe_clk); + + /* PHY reset */ +- if (!cfg->no_pcs_sw_reset) +- qphy_setbits(qphy->pcs, cfg->regs[QPHY_SW_RESET], 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); +@@ -2401,10 +2232,6 @@ static int qcom_qmp_phy_usb_power_off(struct phy *phy) + static int qcom_qmp_phy_usb_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_usb_com_exit(qphy); + +@@ -2676,11 +2503,6 @@ static const struct phy_ops qcom_qmp_phy_usb_ops = { + .owner = THIS_MODULE, + }; + +-static void qcom_qmp_reset_control_put(void *data) +-{ +- reset_control_put(data); +-} +- + static + int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + void __iomem *serdes, const struct qmp_phy_cfg *cfg) +@@ -2762,20 +2584,6 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + return ret; + } + +- /* 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; +- } +- + generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_usb_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-disable-runtime-pm-on-unbind.patch b/queue-5.19/phy-qcom-qmp-usb-disable-runtime-pm-on-unbind.patch new file mode 100644 index 00000000000..1fb3441f1e1 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-disable-runtime-pm-on-unbind.patch @@ -0,0 +1,53 @@ +From 224ecdb29f72f96899d2c767ac6eb68daf11d8b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 13:07:21 +0200 +Subject: phy: qcom-qmp-usb: disable runtime PM on unbind + +From: Johan Hovold + +[ Upstream commit e57655e66806750785f9121c98a962404d02395b ] + +Make sure to disable runtime PM also on driver unbind. + +Fixes: ac0d239936bd ("phy: qcom-qmp: Add support for runtime PM"). +Signed-off-by: Johan Hovold +Reviewed-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20220907110728.19092-10-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index c7309e981bfb..dcf8a8764e17 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -6273,7 +6273,9 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + return -ENOMEM; + + pm_runtime_set_active(dev); +- pm_runtime_enable(dev); ++ ret = devm_pm_runtime_enable(dev); ++ if (ret) ++ return ret; + /* + * Prevent runtime pm from being ON by default. Users can enable + * it using power/control in sysfs. +@@ -6323,13 +6325,10 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + 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; + } +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-drop-all-non-usb-compatibles-suppor.patch b/queue-5.19/phy-qcom-qmp-usb-drop-all-non-usb-compatibles-suppor.patch new file mode 100644 index 00000000000..a973bc37a1b --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-drop-all-non-usb-compatibles-suppor.patch @@ -0,0 +1,3417 @@ +From f33f692e6133cc7c773a440c97f346f41ec9ccac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:38 +0300 +Subject: phy: qcom-qmp-usb: drop all non-USB compatibles support + +From: Dmitry Baryshkov + +[ Upstream commit 8c924330ebe3e5c6f41bad0e5118875848843864 ] + +Drop support for all non-USB compatibles from the new qmp-usb driver. + +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-6-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 3108 +---------------------- + 1 file changed, 40 insertions(+), 3068 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index dcf8a8764e17..e147182afea7 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -141,34 +141,6 @@ enum qphy_reg_layout { + 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, +@@ -192,18 +164,6 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { + [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, +@@ -241,29 +201,6 @@ static const unsigned int qcm2290_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { + [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), +@@ -339,235 +276,6 @@ static const struct qmp_phy_init_tbl ipq8074_usb3_pcs_tbl[] = { + 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), +@@ -639,414 +347,6 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = { + 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), +@@ -1094,88 +394,6 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_tx_tbl[] = { + 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), +@@ -1346,175 +564,6 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = { + 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), +@@ -1624,93 +673,6 @@ static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = { + 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), +@@ -2023,374 +985,44 @@ static const struct qmp_phy_init_tbl sm8250_usb3_uniphy_rx_tbl[] = { + 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_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_PI_CONTROLS, 0x70), +- QMP_PHY_INIT_CFG(QSERDES_V4_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0e), ++ 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, 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_RX_EQU_ADAPTOR_CNTRL4, 0x0a), + 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_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_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 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 sdx55_usb3_uniphy_tx_tbl[] = { +@@ -2440,101 +1072,6 @@ static const struct qmp_phy_init_tbl sdx55_usb3_uniphy_rx_tbl[] = { + 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), +@@ -2579,106 +1116,6 @@ static const struct qmp_phy_init_tbl sdx65_usb3_uniphy_rx_tbl[] = { + 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), +@@ -2910,215 +1347,6 @@ static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = { + 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 */ +@@ -3287,16 +1515,6 @@ struct qcom_qmp { + 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; +@@ -3326,18 +1544,10 @@ 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", + }; +@@ -3347,14 +1557,6 @@ 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" +@@ -3365,10 +1567,6 @@ static const char * const qcm2290_usb3phy_clk_l[] = { + }; + + /* list of resets */ +-static const char * const msm8996_pciephy_reset_l[] = { +- "phy", "common", "cfg", +-}; +- + static const char * const msm8996_usb3phy_reset_l[] = { + "phy", "common", + }; +@@ -3381,10 +1579,6 @@ 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", +@@ -3415,64 +1609,6 @@ static const struct qmp_phy_cfg ipq8074_usb3phy_cfg = { + .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, +@@ -3498,214 +1634,6 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = { + .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, +@@ -3770,46 +1698,6 @@ static const struct qmp_phy_cfg sc7180_usb3phy_cfg = { + .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, +@@ -3839,82 +1727,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { + .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, +@@ -3933,38 +1745,13 @@ static const struct qmp_phy_cfg msm8998_usb3phy_cfg = { + .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, ++ .regs = qmp_v3_usb3phy_regs_layout, + +- .start_ctrl = SERDES_START, +- .pwrdn_ctrl = SW_PWRDN, ++ .start_ctrl = SERDES_START | PCS_START, ++ .pwrdn_ctrl = SW_PWRDN, + .phy_status = PHYSTATUS, + +- .is_dual_lane_phy = true, ++ .is_dual_lane_phy = true, + }; + + static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { +@@ -4000,76 +1787,6 @@ static const struct qmp_phy_cfg sm8150_usb3phy_cfg = { + .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, +@@ -4160,46 +1877,6 @@ static const struct qmp_phy_cfg sm8250_usb3_uniphy_cfg = { + .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, +@@ -4229,38 +1906,6 @@ static const struct qmp_phy_cfg sdx55_usb3_uniphy_cfg = { + .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, +@@ -4290,31 +1935,6 @@ static const struct qmp_phy_cfg sdx65_usb3_uniphy_cfg = { + .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, +@@ -4376,94 +1996,6 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = { + .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, +@@ -4589,457 +2121,6 @@ static int qcom_qmp_phy_serdes_init(struct qmp_phy *qphy) + 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; +@@ -6023,81 +3104,27 @@ 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, +@@ -6107,27 +3134,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { + }, { + .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, +@@ -6140,15 +3149,6 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { + }, { + .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, +@@ -6160,22 +3160,6 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = { + }; + 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) +@@ -6206,20 +3190,8 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + + /* 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 */ +- } ++ if (!cfg) ++ return -EINVAL; + + /* per PHY serdes; usually located at base address */ + usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); +@@ -6336,7 +3308,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev) + static struct platform_driver qcom_qmp_phy_driver = { + .probe = qcom_qmp_phy_probe, + .driver = { +- .name = "qcom-qmp-phy", ++ .name = "qcom-qmp-usb-phy", + .pm = &qcom_qmp_phy_pm_ops, + .of_match_table = qcom_qmp_phy_of_match_table, + }, +@@ -6345,5 +3317,5 @@ static struct platform_driver qcom_qmp_phy_driver = { + module_platform_driver(qcom_qmp_phy_driver); + + MODULE_AUTHOR("Vivek Gautam "); +-MODULE_DESCRIPTION("Qualcomm QMP PHY driver"); ++MODULE_DESCRIPTION("Qualcomm QMP USB PHY driver"); + MODULE_LICENSE("GPL v2"); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-drop-pipe-clock-lane-suffix.patch b/queue-5.19/phy-qcom-qmp-usb-drop-pipe-clock-lane-suffix.patch new file mode 100644 index 00000000000..27311f02185 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-drop-pipe-clock-lane-suffix.patch @@ -0,0 +1,51 @@ +From daa06deeda3b3a38d6e779601a66e1134db96bd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 13:29:23 +0200 +Subject: phy: qcom-qmp-usb: drop pipe clock lane suffix + +From: Johan Hovold + +[ Upstream commit c8c5d5e89ac52a462f48264863a7a32f0c76fa1d ] + +The pipe clock is defined in the "lane" node so there's no need to keep +adding a redundant lane-number suffix to the clock name. + +Update driver to support the new binding where the pipe clock name has +been deprecated by instead requesting the clock by index. + +Reviewed-by: Krzysztof Kozlowski +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220830112923.3725-31-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index 687f1a534837..116f60ef0649 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -2510,7 +2510,6 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct phy *generic_phy; + struct qmp_phy *qphy; +- char prop_name[MAX_PROP_NAME]; + int ret; + + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); +@@ -2566,8 +2565,7 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + if (!qphy->pcs_misc) + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); + +- snprintf(prop_name, sizeof(prop_name), "pipe%d", id); +- qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name); ++ qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); + if (IS_ERR(qphy->pipe_clk)) { + return dev_err_probe(dev, PTR_ERR(qphy->pipe_clk), + "failed to get lane%d pipe clock\n", id); +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-drop-support-for-non-usb-phy-types.patch b/queue-5.19/phy-qcom-qmp-usb-drop-support-for-non-usb-phy-types.patch new file mode 100644 index 00000000000..72cca9e61dc --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-drop-support-for-non-usb-phy-types.patch @@ -0,0 +1,600 @@ +From 8a14e2377a94fc47a263a287a3bebb13feda872d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jun 2022 00:31:51 +0300 +Subject: phy: qcom-qmp-usb: drop support for non-USB PHY types + +From: Dmitry Baryshkov + +[ Upstream commit 86f5ddddcd9c4755e3d1d1ca4be01df5a4ed5d96 ] + +Drop remaining support for PHY types other than 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-19-dmitry.baryshkov@linaro.org +Signed-off-by: Vinod Koul +Stable-dep-of: a5d6b1ac56cb ("phy: qcom-qmp-usb: fix memleak on probe deferral") +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 435 +++--------------------- + 1 file changed, 48 insertions(+), 387 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index 2ae13b4485b6..55785dcd47e0 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -2059,7 +2059,6 @@ static int qcom_qmp_phy_usb_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; +@@ -2069,35 +2068,6 @@ static int qcom_qmp_phy_usb_serdes_init(struct qmp_phy *qphy) + qcom_qmp_phy_usb_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_usb_configure(serdes, cfg->regs, +- cfg->serdes_tbl_rbr, +- cfg->serdes_tbl_rbr_num); +- break; +- case 2700: +- qcom_qmp_phy_usb_configure(serdes, cfg->regs, +- cfg->serdes_tbl_hbr, +- cfg->serdes_tbl_hbr_num); +- break; +- case 5400: +- qcom_qmp_phy_usb_configure(serdes, cfg->regs, +- cfg->serdes_tbl_hbr2, +- cfg->serdes_tbl_hbr2_num); +- break; +- case 8100: +- qcom_qmp_phy_usb_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; +@@ -2121,32 +2091,6 @@ static int qcom_qmp_phy_usb_serdes_init(struct qmp_phy *qphy) + 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_usb_com_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; +@@ -2316,9 +2260,6 @@ static int qcom_qmp_phy_usb_init(struct phy *phy) + if (ret) + return ret; + +- if (cfg->type == PHY_TYPE_DP) +- cfg->dp_aux_init(qphy); +- + return 0; + } + +@@ -2369,10 +2310,6 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) + 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_usb_configure_lane(rx, cfg->regs, + cfg->rx_tbl, cfg->rx_tbl_num, 1); + if (cfg->rx_tbl_sec) +@@ -2389,14 +2326,10 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) + } + + /* Configure link rate, swing, etc. */ +- if (cfg->type == PHY_TYPE_DP) { +- cfg->configure_dp_phy(qphy); +- } else { +- qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); +- if (cfg->pcs_tbl_sec) +- qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, +- cfg->pcs_tbl_num_sec); +- } ++ qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); ++ if (cfg->pcs_tbl_sec) ++ qcom_qmp_phy_usb_configure(pcs, cfg->regs, cfg->pcs_tbl_sec, ++ cfg->pcs_tbl_num_sec); + + ret = reset_control_deassert(qmp->ufs_reset); + if (ret) +@@ -2408,40 +2341,26 @@ static int qcom_qmp_phy_usb_power_on(struct phy *phy) + qcom_qmp_phy_usb_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; +- } ++ /* 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); + +- 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; +- } ++ 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: +@@ -2460,25 +2379,20 @@ static int qcom_qmp_phy_usb_power_off(struct phy *phy) + + 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); ++ /* 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); ++ /* 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); +- } ++ /* 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; +@@ -2755,223 +2669,13 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) + 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_usb_gen_ops = { ++static const struct phy_ops qcom_qmp_phy_usb_ops = { + .init = qcom_qmp_phy_usb_enable, + .exit = qcom_qmp_phy_usb_disable, + .set_mode = qcom_qmp_phy_usb_set_mode, + .owner = THIS_MODULE, + }; + +-static const struct phy_ops qcom_qmp_phy_usb_dp_ops = { +- .init = qcom_qmp_phy_usb_init, +- .configure = qcom_qmp_dp_phy_configure, +- .power_on = qcom_qmp_phy_usb_power_on, +- .calibrate = qcom_qmp_dp_phy_calibrate, +- .power_off = qcom_qmp_phy_usb_power_off, +- .exit = qcom_qmp_phy_usb_exit, +- .set_mode = qcom_qmp_phy_usb_set_mode, +- .owner = THIS_MODULE, +-}; +- +-static const struct phy_ops qcom_qmp_pcie_ufs_ops = { +- .power_on = qcom_qmp_phy_usb_enable, +- .power_off = qcom_qmp_phy_usb_disable, +- .set_mode = qcom_qmp_phy_usb_set_mode, +- .owner = THIS_MODULE, +-}; +- + static void qcom_qmp_reset_control_put(void *data) + { + reset_control_put(data); +@@ -2984,7 +2688,6 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + 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; + +@@ -3051,16 +2754,12 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + 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; ++ 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; + } + + /* Get lane reset, if any */ +@@ -3077,14 +2776,7 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + 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_usb_dp_ops; +- else +- ops = &qcom_qmp_phy_usb_gen_ops; +- +- generic_phy = devm_phy_create(dev, np, ops); ++ generic_phy = devm_phy_create(dev, np, &qcom_qmp_phy_usb_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + dev_err(dev, "failed to create qphy %d\n", ret); +@@ -3172,12 +2864,7 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) + 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; + +@@ -3194,28 +2881,18 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) + return -EINVAL; + + /* per PHY serdes; usually located at base address */ +- usb_serdes = serdes = devm_platform_ioremap_resource(pdev, 0); ++ 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) { ++ if (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; +- } ++ expected_phys = cfg->nlanes; + + mutex_init(&qmp->phy_mutex); + +@@ -3256,14 +2933,6 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) + + 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_usb_create(dev, child, id, serdes, cfg); + if (ret) { +@@ -3276,21 +2945,13 @@ static int qcom_qmp_phy_usb_probe(struct platform_device *pdev) + * 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; +- } ++ ret = phy_pipe_clk_register(qmp, child); ++ if (ret) { ++ dev_err(qmp->dev, ++ "failed to register pipe clock source\n"); ++ goto err_node_put; + } ++ + id++; + } + +-- +2.35.1 + diff --git a/queue-5.19/phy-qcom-qmp-usb-fix-memleak-on-probe-deferral.patch b/queue-5.19/phy-qcom-qmp-usb-fix-memleak-on-probe-deferral.patch new file mode 100644 index 00000000000..3b4b19e7177 --- /dev/null +++ b/queue-5.19/phy-qcom-qmp-usb-fix-memleak-on-probe-deferral.patch @@ -0,0 +1,136 @@ +From 8e399daabb84fb7c47e944fa5aa53259a7fb4099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 12:23:35 +0200 +Subject: phy: qcom-qmp-usb: fix memleak on probe deferral + +From: Johan Hovold + +[ Upstream commit a5d6b1ac56cbd6b5850a3a54e35f1cb71e8e8cdd ] + +Switch to using the device-managed of_iomap helper to avoid leaking +memory on probe deferral and driver unbind. + +Note that this helper checks for already reserved regions and may fail +if there are multiple devices claiming the same memory. + +Two bindings currently rely on overlapping mappings for the PCS region +so fallback to non-exclusive mappings for those for now. + +Fixes: e78f3d15e115 ("phy: qcom-qmp: new qmp phy driver for qcom-chipsets") +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20220916102340.11520-7-johan+linaro@kernel.org +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-qmp-usb.c | 57 ++++++++++++++++++------- + 1 file changed, 42 insertions(+), 15 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +index 116f60ef0649..b727dcf4f906 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c +@@ -2503,6 +2503,21 @@ static const struct phy_ops qcom_qmp_phy_usb_ops = { + .owner = THIS_MODULE, + }; + ++static void __iomem *qmp_usb_iomap(struct device *dev, struct device_node *np, ++ int index, bool exclusive) ++{ ++ struct resource res; ++ ++ if (!exclusive) { ++ if (of_address_to_resource(np, index, &res)) ++ return IOMEM_ERR_PTR(-EINVAL); ++ ++ return devm_ioremap(dev, res.start, resource_size(&res)); ++ } ++ ++ return devm_of_iomap(dev, np, index, NULL); ++} ++ + static + int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + void __iomem *serdes, const struct qmp_phy_cfg *cfg) +@@ -2510,8 +2525,18 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + struct qcom_qmp *qmp = dev_get_drvdata(dev); + struct phy *generic_phy; + struct qmp_phy *qphy; ++ bool exclusive = true; + int ret; + ++ /* ++ * FIXME: These bindings should be fixed to not rely on overlapping ++ * mappings for PCS. ++ */ ++ if (of_device_is_compatible(dev->of_node, "qcom,sdx65-qmp-usb3-uni-phy")) ++ exclusive = false; ++ if (of_device_is_compatible(dev->of_node, "qcom,sm8350-qmp-usb3-uni-phy")) ++ exclusive = false; ++ + qphy = devm_kzalloc(dev, sizeof(*qphy), GFP_KERNEL); + if (!qphy) + return -ENOMEM; +@@ -2524,17 +2549,17 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + * 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->tx = devm_of_iomap(dev, np, 0, NULL); ++ if (IS_ERR(qphy->tx)) ++ return PTR_ERR(qphy->tx); + +- qphy->rx = of_iomap(np, 1); +- if (!qphy->rx) +- return -ENOMEM; ++ qphy->rx = devm_of_iomap(dev, np, 1, NULL); ++ if (IS_ERR(qphy->rx)) ++ return PTR_ERR(qphy->rx); + +- qphy->pcs = of_iomap(np, 2); +- if (!qphy->pcs) +- return -ENOMEM; ++ qphy->pcs = qmp_usb_iomap(dev, np, 2, exclusive); ++ if (IS_ERR(qphy->pcs)) ++ return PTR_ERR(qphy->pcs); + + /* + * If this is a dual-lane PHY, then there should be registers for the +@@ -2543,9 +2568,9 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + * 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) { ++ qphy->tx2 = devm_of_iomap(dev, np, 3, NULL); ++ qphy->rx2 = devm_of_iomap(dev, np, 4, NULL); ++ if (IS_ERR(qphy->tx2) || IS_ERR(qphy->rx2)) { + dev_warn(dev, + "Underspecified device tree, falling back to legacy register regions\n"); + +@@ -2555,15 +2580,17 @@ int qcom_qmp_phy_usb_create(struct device *dev, struct device_node *np, int id, + qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; + + } else { +- qphy->pcs_misc = of_iomap(np, 5); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 5, NULL); + } + + } else { +- qphy->pcs_misc = of_iomap(np, 3); ++ qphy->pcs_misc = devm_of_iomap(dev, np, 3, NULL); + } + +- if (!qphy->pcs_misc) ++ if (IS_ERR(qphy->pcs_misc)) { + dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); ++ qphy->pcs_misc = NULL; ++ } + + qphy->pipe_clk = devm_get_clk_from_child(dev, np, NULL); + if (IS_ERR(qphy->pipe_clk)) { +-- +2.35.1 + diff --git a/queue-5.19/phy-qualcomm-call-clk_disable_unprepare-in-the-error.patch b/queue-5.19/phy-qualcomm-call-clk_disable_unprepare-in-the-error.patch new file mode 100644 index 00000000000..5fe6821b146 --- /dev/null +++ b/queue-5.19/phy-qualcomm-call-clk_disable_unprepare-in-the-error.patch @@ -0,0 +1,53 @@ +From db3001b86a25626061d3330e0d5f5ca6cffefb64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 13:13:33 +0800 +Subject: phy: qualcomm: call clk_disable_unprepare in the error handling + +From: Dongliang Mu + +[ Upstream commit c3966ced8eb8dc53b6c8d7f97d32cc8a2107d83e ] + +Smatch reports the following error: + +drivers/phy/qualcomm/phy-qcom-usb-hsic.c:82 qcom_usb_hsic_phy_power_on() +warn: 'uphy->cal_clk' from clk_prepare_enable() not released on lines: +58. +drivers/phy/qualcomm/phy-qcom-usb-hsic.c:82 qcom_usb_hsic_phy_power_on() +warn: 'uphy->cal_sleep_clk' from clk_prepare_enable() not released on +lines: 58. +drivers/phy/qualcomm/phy-qcom-usb-hsic.c:82 qcom_usb_hsic_phy_power_on() +warn: 'uphy->phy_clk' from clk_prepare_enable() not released on lines: +58. + +Fix this by calling proper clk_disable_unprepare calls. + +Fixes: 0b56e9a7e835 ("phy: Group vendor specific phy drivers") +Signed-off-by: Dongliang Mu +Reviewed-by: Neil Armstrong +Link: https://lore.kernel.org/r/20220914051334.69282-1-dzm91@hust.edu.cn +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/qualcomm/phy-qcom-usb-hsic.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c +index 716a77748ed8..20f6dd37c7c1 100644 +--- a/drivers/phy/qualcomm/phy-qcom-usb-hsic.c ++++ b/drivers/phy/qualcomm/phy-qcom-usb-hsic.c +@@ -54,8 +54,10 @@ static int qcom_usb_hsic_phy_power_on(struct phy *phy) + + /* Configure pins for HSIC functionality */ + pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT); +- if (IS_ERR(pins_default)) +- return PTR_ERR(pins_default); ++ if (IS_ERR(pins_default)) { ++ ret = PTR_ERR(pins_default); ++ goto err_ulpi; ++ } + + ret = pinctrl_select_state(uphy->pctl, pins_default); + if (ret) +-- +2.35.1 + diff --git a/queue-5.19/phy-rockchip-inno-usb2-return-zero-after-otg-sync.patch b/queue-5.19/phy-rockchip-inno-usb2-return-zero-after-otg-sync.patch new file mode 100644 index 00000000000..71b467238a1 --- /dev/null +++ b/queue-5.19/phy-rockchip-inno-usb2-return-zero-after-otg-sync.patch @@ -0,0 +1,64 @@ +From 0990347070d76bfa350a99be5f3f23508a542fa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 14:45:42 -0400 +Subject: phy: rockchip-inno-usb2: Return zero after otg sync + +From: Peter Geis + +[ Upstream commit f340ed8664a55a467850ec1689996e63d9ee971a ] + +The otg sync state patch reuses the ret variable, but fails to set it to +zero after use. This leads to a situation when the otg port is in +peripheral mode where the otg phy aborts halfway through setup. It also +fails to account for a failure to register the extcon notifier. Fix this +by using our own variable and skipping otg sync in case of failure. + +Fixes: 8dc60f8da22f ("phy: rockchip-inno-usb2: Sync initial otg state") +Reported-by: Markus Reichl +Reported-by: Michael Riesch +Signed-off-by: Peter Geis +Tested-by: Michael Riesch +Tested-by: Markus Reichl +Reviewed-by: Samuel Holland +Link: https://lore.kernel.org/r/20220902184543.1234835-1-pgwipeout@gmail.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +index 5223d4c9afdf..39f14a5b78cd 100644 +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1124,7 +1124,7 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, + struct rockchip_usb2phy_port *rport, + struct device_node *child_np) + { +- int ret; ++ int ret, id; + + rport->port_id = USB2PHY_PORT_OTG; + rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG]; +@@ -1162,13 +1162,15 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy, + + ret = devm_extcon_register_notifier(rphy->dev, rphy->edev, + EXTCON_USB_HOST, &rport->event_nb); +- if (ret) ++ if (ret) { + dev_err(rphy->dev, "register USB HOST notifier failed\n"); ++ goto out; ++ } + + if (!of_property_read_bool(rphy->dev->of_node, "extcon")) { + /* do initial sync of usb state */ +- ret = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); +- extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !ret); ++ id = property_enabled(rphy->grf, &rport->port_cfg->utmi_id); ++ extcon_set_state_sync(rphy->edev, EXTCON_USB_HOST, !id); + } + } + +-- +2.35.1 + diff --git a/queue-5.19/platform-chrome-cros_ec-notify-the-pm-of-wake-events.patch b/queue-5.19/platform-chrome-cros_ec-notify-the-pm-of-wake-events.patch new file mode 100644 index 00000000000..19a8ba98779 --- /dev/null +++ b/queue-5.19/platform-chrome-cros_ec-notify-the-pm-of-wake-events.patch @@ -0,0 +1,55 @@ +From abb9e5cec6ffe332d5bcfdcd60701384490d0156 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 20:49:54 +0000 +Subject: platform/chrome: cros_ec: Notify the PM of wake events during resume + +From: Jameson Thies + +[ Upstream commit 8edd2752b0aa498b3a61f3caee8f79f7e0567fad ] + +cros_ec_handle_event in the cros_ec driver can notify the PM of wake +events. When a device is suspended, cros_ec_handle_event will not check +MKBP events. Instead, received MKBP events are checked during resume by +cros_ec_report_events_during_suspend. But +cros_ec_report_events_during_suspend cannot notify the PM if received +events are wake events, causing wake events to not be reported if +received while the device is suspended. + +Update cros_ec_report_events_during_suspend to notify the PM of wake +events during resume by calling pm_wakeup_event. + +Signed-off-by: Jameson Thies +Reviewed-by: Prashant Malani +Reviewed-by: Benson Leung +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20220913204954.2931042-1-jthies@google.com +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_ec.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c +index 00381490dd3e..4b0934ef7714 100644 +--- a/drivers/platform/chrome/cros_ec.c ++++ b/drivers/platform/chrome/cros_ec.c +@@ -352,10 +352,16 @@ EXPORT_SYMBOL(cros_ec_suspend); + + static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev) + { ++ bool wake_event; ++ + while (ec_dev->mkbp_event_supported && +- cros_ec_get_next_event(ec_dev, NULL, NULL) > 0) ++ cros_ec_get_next_event(ec_dev, &wake_event, NULL) > 0) { + blocking_notifier_call_chain(&ec_dev->event_notifier, + 1, ec_dev); ++ ++ if (wake_event && device_may_wakeup(ec_dev->dev)) ++ pm_wakeup_event(ec_dev->dev, 0); ++ } + } + + /** +-- +2.35.1 + diff --git a/queue-5.19/platform-chrome-cros_ec_typec-correct-alt-mode-index.patch b/queue-5.19/platform-chrome-cros_ec_typec-correct-alt-mode-index.patch new file mode 100644 index 00000000000..544a1fadbdd --- /dev/null +++ b/queue-5.19/platform-chrome-cros_ec_typec-correct-alt-mode-index.patch @@ -0,0 +1,40 @@ +From 5902622bf7a4487017c61d79cabb16d7d387d245 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 19:08:03 +0000 +Subject: platform/chrome: cros_ec_typec: Correct alt mode index + +From: Prashant Malani + +[ Upstream commit 4e477663e396f48c5cfc5f2d75d4b514f409516a ] + +Alt mode indices used by USB PD (Power Delivery) start with 1, not 0. + +Update the alt mdoe registration code to factor this in to the alt mode +descriptor. + +Fixes: de0f49487db3 ("platform/chrome: cros_ec_typec: Register partner altmodes") +Signed-off-by: Prashant Malani +Acked-by: Heikki Krogerus +Reviewed-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20220819190807.1275937-3-pmalani@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_ec_typec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c +index 7cb2e35c4ded..1305a22a8831 100644 +--- a/drivers/platform/chrome/cros_ec_typec.c ++++ b/drivers/platform/chrome/cros_ec_typec.c +@@ -669,7 +669,7 @@ static int cros_typec_register_altmodes(struct cros_typec_data *typec, int port_ + for (j = 0; j < sop_disc->svids[i].mode_count; j++) { + memset(&desc, 0, sizeof(desc)); + desc.svid = sop_disc->svids[i].svid; +- desc.mode = j; ++ desc.mode = j + 1; + desc.vdo = sop_disc->svids[i].mode_vdo[j]; + + if (is_partner) +-- +2.35.1 + diff --git a/queue-5.19/platform-chrome-fix-double-free-in-chromeos_laptop_p.patch b/queue-5.19/platform-chrome-fix-double-free-in-chromeos_laptop_p.patch new file mode 100644 index 00000000000..10c1cab6b7d --- /dev/null +++ b/queue-5.19/platform-chrome-fix-double-free-in-chromeos_laptop_p.patch @@ -0,0 +1,88 @@ +From 842848fd7d79a773580c89f890511c7d6f33fe2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Aug 2022 01:08:43 +0300 +Subject: platform/chrome: fix double-free in chromeos_laptop_prepare() + +From: Rustam Subkhankulov + +[ Upstream commit 6ad4194d6a1e1d11b285989cd648ef695b4a93c0 ] + +If chromeos_laptop_prepare_i2c_peripherals() fails after allocating memory +for 'cros_laptop->i2c_peripherals', this memory is freed at 'err_out' label +and nonzero value is returned. Then chromeos_laptop_destroy() is called, +resulting in double-free error. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Signed-off-by: Rustam Subkhankulov +Fixes: 5020cd29d8bf ("platform/chrome: chromeos_laptop - supply properties for ACPI devices") +Reviewed-by: Dmitry Torokhov +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20220813220843.2373004-1-subkhankulov@ispras.ru +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/chromeos_laptop.c | 24 ++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c +index 4e14b4d6635d..a2cdbfbaeae6 100644 +--- a/drivers/platform/chrome/chromeos_laptop.c ++++ b/drivers/platform/chrome/chromeos_laptop.c +@@ -740,6 +740,7 @@ static int __init + chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, + const struct chromeos_laptop *src) + { ++ struct i2c_peripheral *i2c_peripherals; + struct i2c_peripheral *i2c_dev; + struct i2c_board_info *info; + int i; +@@ -748,17 +749,15 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, + if (!src->num_i2c_peripherals) + return 0; + +- cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals, +- src->num_i2c_peripherals * +- sizeof(*src->i2c_peripherals), +- GFP_KERNEL); +- if (!cros_laptop->i2c_peripherals) ++ i2c_peripherals = kmemdup(src->i2c_peripherals, ++ src->num_i2c_peripherals * ++ sizeof(*src->i2c_peripherals), ++ GFP_KERNEL); ++ if (!i2c_peripherals) + return -ENOMEM; + +- cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals; +- +- for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) { +- i2c_dev = &cros_laptop->i2c_peripherals[i]; ++ for (i = 0; i < src->num_i2c_peripherals; i++) { ++ i2c_dev = &i2c_peripherals[i]; + info = &i2c_dev->board_info; + + error = chromeos_laptop_setup_irq(i2c_dev); +@@ -775,16 +774,19 @@ chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop, + } + } + ++ cros_laptop->i2c_peripherals = i2c_peripherals; ++ cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals; ++ + return 0; + + err_out: + while (--i >= 0) { +- i2c_dev = &cros_laptop->i2c_peripherals[i]; ++ i2c_dev = &i2c_peripherals[i]; + info = &i2c_dev->board_info; + if (!IS_ERR_OR_NULL(info->fwnode)) + fwnode_remove_software_node(info->fwnode); + } +- kfree(cros_laptop->i2c_peripherals); ++ kfree(i2c_peripherals); + return error; + } + +-- +2.35.1 + diff --git a/queue-5.19/platform-chrome-fix-memory-corruption-in-ioctl.patch b/queue-5.19/platform-chrome-fix-memory-corruption-in-ioctl.patch new file mode 100644 index 00000000000..ddcf77d8c06 --- /dev/null +++ b/queue-5.19/platform-chrome-fix-memory-corruption-in-ioctl.patch @@ -0,0 +1,39 @@ +From a00fa209ae559fc7682680cb134050a02ad83727 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 08:20:36 +0300 +Subject: platform/chrome: fix memory corruption in ioctl + +From: Dan Carpenter + +[ Upstream commit 8a07b45fd3c2dda24fad43639be5335a4595196a ] + +If "s_mem.bytes" is larger than the buffer size it leads to memory +corruption. + +Fixes: eda2e30c6684 ("mfd / platform: cros_ec: Miscellaneous character device to talk with the EC") +Signed-off-by: Dan Carpenter +Reviewed-by: Guenter Roeck +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/Yv8dpCFZJdbUT5ye@kili +Signed-off-by: Sasha Levin +--- + drivers/platform/chrome/cros_ec_chardev.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/platform/chrome/cros_ec_chardev.c b/drivers/platform/chrome/cros_ec_chardev.c +index fd33de546aee..0de7c255254e 100644 +--- a/drivers/platform/chrome/cros_ec_chardev.c ++++ b/drivers/platform/chrome/cros_ec_chardev.c +@@ -327,6 +327,9 @@ static long cros_ec_chardev_ioctl_readmem(struct cros_ec_dev *ec, + if (copy_from_user(&s_mem, arg, sizeof(s_mem))) + return -EFAULT; + ++ if (s_mem.bytes > sizeof(s_mem.buffer)) ++ return -EINVAL; ++ + num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes, + s_mem.buffer); + if (num <= 0) +-- +2.35.1 + diff --git a/queue-5.19/platform-x86-hp-wmi-setting-thermal-profile-fails-wi.patch b/queue-5.19/platform-x86-hp-wmi-setting-thermal-profile-fails-wi.patch new file mode 100644 index 00000000000..26260a165ba --- /dev/null +++ b/queue-5.19/platform-x86-hp-wmi-setting-thermal-profile-fails-wi.patch @@ -0,0 +1,77 @@ +From 110cd8db9f9e31ea876d91dc927420fc218cb140 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 14:26:03 -0500 +Subject: platform/x86: hp-wmi: Setting thermal profile fails with 0x06 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jorge Lopez + +[ Upstream commit 00b1829294b7c88ecba92c661fbe6fe347b364d2 ] + +Error 0x06 (invalid command parameter) is reported by hp-wmi module +when reading the current thermal profile and then proceed to set it +back. The failing condition occurs in Linux NixOS after user +configures the thermal profile to ‘quiet mode’ in Windows. Quiet Fan +Mode is supported in Windows but was not supported in hp-wmi module. + +This fix adds support for PLATFORM_PROFILE_QUIET in hp-wmi module for +HP notebooks other than HP Omen series. Quiet thermal profile is not +supported in HP Omen series notebooks. + +Signed-off-by: Jorge Lopez +Link: https://lore.kernel.org/r/20220912192603.4001-1-jorge.lopez2@hp.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/hp-wmi.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c +index bc7020e9df9e..fc8dbbd6fc7c 100644 +--- a/drivers/platform/x86/hp-wmi.c ++++ b/drivers/platform/x86/hp-wmi.c +@@ -177,7 +177,8 @@ enum hp_thermal_profile_omen_v1 { + enum hp_thermal_profile { + HP_THERMAL_PROFILE_PERFORMANCE = 0x00, + HP_THERMAL_PROFILE_DEFAULT = 0x01, +- HP_THERMAL_PROFILE_COOL = 0x02 ++ HP_THERMAL_PROFILE_COOL = 0x02, ++ HP_THERMAL_PROFILE_QUIET = 0x03, + }; + + #define IS_HWBLOCKED(x) ((x & HPWMI_POWER_FW_OR_HW) != HPWMI_POWER_FW_OR_HW) +@@ -1194,6 +1195,9 @@ static int hp_wmi_platform_profile_get(struct platform_profile_handler *pprof, + case HP_THERMAL_PROFILE_COOL: + *profile = PLATFORM_PROFILE_COOL; + break; ++ case HP_THERMAL_PROFILE_QUIET: ++ *profile = PLATFORM_PROFILE_QUIET; ++ break; + default: + return -EINVAL; + } +@@ -1216,6 +1220,9 @@ static int hp_wmi_platform_profile_set(struct platform_profile_handler *pprof, + case PLATFORM_PROFILE_COOL: + tp = HP_THERMAL_PROFILE_COOL; + break; ++ case PLATFORM_PROFILE_QUIET: ++ tp = HP_THERMAL_PROFILE_QUIET; ++ break; + default: + return -EOPNOTSUPP; + } +@@ -1263,6 +1270,8 @@ static int thermal_profile_setup(void) + + platform_profile_handler.profile_get = hp_wmi_platform_profile_get; + platform_profile_handler.profile_set = hp_wmi_platform_profile_set; ++ ++ set_bit(PLATFORM_PROFILE_QUIET, platform_profile_handler.choices); + } + + set_bit(PLATFORM_PROFILE_COOL, platform_profile_handler.choices); +-- +2.35.1 + diff --git a/queue-5.19/platform-x86-msi-laptop-change-dmi-match-alias-strin.patch b/queue-5.19/platform-x86-msi-laptop-change-dmi-match-alias-strin.patch new file mode 100644 index 00000000000..e22518b4b58 --- /dev/null +++ b/queue-5.19/platform-x86-msi-laptop-change-dmi-match-alias-strin.patch @@ -0,0 +1,58 @@ +From ef91477b87f3f95ffdb03a2b4c3ede0f214665e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 23:04:07 +0200 +Subject: platform/x86: msi-laptop: Change DMI match / alias strings to fix + module autoloading + +From: Hans de Goede + +[ Upstream commit 2a2565272a3628e45d61625e36ef17af7af4e3de ] + +On a MSI S270 with Fedora 37 x86_64 / systemd-251.4 the module does not +properly autoload. + +This is likely caused by issues with how systemd-udevd handles the single +quote char (') which is part of the sys_vendor / chassis_vendor strings +on this laptop. As a workaround remove the single quote char + everything +behind it from the sys_vendor + chassis_vendor matches. This fixes +the module not autoloading. + +Link: https://github.com/systemd/systemd/issues/24715 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20220917210407.647432-1-hdegoede@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/msi-laptop.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c +index 3e935303b143..0e804b6c2d24 100644 +--- a/drivers/platform/x86/msi-laptop.c ++++ b/drivers/platform/x86/msi-laptop.c +@@ -596,11 +596,10 @@ static const struct dmi_system_id msi_dmi_table[] __initconst = { + { + .ident = "MSI S270", + .matches = { +- DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), ++ DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT"), + DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), +- DMI_MATCH(DMI_CHASSIS_VENDOR, +- "MICRO-STAR INT'L CO.,LTD") ++ DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT") + }, + .driver_data = &quirk_old_ec_model, + .callback = dmi_check_cb +@@ -633,8 +632,7 @@ static const struct dmi_system_id msi_dmi_table[] __initconst = { + DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), + DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0131"), +- DMI_MATCH(DMI_CHASSIS_VENDOR, +- "MICRO-STAR INT'L CO.,LTD") ++ DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT") + }, + .driver_data = &quirk_old_ec_model, + .callback = dmi_check_cb +-- +2.35.1 + diff --git a/queue-5.19/platform-x86-msi-laptop-fix-old-ec-check-for-backlig.patch b/queue-5.19/platform-x86-msi-laptop-fix-old-ec-check-for-backlig.patch new file mode 100644 index 00000000000..c182a8f2ad4 --- /dev/null +++ b/queue-5.19/platform-x86-msi-laptop-fix-old-ec-check-for-backlig.patch @@ -0,0 +1,58 @@ +From a5c2546c81fd94afd9e5384eb3d74b7e40e8964a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 16:13:34 +0200 +Subject: platform/x86: msi-laptop: Fix old-ec check for backlight registering + +From: Hans de Goede + +[ Upstream commit 83ac7a1c2ed5f17caa07cbbc84bad3c05dc3bf22 ] + +Commit 2cc6c717799f ("msi-laptop: Port to new backlight interface +selection API") replaced this check: + + if (!quirks->old_ec_model || acpi_video_backlight_support()) + pr_info("Brightness ignored, ..."); + else + do_register(); + +With: + + if (quirks->old_ec_model || + acpi_video_get_backlight_type() == acpi_backlight_vendor) + do_register(); + +But since the do_register() part was part of the else branch, the entire +condition should be inverted. So not only the 2 statements on either +side of the || should be inverted, but the || itself should be replaced +with a &&. + +In practice this has likely not been an issue because the new-ec models +(old_ec_model==false) likely all support ACPI video backlight control, +making acpi_video_get_backlight_type() return acpi_backlight_video +turning the second part of the || also false when old_ec_model == false. + +Fixes: 2cc6c717799f ("msi-laptop: Port to new backlight interface selection API") +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20220825141336.208597-1-hdegoede@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/msi-laptop.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c +index 24ffc8e2d2d1..0960205ee49f 100644 +--- a/drivers/platform/x86/msi-laptop.c ++++ b/drivers/platform/x86/msi-laptop.c +@@ -1048,8 +1048,7 @@ static int __init msi_init(void) + return -EINVAL; + + /* Register backlight stuff */ +- +- if (quirks->old_ec_model || ++ if (quirks->old_ec_model && + acpi_video_get_backlight_type() == acpi_backlight_vendor) { + struct backlight_properties props; + memset(&props, 0, sizeof(struct backlight_properties)); +-- +2.35.1 + diff --git a/queue-5.19/platform-x86-msi-laptop-fix-resource-cleanup.patch b/queue-5.19/platform-x86-msi-laptop-fix-resource-cleanup.patch new file mode 100644 index 00000000000..64a6b3ac689 --- /dev/null +++ b/queue-5.19/platform-x86-msi-laptop-fix-resource-cleanup.patch @@ -0,0 +1,45 @@ +From c5a88b0033ffe57a0936ab61ac1d18bb0d752b7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 16:13:36 +0200 +Subject: platform/x86: msi-laptop: Fix resource cleanup + +From: Hans de Goede + +[ Upstream commit 5523632aa10f906dfe2eb714ee748590dc7fc6b1 ] + +Fix the input-device not getting free-ed on probe-errors and +fix the msi_touchpad_dwork not getting cancelled on neither +probe-errors nor on remove. + +Fixes: 143a4c0284dc ("msi-laptop: send out touchpad on/off key") +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20220825141336.208597-3-hdegoede@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/msi-laptop.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c +index 0960205ee49f..3e935303b143 100644 +--- a/drivers/platform/x86/msi-laptop.c ++++ b/drivers/platform/x86/msi-laptop.c +@@ -1116,6 +1116,8 @@ static int __init msi_init(void) + fail_create_group: + if (quirks->load_scm_model) { + i8042_remove_filter(msi_laptop_i8042_filter); ++ cancel_delayed_work_sync(&msi_touchpad_dwork); ++ input_unregister_device(msi_laptop_input_dev); + cancel_delayed_work_sync(&msi_rfkill_dwork); + cancel_work_sync(&msi_rfkill_work); + rfkill_cleanup(); +@@ -1136,6 +1138,7 @@ static void __exit msi_cleanup(void) + { + if (quirks->load_scm_model) { + i8042_remove_filter(msi_laptop_i8042_filter); ++ cancel_delayed_work_sync(&msi_touchpad_dwork); + input_unregister_device(msi_laptop_input_dev); + cancel_delayed_work_sync(&msi_rfkill_dwork); + cancel_work_sync(&msi_rfkill_work); +-- +2.35.1 + diff --git a/queue-5.19/platform-x86-pmc_atom-improve-quirk-message-to-be-le.patch b/queue-5.19/platform-x86-pmc_atom-improve-quirk-message-to-be-le.patch new file mode 100644 index 00000000000..84d8e51e68f --- /dev/null +++ b/queue-5.19/platform-x86-pmc_atom-improve-quirk-message-to-be-le.patch @@ -0,0 +1,37 @@ +From 55310f9e6c1c20ac741dc9aa5e1b64b31cae02ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 14:37:32 +0300 +Subject: platform/x86: pmc_atom: Improve quirk message to be less cryptic + +From: Andy Shevchenko + +[ Upstream commit 32c9b75640aeb1b144f9e2963c1640f4cef7c6f2 ] + +Not everyone can get what "critclks" means in the message, improve +it to make less cryptic. + +Signed-off-by: Andy Shevchenko +Link: https://lore.kernel.org/r/20220801113734.36131-2-andriy.shevchenko@linux.intel.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/pmc_atom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/pmc_atom.c b/drivers/platform/x86/pmc_atom.c +index 5c757c7f64de..f4046572a9fe 100644 +--- a/drivers/platform/x86/pmc_atom.c ++++ b/drivers/platform/x86/pmc_atom.c +@@ -354,7 +354,7 @@ static bool pmc_clk_is_critical = true; + + static int dmi_callback(const struct dmi_system_id *d) + { +- pr_info("%s critclks quirk enabled\n", d->ident); ++ pr_info("%s: PMC critical clocks quirk enabled\n", d->ident); + + return 1; + } +-- +2.35.1 + diff --git a/queue-5.19/power-supply-adp5061-fix-out-of-bounds-read-in-adp50.patch b/queue-5.19/power-supply-adp5061-fix-out-of-bounds-read-in-adp50.patch new file mode 100644 index 00000000000..780774ec889 --- /dev/null +++ b/queue-5.19/power-supply-adp5061-fix-out-of-bounds-read-in-adp50.patch @@ -0,0 +1,44 @@ +From d3c3f001e3daf2942c51acae6ed42e885c75cca0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Aug 2022 07:32:23 +0000 +Subject: power: supply: adp5061: fix out-of-bounds read in + adp5061_get_chg_type() + +From: Wei Yongjun + +[ Upstream commit 9d47e01b9d807808224347935562f7043a358054 ] + +ADP5061_CHG_STATUS_1_CHG_STATUS is masked with 0x07, which means a length +of 8, but adp5061_chg_type array size is 4, may end up reading 4 elements +beyond the end of the adp5061_chg_type[] array. + +Signed-off-by: Wei Yongjun +Acked-by: Michael Hennerich +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/adp5061.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/power/supply/adp5061.c b/drivers/power/supply/adp5061.c +index 003557043ab3..daee1161c305 100644 +--- a/drivers/power/supply/adp5061.c ++++ b/drivers/power/supply/adp5061.c +@@ -427,11 +427,11 @@ static int adp5061_get_chg_type(struct adp5061_state *st, + if (ret < 0) + return ret; + +- chg_type = adp5061_chg_type[ADP5061_CHG_STATUS_1_CHG_STATUS(status1)]; +- if (chg_type > ADP5061_CHG_FAST_CV) ++ chg_type = ADP5061_CHG_STATUS_1_CHG_STATUS(status1); ++ if (chg_type >= ARRAY_SIZE(adp5061_chg_type)) + val->intval = POWER_SUPPLY_STATUS_UNKNOWN; + else +- val->intval = chg_type; ++ val->intval = adp5061_chg_type[chg_type]; + + return ret; + } +-- +2.35.1 + diff --git a/queue-5.19/powercap-intel_rapl-fix-ubsan-shift-out-of-bounds-is.patch b/queue-5.19/powercap-intel_rapl-fix-ubsan-shift-out-of-bounds-is.patch new file mode 100644 index 00000000000..49b0b398b6b --- /dev/null +++ b/queue-5.19/powercap-intel_rapl-fix-ubsan-shift-out-of-bounds-is.patch @@ -0,0 +1,45 @@ +From 07ef3e63820d04b6d8a76aaeebc378675f9528bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 14:08:26 +0800 +Subject: powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue + +From: Chao Qin + +[ Upstream commit 2d93540014387d1c73b9ccc4d7895320df66d01b ] + +When value < time_unit, the parameter of ilog2() will be zero and +the return value is -1. u64(-1) is too large for shift exponent +and then will trigger shift-out-of-bounds: + +shift exponent 18446744073709551615 is too large for 32-bit type 'int' +Call Trace: + rapl_compute_time_window_core + rapl_write_data_raw + set_time_window + store_constraint_time_window_us + +Signed-off-by: Chao Qin +Acked-by: Zhang Rui +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/powercap/intel_rapl_common.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c +index 684f177acb44..c053fac05cc2 100644 +--- a/drivers/powercap/intel_rapl_common.c ++++ b/drivers/powercap/intel_rapl_common.c +@@ -994,6 +994,9 @@ static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value, + y = value & 0x1f; + value = (1 << y) * (4 + f) * rp->time_unit / 4; + } else { ++ if (value < rp->time_unit) ++ return 0; ++ + do_div(value, rp->time_unit); + y = ilog2(value); + f = div64_u64(4 * (value - (1 << y)), 1 << y); +-- +2.35.1 + diff --git a/queue-5.19/powerpc-64-interrupt-fix-return-to-masked-context-af.patch b/queue-5.19/powerpc-64-interrupt-fix-return-to-masked-context-af.patch new file mode 100644 index 00000000000..5731fdf41c0 --- /dev/null +++ b/queue-5.19/powerpc-64-interrupt-fix-return-to-masked-context-af.patch @@ -0,0 +1,123 @@ +From a52f364ec1654787310ce4c44e1a0b6a2e1aef97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 15:43:01 +1000 +Subject: powerpc/64/interrupt: Fix return to masked context after hard-mask + irq becomes pending + +From: Nicholas Piggin + +[ Upstream commit e485f6c751e0a969327336c635ca602feea117f0 ] + +If a synchronous interrupt (e.g., hash fault) is taken inside an +irqs-disabled region which has MSR[EE]=1, then an asynchronous interrupt +that is PACA_IRQ_MUST_HARD_MASK (e.g., PMI) is taken inside the +synchronous interrupt handler, then the synchronous interrupt will +return with MSR[EE]=1 and the asynchronous interrupt fires again. + +If the asynchronous interrupt is a PMI and the original context does not +have PMIs disabled (only Linux IRQs), the asynchronous interrupt will +fire despite having the PMI marked soft pending. This can confuse the +perf code and cause warnings. + +This patch changes the interrupt return so that irqs-disabled MSR[EE]=1 +contexts will be returned to with MSR[EE]=0 if a PACA_IRQ_MUST_HARD_MASK +interrupt has become pending in the meantime. + +The longer explanation for what happens: +1. local_irq_disable() +2. Hash fault interrupt fires, do_hash_fault handler runs +3. interrupt_enter_prepare() sets IRQS_ALL_DISABLED +4. interrupt_enter_prepare() sets MSR[EE]=1 +5. PMU interrupt fires, masked handler runs +6. Masked handler marks PMI pending +7. Masked handler returns with PACA_IRQ_HARD_DIS set, MSR[EE]=0 +8. do_hash_fault interrupt return handler runs +9. interrupt_exit_kernel_prepare() clears PACA_IRQ_HARD_DIS +10. interrupt returns with MSR[EE]=1 +11. PMU interrupt fires, perf handler runs + +Fixes: 4423eb5ae32e ("powerpc/64/interrupt: make normal synchronous interrupts enable MSR[EE] if possible") +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220926054305.2671436-4-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/interrupt.c | 10 --------- + arch/powerpc/kernel/interrupt_64.S | 34 +++++++++++++++++++++++++++--- + 2 files changed, 31 insertions(+), 13 deletions(-) + +diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c +index 784ea3289c84..0b656b897f99 100644 +--- a/arch/powerpc/kernel/interrupt.c ++++ b/arch/powerpc/kernel/interrupt.c +@@ -592,16 +592,6 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs) + + if (unlikely(stack_store)) + __hard_EE_RI_disable(); +- /* +- * Returning to a kernel context with local irqs disabled. +- * Here, if EE was enabled in the interrupted context, enable +- * it on return as well. A problem exists here where a soft +- * masked interrupt may have cleared MSR[EE] and set HARD_DIS +- * here, and it will still exist on return to the caller. This +- * will be resolved by the masked interrupt firing again. +- */ +- if (regs->msr & MSR_EE) +- local_paca->irq_happened &= ~PACA_IRQ_HARD_DIS; + #endif /* CONFIG_PPC64 */ + } + +diff --git a/arch/powerpc/kernel/interrupt_64.S b/arch/powerpc/kernel/interrupt_64.S +index ce25b28cf418..d76376ce7291 100644 +--- a/arch/powerpc/kernel/interrupt_64.S ++++ b/arch/powerpc/kernel/interrupt_64.S +@@ -559,15 +559,43 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel) + ld r11,SOFTE(r1) + cmpwi r11,IRQS_ENABLED + stb r11,PACAIRQSOFTMASK(r13) +- bne 1f ++ beq .Linterrupt_return_\srr\()_soft_enabled ++ ++ /* ++ * Returning to soft-disabled context. ++ * Check if a MUST_HARD_MASK interrupt has become pending, in which ++ * case we need to disable MSR[EE] in the return context. ++ */ ++ ld r12,_MSR(r1) ++ andi. r10,r12,MSR_EE ++ beq .Lfast_kernel_interrupt_return_\srr\() // EE already disabled ++ lbz r11,PACAIRQHAPPENED(r13) ++ andi. r10,r11,PACA_IRQ_MUST_HARD_MASK ++ beq 1f // No HARD_MASK pending ++ ++ /* Must clear MSR_EE from _MSR */ ++#ifdef CONFIG_PPC_BOOK3S ++ li r10,0 ++ /* Clear valid before changing _MSR */ ++ .ifc \srr,srr ++ stb r10,PACASRR_VALID(r13) ++ .else ++ stb r10,PACAHSRR_VALID(r13) ++ .endif ++#endif ++ xori r12,r12,MSR_EE ++ std r12,_MSR(r1) ++ b .Lfast_kernel_interrupt_return_\srr\() ++ ++.Linterrupt_return_\srr\()_soft_enabled: + #ifdef CONFIG_PPC_BOOK3S + lbz r11,PACAIRQHAPPENED(r13) + andi. r11,r11,(~PACA_IRQ_HARD_DIS)@l + bne- interrupt_return_\srr\()_kernel_restart + #endif +- li r11,0 +- stb r11,PACAIRQHAPPENED(r13) # clear out possible HARD_DIS + 1: ++ li r11,0 ++ stb r11,PACAIRQHAPPENED(r13) // clear the possible HARD_DIS + + .Lfast_kernel_interrupt_return_\srr\(): + cmpdi cr1,r3,0 +-- +2.35.1 + diff --git a/queue-5.19/powerpc-64-mark-irqs-hard-disabled-in-boot-paca.patch b/queue-5.19/powerpc-64-mark-irqs-hard-disabled-in-boot-paca.patch new file mode 100644 index 00000000000..a602b401fec --- /dev/null +++ b/queue-5.19/powerpc-64-mark-irqs-hard-disabled-in-boot-paca.patch @@ -0,0 +1,41 @@ +From c80487ddfe4d722fc3fc5b7b2c6ba2335cb8ad97 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 26 Sep 2022 15:43:00 +1000 +Subject: powerpc/64: mark irqs hard disabled in boot paca + +From: Nicholas Piggin + +[ Upstream commit 799f7063c7645f9a751d17f5dfd73b952f962cd2 ] + +This prevents interrupts in early boot (e.g., program check) from +enabling MSR[EE], potentially causing endian mismatch or other +crashes when reporting early boot traps. + +Fixes: 4423eb5ae32ec ("powerpc/64/interrupt: make normal synchronous interrupts enable MSR[EE] if possible") +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220926054305.2671436-3-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/setup_64.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c +index 5761f08dae95..6562517bcb3b 100644 +--- a/arch/powerpc/kernel/setup_64.c ++++ b/arch/powerpc/kernel/setup_64.c +@@ -183,8 +183,10 @@ static void __init fixup_boot_paca(void) + get_paca()->cpu_start = 1; + /* Allow percpu accesses to work until we setup percpu data */ + get_paca()->data_offset = 0; +- /* Mark interrupts disabled in PACA */ ++ /* Mark interrupts soft and hard disabled in PACA */ + irq_soft_mask_set(IRQS_DISABLED); ++ get_paca()->irq_happened = PACA_IRQ_HARD_DIS; ++ WARN_ON(mfmsr() & MSR_EE); + } + + static void __init configure_exceptions(void) +-- +2.35.1 + diff --git a/queue-5.19/powerpc-64s-fix-generic_cpu-build-flags-for-ppc970-g.patch b/queue-5.19/powerpc-64s-fix-generic_cpu-build-flags-for-ppc970-g.patch new file mode 100644 index 00000000000..dedc36bdc72 --- /dev/null +++ b/queue-5.19/powerpc-64s-fix-generic_cpu-build-flags-for-ppc970-g.patch @@ -0,0 +1,41 @@ +From 5924c056f9a2b4e8474ed4ed2dfadde1e094cfa4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 11:41:02 +1000 +Subject: powerpc/64s: Fix GENERIC_CPU build flags for PPC970 / G5 + +From: Nicholas Piggin + +[ Upstream commit 58ec7f06b74e0d6e76c4110afce367c8b5f0837d ] + +Big-endian GENERIC_CPU supports 970, but builds with -mcpu=power5. +POWER5 is ISA v2.02 whereas 970 is v2.01 plus Altivec. 2.02 added +the popcntb instruction which a compiler might use. + +Use -mcpu=power4. + +Fixes: 471d7ff8b51b ("powerpc/64s: Remove POWER4 support") +Signed-off-by: Nicholas Piggin +Reviewed-by: Segher Boessenkool +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220921014103.587954-1-npiggin@gmail.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile +index d54e1fe03551..dbeba3e209c0 100644 +--- a/arch/powerpc/Makefile ++++ b/arch/powerpc/Makefile +@@ -152,7 +152,7 @@ CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power8 + CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power9,-mtune=power8) + else + CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,$(call cc-option,-mtune=power5)) +-CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mcpu=power5,-mcpu=power4) ++CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power4 + endif + else ifdef CONFIG_PPC_BOOK3E_64 + CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64 +-- +2.35.1 + diff --git a/queue-5.19/powerpc-configs-properly-enable-papr_scm-in-pseries_.patch b/queue-5.19/powerpc-configs-properly-enable-papr_scm-in-pseries_.patch new file mode 100644 index 00000000000..a2ee13533a3 --- /dev/null +++ b/queue-5.19/powerpc-configs-properly-enable-papr_scm-in-pseries_.patch @@ -0,0 +1,37 @@ +From ff5b876b40576469e64cdd3c0184f5340cda64e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 11:42:53 +1000 +Subject: powerpc/configs: Properly enable PAPR_SCM in pseries_defconfig + +From: Michael Ellerman + +[ Upstream commit aa398d88aea4ec863bd7aea35d5035a37096dc59 ] + +My commit to add PAPR_SCM to pseries_defconfig failed to add the +required dependencies, meaning the driver doesn't get built. + +Add the required LIBNVDIMM=m. + +Fixes: d6481a7195df ("powerpc/configs: Add PAPR_SCM to pseries_defconfig") +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220901014253.252927-1-mpe@ellerman.id.au +Signed-off-by: Sasha Levin +--- + arch/powerpc/configs/pseries_defconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig +index b571d084c148..c05e37af9f1e 100644 +--- a/arch/powerpc/configs/pseries_defconfig ++++ b/arch/powerpc/configs/pseries_defconfig +@@ -40,6 +40,7 @@ CONFIG_PPC_SPLPAR=y + CONFIG_DTL=y + CONFIG_PPC_SMLPAR=y + CONFIG_IBMEBUS=y ++CONFIG_LIBNVDIMM=m + CONFIG_PAPR_SCM=m + CONFIG_PPC_SVM=y + # CONFIG_PPC_PMAC is not set +-- +2.35.1 + diff --git a/queue-5.19/powerpc-fix-fallocate-and-fadvise64_64-compat-parame.patch b/queue-5.19/powerpc-fix-fallocate-and-fadvise64_64-compat-parame.patch new file mode 100644 index 00000000000..73a16d1cf10 --- /dev/null +++ b/queue-5.19/powerpc-fix-fallocate-and-fadvise64_64-compat-parame.patch @@ -0,0 +1,110 @@ +From 5a4376c1448ebdfd8ca6e60ff1f137d52c6f6427 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 16:55:48 +1000 +Subject: powerpc: Fix fallocate and fadvise64_64 compat parameter combination + +From: Rohan McLure + +[ Upstream commit 016ff72bd2090903715c0f9422a44afbb966f4ee ] + +As reported[1] by Arnd, the arch-specific fadvise64_64 and fallocate +compatibility handlers assume parameters are passed with 32-bit +big-endian ABI. This affects the assignment of odd-even parameter pairs +to the high or low words of a 64-bit syscall parameter. + +Fix fadvise64_64 fallocate compat handlers to correctly swap upper/lower +32 bits conditioned on endianness. + +A future patch will replace the arch-specific compat fallocate with an +asm-generic implementation. This patch is intended for ease of +back-port. + +[1]: https://lore.kernel.org/all/be29926f-226e-48dc-871a-e29a54e80583@www.fastmail.com/ + +Fixes: 57f48b4b74e7 ("powerpc/compat_sys: swap hi/lo parts of 64-bit syscall args in LE mode") +Reported-by: Arnd Bergmann +Signed-off-by: Rohan McLure +Reviewed-by: Arnd Bergmann +Reviewed-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220921065605.1051927-9-rmclure@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/include/asm/syscalls.h | 12 ++++++++++++ + arch/powerpc/kernel/sys_ppc32.c | 14 +------------- + arch/powerpc/kernel/syscalls.c | 4 ++-- + 3 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h +index a2b13e55254f..da40219b303a 100644 +--- a/arch/powerpc/include/asm/syscalls.h ++++ b/arch/powerpc/include/asm/syscalls.h +@@ -8,6 +8,18 @@ + #include + #include + ++/* ++ * long long munging: ++ * The 32 bit ABI passes long longs in an odd even register pair. ++ * High and low parts are swapped depending on endian mode, ++ * so define a macro (similar to mips linux32) to handle that. ++ */ ++#ifdef __LITTLE_ENDIAN__ ++#define merge_64(low, high) (((u64)high << 32) | low) ++#else ++#define merge_64(high, low) (((u64)high << 32) | low) ++#endif ++ + struct rtas_args; + + asmlinkage long sys_mmap(unsigned long addr, size_t len, +diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c +index 16ff0399a257..719bfc6d1e3f 100644 +--- a/arch/powerpc/kernel/sys_ppc32.c ++++ b/arch/powerpc/kernel/sys_ppc32.c +@@ -56,18 +56,6 @@ unsigned long compat_sys_mmap2(unsigned long addr, size_t len, + return sys_mmap(addr, len, prot, flags, fd, pgoff << 12); + } + +-/* +- * long long munging: +- * The 32 bit ABI passes long longs in an odd even register pair. +- * High and low parts are swapped depending on endian mode, +- * so define a macro (similar to mips linux32) to handle that. +- */ +-#ifdef __LITTLE_ENDIAN__ +-#define merge_64(low, high) ((u64)high << 32) | low +-#else +-#define merge_64(high, low) ((u64)high << 32) | low +-#endif +- + compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count, + u32 reg6, u32 pos1, u32 pos2) + { +@@ -94,7 +82,7 @@ asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4, + asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offset1, u32 offset2, + u32 len1, u32 len2) + { +- return ksys_fallocate(fd, mode, ((loff_t)offset1 << 32) | offset2, ++ return ksys_fallocate(fd, mode, merge_64(offset1, offset2), + merge_64(len1, len2)); + } + +diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c +index fc999140bc27..abc3fbb3c490 100644 +--- a/arch/powerpc/kernel/syscalls.c ++++ b/arch/powerpc/kernel/syscalls.c +@@ -98,8 +98,8 @@ long ppc64_personality(unsigned long personality) + long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, + u32 len_high, u32 len_low) + { +- return ksys_fadvise64_64(fd, (u64)offset_high << 32 | offset_low, +- (u64)len_high << 32 | len_low, advice); ++ return ksys_fadvise64_64(fd, merge_64(offset_high, offset_low), ++ merge_64(len_high, len_low), advice); + } + + SYSCALL_DEFINE0(switch_endian) +-- +2.35.1 + diff --git a/queue-5.19/powerpc-fix-spe-power-isa-properties-for-e500v1-plat.patch b/queue-5.19/powerpc-fix-spe-power-isa-properties-for-e500v1-plat.patch new file mode 100644 index 00000000000..267240020c6 --- /dev/null +++ b/queue-5.19/powerpc-fix-spe-power-isa-properties-for-e500v1-plat.patch @@ -0,0 +1,150 @@ +From e68be806308c80d0f0f6a1fe348c1f77f302e2bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 23:21:02 +0200 +Subject: powerpc: Fix SPE Power ISA properties for e500v1 platforms +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 37b9345ce7f4ab17538ea62def6f6d430f091355 ] + +Commit 2eb28006431c ("powerpc/e500v2: Add Power ISA properties to comply +with ePAPR 1.1") introduced new include file e500v2_power_isa.dtsi and +should have used it for all e500v2 platforms. But apparently it was used +also for e500v1 platforms mpc8540, mpc8541, mpc8555 and mpc8560. + +e500v1 cores compared to e500v2 do not support double precision floating +point SPE instructions. Hence power-isa-sp.fd should not be set on e500v1 +platforms, which is in e500v2_power_isa.dtsi include file. + +Fix this issue by introducing a new e500v1_power_isa.dtsi include file and +use it in all e500v1 device tree files. + +Fixes: 2eb28006431c ("powerpc/e500v2: Add Power ISA properties to comply with ePAPR 1.1") +Signed-off-by: Pali Rohár +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220902212103.22534-1-pali@kernel.org +Signed-off-by: Sasha Levin +--- + .../boot/dts/fsl/e500v1_power_isa.dtsi | 51 +++++++++++++++++++ + arch/powerpc/boot/dts/fsl/mpc8540ads.dts | 2 +- + arch/powerpc/boot/dts/fsl/mpc8541cds.dts | 2 +- + arch/powerpc/boot/dts/fsl/mpc8555cds.dts | 2 +- + arch/powerpc/boot/dts/fsl/mpc8560ads.dts | 2 +- + 5 files changed, 55 insertions(+), 4 deletions(-) + create mode 100644 arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi + +diff --git a/arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi b/arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi +new file mode 100644 +index 000000000000..7e2a90cde72e +--- /dev/null ++++ b/arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi +@@ -0,0 +1,51 @@ ++/* ++ * e500v1 Power ISA Device Tree Source (include) ++ * ++ * Copyright 2012 Freescale Semiconductor Inc. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * * Neither the name of Freescale Semiconductor nor the ++ * names of its contributors may be used to endorse or promote products ++ * derived from this software without specific prior written permission. ++ * ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY ++ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ++ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ++ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY ++ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ++ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ++ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++/ { ++ cpus { ++ power-isa-version = "2.03"; ++ power-isa-b; // Base ++ power-isa-e; // Embedded ++ power-isa-atb; // Alternate Time Base ++ power-isa-cs; // Cache Specification ++ power-isa-e.le; // Embedded.Little-Endian ++ power-isa-e.pm; // Embedded.Performance Monitor ++ power-isa-ecl; // Embedded Cache Locking ++ power-isa-mmc; // Memory Coherence ++ power-isa-sp; // Signal Processing Engine ++ power-isa-sp.fs; // SPE.Embedded Float Scalar Single ++ power-isa-sp.fv; // SPE.Embedded Float Vector ++ mmu-type = "power-embedded"; ++ }; ++}; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8540ads.dts b/arch/powerpc/boot/dts/fsl/mpc8540ads.dts +index 18a885130538..e03ae130162b 100644 +--- a/arch/powerpc/boot/dts/fsl/mpc8540ads.dts ++++ b/arch/powerpc/boot/dts/fsl/mpc8540ads.dts +@@ -7,7 +7,7 @@ + + /dts-v1/; + +-/include/ "e500v2_power_isa.dtsi" ++/include/ "e500v1_power_isa.dtsi" + + / { + model = "MPC8540ADS"; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8541cds.dts b/arch/powerpc/boot/dts/fsl/mpc8541cds.dts +index ac381e7b1c60..a2a6c5cf852e 100644 +--- a/arch/powerpc/boot/dts/fsl/mpc8541cds.dts ++++ b/arch/powerpc/boot/dts/fsl/mpc8541cds.dts +@@ -7,7 +7,7 @@ + + /dts-v1/; + +-/include/ "e500v2_power_isa.dtsi" ++/include/ "e500v1_power_isa.dtsi" + + / { + model = "MPC8541CDS"; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8555cds.dts b/arch/powerpc/boot/dts/fsl/mpc8555cds.dts +index 9f58db2a7e66..901b6ff06dfb 100644 +--- a/arch/powerpc/boot/dts/fsl/mpc8555cds.dts ++++ b/arch/powerpc/boot/dts/fsl/mpc8555cds.dts +@@ -7,7 +7,7 @@ + + /dts-v1/; + +-/include/ "e500v2_power_isa.dtsi" ++/include/ "e500v1_power_isa.dtsi" + + / { + model = "MPC8555CDS"; +diff --git a/arch/powerpc/boot/dts/fsl/mpc8560ads.dts b/arch/powerpc/boot/dts/fsl/mpc8560ads.dts +index a24722ccaebf..c2f9aea78b29 100644 +--- a/arch/powerpc/boot/dts/fsl/mpc8560ads.dts ++++ b/arch/powerpc/boot/dts/fsl/mpc8560ads.dts +@@ -7,7 +7,7 @@ + + /dts-v1/; + +-/include/ "e500v2_power_isa.dtsi" ++/include/ "e500v1_power_isa.dtsi" + + / { + model = "MPC8560ADS"; +-- +2.35.1 + diff --git a/queue-5.19/powerpc-kprobes-fix-null-pointer-reference-in-arch_p.patch b/queue-5.19/powerpc-kprobes-fix-null-pointer-reference-in-arch_p.patch new file mode 100644 index 00000000000..38da9e13d77 --- /dev/null +++ b/queue-5.19/powerpc-kprobes-fix-null-pointer-reference-in-arch_p.patch @@ -0,0 +1,98 @@ +From 5d19baec5f97456e496c8fe15d12c3b953e768e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Sep 2022 17:32:53 +0800 +Subject: powerpc/kprobes: Fix null pointer reference in arch_prepare_kprobe() + +From: Li Huafei + +[ Upstream commit 97f88a3d723162781d6cbfdc7b9617eefab55b19 ] + +I found a null pointer reference in arch_prepare_kprobe(): + + # echo 'p cmdline_proc_show' > kprobe_events + # echo 'p cmdline_proc_show+16' >> kprobe_events + Kernel attempted to read user page (0) - exploit attempt? (uid: 0) + BUG: Kernel NULL pointer dereference on read at 0x00000000 + Faulting instruction address: 0xc000000000050bfc + Oops: Kernel access of bad area, sig: 11 [#1] + LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA PowerNV + Modules linked in: + CPU: 0 PID: 122 Comm: sh Not tainted 6.0.0-rc3-00007-gdcf8e5633e2e #10 + NIP: c000000000050bfc LR: c000000000050bec CTR: 0000000000005bdc + REGS: c0000000348475b0 TRAP: 0300 Not tainted (6.0.0-rc3-00007-gdcf8e5633e2e) + MSR: 9000000000009033 CR: 88002444 XER: 20040006 + CFAR: c00000000022d100 DAR: 0000000000000000 DSISR: 40000000 IRQMASK: 0 + ... + NIP arch_prepare_kprobe+0x10c/0x2d0 + LR arch_prepare_kprobe+0xfc/0x2d0 + Call Trace: + 0xc0000000012f77a0 (unreliable) + register_kprobe+0x3c0/0x7a0 + __register_trace_kprobe+0x140/0x1a0 + __trace_kprobe_create+0x794/0x1040 + trace_probe_create+0xc4/0xe0 + create_or_delete_trace_kprobe+0x2c/0x80 + trace_parse_run_command+0xf0/0x210 + probes_write+0x20/0x40 + vfs_write+0xfc/0x450 + ksys_write+0x84/0x140 + system_call_exception+0x17c/0x3a0 + system_call_vectored_common+0xe8/0x278 + --- interrupt: 3000 at 0x7fffa5682de0 + NIP: 00007fffa5682de0 LR: 0000000000000000 CTR: 0000000000000000 + REGS: c000000034847e80 TRAP: 3000 Not tainted (6.0.0-rc3-00007-gdcf8e5633e2e) + MSR: 900000000280f033 CR: 44002408 XER: 00000000 + +The address being probed has some special: + + cmdline_proc_show: Probe based on ftrace + cmdline_proc_show+16: Probe for the next instruction at the ftrace location + +The ftrace-based kprobe does not generate kprobe::ainsn::insn, it gets +set to NULL. In arch_prepare_kprobe() it will check for: + + ... + prev = get_kprobe(p->addr - 1); + preempt_enable_no_resched(); + if (prev && ppc_inst_prefixed(ppc_inst_read(prev->ainsn.insn))) { + ... + +If prev is based on ftrace, 'ppc_inst_read(prev->ainsn.insn)' will occur +with a null pointer reference. At this point prev->addr will not be a +prefixed instruction, so the check can be skipped. + +Check if prev is ftrace-based kprobe before reading 'prev->ainsn.insn' +to fix this problem. + +Fixes: b4657f7650ba ("powerpc/kprobes: Don't allow breakpoints on suffixes") +Signed-off-by: Li Huafei +[mpe: Trim oops] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220923093253.177298-1-lihuafei1@huawei.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/kprobes.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c +index 1c97c0f177ae..ed4f6b992f97 100644 +--- a/arch/powerpc/kernel/kprobes.c ++++ b/arch/powerpc/kernel/kprobes.c +@@ -161,7 +161,13 @@ int arch_prepare_kprobe(struct kprobe *p) + preempt_disable(); + prev = get_kprobe(p->addr - 1); + preempt_enable_no_resched(); +- if (prev && ppc_inst_prefixed(ppc_inst_read(prev->ainsn.insn))) { ++ ++ /* ++ * When prev is a ftrace-based kprobe, we don't have an insn, and it ++ * doesn't probe for prefixed instruction. ++ */ ++ if (prev && !kprobe_ftrace(prev) && ++ ppc_inst_prefixed(ppc_inst_read(prev->ainsn.insn))) { + printk("Cannot register a kprobe on the second word of prefixed instruction\n"); + ret = -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.19/powerpc-math_emu-efp-include-module.h.patch b/queue-5.19/powerpc-math_emu-efp-include-module.h.patch new file mode 100644 index 00000000000..d06b114cc96 --- /dev/null +++ b/queue-5.19/powerpc-math_emu-efp-include-module.h.patch @@ -0,0 +1,53 @@ +From bd5f048f3f8a42184beebaec86923001bb8d952e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 18:00:08 +0200 +Subject: powerpc/math_emu/efp: Include module.h + +From: Nathan Chancellor + +[ Upstream commit cfe0d370e0788625ce0df3239aad07a2506c1796 ] + +When building with a recent version of clang, there are a couple of +errors around the call to module_init(): + + arch/powerpc/math-emu/math_efp.c:927:1: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int] + module_init(spe_mathemu_init); + ^ + int + arch/powerpc/math-emu/math_efp.c:927:13: error: a parameter list without types is only allowed in a function definition + module_init(spe_mathemu_init); + ^ + 2 errors generated. + +module_init() is a macro, which is not getting expanded because module.h +is not included in this file. Add the include so that the macro can +expand properly, clearing up the build failure. + +Fixes: ac6f120369ff ("powerpc/85xx: Workaroudn e500 CPU erratum A005") +[chleroy: added fixes tag] +Reported-by: kernel test robot +Signed-off-by: Nathan Chancellor +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Reviewed-by: Christophe Leroy +Link: https://lore.kernel.org/r/8403854a4c187459b2f4da3537f51227b70b9223.1662134272.git.christophe.leroy@csgroup.eu +Signed-off-by: Sasha Levin +--- + arch/powerpc/math-emu/math_efp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c +index 39b84e7452e1..aa3bb8da1cb9 100644 +--- a/arch/powerpc/math-emu/math_efp.c ++++ b/arch/powerpc/math-emu/math_efp.c +@@ -17,6 +17,7 @@ + + #include + #include ++#include + + #include + #include +-- +2.35.1 + diff --git a/queue-5.19/powerpc-pci_dn-add-missing-of_node_put.patch b/queue-5.19/powerpc-pci_dn-add-missing-of_node_put.patch new file mode 100644 index 00000000000..89ea4766563 --- /dev/null +++ b/queue-5.19/powerpc-pci_dn-add-missing-of_node_put.patch @@ -0,0 +1,38 @@ +From a9dedcd87b02684979481556c42705e4c1c0a356 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Jul 2022 21:17:50 +0800 +Subject: powerpc/pci_dn: Add missing of_node_put() + +From: Liang He + +[ Upstream commit 110a1fcb6c4d55144d8179983a475f17a1d6f832 ] + +In pci_add_device_node_info(), use of_node_put() to drop the reference +to 'parent' returned by of_get_parent() to keep refcount balance. + +Fixes: cca87d303c85 ("powerpc/pci: Refactor pci_dn") +Co-authored-by: Miaoqian Lin +Signed-off-by: Liang He +Signed-off-by: Michael Ellerman +Reviewed-by: Tyrel Datwyler +Link: https://lore.kernel.org/r/20220701131750.240170-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/kernel/pci_dn.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c +index 938ab8838ab5..aa221958007e 100644 +--- a/arch/powerpc/kernel/pci_dn.c ++++ b/arch/powerpc/kernel/pci_dn.c +@@ -330,6 +330,7 @@ struct pci_dn *pci_add_device_node_info(struct pci_controller *hose, + INIT_LIST_HEAD(&pdn->list); + parent = of_get_parent(dn); + pdn->parent = parent ? PCI_DN(parent) : NULL; ++ of_node_put(parent); + if (pdn->parent) + list_add_tail(&pdn->list, &pdn->parent->child_list); + +-- +2.35.1 + diff --git a/queue-5.19/powerpc-powernv-add-missing-of_node_put-in-opal_expo.patch b/queue-5.19/powerpc-powernv-add-missing-of_node_put-in-opal_expo.patch new file mode 100644 index 00000000000..18b63cc5fd9 --- /dev/null +++ b/queue-5.19/powerpc-powernv-add-missing-of_node_put-in-opal_expo.patch @@ -0,0 +1,36 @@ +From 2773eee060afa0ca55bd6f8016e95d30161568c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 14:17:03 +0000 +Subject: powerpc/powernv: add missing of_node_put() in opal_export_attrs() + +From: Zheng Yongjun + +[ Upstream commit 71a92e99c47900cc164620948b3863382cec4f1a ] + +After using 'np' returned by of_find_node_by_path(), of_node_put() +need be called to decrease the refcount. + +Fixes: 11fe909d2362 ("powerpc/powernv: Add OPAL exports attributes to sysfs") +Signed-off-by: Zheng Yongjun +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220906141703.118192-1-zhengyongjun3@huawei.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/powernv/opal.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c +index 55a8fbfdb5b2..3510b55b36f8 100644 +--- a/arch/powerpc/platforms/powernv/opal.c ++++ b/arch/powerpc/platforms/powernv/opal.c +@@ -892,6 +892,7 @@ static void opal_export_attrs(void) + kobj = kobject_create_and_add("exports", opal_kobj); + if (!kobj) { + pr_warn("kobject_create_and_add() of exports failed\n"); ++ of_node_put(np); + return; + } + +-- +2.35.1 + diff --git a/queue-5.19/powerpc-pseries-vas-pass-hw_cpu_id-to-node-associati.patch b/queue-5.19/powerpc-pseries-vas-pass-hw_cpu_id-to-node-associati.patch new file mode 100644 index 00000000000..da04bb9aed8 --- /dev/null +++ b/queue-5.19/powerpc-pseries-vas-pass-hw_cpu_id-to-node-associati.patch @@ -0,0 +1,50 @@ +From cd115763b501f00d9d456e84eb1c6a98060cc866 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 18:57:33 -0700 +Subject: powerpc/pseries/vas: Pass hw_cpu_id to node associativity HCALL + +From: Haren Myneni + +[ Upstream commit f3e5d9e53e74d77e711a2c90a91a8b0836a9e0b3 ] + +Generally the hypervisor decides to allocate a window on different +VAS instances. But if user space wishes to allocate on the current VAS +instance where the process is executing, the kernel has to pass +associativity domain IDs to allocate VAS window HCALL. + +To determine the associativity domain IDs for the current CPU, +smp_processor_id() is passed to node associativity HCALL which may +return H_P2 (-55) error during DLPAR CPU event. This is because Linux +CPU numbers (smp_processor_id()) are not the same as the hypervisor's +view of CPU numbers. + +Fix the issue by passing hard_smp_processor_id() with +VPHN_FLAG_VCPU flag (PAPR 14.11.6.1 H_HOME_NODE_ASSOCIATIVITY). + +Fixes: b22f2d88e435 ("powerpc/pseries/vas: Integrate API with open/close windows") +Reviewed-by: Nathan Lynch +Signed-off-by: Haren Myneni +[mpe: Update change log to mention Linux vs HV CPU numbers] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/55380253ea0c11341824cd4c0fc6bbcfc5752689.camel@linux.ibm.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/platforms/pseries/vas.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c +index 500a1fc4a1d7..b2a32f8a837a 100644 +--- a/arch/powerpc/platforms/pseries/vas.c ++++ b/arch/powerpc/platforms/pseries/vas.c +@@ -332,7 +332,7 @@ static struct vas_window *vas_allocate_window(int vas_id, u64 flags, + * So no unpacking needs to be done. + */ + rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, domain, +- VPHN_FLAG_VCPU, smp_processor_id()); ++ VPHN_FLAG_VCPU, hard_smp_processor_id()); + if (rc != H_SUCCESS) { + pr_err("H_HOME_NODE_ASSOCIATIVITY error: %d\n", rc); + goto out; +-- +2.35.1 + diff --git a/queue-5.19/powerpc-sysdev-fsl_msi-add-missing-of_node_put.patch b/queue-5.19/powerpc-sysdev-fsl_msi-add-missing-of_node_put.patch new file mode 100644 index 00000000000..8b03d0d6a99 --- /dev/null +++ b/queue-5.19/powerpc-sysdev-fsl_msi-add-missing-of_node_put.patch @@ -0,0 +1,40 @@ +From 8bbc40805e93f71e417547c12f9436b3242614c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 22:52:33 +0800 +Subject: powerpc/sysdev/fsl_msi: Add missing of_node_put() + +From: Liang He + +[ Upstream commit def435c04ee984a5f9ed2711b2bfe946936c6a21 ] + +In fsl_setup_msi_irqs(), use of_node_put() to drop the reference +returned by of_parse_phandle(). + +Fixes: 895d603f945ba ("powerpc/fsl_msi: add support for the fsl, msi property in PCI nodes") +Co-authored-by: Miaoqian Lin +Signed-off-by: Liang He +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20220704145233.278539-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + arch/powerpc/sysdev/fsl_msi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c +index ef9a5999fa93..73c2d70706c0 100644 +--- a/arch/powerpc/sysdev/fsl_msi.c ++++ b/arch/powerpc/sysdev/fsl_msi.c +@@ -209,8 +209,10 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) + dev_err(&pdev->dev, + "node %pOF has an invalid fsl,msi phandle %u\n", + hose->dn, np->phandle); ++ of_node_put(np); + return -EINVAL; + } ++ of_node_put(np); + } + + msi_for_each_desc(entry, &pdev->dev, MSI_DESC_NOTASSOCIATED) { +-- +2.35.1 + diff --git a/queue-5.19/r8152-rate-limit-overflow-messages.patch b/queue-5.19/r8152-rate-limit-overflow-messages.patch new file mode 100644 index 00000000000..1a2d6e9056c --- /dev/null +++ b/queue-5.19/r8152-rate-limit-overflow-messages.patch @@ -0,0 +1,38 @@ +From 563b4b0416684b7ed68a029713cc16504ba787c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Oct 2022 12:41:28 +0900 +Subject: r8152: Rate limit overflow messages + +From: Andrew Gaul + +[ Upstream commit 93e2be344a7db169b7119de21ac1bf253b8c6907 ] + +My system shows almost 10 million of these messages over a 24-hour +period which pollutes my logs. + +Signed-off-by: Andrew Gaul +Link: https://lore.kernel.org/r/20221002034128.2026653-1-gaul@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/r8152.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c +index 688905ea0a6d..e7b0b59e2bc8 100644 +--- a/drivers/net/usb/r8152.c ++++ b/drivers/net/usb/r8152.c +@@ -1874,7 +1874,9 @@ static void intr_callback(struct urb *urb) + "Stop submitting intr, status %d\n", status); + return; + case -EOVERFLOW: +- netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n"); ++ if (net_ratelimit()) ++ netif_info(tp, intr, tp->netdev, ++ "intr status -EOVERFLOW\n"); + goto resubmit; + /* -EPIPE: should clear the halt */ + default: +-- +2.35.1 + diff --git a/queue-5.19/random-schedule-jitter-credit-for-next-jiffy-not-in-.patch b/queue-5.19/random-schedule-jitter-credit-for-next-jiffy-not-in-.patch new file mode 100644 index 00000000000..b33b65bf603 --- /dev/null +++ b/queue-5.19/random-schedule-jitter-credit-for-next-jiffy-not-in-.patch @@ -0,0 +1,50 @@ +From df47d4958f49cb99502d456bc078f92931b3592a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Oct 2022 00:31:00 +0200 +Subject: random: schedule jitter credit for next jiffy, not in two jiffies + +From: Jason A. Donenfeld + +[ Upstream commit 122733471384be8c23f019fbbd46bdf7be561dcd ] + +Counterintuitively, mod_timer(..., jiffies + 1) will cause the timer to +fire not in the next jiffy, but in two jiffies. The way to cause +the timer to fire in the next jiffy is with mod_timer(..., jiffies). +Doing so then lets us bump the upper bound back up again. + +Fixes: 50ee7529ec45 ("random: try to actively add entropy rather than passively wait for it") +Fixes: 829d680e82a9 ("random: cap jitter samples per bit to factor of HZ") +Cc: Dominik Brodowski +Cc: Sebastian Andrzej Siewior +Cc: Sultan Alsawaf +Signed-off-by: Jason A. Donenfeld +Signed-off-by: Sasha Levin +--- + drivers/char/random.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 8dfb28d5ae3f..5defbc479a5c 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1178,7 +1178,7 @@ static void __cold entropy_timer(struct timer_list *timer) + */ + static void __cold try_to_generate_entropy(void) + { +- enum { NUM_TRIAL_SAMPLES = 8192, MAX_SAMPLES_PER_BIT = HZ / 30 }; ++ enum { NUM_TRIAL_SAMPLES = 8192, MAX_SAMPLES_PER_BIT = HZ / 15 }; + struct entropy_timer_state stack; + unsigned int i, num_different = 0; + unsigned long last = random_get_entropy(); +@@ -1197,7 +1197,7 @@ static void __cold try_to_generate_entropy(void) + timer_setup_on_stack(&stack.timer, entropy_timer, 0); + while (!crng_ready() && !signal_pending(current)) { + if (!timer_pending(&stack.timer)) +- mod_timer(&stack.timer, jiffies + 1); ++ mod_timer(&stack.timer, jiffies); + mix_pool_bytes(&stack.entropy, sizeof(stack.entropy)); + schedule(); + stack.entropy = random_get_entropy(); +-- +2.35.1 + diff --git a/queue-5.19/rcu-avoid-triggering-strict-gp-irq-work-when-rcu-is-.patch b/queue-5.19/rcu-avoid-triggering-strict-gp-irq-work-when-rcu-is-.patch new file mode 100644 index 00000000000..923d01b99d1 --- /dev/null +++ b/queue-5.19/rcu-avoid-triggering-strict-gp-irq-work-when-rcu-is-.patch @@ -0,0 +1,77 @@ +From e0cd1951214c4041672844d9800576f5f637c559 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Aug 2022 10:26:26 +0800 +Subject: rcu: Avoid triggering strict-GP irq-work when RCU is idle + +From: Zqiang + +[ Upstream commit 621189a1fe93cb2b34d62c5cdb9e258bca044813 ] + +Kernels built with PREEMPT_RCU=y and RCU_STRICT_GRACE_PERIOD=y trigger +irq-work from rcu_read_unlock(), and the resulting irq-work handler +invokes rcu_preempt_deferred_qs_handle(). The point of this triggering +is to force grace periods to end quickly in order to give tools like KASAN +a better chance of detecting RCU usage bugs such as leaking RCU-protected +pointers out of an RCU read-side critical section. + +However, this irq-work triggering is unconditional. This works, but +there is no point in doing this irq-work unless the current grace period +is waiting on the running CPU or task, which is not the common case. +After all, in the common case there are many rcu_read_unlock() calls +per CPU per grace period. + +This commit therefore triggers the irq-work only when the current grace +period is waiting on the running CPU or task. + +This change was tested as follows on a four-CPU system: + + echo rcu_preempt_deferred_qs_handler > /sys/kernel/debug/tracing/set_ftrace_filter + echo 1 > /sys/kernel/debug/tracing/function_profile_enabled + insmod rcutorture.ko + sleep 20 + rmmod rcutorture.ko + echo 0 > /sys/kernel/debug/tracing/function_profile_enabled + echo > /sys/kernel/debug/tracing/set_ftrace_filter + +This procedure produces results in this per-CPU set of files: + + /sys/kernel/debug/tracing/trace_stat/function* + +Sample output from one of these files is as follows: + + Function Hit Time Avg s^2 + -------- --- ---- --- --- + rcu_preempt_deferred_qs_handle 838746 182650.3 us 0.217 us 0.004 us + +The baseline sum of the "Hit" values (the number of calls to this +function) was 3,319,015. With this commit, that sum was 1,140,359, +for a 2.9x reduction. The worst-case variance across the CPUs was less +than 25%, so this large effect size is statistically significant. + +The raw data is available in the Link: URL. + +Link: https://lore.kernel.org/all/20220808022626.12825-1-qiang1.zhang@intel.com/ +Signed-off-by: Zqiang +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + kernel/rcu/tree_plugin.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h +index c8ba0fe17267..d164938528cd 100644 +--- a/kernel/rcu/tree_plugin.h ++++ b/kernel/rcu/tree_plugin.h +@@ -641,7 +641,8 @@ static void rcu_read_unlock_special(struct task_struct *t) + + expboost = (t->rcu_blocked_node && READ_ONCE(t->rcu_blocked_node->exp_tasks)) || + (rdp->grpmask & READ_ONCE(rnp->expmask)) || +- IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) || ++ (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && ++ ((rdp->grpmask & READ_ONCE(rnp->qsmask)) || t->rcu_blocked_node)) || + (IS_ENABLED(CONFIG_RCU_BOOST) && irqs_were_disabled && + t->rcu_blocked_node); + // Need to defer quiescent state until everything is enabled. +-- +2.35.1 + diff --git a/queue-5.19/rcu-back-off-upon-fill_page_cache_func-allocation-fa.patch b/queue-5.19/rcu-back-off-upon-fill_page_cache_func-allocation-fa.patch new file mode 100644 index 00000000000..990f8ebda84 --- /dev/null +++ b/queue-5.19/rcu-back-off-upon-fill_page_cache_func-allocation-fa.patch @@ -0,0 +1,89 @@ +From c5de93a7bcdc9be7ce18d950ca1946b2dbb171d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jun 2022 13:47:11 +0200 +Subject: rcu: Back off upon fill_page_cache_func() allocation failure + +From: Michal Hocko + +[ Upstream commit 093590c16b447f53e66771c8579ae66c96f6ef61 ] + +The fill_page_cache_func() function allocates couple of pages to store +kvfree_rcu_bulk_data structures. This is a lightweight (GFP_NORETRY) +allocation which can fail under memory pressure. The function will, +however keep retrying even when the previous attempt has failed. + +This retrying is in theory correct, but in practice the allocation is +invoked from workqueue context, which means that if the memory reclaim +gets stuck, these retries can hog the worker for quite some time. +Although the workqueues subsystem automatically adjusts concurrency, such +adjustment is not guaranteed to happen until the worker context sleeps. +And the fill_page_cache_func() function's retry loop is not guaranteed +to sleep (see the should_reclaim_retry() function). + +And we have seen this function cause workqueue lockups: + +kernel: BUG: workqueue lockup - pool cpus=93 node=1 flags=0x1 nice=0 stuck for 32s! +[...] +kernel: pool 74: cpus=37 node=0 flags=0x1 nice=0 hung=32s workers=2 manager: 2146 +kernel: pwq 498: cpus=249 node=1 flags=0x1 nice=0 active=4/256 refcnt=5 +kernel: in-flight: 1917:fill_page_cache_func +kernel: pending: dbs_work_handler, free_work, kfree_rcu_monitor + +Originally, we thought that the root cause of this lockup was several +retries with direct reclaim, but this is not yet confirmed. Furthermore, +we have seen similar lockups without any heavy memory pressure. This +suggests that there are other factors contributing to these lockups. +However, it is not really clear that endless retries are desireable. + +So let's make the fill_page_cache_func() function back off after +allocation failure. + +Cc: Uladzislau Rezki (Sony) +Cc: "Paul E. McKenney" +Cc: Frederic Weisbecker +Cc: Neeraj Upadhyay +Cc: Josh Triplett +Cc: Steven Rostedt +Cc: Mathieu Desnoyers +Cc: Lai Jiangshan +Cc: Joel Fernandes +Signed-off-by: Michal Hocko +Reviewed-by: Uladzislau Rezki (Sony) +Signed-off-by: Paul E. McKenney +Signed-off-by: Sasha Levin +--- + kernel/rcu/tree.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c +index c25ba442044a..54a3a19c4c0b 100644 +--- a/kernel/rcu/tree.c ++++ b/kernel/rcu/tree.c +@@ -3508,15 +3508,16 @@ static void fill_page_cache_func(struct work_struct *work) + bnode = (struct kvfree_rcu_bulk_data *) + __get_free_page(GFP_KERNEL | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); + +- if (bnode) { +- raw_spin_lock_irqsave(&krcp->lock, flags); +- pushed = put_cached_bnode(krcp, bnode); +- raw_spin_unlock_irqrestore(&krcp->lock, flags); ++ if (!bnode) ++ break; + +- if (!pushed) { +- free_page((unsigned long) bnode); +- break; +- } ++ raw_spin_lock_irqsave(&krcp->lock, flags); ++ pushed = put_cached_bnode(krcp, bnode); ++ raw_spin_unlock_irqrestore(&krcp->lock, flags); ++ ++ if (!pushed) { ++ free_page((unsigned long) bnode); ++ break; + } + } + +-- +2.35.1 + diff --git a/queue-5.19/rdma-cm-use-slid-in-the-work-completion-as-the-dlid-.patch b/queue-5.19/rdma-cm-use-slid-in-the-work-completion-as-the-dlid-.patch new file mode 100644 index 00000000000..4899685f567 --- /dev/null +++ b/queue-5.19/rdma-cm-use-slid-in-the-work-completion-as-the-dlid-.patch @@ -0,0 +1,80 @@ +From 0b7745eb14fb309024f887ad37b019d6f2348ae1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 13:09:02 +0300 +Subject: RDMA/cm: Use SLID in the work completion as the DLID in responder + side + +From: Mark Zhang + +[ Upstream commit b7d95040c13f61a4a6a859c5355faf583eff9658 ] + +The responder should always use WC's SLID as the dlid, to follow the +IB SPEC section "13.5.4.2 COMMON RESPONSE ACTIONS": +A responder always takes the following actions in constructing a +response packet: +- The SLID of the received packet is used as the DLID in the response + packet. + +Fixes: ac3a949fb2ff ("IB/CM: Set appropriate slid and dlid when handling CM request") +Signed-off-by: Mark Zhang +Reviewed-by: Mark Bloch +Link: https://lore.kernel.org/r/cd17c240231e059d2fc07c17dfe555d548b917eb.1662631201.git.leonro@nvidia.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/core/cm.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c +index b985e0d9bc05..5c910f5c01b3 100644 +--- a/drivers/infiniband/core/cm.c ++++ b/drivers/infiniband/core/cm.c +@@ -1632,14 +1632,13 @@ static void cm_path_set_rec_type(struct ib_device *ib_device, u32 port_num, + + static void cm_format_path_lid_from_req(struct cm_req_msg *req_msg, + struct sa_path_rec *primary_path, +- struct sa_path_rec *alt_path) ++ struct sa_path_rec *alt_path, ++ struct ib_wc *wc) + { + u32 lid; + + if (primary_path->rec_type != SA_PATH_REC_TYPE_OPA) { +- sa_path_set_dlid(primary_path, +- IBA_GET(CM_REQ_PRIMARY_LOCAL_PORT_LID, +- req_msg)); ++ sa_path_set_dlid(primary_path, wc->slid); + sa_path_set_slid(primary_path, + IBA_GET(CM_REQ_PRIMARY_REMOTE_PORT_LID, + req_msg)); +@@ -1676,7 +1675,8 @@ static void cm_format_path_lid_from_req(struct cm_req_msg *req_msg, + + static void cm_format_paths_from_req(struct cm_req_msg *req_msg, + struct sa_path_rec *primary_path, +- struct sa_path_rec *alt_path) ++ struct sa_path_rec *alt_path, ++ struct ib_wc *wc) + { + primary_path->dgid = + *IBA_GET_MEM_PTR(CM_REQ_PRIMARY_LOCAL_PORT_GID, req_msg); +@@ -1734,7 +1734,7 @@ static void cm_format_paths_from_req(struct cm_req_msg *req_msg, + if (sa_path_is_roce(alt_path)) + alt_path->roce.route_resolved = false; + } +- cm_format_path_lid_from_req(req_msg, primary_path, alt_path); ++ cm_format_path_lid_from_req(req_msg, primary_path, alt_path, wc); + } + + static u16 cm_get_bth_pkey(struct cm_work *work) +@@ -2148,7 +2148,7 @@ static int cm_req_handler(struct cm_work *work) + if (cm_req_has_alt_path(req_msg)) + work->path[1].rec_type = work->path[0].rec_type; + cm_format_paths_from_req(req_msg, &work->path[0], +- &work->path[1]); ++ &work->path[1], work->mad_recv_wc->wc); + if (cm_id_priv->av.ah_attr.type == RDMA_AH_ATTR_TYPE_ROCE) + sa_path_set_dmac(&work->path[0], + cm_id_priv->av.ah_attr.roce.dmac); +-- +2.35.1 + diff --git a/queue-5.19/rdma-irdma-align-ae-id-codes-to-correct-flush-code-a.patch b/queue-5.19/rdma-irdma-align-ae-id-codes-to-correct-flush-code-a.patch new file mode 100644 index 00000000000..72102d596f0 --- /dev/null +++ b/queue-5.19/rdma-irdma-align-ae-id-codes-to-correct-flush-code-a.patch @@ -0,0 +1,191 @@ +From 272a7a88c7a129d8744e361d98815d4de68274b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 14:13:23 -0500 +Subject: RDMA/irdma: Align AE id codes to correct flush code and event + +From: Sindhu-Devale + +[ Upstream commit 7f51a961f8c6b84752a48e950074a8c4a0808d91 ] + +A number of asynchronous event (AE) ids were not aligned to the +correct flush_code and event_type. Fix these up so that the +correct IBV error and event codes are returned to application. + +Also, add handling for new AE ids like IRDMA_AE_INVALID_REQUEST to +return the correct WC error code. + +Fixes: 44d9e52977a1 ("RDMA/irdma: Implement device initialization definitions") +Signed-off-by: Sindhu-Devale +Signed-off-by: Shiraz Saleem +Link: https://lore.kernel.org/r/20220907191324.1173-2-shiraz.saleem@intel.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/defs.h | 1 + + drivers/infiniband/hw/irdma/hw.c | 51 +++++++++++++++++------------ + drivers/infiniband/hw/irdma/type.h | 1 + + drivers/infiniband/hw/irdma/user.h | 1 + + drivers/infiniband/hw/irdma/utils.c | 3 ++ + drivers/infiniband/hw/irdma/verbs.c | 2 ++ + 6 files changed, 38 insertions(+), 21 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/defs.h b/drivers/infiniband/hw/irdma/defs.h +index e03e03082a5f..c1906cab5c8a 100644 +--- a/drivers/infiniband/hw/irdma/defs.h ++++ b/drivers/infiniband/hw/irdma/defs.h +@@ -314,6 +314,7 @@ enum irdma_cqp_op_type { + #define IRDMA_AE_IB_REMOTE_ACCESS_ERROR 0x020d + #define IRDMA_AE_IB_REMOTE_OP_ERROR 0x020e + #define IRDMA_AE_WQE_LSMM_TOO_LONG 0x0220 ++#define IRDMA_AE_INVALID_REQUEST 0x0223 + #define IRDMA_AE_DDP_INVALID_MSN_GAP_IN_MSN 0x0301 + #define IRDMA_AE_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER 0x0303 + #define IRDMA_AE_DDP_UBE_INVALID_DDP_VERSION 0x0304 +diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c +index 6bba1335993a..971cc7a7f3bc 100644 +--- a/drivers/infiniband/hw/irdma/hw.c ++++ b/drivers/infiniband/hw/irdma/hw.c +@@ -138,59 +138,68 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp, + qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + + switch (info->ae_id) { +- case IRDMA_AE_AMP_UNALLOCATED_STAG: + case IRDMA_AE_AMP_BOUNDS_VIOLATION: + case IRDMA_AE_AMP_INVALID_STAG: +- qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; +- fallthrough; ++ case IRDMA_AE_AMP_RIGHTS_VIOLATION: ++ case IRDMA_AE_AMP_UNALLOCATED_STAG: + case IRDMA_AE_AMP_BAD_PD: +- case IRDMA_AE_UDA_XMIT_BAD_PD: ++ case IRDMA_AE_AMP_BAD_QP: ++ case IRDMA_AE_AMP_BAD_STAG_KEY: ++ case IRDMA_AE_AMP_BAD_STAG_INDEX: ++ case IRDMA_AE_AMP_TO_WRAP: ++ case IRDMA_AE_PRIV_OPERATION_DENIED: + qp->flush_code = FLUSH_PROT_ERR; ++ qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; + break; +- case IRDMA_AE_AMP_BAD_QP: ++ case IRDMA_AE_UDA_XMIT_BAD_PD: + case IRDMA_AE_WQE_UNEXPECTED_OPCODE: + qp->flush_code = FLUSH_LOC_QP_OP_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; ++ break; ++ case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: ++ case IRDMA_AE_UDA_XMIT_DGRAM_TOO_SHORT: ++ case IRDMA_AE_UDA_L4LEN_INVALID: ++ case IRDMA_AE_DDP_UBE_INVALID_MO: ++ case IRDMA_AE_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: ++ qp->flush_code = FLUSH_LOC_LEN_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + break; +- case IRDMA_AE_AMP_BAD_STAG_KEY: +- case IRDMA_AE_AMP_BAD_STAG_INDEX: +- case IRDMA_AE_AMP_TO_WRAP: +- case IRDMA_AE_AMP_RIGHTS_VIOLATION: + case IRDMA_AE_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS: +- case IRDMA_AE_PRIV_OPERATION_DENIED: +- case IRDMA_AE_IB_INVALID_REQUEST: + case IRDMA_AE_IB_REMOTE_ACCESS_ERROR: + qp->flush_code = FLUSH_REM_ACCESS_ERR; + qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; + break; + case IRDMA_AE_LLP_SEGMENT_TOO_SMALL: +- case IRDMA_AE_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER: +- case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: +- case IRDMA_AE_UDA_XMIT_DGRAM_TOO_SHORT: +- case IRDMA_AE_UDA_L4LEN_INVALID: ++ case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: + case IRDMA_AE_ROCE_RSP_LENGTH_ERROR: +- qp->flush_code = FLUSH_LOC_LEN_ERR; ++ case IRDMA_AE_IB_REMOTE_OP_ERROR: ++ qp->flush_code = FLUSH_REM_OP_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + break; + case IRDMA_AE_LCE_QP_CATASTROPHIC: + qp->flush_code = FLUSH_FATAL_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + break; +- case IRDMA_AE_DDP_UBE_INVALID_MO: + case IRDMA_AE_IB_RREQ_AND_Q1_FULL: +- case IRDMA_AE_LLP_RECEIVED_MPA_CRC_ERROR: + qp->flush_code = FLUSH_GENERAL_ERR; + break; + case IRDMA_AE_LLP_TOO_MANY_RETRIES: + qp->flush_code = FLUSH_RETRY_EXC_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + break; + case IRDMA_AE_AMP_MWBIND_INVALID_RIGHTS: + case IRDMA_AE_AMP_MWBIND_BIND_DISABLED: + case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS: + qp->flush_code = FLUSH_MW_BIND_ERR; ++ qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR; + break; +- case IRDMA_AE_IB_REMOTE_OP_ERROR: +- qp->flush_code = FLUSH_REM_OP_ERR; ++ case IRDMA_AE_IB_INVALID_REQUEST: ++ qp->flush_code = FLUSH_REM_INV_REQ_ERR; ++ qp->event_type = IRDMA_QP_EVENT_REQ_ERR; + break; + default: +- qp->flush_code = FLUSH_FATAL_ERR; ++ qp->flush_code = FLUSH_GENERAL_ERR; ++ qp->event_type = IRDMA_QP_EVENT_CATASTROPHIC; + break; + } + } +diff --git a/drivers/infiniband/hw/irdma/type.h b/drivers/infiniband/hw/irdma/type.h +index 9e7b8ecb137a..517d41a1c289 100644 +--- a/drivers/infiniband/hw/irdma/type.h ++++ b/drivers/infiniband/hw/irdma/type.h +@@ -98,6 +98,7 @@ enum irdma_term_mpa_errors { + enum irdma_qp_event_type { + IRDMA_QP_EVENT_CATASTROPHIC, + IRDMA_QP_EVENT_ACCESS_ERR, ++ IRDMA_QP_EVENT_REQ_ERR, + }; + + enum irdma_hw_stats_index_32b { +diff --git a/drivers/infiniband/hw/irdma/user.h b/drivers/infiniband/hw/irdma/user.h +index ddd0ebbdd7d5..2ef61923c926 100644 +--- a/drivers/infiniband/hw/irdma/user.h ++++ b/drivers/infiniband/hw/irdma/user.h +@@ -103,6 +103,7 @@ enum irdma_flush_opcode { + FLUSH_FATAL_ERR, + FLUSH_RETRY_EXC_ERR, + FLUSH_MW_BIND_ERR, ++ FLUSH_REM_INV_REQ_ERR, + }; + + enum irdma_cmpl_status { +diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c +index f4d774451160..c9513b9fc42d 100644 +--- a/drivers/infiniband/hw/irdma/utils.c ++++ b/drivers/infiniband/hw/irdma/utils.c +@@ -2478,6 +2478,9 @@ void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event) + case IRDMA_QP_EVENT_ACCESS_ERR: + ibevent.event = IB_EVENT_QP_ACCESS_ERR; + break; ++ case IRDMA_QP_EVENT_REQ_ERR: ++ ibevent.event = IB_EVENT_QP_REQ_ERR; ++ break; + } + ibevent.device = iwqp->ibqp.device; + ibevent.element.qp = &iwqp->ibqp; +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index ab73d1715f99..7cd50147de1d 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -3307,6 +3307,8 @@ static enum ib_wc_status irdma_flush_err_to_ib_wc_status(enum irdma_flush_opcode + return IB_WC_RETRY_EXC_ERR; + case FLUSH_MW_BIND_ERR: + return IB_WC_MW_BIND_ERR; ++ case FLUSH_REM_INV_REQ_ERR: ++ return IB_WC_REM_INV_REQ_ERR; + case FLUSH_FATAL_ERR: + default: + return IB_WC_FATAL_ERR; +-- +2.35.1 + diff --git a/queue-5.19/rdma-irdma-validate-udata-inlen-and-outlen.patch b/queue-5.19/rdma-irdma-validate-udata-inlen-and-outlen.patch new file mode 100644 index 00000000000..a0f3c2b4e93 --- /dev/null +++ b/queue-5.19/rdma-irdma-validate-udata-inlen-and-outlen.patch @@ -0,0 +1,270 @@ +From 6ef3793013d2d2df64e42f8052a6a7abb09eea0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 14:13:24 -0500 +Subject: RDMA/irdma: Validate udata inlen and outlen + +From: Shiraz Saleem + +[ Upstream commit 34acb833cc83bdea912a160ff99b537e62bb4cf3 ] + +Currently ib_copy_from_udata and ib_copy_to_udata could underfill +the request and response buffer if the user-space passes an undersized +value for udata->inlen or udata->outlen respectively [1] +This could lead to undesirable behavior. + +Zero initing the buffer only goes as far as preventing using the buffer +uninitialized. + +Validate udata->inlen and udata->outlen passed from user-space to ensure +they are at least the required minimum size. + +[1] https://lore.kernel.org/linux-rdma/MWHPR11MB0029F37D40D9D4A993F8F549E9D79@MWHPR11MB0029.namprd11.prod.outlook.com/ + +Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs") +Reported-by: Dan Carpenter +Signed-off-by: Shiraz Saleem +Link: https://lore.kernel.org/r/20220907191324.1173-3-shiraz.saleem@intel.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/irdma/verbs.c | 67 ++++++++++++++++++++++++++--- + 1 file changed, 60 insertions(+), 7 deletions(-) + +diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c +index 7cd50147de1d..c5652efb3df2 100644 +--- a/drivers/infiniband/hw/irdma/verbs.c ++++ b/drivers/infiniband/hw/irdma/verbs.c +@@ -299,13 +299,19 @@ static void irdma_alloc_push_page(struct irdma_qp *iwqp) + static int irdma_alloc_ucontext(struct ib_ucontext *uctx, + struct ib_udata *udata) + { ++#define IRDMA_ALLOC_UCTX_MIN_REQ_LEN offsetofend(struct irdma_alloc_ucontext_req, rsvd8) ++#define IRDMA_ALLOC_UCTX_MIN_RESP_LEN offsetofend(struct irdma_alloc_ucontext_resp, rsvd) + struct ib_device *ibdev = uctx->device; + struct irdma_device *iwdev = to_iwdev(ibdev); +- struct irdma_alloc_ucontext_req req; ++ struct irdma_alloc_ucontext_req req = {}; + struct irdma_alloc_ucontext_resp uresp = {}; + struct irdma_ucontext *ucontext = to_ucontext(uctx); + struct irdma_uk_attrs *uk_attrs; + ++ if (udata->inlen < IRDMA_ALLOC_UCTX_MIN_REQ_LEN || ++ udata->outlen < IRDMA_ALLOC_UCTX_MIN_RESP_LEN) ++ return -EINVAL; ++ + if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) + return -EINVAL; + +@@ -317,7 +323,7 @@ static int irdma_alloc_ucontext(struct ib_ucontext *uctx, + + uk_attrs = &iwdev->rf->sc_dev.hw_attrs.uk_attrs; + /* GEN_1 legacy support with libi40iw */ +- if (udata->outlen < sizeof(uresp)) { ++ if (udata->outlen == IRDMA_ALLOC_UCTX_MIN_RESP_LEN) { + if (uk_attrs->hw_rev != IRDMA_GEN_1) + return -EOPNOTSUPP; + +@@ -389,6 +395,7 @@ static void irdma_dealloc_ucontext(struct ib_ucontext *context) + */ + static int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata) + { ++#define IRDMA_ALLOC_PD_MIN_RESP_LEN offsetofend(struct irdma_alloc_pd_resp, rsvd) + struct irdma_pd *iwpd = to_iwpd(pd); + struct irdma_device *iwdev = to_iwdev(pd->device); + struct irdma_sc_dev *dev = &iwdev->rf->sc_dev; +@@ -398,6 +405,9 @@ static int irdma_alloc_pd(struct ib_pd *pd, struct ib_udata *udata) + u32 pd_id = 0; + int err; + ++ if (udata && udata->outlen < IRDMA_ALLOC_PD_MIN_RESP_LEN) ++ return -EINVAL; ++ + err = irdma_alloc_rsrc(rf, rf->allocated_pds, rf->max_pd, &pd_id, + &rf->next_pd); + if (err) +@@ -814,12 +824,14 @@ static int irdma_create_qp(struct ib_qp *ibqp, + struct ib_qp_init_attr *init_attr, + struct ib_udata *udata) + { ++#define IRDMA_CREATE_QP_MIN_REQ_LEN offsetofend(struct irdma_create_qp_req, user_compl_ctx) ++#define IRDMA_CREATE_QP_MIN_RESP_LEN offsetofend(struct irdma_create_qp_resp, rsvd) + struct ib_pd *ibpd = ibqp->pd; + struct irdma_pd *iwpd = to_iwpd(ibpd); + struct irdma_device *iwdev = to_iwdev(ibpd->device); + struct irdma_pci_f *rf = iwdev->rf; + struct irdma_qp *iwqp = to_iwqp(ibqp); +- struct irdma_create_qp_req req; ++ struct irdma_create_qp_req req = {}; + struct irdma_create_qp_resp uresp = {}; + u32 qp_num = 0; + int err_code; +@@ -836,6 +848,10 @@ static int irdma_create_qp(struct ib_qp *ibqp, + if (err_code) + return err_code; + ++ if (udata && (udata->inlen < IRDMA_CREATE_QP_MIN_REQ_LEN || ++ udata->outlen < IRDMA_CREATE_QP_MIN_RESP_LEN)) ++ return -EINVAL; ++ + sq_size = init_attr->cap.max_send_wr; + rq_size = init_attr->cap.max_recv_wr; + +@@ -1120,6 +1136,8 @@ static int irdma_query_pkey(struct ib_device *ibdev, u32 port, u16 index, + int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + int attr_mask, struct ib_udata *udata) + { ++#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush) ++#define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid) + struct irdma_pd *iwpd = to_iwpd(ibqp->pd); + struct irdma_qp *iwqp = to_iwqp(ibqp); + struct irdma_device *iwdev = iwqp->iwdev; +@@ -1138,6 +1156,13 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + roce_info = &iwqp->roce_info; + udp_info = &iwqp->udp_info; + ++ if (udata) { ++ /* udata inlen/outlen can be 0 when supporting legacy libi40iw */ ++ if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) || ++ (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)) ++ return -EINVAL; ++ } ++ + if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) + return -EOPNOTSUPP; + +@@ -1374,7 +1399,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + + if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) { + spin_unlock_irqrestore(&iwqp->lock, flags); +- if (udata) { ++ if (udata && udata->inlen) { + if (ib_copy_from_udata(&ureq, udata, + min(sizeof(ureq), udata->inlen))) + return -EINVAL; +@@ -1426,7 +1451,7 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + } else { + iwqp->ibqp_state = attr->qp_state; + } +- if (udata && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { ++ if (udata && udata->outlen && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { + struct irdma_ucontext *ucontext; + + ucontext = rdma_udata_to_drv_context(udata, +@@ -1466,6 +1491,8 @@ int irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, + int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, + struct ib_udata *udata) + { ++#define IRDMA_MODIFY_QP_MIN_REQ_LEN offsetofend(struct irdma_modify_qp_req, rq_flush) ++#define IRDMA_MODIFY_QP_MIN_RESP_LEN offsetofend(struct irdma_modify_qp_resp, push_valid) + struct irdma_qp *iwqp = to_iwqp(ibqp); + struct irdma_device *iwdev = iwqp->iwdev; + struct irdma_sc_dev *dev = &iwdev->rf->sc_dev; +@@ -1480,6 +1507,13 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, + int err; + unsigned long flags; + ++ if (udata) { ++ /* udata inlen/outlen can be 0 when supporting legacy libi40iw */ ++ if ((udata->inlen && udata->inlen < IRDMA_MODIFY_QP_MIN_REQ_LEN) || ++ (udata->outlen && udata->outlen < IRDMA_MODIFY_QP_MIN_RESP_LEN)) ++ return -EINVAL; ++ } ++ + if (attr_mask & ~IB_QP_ATTR_STANDARD_BITS) + return -EOPNOTSUPP; + +@@ -1565,7 +1599,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, + case IB_QPS_RESET: + if (iwqp->iwarp_state == IRDMA_QP_STATE_ERROR) { + spin_unlock_irqrestore(&iwqp->lock, flags); +- if (udata) { ++ if (udata && udata->inlen) { + if (ib_copy_from_udata(&ureq, udata, + min(sizeof(ureq), udata->inlen))) + return -EINVAL; +@@ -1662,7 +1696,7 @@ int irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, + } + } + } +- if (attr_mask & IB_QP_STATE && udata && ++ if (attr_mask & IB_QP_STATE && udata && udata->outlen && + dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { + struct irdma_ucontext *ucontext; + +@@ -1797,6 +1831,7 @@ static int irdma_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata) + static int irdma_resize_cq(struct ib_cq *ibcq, int entries, + struct ib_udata *udata) + { ++#define IRDMA_RESIZE_CQ_MIN_REQ_LEN offsetofend(struct irdma_resize_cq_req, user_cq_buffer) + struct irdma_cq *iwcq = to_iwcq(ibcq); + struct irdma_sc_dev *dev = iwcq->sc_cq.dev; + struct irdma_cqp_request *cqp_request; +@@ -1819,6 +1854,9 @@ static int irdma_resize_cq(struct ib_cq *ibcq, int entries, + IRDMA_FEATURE_CQ_RESIZE)) + return -EOPNOTSUPP; + ++ if (udata && udata->inlen < IRDMA_RESIZE_CQ_MIN_REQ_LEN) ++ return -EINVAL; ++ + if (entries > rf->max_cqe) + return -EINVAL; + +@@ -1951,6 +1989,8 @@ static int irdma_create_cq(struct ib_cq *ibcq, + const struct ib_cq_init_attr *attr, + struct ib_udata *udata) + { ++#define IRDMA_CREATE_CQ_MIN_REQ_LEN offsetofend(struct irdma_create_cq_req, user_cq_buf) ++#define IRDMA_CREATE_CQ_MIN_RESP_LEN offsetofend(struct irdma_create_cq_resp, cq_size) + struct ib_device *ibdev = ibcq->device; + struct irdma_device *iwdev = to_iwdev(ibdev); + struct irdma_pci_f *rf = iwdev->rf; +@@ -1969,6 +2009,11 @@ static int irdma_create_cq(struct ib_cq *ibcq, + err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev); + if (err_code) + return err_code; ++ ++ if (udata && (udata->inlen < IRDMA_CREATE_CQ_MIN_REQ_LEN || ++ udata->outlen < IRDMA_CREATE_CQ_MIN_RESP_LEN)) ++ return -EINVAL; ++ + err_code = irdma_alloc_rsrc(rf, rf->allocated_cqs, rf->max_cq, &cq_num, + &rf->next_cq); + if (err_code) +@@ -2738,6 +2783,7 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, + u64 virt, int access, + struct ib_udata *udata) + { ++#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages) + struct irdma_device *iwdev = to_iwdev(pd->device); + struct irdma_ucontext *ucontext; + struct irdma_pble_alloc *palloc; +@@ -2755,6 +2801,9 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, + if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size) + return ERR_PTR(-EINVAL); + ++ if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN) ++ return ERR_PTR(-EINVAL); ++ + region = ib_umem_get(pd->device, start, len, access); + + if (IS_ERR(region)) { +@@ -4290,12 +4339,16 @@ static int irdma_create_user_ah(struct ib_ah *ibah, + struct rdma_ah_init_attr *attr, + struct ib_udata *udata) + { ++#define IRDMA_CREATE_AH_MIN_RESP_LEN offsetofend(struct irdma_create_ah_resp, rsvd) + struct irdma_ah *ah = container_of(ibah, struct irdma_ah, ibah); + struct irdma_device *iwdev = to_iwdev(ibah->pd->device); + struct irdma_create_ah_resp uresp; + struct irdma_ah *parent_ah; + int err; + ++ if (udata && udata->outlen < IRDMA_CREATE_AH_MIN_RESP_LEN) ++ return -EINVAL; ++ + err = irdma_setup_ah(ibah, attr); + if (err) + return err; +-- +2.35.1 + diff --git a/queue-5.19/rdma-mlx5-don-t-compare-mkey-tags-in-devx-indirect-m.patch b/queue-5.19/rdma-mlx5-don-t-compare-mkey-tags-in-devx-indirect-m.patch new file mode 100644 index 00000000000..b93d345c0c4 --- /dev/null +++ b/queue-5.19/rdma-mlx5-don-t-compare-mkey-tags-in-devx-indirect-m.patch @@ -0,0 +1,77 @@ +From d71f618f554614497eb8494f192391039526784f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Jul 2022 11:26:36 +0300 +Subject: RDMA/mlx5: Don't compare mkey tags in DEVX indirect mkey + +From: Aharon Landau + +[ Upstream commit 13ad1125b941a5f257d9d3ae70485773abd34792 ] + +According to the ib spec: +If the CI supports the Base Memory Management Extensions defined in this +specification, the L_Key format must consist of: +24 bit index in the most significant bits of the R_Key, and +8 bit key in the least significant bits of the R_Key +Through a successful Allocate L_Key verb invocation, the CI must let the +consumer own the key portion of the returned R_Key + +Therefore, when creating a mkey using DEVX, the consumer is allowed to +change the key part. The kernel should compare only the index part of a +R_Key to determine equality with another R_Key. + +Adding capability in order not to break backward compatibility. + +Fixes: 534fd7aac56a ("IB/mlx5: Manage indirection mkey upon DEVX flow for ODP") +Link: https://lore.kernel.org/r/3d669aacea85a3a15c3b3b953b3eaba3f80ef9be.1659255945.git.leonro@nvidia.com +Signed-off-by: Aharon Landau +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/mlx5/main.c | 3 +++ + drivers/infiniband/hw/mlx5/odp.c | 3 ++- + include/uapi/rdma/mlx5-abi.h | 1 + + 3 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c +index bb13164124fd..aa4a2a9cb0d5 100644 +--- a/drivers/infiniband/hw/mlx5/main.c ++++ b/drivers/infiniband/hw/mlx5/main.c +@@ -1826,6 +1826,9 @@ static int set_ucontext_resp(struct ib_ucontext *uctx, + if (MLX5_CAP_GEN(dev->mdev, drain_sigerr)) + resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_SQD2RTS; + ++ resp->comp_mask |= ++ MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_MKEY_UPDATE_TAG; ++ + return 0; + } + +diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c +index 84da5674e1ab..9151852f04a1 100644 +--- a/drivers/infiniband/hw/mlx5/odp.c ++++ b/drivers/infiniband/hw/mlx5/odp.c +@@ -795,7 +795,8 @@ static bool mkey_is_eq(struct mlx5_ib_mkey *mmkey, u32 key) + { + if (!mmkey) + return false; +- if (mmkey->type == MLX5_MKEY_MW) ++ if (mmkey->type == MLX5_MKEY_MW || ++ mmkey->type == MLX5_MKEY_INDIRECT_DEVX) + return mlx5_base_mkey(mmkey->key) == mlx5_base_mkey(key); + return mmkey->key == key; + } +diff --git a/include/uapi/rdma/mlx5-abi.h b/include/uapi/rdma/mlx5-abi.h +index 86be4a92b67b..a96b7d2770e1 100644 +--- a/include/uapi/rdma/mlx5-abi.h ++++ b/include/uapi/rdma/mlx5-abi.h +@@ -104,6 +104,7 @@ enum mlx5_ib_alloc_ucontext_resp_mask { + MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE = 1UL << 2, + MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_SQD2RTS = 1UL << 3, + MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_REAL_TIME_TS = 1UL << 4, ++ MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_MKEY_UPDATE_TAG = 1UL << 5, + }; + + enum mlx5_user_cmds_supp_uhw { +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-delete-error-messages-triggered-by-incoming.patch b/queue-5.19/rdma-rxe-delete-error-messages-triggered-by-incoming.patch new file mode 100644 index 00000000000..417a0e4f3fb --- /dev/null +++ b/queue-5.19/rdma-rxe-delete-error-messages-triggered-by-incoming.patch @@ -0,0 +1,54 @@ +From c54cdce52db737317875460d993d098f26a105bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 16:12:18 +0900 +Subject: RDMA/rxe: Delete error messages triggered by incoming Read requests + +From: Daisuke Matsuda + +[ Upstream commit 2c02249fcbfc066bd33e2a7375c7006d4cb367f6 ] + +An incoming Read request causes multiple Read responses. If a user MR to +copy data from is unavailable or responder cannot send a reply, then the +error messages can be printed for each response attempt, resulting in +message overflow. + +Link: https://lore.kernel.org/r/20220829071218.1639065-1-matsuda-daisuke@fujitsu.com +Signed-off-by: Daisuke Matsuda +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_resp.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c +index e38bf958ab48..2ef21a1cba81 100644 +--- a/drivers/infiniband/sw/rxe/rxe_resp.c ++++ b/drivers/infiniband/sw/rxe/rxe_resp.c +@@ -787,10 +787,8 @@ static enum resp_states read_reply(struct rxe_qp *qp, + if (!skb) + return RESPST_ERR_RNR; + +- err = rxe_mr_copy(mr, res->read.va, payload_addr(&ack_pkt), +- payload, RXE_FROM_MR_OBJ); +- if (err) +- pr_err("Failed copying memory\n"); ++ rxe_mr_copy(mr, res->read.va, payload_addr(&ack_pkt), ++ payload, RXE_FROM_MR_OBJ); + if (mr) + rxe_put(mr); + +@@ -801,10 +799,8 @@ static enum resp_states read_reply(struct rxe_qp *qp, + } + + err = rxe_xmit_packet(qp, &ack_pkt, skb); +- if (err) { +- pr_err("Failed sending RDMA reply.\n"); ++ if (err) + return RESPST_ERR_RNR; +- } + + res->read.va += payload; + res->read.resid -= payload; +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-fix-kernel-null-pointer-dereference-error.patch b/queue-5.19/rdma-rxe-fix-kernel-null-pointer-dereference-error.patch new file mode 100644 index 00000000000..2c906770f2a --- /dev/null +++ b/queue-5.19/rdma-rxe-fix-kernel-null-pointer-dereference-error.patch @@ -0,0 +1,48 @@ +From c12eecf889ac809f20594594f526df499e309db3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Aug 2022 21:16:13 -0400 +Subject: RDMA/rxe: Fix "kernel NULL pointer dereference" error + +From: Zhu Yanjun + +[ Upstream commit a625ca30eff806395175ebad3ac1399014bdb280 ] + +When rxe_queue_init in the function rxe_qp_init_req fails, +both qp->req.task.func and qp->req.task.arg are not initialized. + +Because of creation of qp fails, the function rxe_create_qp will +call rxe_qp_do_cleanup to handle allocated resource. + +Before calling __rxe_do_task, both qp->req.task.func and +qp->req.task.arg should be checked. + +Fixes: 8700e3e7c485 ("Soft RoCE driver") +Link: https://lore.kernel.org/r/20220822011615.805603-2-yanjun.zhu@linux.dev +Reported-by: syzbot+ab99dc4c6e961eed8b8e@syzkaller.appspotmail.com +Signed-off-by: Zhu Yanjun +Reviewed-by: Li Zhijian +Reviewed-by: Bob Pearson +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_qp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index fd706dc3009d..173a4253406b 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -794,7 +794,9 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + rxe_cleanup_task(&qp->comp.task); + + /* flush out any receive wr's or pending requests */ +- __rxe_do_task(&qp->req.task); ++ if (qp->req.task.func) ++ __rxe_do_task(&qp->req.task); ++ + if (qp->sq.queue) { + __rxe_do_task(&qp->comp.task); + __rxe_do_task(&qp->req.task); +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-fix-resize_finish-in-rxe_queue.c.patch b/queue-5.19/rdma-rxe-fix-resize_finish-in-rxe_queue.c.patch new file mode 100644 index 00000000000..5838c2b75ea --- /dev/null +++ b/queue-5.19/rdma-rxe-fix-resize_finish-in-rxe_queue.c.patch @@ -0,0 +1,65 @@ +From fbb7c497a6e85f3a4af735c37802cae018348cf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 17:14:47 -0500 +Subject: RDMA/rxe: Fix resize_finish() in rxe_queue.c + +From: Bob Pearson + +[ Upstream commit fda5d0cf8aef12f0a4f714a96a4b2fce039a3e55 ] + +Currently in resize_finish() in rxe_queue.c there is a loop which copies +the entries in the original queue into a newly allocated queue. The +termination logic for this loop is incorrect. The call to +queue_next_index() updates cons but has no effect on whether the queue is +empty. So if the queue starts out empty nothing is copied but if it is not +then the loop will run forever. This patch changes the loop to compare the +value of cons to the original producer index. + +Fixes: ae6e843fe08d0 ("RDMA/rxe: Add memory barriers to kernel queues") +Link: https://lore.kernel.org/r/20220825221446.6512-1-rpearsonhpe@gmail.com +Signed-off-by: Bob Pearson +Reviewed-by: Li Zhijian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_queue.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_queue.c b/drivers/infiniband/sw/rxe/rxe_queue.c +index dbd4971039c0..d6dbf5a0058d 100644 +--- a/drivers/infiniband/sw/rxe/rxe_queue.c ++++ b/drivers/infiniband/sw/rxe/rxe_queue.c +@@ -112,23 +112,25 @@ static int resize_finish(struct rxe_queue *q, struct rxe_queue *new_q, + unsigned int num_elem) + { + enum queue_type type = q->type; ++ u32 new_prod; + u32 prod; + u32 cons; + + if (!queue_empty(q, q->type) && (num_elem < queue_count(q, type))) + return -EINVAL; + +- prod = queue_get_producer(new_q, type); ++ new_prod = queue_get_producer(new_q, type); ++ prod = queue_get_producer(q, type); + cons = queue_get_consumer(q, type); + +- while (!queue_empty(q, type)) { +- memcpy(queue_addr_from_index(new_q, prod), ++ while ((prod - cons) & q->index_mask) { ++ memcpy(queue_addr_from_index(new_q, new_prod), + queue_addr_from_index(q, cons), new_q->elem_size); +- prod = queue_next_index(new_q, prod); ++ new_prod = queue_next_index(new_q, new_prod); + cons = queue_next_index(q, cons); + } + +- new_q->buf->producer_index = prod; ++ new_q->buf->producer_index = new_prod; + q->buf->consumer_index = cons; + + /* update private index copies */ +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-fix-the-error-caused-by-qp-sk.patch b/queue-5.19/rdma-rxe-fix-the-error-caused-by-qp-sk.patch new file mode 100644 index 00000000000..4911e0970b3 --- /dev/null +++ b/queue-5.19/rdma-rxe-fix-the-error-caused-by-qp-sk.patch @@ -0,0 +1,48 @@ +From b55f483ddb9fbae97c4c34928c007ff8c1309504 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Aug 2022 21:16:14 -0400 +Subject: RDMA/rxe: Fix the error caused by qp->sk + +From: Zhu Yanjun + +[ Upstream commit 548ce2e66725dcba4e27d1e8ac468d5dd17fd509 ] + +When sock_create_kern in the function rxe_qp_init_req fails, +qp->sk is set to NULL. + +Then the function rxe_create_qp will call rxe_qp_do_cleanup +to handle allocated resource. + +Before handling qp->sk, this variable should be checked. + +Fixes: 8700e3e7c485 ("Soft RoCE driver") +Link: https://lore.kernel.org/r/20220822011615.805603-3-yanjun.zhu@linux.dev +Signed-off-by: Zhu Yanjun +Reviewed-by: Li Zhijian +Reviewed-by: Bob Pearson +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_qp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c +index 173a4253406b..3df2db893dd3 100644 +--- a/drivers/infiniband/sw/rxe/rxe_qp.c ++++ b/drivers/infiniband/sw/rxe/rxe_qp.c +@@ -832,8 +832,10 @@ static void rxe_qp_do_cleanup(struct work_struct *work) + + free_rd_atomic_resources(qp); + +- kernel_sock_shutdown(qp->sk, SHUT_RDWR); +- sock_release(qp->sk); ++ if (qp->sk) { ++ kernel_sock_shutdown(qp->sk, SHUT_RDWR); ++ sock_release(qp->sk); ++ } + } + + /* called when the last reference to the qp is dropped */ +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-set-pd-early-in-mr-alloc-routines.patch b/queue-5.19/rdma-rxe-set-pd-early-in-mr-alloc-routines.patch new file mode 100644 index 00000000000..dc8ae94fe2d --- /dev/null +++ b/queue-5.19/rdma-rxe-set-pd-early-in-mr-alloc-routines.patch @@ -0,0 +1,157 @@ +From e00889247b3c09ea2aa8010882be1ee5b1fe3de2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Aug 2022 13:31:54 -0500 +Subject: RDMA/rxe: Set pd early in mr alloc routines + +From: Bob Pearson + +[ Upstream commit 58651bbb30f87dab474eff31ab564391aa6ea1f3 ] + +Move setting of pd in mr objects ahead of any possible errors so that it +will always be set in rxe_mr_cleanup() to avoid seg faults when +rxe_put(mr_pd(mr)) is called. + +Fixes: cf40367961d8 ("RDMA/rxe: Move mr cleanup code to rxe_mr_cleanup()") +Link: https://lore.kernel.org/r/20220805183153.32007-2-rpearsonhpe@gmail.com +Signed-off-by: Bob Pearson +Reviewed-by: Li Zhijian +Signed-off-by: Jason Gunthorpe +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_loc.h | 6 +++--- + drivers/infiniband/sw/rxe/rxe_mr.c | 11 ++++------- + drivers/infiniband/sw/rxe/rxe_verbs.c | 12 +++++++----- + 3 files changed, 14 insertions(+), 15 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_loc.h b/drivers/infiniband/sw/rxe/rxe_loc.h +index d86253c6d6b5..301b8fac2343 100644 +--- a/drivers/infiniband/sw/rxe/rxe_loc.h ++++ b/drivers/infiniband/sw/rxe/rxe_loc.h +@@ -64,10 +64,10 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); + + /* rxe_mr.c */ + u8 rxe_get_next_key(u32 last_key); +-void rxe_mr_init_dma(struct rxe_pd *pd, int access, struct rxe_mr *mr); +-int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, ++void rxe_mr_init_dma(int access, struct rxe_mr *mr); ++int rxe_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, u64 iova, + int access, struct rxe_mr *mr); +-int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr); ++int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr); + int rxe_mr_copy(struct rxe_mr *mr, u64 iova, void *addr, int length, + enum rxe_mr_copy_dir dir); + int copy_data(struct rxe_pd *pd, int access, struct rxe_dma_info *dma, +diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c +index 850b80f5ad8b..af34f198e645 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mr.c ++++ b/drivers/infiniband/sw/rxe/rxe_mr.c +@@ -103,17 +103,16 @@ static int rxe_mr_alloc(struct rxe_mr *mr, int num_buf) + return -ENOMEM; + } + +-void rxe_mr_init_dma(struct rxe_pd *pd, int access, struct rxe_mr *mr) ++void rxe_mr_init_dma(int access, struct rxe_mr *mr) + { + rxe_mr_init(access, mr); + +- mr->ibmr.pd = &pd->ibpd; + mr->access = access; + mr->state = RXE_MR_STATE_VALID; + mr->type = IB_MR_TYPE_DMA; + } + +-int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, ++int rxe_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, u64 iova, + int access, struct rxe_mr *mr) + { + struct rxe_map **map; +@@ -125,7 +124,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, + int err; + int i; + +- umem = ib_umem_get(pd->ibpd.device, start, length, access); ++ umem = ib_umem_get(&rxe->ib_dev, start, length, access); + if (IS_ERR(umem)) { + pr_warn("%s: Unable to pin memory region err = %d\n", + __func__, (int)PTR_ERR(umem)); +@@ -175,7 +174,6 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, + } + } + +- mr->ibmr.pd = &pd->ibpd; + mr->umem = umem; + mr->access = access; + mr->length = length; +@@ -197,7 +195,7 @@ int rxe_mr_init_user(struct rxe_pd *pd, u64 start, u64 length, u64 iova, + return err; + } + +-int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr) ++int rxe_mr_init_fast(int max_pages, struct rxe_mr *mr) + { + int err; + +@@ -208,7 +206,6 @@ int rxe_mr_init_fast(struct rxe_pd *pd, int max_pages, struct rxe_mr *mr) + if (err) + goto err1; + +- mr->ibmr.pd = &pd->ibpd; + mr->max_buf = max_pages; + mr->state = RXE_MR_STATE_FREE; + mr->type = IB_MR_TYPE_MEM_REG; +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c +index e264cf69bf55..f54a3eba652f 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.c ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c +@@ -903,7 +903,9 @@ static struct ib_mr *rxe_get_dma_mr(struct ib_pd *ibpd, int access) + return ERR_PTR(-ENOMEM); + + rxe_get(pd); +- rxe_mr_init_dma(pd, access, mr); ++ mr->ibmr.pd = ibpd; ++ ++ rxe_mr_init_dma(access, mr); + rxe_finalize(mr); + + return &mr->ibmr; +@@ -928,8 +930,9 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, + + + rxe_get(pd); ++ mr->ibmr.pd = ibpd; + +- err = rxe_mr_init_user(pd, start, length, iova, access, mr); ++ err = rxe_mr_init_user(rxe, start, length, iova, access, mr); + if (err) + goto err3; + +@@ -938,7 +941,6 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, + return &mr->ibmr; + + err3: +- rxe_put(pd); + rxe_cleanup(mr); + err2: + return ERR_PTR(err); +@@ -962,8 +964,9 @@ static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, + } + + rxe_get(pd); ++ mr->ibmr.pd = ibpd; + +- err = rxe_mr_init_fast(pd, max_num_sg, mr); ++ err = rxe_mr_init_fast(max_num_sg, mr); + if (err) + goto err2; + +@@ -972,7 +975,6 @@ static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, + return &mr->ibmr; + + err2: +- rxe_put(pd); + rxe_cleanup(mr); + err1: + return ERR_PTR(err); +-- +2.35.1 + diff --git a/queue-5.19/rdma-rxe-stop-lookup-of-partially-built-objects.patch b/queue-5.19/rdma-rxe-stop-lookup-of-partially-built-objects.patch new file mode 100644 index 00000000000..2206cf9daba --- /dev/null +++ b/queue-5.19/rdma-rxe-stop-lookup-of-partially-built-objects.patch @@ -0,0 +1,439 @@ +From f776297112ffff04df95795c3ded986b58d886ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jun 2022 17:34:34 -0500 +Subject: RDMA/rxe: Stop lookup of partially built objects + +From: Bob Pearson + +[ Upstream commit 215d0a755e1bcd92cbe6a71a21194ce7c82ec106 ] + +Currently the rdma_rxe driver has a security weakness due to giving +objects which are partially initialized indices allowing external actors +to gain access to them by sending packets which refer to their +index (e.g. qpn, rkey, etc) causing unpredictable results. + +This patch adds a new API rxe_finalize(obj) which enables looking up pool +objects from indices using rxe_pool_get_index() for AH, QP, MR, and +MW. They are added in create verbs only after the objects are fully +initialized. + +It also adds wait for completion to destroy/dealloc verbs to assure that +all references have been dropped before returning to rdma_core by +implementing a new rxe_pool API rxe_cleanup() which drops a reference to +the object and then waits for all other references to be dropped. When +the last reference is dropped the object is completed by kref. After that +it cleans up the object and if locally allocated frees the memory. In the +special case of address handle objects the delay is implemented separately +if the destroy_ah call is not sleepable. + +Combined with deferring cleanup code to type specific cleanup routines +this allows all pending activity referring to objects to complete before +returning to rdma_core. + +Link: https://lore.kernel.org/r/20220612223434.31462-2-rpearsonhpe@gmail.com +Signed-off-by: Bob Pearson +Signed-off-by: Jason Gunthorpe +Stable-dep-of: 58651bbb30f8 ("RDMA/rxe: Set pd early in mr alloc routines") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/rxe/rxe_mr.c | 2 +- + drivers/infiniband/sw/rxe/rxe_mw.c | 4 +- + drivers/infiniband/sw/rxe/rxe_pool.c | 100 ++++++++++++++++++++++++-- + drivers/infiniband/sw/rxe/rxe_pool.h | 18 +++-- + drivers/infiniband/sw/rxe/rxe_verbs.c | 39 ++++++---- + 5 files changed, 136 insertions(+), 27 deletions(-) + +diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c +index c28b18d59a06..850b80f5ad8b 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mr.c ++++ b/drivers/infiniband/sw/rxe/rxe_mr.c +@@ -619,7 +619,7 @@ int rxe_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata) + if (atomic_read(&mr->num_mw) > 0) + return -EINVAL; + +- rxe_put(mr); ++ rxe_cleanup(mr); + + return 0; + } +diff --git a/drivers/infiniband/sw/rxe/rxe_mw.c b/drivers/infiniband/sw/rxe/rxe_mw.c +index 6c24bc4318e8..ad7ea8fccf11 100644 +--- a/drivers/infiniband/sw/rxe/rxe_mw.c ++++ b/drivers/infiniband/sw/rxe/rxe_mw.c +@@ -33,6 +33,8 @@ int rxe_alloc_mw(struct ib_mw *ibmw, struct ib_udata *udata) + RXE_MW_STATE_FREE : RXE_MW_STATE_VALID; + spin_lock_init(&mw->lock); + ++ rxe_finalize(mw); ++ + return 0; + } + +@@ -40,7 +42,7 @@ int rxe_dealloc_mw(struct ib_mw *ibmw) + { + struct rxe_mw *mw = to_rmw(ibmw); + +- rxe_put(mw); ++ rxe_cleanup(mw); + + return 0; + } +diff --git a/drivers/infiniband/sw/rxe/rxe_pool.c b/drivers/infiniband/sw/rxe/rxe_pool.c +index e9f3bbd8d605..74eca7f33f3b 100644 +--- a/drivers/infiniband/sw/rxe/rxe_pool.c ++++ b/drivers/infiniband/sw/rxe/rxe_pool.c +@@ -6,6 +6,7 @@ + + #include "rxe.h" + ++#define RXE_POOL_TIMEOUT (200) + #define RXE_POOL_ALIGN (16) + + static const struct rxe_type_info { +@@ -136,8 +137,12 @@ void *rxe_alloc(struct rxe_pool *pool) + elem->pool = pool; + elem->obj = obj; + kref_init(&elem->ref_cnt); ++ init_completion(&elem->complete); + +- err = xa_alloc_cyclic(&pool->xa, &elem->index, elem, pool->limit, ++ /* allocate index in array but leave pointer as NULL so it ++ * can't be looked up until rxe_finalize() is called ++ */ ++ err = xa_alloc_cyclic(&pool->xa, &elem->index, NULL, pool->limit, + &pool->next, GFP_KERNEL); + if (err < 0) + goto err_free; +@@ -151,9 +156,11 @@ void *rxe_alloc(struct rxe_pool *pool) + return NULL; + } + +-int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_elem *elem) ++int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_elem *elem, ++ bool sleepable) + { + int err; ++ gfp_t gfp_flags; + + if (WARN_ON(pool->type == RXE_TYPE_MR)) + return -EINVAL; +@@ -164,9 +171,18 @@ int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_elem *elem) + elem->pool = pool; + elem->obj = (u8 *)elem - pool->elem_offset; + kref_init(&elem->ref_cnt); +- +- err = xa_alloc_cyclic(&pool->xa, &elem->index, elem, pool->limit, +- &pool->next, GFP_KERNEL); ++ init_completion(&elem->complete); ++ ++ /* AH objects are unique in that the create_ah verb ++ * can be called in atomic context. If the create_ah ++ * call is not sleepable use GFP_ATOMIC. ++ */ ++ gfp_flags = sleepable ? GFP_KERNEL : GFP_ATOMIC; ++ ++ if (sleepable) ++ might_sleep(); ++ err = xa_alloc_cyclic(&pool->xa, &elem->index, NULL, pool->limit, ++ &pool->next, gfp_flags); + if (err < 0) + goto err_cnt; + +@@ -198,9 +214,67 @@ void *rxe_pool_get_index(struct rxe_pool *pool, u32 index) + static void rxe_elem_release(struct kref *kref) + { + struct rxe_pool_elem *elem = container_of(kref, typeof(*elem), ref_cnt); ++ ++ complete(&elem->complete); ++} ++ ++int __rxe_cleanup(struct rxe_pool_elem *elem, bool sleepable) ++{ + struct rxe_pool *pool = elem->pool; ++ struct xarray *xa = &pool->xa; ++ static int timeout = RXE_POOL_TIMEOUT; ++ unsigned long flags; ++ int ret, err = 0; ++ void *xa_ret; + +- xa_erase(&pool->xa, elem->index); ++ if (sleepable) ++ might_sleep(); ++ ++ /* erase xarray entry to prevent looking up ++ * the pool elem from its index ++ */ ++ xa_lock_irqsave(xa, flags); ++ xa_ret = __xa_erase(xa, elem->index); ++ xa_unlock_irqrestore(xa, flags); ++ WARN_ON(xa_err(xa_ret)); ++ ++ /* if this is the last call to rxe_put complete the ++ * object. It is safe to touch obj->elem after this since ++ * it is freed below ++ */ ++ __rxe_put(elem); ++ ++ /* wait until all references to the object have been ++ * dropped before final object specific cleanup and ++ * return to rdma-core ++ */ ++ if (sleepable) { ++ if (!completion_done(&elem->complete) && timeout) { ++ ret = wait_for_completion_timeout(&elem->complete, ++ timeout); ++ ++ /* Shouldn't happen. There are still references to ++ * the object but, rather than deadlock, free the ++ * object or pass back to rdma-core. ++ */ ++ if (WARN_ON(!ret)) ++ err = -EINVAL; ++ } ++ } else { ++ unsigned long until = jiffies + timeout; ++ ++ /* AH objects are unique in that the destroy_ah verb ++ * can be called in atomic context. This delay ++ * replaces the wait_for_completion call above ++ * when the destroy_ah call is not sleepable ++ */ ++ while (!completion_done(&elem->complete) && ++ time_before(jiffies, until)) ++ mdelay(1); ++ ++ if (WARN_ON(!completion_done(&elem->complete))) ++ err = -EINVAL; ++ } + + if (pool->cleanup) + pool->cleanup(elem); +@@ -209,6 +283,8 @@ static void rxe_elem_release(struct kref *kref) + kfree(elem->obj); + + atomic_dec(&pool->num_elem); ++ ++ return err; + } + + int __rxe_get(struct rxe_pool_elem *elem) +@@ -220,3 +296,15 @@ int __rxe_put(struct rxe_pool_elem *elem) + { + return kref_put(&elem->ref_cnt, rxe_elem_release); + } ++ ++void __rxe_finalize(struct rxe_pool_elem *elem) ++{ ++ struct xarray *xa = &elem->pool->xa; ++ unsigned long flags; ++ void *ret; ++ ++ xa_lock_irqsave(xa, flags); ++ ret = __xa_store(&elem->pool->xa, elem->index, elem, GFP_KERNEL); ++ xa_unlock_irqrestore(xa, flags); ++ WARN_ON(xa_err(ret)); ++} +diff --git a/drivers/infiniband/sw/rxe/rxe_pool.h b/drivers/infiniband/sw/rxe/rxe_pool.h +index 0860660d65ec..9d83cb32092f 100644 +--- a/drivers/infiniband/sw/rxe/rxe_pool.h ++++ b/drivers/infiniband/sw/rxe/rxe_pool.h +@@ -24,6 +24,7 @@ struct rxe_pool_elem { + void *obj; + struct kref ref_cnt; + struct list_head list; ++ struct completion complete; + u32 index; + }; + +@@ -57,21 +58,28 @@ void rxe_pool_cleanup(struct rxe_pool *pool); + void *rxe_alloc(struct rxe_pool *pool); + + /* connect already allocated object to pool */ +-int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_elem *elem); +- +-#define rxe_add_to_pool(pool, obj) __rxe_add_to_pool(pool, &(obj)->elem) ++int __rxe_add_to_pool(struct rxe_pool *pool, struct rxe_pool_elem *elem, ++ bool sleepable); ++#define rxe_add_to_pool(pool, obj) __rxe_add_to_pool(pool, &(obj)->elem, true) ++#define rxe_add_to_pool_ah(pool, obj, sleepable) __rxe_add_to_pool(pool, \ ++ &(obj)->elem, sleepable) + + /* lookup an indexed object from index. takes a reference on object */ + void *rxe_pool_get_index(struct rxe_pool *pool, u32 index); + + int __rxe_get(struct rxe_pool_elem *elem); +- + #define rxe_get(obj) __rxe_get(&(obj)->elem) + + int __rxe_put(struct rxe_pool_elem *elem); +- + #define rxe_put(obj) __rxe_put(&(obj)->elem) + ++int __rxe_cleanup(struct rxe_pool_elem *elem, bool sleepable); ++#define rxe_cleanup(obj) __rxe_cleanup(&(obj)->elem, true) ++#define rxe_cleanup_ah(obj, sleepable) __rxe_cleanup(&(obj)->elem, sleepable) ++ + #define rxe_read(obj) kref_read(&(obj)->elem.ref_cnt) + ++void __rxe_finalize(struct rxe_pool_elem *elem); ++#define rxe_finalize(obj) __rxe_finalize(&(obj)->elem) ++ + #endif /* RXE_POOL_H */ +diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c +index d2b4e68402d4..e264cf69bf55 100644 +--- a/drivers/infiniband/sw/rxe/rxe_verbs.c ++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c +@@ -115,7 +115,7 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc) + { + struct rxe_ucontext *uc = to_ruc(ibuc); + +- rxe_put(uc); ++ rxe_cleanup(uc); + } + + static int rxe_port_immutable(struct ib_device *dev, u32 port_num, +@@ -149,7 +149,7 @@ static int rxe_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata) + { + struct rxe_pd *pd = to_rpd(ibpd); + +- rxe_put(pd); ++ rxe_cleanup(pd); + return 0; + } + +@@ -176,7 +176,8 @@ static int rxe_create_ah(struct ib_ah *ibah, + if (err) + return err; + +- err = rxe_add_to_pool(&rxe->ah_pool, ah); ++ err = rxe_add_to_pool_ah(&rxe->ah_pool, ah, ++ init_attr->flags & RDMA_CREATE_AH_SLEEPABLE); + if (err) + return err; + +@@ -188,7 +189,7 @@ static int rxe_create_ah(struct ib_ah *ibah, + err = copy_to_user(&uresp->ah_num, &ah->ah_num, + sizeof(uresp->ah_num)); + if (err) { +- rxe_put(ah); ++ rxe_cleanup(ah); + return -EFAULT; + } + } else if (ah->is_user) { +@@ -197,6 +198,8 @@ static int rxe_create_ah(struct ib_ah *ibah, + } + + rxe_init_av(init_attr->ah_attr, &ah->av); ++ rxe_finalize(ah); ++ + return 0; + } + +@@ -228,7 +231,8 @@ static int rxe_destroy_ah(struct ib_ah *ibah, u32 flags) + { + struct rxe_ah *ah = to_rah(ibah); + +- rxe_put(ah); ++ rxe_cleanup_ah(ah, flags & RDMA_DESTROY_AH_SLEEPABLE); ++ + return 0; + } + +@@ -308,12 +312,13 @@ static int rxe_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *init, + + err = rxe_srq_from_init(rxe, srq, init, udata, uresp); + if (err) +- goto err_put; ++ goto err_cleanup; + + return 0; + +-err_put: +- rxe_put(srq); ++err_cleanup: ++ rxe_cleanup(srq); ++ + return err; + } + +@@ -362,7 +367,7 @@ static int rxe_destroy_srq(struct ib_srq *ibsrq, struct ib_udata *udata) + { + struct rxe_srq *srq = to_rsrq(ibsrq); + +- rxe_put(srq); ++ rxe_cleanup(srq); + return 0; + } + +@@ -429,10 +434,11 @@ static int rxe_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *init, + if (err) + goto qp_init; + ++ rxe_finalize(qp); + return 0; + + qp_init: +- rxe_put(qp); ++ rxe_cleanup(qp); + return err; + } + +@@ -485,7 +491,7 @@ static int rxe_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) + if (ret) + return ret; + +- rxe_put(qp); ++ rxe_cleanup(qp); + return 0; + } + +@@ -803,7 +809,7 @@ static int rxe_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata) + + rxe_cq_disable(cq); + +- rxe_put(cq); ++ rxe_cleanup(cq); + return 0; + } + +@@ -898,6 +904,7 @@ static struct ib_mr *rxe_get_dma_mr(struct ib_pd *ibpd, int access) + + rxe_get(pd); + rxe_mr_init_dma(pd, access, mr); ++ rxe_finalize(mr); + + return &mr->ibmr; + } +@@ -926,11 +933,13 @@ static struct ib_mr *rxe_reg_user_mr(struct ib_pd *ibpd, + if (err) + goto err3; + ++ rxe_finalize(mr); ++ + return &mr->ibmr; + + err3: + rxe_put(pd); +- rxe_put(mr); ++ rxe_cleanup(mr); + err2: + return ERR_PTR(err); + } +@@ -958,11 +967,13 @@ static struct ib_mr *rxe_alloc_mr(struct ib_pd *ibpd, enum ib_mr_type mr_type, + if (err) + goto err2; + ++ rxe_finalize(mr); ++ + return &mr->ibmr; + + err2: + rxe_put(pd); +- rxe_put(mr); ++ rxe_cleanup(mr); + err1: + return ERR_PTR(err); + } +-- +2.35.1 + diff --git a/queue-5.19/rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch b/queue-5.19/rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch new file mode 100644 index 00000000000..016f13a19b3 --- /dev/null +++ b/queue-5.19/rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch @@ -0,0 +1,99 @@ +From 1bd6df571e64b0847ec805f59a66e8638f1eba64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 10:12:02 +0200 +Subject: RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall. + +From: Bernard Metzler + +[ Upstream commit 754209850df8367c954ac1de7671c7430b1f342c ] + +For header and trailer/padding processing, siw did not consume new +skb data until minimum amount present to fill current header or trailer +structure, including potential payload padding. Not consuming any +data during upcall may cause a receive stall, since tcp_read_sock() +is not upcalling again if no new data arrive. +A NFSoRDMA client got stuck at RDMA Write reception of unaligned +payload, if the current skb did contain only the expected 3 padding +bytes, but not the 4 bytes CRC trailer. Expecting 4 more bytes already +arrived in another skb, and not consuming those 3 bytes in the current +upcall left the Write incomplete, waiting for the CRC forever. + +Fixes: 8b6a361b8c48 ("rdma/siw: receive path") +Reported-by: Olga Kornievskaia +Tested-by: Olga Kornievskaia +Signed-off-by: Bernard Metzler +Link: https://lore.kernel.org/r/20220920081202.223629-1-bmt@zurich.ibm.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw_qp_rx.c | 27 +++++++++++++++------------ + 1 file changed, 15 insertions(+), 12 deletions(-) + +diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c +index 875ea6f1b04a..fd721cc19682 100644 +--- a/drivers/infiniband/sw/siw/siw_qp_rx.c ++++ b/drivers/infiniband/sw/siw/siw_qp_rx.c +@@ -961,27 +961,28 @@ int siw_proc_terminate(struct siw_qp *qp) + static int siw_get_trailer(struct siw_qp *qp, struct siw_rx_stream *srx) + { + struct sk_buff *skb = srx->skb; ++ int avail = min(srx->skb_new, srx->fpdu_part_rem); + u8 *tbuf = (u8 *)&srx->trailer.crc - srx->pad; + __wsum crc_in, crc_own = 0; + + siw_dbg_qp(qp, "expected %d, available %d, pad %u\n", + srx->fpdu_part_rem, srx->skb_new, srx->pad); + +- if (srx->skb_new < srx->fpdu_part_rem) +- return -EAGAIN; +- +- skb_copy_bits(skb, srx->skb_offset, tbuf, srx->fpdu_part_rem); ++ skb_copy_bits(skb, srx->skb_offset, tbuf, avail); + +- if (srx->mpa_crc_hd && srx->pad) +- crypto_shash_update(srx->mpa_crc_hd, tbuf, srx->pad); ++ srx->skb_new -= avail; ++ srx->skb_offset += avail; ++ srx->skb_copied += avail; ++ srx->fpdu_part_rem -= avail; + +- srx->skb_new -= srx->fpdu_part_rem; +- srx->skb_offset += srx->fpdu_part_rem; +- srx->skb_copied += srx->fpdu_part_rem; ++ if (srx->fpdu_part_rem) ++ return -EAGAIN; + + if (!srx->mpa_crc_hd) + return 0; + ++ if (srx->pad) ++ crypto_shash_update(srx->mpa_crc_hd, tbuf, srx->pad); + /* + * CRC32 is computed, transmitted and received directly in NBO, + * so there's never a reason to convert byte order. +@@ -1083,10 +1084,9 @@ static int siw_get_hdr(struct siw_rx_stream *srx) + * completely received. + */ + if (iwarp_pktinfo[opcode].hdr_len > sizeof(struct iwarp_ctrl_tagged)) { +- bytes = iwarp_pktinfo[opcode].hdr_len - MIN_DDP_HDR; ++ int hdrlen = iwarp_pktinfo[opcode].hdr_len; + +- if (srx->skb_new < bytes) +- return -EAGAIN; ++ bytes = min_t(int, hdrlen - MIN_DDP_HDR, srx->skb_new); + + skb_copy_bits(skb, srx->skb_offset, + (char *)c_hdr + srx->fpdu_part_rcvd, bytes); +@@ -1096,6 +1096,9 @@ static int siw_get_hdr(struct siw_rx_stream *srx) + srx->skb_new -= bytes; + srx->skb_offset += bytes; + srx->skb_copied += bytes; ++ ++ if (srx->fpdu_part_rcvd < hdrlen) ++ return -EAGAIN; + } + + /* +-- +2.35.1 + diff --git a/queue-5.19/rdma-siw-fix-qp-destroy-to-wait-for-all-references-d.patch b/queue-5.19/rdma-siw-fix-qp-destroy-to-wait-for-all-references-d.patch new file mode 100644 index 00000000000..1d831c0e38a --- /dev/null +++ b/queue-5.19/rdma-siw-fix-qp-destroy-to-wait-for-all-references-d.patch @@ -0,0 +1,78 @@ +From 4597593a6104f191fb8674adc9613d4387aee0e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 10:25:03 +0200 +Subject: RDMA/siw: Fix QP destroy to wait for all references dropped. + +From: Bernard Metzler + +[ Upstream commit a3c278807a459e6f50afee6971cabe74cccfb490 ] + +Delay QP destroy completion until all siw references to QP are +dropped. The calling RDMA core will free QP structure after +successful return from siw_qp_destroy() call, so siw must not +hold any remaining reference to the QP upon return. +A use-after-free was encountered in xfstest generic/460, while +testing NFSoRDMA. Here, after a TCP connection drop by peer, +the triggered siw_cm_work_handler got delayed until after +QP destroy call, referencing a QP which has already freed. + +Fixes: 303ae1cdfdf7 ("rdma/siw: application interface") +Reported-by: Olga Kornievskaia +Signed-off-by: Bernard Metzler +Link: https://lore.kernel.org/r/20220920082503.224189-1-bmt@zurich.ibm.com +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/sw/siw/siw.h | 1 + + drivers/infiniband/sw/siw/siw_qp.c | 2 +- + drivers/infiniband/sw/siw/siw_verbs.c | 3 +++ + 3 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h +index df03d84c6868..2f3a9cda3850 100644 +--- a/drivers/infiniband/sw/siw/siw.h ++++ b/drivers/infiniband/sw/siw/siw.h +@@ -418,6 +418,7 @@ struct siw_qp { + struct ib_qp base_qp; + struct siw_device *sdev; + struct kref ref; ++ struct completion qp_free; + struct list_head devq; + int tx_cpu; + struct siw_qp_attrs attrs; +diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c +index 7e01f2438afc..e6f634971228 100644 +--- a/drivers/infiniband/sw/siw/siw_qp.c ++++ b/drivers/infiniband/sw/siw/siw_qp.c +@@ -1342,6 +1342,6 @@ void siw_free_qp(struct kref *ref) + vfree(qp->orq); + + siw_put_tx_cpu(qp->tx_cpu); +- ++ complete(&qp->qp_free); + atomic_dec(&sdev->num_qp); + } +diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c +index 09316072b789..598dab44536b 100644 +--- a/drivers/infiniband/sw/siw/siw_verbs.c ++++ b/drivers/infiniband/sw/siw/siw_verbs.c +@@ -480,6 +480,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + list_add_tail(&qp->devq, &sdev->qp_list); + spin_unlock_irqrestore(&sdev->lock, flags); + ++ init_completion(&qp->qp_free); ++ + return 0; + + err_out_xa: +@@ -624,6 +626,7 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata) + qp->scq = qp->rcq = NULL; + + siw_qp_put(qp); ++ wait_for_completion(&qp->qp_free); + + return 0; + } +-- +2.35.1 + diff --git a/queue-5.19/rdma-srp-fix-srp_abort.patch b/queue-5.19/rdma-srp-fix-srp_abort.patch new file mode 100644 index 00000000000..9e0440d8e58 --- /dev/null +++ b/queue-5.19/rdma-srp-fix-srp_abort.patch @@ -0,0 +1,47 @@ +From 714e0cd47694dbb74dcc831fb985e53b90849a2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 16:31:39 -0700 +Subject: RDMA/srp: Fix srp_abort() + +From: Bart Van Assche + +[ Upstream commit 6dbe4a8dead84de474483910b02ec9e6a10fc1a9 ] + +Fix the code for converting a SCSI command pointer into an SRP request +pointer. + +Cc: Xiao Yang +Fixes: ad215aaea4f9 ("RDMA/srp: Make struct scsi_cmnd and struct srp_request adjacent") +Signed-off-by: Bart Van Assche +Link: https://lore.kernel.org/r/20220908233139.3042628-1-bvanassche@acm.org +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index 3d9c108d73ad..c3fa65977b3e 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -2790,7 +2790,7 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, + static int srp_abort(struct scsi_cmnd *scmnd) + { + struct srp_target_port *target = host_to_target(scmnd->device->host); +- struct srp_request *req = (struct srp_request *) scmnd->host_scribble; ++ struct srp_request *req = scsi_cmd_priv(scmnd); + u32 tag; + u16 ch_idx; + struct srp_rdma_ch *ch; +@@ -2798,8 +2798,6 @@ static int srp_abort(struct scsi_cmnd *scmnd) + + shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); + +- if (!req) +- return SUCCESS; + tag = blk_mq_unique_tag(scsi_cmd_to_rq(scmnd)); + ch_idx = blk_mq_unique_tag_to_hwq(tag); + if (WARN_ON_ONCE(ch_idx >= target->ch_count)) +-- +2.35.1 + diff --git a/queue-5.19/rdma-srp-handle-dev_set_name-failure.patch b/queue-5.19/rdma-srp-handle-dev_set_name-failure.patch new file mode 100644 index 00000000000..c6e16dd1893 --- /dev/null +++ b/queue-5.19/rdma-srp-handle-dev_set_name-failure.patch @@ -0,0 +1,48 @@ +From 6c09fe49dca1198d7cb275d3819ba70a0e93761b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 14:38:59 -0700 +Subject: RDMA/srp: Handle dev_set_name() failure + +From: Bart Van Assche + +[ Upstream commit 351e458f725da8106eba920f3cdecf39a0e31136 ] + +Instead of ignoring dev_set_name() failure, handle dev_set_name() +failure. Convert a device_register() call into device_initialize() and +device_add() calls. + +Link: https://lore.kernel.org/r/20220825213900.864587-4-bvanassche@acm.org +Reported-by: Bo Liu +Signed-off-by: Bart Van Assche +Signed-off-by: Leon Romanovsky +Stable-dep-of: b05398aff9ad ("RDMA/srp: Support more than 255 rdma ports") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index 17fa38889ada..a37fbd87d6fd 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -3903,12 +3903,13 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) + host->srp_dev = device; + host->port = port; + ++ device_initialize(&host->dev); + host->dev.class = &srp_class; + host->dev.parent = device->dev->dev.parent; +- dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev), +- port); +- +- if (device_register(&host->dev)) ++ if (dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev), ++ port)) ++ goto put_host; ++ if (device_add(&host->dev)) + goto put_host; + if (device_create_file(&host->dev, &dev_attr_add_target)) + goto put_host; +-- +2.35.1 + diff --git a/queue-5.19/rdma-srp-rework-the-srp_add_port-error-path.patch b/queue-5.19/rdma-srp-rework-the-srp_add_port-error-path.patch new file mode 100644 index 00000000000..c93c5ad953c --- /dev/null +++ b/queue-5.19/rdma-srp-rework-the-srp_add_port-error-path.patch @@ -0,0 +1,61 @@ +From 2c33d7a1123c93a2ce85eb868f592cfcbf89e89d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 14:38:57 -0700 +Subject: RDMA/srp: Rework the srp_add_port() error path + +From: Bart Van Assche + +[ Upstream commit c8e4c23976554fb9dda1658bd1a3914b202815cd ] + +device_register() always calls device_initialize() so calling device_del() +is safe even if device_register() fails. Implement the following advice +from the comment block above device_register(): "NOTE: _Never_ directly free +@dev after calling this function, even if it returned an error! Always use +put_device() to give up the reference initialized in this function instead." +Keep the kfree() call in the error path since srp_release_dev() does not +free the host. + +Link: https://lore.kernel.org/r/20220825213900.864587-2-bvanassche@acm.org +Signed-off-by: Bart Van Assche +Signed-off-by: Leon Romanovsky +Stable-dep-of: b05398aff9ad ("RDMA/srp: Support more than 255 rdma ports") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index c3fa65977b3e..17fa38889ada 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -3909,20 +3909,19 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) + port); + + if (device_register(&host->dev)) +- goto free_host; ++ goto put_host; + if (device_create_file(&host->dev, &dev_attr_add_target)) +- goto err_class; ++ goto put_host; + if (device_create_file(&host->dev, &dev_attr_ibdev)) +- goto err_class; ++ goto put_host; + if (device_create_file(&host->dev, &dev_attr_port)) +- goto err_class; ++ goto put_host; + + return host; + +-err_class: +- device_unregister(&host->dev); +- +-free_host: ++put_host: ++ device_del(&host->dev); ++ put_device(&host->dev); + kfree(host); + + return NULL; +-- +2.35.1 + diff --git a/queue-5.19/rdma-srp-support-more-than-255-rdma-ports.patch b/queue-5.19/rdma-srp-support-more-than-255-rdma-ports.patch new file mode 100644 index 00000000000..e582c702dce --- /dev/null +++ b/queue-5.19/rdma-srp-support-more-than-255-rdma-ports.patch @@ -0,0 +1,98 @@ +From 673ecf37aa932e28425d9ed53c8ff897f4ba2b73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 11:03:07 +0300 +Subject: RDMA/srp: Support more than 255 rdma ports + +From: Mikhael Goikhman + +[ Upstream commit b05398aff9ad9dc701b261183a5d756165d28b51 ] + +Currently ib_srp module does not support devices with more than 256 +ports. Switch from u8 to u32 to fix the problem. + +Fixes: 1fb7f8973f51 ("RDMA: Support more than 255 rdma ports") +Reviewed-by: Shay Drory +Signed-off-by: Mikhael Goikhman +Link: https://lore.kernel.org/r/7d80d8844f1abb3a54170b7259f0a02be38080a6.1663747327.git.leonro@nvidia.com +Reviewed-by: Bart Van Assche +Signed-off-by: Leon Romanovsky +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 12 ++++++------ + drivers/infiniband/ulp/srp/ib_srp.h | 2 +- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index b6463630c7d8..cc9d7fbfe014 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -2990,7 +2990,7 @@ static ssize_t local_ib_port_show(struct device *dev, + { + struct srp_target_port *target = host_to_target(class_to_shost(dev)); + +- return sysfs_emit(buf, "%d\n", target->srp_host->port); ++ return sysfs_emit(buf, "%u\n", target->srp_host->port); + } + + static DEVICE_ATTR_RO(local_ib_port); +@@ -3888,7 +3888,7 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr, + { + struct srp_host *host = container_of(dev, struct srp_host, dev); + +- return sysfs_emit(buf, "%d\n", host->port); ++ return sysfs_emit(buf, "%u\n", host->port); + } + + static DEVICE_ATTR_RO(port); +@@ -3900,7 +3900,7 @@ static struct attribute *srp_class_attrs[] = { + NULL + }; + +-static struct srp_host *srp_add_port(struct srp_device *device, u8 port) ++static struct srp_host *srp_add_port(struct srp_device *device, u32 port) + { + struct srp_host *host; + +@@ -3918,7 +3918,7 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) + device_initialize(&host->dev); + host->dev.class = &srp_class; + host->dev.parent = device->dev->dev.parent; +- if (dev_set_name(&host->dev, "srp-%s-%d", dev_name(&device->dev->dev), ++ if (dev_set_name(&host->dev, "srp-%s-%u", dev_name(&device->dev->dev), + port)) + goto put_host; + if (device_add(&host->dev)) +@@ -3942,7 +3942,7 @@ static void srp_rename_dev(struct ib_device *device, void *client_data) + list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) { + char name[IB_DEVICE_NAME_MAX + 8]; + +- snprintf(name, sizeof(name), "srp-%s-%d", ++ snprintf(name, sizeof(name), "srp-%s-%u", + dev_name(&device->dev), host->port); + device_rename(&host->dev, name); + } +@@ -3954,7 +3954,7 @@ static int srp_add_one(struct ib_device *device) + struct ib_device_attr *attr = &device->attrs; + struct srp_host *host; + int mr_page_shift; +- unsigned int p; ++ u32 p; + u64 max_pages_per_mr; + unsigned int flags = 0; + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h +index 55a575e2cace..c80709dfbe77 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.h ++++ b/drivers/infiniband/ulp/srp/ib_srp.h +@@ -120,7 +120,7 @@ struct srp_device { + */ + struct srp_host { + struct srp_device *srp_dev; +- u8 port; ++ u32 port; + struct device dev; + struct list_head target_list; + spinlock_t target_lock; +-- +2.35.1 + diff --git a/queue-5.19/rdma-srp-use-the-attribute-group-mechanism-for-sysfs.patch b/queue-5.19/rdma-srp-use-the-attribute-group-mechanism-for-sysfs.patch new file mode 100644 index 00000000000..18c3e2676a4 --- /dev/null +++ b/queue-5.19/rdma-srp-use-the-attribute-group-mechanism-for-sysfs.patch @@ -0,0 +1,69 @@ +From 63e4e45263d12d20fd86e3bf4f752e0bf251cca0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 14:39:00 -0700 +Subject: RDMA/srp: Use the attribute group mechanism for sysfs attributes + +From: Bart Van Assche + +[ Upstream commit b8a9c18c2f39bd84b8240b744b666114f7d62054 ] + +Simplify the SRP driver by using the attribute group mechanism instead +of calling device_create_file() explicitly. + +Link: https://lore.kernel.org/r/20220825213900.864587-5-bvanassche@acm.org +Signed-off-by: Bart Van Assche +Signed-off-by: Leon Romanovsky +Stable-dep-of: b05398aff9ad ("RDMA/srp: Support more than 255 rdma ports") +Signed-off-by: Sasha Levin +--- + drivers/infiniband/ulp/srp/ib_srp.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c +index a37fbd87d6fd..b6463630c7d8 100644 +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -3181,8 +3181,13 @@ static void srp_release_dev(struct device *dev) + complete(&host->released); + } + ++static struct attribute *srp_class_attrs[]; ++ ++ATTRIBUTE_GROUPS(srp_class); ++ + static struct class srp_class = { + .name = "infiniband_srp", ++ .dev_groups = srp_class_groups, + .dev_release = srp_release_dev + }; + +@@ -3888,6 +3893,13 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr, + + static DEVICE_ATTR_RO(port); + ++static struct attribute *srp_class_attrs[] = { ++ &dev_attr_add_target.attr, ++ &dev_attr_ibdev.attr, ++ &dev_attr_port.attr, ++ NULL ++}; ++ + static struct srp_host *srp_add_port(struct srp_device *device, u8 port) + { + struct srp_host *host; +@@ -3911,12 +3923,6 @@ static struct srp_host *srp_add_port(struct srp_device *device, u8 port) + goto put_host; + if (device_add(&host->dev)) + goto put_host; +- if (device_create_file(&host->dev, &dev_attr_add_target)) +- goto put_host; +- if (device_create_file(&host->dev, &dev_attr_ibdev)) +- goto put_host; +- if (device_create_file(&host->dev, &dev_attr_port)) +- goto put_host; + + return host; + +-- +2.35.1 + diff --git a/queue-5.19/regulator-core-prevent-integer-underflow.patch b/queue-5.19/regulator-core-prevent-integer-underflow.patch new file mode 100644 index 00000000000..fdd9a9e8f67 --- /dev/null +++ b/queue-5.19/regulator-core-prevent-integer-underflow.patch @@ -0,0 +1,41 @@ +From af21109628ba9f997fd4f0c08efc658e0d61e321 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 14:59:53 +0200 +Subject: regulator: core: Prevent integer underflow + +From: Patrick Rudolph + +[ Upstream commit 8d8e16592022c9650df8aedfe6552ed478d7135b ] + +By using a ratio of delay to poll_enabled_time that is not integer +time_remaining underflows and does not exit the loop as expected. +As delay could be derived from DT and poll_enabled_time is defined +in the driver this can easily happen. + +Use a signed iterator to make sure that the loop exits once +the remaining time is negative. + +Signed-off-by: Patrick Rudolph +Link: https://lore.kernel.org/r/20220909125954.577669-1-patrick.rudolph@9elements.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 a9daaf4d5aaa..9567d2fc3f00 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -2680,7 +2680,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) + * return -ETIMEDOUT. + */ + if (rdev->desc->poll_enabled_time) { +- unsigned int time_remaining = delay; ++ int time_remaining = delay; + + while (time_remaining > 0) { + _regulator_delay_helper(rdev->desc->poll_enabled_time); +-- +2.35.1 + diff --git a/queue-5.19/remoteproc-harden-rproc_handle_vdev-against-integer-.patch b/queue-5.19/remoteproc-harden-rproc_handle_vdev-against-integer-.patch new file mode 100644 index 00000000000..b7c804fcb5e --- /dev/null +++ b/queue-5.19/remoteproc-harden-rproc_handle_vdev-against-integer-.patch @@ -0,0 +1,47 @@ +From cae2f9b262de69e924ec4e052089f427018fb3a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 17:11:44 +0300 +Subject: remoteproc: Harden rproc_handle_vdev() against integer overflow + +From: Dan Carpenter + +[ Upstream commit 7d7f8fe4e399519cc9ac68a475fec6d3a996341b ] + +The struct_size() macro protects against integer overflows but adding +"+ rsc->config_len" introduces the risk of integer overflows again. +Use size_add() to be safe. + +Fixes: c87846571587 ("remoteproc: use struct_size() helper") +Signed-off-by: Dan Carpenter +Reviewed-by: Gustavo A. R. Silva +Reviewed-by: Mukesh Ojha +Link: https://lore.kernel.org/r/YyMyoPoGOJUcEpZT@kili +Signed-off-by: Mathieu Poirier +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/remoteproc_core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c +index 02a04ab34a23..9d86470df79b 100644 +--- a/drivers/remoteproc/remoteproc_core.c ++++ b/drivers/remoteproc/remoteproc_core.c +@@ -518,12 +518,13 @@ static int rproc_handle_vdev(struct rproc *rproc, void *ptr, + struct fw_rsc_vdev *rsc = ptr; + struct device *dev = &rproc->dev; + struct rproc_vdev *rvdev; ++ size_t rsc_size; + int i, ret; + char name[16]; + + /* make sure resource isn't truncated */ +- if (struct_size(rsc, vring, rsc->num_of_vrings) + rsc->config_len > +- avail) { ++ rsc_size = struct_size(rsc, vring, rsc->num_of_vrings); ++ if (size_add(rsc_size, rsc->config_len) > avail) { + dev_err(dev, "vdev rsc is truncated\n"); + return -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.19/remoteproc-imx_dsp_rproc-fix-argument-2-of-rproc_mem.patch b/queue-5.19/remoteproc-imx_dsp_rproc-fix-argument-2-of-rproc_mem.patch new file mode 100644 index 00000000000..4443bcd6470 --- /dev/null +++ b/queue-5.19/remoteproc-imx_dsp_rproc-fix-argument-2-of-rproc_mem.patch @@ -0,0 +1,53 @@ +From dd6593236cdda4914553636ebe5a0489c29d1f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 20:43:18 +0800 +Subject: remoteproc: imx_dsp_rproc: fix argument 2 of rproc_mem_entry_init + +From: Shengjiu Wang + +[ Upstream commit 729c16326b7f3f4e83e4195f620a6ca0b7dfa25a ] + +There are sparse warning: +drivers/remoteproc/imx_dsp_rproc.c:602:49: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void *va @@ got void [noderef] __iomem *[assigned] cpu_addr @@ +drivers/remoteproc/imx_dsp_rproc.c:602:49: sparse: expected void *va +drivers/remoteproc/imx_dsp_rproc.c:602:49: sparse: got void [noderef] __iomem *[assigned] cpu_addr +drivers/remoteproc/imx_dsp_rproc.c:638:49: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void *va @@ got void [noderef] __iomem *[assigned] cpu_addr @@ +drivers/remoteproc/imx_dsp_rproc.c:638:49: sparse: expected void *va +drivers/remoteproc/imx_dsp_rproc.c:638:49: sparse: got void [noderef] __iomem *[assigned] cpu_addr + +Fixes: ec0e5549f358 ("remoteproc: imx_dsp_rproc: Add remoteproc driver for DSP on i.MX") +Reported-by: kernel test robot +Signed-off-by: Shengjiu Wang +Link: https://lore.kernel.org/r/1660567398-24495-1-git-send-email-shengjiu.wang@nxp.com +Acked-by: Mukesh Ojha +Signed-off-by: Mathieu Poirier +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/imx_dsp_rproc.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c +index ca0817f8e41e..899aa8dd12f0 100644 +--- a/drivers/remoteproc/imx_dsp_rproc.c ++++ b/drivers/remoteproc/imx_dsp_rproc.c +@@ -599,7 +599,7 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) + } + + /* Register memory region */ +- mem = rproc_mem_entry_init(dev, cpu_addr, (dma_addr_t)att->sa, ++ mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa, + att->size, da, NULL, NULL, "dsp_mem"); + + if (mem) +@@ -635,7 +635,7 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv) + } + + /* Register memory region */ +- mem = rproc_mem_entry_init(dev, cpu_addr, (dma_addr_t)rmem->base, ++ mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)rmem->base, + rmem->size, da, NULL, NULL, it.node->name); + + if (mem) +-- +2.35.1 + diff --git a/queue-5.19/remoteproc-imx_rproc-simplify-some-error-message.patch b/queue-5.19/remoteproc-imx_rproc-simplify-some-error-message.patch new file mode 100644 index 00000000000..1eb84f88038 --- /dev/null +++ b/queue-5.19/remoteproc-imx_rproc-simplify-some-error-message.patch @@ -0,0 +1,63 @@ +From d6f39ccb0d7717063748eadb29eadce7e227dfb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Aug 2022 00:02:32 +0200 +Subject: remoteproc: imx_rproc: Simplify some error message + +From: Christophe JAILLET + +[ Upstream commit a1c3611dcfb08e62e165ab5c00122dd13f210166 ] + +dev_err_probe() already prints the error code in a human readable way, so +there is no need to duplicate it as a numerical value at the end of the +message. + +While at it, remove 'ret' that is mostly useless. + +Fixes: 2df7062002d0 ("remoteproc: imx_proc: enable virtio/mailbox") +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/6b9343c2688117a340661d8ee491c2962c54a09a.1659736936.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mathieu Poirier +Signed-off-by: Sasha Levin +--- + drivers/remoteproc/imx_rproc.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c +index 38383e7de3c1..7cc4fd207e2d 100644 +--- a/drivers/remoteproc/imx_rproc.c ++++ b/drivers/remoteproc/imx_rproc.c +@@ -646,7 +646,6 @@ static int imx_rproc_xtr_mbox_init(struct rproc *rproc) + struct imx_rproc *priv = rproc->priv; + struct device *dev = priv->dev; + struct mbox_client *cl; +- int ret; + + if (!of_get_property(dev->of_node, "mbox-names", NULL)) + return 0; +@@ -659,18 +658,15 @@ static int imx_rproc_xtr_mbox_init(struct rproc *rproc) + cl->rx_callback = imx_rproc_rx_callback; + + priv->tx_ch = mbox_request_channel_byname(cl, "tx"); +- if (IS_ERR(priv->tx_ch)) { +- ret = PTR_ERR(priv->tx_ch); +- return dev_err_probe(cl->dev, ret, +- "failed to request tx mailbox channel: %d\n", ret); +- } ++ if (IS_ERR(priv->tx_ch)) ++ return dev_err_probe(cl->dev, PTR_ERR(priv->tx_ch), ++ "failed to request tx mailbox channel\n"); + + priv->rx_ch = mbox_request_channel_byname(cl, "rx"); + if (IS_ERR(priv->rx_ch)) { + mbox_free_channel(priv->tx_ch); +- ret = PTR_ERR(priv->rx_ch); +- return dev_err_probe(cl->dev, ret, +- "failed to request rx mailbox channel: %d\n", ret); ++ return dev_err_probe(cl->dev, PTR_ERR(priv->rx_ch), ++ "failed to request rx mailbox channel\n"); + } + + return 0; +-- +2.35.1 + diff --git a/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch b/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch new file mode 100644 index 00000000000..b09177087a0 --- /dev/null +++ b/queue-5.19/revert-sbitmap-fix-batched-wait_cnt-accounting.patch @@ -0,0 +1,142 @@ +From 0457860446369e63cb410d6590d32f1a99647e6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 4 Sep 2022 06:39:25 -0600 +Subject: Revert "sbitmap: fix batched wait_cnt accounting" + +From: Jens Axboe + +[ Upstream commit bce1b56c73826fec8caf6187f0c922ede397a5a8 ] + +This reverts commit 16ede66973c84f890c03584f79158dd5b2d725f5. + +This is causing issues with CPU stalls on my test box, revert it for +now until we understand what is going on. It looks like infinite +looping off sbitmap_queue_wake_up(), but hard to tell with a lot of +CPUs hitting this issue and the console scrolling infinitely. + +Link: https://lore.kernel.org/linux-block/e742813b-ce5c-0d58-205b-1626f639b1bd@kernel.dk/ +Signed-off-by: Jens Axboe +Stable-dep-of: 48c033314f37 ("sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up()") +Signed-off-by: Sasha Levin +--- + block/blk-mq-tag.c | 2 +- + include/linux/sbitmap.h | 3 +-- + lib/sbitmap.c | 31 ++++++++++++++----------------- + 3 files changed, 16 insertions(+), 20 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 7aea93047caf..2dcd738c6952 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -200,7 +200,7 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) + * other allocations on previous queue won't be starved. + */ + if (bt != bt_prev) +- sbitmap_queue_wake_up(bt_prev, 1); ++ sbitmap_queue_wake_up(bt_prev); + + ws = bt_wait_ptr(bt, data->hctx); + } while (1); +diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h +index 4d2d5205ab58..8f5a86e210b9 100644 +--- a/include/linux/sbitmap.h ++++ b/include/linux/sbitmap.h +@@ -575,9 +575,8 @@ void sbitmap_queue_wake_all(struct sbitmap_queue *sbq); + * sbitmap_queue_wake_up() - Wake up some of waiters in one waitqueue + * on a &struct sbitmap_queue. + * @sbq: Bitmap queue to wake up. +- * @nr: Number of bits cleared. + */ +-void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr); ++void sbitmap_queue_wake_up(struct sbitmap_queue *sbq); + + /** + * sbitmap_queue_show() - Dump &struct sbitmap_queue information to a &struct +diff --git a/lib/sbitmap.c b/lib/sbitmap.c +index a8aae1fc5206..1f31147872e6 100644 +--- a/lib/sbitmap.c ++++ b/lib/sbitmap.c +@@ -600,38 +600,34 @@ static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) + return NULL; + } + +-static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) ++static bool __sbq_wake_up(struct sbitmap_queue *sbq) + { + struct sbq_wait_state *ws; +- int wake_batch, wait_cnt, cur; ++ unsigned int wake_batch; ++ int wait_cnt; + + ws = sbq_wake_ptr(sbq); +- if (!ws || !nr) ++ if (!ws) + return false; + +- wake_batch = READ_ONCE(sbq->wake_batch); +- cur = atomic_read(&ws->wait_cnt); +- do { +- if (cur <= 0) +- return true; +- wait_cnt = cur - nr; +- } while (!atomic_try_cmpxchg(&ws->wait_cnt, &cur, wait_cnt)); +- ++ wait_cnt = atomic_dec_return(&ws->wait_cnt); + /* + * For concurrent callers of this, callers should call this function + * again to wakeup a new batch on a different 'ws'. + */ +- if (!waitqueue_active(&ws->wait)) ++ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) + return true; + + if (wait_cnt > 0) + return false; + ++ wake_batch = READ_ONCE(sbq->wake_batch); ++ + /* + * Wake up first in case that concurrent callers decrease wait_cnt + * while waitqueue is empty. + */ +- wake_up_nr(&ws->wait, max(wake_batch, nr)); ++ wake_up_nr(&ws->wait, wake_batch); + + /* + * Pairs with the memory barrier in sbitmap_queue_resize() to +@@ -656,11 +652,12 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) + return false; + } + +-void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr) ++void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) + { +- while (__sbq_wake_up(sbq, nr)) ++ while (__sbq_wake_up(sbq)) + ; + } ++EXPORT_SYMBOL_GPL(sbitmap_queue_wake_up); + + static inline void sbitmap_update_cpu_hint(struct sbitmap *sb, int cpu, int tag) + { +@@ -697,7 +694,7 @@ void sbitmap_queue_clear_batch(struct sbitmap_queue *sbq, int offset, + atomic_long_andnot(mask, (atomic_long_t *) addr); + + smp_mb__after_atomic(); +- sbitmap_queue_wake_up(sbq, nr_tags); ++ sbitmap_queue_wake_up(sbq); + sbitmap_update_cpu_hint(&sbq->sb, raw_smp_processor_id(), + tags[nr_tags - 1] - offset); + } +@@ -725,7 +722,7 @@ void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr, + * waiter. See the comment on waitqueue_active(). + */ + smp_mb__after_atomic(); +- sbitmap_queue_wake_up(sbq, 1); ++ sbitmap_queue_wake_up(sbq); + sbitmap_update_cpu_hint(&sbq->sb, cpu, nr); + } + EXPORT_SYMBOL_GPL(sbitmap_queue_clear); +-- +2.35.1 + diff --git a/queue-5.19/revert-usb-storage-add-quirk-for-samsung-fit-flash.patch b/queue-5.19/revert-usb-storage-add-quirk-for-samsung-fit-flash.patch new file mode 100644 index 00000000000..d273702f2fb --- /dev/null +++ b/queue-5.19/revert-usb-storage-add-quirk-for-samsung-fit-flash.patch @@ -0,0 +1,59 @@ +From 2fe0807b2a0f8240d7b79db153dce6cc9b2e0cfc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 20:49:13 +0900 +Subject: Revert "usb: storage: Add quirk for Samsung Fit flash" + +From: sunghwan jung + +[ Upstream commit ad5dbfc123e6ffbbde194e2a4603323e09f741ee ] + +This reverts commit 86d92f5465958752481269348d474414dccb1552, +which fix the timeout issue for "Samsung Fit Flash". + +But the commit affects not only "Samsung Fit Flash" but also other usb +storages that use the same controller and causes severe performance +regression. + + # hdparm -t /dev/sda (without the quirk) + Timing buffered disk reads: 622 MB in 3.01 seconds = 206.66 MB/sec + + # hdparm -t /dev/sda (with the quirk) + Timing buffered disk reads: 220 MB in 3.00 seconds = 73.32 MB/sec + +The commit author mentioned that "Issue was reproduced after device has +bad block", so this quirk should be applied when we have the timeout +issue with a device that has bad blocks. + +We revert the commit so that we apply this quirk by adding kernel +paramters using a bootloader or other ways when we really need it, +without the performance regression with devices that don't have the +issue. + +Signed-off-by: sunghwan jung +Link: https://lore.kernel.org/r/20220913114913.3073-1-onenowy@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/storage/unusual_devs.h | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index 4993227ab293..20dcbccb290b 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -1275,12 +1275,6 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, + USB_SC_RBC, USB_PR_BULK, NULL, + 0 ), + +-UNUSUAL_DEV(0x090c, 0x1000, 0x1100, 0x1100, +- "Samsung", +- "Flash Drive FIT", +- USB_SC_DEVICE, USB_PR_DEVICE, NULL, +- US_FL_MAX_SECTORS_64), +- + /* aeb */ + UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, + "Feiya", +-- +2.35.1 + diff --git a/queue-5.19/rtw89-ser-leave-lps-with-mutex.patch b/queue-5.19/rtw89-ser-leave-lps-with-mutex.patch new file mode 100644 index 00000000000..55c7ec743c4 --- /dev/null +++ b/queue-5.19/rtw89-ser-leave-lps-with-mutex.patch @@ -0,0 +1,39 @@ +From c600ce74c77864abee6957967b335c12b47f1700 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Jul 2022 10:34:51 +0800 +Subject: rtw89: ser: leave lps with mutex + +From: Zong-Zhe Yang + +[ Upstream commit 8676031bae1c91037d06341214f4150b33707c68 ] + +Calling rtw89_leave_lps() should hold rtwdev::mutex. +So, fix it. + +Signed-off-by: Zong-Zhe Yang +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220704023453.19935-5-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/ser.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c +index 9e95ed972710..5d88200cbd3e 100644 +--- a/drivers/net/wireless/realtek/rtw89/ser.c ++++ b/drivers/net/wireless/realtek/rtw89/ser.c +@@ -152,7 +152,10 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt) + rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n", + ser_st_name(ser), ser_ev_name(ser, evt)); + ++ mutex_lock(&rtwdev->mutex); + rtw89_leave_lps(rtwdev); ++ mutex_unlock(&rtwdev->mutex); ++ + ser->st_tbl[ser->state].st_func(ser, evt); + } + +-- +2.35.1 + diff --git a/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch b/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch new file mode 100644 index 00000000000..4f6848fe34f --- /dev/null +++ b/queue-5.19/sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch @@ -0,0 +1,77 @@ +From c1fc79d079bd7a0ceec512ee7946ce8150c046ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 15:09:37 +0200 +Subject: sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up() + +From: Jan Kara + +[ Upstream commit 48c033314f372478548203c583529f53080fd078 ] + +When __sbq_wake_up() decrements wait_cnt to 0 but races with someone +else waking the waiter on the waitqueue (so the waitqueue becomes +empty), it exits without reseting wait_cnt to wake_batch number. Once +wait_cnt is 0, nobody will ever reset the wait_cnt or wake the new +waiters resulting in possible deadlocks or busyloops. Fix the problem by +making sure we reset wait_cnt even if we didn't wake up anybody in the +end. + +Fixes: 040b83fcecfb ("sbitmap: fix possible io hung due to lost wakeup") +Reported-by: Keith Busch +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20220908130937.2795-1-jack@suse.cz +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + lib/sbitmap.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/lib/sbitmap.c b/lib/sbitmap.c +index 1f31147872e6..bb1970ad4875 100644 +--- a/lib/sbitmap.c ++++ b/lib/sbitmap.c +@@ -605,6 +605,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) + struct sbq_wait_state *ws; + unsigned int wake_batch; + int wait_cnt; ++ bool ret; + + ws = sbq_wake_ptr(sbq); + if (!ws) +@@ -615,12 +616,23 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) + * For concurrent callers of this, callers should call this function + * again to wakeup a new batch on a different 'ws'. + */ +- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) ++ if (wait_cnt < 0) + return true; + ++ /* ++ * If we decremented queue without waiters, retry to avoid lost ++ * wakeups. ++ */ + if (wait_cnt > 0) +- return false; ++ return !waitqueue_active(&ws->wait); + ++ /* ++ * When wait_cnt == 0, we have to be particularly careful as we are ++ * responsible to reset wait_cnt regardless whether we've actually ++ * woken up anybody. But in case we didn't wakeup anybody, we still ++ * need to retry. ++ */ ++ ret = !waitqueue_active(&ws->wait); + wake_batch = READ_ONCE(sbq->wake_batch); + + /* +@@ -649,7 +661,7 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) + sbq_index_atomic_inc(&sbq->wake_index); + atomic_set(&ws->wait_cnt, wake_batch); + +- return false; ++ return ret; + } + + void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) +-- +2.35.1 + diff --git a/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch b/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch new file mode 100644 index 00000000000..ebbeff6e57f --- /dev/null +++ b/queue-5.19/sbitmap-fix-batched-wait_cnt-accounting.patch @@ -0,0 +1,141 @@ +From 3551abd659b4be2344b67cfd036151bd6c6363e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 07:53:12 -0700 +Subject: sbitmap: fix batched wait_cnt accounting + +From: Keith Busch + +[ Upstream commit 16ede66973c84f890c03584f79158dd5b2d725f5 ] + +Batched completions can clear multiple bits, but we're only decrementing +the wait_cnt by one each time. This can cause waiters to never be woken, +stalling IO. Use the batched count instead. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=215679 +Signed-off-by: Keith Busch +Link: https://lore.kernel.org/r/20220825145312.1217900-1-kbusch@fb.com +Signed-off-by: Jens Axboe +Stable-dep-of: 48c033314f37 ("sbitmap: Avoid leaving waitqueue in invalid state in __sbq_wake_up()") +Signed-off-by: Sasha Levin +--- + block/blk-mq-tag.c | 2 +- + include/linux/sbitmap.h | 3 ++- + lib/sbitmap.c | 31 +++++++++++++++++-------------- + 3 files changed, 20 insertions(+), 16 deletions(-) + +diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c +index 2dcd738c6952..7aea93047caf 100644 +--- a/block/blk-mq-tag.c ++++ b/block/blk-mq-tag.c +@@ -200,7 +200,7 @@ unsigned int blk_mq_get_tag(struct blk_mq_alloc_data *data) + * other allocations on previous queue won't be starved. + */ + if (bt != bt_prev) +- sbitmap_queue_wake_up(bt_prev); ++ sbitmap_queue_wake_up(bt_prev, 1); + + ws = bt_wait_ptr(bt, data->hctx); + } while (1); +diff --git a/include/linux/sbitmap.h b/include/linux/sbitmap.h +index 8f5a86e210b9..4d2d5205ab58 100644 +--- a/include/linux/sbitmap.h ++++ b/include/linux/sbitmap.h +@@ -575,8 +575,9 @@ void sbitmap_queue_wake_all(struct sbitmap_queue *sbq); + * sbitmap_queue_wake_up() - Wake up some of waiters in one waitqueue + * on a &struct sbitmap_queue. + * @sbq: Bitmap queue to wake up. ++ * @nr: Number of bits cleared. + */ +-void sbitmap_queue_wake_up(struct sbitmap_queue *sbq); ++void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr); + + /** + * sbitmap_queue_show() - Dump &struct sbitmap_queue information to a &struct +diff --git a/lib/sbitmap.c b/lib/sbitmap.c +index 1f31147872e6..a8aae1fc5206 100644 +--- a/lib/sbitmap.c ++++ b/lib/sbitmap.c +@@ -600,34 +600,38 @@ static struct sbq_wait_state *sbq_wake_ptr(struct sbitmap_queue *sbq) + return NULL; + } + +-static bool __sbq_wake_up(struct sbitmap_queue *sbq) ++static bool __sbq_wake_up(struct sbitmap_queue *sbq, int nr) + { + struct sbq_wait_state *ws; +- unsigned int wake_batch; +- int wait_cnt; ++ int wake_batch, wait_cnt, cur; + + ws = sbq_wake_ptr(sbq); +- if (!ws) ++ if (!ws || !nr) + return false; + +- wait_cnt = atomic_dec_return(&ws->wait_cnt); ++ wake_batch = READ_ONCE(sbq->wake_batch); ++ cur = atomic_read(&ws->wait_cnt); ++ do { ++ if (cur <= 0) ++ return true; ++ wait_cnt = cur - nr; ++ } while (!atomic_try_cmpxchg(&ws->wait_cnt, &cur, wait_cnt)); ++ + /* + * For concurrent callers of this, callers should call this function + * again to wakeup a new batch on a different 'ws'. + */ +- if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) ++ if (!waitqueue_active(&ws->wait)) + return true; + + if (wait_cnt > 0) + return false; + +- wake_batch = READ_ONCE(sbq->wake_batch); +- + /* + * Wake up first in case that concurrent callers decrease wait_cnt + * while waitqueue is empty. + */ +- wake_up_nr(&ws->wait, wake_batch); ++ wake_up_nr(&ws->wait, max(wake_batch, nr)); + + /* + * Pairs with the memory barrier in sbitmap_queue_resize() to +@@ -652,12 +656,11 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) + return false; + } + +-void sbitmap_queue_wake_up(struct sbitmap_queue *sbq) ++void sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr) + { +- while (__sbq_wake_up(sbq)) ++ while (__sbq_wake_up(sbq, nr)) + ; + } +-EXPORT_SYMBOL_GPL(sbitmap_queue_wake_up); + + static inline void sbitmap_update_cpu_hint(struct sbitmap *sb, int cpu, int tag) + { +@@ -694,7 +697,7 @@ void sbitmap_queue_clear_batch(struct sbitmap_queue *sbq, int offset, + atomic_long_andnot(mask, (atomic_long_t *) addr); + + smp_mb__after_atomic(); +- sbitmap_queue_wake_up(sbq); ++ sbitmap_queue_wake_up(sbq, nr_tags); + sbitmap_update_cpu_hint(&sbq->sb, raw_smp_processor_id(), + tags[nr_tags - 1] - offset); + } +@@ -722,7 +725,7 @@ void sbitmap_queue_clear(struct sbitmap_queue *sbq, unsigned int nr, + * waiter. See the comment on waitqueue_active(). + */ + smp_mb__after_atomic(); +- sbitmap_queue_wake_up(sbq); ++ sbitmap_queue_wake_up(sbq, 1); + sbitmap_update_cpu_hint(&sbq->sb, cpu, nr); + } + EXPORT_SYMBOL_GPL(sbitmap_queue_clear); +-- +2.35.1 + diff --git a/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch b/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch new file mode 100644 index 00000000000..f743495eb25 --- /dev/null +++ b/queue-5.19/sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch @@ -0,0 +1,141 @@ +From 4cb065659e053366d6113a3526580558897ea8fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 20:15:04 +0800 +Subject: sbitmap: fix possible io hung due to lost wakeup + +From: Yu Kuai + +[ Upstream commit 040b83fcecfb86f3225d3a5de7fd9b3fbccf83b4 ] + +There are two problems can lead to lost wakeup: + +1) invalid wakeup on the wrong waitqueue: + +For example, 2 * wake_batch tags are put, while only wake_batch threads +are woken: + +__sbq_wake_up + atomic_cmpxchg -> reset wait_cnt + __sbq_wake_up -> decrease wait_cnt + ... + __sbq_wake_up -> wait_cnt is decreased to 0 again + atomic_cmpxchg + sbq_index_atomic_inc -> increase wake_index + wake_up_nr -> wake up and waitqueue might be empty + sbq_index_atomic_inc -> increase again, one waitqueue is skipped + wake_up_nr -> invalid wake up because old wakequeue might be empty + +To fix the problem, increasing 'wake_index' before resetting 'wait_cnt'. + +2) 'wait_cnt' can be decreased while waitqueue is empty + +As pointed out by Jan Kara, following race is possible: + +CPU1 CPU2 +__sbq_wake_up __sbq_wake_up + sbq_wake_ptr() sbq_wake_ptr() -> the same + wait_cnt = atomic_dec_return() + /* decreased to 0 */ + sbq_index_atomic_inc() + /* move to next waitqueue */ + atomic_set() + /* reset wait_cnt */ + wake_up_nr() + /* wake up on the old waitqueue */ + wait_cnt = atomic_dec_return() + /* + * decrease wait_cnt in the old + * waitqueue, while it can be + * empty. + */ + +Fix the problem by waking up before updating 'wake_index' and +'wait_cnt'. + +With this patch, noted that 'wait_cnt' is still decreased in the old +empty waitqueue, however, the wakeup is redirected to a active waitqueue, +and the extra decrement on the old empty waitqueue is not handled. + +Fixes: 88459642cba4 ("blk-mq: abstract tag allocation out into sbitmap library") +Signed-off-by: Yu Kuai +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220803121504.212071-1-yukuai1@huaweicloud.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + lib/sbitmap.c | 55 ++++++++++++++++++++++++++++++--------------------- + 1 file changed, 33 insertions(+), 22 deletions(-) + +diff --git a/lib/sbitmap.c b/lib/sbitmap.c +index 29eb0484215a..1f31147872e6 100644 +--- a/lib/sbitmap.c ++++ b/lib/sbitmap.c +@@ -611,32 +611,43 @@ static bool __sbq_wake_up(struct sbitmap_queue *sbq) + return false; + + wait_cnt = atomic_dec_return(&ws->wait_cnt); +- if (wait_cnt <= 0) { +- int ret; ++ /* ++ * For concurrent callers of this, callers should call this function ++ * again to wakeup a new batch on a different 'ws'. ++ */ ++ if (wait_cnt < 0 || !waitqueue_active(&ws->wait)) ++ return true; + +- wake_batch = READ_ONCE(sbq->wake_batch); ++ if (wait_cnt > 0) ++ return false; + +- /* +- * Pairs with the memory barrier in sbitmap_queue_resize() to +- * ensure that we see the batch size update before the wait +- * count is reset. +- */ +- smp_mb__before_atomic(); ++ wake_batch = READ_ONCE(sbq->wake_batch); + +- /* +- * For concurrent callers of this, the one that failed the +- * atomic_cmpxhcg() race should call this function again +- * to wakeup a new batch on a different 'ws'. +- */ +- ret = atomic_cmpxchg(&ws->wait_cnt, wait_cnt, wake_batch); +- if (ret == wait_cnt) { +- sbq_index_atomic_inc(&sbq->wake_index); +- wake_up_nr(&ws->wait, wake_batch); +- return false; +- } ++ /* ++ * Wake up first in case that concurrent callers decrease wait_cnt ++ * while waitqueue is empty. ++ */ ++ wake_up_nr(&ws->wait, wake_batch); + +- return true; +- } ++ /* ++ * Pairs with the memory barrier in sbitmap_queue_resize() to ++ * ensure that we see the batch size update before the wait ++ * count is reset. ++ * ++ * Also pairs with the implicit barrier between decrementing wait_cnt ++ * and checking for waitqueue_active() to make sure waitqueue_active() ++ * sees result of the wakeup if atomic_dec_return() has seen the result ++ * of atomic_set(). ++ */ ++ smp_mb__before_atomic(); ++ ++ /* ++ * Increase wake_index before updating wait_cnt, otherwise concurrent ++ * callers can see valid wait_cnt in old waitqueue, which can cause ++ * invalid wakeup on the old waitqueue. ++ */ ++ sbq_index_atomic_inc(&sbq->wake_index); ++ atomic_set(&ws->wait_cnt, wake_batch); + + return false; + } +-- +2.35.1 + diff --git a/queue-5.19/scsi-3w-9xxx-avoid-disabling-device-if-failing-to-en.patch b/queue-5.19/scsi-3w-9xxx-avoid-disabling-device-if-failing-to-en.patch new file mode 100644 index 00000000000..75719d77c17 --- /dev/null +++ b/queue-5.19/scsi-3w-9xxx-avoid-disabling-device-if-failing-to-en.patch @@ -0,0 +1,42 @@ +From 40c978c2703238288a242303a317c29e0e10b23c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Aug 2022 19:01:15 +0800 +Subject: scsi: 3w-9xxx: Avoid disabling device if failing to enable it + +From: Letu Ren + +[ Upstream commit 7eff437b5ee1309b34667844361c6bbb5c97df05 ] + +The original code will "goto out_disable_device" and call +pci_disable_device() if pci_enable_device() fails. The kernel will generate +a warning message like "3w-9xxx 0000:00:05.0: disabling already-disabled +device". + +We shouldn't disable a device that failed to be enabled. A simple return is +fine. + +Link: https://lore.kernel.org/r/20220829110115.38789-1-fantasquex@gmail.com +Reported-by: Zheyu Ma +Signed-off-by: Letu Ren +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/3w-9xxx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c +index cd823ff5deab..6cb9cca9565b 100644 +--- a/drivers/scsi/3w-9xxx.c ++++ b/drivers/scsi/3w-9xxx.c +@@ -2006,7 +2006,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) + retval = pci_enable_device(pdev); + if (retval) { + TW_PRINTK(host, TW_DRIVER, 0x34, "Failed to enable pci device"); +- goto out_disable_device; ++ return -ENODEV; + } + + pci_set_master(pdev); +-- +2.35.1 + diff --git a/queue-5.19/scsi-iscsi-add-recv-workqueue-helpers.patch b/queue-5.19/scsi-iscsi-add-recv-workqueue-helpers.patch new file mode 100644 index 00000000000..2cc3a063b6f --- /dev/null +++ b/queue-5.19/scsi-iscsi-add-recv-workqueue-helpers.patch @@ -0,0 +1,111 @@ +From 38a1a89f37963e3a892e7cf93b8ea32f430f3bde Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 17:45:50 -0500 +Subject: scsi: iscsi: Add recv workqueue helpers + +From: Mike Christie + +[ Upstream commit 8af809966c0b34cfacd8da9a412689b8e9910354 ] + +Add helpers to allow the drivers to run their recv paths from libiscsi's +workqueue. + +Link: https://lore.kernel.org/r/20220616224557.115234-3-michael.christie@oracle.com +Reviewed-by: Lee Duncan +Signed-off-by: Mike Christie +Signed-off-by: Martin K. Petersen +Stable-dep-of: 57569c37f0ad ("scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername()") +Signed-off-by: Sasha Levin +--- + drivers/scsi/libiscsi.c | 29 +++++++++++++++++++++++++++-- + include/scsi/libiscsi.h | 4 ++++ + 2 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 1bd772d9b804..8f73c8d6ef22 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -93,6 +93,16 @@ inline void iscsi_conn_queue_xmit(struct iscsi_conn *conn) + } + EXPORT_SYMBOL_GPL(iscsi_conn_queue_xmit); + ++inline void iscsi_conn_queue_recv(struct iscsi_conn *conn) ++{ ++ struct Scsi_Host *shost = conn->session->host; ++ struct iscsi_host *ihost = shost_priv(shost); ++ ++ if (ihost->workq && !test_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags)) ++ queue_work(ihost->workq, &conn->recvwork); ++} ++EXPORT_SYMBOL_GPL(iscsi_conn_queue_recv); ++ + static void __iscsi_update_cmdsn(struct iscsi_session *session, + uint32_t exp_cmdsn, uint32_t max_cmdsn) + { +@@ -1943,7 +1953,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_queue); + + /** + * iscsi_suspend_tx - suspend iscsi_data_xmit +- * @conn: iscsi conn tp stop processing IO on. ++ * @conn: iscsi conn to stop processing IO on. + * + * This function sets the suspend bit to prevent iscsi_data_xmit + * from sending new IO, and if work is queued on the xmit thread +@@ -1956,7 +1966,7 @@ void iscsi_suspend_tx(struct iscsi_conn *conn) + + set_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); + if (ihost->workq) +- flush_workqueue(ihost->workq); ++ flush_work(&conn->xmitwork); + } + EXPORT_SYMBOL_GPL(iscsi_suspend_tx); + +@@ -1966,6 +1976,21 @@ static void iscsi_start_tx(struct iscsi_conn *conn) + iscsi_conn_queue_xmit(conn); + } + ++/** ++ * iscsi_suspend_rx - Prevent recvwork from running again. ++ * @conn: iscsi conn to stop. ++ */ ++void iscsi_suspend_rx(struct iscsi_conn *conn) ++{ ++ struct Scsi_Host *shost = conn->session->host; ++ struct iscsi_host *ihost = shost_priv(shost); ++ ++ set_bit(ISCSI_CONN_FLAG_SUSPEND_RX, &conn->flags); ++ if (ihost->workq) ++ flush_work(&conn->recvwork); ++} ++EXPORT_SYMBOL_GPL(iscsi_suspend_rx); ++ + /* + * We want to make sure a ping is in flight. It has timed out. + * And we are not busy processing a pdu that is making +diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h +index 51fb0c17815e..5a10e5acfad2 100644 +--- a/include/scsi/libiscsi.h ++++ b/include/scsi/libiscsi.h +@@ -213,6 +213,8 @@ struct iscsi_conn { + struct list_head cmdqueue; /* data-path cmd queue */ + struct list_head requeue; /* tasks needing another run */ + struct work_struct xmitwork; /* per-conn. xmit workqueue */ ++ /* recv */ ++ struct work_struct recvwork; + unsigned long flags; /* ISCSI_CONN_FLAGs */ + + /* negotiated params */ +@@ -452,8 +454,10 @@ extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, + extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr, + enum iscsi_param param, char *buf); + extern void iscsi_suspend_tx(struct iscsi_conn *conn); ++extern void iscsi_suspend_rx(struct iscsi_conn *conn); + extern void iscsi_suspend_queue(struct iscsi_conn *conn); + extern void iscsi_conn_queue_xmit(struct iscsi_conn *conn); ++extern void iscsi_conn_queue_recv(struct iscsi_conn *conn); + + #define iscsi_conn_printk(prefix, _c, fmt, a...) \ + iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ +-- +2.35.1 + diff --git a/queue-5.19/scsi-iscsi-iscsi_tcp-fix-null-ptr-deref-while-callin.patch b/queue-5.19/scsi-iscsi-iscsi_tcp-fix-null-ptr-deref-while-callin.patch new file mode 100644 index 00000000000..568868ee7d0 --- /dev/null +++ b/queue-5.19/scsi-iscsi-iscsi_tcp-fix-null-ptr-deref-while-callin.patch @@ -0,0 +1,225 @@ +From 7c484cdba1508487d313df392bde9830f3ac93b7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 17:17:00 -0500 +Subject: scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling + getpeername() + +From: Mike Christie + +[ Upstream commit 57569c37f0add1b6489e1a1563c71519daf732cf ] + +Fix a NULL pointer crash that occurs when we are freeing the socket at the +same time we access it via sysfs. + +The problem is that: + + 1. iscsi_sw_tcp_conn_get_param() and iscsi_sw_tcp_host_get_param() take + the frwd_lock and do sock_hold() then drop the frwd_lock. sock_hold() + does a get on the "struct sock". + + 2. iscsi_sw_tcp_release_conn() does sockfd_put() which does the last put + on the "struct socket" and that does __sock_release() which sets the + sock->ops to NULL. + + 3. iscsi_sw_tcp_conn_get_param() and iscsi_sw_tcp_host_get_param() then + call kernel_getpeername() which accesses the NULL sock->ops. + +Above we do a get on the "struct sock", but we needed a get on the "struct +socket". Originally, we just held the frwd_lock the entire time but in +commit bcf3a2953d36 ("scsi: iscsi: iscsi_tcp: Avoid holding spinlock while +calling getpeername()") we switched to refcount based because the network +layer changed and started taking a mutex in that path, so we could no +longer hold the frwd_lock. + +Instead of trying to maintain multiple refcounts, this just has us use a +mutex for accessing the socket in the interface code paths. + +Link: https://lore.kernel.org/r/20220907221700.10302-1-michael.christie@oracle.com +Fixes: bcf3a2953d36 ("scsi: iscsi: iscsi_tcp: Avoid holding spinlock while calling getpeername()") +Signed-off-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/iscsi_tcp.c | 73 ++++++++++++++++++++++++++++------------ + drivers/scsi/iscsi_tcp.h | 3 ++ + 2 files changed, 55 insertions(+), 21 deletions(-) + +diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c +index 10d7f2b7dd0e..7e99070ea611 100644 +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -595,6 +595,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, + INIT_WORK(&conn->recvwork, iscsi_sw_tcp_recv_data_work); + tcp_sw_conn->queue_recv = iscsi_recv_from_iscsi_q; + ++ mutex_init(&tcp_sw_conn->sock_lock); ++ + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) + goto free_conn; +@@ -629,11 +631,15 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, + + static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn) + { +- struct iscsi_session *session = conn->session; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; + struct socket *sock = tcp_sw_conn->sock; + ++ /* ++ * The iscsi transport class will make sure we are not called in ++ * parallel with start, stop, bind and destroys. However, this can be ++ * called twice if userspace does a stop then a destroy. ++ */ + if (!sock) + return; + +@@ -649,9 +655,9 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn) + + iscsi_suspend_rx(conn); + +- spin_lock_bh(&session->frwd_lock); ++ mutex_lock(&tcp_sw_conn->sock_lock); + tcp_sw_conn->sock = NULL; +- spin_unlock_bh(&session->frwd_lock); ++ mutex_unlock(&tcp_sw_conn->sock_lock); + sockfd_put(sock); + } + +@@ -703,7 +709,6 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, + int is_leading) + { +- struct iscsi_session *session = cls_session->dd_data; + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; +@@ -723,10 +728,10 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session, + if (err) + goto free_socket; + +- spin_lock_bh(&session->frwd_lock); ++ mutex_lock(&tcp_sw_conn->sock_lock); + /* bind iSCSI connection and socket */ + tcp_sw_conn->sock = sock; +- spin_unlock_bh(&session->frwd_lock); ++ mutex_unlock(&tcp_sw_conn->sock_lock); + + /* setup Socket parameters */ + sk = sock->sk; +@@ -763,8 +768,15 @@ static int iscsi_sw_tcp_conn_set_param(struct iscsi_cls_conn *cls_conn, + break; + case ISCSI_PARAM_DATADGST_EN: + iscsi_set_param(cls_conn, param, buf, buflen); ++ ++ mutex_lock(&tcp_sw_conn->sock_lock); ++ if (!tcp_sw_conn->sock) { ++ mutex_unlock(&tcp_sw_conn->sock_lock); ++ return -ENOTCONN; ++ } + tcp_sw_conn->sendpage = conn->datadgst_en ? + sock_no_sendpage : tcp_sw_conn->sock->ops->sendpage; ++ mutex_unlock(&tcp_sw_conn->sock_lock); + break; + case ISCSI_PARAM_MAX_R2T: + return iscsi_tcp_set_max_r2t(conn, buf); +@@ -779,8 +791,8 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, char *buf) + { + struct iscsi_conn *conn = cls_conn->dd_data; +- struct iscsi_tcp_conn *tcp_conn = conn->dd_data; +- struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; ++ struct iscsi_sw_tcp_conn *tcp_sw_conn; ++ struct iscsi_tcp_conn *tcp_conn; + struct sockaddr_in6 addr; + struct socket *sock; + int rc; +@@ -790,21 +802,36 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn, + case ISCSI_PARAM_CONN_ADDRESS: + case ISCSI_PARAM_LOCAL_PORT: + spin_lock_bh(&conn->session->frwd_lock); +- if (!tcp_sw_conn || !tcp_sw_conn->sock) { ++ if (!conn->session->leadconn) { + spin_unlock_bh(&conn->session->frwd_lock); + return -ENOTCONN; + } +- sock = tcp_sw_conn->sock; +- sock_hold(sock->sk); ++ /* ++ * The conn has been setup and bound, so just grab a ref ++ * incase a destroy runs while we are in the net layer. ++ */ ++ iscsi_get_conn(conn->cls_conn); + spin_unlock_bh(&conn->session->frwd_lock); + ++ tcp_conn = conn->dd_data; ++ tcp_sw_conn = tcp_conn->dd_data; ++ ++ mutex_lock(&tcp_sw_conn->sock_lock); ++ sock = tcp_sw_conn->sock; ++ if (!sock) { ++ rc = -ENOTCONN; ++ goto sock_unlock; ++ } ++ + if (param == ISCSI_PARAM_LOCAL_PORT) + rc = kernel_getsockname(sock, + (struct sockaddr *)&addr); + else + rc = kernel_getpeername(sock, + (struct sockaddr *)&addr); +- sock_put(sock->sk); ++sock_unlock: ++ mutex_unlock(&tcp_sw_conn->sock_lock); ++ iscsi_put_conn(conn->cls_conn); + if (rc < 0) + return rc; + +@@ -842,17 +869,21 @@ static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost, + } + tcp_conn = conn->dd_data; + tcp_sw_conn = tcp_conn->dd_data; +- sock = tcp_sw_conn->sock; +- if (!sock) { +- spin_unlock_bh(&session->frwd_lock); +- return -ENOTCONN; +- } +- sock_hold(sock->sk); ++ /* ++ * The conn has been setup and bound, so just grab a ref ++ * incase a destroy runs while we are in the net layer. ++ */ ++ iscsi_get_conn(conn->cls_conn); + spin_unlock_bh(&session->frwd_lock); + +- rc = kernel_getsockname(sock, +- (struct sockaddr *)&addr); +- sock_put(sock->sk); ++ mutex_lock(&tcp_sw_conn->sock_lock); ++ sock = tcp_sw_conn->sock; ++ if (!sock) ++ rc = -ENOTCONN; ++ else ++ rc = kernel_getsockname(sock, (struct sockaddr *)&addr); ++ mutex_unlock(&tcp_sw_conn->sock_lock); ++ iscsi_put_conn(conn->cls_conn); + if (rc < 0) + return rc; + +diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h +index 850a018aefb9..68e14a344904 100644 +--- a/drivers/scsi/iscsi_tcp.h ++++ b/drivers/scsi/iscsi_tcp.h +@@ -28,6 +28,9 @@ struct iscsi_sw_tcp_send { + + struct iscsi_sw_tcp_conn { + struct socket *sock; ++ /* Taken when accessing the sock from the netlink/sysfs interface */ ++ struct mutex sock_lock; ++ + struct work_struct recvwork; + bool queue_recv; + +-- +2.35.1 + diff --git a/queue-5.19/scsi-iscsi-rename-iscsi_conn_queue_work.patch b/queue-5.19/scsi-iscsi-rename-iscsi_conn_queue_work.patch new file mode 100644 index 00000000000..3928b67878f --- /dev/null +++ b/queue-5.19/scsi-iscsi-rename-iscsi_conn_queue_work.patch @@ -0,0 +1,126 @@ +From 6b0551e3666a5dcbb95f9fa8fce9b6381e4b7bdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 17:45:49 -0500 +Subject: scsi: iscsi: Rename iscsi_conn_queue_work() + +From: Mike Christie + +[ Upstream commit 4b9f8ce4d5e823e42944c5a0a4842b0f936365ad ] + +Rename iscsi_conn_queue_work() to iscsi_conn_queue_xmit() to reflect that +it handles queueing of xmits only. + +Link: https://lore.kernel.org/r/20220616224557.115234-2-michael.christie@oracle.com +Reviewed-by: Lee Duncan +Reviewed-by: Wu Bo +Signed-off-by: Mike Christie +Signed-off-by: Martin K. Petersen +Stable-dep-of: 57569c37f0ad ("scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername()") +Signed-off-by: Sasha Levin +--- + drivers/scsi/cxgbi/libcxgbi.c | 2 +- + drivers/scsi/iscsi_tcp.c | 2 +- + drivers/scsi/libiscsi.c | 12 ++++++------ + include/scsi/libiscsi.h | 2 +- + 4 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c +index 32abdf0fa9aa..af281e271f88 100644 +--- a/drivers/scsi/cxgbi/libcxgbi.c ++++ b/drivers/scsi/cxgbi/libcxgbi.c +@@ -1455,7 +1455,7 @@ void cxgbi_conn_tx_open(struct cxgbi_sock *csk) + if (conn) { + log_debug(1 << CXGBI_DBG_SOCK, + "csk 0x%p, cid %d.\n", csk, conn->id); +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + } + } + EXPORT_SYMBOL_GPL(cxgbi_conn_tx_open); +diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c +index 52c6f70d60ec..da1dc345b873 100644 +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -205,7 +205,7 @@ static void iscsi_sw_tcp_write_space(struct sock *sk) + old_write_space(sk); + + ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n"); +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + } + + static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn) +diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c +index 3ddb701cd29c..1bd772d9b804 100644 +--- a/drivers/scsi/libiscsi.c ++++ b/drivers/scsi/libiscsi.c +@@ -83,7 +83,7 @@ MODULE_PARM_DESC(debug_libiscsi_eh, + "%s " dbg_fmt, __func__, ##arg); \ + } while (0); + +-inline void iscsi_conn_queue_work(struct iscsi_conn *conn) ++inline void iscsi_conn_queue_xmit(struct iscsi_conn *conn) + { + struct Scsi_Host *shost = conn->session->host; + struct iscsi_host *ihost = shost_priv(shost); +@@ -91,7 +91,7 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn) + if (ihost->workq) + queue_work(ihost->workq, &conn->xmitwork); + } +-EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); ++EXPORT_SYMBOL_GPL(iscsi_conn_queue_xmit); + + static void __iscsi_update_cmdsn(struct iscsi_session *session, + uint32_t exp_cmdsn, uint32_t max_cmdsn) +@@ -765,7 +765,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, + goto free_task; + } else { + list_add_tail(&task->running, &conn->mgmtqueue); +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + } + + return task; +@@ -1513,7 +1513,7 @@ void iscsi_requeue_task(struct iscsi_task *task) + */ + iscsi_put_task(task); + } +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + spin_unlock_bh(&conn->session->frwd_lock); + } + EXPORT_SYMBOL_GPL(iscsi_requeue_task); +@@ -1782,7 +1782,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) + } + } else { + list_add_tail(&task->running, &conn->cmdqueue); +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + } + + session->queued_cmdsn++; +@@ -1963,7 +1963,7 @@ EXPORT_SYMBOL_GPL(iscsi_suspend_tx); + static void iscsi_start_tx(struct iscsi_conn *conn) + { + clear_bit(ISCSI_CONN_FLAG_SUSPEND_TX, &conn->flags); +- iscsi_conn_queue_work(conn); ++ iscsi_conn_queue_xmit(conn); + } + + /* +diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h +index 9758a4a9923f..51fb0c17815e 100644 +--- a/include/scsi/libiscsi.h ++++ b/include/scsi/libiscsi.h +@@ -453,7 +453,7 @@ extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr, + enum iscsi_param param, char *buf); + extern void iscsi_suspend_tx(struct iscsi_conn *conn); + extern void iscsi_suspend_queue(struct iscsi_conn *conn); +-extern void iscsi_conn_queue_work(struct iscsi_conn *conn); ++extern void iscsi_conn_queue_xmit(struct iscsi_conn *conn); + + #define iscsi_conn_printk(prefix, _c, fmt, a...) \ + iscsi_cls_conn_printk(prefix, ((struct iscsi_conn *)_c)->cls_conn, \ +-- +2.35.1 + diff --git a/queue-5.19/scsi-iscsi-run-recv-path-from-workqueue.patch b/queue-5.19/scsi-iscsi-run-recv-path-from-workqueue.patch new file mode 100644 index 00000000000..430dd09f456 --- /dev/null +++ b/queue-5.19/scsi-iscsi-run-recv-path-from-workqueue.patch @@ -0,0 +1,174 @@ +From fe6050fca540b19dc86fcf60c67e83687746029f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jun 2022 17:45:51 -0500 +Subject: scsi: iscsi: Run recv path from workqueue + +From: Mike Christie + +[ Upstream commit f1d269765ee29da56b32818b7a08054484ed89f2 ] + +We don't always want to run the recv path from the network softirq because +when we have to have multiple sessions sharing the same CPUs, some sessions +can eat up the NAPI softirq budget and affect other sessions or users. + +Allow us to queue the recv handling to the iscsi workqueue so we can have +the scheduler/wq code try to balance the work and CPU use across all +sessions' worker threads. + +Note: It wasn't the original intent of the change but a nice side effect is +that for some workloads/configs we get a nice performance boost. For a +simple read heavy test: + + fio --direct=1 --filename=/dev/dm-0 --rw=randread --bs=256K + --ioengine=libaio --iodepth=128 --numjobs=4 + +where the iscsi threads, fio jobs, and rps_cpus share CPUs we see a 32% +throughput boost. We also see increases for small I/O IOPs tests but it's +not as high. + +Link: https://lore.kernel.org/r/20220616224557.115234-4-michael.christie@oracle.com +Reviewed-by: Lee Duncan +Signed-off-by: Mike Christie +Signed-off-by: Martin K. Petersen +Stable-dep-of: 57569c37f0ad ("scsi: iscsi: iscsi_tcp: Fix null-ptr-deref while calling getpeername()") +Signed-off-by: Sasha Levin +--- + drivers/scsi/iscsi_tcp.c | 65 ++++++++++++++++++++++++++++++++-------- + drivers/scsi/iscsi_tcp.h | 2 ++ + 2 files changed, 54 insertions(+), 13 deletions(-) + +diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c +index da1dc345b873..10d7f2b7dd0e 100644 +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -52,6 +52,10 @@ static struct iscsi_transport iscsi_sw_tcp_transport; + static unsigned int iscsi_max_lun = ~0; + module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); + ++static bool iscsi_recv_from_iscsi_q; ++module_param_named(recv_from_iscsi_q, iscsi_recv_from_iscsi_q, bool, 0644); ++MODULE_PARM_DESC(recv_from_iscsi_q, "Set to true to read iSCSI data/headers from the iscsi_q workqueue. The default is false which will perform reads from the network softirq context."); ++ + static int iscsi_sw_tcp_dbg; + module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int, + S_IRUGO | S_IWUSR); +@@ -122,20 +126,13 @@ static inline int iscsi_sw_sk_state_check(struct sock *sk) + return 0; + } + +-static void iscsi_sw_tcp_data_ready(struct sock *sk) ++static void iscsi_sw_tcp_recv_data(struct iscsi_conn *conn) + { +- struct iscsi_conn *conn; +- struct iscsi_tcp_conn *tcp_conn; ++ struct iscsi_tcp_conn *tcp_conn = conn->dd_data; ++ struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; ++ struct sock *sk = tcp_sw_conn->sock->sk; + read_descriptor_t rd_desc; + +- read_lock_bh(&sk->sk_callback_lock); +- conn = sk->sk_user_data; +- if (!conn) { +- read_unlock_bh(&sk->sk_callback_lock); +- return; +- } +- tcp_conn = conn->dd_data; +- + /* + * Use rd_desc to pass 'conn' to iscsi_tcp_recv. + * We set count to 1 because we want the network layer to +@@ -144,13 +141,48 @@ static void iscsi_sw_tcp_data_ready(struct sock *sk) + */ + rd_desc.arg.data = conn; + rd_desc.count = 1; +- tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv); + +- iscsi_sw_sk_state_check(sk); ++ tcp_read_sock(sk, &rd_desc, iscsi_sw_tcp_recv); + + /* If we had to (atomically) map a highmem page, + * unmap it now. */ + iscsi_tcp_segment_unmap(&tcp_conn->in.segment); ++ ++ iscsi_sw_sk_state_check(sk); ++} ++ ++static void iscsi_sw_tcp_recv_data_work(struct work_struct *work) ++{ ++ struct iscsi_conn *conn = container_of(work, struct iscsi_conn, ++ recvwork); ++ struct iscsi_tcp_conn *tcp_conn = conn->dd_data; ++ struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; ++ struct sock *sk = tcp_sw_conn->sock->sk; ++ ++ lock_sock(sk); ++ iscsi_sw_tcp_recv_data(conn); ++ release_sock(sk); ++} ++ ++static void iscsi_sw_tcp_data_ready(struct sock *sk) ++{ ++ struct iscsi_sw_tcp_conn *tcp_sw_conn; ++ struct iscsi_tcp_conn *tcp_conn; ++ struct iscsi_conn *conn; ++ ++ read_lock_bh(&sk->sk_callback_lock); ++ conn = sk->sk_user_data; ++ if (!conn) { ++ read_unlock_bh(&sk->sk_callback_lock); ++ return; ++ } ++ tcp_conn = conn->dd_data; ++ tcp_sw_conn = tcp_conn->dd_data; ++ ++ if (tcp_sw_conn->queue_recv) ++ iscsi_conn_queue_recv(conn); ++ else ++ iscsi_sw_tcp_recv_data(conn); + read_unlock_bh(&sk->sk_callback_lock); + } + +@@ -276,6 +308,9 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, + if (segment->total_copied + segment->size < segment->total_size) + flags |= MSG_MORE; + ++ if (tcp_sw_conn->queue_recv) ++ flags |= MSG_DONTWAIT; ++ + /* Use sendpage if we can; else fall back to sendmsg */ + if (!segment->data) { + sg = segment->sg; +@@ -557,6 +592,8 @@ iscsi_sw_tcp_conn_create(struct iscsi_cls_session *cls_session, + conn = cls_conn->dd_data; + tcp_conn = conn->dd_data; + tcp_sw_conn = tcp_conn->dd_data; ++ INIT_WORK(&conn->recvwork, iscsi_sw_tcp_recv_data_work); ++ tcp_sw_conn->queue_recv = iscsi_recv_from_iscsi_q; + + tfm = crypto_alloc_ahash("crc32c", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(tfm)) +@@ -610,6 +647,8 @@ static void iscsi_sw_tcp_release_conn(struct iscsi_conn *conn) + iscsi_sw_tcp_conn_restore_callbacks(conn); + sock_put(sock->sk); + ++ iscsi_suspend_rx(conn); ++ + spin_lock_bh(&session->frwd_lock); + tcp_sw_conn->sock = NULL; + spin_unlock_bh(&session->frwd_lock); +diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h +index 791453195099..850a018aefb9 100644 +--- a/drivers/scsi/iscsi_tcp.h ++++ b/drivers/scsi/iscsi_tcp.h +@@ -28,6 +28,8 @@ struct iscsi_sw_tcp_send { + + struct iscsi_sw_tcp_conn { + struct socket *sock; ++ struct work_struct recvwork; ++ bool queue_recv; + + struct iscsi_sw_tcp_send out; + /* old values for socket callbacks */ +-- +2.35.1 + diff --git a/queue-5.19/scsi-libsas-fix-use-after-free-bug-in-smp_execute_ta.patch b/queue-5.19/scsi-libsas-fix-use-after-free-bug-in-smp_execute_ta.patch new file mode 100644 index 00000000000..6451c65cf00 --- /dev/null +++ b/queue-5.19/scsi-libsas-fix-use-after-free-bug-in-smp_execute_ta.patch @@ -0,0 +1,54 @@ +From cfd59f1da4c9732bc154d27e68b7f40ceedb4417 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 22:42:13 +0800 +Subject: scsi: libsas: Fix use-after-free bug in smp_execute_task_sg() + +From: Duoming Zhou + +[ Upstream commit 46ba53c30666717cb06c2b3c5d896301cd00d0c0 ] + +When executing SMP task failed, the smp_execute_task_sg() calls del_timer() +to delete "slow_task->timer". However, if the timer handler +sas_task_internal_timedout() is running, the del_timer() in +smp_execute_task_sg() will not stop it and a UAF will happen. The process +is shown below: + + (thread 1) | (thread 2) +smp_execute_task_sg() | sas_task_internal_timedout() + ... | + del_timer() | + ... | ... + sas_free_task(task) | + kfree(task->slow_task) //FREE| + | task->slow_task->... //USE + +Fix by calling del_timer_sync() in smp_execute_task_sg(), which makes sure +the timer handler have finished before the "task->slow_task" is +deallocated. + +Link: https://lore.kernel.org/r/20220920144213.10536-1-duoming@zju.edu.cn +Fixes: 2908d778ab3e ("[SCSI] aic94xx: new driver") +Reviewed-by: Jason Yan +Signed-off-by: Duoming Zhou +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/libsas/sas_expander.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c +index 260e735d06fa..1ec5f4c8e430 100644 +--- a/drivers/scsi/libsas/sas_expander.c ++++ b/drivers/scsi/libsas/sas_expander.c +@@ -67,7 +67,7 @@ static int smp_execute_task_sg(struct domain_device *dev, + res = i->dft->lldd_execute_task(task, GFP_KERNEL); + + if (res) { +- del_timer(&task->slow_task->timer); ++ del_timer_sync(&task->slow_task->timer); + pr_notice("executing SMP task failed:%d\n", res); + break; + } +-- +2.35.1 + diff --git a/queue-5.19/scsi-lpfc-fix-null-ndlp-ptr-dereference-in-abnormal-.patch b/queue-5.19/scsi-lpfc-fix-null-ndlp-ptr-dereference-in-abnormal-.patch new file mode 100644 index 00000000000..5b4315c6ed0 --- /dev/null +++ b/queue-5.19/scsi-lpfc-fix-null-ndlp-ptr-dereference-in-abnormal-.patch @@ -0,0 +1,59 @@ +From d23da277c021c4d22df2c2a6606148384764987e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 18:17:31 -0700 +Subject: scsi: lpfc: Fix null ndlp ptr dereference in abnormal exit path for + GFT_ID + +From: James Smart + +[ Upstream commit 59b7e210a522b836a01516c71ee85d1d92c1f075 ] + +An error case exit from lpfc_cmpl_ct_cmd_gft_id() results in a call to +lpfc_nlp_put() with a null pointer to a nodelist structure. + +Changed lpfc_cmpl_ct_cmd_gft_id() to initialize nodelist pointer upon +entry. + +Link: https://lore.kernel.org/r/20220819011736.14141-3-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_ct.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c +index 13dfe285493d..b555ccb5ae34 100644 +--- a/drivers/scsi/lpfc/lpfc_ct.c ++++ b/drivers/scsi/lpfc/lpfc_ct.c +@@ -1509,7 +1509,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + struct lpfc_sli_ct_request *CTrsp; + int did; + struct lpfc_nodelist *ndlp = NULL; +- struct lpfc_nodelist *ns_ndlp = NULL; ++ struct lpfc_nodelist *ns_ndlp = cmdiocb->ndlp; + uint32_t fc4_data_0, fc4_data_1; + u32 ulp_status = get_job_ulpstatus(phba, rspiocb); + u32 ulp_word4 = get_job_word4(phba, rspiocb); +@@ -1522,15 +1522,12 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + ulp_status, ulp_word4, did); + + /* Ignore response if link flipped after this request was made */ +- if ((uint32_t) cmdiocb->event_tag != phba->fc_eventTag) { ++ if ((uint32_t)cmdiocb->event_tag != phba->fc_eventTag) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, + "9046 Event tag mismatch. Ignoring NS rsp\n"); + goto out; + } + +- /* Preserve the nameserver node to release the reference. */ +- ns_ndlp = cmdiocb->ndlp; +- + if (ulp_status == IOSTAT_SUCCESS) { + /* Good status, continue checking */ + CTrsp = (struct lpfc_sli_ct_request *)outp->virt; +-- +2.35.1 + diff --git a/queue-5.19/scsi-lpfc-fix-various-issues-reported-by-tools.patch b/queue-5.19/scsi-lpfc-fix-various-issues-reported-by-tools.patch new file mode 100644 index 00000000000..c17bb3b1dbc --- /dev/null +++ b/queue-5.19/scsi-lpfc-fix-various-issues-reported-by-tools.patch @@ -0,0 +1,525 @@ +From 7456d0bfc65c4b041fd112538000556b4e3ec57d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Sep 2022 15:15:04 -0700 +Subject: scsi: lpfc: Fix various issues reported by tools + +From: James Smart + +[ Upstream commit a4de8356b68e54149ebdbe6e748e2726152b650c ] + +This patch fixes below Smatch reported issues: + + 1. lpfc_hbadisc.c:3020 lpfc_mbx_cmpl_fcf_rr_read_fcf_rec() + error: uninitialized symbol 'vlan_id'. + + 2. lpfc_hbadisc.c:3121 lpfc_mbx_cmpl_read_fcf_rec() + error: uninitialized symbol 'vlan_id'. + + 3. lpfc_init.c:335 lpfc_dump_wakeup_param_cmpl() + warn: always true condition '(prg->dist < 4) => (0-3 < 4)' + + 4. lpfc_init.c:2419 lpfc_parse_vpd() + warn: inconsistent indenting. + + 5. lpfc_init.c:13248 lpfc_sli4_enable_msi() + warn: 'phba->pcidev->irq' 2147483648 can't fit into 65535 + 'eqhdl->irq' + + 6. lpfc_debugfs.c:5300 lpfc_idiag_extacc_avail_get() + error: uninitialized symbol 'ext_cnt' + + 7. lpfc_debugfs.c:5300 lpfc_idiag_extacc_avail_get() + error: uninitialized symbol 'ext_size' + + 8. lpfc_vmid.c:248 lpfc_vmid_get_appid() + warn: sleeping in atomic context. + + 9. lpfc_init.c:8342 lpfc_sli4_driver_resource_setup() + warn: missing error code 'rc'. + +10. lpfc_init.c:13573 lpfc_sli4_hba_unset() + warn: variable dereferenced before check 'phba->pport' (see + line 13546) + +11. lpfc_auth.c:1923 lpfc_auth_handle_dhchap_reply() + error: double free of 'hash_value' + +Fixes: + + 1. Initialize vlan_id to LPFC_FCOE_NULL_VID. + + 2. Initialize vlan_id to LPFC_FCOE_NULL_VID. + + 3. prg->dist is a 2 bit field. Its value can only be between 0-3. + Remove redundent check 'if (prg->dist < 4)'. + + 4. Fix inconsistent indenting. Moved logic into helper function + lpfc_fill_vpd(). + + 5. Define 'eqhdl->irq' as int value as pci_irq_vector() returns int. + Also, check for return value of pci_irq_vector() and log message in + case of failure. + + 6. Initialize 'ext_cnt' to 0. + + 7. Initialize 'ext_size' to 0. + + 8. Use alloc_percpu_gfp() with GFP_ATOMIC flag. + + 9. 'rc' was not updated when dma_pool_create() fails. Update 'rc = + -ENOMEM' when dma_pool_create() fails before calling goto statement. + +10. Add check for 'phba->pport' in lpfc_cpuhp_remove(). + +11. Initialize 'hash_value' to NULL, same like 'aug_chal' variable. + +Link: https://lore.kernel.org/r/20220911221505.117655-13-jsmart2021@gmail.com +Co-developed-by: Justin Tee +Signed-off-by: Justin Tee +Signed-off-by: James Smart +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_debugfs.c | 2 +- + drivers/scsi/lpfc/lpfc_hbadisc.c | 4 +- + drivers/scsi/lpfc/lpfc_init.c | 249 +++++++++++++++++-------------- + drivers/scsi/lpfc/lpfc_sli.c | 3 + + drivers/scsi/lpfc/lpfc_sli4.h | 4 +- + drivers/scsi/lpfc/lpfc_vmid.c | 4 +- + 6 files changed, 148 insertions(+), 118 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index 24fbf21ea051..32c46fc9fc97 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -5156,7 +5156,7 @@ lpfc_idiag_mbxacc_write(struct file *file, const char __user *buf, + static int + lpfc_idiag_extacc_avail_get(struct lpfc_hba *phba, char *pbuffer, int len) + { +- uint16_t ext_cnt, ext_size; ++ uint16_t ext_cnt = 0, ext_size = 0; + + len += scnprintf(pbuffer+len, LPFC_EXT_ACC_BUF_SIZE-len, + "\nAvailable Extents Information:\n"); +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 5cd838eac455..cf234a80cfc2 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -2964,7 +2964,7 @@ lpfc_mbx_cmpl_fcf_rr_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) + uint32_t boot_flag, addr_mode; + uint16_t next_fcf_index, fcf_index; + uint16_t current_fcf_index; +- uint16_t vlan_id; ++ uint16_t vlan_id = LPFC_FCOE_NULL_VID; + int rc; + + /* If link state is not up, stop the roundrobin failover process */ +@@ -3069,7 +3069,7 @@ lpfc_mbx_cmpl_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) + struct fcf_record *new_fcf_record; + uint32_t boot_flag, addr_mode; + uint16_t fcf_index, next_fcf_index; +- uint16_t vlan_id; ++ uint16_t vlan_id = LPFC_FCOE_NULL_VID; + int rc; + + /* If link state is not up, no need to proceed */ +diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c +index df8216a07d9b..f7d23d2232b3 100644 +--- a/drivers/scsi/lpfc/lpfc_init.c ++++ b/drivers/scsi/lpfc/lpfc_init.c +@@ -325,8 +325,7 @@ lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) + prog_id_word = pmboxq->u.mb.un.varWords[7]; + + /* Decode the Option rom version word to a readable string */ +- if (prg->dist < 4) +- dist = dist_char[prg->dist]; ++ dist = dist_char[prg->dist]; + + if ((prg->dist == 3) && (prg->num == 0)) + snprintf(phba->OptionROMVersion, 32, "%d.%d%d", +@@ -2255,6 +2254,101 @@ lpfc_handle_latt(struct lpfc_hba *phba) + return; + } + ++static void ++lpfc_fill_vpd(struct lpfc_hba *phba, uint8_t *vpd, int length, int *pindex) ++{ ++ int i, j; ++ ++ while (length > 0) { ++ /* Look for Serial Number */ ++ if ((vpd[*pindex] == 'S') && (vpd[*pindex + 1] == 'N')) { ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ j = 0; ++ length -= (3+i); ++ while (i--) { ++ phba->SerialNumber[j++] = vpd[(*pindex)++]; ++ if (j == 31) ++ break; ++ } ++ phba->SerialNumber[j] = 0; ++ continue; ++ } else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '1')) { ++ phba->vpd_flag |= VPD_MODEL_DESC; ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ j = 0; ++ length -= (3+i); ++ while (i--) { ++ phba->ModelDesc[j++] = vpd[(*pindex)++]; ++ if (j == 255) ++ break; ++ } ++ phba->ModelDesc[j] = 0; ++ continue; ++ } else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '2')) { ++ phba->vpd_flag |= VPD_MODEL_NAME; ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ j = 0; ++ length -= (3+i); ++ while (i--) { ++ phba->ModelName[j++] = vpd[(*pindex)++]; ++ if (j == 79) ++ break; ++ } ++ phba->ModelName[j] = 0; ++ continue; ++ } else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '3')) { ++ phba->vpd_flag |= VPD_PROGRAM_TYPE; ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ j = 0; ++ length -= (3+i); ++ while (i--) { ++ phba->ProgramType[j++] = vpd[(*pindex)++]; ++ if (j == 255) ++ break; ++ } ++ phba->ProgramType[j] = 0; ++ continue; ++ } else if ((vpd[*pindex] == 'V') && (vpd[*pindex + 1] == '4')) { ++ phba->vpd_flag |= VPD_PORT; ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ j = 0; ++ length -= (3 + i); ++ while (i--) { ++ if ((phba->sli_rev == LPFC_SLI_REV4) && ++ (phba->sli4_hba.pport_name_sta == ++ LPFC_SLI4_PPNAME_GET)) { ++ j++; ++ (*pindex)++; ++ } else ++ phba->Port[j++] = vpd[(*pindex)++]; ++ if (j == 19) ++ break; ++ } ++ if ((phba->sli_rev != LPFC_SLI_REV4) || ++ (phba->sli4_hba.pport_name_sta == ++ LPFC_SLI4_PPNAME_NON)) ++ phba->Port[j] = 0; ++ continue; ++ } else { ++ *pindex += 2; ++ i = vpd[*pindex]; ++ *pindex += 1; ++ *pindex += i; ++ length -= (3 + i); ++ } ++ } ++} ++ + /** + * lpfc_parse_vpd - Parse VPD (Vital Product Data) + * @phba: pointer to lpfc hba data structure. +@@ -2274,7 +2368,7 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) + { + uint8_t lenlo, lenhi; + int Length; +- int i, j; ++ int i; + int finished = 0; + int index = 0; + +@@ -2307,101 +2401,10 @@ lpfc_parse_vpd(struct lpfc_hba *phba, uint8_t *vpd, int len) + Length = ((((unsigned short)lenhi) << 8) + lenlo); + if (Length > len - index) + Length = len - index; +- while (Length > 0) { +- /* Look for Serial Number */ +- if ((vpd[index] == 'S') && (vpd[index+1] == 'N')) { +- index += 2; +- i = vpd[index]; +- index += 1; +- j = 0; +- Length -= (3+i); +- while(i--) { +- phba->SerialNumber[j++] = vpd[index++]; +- if (j == 31) +- break; +- } +- phba->SerialNumber[j] = 0; +- continue; +- } +- else if ((vpd[index] == 'V') && (vpd[index+1] == '1')) { +- phba->vpd_flag |= VPD_MODEL_DESC; +- index += 2; +- i = vpd[index]; +- index += 1; +- j = 0; +- Length -= (3+i); +- while(i--) { +- phba->ModelDesc[j++] = vpd[index++]; +- if (j == 255) +- break; +- } +- phba->ModelDesc[j] = 0; +- continue; +- } +- else if ((vpd[index] == 'V') && (vpd[index+1] == '2')) { +- phba->vpd_flag |= VPD_MODEL_NAME; +- index += 2; +- i = vpd[index]; +- index += 1; +- j = 0; +- Length -= (3+i); +- while(i--) { +- phba->ModelName[j++] = vpd[index++]; +- if (j == 79) +- break; +- } +- phba->ModelName[j] = 0; +- continue; +- } +- else if ((vpd[index] == 'V') && (vpd[index+1] == '3')) { +- phba->vpd_flag |= VPD_PROGRAM_TYPE; +- index += 2; +- i = vpd[index]; +- index += 1; +- j = 0; +- Length -= (3+i); +- while(i--) { +- phba->ProgramType[j++] = vpd[index++]; +- if (j == 255) +- break; +- } +- phba->ProgramType[j] = 0; +- continue; +- } +- else if ((vpd[index] == 'V') && (vpd[index+1] == '4')) { +- phba->vpd_flag |= VPD_PORT; +- index += 2; +- i = vpd[index]; +- index += 1; +- j = 0; +- Length -= (3+i); +- while(i--) { +- if ((phba->sli_rev == LPFC_SLI_REV4) && +- (phba->sli4_hba.pport_name_sta == +- LPFC_SLI4_PPNAME_GET)) { +- j++; +- index++; +- } else +- phba->Port[j++] = vpd[index++]; +- if (j == 19) +- break; +- } +- if ((phba->sli_rev != LPFC_SLI_REV4) || +- (phba->sli4_hba.pport_name_sta == +- LPFC_SLI4_PPNAME_NON)) +- phba->Port[j] = 0; +- continue; +- } +- else { +- index += 2; +- i = vpd[index]; +- index += 1; +- index += i; +- Length -= (3 + i); +- } +- } +- finished = 0; +- break; ++ ++ lpfc_fill_vpd(phba, vpd, Length, &index); ++ finished = 0; ++ break; + case 0x78: + finished = 1; + break; +@@ -8286,8 +8289,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) + &phba->pcidev->dev, + phba->cfg_sg_dma_buf_size, + i, 0); +- if (!phba->lpfc_sg_dma_buf_pool) ++ if (!phba->lpfc_sg_dma_buf_pool) { ++ rc = -ENOMEM; + goto out_free_bsmbx; ++ } + + phba->lpfc_cmd_rsp_buf_pool = + dma_pool_create("lpfc_cmd_rsp_buf_pool", +@@ -8295,8 +8300,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) + sizeof(struct fcp_cmnd) + + sizeof(struct fcp_rsp), + i, 0); +- if (!phba->lpfc_cmd_rsp_buf_pool) ++ if (!phba->lpfc_cmd_rsp_buf_pool) { ++ rc = -ENOMEM; + goto out_free_sg_dma_buf; ++ } + + mempool_free(mboxq, phba->mbox_mem_pool); + +@@ -12386,7 +12393,7 @@ lpfc_hba_eq_hdl_array_init(struct lpfc_hba *phba) + + for (i = 0; i < phba->cfg_irq_chann; i++) { + eqhdl = lpfc_get_eq_hdl(i); +- eqhdl->irq = LPFC_VECTOR_MAP_EMPTY; ++ eqhdl->irq = LPFC_IRQ_EMPTY; + eqhdl->phba = phba; + } + } +@@ -12759,7 +12766,7 @@ static void __lpfc_cpuhp_remove(struct lpfc_hba *phba) + + static void lpfc_cpuhp_remove(struct lpfc_hba *phba) + { +- if (phba->pport->fc_flag & FC_OFFLINE_MODE) ++ if (phba->pport && (phba->pport->fc_flag & FC_OFFLINE_MODE)) + return; + + __lpfc_cpuhp_remove(phba); +@@ -13023,9 +13030,17 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) + LPFC_DRIVER_HANDLER_NAME"%d", index); + + eqhdl->idx = index; +- rc = request_irq(pci_irq_vector(phba->pcidev, index), +- &lpfc_sli4_hba_intr_handler, 0, +- name, eqhdl); ++ rc = pci_irq_vector(phba->pcidev, index); ++ if (rc < 0) { ++ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, ++ "0489 MSI-X fast-path (%d) " ++ "pci_irq_vec failed (%d)\n", index, rc); ++ goto cfg_fail_out; ++ } ++ eqhdl->irq = rc; ++ ++ rc = request_irq(eqhdl->irq, &lpfc_sli4_hba_intr_handler, 0, ++ name, eqhdl); + if (rc) { + lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, + "0486 MSI-X fast-path (%d) " +@@ -13033,8 +13048,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba) + goto cfg_fail_out; + } + +- eqhdl->irq = pci_irq_vector(phba->pcidev, index); +- + if (aff_mask) { + /* If found a neighboring online cpu, set affinity */ + if (cpu_select < nr_cpu_ids) +@@ -13151,7 +13164,14 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) + } + + eqhdl = lpfc_get_eq_hdl(0); +- eqhdl->irq = pci_irq_vector(phba->pcidev, 0); ++ rc = pci_irq_vector(phba->pcidev, 0); ++ if (rc < 0) { ++ pci_free_irq_vectors(phba->pcidev); ++ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, ++ "0496 MSI pci_irq_vec failed (%d)\n", rc); ++ return rc; ++ } ++ eqhdl->irq = rc; + + cpu = cpumask_first(cpu_present_mask); + lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ, cpu); +@@ -13178,8 +13198,8 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba) + * MSI-X -> MSI -> IRQ. + * + * Return codes +- * 0 - successful +- * other values - error ++ * Interrupt mode (2, 1, 0) - successful ++ * LPFC_INTR_ERROR - error + **/ + static uint32_t + lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) +@@ -13224,7 +13244,14 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) + intr_mode = 0; + + eqhdl = lpfc_get_eq_hdl(0); +- eqhdl->irq = pci_irq_vector(phba->pcidev, 0); ++ retval = pci_irq_vector(phba->pcidev, 0); ++ if (retval < 0) { ++ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, ++ "0502 INTR pci_irq_vec failed (%d)\n", ++ retval); ++ return LPFC_INTR_ERROR; ++ } ++ eqhdl->irq = retval; + + cpu = cpumask_first(cpu_present_mask); + lpfc_assign_eq_map_info(phba, 0, LPFC_CPU_FIRST_IRQ, +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index 2269253aeb3d..73a6d6a503a8 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -6197,6 +6197,9 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type, + struct lpfc_mbx_get_rsrc_extent_info *rsrc_info; + LPFC_MBOXQ_t *mbox; + ++ *extnt_count = 0; ++ *extnt_size = 0; ++ + mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); + if (!mbox) + return -ENOMEM; +diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h +index 1ddad5b170a6..cbb1aa1cf025 100644 +--- a/drivers/scsi/lpfc/lpfc_sli4.h ++++ b/drivers/scsi/lpfc/lpfc_sli4.h +@@ -489,7 +489,7 @@ struct lpfc_hba; + #define LPFC_SLI4_HANDLER_NAME_SZ 16 + struct lpfc_hba_eq_hdl { + uint32_t idx; +- uint16_t irq; ++ int irq; + char handler_name[LPFC_SLI4_HANDLER_NAME_SZ]; + struct lpfc_hba *phba; + struct lpfc_queue *eq; +@@ -611,6 +611,8 @@ struct lpfc_vector_map_info { + }; + #define LPFC_VECTOR_MAP_EMPTY 0xffff + ++#define LPFC_IRQ_EMPTY 0xffffffff ++ + /* Multi-XRI pool */ + #define XRI_BATCH 8 + +diff --git a/drivers/scsi/lpfc/lpfc_vmid.c b/drivers/scsi/lpfc/lpfc_vmid.c +index f64ced04b912..ed1d7f7b88a3 100644 +--- a/drivers/scsi/lpfc/lpfc_vmid.c ++++ b/drivers/scsi/lpfc/lpfc_vmid.c +@@ -245,9 +245,7 @@ int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, + /* allocate the per cpu variable for holding */ + /* the last access time stamp only if VMID is enabled */ + if (!vmp->last_io_time) +- vmp->last_io_time = __alloc_percpu(sizeof(u64), +- __alignof__(struct +- lpfc_vmid)); ++ vmp->last_io_time = alloc_percpu_gfp(u64, GFP_ATOMIC); + if (!vmp->last_io_time) { + hash_del(&vmp->hnode); + vmp->flag = LPFC_VMID_SLOT_FREE; +-- +2.35.1 + diff --git a/queue-5.19/scsi-pm8001-fix-running_req-for-internal-abort-comma.patch b/queue-5.19/scsi-pm8001-fix-running_req-for-internal-abort-comma.patch new file mode 100644 index 00000000000..b5a513aa701 --- /dev/null +++ b/queue-5.19/scsi-pm8001-fix-running_req-for-internal-abort-comma.patch @@ -0,0 +1,78 @@ +From b77df5a39b8e06f1736f3ec20b8b2da2b9d97c0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 21:51:04 +0800 +Subject: scsi: pm8001: Fix running_req for internal abort commands + +From: John Garry + +[ Upstream commit d8c22c4697c11ed28062afe3c2b377025be11a23 ] + +Disabling the remote phy for a SATA disk causes a hang: + +root@(none)$ more /sys/class/sas_phy/phy-0:0:8/target_port_protocols +sata +root@(none)$ echo 0 > sys/class/sas_phy/phy-0:0:8/enable +root@(none)$ [ 67.855950] sas: ex 500e004aaaaaaa1f phy08 change count has changed +[ 67.920585] sd 0:0:2:0: [sdc] Synchronizing SCSI cache +[ 67.925780] sd 0:0:2:0: [sdc] Synchronize Cache(10) failed: Result: hostbyte=0x04 driverbyte=DRIVER_OK +[ 67.935094] sd 0:0:2:0: [sdc] Stopping disk +[ 67.939305] sd 0:0:2:0: [sdc] Start/Stop Unit failed: Result: hostbyte=0x04 driverbyte=DRIVER_OK +... +[ 123.998998] INFO: task kworker/u192:1:642 blocked for more than 30 seconds. +[ 124.005960] Not tainted 6.0.0-rc1-205202-gf26f8f761e83 #218 +[ 124.012049] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +[ 124.019872] task:kworker/u192:1 state:D stack:0 pid: 642 ppid: 2 flags:0x00000008 +[ 124.028223] Workqueue: 0000:04:00.0_event_q sas_port_event_worker +[ 124.034319] Call trace: +[ 124.036758] __switch_to+0x128/0x278 +[ 124.040333] __schedule+0x434/0xa58 +[ 124.043820] schedule+0x94/0x138 +[ 124.047045] schedule_timeout+0x2fc/0x368 +[ 124.051052] wait_for_completion+0xdc/0x200 +[ 124.055234] __flush_workqueue+0x1a8/0x708 +[ 124.059328] sas_porte_broadcast_rcvd+0xa8/0xc0 +[ 124.063858] sas_port_event_worker+0x60/0x98 +[ 124.068126] process_one_work+0x3f8/0x660 +[ 124.072134] worker_thread+0x70/0x700 +[ 124.075793] kthread+0x1a4/0x1b8 +[ 124.079014] ret_from_fork+0x10/0x20 + +The issue is that the per-device running_req read in +pm8001_dev_gone_notify() never goes to zero and we never make progress. +This is caused by missing accounting for running_req for when an internal +abort command completes. + +In commit 2cbbf489778e ("scsi: pm8001: Use libsas internal abort support") +we started to send internal abort commands as a proper sas_task. In this +when we deliver a sas_task to HW the per-device running_req is incremented +in pm8001_queue_command(). However it is never decremented for internal +abort commnds, so decrement in pm8001_mpi_task_abort_resp(). + +Link: https://lore.kernel.org/r/1663854664-76165-1-git-send-email-john.garry@huawei.com +Fixes: 2cbbf489778e ("scsi: pm8001: Use libsas internal abort support") +Acked-by: Jack Wang +Signed-off-by: John Garry +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/pm8001/pm8001_hwi.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c +index 991eb01bb1e0..0ccaefc35d6b 100644 +--- a/drivers/scsi/pm8001/pm8001_hwi.c ++++ b/drivers/scsi/pm8001/pm8001_hwi.c +@@ -3608,6 +3608,10 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_dbg(pm8001_ha, FAIL, " TASK NULL. RETURNING !!!\n"); + return -1; + } ++ ++ if (t->task_proto == SAS_PROTOCOL_INTERNAL_ABORT) ++ atomic_dec(&pm8001_dev->running_req); ++ + ts = &t->task_status; + if (status != 0) + pm8001_dbg(pm8001_ha, FAIL, "task abort failed status 0x%x ,tag = 0x%x, scp= 0x%x\n", +-- +2.35.1 + diff --git a/queue-5.19/scsi-tracing-fix-compile-error-in-trace_array-calls-.patch b/queue-5.19/scsi-tracing-fix-compile-error-in-trace_array-calls-.patch new file mode 100644 index 00000000000..006348875e3 --- /dev/null +++ b/queue-5.19/scsi-tracing-fix-compile-error-in-trace_array-calls-.patch @@ -0,0 +1,100 @@ +From a9dfaea96c6b95695f13c9199a7a925089fd9f2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 16:33:08 -0700 +Subject: scsi: tracing: Fix compile error in trace_array calls when TRACING is + disabled + +From: Arun Easi + +[ Upstream commit 1a77dd1c2bb5d4a58c16d198cf593720787c02e4 ] + +Fix this compilation error seen when CONFIG_TRACING is not enabled: + +drivers/scsi/qla2xxx/qla_os.c: In function 'qla_trace_init': +drivers/scsi/qla2xxx/qla_os.c:2854:25: error: implicit declaration of function +'trace_array_get_by_name'; did you mean 'trace_array_set_clr_event'? +[-Werror=implicit-function-declaration] + 2854 | qla_trc_array = trace_array_get_by_name("qla2xxx"); + | ^~~~~~~~~~~~~~~~~~~~~~~ + | trace_array_set_clr_event + +drivers/scsi/qla2xxx/qla_os.c: In function 'qla_trace_uninit': +drivers/scsi/qla2xxx/qla_os.c:2869:9: error: implicit declaration of function +'trace_array_put' [-Werror=implicit-function-declaration] + 2869 | trace_array_put(qla_trc_array); + | ^~~~~~~~~~~~~~~ + +Link: https://lore.kernel.org/r/20220907233308.4153-2-aeasi@marvell.com +Reported-by: kernel test robot +Reviewed-by: Steven Rostedt (Google) +Signed-off-by: Arun Easi +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + include/linux/trace.h | 36 ++++++++++++++++++++++++++++++++++-- + 1 file changed, 34 insertions(+), 2 deletions(-) + +diff --git a/include/linux/trace.h b/include/linux/trace.h +index bf169612ffe1..b5e16e438448 100644 +--- a/include/linux/trace.h ++++ b/include/linux/trace.h +@@ -2,8 +2,6 @@ + #ifndef _LINUX_TRACE_H + #define _LINUX_TRACE_H + +-#ifdef CONFIG_TRACING +- + #define TRACE_EXPORT_FUNCTION BIT(0) + #define TRACE_EXPORT_EVENT BIT(1) + #define TRACE_EXPORT_MARKER BIT(2) +@@ -28,6 +26,8 @@ struct trace_export { + int flags; + }; + ++#ifdef CONFIG_TRACING ++ + int register_ftrace_export(struct trace_export *export); + int unregister_ftrace_export(struct trace_export *export); + +@@ -48,6 +48,38 @@ void osnoise_arch_unregister(void); + void osnoise_trace_irq_entry(int id); + void osnoise_trace_irq_exit(int id, const char *desc); + ++#else /* CONFIG_TRACING */ ++static inline int register_ftrace_export(struct trace_export *export) ++{ ++ return -EINVAL; ++} ++static inline int unregister_ftrace_export(struct trace_export *export) ++{ ++ return 0; ++} ++static inline void trace_printk_init_buffers(void) ++{ ++} ++static inline int trace_array_printk(struct trace_array *tr, unsigned long ip, ++ const char *fmt, ...) ++{ ++ return 0; ++} ++static inline int trace_array_init_printk(struct trace_array *tr) ++{ ++ return -EINVAL; ++} ++static inline void trace_array_put(struct trace_array *tr) ++{ ++} ++static inline struct trace_array *trace_array_get_by_name(const char *name) ++{ ++ return NULL; ++} ++static inline int trace_array_destroy(struct trace_array *tr) ++{ ++ return 0; ++} + #endif /* CONFIG_TRACING */ + + #endif /* _LINUX_TRACE_H */ +-- +2.35.1 + diff --git a/queue-5.19/sctp-handle-the-error-returned-from-sctp_auth_asoc_i.patch b/queue-5.19/sctp-handle-the-error-returned-from-sctp_auth_asoc_i.patch new file mode 100644 index 00000000000..0c31faa0681 --- /dev/null +++ b/queue-5.19/sctp-handle-the-error-returned-from-sctp_auth_asoc_i.patch @@ -0,0 +1,79 @@ +From b7d1619dbeb033591dd4772d3053a46b78fc1a67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 14:10:13 -0400 +Subject: sctp: handle the error returned from sctp_auth_asoc_init_active_key + +From: Xin Long + +[ Upstream commit 022152aaebe116a25c39818a07e175a8cd3c1e11 ] + +When it returns an error from sctp_auth_asoc_init_active_key(), the +active_key is actually not updated. The old sh_key will be freeed +while it's still used as active key in asoc. Then an use-after-free +will be triggered when sending patckets, as found by syzbot: + + sctp_auth_shkey_hold+0x22/0xa0 net/sctp/auth.c:112 + sctp_set_owner_w net/sctp/socket.c:132 [inline] + sctp_sendmsg_to_asoc+0xbd5/0x1a20 net/sctp/socket.c:1863 + sctp_sendmsg+0x1053/0x1d50 net/sctp/socket.c:2025 + inet_sendmsg+0x99/0xe0 net/ipv4/af_inet.c:819 + sock_sendmsg_nosec net/socket.c:714 [inline] + sock_sendmsg+0xcf/0x120 net/socket.c:734 + +This patch is to fix it by not replacing the sh_key when it returns +errors from sctp_auth_asoc_init_active_key() in sctp_auth_set_key(). +For sctp_auth_set_active_key(), old active_key_id will be set back +to asoc->active_key_id when the same thing happens. + +Fixes: 58acd1009226 ("sctp: update active_key for asoc when old key is being replaced") +Reported-by: syzbot+a236dd8e9622ed8954a3@syzkaller.appspotmail.com +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index db6b7373d16c..34964145514e 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -863,12 +863,17 @@ int sctp_auth_set_key(struct sctp_endpoint *ep, + } + + list_del_init(&shkey->key_list); +- sctp_auth_shkey_release(shkey); + list_add(&cur_key->key_list, sh_keys); + +- if (asoc && asoc->active_key_id == auth_key->sca_keynumber) +- sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); ++ if (asoc && asoc->active_key_id == auth_key->sca_keynumber && ++ sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL)) { ++ list_del_init(&cur_key->key_list); ++ sctp_auth_shkey_release(cur_key); ++ list_add(&shkey->key_list, sh_keys); ++ return -ENOMEM; ++ } + ++ sctp_auth_shkey_release(shkey); + return 0; + } + +@@ -902,8 +907,13 @@ int sctp_auth_set_active_key(struct sctp_endpoint *ep, + return -EINVAL; + + if (asoc) { ++ __u16 active_key_id = asoc->active_key_id; ++ + asoc->active_key_id = key_id; +- sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL); ++ if (sctp_auth_asoc_init_active_key(asoc, GFP_KERNEL)) { ++ asoc->active_key_id = active_key_id; ++ return -ENOMEM; ++ } + } else + ep->active_key_id = key_id; + +-- +2.35.1 + diff --git a/queue-5.19/selftest-tpm2-add-client.__del__-to-close-dev-tpm-ha.patch b/queue-5.19/selftest-tpm2-add-client.__del__-to-close-dev-tpm-ha.patch new file mode 100644 index 00000000000..b78f6bf2653 --- /dev/null +++ b/queue-5.19/selftest-tpm2-add-client.__del__-to-close-dev-tpm-ha.patch @@ -0,0 +1,49 @@ +From 76208c1b1ed41ffd9b4298950615c65d5df01d0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 09:15:18 -0400 +Subject: selftest: tpm2: Add Client.__del__() to close /dev/tpm* handle + +From: Stefan Berger + +[ Upstream commit 2d869f0b458547386fbcd8cf3004b271b7347b7f ] + +The following output can bee seen when the test is executed: + + test_flush_context (tpm2_tests.SpaceTest) ... \ + /usr/lib64/python3.6/unittest/case.py:605: ResourceWarning: \ + unclosed file <_io.FileIO name='/dev/tpmrm0' mode='rb+' closefd=True> + +An instance of Client does not implicitly close /dev/tpm* handle, once it +gets destroyed. Close the file handle in the class destructor +Client.__del__(). + +Fixes: 6ea3dfe1e0732 ("selftests: add TPM 2.0 tests") +Cc: Shuah Khan +Cc: linux-kselftest@vger.kernel.org +Cc: Jarkko Sakkinen +Signed-off-by: Stefan Berger +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/tpm2/tpm2.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/testing/selftests/tpm2/tpm2.py b/tools/testing/selftests/tpm2/tpm2.py +index 057a4f49c79d..c7363c6764fc 100644 +--- a/tools/testing/selftests/tpm2/tpm2.py ++++ b/tools/testing/selftests/tpm2/tpm2.py +@@ -371,6 +371,10 @@ class Client: + fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags) + self.tpm_poll = select.poll() + ++ def __del__(self): ++ if self.tpm: ++ self.tpm.close() ++ + def close(self): + self.tpm.close() + +-- +2.35.1 + diff --git a/queue-5.19/selftests-bpf-free-the-allocated-resources-after-tes.patch b/queue-5.19/selftests-bpf-free-the-allocated-resources-after-tes.patch new file mode 100644 index 00000000000..af58bc158d9 --- /dev/null +++ b/queue-5.19/selftests-bpf-free-the-allocated-resources-after-tes.patch @@ -0,0 +1,196 @@ +From 42f569ebc016728b8917be0de0347bbe531e52e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 15:00:35 +0800 +Subject: selftests/bpf: Free the allocated resources after test case succeeds + +From: Hou Tao + +[ Upstream commit 103d002fb7d548fb1187e350f2b73788558128b9 ] + +Free the created fd or allocated bpf_object after test case succeeds, +else there will be resource leaks. + +Spotted by using address sanitizer and checking the content of +/proc/$pid/fd directory. + +Signed-off-by: Hou Tao +Link: https://lore.kernel.org/r/20220921070035.2016413-3-houtao@huaweicloud.com +Signed-off-by: Martin KaFai Lau +Signed-off-by: Sasha Levin +--- + .../bpf/map_tests/array_map_batch_ops.c | 2 ++ + .../bpf/map_tests/htab_map_batch_ops.c | 2 ++ + .../bpf/map_tests/lpm_trie_map_batch_ops.c | 2 ++ + tools/testing/selftests/bpf/test_maps.c | 24 ++++++++++++------- + 4 files changed, 21 insertions(+), 9 deletions(-) + +diff --git a/tools/testing/selftests/bpf/map_tests/array_map_batch_ops.c b/tools/testing/selftests/bpf/map_tests/array_map_batch_ops.c +index 78c76496b14a..b595556315bc 100644 +--- a/tools/testing/selftests/bpf/map_tests/array_map_batch_ops.c ++++ b/tools/testing/selftests/bpf/map_tests/array_map_batch_ops.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -137,6 +138,7 @@ static void __test_map_lookup_and_update_batch(bool is_pcpu) + free(keys); + free(values); + free(visited); ++ close(map_fd); + } + + static void array_map_batch_ops(void) +diff --git a/tools/testing/selftests/bpf/map_tests/htab_map_batch_ops.c b/tools/testing/selftests/bpf/map_tests/htab_map_batch_ops.c +index f807d53fd8dd..1230ccf90128 100644 +--- a/tools/testing/selftests/bpf/map_tests/htab_map_batch_ops.c ++++ b/tools/testing/selftests/bpf/map_tests/htab_map_batch_ops.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -255,6 +256,7 @@ void __test_map_lookup_and_delete_batch(bool is_pcpu) + free(visited); + if (!is_pcpu) + free(values); ++ close(map_fd); + } + + void htab_map_batch_ops(void) +diff --git a/tools/testing/selftests/bpf/map_tests/lpm_trie_map_batch_ops.c b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_batch_ops.c +index 87d07b596e17..b66d56ddb7ef 100644 +--- a/tools/testing/selftests/bpf/map_tests/lpm_trie_map_batch_ops.c ++++ b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_batch_ops.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -150,4 +151,5 @@ void test_lpm_trie_map_batch_ops(void) + free(keys); + free(values); + free(visited); ++ close(map_fd); + } +diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c +index cbebfaa7c1e8..4d42ffea0038 100644 +--- a/tools/testing/selftests/bpf/test_maps.c ++++ b/tools/testing/selftests/bpf/test_maps.c +@@ -658,13 +658,13 @@ static void test_sockmap(unsigned int tasks, void *data) + { + struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break; + int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break; ++ struct bpf_object *parse_obj, *verdict_obj, *msg_obj; + int ports[] = {50200, 50201, 50202, 50204}; + int err, i, fd, udp, sfd[6] = {0xdeadbeef}; + u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; + int parse_prog, verdict_prog, msg_prog; + struct sockaddr_in addr; + int one = 1, s, sc, rc; +- struct bpf_object *obj; + struct timeval to; + __u32 key, value; + pid_t pid[tasks]; +@@ -760,6 +760,7 @@ static void test_sockmap(unsigned int tasks, void *data) + i, udp); + goto out_sockmap; + } ++ close(udp); + + /* Test update without programs */ + for (i = 0; i < 6; i++) { +@@ -822,27 +823,27 @@ static void test_sockmap(unsigned int tasks, void *data) + + /* Load SK_SKB program and Attach */ + err = bpf_prog_test_load(SOCKMAP_PARSE_PROG, +- BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog); ++ BPF_PROG_TYPE_SK_SKB, &parse_obj, &parse_prog); + if (err) { + printf("Failed to load SK_SKB parse prog\n"); + goto out_sockmap; + } + + err = bpf_prog_test_load(SOCKMAP_TCP_MSG_PROG, +- BPF_PROG_TYPE_SK_MSG, &obj, &msg_prog); ++ BPF_PROG_TYPE_SK_MSG, &msg_obj, &msg_prog); + if (err) { + printf("Failed to load SK_SKB msg prog\n"); + goto out_sockmap; + } + + err = bpf_prog_test_load(SOCKMAP_VERDICT_PROG, +- BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog); ++ BPF_PROG_TYPE_SK_SKB, &verdict_obj, &verdict_prog); + if (err) { + printf("Failed to load SK_SKB verdict prog\n"); + goto out_sockmap; + } + +- bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx"); ++ bpf_map_rx = bpf_object__find_map_by_name(verdict_obj, "sock_map_rx"); + if (!bpf_map_rx) { + printf("Failed to load map rx from verdict prog\n"); + goto out_sockmap; +@@ -854,7 +855,7 @@ static void test_sockmap(unsigned int tasks, void *data) + goto out_sockmap; + } + +- bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx"); ++ bpf_map_tx = bpf_object__find_map_by_name(verdict_obj, "sock_map_tx"); + if (!bpf_map_tx) { + printf("Failed to load map tx from verdict prog\n"); + goto out_sockmap; +@@ -866,7 +867,7 @@ static void test_sockmap(unsigned int tasks, void *data) + goto out_sockmap; + } + +- bpf_map_msg = bpf_object__find_map_by_name(obj, "sock_map_msg"); ++ bpf_map_msg = bpf_object__find_map_by_name(verdict_obj, "sock_map_msg"); + if (!bpf_map_msg) { + printf("Failed to load map msg from msg_verdict prog\n"); + goto out_sockmap; +@@ -878,7 +879,7 @@ static void test_sockmap(unsigned int tasks, void *data) + goto out_sockmap; + } + +- bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break"); ++ bpf_map_break = bpf_object__find_map_by_name(verdict_obj, "sock_map_break"); + if (!bpf_map_break) { + printf("Failed to load map tx from verdict prog\n"); + goto out_sockmap; +@@ -1124,7 +1125,9 @@ static void test_sockmap(unsigned int tasks, void *data) + } + close(fd); + close(map_fd_rx); +- bpf_object__close(obj); ++ bpf_object__close(parse_obj); ++ bpf_object__close(msg_obj); ++ bpf_object__close(verdict_obj); + return; + out: + for (i = 0; i < 6; i++) +@@ -1282,8 +1285,11 @@ static void test_map_in_map(void) + printf("Inner map mim.inner was not destroyed\n"); + goto out_map_in_map; + } ++ ++ close(fd); + } + ++ bpf_object__close(obj); + return; + + out_map_in_map: +-- +2.35.1 + diff --git a/queue-5.19/selftests-cpu-hotplug-delete-fault-injection-related.patch b/queue-5.19/selftests-cpu-hotplug-delete-fault-injection-related.patch new file mode 100644 index 00000000000..578721adefb --- /dev/null +++ b/queue-5.19/selftests-cpu-hotplug-delete-fault-injection-related.patch @@ -0,0 +1,168 @@ +From 3ebbdd2966382da0d4d34b48b7f9e925e1347dc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 21:36:13 +0800 +Subject: selftests/cpu-hotplug: Delete fault injection related code + +From: Zhao Gongyi + +[ Upstream commit 195d74be717af14e5991f818f73f067367bfc1ed ] + +Delete fault injection related code since the module has been deleted. + +Signed-off-by: Zhao Gongyi +Signed-off-by: Shuah Khan +Stable-dep-of: 51d4c851465c ("selftests/cpu-hotplug: Reserve one cpu online at least") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/cpu-hotplug/config | 1 - + .../selftests/cpu-hotplug/cpu-on-off-test.sh | 87 ++----------------- + 2 files changed, 6 insertions(+), 82 deletions(-) + delete mode 100644 tools/testing/selftests/cpu-hotplug/config + +diff --git a/tools/testing/selftests/cpu-hotplug/config b/tools/testing/selftests/cpu-hotplug/config +deleted file mode 100644 +index d4aca2ad5069..000000000000 +--- a/tools/testing/selftests/cpu-hotplug/config ++++ /dev/null +@@ -1 +0,0 @@ +-CONFIG_NOTIFIER_ERROR_INJECTION=y +diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +index 940b68c940bb..32ec7e4489ee 100755 +--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh ++++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +@@ -116,10 +116,10 @@ online_cpu_expect_fail() + + if online_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 +- exit 1 ++ retval=1 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected online >&2 +- exit 1 ++ retval=1 + fi + } + +@@ -142,16 +142,14 @@ offline_cpu_expect_fail() + + if offline_cpu $cpu 2> /dev/null; then + echo $FUNCNAME $cpu: unexpected success >&2 +- exit 1 ++ retval=1 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 +- exit 1 ++ retval=1 + fi + } + +-error=-12 + allcpus=0 +-priority=0 + online_cpus=0 + online_max=0 + offline_cpus=0 +@@ -159,31 +157,20 @@ offline_max=0 + present_cpus=0 + present_max=0 + +-while getopts e:ahp: opt; do ++while getopts ah opt; do + case $opt in +- e) +- error=$OPTARG +- ;; + a) + allcpus=1 + ;; + h) +- echo "Usage $0 [ -a ] [ -e errno ] [ -p notifier-priority ]" ++ echo "Usage $0 [ -a ]" + echo -e "\t default offline one cpu" + echo -e "\t run with -a option to offline all cpus" + exit + ;; +- p) +- priority=$OPTARG +- ;; + esac + done + +-if ! [ "$error" -ge -4095 -a "$error" -lt 0 ]; then +- echo "error code must be -4095 <= errno < 0" >&2 +- exit 1 +-fi +- + prerequisite + + # +@@ -231,66 +218,4 @@ for cpu in `hotplaggable_offline_cpus`; do + online_cpu_expect_success $cpu + done + +-# +-# Test with cpu notifier error injection +-# +- +-DEBUGFS=`mount -t debugfs | head -1 | awk '{ print $3 }'` +-NOTIFIER_ERR_INJECT_DIR=$DEBUGFS/notifier-error-inject/cpu +- +-prerequisite_extra() +-{ +- msg="skip extra tests:" +- +- /sbin/modprobe -q -r cpu-notifier-error-inject +- /sbin/modprobe -q cpu-notifier-error-inject priority=$priority +- +- if [ ! -d "$DEBUGFS" ]; then +- echo $msg debugfs is not mounted >&2 +- exit $ksft_skip +- fi +- +- if [ ! -d $NOTIFIER_ERR_INJECT_DIR ]; then +- echo $msg cpu-notifier-error-inject module is not available >&2 +- exit $ksft_skip +- fi +-} +- +-prerequisite_extra +- +-# +-# Offline all hot-pluggable CPUs +-# +-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +-for cpu in `hotpluggable_online_cpus`; do +- offline_cpu_expect_success $cpu +-done +- +-# +-# Test CPU hot-add error handling (offline => online) +-# +-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error +-for cpu in `hotplaggable_offline_cpus`; do +- online_cpu_expect_fail $cpu +-done +- +-# +-# Online all hot-pluggable CPUs +-# +-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_UP_PREPARE/error +-for cpu in `hotplaggable_offline_cpus`; do +- online_cpu_expect_success $cpu +-done +- +-# +-# Test CPU hot-remove error handling (online => offline) +-# +-echo $error > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +-for cpu in `hotpluggable_online_cpus`; do +- offline_cpu_expect_fail $cpu +-done +- +-echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error +-/sbin/modprobe -q -r cpu-notifier-error-inject +- + exit $retval +-- +2.35.1 + diff --git a/queue-5.19/selftests-cpu-hotplug-reserve-one-cpu-online-at-leas.patch b/queue-5.19/selftests-cpu-hotplug-reserve-one-cpu-online-at-leas.patch new file mode 100644 index 00000000000..e6cc8ede2a9 --- /dev/null +++ b/queue-5.19/selftests-cpu-hotplug-reserve-one-cpu-online-at-leas.patch @@ -0,0 +1,84 @@ +From e6006d195338689e0c40d3c5e4c13859ca18a7dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 21:36:14 +0800 +Subject: selftests/cpu-hotplug: Reserve one cpu online at least + +From: Zhao Gongyi + +[ Upstream commit 51d4c851465c32143d9c7b1cfb46fc581922b116 ] + +Considering that we can not offline all cpus in any cases, +we need to reserve one cpu online when the test offline all +hotpluggable online cpus, otherwise the test will fail forever. + +Fixes: d89dffa976bc ("fault-injection: add selftests for cpu and memory hotplug") + +Signed-off-by: Zhao Gongyi +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + .../selftests/cpu-hotplug/cpu-on-off-test.sh | 40 ++++++++++--------- + 1 file changed, 22 insertions(+), 18 deletions(-) + +diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +index 32ec7e4489ee..4c1d6d9abecc 100755 +--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh ++++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +@@ -149,6 +149,25 @@ offline_cpu_expect_fail() + fi + } + ++online_all_hot_pluggable_cpus() ++{ ++ for cpu in `hotplaggable_offline_cpus`; do ++ online_cpu_expect_success $cpu ++ done ++} ++ ++offline_all_hot_pluggable_cpus() ++{ ++ local reserve_cpu=$online_max ++ for cpu in `hotpluggable_online_cpus`; do ++ # Reserve one cpu oneline at least. ++ if [ $cpu -eq $reserve_cpu ];then ++ continue ++ fi ++ offline_cpu_expect_success $cpu ++ done ++} ++ + allcpus=0 + online_cpus=0 + online_max=0 +@@ -197,25 +216,10 @@ else + echo -e "\t online all offline cpus" + fi + +-# +-# Online all hot-pluggable CPUs +-# +-for cpu in `hotplaggable_offline_cpus`; do +- online_cpu_expect_success $cpu +-done ++online_all_hot_pluggable_cpus + +-# +-# Offline all hot-pluggable CPUs +-# +-for cpu in `hotpluggable_online_cpus`; do +- offline_cpu_expect_success $cpu +-done ++offline_all_hot_pluggable_cpus + +-# +-# Online all hot-pluggable CPUs again +-# +-for cpu in `hotplaggable_offline_cpus`; do +- online_cpu_expect_success $cpu +-done ++online_all_hot_pluggable_cpus + + exit $retval +-- +2.35.1 + diff --git a/queue-5.19/selftests-cpu-hotplug-use-return-instead-of-exit.patch b/queue-5.19/selftests-cpu-hotplug-use-return-instead-of-exit.patch new file mode 100644 index 00000000000..3b69f393ca2 --- /dev/null +++ b/queue-5.19/selftests-cpu-hotplug-use-return-instead-of-exit.patch @@ -0,0 +1,77 @@ +From 76399f911221e984d4c4829293ab97c081b508ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Sep 2022 21:36:12 +0800 +Subject: selftests/cpu-hotplug: Use return instead of exit + +From: Zhao Gongyi + +[ Upstream commit 972cf4ce51ef5532d56822af17defb148aac0ccb ] + +Some cpus will be left in offline state when online +function exits in some error conditions. Use return +instead of exit to fix it. + +Signed-off-by: Zhao Gongyi +Signed-off-by: Shuah Khan +Stable-dep-of: 51d4c851465c ("selftests/cpu-hotplug: Reserve one cpu online at least") +Signed-off-by: Sasha Levin +--- + .../selftests/cpu-hotplug/cpu-on-off-test.sh | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +index 0d26b5e3f966..940b68c940bb 100755 +--- a/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh ++++ b/tools/testing/selftests/cpu-hotplug/cpu-on-off-test.sh +@@ -4,6 +4,7 @@ + SYSFS= + # Kselftest framework requirement - SKIP code is 4. + ksft_skip=4 ++retval=0 + + prerequisite() + { +@@ -102,10 +103,10 @@ online_cpu_expect_success() + + if ! online_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 +- exit 1 ++ retval=1 + elif ! cpu_is_online $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 +- exit 1 ++ retval=1 + fi + } + +@@ -128,10 +129,10 @@ offline_cpu_expect_success() + + if ! offline_cpu $cpu; then + echo $FUNCNAME $cpu: unexpected fail >&2 +- exit 1 ++ retval=1 + elif ! cpu_is_offline $cpu; then + echo $FUNCNAME $cpu: unexpected offline >&2 +- exit 1 ++ retval=1 + fi + } + +@@ -201,7 +202,7 @@ if [ $allcpus -eq 0 ]; then + offline_cpu_expect_success $present_max + online_cpu $present_max + fi +- exit 0 ++ exit $retval + else + echo "Full scope test: all hotplug cpus" + echo -e "\t online all offline cpus" +@@ -291,3 +292,5 @@ done + + echo 0 > $NOTIFIER_ERR_INJECT_DIR/actions/CPU_DOWN_PREPARE/error + /sbin/modprobe -q -r cpu-notifier-error-inject ++ ++exit $retval +-- +2.35.1 + diff --git a/queue-5.19/selftests-xsk-add-missing-close-on-netns-fd.patch b/queue-5.19/selftests-xsk-add-missing-close-on-netns-fd.patch new file mode 100644 index 00000000000..c77c6bfc057 --- /dev/null +++ b/queue-5.19/selftests-xsk-add-missing-close-on-netns-fd.patch @@ -0,0 +1,47 @@ +From cf8f594fbe0feea9c56e80262b0db568f1bdb206 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:39:05 +0200 +Subject: selftests/xsk: Add missing close() on netns fd + +From: Maciej Fijalkowski + +[ Upstream commit 8a7d61bdc2fac2c460a2f32a062f5c6dbd21a764 ] + +Commit 1034b03e54ac ("selftests: xsk: Simplify cleanup of ifobjects") +removed close on netns fd, which is not correct, so let us restore it. + +Fixes: 1034b03e54ac ("selftests: xsk: Simplify cleanup of ifobjects") +Signed-off-by: Maciej Fijalkowski +Signed-off-by: Daniel Borkmann +Acked-by: Magnus Karlsson +Link: https://lore.kernel.org/bpf/20220830133905.9945-1-maciej.fijalkowski@intel.com +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/bpf/xdpxceiver.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/testing/selftests/bpf/xdpxceiver.c b/tools/testing/selftests/bpf/xdpxceiver.c +index e5992a6b5e09..92e466310e27 100644 +--- a/tools/testing/selftests/bpf/xdpxceiver.c ++++ b/tools/testing/selftests/bpf/xdpxceiver.c +@@ -1589,6 +1589,8 @@ static struct ifobject *ifobject_create(void) + if (!ifobj->umem) + goto out_umem; + ++ ifobj->ns_fd = -1; ++ + return ifobj; + + out_umem: +@@ -1600,6 +1602,8 @@ static struct ifobject *ifobject_create(void) + + static void ifobject_delete(struct ifobject *ifobj) + { ++ if (ifobj->ns_fd != -1) ++ close(ifobj->ns_fd); + free(ifobj->umem); + free(ifobj->xsk_arr); + free(ifobj); +-- +2.35.1 + diff --git a/queue-5.19/selftests-xsk-avoid-use-after-free-on-ctx.patch b/queue-5.19/selftests-xsk-avoid-use-after-free-on-ctx.patch new file mode 100644 index 00000000000..41ab99c0a44 --- /dev/null +++ b/queue-5.19/selftests-xsk-avoid-use-after-free-on-ctx.patch @@ -0,0 +1,49 @@ +From 94e01bb64585a3b628e6f19e5e53397c4e0700d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 13:26:45 -0700 +Subject: selftests/xsk: Avoid use-after-free on ctx + +From: Ian Rogers + +[ Upstream commit af515a5587b8f45f19e11657746e0c89411b0380 ] + +The put lowers the reference count to 0 and frees ctx, reading it +afterwards is invalid. Move the put after the uses and determine the +last use by the reference count being 1. + +Fixes: 39e940d4abfa ("selftests/xsk: Destroy BPF resources only when ctx refcount drops to 0") +Signed-off-by: Ian Rogers +Signed-off-by: Daniel Borkmann +Acked-by: Magnus Karlsson +Link: https://lore.kernel.org/bpf/20220901202645.1463552-1-irogers@google.com +Signed-off-by: Sasha Levin +--- + tools/lib/bpf/xsk.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c +index 67dc010e9fe3..63954a2e213d 100644 +--- a/tools/lib/bpf/xsk.c ++++ b/tools/lib/bpf/xsk.c +@@ -1228,15 +1228,15 @@ void xsk_socket__delete(struct xsk_socket *xsk) + ctx = xsk->ctx; + umem = ctx->umem; + +- xsk_put_ctx(ctx, true); +- +- if (!ctx->refcount) { ++ if (ctx->refcount == 1) { + xsk_delete_bpf_maps(xsk); + close(ctx->prog_fd); + if (ctx->has_bpf_link) + close(ctx->link_fd); + } + ++ xsk_put_ctx(ctx, true); ++ + err = xsk_get_mmap_offsets(xsk->fd, &off); + if (!err) { + if (xsk->rx) { +-- +2.35.1 + diff --git a/queue-5.19/serial-8250-fix-restoring-termios-speed-after-suspen.patch b/queue-5.19/serial-8250-fix-restoring-termios-speed-after-suspen.patch new file mode 100644 index 00000000000..b447e8a4319 --- /dev/null +++ b/queue-5.19/serial-8250-fix-restoring-termios-speed-after-suspen.patch @@ -0,0 +1,54 @@ +From ec4e66ed4a9e3dcdd7589a034bf23b123768a223 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 12:43:24 +0200 +Subject: serial: 8250: Fix restoring termios speed after suspend +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Pali Rohár + +[ Upstream commit 379a33786d489ab81885ff0b3935cfeb36137fea ] + +Since commit edc6afc54968 ("tty: switch to ktermios and new framework") +termios speed is no longer stored only in c_cflag member but also in new +additional c_ispeed and c_ospeed members. If BOTHER flag is set in c_cflag +then termios speed is stored only in these new members. + +Since commit 027b57170bf8 ("serial: core: Fix initializing and restoring +termios speed") termios speed is available also in struct console. + +So properly restore also c_ispeed and c_ospeed members after suspend to fix +restoring termios speed which is not represented by Bnnn constant. + +Fixes: 4516d50aabed ("serial: 8250: Use canary to restart console after suspend") +Signed-off-by: Pali Rohár +Link: https://lore.kernel.org/r/20220924104324.4035-1-pali@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/8250/8250_port.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index d5f9b56fdbab..c66a029882e6 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -3325,8 +3325,13 @@ static void serial8250_console_restore(struct uart_8250_port *up) + unsigned int baud, quot, frac = 0; + + termios.c_cflag = port->cons->cflag; +- if (port->state->port.tty && termios.c_cflag == 0) ++ termios.c_ispeed = port->cons->ispeed; ++ termios.c_ospeed = port->cons->ospeed; ++ if (port->state->port.tty && termios.c_cflag == 0) { + termios.c_cflag = port->state->port.tty->termios.c_cflag; ++ termios.c_ispeed = port->state->port.tty->termios.c_ispeed; ++ termios.c_ospeed = port->state->port.tty->termios.c_ospeed; ++ } + + baud = serial8250_get_baud_rate(port, &termios, NULL); + quot = serial8250_get_divisor(port, baud, &frac); +-- +2.35.1 + diff --git a/queue-5.19/serial-8250-toggle-ier-bits-on-only-after-irq-has-be.patch b/queue-5.19/serial-8250-toggle-ier-bits-on-only-after-irq-has-be.patch new file mode 100644 index 00000000000..e4c46422be9 --- /dev/null +++ b/queue-5.19/serial-8250-toggle-ier-bits-on-only-after-irq-has-be.patch @@ -0,0 +1,143 @@ +From 9632d167ca6a8899cea09e3b749f32d4c4fefca3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 10:00:05 +0300 +Subject: serial: 8250: Toggle IER bits on only after irq has been set up +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +[ Upstream commit 039d4926379b1d1c17b51cf21c500a5eed86899e ] + +Invoking TIOCVHANGUP on 8250_mid port on Ice Lake-D and then reopening +the port triggers these faults during serial8250_do_startup(): + + DMAR: DRHD: handling fault status reg 3 + DMAR: [DMA Write NO_PASID] Request device [00:1a.0] fault addr 0x0 [fault reason 0x05] PTE Write access is not set + +If the IRQ hasn't been set up yet, the UART will have zeroes in its MSI +address/data registers. Disabling the IRQ at the interrupt controller +won't stop the UART from performing a DMA write to the address programmed +in its MSI address register (zero) when it wants to signal an interrupt. + +The UARTs (in Ice Lake-D) implement PCI 2.1 style MSI without masking +capability, so there is no way to mask the interrupt at the source PCI +function level, except disabling the MSI capability entirely, but that +would cause it to fall back to INTx# assertion, and the PCI specification +prohibits disabling the MSI capability as a way to mask a function's +interrupt service request. + +The MSI address register is zeroed by the hangup as the irq is freed. +The interrupt is signalled during serial8250_do_startup() performing a +THRE test that temporarily toggles THRI in IER. The THRE test currently +occurs before UART's irq (and MSI address) is properly set up. + +Refactor serial8250_do_startup() such that irq is set up before the +THRE test. The current irq setup code is intermixed with the timer +setup code. As THRE test must be performed prior to the timer setup, +extract it into own function and call it only after the THRE test. + +The ->setup_timer() needs to be part of the struct uart_8250_ops in +order to not create circular dependency between 8250 and 8250_base +modules. + +Fixes: 40b36daad0ac ("[PATCH] 8250 UART backup timer") +Reported-by: Lennert Buytenhek +Tested-by: Lennert Buytenhek +Reviewed-by: Andy Shevchenko +Signed-off-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20220922070005.2965-1-ilpo.jarvinen@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/8250/8250_core.c | 16 +++++++++++----- + drivers/tty/serial/8250/8250_port.c | 8 +++++--- + include/linux/serial_8250.h | 1 + + 3 files changed, 17 insertions(+), 8 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c +index 82726cda6066..f05544e93eae 100644 +--- a/drivers/tty/serial/8250/8250_core.c ++++ b/drivers/tty/serial/8250/8250_core.c +@@ -298,10 +298,9 @@ static void serial8250_backup_timeout(struct timer_list *t) + jiffies + uart_poll_timeout(&up->port) + HZ / 5); + } + +-static int univ8250_setup_irq(struct uart_8250_port *up) ++static void univ8250_setup_timer(struct uart_8250_port *up) + { + struct uart_port *port = &up->port; +- int retval = 0; + + /* + * The above check will only give an accurate result the first time +@@ -322,10 +321,16 @@ static int univ8250_setup_irq(struct uart_8250_port *up) + */ + if (!port->irq) + mod_timer(&up->timer, jiffies + uart_poll_timeout(port)); +- else +- retval = serial_link_irq_chain(up); ++} + +- return retval; ++static int univ8250_setup_irq(struct uart_8250_port *up) ++{ ++ struct uart_port *port = &up->port; ++ ++ if (port->irq) ++ return serial_link_irq_chain(up); ++ ++ return 0; + } + + static void univ8250_release_irq(struct uart_8250_port *up) +@@ -381,6 +386,7 @@ static struct uart_ops univ8250_port_ops; + static const struct uart_8250_ops univ8250_driver_ops = { + .setup_irq = univ8250_setup_irq, + .release_irq = univ8250_release_irq, ++ .setup_timer = univ8250_setup_timer, + }; + + static struct uart_8250_port serial8250_ports[UART_NR]; +diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c +index 5db53941d881..d5f9b56fdbab 100644 +--- a/drivers/tty/serial/8250/8250_port.c ++++ b/drivers/tty/serial/8250/8250_port.c +@@ -2303,6 +2303,10 @@ int serial8250_do_startup(struct uart_port *port) + if (port->irq && (up->port.flags & UPF_SHARE_IRQ)) + up->port.irqflags |= IRQF_SHARED; + ++ retval = up->ops->setup_irq(up); ++ if (retval) ++ goto out; ++ + if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) { + unsigned char iir1; + +@@ -2345,9 +2349,7 @@ int serial8250_do_startup(struct uart_port *port) + } + } + +- retval = up->ops->setup_irq(up); +- if (retval) +- goto out; ++ up->ops->setup_timer(up); + + /* + * Now, initialize the UART +diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h +index ff84a3ed10ea..b0183e90fe90 100644 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -74,6 +74,7 @@ struct uart_8250_port; + struct uart_8250_ops { + int (*setup_irq)(struct uart_8250_port *); + void (*release_irq)(struct uart_8250_port *); ++ void (*setup_timer)(struct uart_8250_port *); + }; + + struct uart_8250_em485 { +-- +2.35.1 + diff --git a/queue-5.19/series b/queue-5.19/series index 678b0fe7092..fc54c1850bb 100644 --- a/queue-5.19/series +++ b/queue-5.19/series @@ -174,3 +174,654 @@ drm-amd-display-fix-vblank-refcount-in-vrr-transition.patch drm-amd-display-explicitly-disable-psr_feature_enable-appropriately.patch smb3-must-initialize-two-acl-struct-fields-to-zero.patch selinux-use-grep-e-instead-of-egrep.patch +ima-fix-blocking-of-security.ima-xattrs-of-unsupport.patch +userfaultfd-open-userfaultfds-with-o_rdonly.patch +arm-dts-exynos-add-panel-and-backlight-to-p4note.patch +ntfs3-rework-xattr-handlers-and-switch-to-posix-acl-.patch +thermal-cpufreq_cooling-check-the-policy-first-in-cp.patch +cpufreq-amd-pstate-fix-initial-highest_perf-value.patch +sh-machvec-use-char-for-section-boundaries.patch +mips-sgi-ip30-fix-platform-device-leak-in-bridge_pla.patch +mips-sgi-ip27-fix-platform-device-leak-in-bridge_pla.patch +erofs-fix-order-max_order-warning-due-to-crafted-neg.patch +erofs-use-kill_anon_super-to-kill-super-in-fscache-m.patch +fscrypt-stop-using-keyrings-subsystem-for-fscrypt_ma.patch +arm-9243-1-riscpc-unbreak-the-build.patch +arm-9244-1-dump-fix-wrong-pg_level-in-walk_pmd.patch +arm-9247-1-mm-set-readonly-for-mt_memory_ro-with-arm.patch +acpi-pcc-release-resources-on-address-space-setup-fa.patch +acpi-pcc-replace-wait_for_completion.patch +acpi-pcc-fix-tx-acknowledge-in-the-pcc-address-space.patch +objtool-preserve-special-st_shndx-indexes-in-elf_upd.patch +nfsd-fix-a-memory-leak-in-an-error-handling-path.patch +sunrpc-fix-svcxdr_init_decode-s-end-of-buffer-calcul.patch +sunrpc-fix-svcxdr_init_encode-s-buflen-calculation.patch +nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch +nfsd-fix-handling-of-oversized-nfsv4-compound-reques.patch +x86-paravirt-add-extra-clobbers-with-zero_call_used_.patch +libbpf-initialize-err-in-probe_map_create.patch +wan-fix-syntax-errors-in-comments.patch +wifi-rtlwifi-8192de-correct-checking-of-iqk-reload.patch +wifi-ath10k-add-peer-map-clean-up-for-peer-delete-in.patch +bpf-fix-non-static-bpf_func_proto-struct-definitions.patch +bpf-convert-cgroup_bpf.progs-to-hlist.patch +bpf-cleanup-check_refcount_ok.patch +leds-lm3601x-don-t-use-mutex-after-it-was-destroyed.patch +tsnep-fix-tsnep_info_tx_time-register-define.patch +bpf-fix-reference-state-management-for-synchronous-c.patch +wifi-cfg80211-get-correct-ap-link-chandef.patch +wifi-mac80211-allow-bw-change-during-channel-switch-.patch +bpftool-fix-a-wrong-type-cast-in-btf_dumper_int.patch +audit-explicitly-check-audit_context-context-enum-va.patch +audit-free-audit_proctitle-only-on-task-exit.patch +esp-choose-the-correct-inner-protocol-for-gso-on-int.patch +spi-mt7621-fix-an-error-message-in-mt7621_spi_probe.patch +x86-resctrl-fix-to-restore-to-original-value-when-re.patch +xsk-fix-backpressure-mechanism-on-tx.patch +selftests-xsk-add-missing-close-on-netns-fd.patch +bpf-disable-preemption-when-increasing-per-cpu-map_l.patch +bpf-propagate-error-from-htab_lock_bucket-to-userspa.patch +wifi-ath11k-fix-incorrect-qmi-message-id-mappings.patch +bpf-use-this_cpu_-inc-dec-inc_return-for-bpf_task_st.patch +bpf-use-this_cpu_-inc_return-dec-for-prog-active.patch +bluetooth-btusb-mediatek-fix-wmt-failure-during-runt.patch +wifi-rtw89-pci-fix-interrupt-stuck-after-leaving-low.patch +wifi-rtw89-pci-correct-tx-resource-checking-in-low-p.patch +wifi-rtl8xxxu-tighten-bounds-checking-in-rtl8xxxu_re.patch +wifi-wfx-prevent-underflow-in-wfx_send_pds.patch +wifi-rtw88-add-missing-destroy_workqueue-on-error-pa.patch +selftests-xsk-avoid-use-after-free-on-ctx.patch +spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch +spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch-30157 +can-rx-offload-can_rx_offload_init_queue-fix-typo.patch +wifi-rtl8xxxu-fix-skb-misuse-in-tx-queue-selection.patch +spi-meson-spicc-do-not-rely-on-busy-flag-in-pow2-clk.patch +bpf-btf-fix-truncated-last_member_type_id-in-btf_str.patch +wifi-rtl8xxxu-gen2-fix-mistake-in-path-b-iq-calibrat.patch +wifi-rtl8xxxu-remove-copy-paste-leftover-in-gen2_upd.patch +wifi-mt76-mt7921e-fix-race-issue-between-reset-and-s.patch +wifi-mt76-mt7921s-fix-race-issue-between-reset-and-s.patch +wifi-mt76-mt7921u-fix-race-issue-between-reset-and-s.patch +wifi-mt76-sdio-fix-the-deadlock-caused-by-sdio-stat_.patch +wifi-mt76-sdio-poll-sta-stat-when-device-transmits-d.patch +wifi-mt76-sdio-fix-transmitting-packet-hangs.patch +wifi-mt76-mt7615-add-mt7615_mutex_acquire-release-in.patch +wifi-mt76-mt7915-fix-possible-unaligned-access-in-mt.patch +wifi-mt76-connac-fix-possible-unaligned-access-in-mt.patch +wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch +wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch-23501 +wifi-mt76-mt7915-fix-mcs-value-in-ht-mode.patch +wifi-mt76-mt7915-do-not-check-state-before-configuri.patch +wifi-mt76-mt7921e-fix-rmmod-crash-in-driver-reload-t.patch +bluetooth-rfcomm-fix-possible-deadlock-on-socket-shu.patch +net-fs_enet-fix-wrong-check-in-do_pd_setup.patch +bpf-ensure-correct-locking-around-vulnerable-functio.patch +libbpf-fix-crash-if-sec-freplace-programs-don-t-have.patch +wifi-ath11k-include-sta_keepalive_arp_response-tlv-h.patch +bluetooth-hci_-ldisc-serdev-check-percpu_init_rwsem-.patch +libbpf-fix-null-pointer-exception-in-api-btf_dump__d.patch +netfilter-conntrack-fix-the-gc-rescheduling-delay.patch +netfilter-conntrack-revisit-the-gc-initial-reschedul.patch +flow_dissector-do-not-count-vlan-tags-inside-tunnel-.patch +wifi-ath11k-fix-failed-to-find-the-peer-with-peer_id.patch +wifi-ath11k-fix-number-of-vht-beamformee-spatial-str.patch +mips-dts-ralink-mt7621-fix-external-phy-on-gb-pc2.patch +x86-microcode-amd-track-patch-allocation-size-explic.patch +wifi-ath11k-fix-peer-addition-deletion-error-on-sta-.patch +x86-cpu-include-the-header-of-init_ia32_feat_ctl-s-p.patch +spi-cadence-quadspi-fix-pm-disable-depth-imbalance-i.patch +spi-dw-fix-pm-disable-depth-imbalance-in-dw_spi_bt1_.patch +spi-omap100k-fix-pm-disable-depth-imbalance-in-omap1.patch +skmsg-schedule-psock-work-if-the-cached-skb-exists-o.patch +cw1200-fix-incorrect-check-to-determine-if-no-elemen.patch +i2c-mlxbf-support-lock-mechanism.patch +bluetooth-hci_core-fix-not-handling-link-timeouts-pr.patch +xfrm-reinject-transport-mode-packets-through-workque.patch +netfilter-nft_fib-fix-for-rpath-check-with-vrf-devic.patch +spi-s3c64xx-fix-large-transfers-with-dma.patch +wifi-rtl8xxxu-gen2-enable-40-mhz-channel-width.patch +wifi-rtl8xxxu-fix-aifs-written-to-reg_edca_-_param.patch +vhost-vsock-use-kvmalloc-kvfree-for-larger-packets.patch +eth-alx-take-rtnl_lock-on-resume.patch +misdn-fix-use-after-free-bugs-in-l1oip-timer-handler.patch +sctp-handle-the-error-returned-from-sctp_auth_asoc_i.patch +tcp-fix-tcp_cwnd_validate-to-not-forget-is_cwnd_limi.patch +spi-ensure-that-sg_table-won-t-be-used-after-being-f.patch +bluetooth-hci_sync-fix-not-indicating-power-state.patch +hwmon-pmbus-mp2888-fix-sensors-readouts-for-mps-mult.patch +net-rds-don-t-hold-sock-lock-when-cancelling-work-fr.patch +af_unix-use-debug_net_warn_on_once.patch +af_unix-fix-memory-leaks-of-the-whole-sk-due-to-oob-.patch +net-prestera-acl-add-check-for-kmemdup.patch +eth-lan743x-reject-extts-for-non-pci11x1x-devices.patch +bnx2x-fix-potential-memory-leak-in-bnx2x_tpa_stop.patch +eth-sp7021-fix-use-after-free-bug-in-spl2sw_nvmem_ge.patch +net-wwan-iosm-call-mutex_init-before-locking-it.patch +net-ieee802154-reject-zero-sized-raw_sendmsg.patch +once-add-do_once_slow-for-sleepable-contexts.patch +net-mvpp2-fix-mvpp2-debugfs-leak.patch +drm-bridge-adv7511-fix-cec-power-down-control-regist.patch +drm-bridge-adv7511-unregister-cec-i2c-device-after-c.patch +drm-bridge-avoid-uninitialized-variable-warning.patch +drm-mipi-dsi-detach-devices-when-removing-the-host.patch +drm-bridge-it6505-power-on-downstream-device-in-.ato.patch +drm-virtio-correct-drm_gem_shmem_get_sg_table-error-.patch +drm-bridge-tc358767-add-of_node_put-when-breaking-ou.patch +drm-bridge-parade-ps8640-fix-regulator-supply-order.patch +drm-dp_mst-fix-drm_dp_dpcd_read-return-value-checks.patch +drm-pl111-add-of_node_put-when-breaking-out-of-for_e.patch +asoc-mt6359-fix-tests-for-platform_get_irq-failure.patch +drm-msm-make-.remove-and-.shutdown-hw-shutdown-consi.patch +platform-chrome-fix-double-free-in-chromeos_laptop_p.patch +platform-chrome-fix-memory-corruption-in-ioctl.patch +drm-virtio-fix-same-context-optimization.patch +asoc-soc-pcm.c-call-__soc_pcm_close-in-soc_pcm_close.patch +asoc-tas2764-allow-mono-streams.patch +asoc-tas2764-drop-conflicting-set_bias_level-power-s.patch +asoc-tas2764-fix-mute-unmute.patch +platform-x86-msi-laptop-fix-old-ec-check-for-backlig.patch +platform-x86-msi-laptop-fix-resource-cleanup.patch +drm-vc4-txp-protect-device-resources.patch +platform-chrome-cros_ec_typec-correct-alt-mode-index.patch +drm-amdgpu-add-missing-pci_disable_device-in-amdgpu_.patch +drm-bridge-megachips-fix-a-null-pointer-dereference-.patch +drm-bridge-it6505-fix-the-order-of-dp_set_power-comm.patch +asoc-rsnd-add-check-for-rsnd_mod_power_on.patch +asoc-wm_adsp-handle-optional-legacy-support.patch +alsa-hda-beep-simplify-keep-power-at-enable-behavior.patch +drm-virtio-set-fb_modifiers_not_supported.patch +drm-bochs-fix-blanking.patch +asoc-sof-mediatek-mt8195-import-namespace-snd_soc_so.patch +drm-omap-dss-fix-refcount-leak-bugs.patch +drm-amdgpu-fix-memory-leak-in-hpd_rx_irq_create_work.patch +mmc-au1xmmc-fix-an-error-handling-path-in-au1xmmc_pr.patch +asoc-eureka-tlv320-hold-reference-returned-from-of_f.patch +drm-msm-lookup-the-icc-paths-in-both-mdp5-dpu-and-md.patch +drm-msm-dpu-index-dpu_kms-hw_vbif-using-vbif_idx.patch +drm-msm-dp-correct-1.62g-link-rate-at-dp_catalog_ctr.patch +alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch +alsa-usb-audio-properly-refcounting-clock-rate.patch +drm-vmwgfx-fix-memory-leak-in-vmw_mksstat_add_ioctl.patch +virtio-gpu-fix-shift-wrapping-bug-in-virtio_gpu_fenc.patch +asoc-codecs-tx-macro-fix-kcontrol-put.patch +asoc-da7219-fix-an-error-handling-path-in-da7219_reg.patch +alsa-dmaengine-increment-buffer-pointer-atomically.patch +mmc-wmt-sdmmc-fix-an-error-handling-path-in-wmt_mci_.patch +asoc-stm32-dfsdm-fix-pm-disable-depth-imbalance-in-s.patch +asoc-stm32-spdifrx-fix-pm-disable-depth-imbalance-in.patch +asoc-stm-fix-pm-disable-depth-imbalance-in-stm32_i2s.patch +asoc-wm8997-fix-pm-disable-depth-imbalance-in-wm8997.patch +asoc-wm5110-fix-pm-disable-depth-imbalance-in-wm5110.patch +asoc-wm5102-fix-pm-disable-depth-imbalance-in-wm5102.patch +asoc-mt6660-fix-pm-disable-depth-imbalance-in-mt6660.patch +alsa-hda-hdmi-don-t-skip-notification-handling-durin.patch +memory-pl353-smc-fix-refcount-leak-bug-in-pl353_smc_.patch +memory-of-fix-refcount-leak-bug-in-of_get_ddr_timing.patch +memory-of-fix-refcount-leak-bug-in-of_lpddr3_get_ddr.patch +locks-fix-toctou-race-when-granting-write-lease.patch +soc-qcom-smsm-fix-refcount-leak-bugs-in-qcom_smsm_pr.patch +soc-qcom-smem_state-add-refcounting-for-the-state-of.patch +arm-dts-imx6qdl-kontron-samx6i-hook-up-ddc-i2c-bus.patch +arm64-dts-renesas-r9a07g044-fix-sci-rx-tx-interrupt-.patch +arm64-dts-renesas-r9a07g054-fix-sci-rx-tx-interrupt-.patch +arm64-dts-renesas-r9a07g043-fix-sci-rx-tx-interrupt-.patch +dt-bindings-clock-exynosautov9-correct-clock-numberi.patch +arm64-dts-qcom-sc7280-cleanup-the-lpasscc-node.patch +arm64-dts-qcom-sc7280-update-lpasscore-node.patch +arm64-dts-qcom-pm8350c-drop-pwm-reg-declaration.patch +arm64-dts-qcom-sc7180-trogdor-keep-pm6150_adc-enable.patch +arm-dts-turris-omnia-fix-mpp26-pin-name-and-comment.patch +arm-dts-kirkwood-lsxl-fix-serial-line.patch +arm-dts-kirkwood-lsxl-remove-first-ethernet-port.patch +arm64-dts-qcom-sdm660-add-initial-inforce-ifc6560-bo.patch +arm64-dts-qcom-sc8280xp-add-reference-device.patch +arm64-dts-qcom-sc8280xp-pmics-remove-reg-entry-use-c.patch +ia64-export-memory_add_physaddr_to_nid-to-fix-cxl-bu.patch +arm64-dts-qcom-sm8350-sagami-correct-ts-pin-property.patch +soc-tegra-fuse-drop-kconfig-dependency-on-tegra20_ap.patch +arm64-dts-qcom-ipq8074-fix-pcie-phy-serdes-size.patch +arm64-dts-qcom-sm8450-fix-ufs-phy-serdes-size.patch +arm64-dts-ti-k3-j7200-fix-main-pinmux-range.patch +arm-dts-exynos-correct-s5k6a3-reset-polarity-on-mida.patch +arm-drop-cmdline_-dependency-on-atags.patch +ext4-don-t-run-ext4lazyinit-for-read-only-filesystem.patch +arm64-ftrace-fix-module-plts-with-mcount.patch +arm-dts-exynos-fix-polarity-of-vbus-gpio-of-origen.patch +iomap-iomap-fix-memory-corruption-when-recording-err.patch +selftests-cpu-hotplug-use-return-instead-of-exit.patch +selftests-cpu-hotplug-delete-fault-injection-related.patch +selftests-cpu-hotplug-reserve-one-cpu-online-at-leas.patch +iio-adc-at91-sama5d2_adc-fix-at91_sama5d2_mr_trackti.patch +iio-adc-at91-sama5d2_adc-check-return-status-for-pre.patch +iio-adc-at91-sama5d2_adc-lock-around-oversampling-an.patch +iio-adc-at91-sama5d2_adc-disable-prepare-buffer-on-s.patch +iio-inkern-only-release-the-device-node-when-done-wi.patch +iio-inkern-fix-return-value-in-devm_of_iio_channel_g.patch +iio-abi-fix-wrong-format-of-differential-capacitance.patch +iio-magnetometer-yas530-change-data-type-of-hard_off.patch +rdma-mlx5-don-t-compare-mkey-tags-in-devx-indirect-m.patch +usb-common-debug-check-non-standard-control-requests.patch +clk-meson-hold-reference-returned-by-of_get_parent.patch +clk-st-hold-reference-returned-by-of_get_parent.patch +clk-oxnas-hold-reference-returned-by-of_get_parent.patch +clk-qoriq-hold-reference-returned-by-of_get_parent.patch +clk-berlin-add-of_node_put-for-of_get_parent.patch +clk-sprd-hold-reference-returned-by-of_get_parent.patch +clk-tegra-fix-refcount-leak-in-tegra210_clock_init.patch +clk-tegra-fix-refcount-leak-in-tegra114_clock_init.patch +clk-tegra20-fix-refcount-leak-in-tegra20_clock_init.patch +clk-samsung-exynosautov9-correct-register-offsets-of.patch +sbitmap-fix-possible-io-hung-due-to-lost-wakeup.patch +remoteproc-imx_rproc-simplify-some-error-message.patch +remoteproc-imx_dsp_rproc-fix-argument-2-of-rproc_mem.patch +hid-uclogic-make-template-placeholder-ids-generic.patch +hid-uclogic-fix-warning-in-uclogic_rdesc_template_ap.patch +hsi-omap_ssi-fix-refcount-leak-in-ssi_probe.patch +hsi-omap_ssi_port-fix-dma_map_sg-error-check.patch +clk-qcom-gcc-sdm660-use-floor-ops-for-sdcc1-clock.patch +media-exynos4-is-fimc-is-add-of_node_put-when-breaki.patch +media-tm6000-fix-unused-value-in-vidioc_try_fmt_vid_.patch +tty-xilinx_uartps-fix-the-ignore_status.patch +media-amphion-insert-picture-startcode-after-seek-fo.patch +media-amphion-adjust-the-encoder-s-value-range-of-go.patch +media-amphion-don-t-change-the-colorspace-reported-b.patch +media-amphion-fix-a-bug-that-vpu-core-may-not-resume.patch +media-meson-vdec-add-missing-clk_disable_unprepare-o.patch +media-uvcvideo-fix-memory-leak-in-uvc_gpio_parse.patch +media-uvcvideo-use-entity-get_cur-in-uvc_ctrl_set.patch +media-xilinx-vipp-fix-refcount-leak-in-xvip_graph_dm.patch +rdma-rxe-fix-kernel-null-pointer-dereference-error.patch +rdma-rxe-fix-the-error-caused-by-qp-sk.patch +clk-mediatek-clk-mt8195-vdo0-set-rate-on-vdo0_dp_int.patch +clk-mediatek-clk-mt8195-vdo1-reparent-and-set-rate-o.patch +clk-mediatek-mt8195-infra_ao-set-pwrmcu-clocks-as-cr.patch +misc-ocxl-fix-possible-refcount-leak-in-afu_ioctl.patch +fpga-prevent-integer-overflow-in-dfl_feature_ioctl_s.patch +phy-rockchip-inno-usb2-return-zero-after-otg-sync.patch +dmaengine-idxd-avoid-deadlock-in-process_misc_interr.patch +dmaengine-hisilicon-disable-channels-when-unregister.patch +dmaengine-hisilicon-fix-cq-head-update.patch +dmaengine-hisilicon-add-multi-thread-support-for-a-d.patch +iio-directly-use-ida_alloc-free.patch +iio-use-per-device-lockdep-class-for-mlock.patch +usb-gadget-f_fs-stricter-integer-overflow-checks.patch +dyndbg-fix-static_branch-manipulation.patch +dyndbg-fix-module.dyndbg-handling.patch +dyndbg-let-query-modname-override-actual-module-name.patch +dyndbg-drop-exported-dynamic_debug_exec_queries.patch +sbitmap-fix-batched-wait_cnt-accounting.patch +revert-sbitmap-fix-batched-wait_cnt-accounting.patch +sbitmap-avoid-leaving-waitqueue-in-invalid-state-in-.patch +clk-qcom-sm6115-select-qcom_gdsc.patch +scsi-lpfc-fix-various-issues-reported-by-tools.patch +usb-serial-console-move-mutex_unlock-before-usb_seri.patch +mtd-devices-docg3-check-the-return-value-of-devm_ior.patch +remoteproc-harden-rproc_handle_vdev-against-integer-.patch +phy-qcom-qmp-create-copies-of-qmp-phy-driver.patch +phy-qcom-qmp-combo-disable-runtime-pm-on-unbind.patch +phy-qcom-qmp-usb-disable-runtime-pm-on-unbind.patch +phy-qcom-qmp-pcie-split-pcs_misc-region-for-ipq6018-.patch +phy-qcom-qmp-pcie-add-pcs_misc-sanity-check.patch +phy-qcom-qmp-pcie-fix-memleak-on-probe-deferral.patch +phy-qcom-qmp-pcie-msm8996-drop-all-compatibles-excep.patch +phy-qcom-qmp-pcie-change-symbol-prefix-to-qcom_qmp_p.patch +phy-qcom-qmp-pcie-msm8996-drop-support-for-non-pcie-.patch +phy-qcom-qmp-pcie-msm8996-cleanup-the-driver.patch +phy-qcom-qmp-pcie-msm8996-fix-memleak-on-probe-defer.patch +phy-qcom-qmp-combo-fix-memleak-on-probe-deferral.patch +phy-qcom-qmp-ufs-fix-memleak-on-probe-deferral.patch +phy-qcom-qmp-usb-drop-all-non-usb-compatibles-suppor.patch +phy-qcom-qmp-usb-change-symbol-prefix-to-qcom_qmp_ph.patch +phy-qcom-qmp-usb-drop-support-for-non-usb-phy-types.patch +phy-qcom-qmp-usb-cleanup-the-driver.patch +phy-qcom-qmp-usb-clean-up-pipe-clock-handling.patch +phy-qcom-qmp-usb-drop-pipe-clock-lane-suffix.patch +phy-qcom-qmp-usb-fix-memleak-on-probe-deferral.patch +phy-amlogic-phy-meson-axg-mipi-pcie-analog-hold-refe.patch +phy-phy-mtk-tphy-fix-the-phy-type-setting-issue.patch +mtd-rawnand-intel-read-the-chip-select-line-from-the.patch +mtd-rawnand-intel-remove-undocumented-compatible-str.patch +mtd-rawnand-intel-don-t-re-define-nand_data_iface_ch.patch +mtd-rawnand-fsl_elbc-fix-none-ecc-mode.patch +rdma-irdma-align-ae-id-codes-to-correct-flush-code-a.patch +rdma-irdma-validate-udata-inlen-and-outlen.patch +rdma-srp-fix-srp_abort.patch +rdma-siw-always-consume-all-skbuf-data-in-sk_data_re.patch +rdma-siw-fix-qp-destroy-to-wait-for-all-references-d.patch +ata-fix-ata_id_sense_reporting_enabled-and-ata_id_ha.patch +ata-fix-ata_id_has_devslp.patch +ata-fix-ata_id_has_ncq_autosense.patch +ata-fix-ata_id_has_dipm.patch +mtd-rawnand-meson-fix-bit-map-use-in-meson_nfc_ecc_c.patch +block-fix-the-enum-blk_eh_timer_return-documentation.patch +md-replace-snprintf-with-scnprintf.patch +md-raid5-ensure-stripe_fill-happens-on-non-read-io-w.patch +md-raid5-remove-unnecessary-bio_put-in-raid5_read_on.patch +rdma-cm-use-slid-in-the-work-completion-as-the-dlid-.patch +ib-set-iova-length-on-ib_mr-in-core-uverbs-layers.patch +rdma-srp-rework-the-srp_add_port-error-path.patch +rdma-srp-handle-dev_set_name-failure.patch +rdma-srp-use-the-attribute-group-mechanism-for-sysfs.patch +rdma-srp-support-more-than-255-rdma-ports.patch +xhci-don-t-show-warning-for-reinit-on-known-broken-s.patch +usb-gadget-function-fix-dangling-pnp_string-in-f_pri.patch +usb-dwc3-core-fix-some-leaks-in-probe.patch +drivers-serial-jsm-fix-some-leaks-in-probe.patch +serial-8250-toggle-ier-bits-on-only-after-irq-has-be.patch +tty-serial-fsl_lpuart-disable-dma-rx-tx-use-flags-in.patch +phy-qualcomm-call-clk_disable_unprepare-in-the-error.patch +staging-vt6655-fix-some-erroneous-memory-clean-up-lo.patch +slimbus-qcom-ngd-ctrl-allow-compile-testing-without-.patch +slimbus-qcom-ngd-add-error-handling-in-of_qcom_slim_.patch +firmware-google-test-spinlock-on-panic-path-to-avoid.patch +serial-8250-fix-restoring-termios-speed-after-suspen.patch +scsi-libsas-fix-use-after-free-bug-in-smp_execute_ta.patch +scsi-pm8001-fix-running_req-for-internal-abort-comma.patch +scsi-iscsi-rename-iscsi_conn_queue_work.patch +scsi-iscsi-add-recv-workqueue-helpers.patch +scsi-iscsi-run-recv-path-from-workqueue.patch +scsi-iscsi-iscsi_tcp-fix-null-ptr-deref-while-callin.patch +clk-qcom-clk-rcg2-add-rcg2-mux-ops.patch +clk-qcom-apss-ipq6018-fix-apcs_alias0_clk_src.patch +clk-qcom-apss-ipq6018-mark-apcs_alias0_core_clk-as-c.patch +clk-qcom-gcc-sm6115-override-default-alpha-pll-regs.patch +rdma-rxe-stop-lookup-of-partially-built-objects.patch +rdma-rxe-set-pd-early-in-mr-alloc-routines.patch +rdma-rxe-fix-resize_finish-in-rxe_queue.c.patch +ib-rdmavt-add-__init-__exit-annotations-to-module-in.patch +fsi-core-check-error-number-after-calling-ida_simple.patch +mfd-intel_soc_pmic-fix-an-error-handling-path-in-int.patch +mfd-fsl-imx25-fix-an-error-handling-path-in-mx25_tsa.patch +mfd-lp8788-fix-an-error-handling-path-in-lp8788_prob.patch +mfd-lp8788-fix-an-error-handling-path-in-lp8788_irq_.patch +mfd-fsl-imx25-fix-check-for-platform_get_irq-errors.patch +mfd-sm501-add-check-for-platform_driver_register.patch +mfd-da9061-fix-failed-to-set-two-wire-bus-mode.patch +clk-mediatek-mt8183-mfgcfg-propagate-rate-changes-to.patch +clk-mediatek-clk-mt8195-mfg-reparent-mfg_bg3d-and-pr.patch +clk-mediatek-fix-unregister-function-in-mtk_clk_regi.patch +clk-mediatek-migrate-remaining-clk_unregister_-to-cl.patch +phy-qcom-qmp-pcie-fix-resource-mapping-for-sdm845-qh.patch +fs-don-t-randomize-struct-kiocb-fields.patch +dmaengine-ioat-stop-mod_timer-from-resurrecting-dele.patch +usb-mtu3-fix-failed-runtime-suspend-in-host-only-mod.patch +spmi-pmic-arb-correct-duplicate-apid-to-ppid-mapping.patch +clk-vc5-fix-5p49v6901-outputs-disabling-when-enablin.patch +clk-baikal-t1-fix-invalid-xgmac-ptp-clock-divider.patch +clk-baikal-t1-add-shared-xgmac-ref-ptp-clocks-intern.patch +clk-baikal-t1-add-sata-internal-ref-clock-buffer.patch +clk-bcm2835-fix-bcm2835_clock_rate_from_divisor-decl.patch +clk-imx-scu-fix-memleak-on-platform_device_add-fails.patch +clk-ti-balance-of_node_get-calls-for-of_find_node_by.patch +clk-ti-dra7-atl-fix-reference-leak-in-of_dra7_atl_cl.patch +clk-ast2600-bclk-comes-from-epll.patch +mailbox-mpfs-fix-handling-of-the-reg-property.patch +mailbox-mpfs-account-for-mbox-offsets-while-sending.patch +mailbox-bcm-ferxrm-mailbox-fix-error-check-for-dma_m.patch +ipc-mqueue-fix-possible-memory-leak-in-init_mqueue_f.patch +kvm-x86-mmu-fix-memoryleak-in-kvm_mmu_vendor_module_.patch +powerpc-configs-properly-enable-papr_scm-in-pseries_.patch +powerpc-math_emu-efp-include-module.h.patch +powerpc-sysdev-fsl_msi-add-missing-of_node_put.patch +powerpc-pci_dn-add-missing-of_node_put.patch +powerpc-powernv-add-missing-of_node_put-in-opal_expo.patch +cpuidle-riscv-sbi-fix-cpu_pm_cpu_idle_enter_xyz-macr.patch +powerpc-fix-fallocate-and-fadvise64_64-compat-parame.patch +kvm-fix-memoryleak-in-kvm_init.patch +x86-hyperv-fix-struct-hv_enlightened_vmcs-definition.patch +kvm-x86-add-dedicated-helper-to-get-cpuid-entry-with.patch +kvm-x86-zero-out-entire-hyper-v-cpuid-cache-before-p.patch +kvm-x86-check-for-existing-hyper-v-vcpu-in-kvm_hv_vc.patch +kvm-x86-report-error-when-setting-cpuid-if-hyper-v-a.patch +kvm-nvmx-treat-general-detect-db-dr7.gd-1-as-fault-l.patch +kvm-nvmx-prioritize-tss-t-flag-dbs-over-monitor-trap.patch +kvm-nvmx-ignore-sipi-that-arrives-in-l2-when-vcpu-is.patch +kvm-vmx-inject-pf-on-encls-as-emulated-pf.patch +kvm-nvmx-unconditionally-clear-mtf_pending-on-nested.patch +kvm-ppc-book3s-hv-fix-decrementer-migration.patch +kvm-ppc-book3s-hv-p9-fix-irq-disabling-in-tick-accou.patch +kvm-ppc-book3s-hv-p9-clear-vcpu-cpu-fields-before-en.patch +kvm-ppc-book3s-hv-p9-restore-stolen-time-logging-in-.patch +powerpc-64s-fix-generic_cpu-build-flags-for-ppc970-g.patch +powerpc-64-mark-irqs-hard-disabled-in-boot-paca.patch +powerpc-64-interrupt-fix-return-to-masked-context-af.patch +powerpc-fix-spe-power-isa-properties-for-e500v1-plat.patch +powerpc-kprobes-fix-null-pointer-reference-in-arch_p.patch +powerpc-pseries-vas-pass-hw_cpu_id-to-node-associati.patch +crypto-sahara-don-t-sleep-when-in-softirq.patch +crypto-hisilicon-zip-fix-mismatch-in-get-set-sgl_sge.patch +hwrng-arm-smccc-trng-fix-no_entropy-handling.patch +crypto-ccp-fail-the-psp-initialization-when-writing-.patch +cgroup-honor-caller-s-cgroup-ns-when-resolving-path.patch +clk-generalize-devm_clk_get-a-bit.patch +clk-provide-new-devm_clk-helpers-for-prepared-and-en.patch +hwrng-imx-rngc-use-devm_clk_get_enabled.patch +hwrng-imx-rngc-moving-irq-handler-registering-after-.patch +crypto-qat-fix-default-value-of-wdt-timer.patch +crypto-hisilicon-qm-fix-missing-put-dfx-access.patch +cgroup-cpuset-enable-update_tasks_cpumask-on-top_cpu.patch +iommu-omap-fix-buffer-overflow-in-debugfs.patch +crypto-akcipher-default-implementation-for-setting-a.patch +crypto-ccp-release-dma-channels-before-dmaengine-unr.patch +crypto-inside-secure-change-swab-to-swab32.patch +crypto-qat-fix-dma-transfer-direction.patch +dt-bindings-timer-add-nomadik-mtu-binding.patch +clocksource-drivers-arm_arch_timer-fix-handling-of-a.patch +clocksource-drivers-timer-gxp-add-missing-error-hand.patch +cifs-return-correct-error-in-calc_signature.patch +iommu-iova-fix-module-config-properly.patch +tracing-kprobe-fix-kprobe-event-gen-test-module-on-e.patch +tracing-kprobe-make-gen-test-module-work-in-arm-and-.patch +tracing-osnoise-fix-possible-recursive-locking-in-st.patch +kbuild-remove-the-target-in-signal-traps-when-interr.patch +linux-export-use-inline-assembler-to-populate-symbol.patch +kbuild-rpm-pkg-fix-breakage-when-v-1-is-used.patch +crypto-marvell-octeontx-prevent-integer-overflows.patch +crypto-cavium-prevent-integer-overflow-loading-firmw.patch +random-schedule-jitter-credit-for-next-jiffy-not-in-.patch +thermal-drivers-qcom-tsens-v0_1-fix-msm8939-fourth-s.patch +acpi-apei-do-not-add-task_work-to-kernel-thread-to-a.patch +f2fs-fix-race-condition-on-setting-fi_no_extent-flag.patch +f2fs-fix-to-account-fs_cp_data_io-correctly.patch +tools-power-turbostat-separate-spr-from-icx.patch +tools-power-turbostat-use-standard-energy-unit-for-s.patch +selftest-tpm2-add-client.__del__-to-close-dev-tpm-ha.patch +module-tracking-keep-a-record-of-tainted-unloaded-mo.patch +fs-dlm-fix-race-in-lowcomms.patch +rcu-avoid-triggering-strict-gp-irq-work-when-rcu-is-.patch +rcu-back-off-upon-fill_page_cache_func-allocation-fa.patch +cpufreq-amd_pstate-fix-wrong-lowest-perf-fetch.patch +acpi-video-add-toshiba-satellite-portege-z830-quirk.patch +fortify-fix-__compiletime_strlen-under-ubsan_bounds_.patch +acpi-tables-fpdt-don-t-call-acpi_os_map_memory-on-in.patch +cpufreq-intel_pstate-add-tigerlake-support-in-no-hwp.patch +mips-bcm47xx-cast-memcmp-of-function-to-void.patch +powercap-intel_rapl-fix-ubsan-shift-out-of-bounds-is.patch +thermal-intel_powerclamp-use-get_cpu-instead-of-smp_.patch +arm-decompressor-include-.data.rel.ro.local.patch +acpi-x86-add-a-quirk-for-dell-inspiron-14-2-in-1-for.patch +x86-entry-work-around-clang-__bdos-bug.patch +nfsd-return-nfserr_serverfault-if-splice_ok-but-buf-.patch +nfsd-fix-use-after-free-on-source-server-when-doing-.patch +libbpf-do-not-require-executable-permission-for-shar.patch +wifi-rtw88-phy-fix-warning-of-possible-buffer-overfl.patch +wifi-ath10k-set-tx-credit-to-one-for-wcn3990-snoc-ba.patch +wifi-brcmfmac-fix-invalid-address-access-when-enabli.patch +bpftool-clear-errno-after-libcap-s-checks.patch +ice-set-tx_tstamps-when-creating-new-tx-rings-via-et.patch +net-ethernet-ti-davinci_mdio-add-workaround-for-erra.patch +openvswitch-fix-double-reporting-of-drops-in-dropwat.patch +openvswitch-fix-overreporting-of-drops-in-dropwatch.patch +tcp-annotate-data-race-around-tcp_md5sig_pool_popula.patch +micrel-ksz8851-fixes-struct-pointer-issue.patch +x86-mce-retrieve-poison-range-from-hardware.patch +wifi-ath9k-avoid-uninit-memory-read-in-ath9k_htc_rx_.patch +thunderbolt-add-back-intel-falcon-ridge-end-to-end-f.patch +x86-apic-don-t-disable-x2apic-if-locked.patch +net-axienet-switch-to-64-bit-rx-tx-statistics.patch +net-next-fix-ip_unicast_if-option-behavior-for-conne.patch +xfrm-update-ipcomp_scratches-with-null-when-freed.patch +wifi-ath11k-register-shutdown-handler-for-wcn6750.patch +rtw89-ser-leave-lps-with-mutex.patch +net-broadcom-fix-return-type-for-implementation-of.patch +net-xscale-fix-return-type-for-implementation-of-ndo.patch +net-sunplus-fix-return-type-for-implementation-of-nd.patch +net-lantiq_etop-fix-return-type-for-implementation-o.patch +netlink-bounds-check-struct-nlmsgerr-creation.patch +net-ftmac100-fix-endianness-related-issues-from-spar.patch +iavf-fix-race-between-iavf_close-and-iavf_reset_task.patch +wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_netdev.patch +net-sparx5-fix-function-return-type-to-match-actual-.patch +bluetooth-btintel-mark-intel-controller-to-support-l.patch +regulator-core-prevent-integer-underflow.patch +wifi-ath11k-mhi-fix-potential-memory-leak-in-ath11k_.patch +wifi-mt76-mt7921-reset-msta-airtime_ac-while-clearin.patch +wifi-rtw89-free-unused-skb-to-prevent-memory-leak.patch +wifi-rtw89-fix-rx-filter-after-scan.patch +bluetooth-l2cap-initialize-delayed-works-at-l2cap_ch.patch +net-ax88796c-fix-return-type-of-ax88796c_start_xmit.patch +net-davicom-fix-return-type-of-dm9000_start_xmit.patch +net-ethernet-ti-davinci_emac-fix-return-type-of-emac.patch +net-ethernet-litex-fix-return-type-of-liteeth_start_.patch +net-korina-fix-return-type-of-korina_send_packet.patch +net-wwan-iosm-fix-return-type-of-ipc_wwan_link_trans.patch +net-wwan-t7xx-fix-return-type-of-t7xx_ccmni_start_xm.patch +bluetooth-hci_sysfs-fix-attempting-to-call-device_ad.patch +wifi-ath10k-reset-pointer-after-memory-free-to-avoid.patch +bnxt_en-replace-reset-with-config-timestamps.patch +selftests-bpf-free-the-allocated-resources-after-tes.patch +can-bcm-check-the-result-of-can_send-in-bcm_can_tx.patch +wifi-rt2x00-don-t-run-rt5592-iq-calibration-on-mt762.patch +wifi-rt2x00-set-correct-tx_sw_cfg1-mac-register-for-.patch +wifi-rt2x00-set-vgc-gain-for-both-chains-of-mt7620.patch +wifi-rt2x00-set-soc-wmac-clock-register.patch +wifi-rt2x00-correctly-set-bbp-register-86-for-mt7620.patch +hwmon-sht4x-do-not-overflow-clamping-operation-on-32.patch +net-if-sock-is-dead-don-t-access-sock-s-sk_wq-in-sk_.patch +bpf-adjust-kprobe_multi-entry_ip-for-config_x86_kern.patch +bpf-use-bpf_prog_pack-for-bpf_dispatcher.patch +bluetooth-l2cap-fix-user-after-free.patch +net-sched-cls_u32-avoid-memcpy-false-positive-warnin.patch +libbpf-fix-overrun-in-netlink-attribute-iteration.patch +i2c-designware-pci-group-amd-navi-quirk-parts-togeth.patch +net-sparx5-fix-return-type-of-sparx5_port_xmit_impl.patch +net-lan966x-fix-return-type-of-lan966x_port_xmit.patch +r8152-rate-limit-overflow-messages.patch +drm-nouveau-nouveau_bo-fix-potential-memory-leak-in-.patch +drm-use-size_t-type-for-len-variable-in-drm_copy_fie.patch +drm-prevent-drm_copy_field-to-attempt-copying-a-null.patch +drm-komeda-fix-handling-of-atomic-commits-in-the-ato.patch +gpu-lontium-lt9611-fix-null-pointer-dereference-in-l.patch +drm-amd-display-fix-overflow-on-min_i64-definition.patch +alsa-usb-audio-add-quirk-to-enable-avid-mbox-3-suppo.patch +udmabuf-set-ubuf-sg-null-if-the-creation-of-sg-table.patch +platform-x86-pmc_atom-improve-quirk-message-to-be-le.patch +drm-bridge-dw_hdmi-only-trigger-hotplug-event-on-lin.patch +drm-amdgpu-skip-the-program-of-mmmc_vm_agp_-in-sriov.patch +drm-admgpu-skip-cg-pg-on-soc21-under-sriov-vf.patch +alsa-usb-audio-register-card-at-the-last-interface.patch +drm-vc4-vec-fix-timings-for-vec-modes.patch +drm-panel-orientation-quirks-add-quirk-for-anbernic-.patch +drm-panel-orientation-quirks-add-quirk-for-aya-neo-a.patch +platform-chrome-cros_ec-notify-the-pm-of-wake-events.patch +platform-x86-hp-wmi-setting-thermal-profile-fails-wi.patch +platform-x86-msi-laptop-change-dmi-match-alias-strin.patch +alsa-intel-dspconfig-add-es8336-support-for-alderlak.patch +asoc-sof-pci-change-dmi-match-info-to-support-all-ch.patch +asoc-sof-add-quirk-to-override-topology-mclk_id.patch +drm-amdgpu-sdma-update-use-unlocked-iterator.patch +drm-amd-display-correct-hostvm-flag.patch +drm-amdgpu-fix-initial-connector-audio-value.patch +drm-meson-reorder-driver-deinit-sequence-to-fix-use-.patch +drm-meson-explicitly-remove-aggregate-driver-at-modu.patch +drm-meson-remove-drm-bridges-at-aggregate-driver-unb.patch +drm-exynos-fix-return-type-for-mixer_mode_valid-and-.patch +drm-dp-don-t-rewrite-link-config-when-setting-phy-te.patch +drm-amd-display-remove-interface-for-periodic-interr.patch +drm-amd-display-polling-vid-stream-status-in-hpo-dp-.patch +drm-amd-display-fix-array-bounds-error-in-dc_stream_.patch +drm-amdkfd-fix-ubsan-shift-out-of-bounds-warning.patch +arm64-dts-qcom-sdm845-narrow-llcc-address-space.patch +arm-dts-imx6-delete-interrupts-property-if-interrupt.patch +arm-dts-imx7d-sdb-config-the-max-pressure-for-tsc204.patch +arm64-dts-qcom-sc7280-idp-correct-adc-channel-node-n.patch +arm-dts-imx6q-add-missing-properties-for-sram.patch +arm-dts-imx6dl-add-missing-properties-for-sram.patch +arm-dts-imx6qp-add-missing-properties-for-sram.patch +arm-dts-imx6sl-add-missing-properties-for-sram.patch +arm-dts-imx6sll-add-missing-properties-for-sram.patch +arm-dts-imx6sx-add-missing-properties-for-sram.patch +arm-dts-imx6sl-use-tabs-for-code-indent.patch +arm-dts-imx6sx-udoo-neo-don-t-use-multiple-blank-lin.patch +kselftest-arm64-fix-validatation-termination-record-.patch +sparc-fix-the-generic-io-helpers.patch +arm64-run-softirqs-on-the-per-cpu-irq-stack.patch +arm64-dts-imx8mm-kontron-use-the-vselect-signal-to-s.patch +arm64-dts-imx8ulp-no-executable-source-file-permissi.patch +arm64-dts-imx8mq-librem5-add-bq25895-as-max17055-s-p.patch +arm-orion-fix-include-path.patch +btrfs-dump-extra-info-if-one-free-space-cache-has-mo.patch +btrfs-add-macros-for-annotating-wait-events-with-loc.patch +btrfs-change-the-lockdep-class-of-free-space-inode-s.patch +btrfs-scrub-properly-report-super-block-errors-in-sy.patch +btrfs-scrub-try-to-fix-super-block-errors.patch +btrfs-don-t-print-information-about-space-cache-or-t.patch +btrfs-call-__btrfs_remove_free_space_cache_locked-on.patch +btrfs-check-superblock-to-ensure-the-fs-was-not-modi.patch +btrfs-add-kcsan-annotations-for-unlocked-access-to-b.patch +btrfs-separate-out-the-eb-and-extent-state-leak-help.patch +arm64-dts-uniphier-add-usb-device-support-for-pxs3-r.patch +arm-9233-1-stacktrace-skip-frame-pointer-boundary-ch.patch +arm-9234-1-stacktrace-avoid-duplicate-saving-of-exce.patch +arm-9242-1-kasan-only-map-modules-if-config_kasan_vm.patch +clk-zynqmp-fix-stack-out-of-bounds-in-strncpy.patch +media-cx88-fix-a-null-ptr-deref-bug-in-buffer_prepar.patch +media-platform-fix-some-double-free-in-meson-ge2d-an.patch +clk-zynqmp-pll-rectify-rate-rounding-in-zynqmp_pll_r.patch +rdma-rxe-delete-error-messages-triggered-by-incoming.patch +usb-host-xhci-plat-suspend-and-resume-clocks.patch +usb-host-xhci-plat-suspend-resume-clks-for-brcm.patch +scsi-lpfc-fix-null-ndlp-ptr-dereference-in-abnormal-.patch +dmaengine-ti-k3-udma-reset-udma_chan_rt-byte-counter.patch +scsi-3w-9xxx-avoid-disabling-device-if-failing-to-en.patch +nbd-fix-hung-when-signal-interrupts-nbd_start_device.patch +iommu-arm-smmu-v3-make-default-domain-type-of-hisili.patch +usb-gadget-uvc-increase-worker-prio-to-wq_highpri.patch +power-supply-adp5061-fix-out-of-bounds-read-in-adp50.patch +staging-vt6655-fix-potential-memory-leak.patch +blk-throttle-prevent-overflow-while-calculating-wait.patch +ata-libahci_platform-sanity-check-the-dt-child-nodes.patch +habanalabs-ignore-eeprom-errors-during-boot.patch +bcache-fix-set_at_max_writeback_rate-for-multiple-at.patch +soundwire-cadence-don-t-overwrite-msg-buf-during-wri.patch +soundwire-intel-fix-error-handling-on-dai-registrati.patch +hid-topre-add-driver-fixing-report-descriptor.patch +habanalabs-remove-some-f-w-descriptor-validations.patch +hid-roccat-fix-use-after-free-in-roccat_read.patch +hsi-ssi_protocol-fix-potential-resource-leak-in-ssip.patch +hid-nintendo-check-analog-user-calibration-for-plaus.patch +eventfd-guard-wake_up-in-eventfd-fs-calls-as-well.patch +md-raid5-wait-for-md_sb_change_pending-in-raid5d.patch +usb-host-xhci-fix-potential-memory-leak-in-xhci_allo.patch +usb-musb-fix-musb_gadget.c-rxstate-overflow-bug.patch +usb-dwc3-core-add-gfladj_refclk_lpm_sel-quirk.patch +arm64-dts-imx8mp-add-snps-gfladj-refclk-lpm-sel-quir.patch +usb-dwc3-core-enable-guctl1-bit-10-for-fixing-termin.patch +revert-usb-storage-add-quirk-for-samsung-fit-flash.patch +staging-rtl8723bs-fix-potential-memory-leak-in-rtw_i.patch +staging-rtl8723bs-fix-a-potential-memory-leak-in-rtw.patch +scsi-tracing-fix-compile-error-in-trace_array-calls-.patch +ext2-use-kvmalloc-for-group-descriptor-array.patch +nvme-handle-effects-after-freeing-the-request.patch +nvme-copy-firmware_rev-on-each-init.patch +nvmet-tcp-add-bounds-check-on-transfer-tag.patch +usb-idmouse-fix-an-uninit-value-in-idmouse_open.patch +block-replace-blk_queue_nowait-with-bdev_nowait.patch +blk-mq-use-quiesced-elevator-switch-when-reinitializ.patch +nvmet-don-t-look-at-the-request_queue-in-nvmet_bdev_.patch +hwmon-occ-retry-for-checksum-failure.patch +fsi-occ-prevent-use-after-free.patch +fsi-master-ast-cf-fix-missing-of_node_put-in-fsi_mas.patch +usb-typec-ucsi-don-t-warn-on-probe-deferral.patch +clk-bcm2835-make-peripheral-pllc-critical.patch +clk-bcm2835-round-uart-input-clock-up.patch diff --git a/queue-5.19/sh-machvec-use-char-for-section-boundaries.patch b/queue-5.19/sh-machvec-use-char-for-section-boundaries.patch new file mode 100644 index 00000000000..499dd54f464 --- /dev/null +++ b/queue-5.19/sh-machvec-use-char-for-section-boundaries.patch @@ -0,0 +1,82 @@ +From 67033131c943932bd9a965e0b214acef6f32cad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 16:40:44 -0700 +Subject: sh: machvec: Use char[] for section boundaries + +From: Kees Cook + +[ Upstream commit c5783af354688b24abd359f7086c282ec74de993 ] + +As done for other sections, define the extern as a character array, +which relaxes many of the compiler-time object size checks, which would +otherwise assume it's a single long. Solves the following build error: + +arch/sh/kernel/machvec.c: error: array subscript 'struct sh_machine_vector[0]' is partly outside array bounds of 'long int[1]' [-Werror=array-bounds]: => 105:33 + +Cc: Yoshinori Sato +Cc: Rich Felker +Cc: linux-sh@vger.kernel.org +Reported-by: Geert Uytterhoeven +Link: https://lore.kernel.org/lkml/alpine.DEB.2.22.394.2209050944290.964530@ramsan.of.borg/ +Fixes: 9655ad03af2d ("sh: Fixup machvec support.") +Reviewed-by: Geert Uytterhoeven +Reviewed-by: Gustavo A. R. Silva +Acked-by: Rich Felker +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + arch/sh/include/asm/sections.h | 2 +- + arch/sh/kernel/machvec.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h +index 8edb824049b9..0cb0ca149ac3 100644 +--- a/arch/sh/include/asm/sections.h ++++ b/arch/sh/include/asm/sections.h +@@ -4,7 +4,7 @@ + + #include + +-extern long __machvec_start, __machvec_end; ++extern char __machvec_start[], __machvec_end[]; + extern char __uncached_start, __uncached_end; + extern char __start_eh_frame[], __stop_eh_frame[]; + +diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c +index d606679a211e..57efaf5b82ae 100644 +--- a/arch/sh/kernel/machvec.c ++++ b/arch/sh/kernel/machvec.c +@@ -20,8 +20,8 @@ + #define MV_NAME_SIZE 32 + + #define for_each_mv(mv) \ +- for ((mv) = (struct sh_machine_vector *)&__machvec_start; \ +- (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \ ++ for ((mv) = (struct sh_machine_vector *)__machvec_start; \ ++ (mv) && (unsigned long)(mv) < (unsigned long)__machvec_end; \ + (mv)++) + + static struct sh_machine_vector * __init get_mv_byname(const char *name) +@@ -87,8 +87,8 @@ void __init sh_mv_setup(void) + if (!machvec_selected) { + unsigned long machvec_size; + +- machvec_size = ((unsigned long)&__machvec_end - +- (unsigned long)&__machvec_start); ++ machvec_size = ((unsigned long)__machvec_end - ++ (unsigned long)__machvec_start); + + /* + * Sanity check for machvec section alignment. Ensure +@@ -102,7 +102,7 @@ void __init sh_mv_setup(void) + * vector (usually the only one) from .machvec.init. + */ + if (machvec_size >= sizeof(struct sh_machine_vector)) +- sh_mv = *(struct sh_machine_vector *)&__machvec_start; ++ sh_mv = *(struct sh_machine_vector *)__machvec_start; + } + + pr_notice("Booting machvec: %s\n", get_system_type()); +-- +2.35.1 + diff --git a/queue-5.19/skmsg-schedule-psock-work-if-the-cached-skb-exists-o.patch b/queue-5.19/skmsg-schedule-psock-work-if-the-cached-skb-exists-o.patch new file mode 100644 index 00000000000..9f82eb293d9 --- /dev/null +++ b/queue-5.19/skmsg-schedule-psock-work-if-the-cached-skb-exists-o.patch @@ -0,0 +1,65 @@ +From 62d2dd4a3fd26be1ed9404f9a3617d1b490ce52e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 15:13:11 +0800 +Subject: skmsg: Schedule psock work if the cached skb exists on the psock + +From: Liu Jian + +[ Upstream commit bec217197b412d74168c6a42fc0f76d0cc9cad00 ] + +In sk_psock_backlog function, for ingress direction skb, if no new data +packet arrives after the skb is cached, the cached skb does not have a +chance to be added to the receive queue of psock. As a result, the cached +skb cannot be received by the upper-layer application. Fix this by reschedule +the psock work to dispose the cached skb in sk_msg_recvmsg function. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Liu Jian +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Link: https://lore.kernel.org/bpf/20220907071311.60534-1-liujian56@huawei.com +Signed-off-by: Sasha Levin +--- + net/core/skmsg.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 69ac686c7cae..864cd7ded2ca 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -435,8 +435,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + if (copied + copy > len) + copy = len - copied; + copy = copy_page_to_iter(page, sge->offset, copy, iter); +- if (!copy) +- return copied ? copied : -EFAULT; ++ if (!copy) { ++ copied = copied ? copied : -EFAULT; ++ goto out; ++ } + + copied += copy; + if (likely(!peek)) { +@@ -456,7 +458,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + * didn't copy the entire length lets just break. + */ + if (copy != sge->length) +- return copied; ++ goto out; + sk_msg_iter_var_next(i); + } + +@@ -478,7 +480,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + } + msg_rx = sk_psock_peek_msg(psock); + } +- ++out: ++ if (psock->work_state.skb && copied > 0) ++ schedule_work(&psock->work); + return copied; + } + EXPORT_SYMBOL_GPL(sk_msg_recvmsg); +-- +2.35.1 + diff --git a/queue-5.19/slimbus-qcom-ngd-add-error-handling-in-of_qcom_slim_.patch b/queue-5.19/slimbus-qcom-ngd-add-error-handling-in-of_qcom_slim_.patch new file mode 100644 index 00000000000..583701234c7 --- /dev/null +++ b/queue-5.19/slimbus-qcom-ngd-add-error-handling-in-of_qcom_slim_.patch @@ -0,0 +1,45 @@ +From 26f6d8e759bfd68e92104eb2265d36d08013bbe4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 14 Sep 2022 11:19:53 +0800 +Subject: slimbus: qcom-ngd: Add error handling in of_qcom_slim_ngd_register + +From: Lin Yujun + +[ Upstream commit 42992cf187e4e4bcfe3c58f8fc7b1832c5652d9f ] + +No error handling is performed when platform_device_add() +return fails. Refer to the error handling of driver_set_override(), +add error handling for platform_device_add(). + +Fixes: 917809e2280b ("slimbus: ngd: Add qcom SLIMBus NGD driver") +Reviewed-by: Neil Armstrong +Signed-off-by: Lin Yujun +Link: https://lore.kernel.org/r/20220914031953.94061-1-linyujun809@huawei.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/slimbus/qcom-ngd-ctrl.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c +index bacc6af1d51e..d29a1a9cf12f 100644 +--- a/drivers/slimbus/qcom-ngd-ctrl.c ++++ b/drivers/slimbus/qcom-ngd-ctrl.c +@@ -1470,7 +1470,13 @@ static int of_qcom_slim_ngd_register(struct device *parent, + ngd->pdev->dev.of_node = node; + ctrl->ngd = ngd; + +- platform_device_add(ngd->pdev); ++ ret = platform_device_add(ngd->pdev); ++ if (ret) { ++ platform_device_put(ngd->pdev); ++ kfree(ngd); ++ of_node_put(node); ++ return ret; ++ } + ngd->base = ctrl->base + ngd->id * data->offset + + (ngd->id - 1) * data->size; + +-- +2.35.1 + diff --git a/queue-5.19/slimbus-qcom-ngd-ctrl-allow-compile-testing-without-.patch b/queue-5.19/slimbus-qcom-ngd-ctrl-allow-compile-testing-without-.patch new file mode 100644 index 00000000000..498d2cc97a6 --- /dev/null +++ b/queue-5.19/slimbus-qcom-ngd-ctrl-allow-compile-testing-without-.patch @@ -0,0 +1,40 @@ +From 44e22e1e91e4baa22061d3e8ed8b49c1693fa8ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 13:29:10 +0100 +Subject: slimbus: qcom-ngd-ctrl: allow compile testing without + QCOM_RPROC_COMMON + +From: Krzysztof Kozlowski + +[ Upstream commit e291691c69776ad278cd39dec2306dd39d681a9f ] + +The Qualcomm common remote-proc code (CONFIG_QCOM_RPROC_COMMON) has +necessary stubs, so it is not needed for compile testing. + +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: Srinivas Kandagatla +Link: https://lore.kernel.org/r/20220916122910.170730-5-srinivas.kandagatla@linaro.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 42992cf187e4 ("slimbus: qcom-ngd: Add error handling in of_qcom_slim_ngd_register") +Signed-off-by: Sasha Levin +--- + drivers/slimbus/Kconfig | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/slimbus/Kconfig b/drivers/slimbus/Kconfig +index 1235b7dc8496..2ed821f75816 100644 +--- a/drivers/slimbus/Kconfig ++++ b/drivers/slimbus/Kconfig +@@ -22,7 +22,8 @@ config SLIM_QCOM_CTRL + + config SLIM_QCOM_NGD_CTRL + tristate "Qualcomm SLIMbus Satellite Non-Generic Device Component" +- depends on HAS_IOMEM && DMA_ENGINE && NET && QCOM_RPROC_COMMON ++ depends on HAS_IOMEM && DMA_ENGINE && NET ++ depends on QCOM_RPROC_COMMON || COMPILE_TEST + depends on ARCH_QCOM || COMPILE_TEST + select QCOM_QMI_HELPERS + select QCOM_PDR_HELPERS +-- +2.35.1 + diff --git a/queue-5.19/soc-qcom-smem_state-add-refcounting-for-the-state-of.patch b/queue-5.19/soc-qcom-smem_state-add-refcounting-for-the-state-of.patch new file mode 100644 index 00000000000..3fd5316ce87 --- /dev/null +++ b/queue-5.19/soc-qcom-smem_state-add-refcounting-for-the-state-of.patch @@ -0,0 +1,46 @@ +From bf6cbceee3db6f7bfc9086ff6f42763989699953 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 21:52:17 +0800 +Subject: soc: qcom: smem_state: Add refcounting for the 'state->of_node' + +From: Liang He + +[ Upstream commit 90681f53b9381c23ff7762a3b13826d620c272de ] + +In qcom_smem_state_register() and qcom_smem_state_release(), we +should better use of_node_get() and of_node_put() for the reference +creation and destruction of 'device_node'. + +Fixes: 9460ae2ff308 ("soc: qcom: Introduce common SMEM state machine code") +Signed-off-by: Liang He +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220721135217.1301039-2-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/smem_state.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c +index 31faf4aa868e..e848cc9a3cf8 100644 +--- a/drivers/soc/qcom/smem_state.c ++++ b/drivers/soc/qcom/smem_state.c +@@ -136,6 +136,7 @@ static void qcom_smem_state_release(struct kref *ref) + struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount); + + list_del(&state->list); ++ of_node_put(state->of_node); + kfree(state); + } + +@@ -205,7 +206,7 @@ struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node, + + kref_init(&state->refcount); + +- state->of_node = of_node; ++ state->of_node = of_node_get(of_node); + state->ops = *ops; + state->priv = priv; + +-- +2.35.1 + diff --git a/queue-5.19/soc-qcom-smsm-fix-refcount-leak-bugs-in-qcom_smsm_pr.patch b/queue-5.19/soc-qcom-smsm-fix-refcount-leak-bugs-in-qcom_smsm_pr.patch new file mode 100644 index 00000000000..6e290b91df0 --- /dev/null +++ b/queue-5.19/soc-qcom-smsm-fix-refcount-leak-bugs-in-qcom_smsm_pr.patch @@ -0,0 +1,107 @@ +From 20f217aac88ff1a31ea6736f9867f44a0b1b2ba1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 21:52:16 +0800 +Subject: soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe() + +From: Liang He + +[ Upstream commit af8f6f39b8afd772fda4f8e61823ef8c021bf382 ] + +There are two refcount leak bugs in qcom_smsm_probe(): + +(1) The 'local_node' is escaped out from for_each_child_of_node() as +the break of iteration, we should call of_node_put() for it in error +path or when it is not used anymore. +(2) The 'node' is escaped out from for_each_available_child_of_node() +as the 'goto', we should call of_node_put() for it in goto target. + +Fixes: c97c4090ff72 ("soc: qcom: smsm: Add driver for Qualcomm SMSM") +Signed-off-by: Liang He +Signed-off-by: Bjorn Andersson +Link: https://lore.kernel.org/r/20220721135217.1301039-1-windhl@126.com +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/smsm.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c +index 9df9bba242f3..3e8994d6110e 100644 +--- a/drivers/soc/qcom/smsm.c ++++ b/drivers/soc/qcom/smsm.c +@@ -526,7 +526,7 @@ static int qcom_smsm_probe(struct platform_device *pdev) + for (id = 0; id < smsm->num_hosts; id++) { + ret = smsm_parse_ipc(smsm, id); + if (ret < 0) +- return ret; ++ goto out_put; + } + + /* Acquire the main SMSM state vector */ +@@ -534,13 +534,14 @@ static int qcom_smsm_probe(struct platform_device *pdev) + smsm->num_entries * sizeof(u32)); + if (ret < 0 && ret != -EEXIST) { + dev_err(&pdev->dev, "unable to allocate shared state entry\n"); +- return ret; ++ goto out_put; + } + + states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL); + if (IS_ERR(states)) { + dev_err(&pdev->dev, "Unable to acquire shared state entry\n"); +- return PTR_ERR(states); ++ ret = PTR_ERR(states); ++ goto out_put; + } + + /* Acquire the list of interrupt mask vectors */ +@@ -548,13 +549,14 @@ static int qcom_smsm_probe(struct platform_device *pdev) + ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size); + if (ret < 0 && ret != -EEXIST) { + dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n"); +- return ret; ++ goto out_put; + } + + intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL); + if (IS_ERR(intr_mask)) { + dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n"); +- return PTR_ERR(intr_mask); ++ ret = PTR_ERR(intr_mask); ++ goto out_put; + } + + /* Setup the reference to the local state bits */ +@@ -565,7 +567,8 @@ static int qcom_smsm_probe(struct platform_device *pdev) + smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm); + if (IS_ERR(smsm->state)) { + dev_err(smsm->dev, "failed to register qcom_smem_state\n"); +- return PTR_ERR(smsm->state); ++ ret = PTR_ERR(smsm->state); ++ goto out_put; + } + + /* Register handlers for remote processor entries of interest. */ +@@ -595,16 +598,19 @@ static int qcom_smsm_probe(struct platform_device *pdev) + } + + platform_set_drvdata(pdev, smsm); ++ of_node_put(local_node); + + return 0; + + unwind_interfaces: ++ of_node_put(node); + for (id = 0; id < smsm->num_entries; id++) + if (smsm->entries[id].domain) + irq_domain_remove(smsm->entries[id].domain); + + qcom_smem_state_unregister(smsm->state); +- ++out_put: ++ of_node_put(local_node); + return ret; + } + +-- +2.35.1 + diff --git a/queue-5.19/soc-tegra-fuse-drop-kconfig-dependency-on-tegra20_ap.patch b/queue-5.19/soc-tegra-fuse-drop-kconfig-dependency-on-tegra20_ap.patch new file mode 100644 index 00000000000..3e8c799fcb7 --- /dev/null +++ b/queue-5.19/soc-tegra-fuse-drop-kconfig-dependency-on-tegra20_ap.patch @@ -0,0 +1,45 @@ +From 2668eda93c7ad03315e5c66a15e3df20dd5a3379 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 23 Sep 2020 03:34:21 +0300 +Subject: soc/tegra: fuse: Drop Kconfig dependency on TEGRA20_APB_DMA + +From: Dmitry Osipenko + +[ Upstream commit 2254182807fc09ba9dec9a42ef239e373796f1b2 ] + +The DMA subsystem could be entirely disabled in Kconfig and then the +TEGRA20_APB_DMA option isn't available too. Hence kernel configuration +fails if DMADEVICES Kconfig option is disabled due to the unsatisfiable +dependency. + +The FUSE driver isn't a critical driver and currently it only provides +NVMEM interface to userspace which isn't known to be widely used, and +thus, it's fine if FUSE driver fails to load. + +Let's remove the erroneous Kconfig dependency and let the FUSE driver to +fail the probing if DMA is unavailable. + +Fixes: 19d41e5e9c68 ("soc/tegra: fuse: Add APB DMA dependency for Tegra20") +Reported-by: Necip Fazil Yildiran +Link: https://bugzilla.kernel.org/show_bug.cgi?id=209301 +Signed-off-by: Dmitry Osipenko +Signed-off-by: Sasha Levin +--- + drivers/soc/tegra/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig +index 5725c8ef0406..6f601227da3c 100644 +--- a/drivers/soc/tegra/Kconfig ++++ b/drivers/soc/tegra/Kconfig +@@ -136,7 +136,6 @@ config SOC_TEGRA_FUSE + def_bool y + depends on ARCH_TEGRA + select SOC_BUS +- select TEGRA20_APB_DMA if ARCH_TEGRA_2x_SOC + + config SOC_TEGRA_FLOWCTRL + bool +-- +2.35.1 + diff --git a/queue-5.19/soundwire-cadence-don-t-overwrite-msg-buf-during-wri.patch b/queue-5.19/soundwire-cadence-don-t-overwrite-msg-buf-during-wri.patch new file mode 100644 index 00000000000..83c823cd600 --- /dev/null +++ b/queue-5.19/soundwire-cadence-don-t-overwrite-msg-buf-during-wri.patch @@ -0,0 +1,49 @@ +From dfcf82f837624e0fc98e8020448caf493930b74e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 11:35:05 +0100 +Subject: soundwire: cadence: Don't overwrite msg->buf during write commands + +From: Richard Fitzgerald + +[ Upstream commit ba05b39d265bdd16913f7684600d9d41e2796745 ] + +The buf passed in struct sdw_msg must only be written for a READ, +in that case the RDATA part of the response is the data value of the +register. + +For a write command there is no RDATA, and buf should be assumed to +be const and unmodifable. The original caller should not expect its data +buffer to be corrupted by an sdw_nwrite(). + +Signed-off-by: Richard Fitzgerald +Reviewed-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20220916103505.1562210-1-rf@opensource.cirrus.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/cadence_master.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c +index 4fbb19557f5e..42c5fae80efb 100644 +--- a/drivers/soundwire/cadence_master.c ++++ b/drivers/soundwire/cadence_master.c +@@ -544,9 +544,12 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns, + return SDW_CMD_IGNORED; + } + +- /* fill response */ +- for (i = 0; i < count; i++) +- msg->buf[i + offset] = FIELD_GET(CDNS_MCP_RESP_RDATA, cdns->response_buf[i]); ++ if (msg->flags == SDW_MSG_FLAG_READ) { ++ /* fill response */ ++ for (i = 0; i < count; i++) ++ msg->buf[i + offset] = FIELD_GET(CDNS_MCP_RESP_RDATA, ++ cdns->response_buf[i]); ++ } + + return SDW_CMD_OK; + } +-- +2.35.1 + diff --git a/queue-5.19/soundwire-intel-fix-error-handling-on-dai-registrati.patch b/queue-5.19/soundwire-intel-fix-error-handling-on-dai-registrati.patch new file mode 100644 index 00000000000..6bc6ae91949 --- /dev/null +++ b/queue-5.19/soundwire-intel-fix-error-handling-on-dai-registrati.patch @@ -0,0 +1,39 @@ +From 6a11155b0fd0acfc62bc45eec6c4a3122be0ba47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 01:57:11 +0800 +Subject: soundwire: intel: fix error handling on dai registration issues + +From: Pierre-Louis Bossart + +[ Upstream commit c6867cda906aadbce5e71efde9c78a26108b2bad ] + +The call to intel_register_dai() may fail because of memory allocation +issues or problems reported by the ASoC core. In all cases, when a +error is thrown the component is not registered, it's invalid to +unregister it. + +Signed-off-by: Pierre-Louis Bossart +Reviewed-by: Rander Wang +Signed-off-by: Bard Liao +Link: https://lore.kernel.org/r/20220919175721.354679-2-yung-chuan.liao@linux.intel.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/soundwire/intel.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c +index 505c5ef061e3..865d91ecb862 100644 +--- a/drivers/soundwire/intel.c ++++ b/drivers/soundwire/intel.c +@@ -1401,7 +1401,6 @@ int intel_link_startup(struct auxiliary_device *auxdev) + ret = intel_register_dai(sdw); + if (ret) { + dev_err(dev, "DAI registration failed: %d\n", ret); +- snd_soc_unregister_component(dev); + goto err_interrupt; + } + +-- +2.35.1 + diff --git a/queue-5.19/sparc-fix-the-generic-io-helpers.patch b/queue-5.19/sparc-fix-the-generic-io-helpers.patch new file mode 100644 index 00000000000..fd56439b159 --- /dev/null +++ b/queue-5.19/sparc-fix-the-generic-io-helpers.patch @@ -0,0 +1,165 @@ +From 36728f5f8ddec9d695ede1d89991cfb6f1f2f9cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 21:55:53 +0200 +Subject: sparc: Fix the generic IO helpers + +From: Linus Walleij + +[ Upstream commit 2c230431e1e809270178905974f57cf3878939f5 ] + +This enables the Sparc to use to fill in the +missing (undefined) [read|write]sq I/O accessor functions. + +This is needed if Sparc[64] ever wants to uses CONFIG_REGMAP_MMIO +which has been patches to use accelerated _noinc accessors +such as readsq/writesq that Sparc64, while being a 64bit platform, +as of now not yet provide. + +This comes with the requirement that everything the architecture +already provides needs to be defined, rather than just being, +say, static inline functions. + +Bite the bullet and just provide the definitions and make it work. +Compile-tested on sparc32 and sparc64. + +Reported-by: kernel test robot +Signed-off-by: Linus Walleij +Cc: David S. Miller +Cc: sparclinux@vger.kernel.org +Cc: linux-arch@vger.kernel.org +Cc: Mark Brown +Cc: Arnd Bergmann +Link: https://lore.kernel.org/linux-arm-kernel/202208201639.HXye3ke4-lkp@intel.com/ +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/sparc/include/asm/io.h | 2 ++ + arch/sparc/include/asm/io_64.h | 22 ++++++++++++++++++++++ + 2 files changed, 24 insertions(+) + +diff --git a/arch/sparc/include/asm/io.h b/arch/sparc/include/asm/io.h +index 2eefa526b38f..2dad9be9ec75 100644 +--- a/arch/sparc/include/asm/io.h ++++ b/arch/sparc/include/asm/io.h +@@ -19,4 +19,6 @@ + #define writel_be(__w, __addr) __raw_writel(__w, __addr) + #define writew_be(__l, __addr) __raw_writew(__l, __addr) + ++#include ++ + #endif +diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h +index 5ffa820dcd4d..9303270b22f3 100644 +--- a/arch/sparc/include/asm/io_64.h ++++ b/arch/sparc/include/asm/io_64.h +@@ -9,6 +9,7 @@ + #include /* IO address mapping routines need this */ + #include + #include ++#define pci_iomap pci_iomap + + /* BIO layer definitions. */ + extern unsigned long kern_base, kern_size; +@@ -239,38 +240,51 @@ static inline void outl(u32 l, unsigned long addr) + void outsb(unsigned long, const void *, unsigned long); + void outsw(unsigned long, const void *, unsigned long); + void outsl(unsigned long, const void *, unsigned long); ++#define outsb outsb ++#define outsw outsw ++#define outsl outsl + void insb(unsigned long, void *, unsigned long); + void insw(unsigned long, void *, unsigned long); + void insl(unsigned long, void *, unsigned long); ++#define insb insb ++#define insw insw ++#define insl insl + + static inline void readsb(void __iomem *port, void *buf, unsigned long count) + { + insb((unsigned long __force)port, buf, count); + } ++#define readsb readsb ++ + static inline void readsw(void __iomem *port, void *buf, unsigned long count) + { + insw((unsigned long __force)port, buf, count); + } ++#define readsw readsw + + static inline void readsl(void __iomem *port, void *buf, unsigned long count) + { + insl((unsigned long __force)port, buf, count); + } ++#define readsl readsl + + static inline void writesb(void __iomem *port, const void *buf, unsigned long count) + { + outsb((unsigned long __force)port, buf, count); + } ++#define writesb writesb + + static inline void writesw(void __iomem *port, const void *buf, unsigned long count) + { + outsw((unsigned long __force)port, buf, count); + } ++#define writesw writesw + + static inline void writesl(void __iomem *port, const void *buf, unsigned long count) + { + outsl((unsigned long __force)port, buf, count); + } ++#define writesl writesl + + #define ioread8_rep(p,d,l) readsb(p,d,l) + #define ioread16_rep(p,d,l) readsw(p,d,l) +@@ -344,6 +358,7 @@ static inline void memset_io(volatile void __iomem *dst, int c, __kernel_size_t + d++; + } + } ++#define memset_io memset_io + + static inline void sbus_memcpy_fromio(void *dst, const volatile void __iomem *src, + __kernel_size_t n) +@@ -369,6 +384,7 @@ static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, + src++; + } + } ++#define memcpy_fromio memcpy_fromio + + static inline void sbus_memcpy_toio(volatile void __iomem *dst, const void *src, + __kernel_size_t n) +@@ -395,6 +411,7 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src, + d++; + } + } ++#define memcpy_toio memcpy_toio + + #ifdef __KERNEL__ + +@@ -412,7 +429,9 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size) + static inline void __iomem *ioremap_np(unsigned long offset, unsigned long size) + { + return NULL; ++ + } ++#define ioremap_np ioremap_np + + static inline void iounmap(volatile void __iomem *addr) + { +@@ -432,10 +451,13 @@ static inline void iounmap(volatile void __iomem *addr) + /* Create a virtual mapping cookie for an IO port range */ + void __iomem *ioport_map(unsigned long port, unsigned int nr); + void ioport_unmap(void __iomem *); ++#define ioport_map ioport_map ++#define ioport_unmap ioport_unmap + + /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ + struct pci_dev; + void pci_iounmap(struct pci_dev *dev, void __iomem *); ++#define pci_iounmap pci_iounmap + + static inline int sbus_can_dma_64bit(void) + { +-- +2.35.1 + diff --git a/queue-5.19/spi-cadence-quadspi-fix-pm-disable-depth-imbalance-i.patch b/queue-5.19/spi-cadence-quadspi-fix-pm-disable-depth-imbalance-i.patch new file mode 100644 index 00000000000..baa2e1a3566 --- /dev/null +++ b/queue-5.19/spi-cadence-quadspi-fix-pm-disable-depth-imbalance-i.patch @@ -0,0 +1,47 @@ +From d7a27eb313cadc45e13315ca9bc97959397b3d70 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 20:13:07 +0800 +Subject: spi: cadence-quadspi: Fix PM disable depth imbalance in cqspi_probe + +From: Zhang Qilong + +[ Upstream commit 4d0ef0a1c35189a6e8377d8ee8310ea5ef22c5f3 ] + +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:73d5fe0462702 ("spi: cadence-quadspi: Remove spi_master_put() in probe failure path") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220924121310.78331-2-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-cadence-quadspi.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c +index 72b1a5a2298c..106c09ffa425 100644 +--- a/drivers/spi/spi-cadence-quadspi.c ++++ b/drivers/spi/spi-cadence-quadspi.c +@@ -1619,7 +1619,7 @@ static int cqspi_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) +- return ret; ++ goto probe_pm_failed; + + ret = clk_prepare_enable(cqspi->clk); + if (ret) { +@@ -1712,6 +1712,7 @@ static int cqspi_probe(struct platform_device *pdev) + clk_disable_unprepare(cqspi->clk); + probe_clk_failed: + pm_runtime_put_sync(dev); ++probe_pm_failed: + pm_runtime_disable(dev); + return ret; + } +-- +2.35.1 + diff --git a/queue-5.19/spi-dw-fix-pm-disable-depth-imbalance-in-dw_spi_bt1_.patch b/queue-5.19/spi-dw-fix-pm-disable-depth-imbalance-in-dw_spi_bt1_.patch new file mode 100644 index 00000000000..bd29ad0f5a4 --- /dev/null +++ b/queue-5.19/spi-dw-fix-pm-disable-depth-imbalance-in-dw_spi_bt1_.patch @@ -0,0 +1,42 @@ +From c16dfd8c2889803e0c3e7c862866c501f7081a42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 20:13:08 +0800 +Subject: spi: dw: Fix PM disable depth imbalance in dw_spi_bt1_probe + +From: Zhang Qilong + +[ Upstream commit 618d815fc93477b1675878f3c04ff32657cc18b4 ] + +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:abf00907538e2 ("spi: dw: Add Baikal-T1 SPI Controller glue driver") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220924121310.78331-3-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-dw-bt1.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c +index c06553416123..3fb89dee595e 100644 +--- a/drivers/spi/spi-dw-bt1.c ++++ b/drivers/spi/spi-dw-bt1.c +@@ -293,8 +293,10 @@ static int dw_spi_bt1_probe(struct platform_device *pdev) + pm_runtime_enable(&pdev->dev); + + ret = dw_spi_add_host(&pdev->dev, dws); +- if (ret) ++ if (ret) { ++ pm_runtime_disable(&pdev->dev); + goto err_disable_clk; ++ } + + platform_set_drvdata(pdev, dwsbt1); + +-- +2.35.1 + diff --git a/queue-5.19/spi-ensure-that-sg_table-won-t-be-used-after-being-f.patch b/queue-5.19/spi-ensure-that-sg_table-won-t-be-used-after-being-f.patch new file mode 100644 index 00000000000..c8105f04c23 --- /dev/null +++ b/queue-5.19/spi-ensure-that-sg_table-won-t-be-used-after-being-f.patch @@ -0,0 +1,39 @@ +From 9a27b08e8baa523d8aa8bb3712524886bd040344 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Sep 2022 13:34:08 +0200 +Subject: spi: Ensure that sg_table won't be used after being freed + +From: Marek Szyprowski + +[ Upstream commit 8e9204cddcc3fea9affcfa411715ba4f66e97587 ] + +SPI code checks for non-zero sgt->orig_nents to determine if the buffer +has been DMA-mapped. Ensure that sg_table is really zeroed after free to +avoid potential NULL pointer dereference if the given SPI xfer object is +reused again without being DMA-mapped. + +Fixes: 0c17ba73c08f ("spi: Fix cache corruption due to DMA/PIO overlap") +Signed-off-by: Marek Szyprowski +Link: https://lore.kernel.org/r/20220930113408.19720-1-m.szyprowski@samsung.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c +index 2c616024f7c0..f595e516058c 100644 +--- a/drivers/spi/spi.c ++++ b/drivers/spi/spi.c +@@ -1047,6 +1047,8 @@ void spi_unmap_buf(struct spi_controller *ctlr, struct device *dev, + if (sgt->orig_nents) { + dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir); + sg_free_table(sgt); ++ sgt->orig_nents = 0; ++ sgt->nents = 0; + } + } + +-- +2.35.1 + diff --git a/queue-5.19/spi-meson-spicc-do-not-rely-on-busy-flag-in-pow2-clk.patch b/queue-5.19/spi-meson-spicc-do-not-rely-on-busy-flag-in-pow2-clk.patch new file mode 100644 index 00000000000..ad6b9614dd2 --- /dev/null +++ b/queue-5.19/spi-meson-spicc-do-not-rely-on-busy-flag-in-pow2-clk.patch @@ -0,0 +1,66 @@ +From b7d0da2c814fa9559c841dc02a9e6b12ad2907b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Sep 2022 14:18:03 +0200 +Subject: spi: meson-spicc: do not rely on busy flag in pow2 clk ops + +From: Neil Armstrong + +[ Upstream commit 36acf80fc0c4b5ebe6fa010b524d442ee7f08fd3 ] + +Since [1], controller's busy flag isn't set anymore when the +__spi_transfer_message_noqueue() is used instead of the +__spi_pump_transfer_message() logic for spi_sync transfers. + +Since the pow2 clock ops were limited to only be available when a +transfer is ongoing (between prepare_transfer_hardware and +unprepare_transfer_hardware callbacks), the only way to track this +down is to check for the controller cur_msg. + +[1] ae7d2346dc89 ("spi: Don't use the message queue if possible in spi_sync") + +Fixes: 09992025dacd ("spi: meson-spicc: add local pow2 clock ops to preserve rate between messages") +Fixes: ae7d2346dc89 ("spi: Don't use the message queue if possible in spi_sync") +Reported-by: Markus Schneider-Pargmann +Signed-off-by: Neil Armstrong +Tested-by: Markus Schneider-Pargmann +Link: https://lore.kernel.org/r/20220908121803.919943-1-narmstrong@baylibre.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-meson-spicc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c +index e4cb52e1fe26..6974a1c947aa 100644 +--- a/drivers/spi/spi-meson-spicc.c ++++ b/drivers/spi/spi-meson-spicc.c +@@ -537,7 +537,7 @@ static unsigned long meson_spicc_pow2_recalc_rate(struct clk_hw *hw, + struct clk_divider *divider = to_clk_divider(hw); + struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); + +- if (!spicc->master->cur_msg || !spicc->master->busy) ++ if (!spicc->master->cur_msg) + return 0; + + return clk_divider_ops.recalc_rate(hw, parent_rate); +@@ -549,7 +549,7 @@ static int meson_spicc_pow2_determine_rate(struct clk_hw *hw, + struct clk_divider *divider = to_clk_divider(hw); + struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); + +- if (!spicc->master->cur_msg || !spicc->master->busy) ++ if (!spicc->master->cur_msg) + return -EINVAL; + + return clk_divider_ops.determine_rate(hw, req); +@@ -561,7 +561,7 @@ static int meson_spicc_pow2_set_rate(struct clk_hw *hw, unsigned long rate, + struct clk_divider *divider = to_clk_divider(hw); + struct meson_spicc_device *spicc = pow2_clk_to_spicc(divider); + +- if (!spicc->master->cur_msg || !spicc->master->busy) ++ if (!spicc->master->cur_msg) + return -EINVAL; + + return clk_divider_ops.set_rate(hw, rate, parent_rate); +-- +2.35.1 + diff --git a/queue-5.19/spi-mt7621-fix-an-error-message-in-mt7621_spi_probe.patch b/queue-5.19/spi-mt7621-fix-an-error-message-in-mt7621_spi_probe.patch new file mode 100644 index 00000000000..bc105b0a867 --- /dev/null +++ b/queue-5.19/spi-mt7621-fix-an-error-message-in-mt7621_spi_probe.patch @@ -0,0 +1,48 @@ +From abaf122fd7d121dc7719003eccf24cb1c107279e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Aug 2022 13:42:07 +0200 +Subject: spi: mt7621: Fix an error message in mt7621_spi_probe() + +From: Christophe JAILLET + +[ Upstream commit 2b2bf6b7faa9010fae10dc7de76627a3fdb525b3 ] + +'status' is known to be 0 at this point. The expected error code is +PTR_ERR(clk). + +Switch to dev_err_probe() in order to display the expected error code (in a +human readable way). +This also filters -EPROBE_DEFER cases, should it happen. + +Fixes: 1ab7f2a43558 ("staging: mt7621-spi: add mt7621 support") +Signed-off-by: Christophe JAILLET +Reviewed-by: Matthias Brugger +Link: https://lore.kernel.org/r/928f3fb507d53ba0774df27cea0bbba4b055993b.1661599671.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-mt7621.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c +index b4b9b7309b5e..351b0ef52bbc 100644 +--- a/drivers/spi/spi-mt7621.c ++++ b/drivers/spi/spi-mt7621.c +@@ -340,11 +340,9 @@ static int mt7621_spi_probe(struct platform_device *pdev) + return PTR_ERR(base); + + clk = devm_clk_get(&pdev->dev, NULL); +- if (IS_ERR(clk)) { +- dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", +- status); +- return PTR_ERR(clk); +- } ++ if (IS_ERR(clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(clk), ++ "unable to get SYS clock\n"); + + status = clk_prepare_enable(clk); + if (status) +-- +2.35.1 + diff --git a/queue-5.19/spi-omap100k-fix-pm-disable-depth-imbalance-in-omap1.patch b/queue-5.19/spi-omap100k-fix-pm-disable-depth-imbalance-in-omap1.patch new file mode 100644 index 00000000000..68970865bdb --- /dev/null +++ b/queue-5.19/spi-omap100k-fix-pm-disable-depth-imbalance-in-omap1.patch @@ -0,0 +1,38 @@ +From a7c15554a2c8aba82e950c458b64e3cc6ba29873 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 20:13:09 +0800 +Subject: spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe + +From: Zhang Qilong + +[ Upstream commit 29f65f2171c85a9633daa380df14009a365f42f2 ] + +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:db91841b58f9a ("spi/omap100k: Convert to runtime PM") + +Signed-off-by: Zhang Qilong +Link: https://lore.kernel.org/r/20220924121310.78331-4-zhangqilong3@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-omap-100k.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c +index 20b047172965..061f7394e5b9 100644 +--- a/drivers/spi/spi-omap-100k.c ++++ b/drivers/spi/spi-omap-100k.c +@@ -412,6 +412,7 @@ static int omap1_spi100k_probe(struct platform_device *pdev) + return status; + + err_fck: ++ pm_runtime_disable(&pdev->dev); + clk_disable_unprepare(spi100k->fck); + err_ick: + clk_disable_unprepare(spi100k->ick); +-- +2.35.1 + diff --git a/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch b/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch new file mode 100644 index 00000000000..d547f93f48c --- /dev/null +++ b/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch @@ -0,0 +1,61 @@ +From e9852302834a6f830ca948ae5adf351ed1d0ada8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 06:53:23 +0000 +Subject: spi: qup: add missing clk_disable_unprepare on error in + spi_qup_resume() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Xu Qiang + +[ Upstream commit 70034320fdc597b8f58b4a43bb547f17c4c5557a ] + +Add the missing clk_disable_unprepare() before return +from spi_qup_resume() in the error handling case. + +Fixes: 64ff247a978f (“spi: Add Qualcomm QUP SPI controller support”) +Signed-off-by: Xu Qiang +Link: https://lore.kernel.org/r/20220825065324.68446-1-xuqiang36@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-qup.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c +index 00d6084306b4..ae4e67f152ec 100644 +--- a/drivers/spi/spi-qup.c ++++ b/drivers/spi/spi-qup.c +@@ -1245,14 +1245,25 @@ static int spi_qup_resume(struct device *device) + return ret; + + ret = clk_prepare_enable(controller->cclk); +- if (ret) ++ if (ret) { ++ clk_disable_unprepare(controller->iclk); + return ret; ++ } + + ret = spi_qup_set_state(controller, QUP_STATE_RESET); + if (ret) +- return ret; ++ goto disable_clk; ++ ++ ret = spi_master_resume(master); ++ if (ret) ++ goto disable_clk; + +- return spi_master_resume(master); ++ return 0; ++ ++disable_clk: ++ clk_disable_unprepare(controller->cclk); ++ clk_disable_unprepare(controller->iclk); ++ return ret; + } + #endif /* CONFIG_PM_SLEEP */ + +-- +2.35.1 + diff --git a/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch-30157 b/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch-30157 new file mode 100644 index 00000000000..14c86e236d8 --- /dev/null +++ b/queue-5.19/spi-qup-add-missing-clk_disable_unprepare-on-error-i.patch-30157 @@ -0,0 +1,44 @@ +From 3b7981bcc842f3616f79a68d95e10cac96f7ebaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 06:53:24 +0000 +Subject: spi: qup: add missing clk_disable_unprepare on error in + spi_qup_pm_resume_runtime() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Xu Qiang + +[ Upstream commit 494a22765ce479c9f8ad181c5d24cffda9f534bb ] + +Add the missing clk_disable_unprepare() before return +from spi_qup_pm_resume_runtime() in the error handling case. + +Fixes: dae1a7700b34 (“spi: qup: Handle clocks in pm_runtime suspend and resume”) +Signed-off-by: Xu Qiang +Link: https://lore.kernel.org/r/20220825065324.68446-2-xuqiang36@huawei.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-qup.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c +index ae4e67f152ec..7d89510dc3f0 100644 +--- a/drivers/spi/spi-qup.c ++++ b/drivers/spi/spi-qup.c +@@ -1198,8 +1198,10 @@ static int spi_qup_pm_resume_runtime(struct device *device) + return ret; + + ret = clk_prepare_enable(controller->cclk); +- if (ret) ++ if (ret) { ++ clk_disable_unprepare(controller->iclk); + return ret; ++ } + + /* Disable clocks auto gaiting */ + config = readl_relaxed(controller->base + QUP_CONFIG); +-- +2.35.1 + diff --git a/queue-5.19/spi-s3c64xx-fix-large-transfers-with-dma.patch b/queue-5.19/spi-s3c64xx-fix-large-transfers-with-dma.patch new file mode 100644 index 00000000000..582e0522a73 --- /dev/null +++ b/queue-5.19/spi-s3c64xx-fix-large-transfers-with-dma.patch @@ -0,0 +1,60 @@ +From 09da53ba01a8871a3f5735903f954bcab48950d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 13:21:17 +0200 +Subject: spi: s3c64xx: Fix large transfers with DMA + +From: Vincent Whitchurch + +[ Upstream commit 1224e29572f655facfcd850cf0f0a4784f36a903 ] + +The COUNT_VALUE in the PACKET_CNT register is 16-bit so the maximum +value is 65535. Asking the driver to transfer a larger size currently +leads to the DMA transfer timing out. Implement ->max_transfer_size() +and have the core split the transfer as needed. + +Fixes: 230d42d422e7 ("spi: Add s3c64xx SPI Controller driver") +Signed-off-by: Vincent Whitchurch +Link: https://lore.kernel.org/r/20220927112117.77599-5-vincent.whitchurch@axis.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-s3c64xx.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c +index 8fa21afc6a35..b77c98bcf93f 100644 +--- a/drivers/spi/spi-s3c64xx.c ++++ b/drivers/spi/spi-s3c64xx.c +@@ -83,6 +83,7 @@ + #define S3C64XX_SPI_ST_TX_FIFORDY (1<<0) + + #define S3C64XX_SPI_PACKET_CNT_EN (1<<16) ++#define S3C64XX_SPI_PACKET_CNT_MASK GENMASK(15, 0) + + #define S3C64XX_SPI_PND_TX_UNDERRUN_CLR (1<<4) + #define S3C64XX_SPI_PND_TX_OVERRUN_CLR (1<<3) +@@ -663,6 +664,13 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master, + return 0; + } + ++static size_t s3c64xx_spi_max_transfer_size(struct spi_device *spi) ++{ ++ struct spi_controller *ctlr = spi->controller; ++ ++ return ctlr->can_dma ? S3C64XX_SPI_PACKET_CNT_MASK : SIZE_MAX; ++} ++ + static int s3c64xx_spi_transfer_one(struct spi_master *master, + struct spi_device *spi, + struct spi_transfer *xfer) +@@ -1100,6 +1108,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) + master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; + master->prepare_message = s3c64xx_spi_prepare_message; + master->transfer_one = s3c64xx_spi_transfer_one; ++ master->max_transfer_size = s3c64xx_spi_max_transfer_size; + master->num_chipselect = sci->num_cs; + master->use_gpio_descriptors = true; + master->dma_alignment = 8; +-- +2.35.1 + diff --git a/queue-5.19/spmi-pmic-arb-correct-duplicate-apid-to-ppid-mapping.patch b/queue-5.19/spmi-pmic-arb-correct-duplicate-apid-to-ppid-mapping.patch new file mode 100644 index 00000000000..584d95d6b82 --- /dev/null +++ b/queue-5.19/spmi-pmic-arb-correct-duplicate-apid-to-ppid-mapping.patch @@ -0,0 +1,65 @@ +From 375f52e1b6e38156d1305d3e4f8377f878b8c192 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 17:50:16 -0700 +Subject: spmi: pmic-arb: correct duplicate APID to PPID mapping logic + +From: David Collins + +[ Upstream commit 1f1693118c2476cb1666ad357edcf3cf48bf9b16 ] + +Correct the way that duplicate PPID mappings are handled for PMIC +arbiter v5. The final APID mapped to a given PPID should be the +one which has write owner = APPS EE, if it exists, or if not +that, then the first APID mapped to the PPID, if it exists. + +Fixes: 40f318f0ed67 ("spmi: pmic-arb: add support for HW version 5") +Signed-off-by: David Collins +Signed-off-by: Fenglin Wu +Link: https://lore.kernel.org/r/1655004286-11493-7-git-send-email-quic_fenglinw@quicinc.com +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20220930005019.2663064-8-sboyd@kernel.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/spmi/spmi-pmic-arb.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c +index 2113be40b5a9..58f580e7aacc 100644 +--- a/drivers/spmi/spmi-pmic-arb.c ++++ b/drivers/spmi/spmi-pmic-arb.c +@@ -992,7 +992,8 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb) + * version 5, there is more than one APID mapped to each PPID. + * The owner field for each of these mappings specifies the EE which is + * allowed to write to the APID. The owner of the last (highest) APID +- * for a given PPID will receive interrupts from the PPID. ++ * which has the IRQ owner bit set for a given PPID will receive ++ * interrupts from the PPID. + */ + for (i = 0; ; i++, apidd++) { + offset = pmic_arb->ver_ops->apid_map_offset(i); +@@ -1015,16 +1016,16 @@ static int pmic_arb_read_apid_map_v5(struct spmi_pmic_arb *pmic_arb) + apid = pmic_arb->ppid_to_apid[ppid] & ~PMIC_ARB_APID_VALID; + prev_apidd = &pmic_arb->apid_data[apid]; + +- if (valid && is_irq_ee && +- prev_apidd->write_ee == pmic_arb->ee) { ++ if (!valid || apidd->write_ee == pmic_arb->ee) { ++ /* First PPID mapping or one for this EE */ ++ pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID; ++ } else if (valid && is_irq_ee && ++ prev_apidd->write_ee == pmic_arb->ee) { + /* + * Duplicate PPID mapping after the one for this EE; + * override the irq owner + */ + prev_apidd->irq_ee = apidd->irq_ee; +- } else if (!valid || is_irq_ee) { +- /* First PPID mapping or duplicate for another EE */ +- pmic_arb->ppid_to_apid[ppid] = i | PMIC_ARB_APID_VALID; + } + + apidd->ppid = ppid; +-- +2.35.1 + diff --git a/queue-5.19/staging-rtl8723bs-fix-a-potential-memory-leak-in-rtw.patch b/queue-5.19/staging-rtl8723bs-fix-a-potential-memory-leak-in-rtw.patch new file mode 100644 index 00000000000..45761d3e9b6 --- /dev/null +++ b/queue-5.19/staging-rtl8723bs-fix-a-potential-memory-leak-in-rtw.patch @@ -0,0 +1,79 @@ +From 7b09f2e2eb13d43d98c40f4e08357de951882d11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 19:27:21 +0800 +Subject: staging: rtl8723bs: fix a potential memory leak in + rtw_init_cmd_priv() + +From: Xiaoke Wang + +[ Upstream commit 708056fba733a73d926772ea4ce9a42d240345da ] + +In rtw_init_cmd_priv(), if `pcmdpriv->rsp_allocated_buf` is allocated +in failure, then `pcmdpriv->cmd_allocated_buf` will be not properly +released. Besides, considering there are only two error paths and the +first one can directly return, so we do not need implicitly jump to the +`exit` tag to execute the error handler. + +So this patch added `kfree(pcmdpriv->cmd_allocated_buf);` on the error +path to release the resource and simplified the return logic of +rtw_init_cmd_priv(). As there is no proper device to test with, no runtime +testing was performed. + +Signed-off-by: Xiaoke Wang +Link: https://lore.kernel.org/r/tencent_2B7931B79BA38E22205C5A09EFDF11E48805@qq.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/rtl8723bs/core/rtw_cmd.c | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c +index b4170f64d118..03c2c66dbf66 100644 +--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c ++++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c +@@ -161,8 +161,6 @@ static struct cmd_hdl wlancmds[] = { + + int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) + { +- int res = 0; +- + init_completion(&pcmdpriv->cmd_queue_comp); + init_completion(&pcmdpriv->terminate_cmdthread_comp); + +@@ -175,18 +173,16 @@ int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) + + pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ); + +- if (!pcmdpriv->cmd_allocated_buf) { +- res = -ENOMEM; +- goto exit; +- } ++ if (!pcmdpriv->cmd_allocated_buf) ++ return -ENOMEM; + + pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ - ((SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1)); + + pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4); + + if (!pcmdpriv->rsp_allocated_buf) { +- res = -ENOMEM; +- goto exit; ++ kfree(pcmdpriv->cmd_allocated_buf); ++ return -ENOMEM; + } + + pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 - ((SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3); +@@ -196,8 +192,8 @@ int rtw_init_cmd_priv(struct cmd_priv *pcmdpriv) + pcmdpriv->rsp_cnt = 0; + + mutex_init(&pcmdpriv->sctx_mutex); +-exit: +- return res; ++ ++ return 0; + } + + static void c2h_wk_callback(struct work_struct *work); +-- +2.35.1 + diff --git a/queue-5.19/staging-rtl8723bs-fix-potential-memory-leak-in-rtw_i.patch b/queue-5.19/staging-rtl8723bs-fix-potential-memory-leak-in-rtw_i.patch new file mode 100644 index 00000000000..d83950406f2 --- /dev/null +++ b/queue-5.19/staging-rtl8723bs-fix-potential-memory-leak-in-rtw_i.patch @@ -0,0 +1,128 @@ +From a9c9c84ff7e5bfbd9f7aa9aedaf677426813e86f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 18:39:35 +0800 +Subject: staging: rtl8723bs: fix potential memory leak in rtw_init_drv_sw() + +From: Xiaoke Wang + +[ Upstream commit 5a5aa9cce621e2c0e25a1e5d72d6be1749167cc0 ] + +In rtw_init_drv_sw(), there are various init functions are called to +populate the padapter structure and some checks for their return value. +However, except for the first one error path, the other five error paths +do not properly release the previous allocated resources, which leads to +various memory leaks. + +This patch fixes them and keeps the success and error separate. +Note that these changes keep the form of `rtw_init_drv_sw()` in +"drivers/staging/r8188eu/os_dep/os_intfs.c". As there is no proper device +to test with, no runtime testing was performed. + +Signed-off-by: Xiaoke Wang +Link: https://lore.kernel.org/r/tencent_C3B899D2FC3F1BC827F3552E0B0734056006@qq.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/rtl8723bs/os_dep/os_intfs.c | 60 +++++++++++---------- + 1 file changed, 31 insertions(+), 29 deletions(-) + +diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c +index 380d8c9e1239..68bba3c0e757 100644 +--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c ++++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c +@@ -664,51 +664,36 @@ void rtw_reset_drv_sw(struct adapter *padapter) + + u8 rtw_init_drv_sw(struct adapter *padapter) + { +- u8 ret8 = _SUCCESS; +- + rtw_init_default_value(padapter); + + rtw_init_hal_com_default_value(padapter); + +- if (rtw_init_cmd_priv(&padapter->cmdpriv)) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (rtw_init_cmd_priv(&padapter->cmdpriv)) ++ return _FAIL; + + padapter->cmdpriv.padapter = padapter; + +- if (rtw_init_evt_priv(&padapter->evtpriv)) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (rtw_init_evt_priv(&padapter->evtpriv)) ++ goto free_cmd_priv; + +- +- if (rtw_init_mlme_priv(padapter) == _FAIL) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (rtw_init_mlme_priv(padapter) == _FAIL) ++ goto free_evt_priv; + + init_mlme_ext_priv(padapter); + +- if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (_rtw_init_xmit_priv(&padapter->xmitpriv, padapter) == _FAIL) ++ goto free_mlme_ext; + +- if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (_rtw_init_recv_priv(&padapter->recvpriv, padapter) == _FAIL) ++ goto free_xmit_priv; + /* add for CONFIG_IEEE80211W, none 11w also can use */ + spin_lock_init(&padapter->security_key_mutex); + + /* We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */ + /* memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv)); */ + +- if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) { +- ret8 = _FAIL; +- goto exit; +- } ++ if (_rtw_init_sta_priv(&padapter->stapriv) == _FAIL) ++ goto free_recv_priv; + + padapter->stapriv.padapter = padapter; + padapter->setband = GHZ24_50; +@@ -719,9 +704,26 @@ u8 rtw_init_drv_sw(struct adapter *padapter) + + rtw_hal_dm_init(padapter); + +-exit: ++ return _SUCCESS; ++ ++free_recv_priv: ++ _rtw_free_recv_priv(&padapter->recvpriv); ++ ++free_xmit_priv: ++ _rtw_free_xmit_priv(&padapter->xmitpriv); ++ ++free_mlme_ext: ++ free_mlme_ext_priv(&padapter->mlmeextpriv); + +- return ret8; ++ rtw_free_mlme_priv(&padapter->mlmepriv); ++ ++free_evt_priv: ++ rtw_free_evt_priv(&padapter->evtpriv); ++ ++free_cmd_priv: ++ rtw_free_cmd_priv(&padapter->cmdpriv); ++ ++ return _FAIL; + } + + void rtw_cancel_all_timer(struct adapter *padapter) +-- +2.35.1 + diff --git a/queue-5.19/staging-vt6655-fix-potential-memory-leak.patch b/queue-5.19/staging-vt6655-fix-potential-memory-leak.patch new file mode 100644 index 00000000000..97311400a66 --- /dev/null +++ b/queue-5.19/staging-vt6655-fix-potential-memory-leak.patch @@ -0,0 +1,42 @@ +From 550e2a96bd19f82676052dc4b1bcd529adfe7c89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Sep 2022 16:13:39 +0200 +Subject: staging: vt6655: fix potential memory leak + +From: Nam Cao + +[ Upstream commit c8ff91535880d41b49699b3829fb6151942de29e ] + +In function device_init_td0_ring, memory is allocated for member +td_info of priv->apTD0Rings[i], with i increasing from 0. In case of +allocation failure, the memory is freed in reversed order, with i +decreasing to 0. However, the case i=0 is left out and thus memory is +leaked. + +Modify the memory freeing loop to include the case i=0. + +Tested-by: Philipp Hortmann +Signed-off-by: Nam Cao +Link: https://lore.kernel.org/r/20220909141338.19343-1-namcaov@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/vt6655/device_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c +index ecb8c3934bc6..a91c834c96c0 100644 +--- a/drivers/staging/vt6655/device_main.c ++++ b/drivers/staging/vt6655/device_main.c +@@ -675,7 +675,7 @@ static int device_init_td0_ring(struct vnt_private *priv) + return 0; + + err_free_desc: +- while (--i) { ++ while (i--) { + desc = &priv->apTD0Rings[i]; + kfree(desc->td_info); + } +-- +2.35.1 + diff --git a/queue-5.19/staging-vt6655-fix-some-erroneous-memory-clean-up-lo.patch b/queue-5.19/staging-vt6655-fix-some-erroneous-memory-clean-up-lo.patch new file mode 100644 index 00000000000..2a3696677a0 --- /dev/null +++ b/queue-5.19/staging-vt6655-fix-some-erroneous-memory-clean-up-lo.patch @@ -0,0 +1,68 @@ +From 33f77016ce440b7cdd13f2efb043aeace0b6975b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Sep 2022 19:04:31 +0200 +Subject: staging: vt6655: fix some erroneous memory clean-up loops + +From: Nam Cao + +[ Upstream commit 2a2db520e3ca5aafba7c211abfd397666c9b5f9d ] + +In some initialization functions of this driver, memory is allocated with +'i' acting as an index variable and increasing from 0. The commit in +"Fixes" introduces some clean-up codes in case of allocation failure, +which free memory in reverse order with 'i' decreasing to 0. However, +there are some problems: + - The case i=0 is left out. Thus memory is leaked. + - In case memory allocation fails right from the start, the memory + freeing loops will start with i=-1 and invalid memory locations will + be accessed. + +One of these loops has been fixed in commit c8ff91535880 ("staging: +vt6655: fix potential memory leak"). Fix the remaining erroneous loops. + +Link: https://lore.kernel.org/linux-staging/Yx9H1zSpxmNqx6Xc@kadam/ +Fixes: 5341ee0adb17 ("staging: vt6655: check for memory allocation failures") +Reported-by: Dan Carpenter +Tested-by: Philipp Hortmann +Signed-off-by: Nam Cao +Link: https://lore.kernel.org/r/20220912170429.29852-1-namcaov@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/staging/vt6655/device_main.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c +index afaf331fe125..ecb8c3934bc6 100644 +--- a/drivers/staging/vt6655/device_main.c ++++ b/drivers/staging/vt6655/device_main.c +@@ -564,7 +564,7 @@ static int device_init_rd0_ring(struct vnt_private *priv) + kfree(desc->rd_info); + + err_free_desc: +- while (--i) { ++ while (i--) { + desc = &priv->aRD0Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); +@@ -610,7 +610,7 @@ static int device_init_rd1_ring(struct vnt_private *priv) + kfree(desc->rd_info); + + err_free_desc: +- while (--i) { ++ while (i--) { + desc = &priv->aRD1Ring[i]; + device_free_rx_buf(priv, desc); + kfree(desc->rd_info); +@@ -715,7 +715,7 @@ static int device_init_td1_ring(struct vnt_private *priv) + return 0; + + err_free_desc: +- while (--i) { ++ while (i--) { + desc = &priv->apTD1Rings[i]; + kfree(desc->td_info); + } +-- +2.35.1 + diff --git a/queue-5.19/sunrpc-fix-svcxdr_init_decode-s-end-of-buffer-calcul.patch b/queue-5.19/sunrpc-fix-svcxdr_init_decode-s-end-of-buffer-calcul.patch new file mode 100644 index 00000000000..b9f9c77ef80 --- /dev/null +++ b/queue-5.19/sunrpc-fix-svcxdr_init_decode-s-end-of-buffer-calcul.patch @@ -0,0 +1,71 @@ +From 4eff01c8578eeee66fbf73b64f544f8e14d61291 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 15:09:53 -0400 +Subject: SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation + +From: Chuck Lever + +[ Upstream commit 90bfc37b5ab91c1a6165e3e5cfc49bf04571b762 ] + +Ensure that stream-based argument decoding can't go past the actual +end of the receive buffer. xdr_init_decode's calculation of the +value of xdr->end over-estimates the end of the buffer because the +Linux kernel RPC server code does not remove the size of the RPC +header from rqstp->rq_arg before calling the upper layer's +dispatcher. + +The server-side still uses the svc_getnl() macros to decode the +RPC call header. These macros reduce the length of the head iov +but do not update the total length of the message in the buffer +(buf->len). + +A proper fix for this would be to replace the use of svc_getnl() and +friends in the RPC header decoder, but that would be a large and +invasive change that would be difficult to backport. + +Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side") +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + include/linux/sunrpc/svc.h | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index daecb009c05b..5a830b66f059 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -544,16 +544,27 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space) + } + + /** +- * svcxdr_init_decode - Prepare an xdr_stream for svc Call decoding ++ * svcxdr_init_decode - Prepare an xdr_stream for Call decoding + * @rqstp: controlling server RPC transaction context + * ++ * This function currently assumes the RPC header in rq_arg has ++ * already been decoded. Upon return, xdr->p points to the ++ * location of the upper layer header. + */ + static inline void svcxdr_init_decode(struct svc_rqst *rqstp) + { + struct xdr_stream *xdr = &rqstp->rq_arg_stream; +- struct kvec *argv = rqstp->rq_arg.head; ++ struct xdr_buf *buf = &rqstp->rq_arg; ++ struct kvec *argv = buf->head; + +- xdr_init_decode(xdr, &rqstp->rq_arg, argv->iov_base, NULL); ++ /* ++ * svc_getnl() and friends do not keep the xdr_buf's ::len ++ * field up to date. Refresh that field before initializing ++ * the argument decoding stream. ++ */ ++ buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; ++ ++ xdr_init_decode(xdr, buf, argv->iov_base, NULL); + xdr_set_scratch_page(xdr, rqstp->rq_scratch_page); + } + +-- +2.35.1 + diff --git a/queue-5.19/sunrpc-fix-svcxdr_init_encode-s-buflen-calculation.patch b/queue-5.19/sunrpc-fix-svcxdr_init_encode-s-buflen-calculation.patch new file mode 100644 index 00000000000..ee0de67f1d2 --- /dev/null +++ b/queue-5.19/sunrpc-fix-svcxdr_init_encode-s-buflen-calculation.patch @@ -0,0 +1,42 @@ +From 967285fabbc0d4a1431b937f0938452aab92eac4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 15:09:59 -0400 +Subject: SUNRPC: Fix svcxdr_init_encode's buflen calculation + +From: Chuck Lever + +[ Upstream commit 1242a87da0d8cd2a428e96ca68e7ea899b0f4624 ] + +Commit 2825a7f90753 ("nfsd4: allow encoding across page boundaries") +added an explicit computation of the remaining length in the rq_res +XDR buffer. + +The computation appears to suffer from an "off-by-one" bug. Because +buflen is too large by one page, XDR encoding can run off the end of +the send buffer by eventually trying to use the struct page address +in rq_page_end, which always contains NULL. + +Fixes: bddfdbcddbe2 ("NFSD: Extract the svcxdr_init_encode() helper") +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + include/linux/sunrpc/svc.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h +index 5a830b66f059..0ca8a8ffb47e 100644 +--- a/include/linux/sunrpc/svc.h ++++ b/include/linux/sunrpc/svc.h +@@ -587,7 +587,7 @@ static inline void svcxdr_init_encode(struct svc_rqst *rqstp) + xdr->end = resv->iov_base + PAGE_SIZE - rqstp->rq_auth_slack; + buf->len = resv->iov_len; + xdr->page_ptr = buf->pages - 1; +- buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages); ++ buf->buflen = PAGE_SIZE * (rqstp->rq_page_end - buf->pages); + buf->buflen -= rqstp->rq_auth_slack; + xdr->rqst = NULL; + } +-- +2.35.1 + diff --git a/queue-5.19/tcp-annotate-data-race-around-tcp_md5sig_pool_popula.patch b/queue-5.19/tcp-annotate-data-race-around-tcp_md5sig_pool_popula.patch new file mode 100644 index 00000000000..65fe81ba27c --- /dev/null +++ b/queue-5.19/tcp-annotate-data-race-around-tcp_md5sig_pool_popula.patch @@ -0,0 +1,72 @@ +From 45871494fccf1da71f4de749b5a01d7a5a92a4d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Aug 2022 21:15:28 +0000 +Subject: tcp: annotate data-race around tcp_md5sig_pool_populated + +From: Eric Dumazet + +[ Upstream commit aacd467c0a576e5e44d2de4205855dc0fe43f6fb ] + +tcp_md5sig_pool_populated can be read while another thread +changes its value. + +The race has no consequence because allocations +are protected with tcp_md5sig_mutex. + +This patch adds READ_ONCE() and WRITE_ONCE() to document +the race and silence KCSAN. + +Reported-by: Abhishek Shah +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index f82cd6eb7088..83fa8886f868 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -4349,12 +4349,16 @@ static void __tcp_alloc_md5sig_pool(void) + * to memory. See smp_rmb() in tcp_get_md5sig_pool() + */ + smp_wmb(); +- tcp_md5sig_pool_populated = true; ++ /* Paired with READ_ONCE() from tcp_alloc_md5sig_pool() ++ * and tcp_get_md5sig_pool(). ++ */ ++ WRITE_ONCE(tcp_md5sig_pool_populated, true); + } + + bool tcp_alloc_md5sig_pool(void) + { +- if (unlikely(!tcp_md5sig_pool_populated)) { ++ /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */ ++ if (unlikely(!READ_ONCE(tcp_md5sig_pool_populated))) { + mutex_lock(&tcp_md5sig_mutex); + + if (!tcp_md5sig_pool_populated) { +@@ -4365,7 +4369,8 @@ bool tcp_alloc_md5sig_pool(void) + + mutex_unlock(&tcp_md5sig_mutex); + } +- return tcp_md5sig_pool_populated; ++ /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */ ++ return READ_ONCE(tcp_md5sig_pool_populated); + } + EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + +@@ -4381,7 +4386,8 @@ struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) + { + local_bh_disable(); + +- if (tcp_md5sig_pool_populated) { ++ /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */ ++ if (READ_ONCE(tcp_md5sig_pool_populated)) { + /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */ + smp_rmb(); + return this_cpu_ptr(&tcp_md5sig_pool); +-- +2.35.1 + diff --git a/queue-5.19/tcp-fix-tcp_cwnd_validate-to-not-forget-is_cwnd_limi.patch b/queue-5.19/tcp-fix-tcp_cwnd_validate-to-not-forget-is_cwnd_limi.patch new file mode 100644 index 00000000000..6c8bbee0d18 --- /dev/null +++ b/queue-5.19/tcp-fix-tcp_cwnd_validate-to-not-forget-is_cwnd_limi.patch @@ -0,0 +1,150 @@ +From 78c58deea0ce32ee67612357c2359f3fca142946 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 16:03:31 -0400 +Subject: tcp: fix tcp_cwnd_validate() to not forget is_cwnd_limited + +From: Neal Cardwell + +[ Upstream commit f4ce91ce12a7c6ead19b128ffa8cff6e3ded2a14 ] + +This commit fixes a bug in the tracking of max_packets_out and +is_cwnd_limited. This bug can cause the connection to fail to remember +that is_cwnd_limited is true, causing the connection to fail to grow +cwnd when it should, causing throughput to be lower than it should be. + +The following event sequence is an example that triggers the bug: + + (a) The connection is cwnd_limited, but packets_out is not at its + peak due to TSO deferral deciding not to send another skb yet. + In such cases the connection can advance max_packets_seq and set + tp->is_cwnd_limited to true and max_packets_out to a small + number. + +(b) Then later in the round trip the connection is pacing-limited (not + cwnd-limited), and packets_out is larger. In such cases the + connection would raise max_packets_out to a bigger number but + (unexpectedly) flip tp->is_cwnd_limited from true to false. + +This commit fixes that bug. + +One straightforward fix would be to separately track (a) the next +window after max_packets_out reaches a maximum, and (b) the next +window after tp->is_cwnd_limited is set to true. But this would +require consuming an extra u32 sequence number. + +Instead, to save space we track only the most important +information. Specifically, we track the strongest available signal of +the degree to which the cwnd is fully utilized: + +(1) If the connection is cwnd-limited then we remember that fact for +the current window. + +(2) If the connection not cwnd-limited then we track the maximum +number of outstanding packets in the current window. + +In particular, note that the new logic cannot trigger the buggy +(a)/(b) sequence above because with the new logic a condition where +tp->packets_out > tp->max_packets_out can only trigger an update of +tp->is_cwnd_limited if tp->is_cwnd_limited is false. + +This first showed up in a testing of a BBRv2 dev branch, but this +buggy behavior highlighted a general issue with the +tcp_cwnd_validate() logic that can cause cwnd to fail to increase at +the proper rate for any TCP congestion control, including Reno or +CUBIC. + +Fixes: ca8a22634381 ("tcp: make cwnd-limited checks measurement-based, and gentler") +Signed-off-by: Neal Cardwell +Signed-off-by: Kevin(Yudong) Yang +Signed-off-by: Yuchung Cheng +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/linux/tcp.h | 2 +- + include/net/tcp.h | 5 ++++- + net/ipv4/tcp.c | 2 ++ + net/ipv4/tcp_output.c | 19 ++++++++++++------- + 4 files changed, 19 insertions(+), 9 deletions(-) + +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index 1168302b7927..bb31d60addac 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -265,7 +265,7 @@ struct tcp_sock { + u32 packets_out; /* Packets which are "in flight" */ + u32 retrans_out; /* Retransmitted packets out */ + u32 max_packets_out; /* max packets_out in last window */ +- u32 max_packets_seq; /* right edge of max_packets_out flight */ ++ u32 cwnd_usage_seq; /* right edge of cwnd usage tracking flight */ + + u16 urg_data; /* Saved octet of OOB data and control flags */ + u8 ecn_flags; /* ECN status bits. */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 78a64e1b33a7..788b1f17b5e3 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1289,11 +1289,14 @@ static inline bool tcp_is_cwnd_limited(const struct sock *sk) + { + const struct tcp_sock *tp = tcp_sk(sk); + ++ if (tp->is_cwnd_limited) ++ return true; ++ + /* If in slow start, ensure cwnd grows to twice what was ACKed. */ + if (tcp_in_slow_start(tp)) + return tcp_snd_cwnd(tp) < 2 * tp->max_packets_out; + +- return tp->is_cwnd_limited; ++ return false; + } + + /* BBR congestion control needs pacing. +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index ab03977b6578..f82cd6eb7088 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -3042,6 +3042,8 @@ int tcp_disconnect(struct sock *sk, int flags) + tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; + tcp_snd_cwnd_set(tp, TCP_INIT_CWND); + tp->snd_cwnd_cnt = 0; ++ tp->is_cwnd_limited = 0; ++ tp->max_packets_out = 0; + tp->window_clamp = 0; + tp->delivered = 0; + tp->delivered_ce = 0; +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 84314de754f8..a16139cacc45 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1875,15 +1875,20 @@ static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited) + const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; + struct tcp_sock *tp = tcp_sk(sk); + +- /* Track the maximum number of outstanding packets in each +- * window, and remember whether we were cwnd-limited then. ++ /* Track the strongest available signal of the degree to which the cwnd ++ * is fully utilized. If cwnd-limited then remember that fact for the ++ * current window. If not cwnd-limited then track the maximum number of ++ * outstanding packets in the current window. (If cwnd-limited then we ++ * chose to not update tp->max_packets_out to avoid an extra else ++ * clause with no functional impact.) + */ +- if (!before(tp->snd_una, tp->max_packets_seq) || +- tp->packets_out > tp->max_packets_out || +- is_cwnd_limited) { +- tp->max_packets_out = tp->packets_out; +- tp->max_packets_seq = tp->snd_nxt; ++ if (!before(tp->snd_una, tp->cwnd_usage_seq) || ++ is_cwnd_limited || ++ (!tp->is_cwnd_limited && ++ tp->packets_out > tp->max_packets_out)) { + tp->is_cwnd_limited = is_cwnd_limited; ++ tp->max_packets_out = tp->packets_out; ++ tp->cwnd_usage_seq = tp->snd_nxt; + } + + if (tcp_is_cwnd_limited(sk)) { +-- +2.35.1 + diff --git a/queue-5.19/thermal-cpufreq_cooling-check-the-policy-first-in-cp.patch b/queue-5.19/thermal-cpufreq_cooling-check-the-policy-first-in-cp.patch new file mode 100644 index 00000000000..e64e3135e96 --- /dev/null +++ b/queue-5.19/thermal-cpufreq_cooling-check-the-policy-first-in-cp.patch @@ -0,0 +1,52 @@ +From f09ecd0b2e4cc313d654b61c898fb5e53feb76ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 19:40:17 +0800 +Subject: thermal: cpufreq_cooling: Check the policy first in + cpufreq_cooling_register() + +From: Xuewen Yan + +[ Upstream commit cff895277c8558221ba180aefe26799dcb4eec86 ] + +Since the policy needs to be accessed first when obtaining cpu devices, +first check whether the policy is legal before this. + +Fixes: 5130802ddbb1 ("thermal: cpu_cooling: Switch to QoS requests for freq limits") +Signed-off-by: Xuewen Yan +Acked-by: Viresh Kumar +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/thermal/cpufreq_cooling.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c +index dc19e7c80751..ca5746f53d9e 100644 +--- a/drivers/thermal/cpufreq_cooling.c ++++ b/drivers/thermal/cpufreq_cooling.c +@@ -530,17 +530,17 @@ __cpufreq_cooling_register(struct device_node *np, + struct thermal_cooling_device_ops *cooling_ops; + char *name; + ++ if (IS_ERR_OR_NULL(policy)) { ++ pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); ++ return ERR_PTR(-EINVAL); ++ } ++ + dev = get_cpu_device(policy->cpu); + if (unlikely(!dev)) { + pr_warn("No cpu device for cpu %d\n", policy->cpu); + return ERR_PTR(-ENODEV); + } + +- if (IS_ERR_OR_NULL(policy)) { +- pr_err("%s: cpufreq policy isn't valid: %p\n", __func__, policy); +- return ERR_PTR(-EINVAL); +- } +- + i = cpufreq_table_count_valid_entries(policy); + if (!i) { + pr_debug("%s: CPUFreq table not found or has no valid entries\n", +-- +2.35.1 + diff --git a/queue-5.19/thermal-drivers-qcom-tsens-v0_1-fix-msm8939-fourth-s.patch b/queue-5.19/thermal-drivers-qcom-tsens-v0_1-fix-msm8939-fourth-s.patch new file mode 100644 index 00000000000..04c91e074f2 --- /dev/null +++ b/queue-5.19/thermal-drivers-qcom-tsens-v0_1-fix-msm8939-fourth-s.patch @@ -0,0 +1,44 @@ +From a7a83ba8a613e7d75cbde69e15c759679c9beac3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Aug 2022 12:50:14 +0200 +Subject: thermal/drivers/qcom/tsens-v0_1: Fix MSM8939 fourth sensor hw_id + +From: Vincent Knecht + +[ Upstream commit b0c883e900702f408d62cf92b0ef01303ed69be9 ] + +Reading temperature from this sensor fails with 'Invalid argument'. + +Looking at old vendor dts [1], its hw_id should be 3 instead of 4. +Change this hw_id accordingly. + +[1] https://github.com/msm8916-mainline/android_kernel_qcom_msm8916/blob/master/arch/arm/boot/dts/qcom/msm8939-common.dtsi#L511 + +Fixes: 332bc8ebab2c ("thermal: qcom: tsens-v0_1: Add support for MSM8939") +Signed-off-by: Vincent Knecht +Reviewed-by: Dmitry Baryshkov +Reviewed-by: Bjorn Andersson +Reviewed-by: Bryan O'Donoghue +Link: https://lore.kernel.org/r/20220811105014.7194-1-vincent.knecht@mailoo.org +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + drivers/thermal/qcom/tsens-v0_1.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c +index f136cb350238..327f37202c69 100644 +--- a/drivers/thermal/qcom/tsens-v0_1.c ++++ b/drivers/thermal/qcom/tsens-v0_1.c +@@ -604,7 +604,7 @@ static const struct tsens_ops ops_8939 = { + struct tsens_plat_data data_8939 = { + .num_sensors = 10, + .ops = &ops_8939, +- .hw_ids = (unsigned int []){ 0, 1, 2, 4, 5, 6, 7, 8, 9, 10 }, ++ .hw_ids = (unsigned int []){ 0, 1, 2, 3, 5, 6, 7, 8, 9, 10 }, + + .feat = &tsens_v0_1_feat, + .fields = tsens_v0_1_regfields, +-- +2.35.1 + diff --git a/queue-5.19/thermal-intel_powerclamp-use-get_cpu-instead-of-smp_.patch b/queue-5.19/thermal-intel_powerclamp-use-get_cpu-instead-of-smp_.patch new file mode 100644 index 00000000000..4fc0b96a68e --- /dev/null +++ b/queue-5.19/thermal-intel_powerclamp-use-get_cpu-instead-of-smp_.patch @@ -0,0 +1,61 @@ +From 8909dbe1f558c7e82466108d5c302fd5bd139de3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 04:06:57 -0700 +Subject: thermal: intel_powerclamp: Use get_cpu() instead of + smp_processor_id() to avoid crash + +From: Srinivas Pandruvada + +[ Upstream commit 68b99e94a4a2db6ba9b31fe0485e057b9354a640 ] + +When CPU 0 is offline and intel_powerclamp is used to inject +idle, it generates kernel BUG: + +BUG: using smp_processor_id() in preemptible [00000000] code: bash/15687 +caller is debug_smp_processor_id+0x17/0x20 +CPU: 4 PID: 15687 Comm: bash Not tainted 5.19.0-rc7+ #57 +Call Trace: + +dump_stack_lvl+0x49/0x63 +dump_stack+0x10/0x16 +check_preemption_disabled+0xdd/0xe0 +debug_smp_processor_id+0x17/0x20 +powerclamp_set_cur_state+0x7f/0xf9 [intel_powerclamp] +... +... + +Here CPU 0 is the control CPU by default and changed to the current CPU, +if CPU 0 offlined. This check has to be performed under cpus_read_lock(), +hence the above warning. + +Use get_cpu() instead of smp_processor_id() to avoid this BUG. + +Suggested-by: Chen Yu +Signed-off-by: Srinivas Pandruvada +[ rjw: Subject edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/thermal/intel/intel_powerclamp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c +index c841ab37e7c6..46cd799af148 100644 +--- a/drivers/thermal/intel/intel_powerclamp.c ++++ b/drivers/thermal/intel/intel_powerclamp.c +@@ -532,8 +532,10 @@ static int start_power_clamp(void) + + /* prefer BSP */ + control_cpu = 0; +- if (!cpu_online(control_cpu)) +- control_cpu = smp_processor_id(); ++ if (!cpu_online(control_cpu)) { ++ control_cpu = get_cpu(); ++ put_cpu(); ++ } + + clamping = true; + schedule_delayed_work(&poll_pkg_cstate_work, 0); +-- +2.35.1 + diff --git a/queue-5.19/thunderbolt-add-back-intel-falcon-ridge-end-to-end-f.patch b/queue-5.19/thunderbolt-add-back-intel-falcon-ridge-end-to-end-f.patch new file mode 100644 index 00000000000..cd189a134e8 --- /dev/null +++ b/queue-5.19/thunderbolt-add-back-intel-falcon-ridge-end-to-end-f.patch @@ -0,0 +1,129 @@ +From 6f1f74ab0ca5e46cdcba6eee31d00a000841d0a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 18:32:48 +0300 +Subject: thunderbolt: Add back Intel Falcon Ridge end-to-end flow control + workaround + +From: Mika Westerberg + +[ Upstream commit 54669e2f17cb5a4c41ade89427f074dc22cecb17 ] + +As we are now enabling full end-to-end flow control to the Thunderbolt +networking driver, in order for it to work properly on second generation +Thunderbolt hardware (Falcon Ridge), we need to add back the workaround +that was removed with commit 53f13319d131 ("thunderbolt: Get rid of E2E +workaround"). However, this time we only apply it for Falcon Ridge +controllers as a form of an additional quirk. For non-Falcon Ridge this +does nothing. + +While there fix a typo 'reqister' -> 'register' in the comment. + +Signed-off-by: Mika Westerberg +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/thunderbolt/nhi.c | 49 +++++++++++++++++++++++++++++++++------ + 1 file changed, 42 insertions(+), 7 deletions(-) + +diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c +index 1333b158a95e..407a89047473 100644 +--- a/drivers/thunderbolt/nhi.c ++++ b/drivers/thunderbolt/nhi.c +@@ -28,7 +28,11 @@ + #define RING_TYPE(ring) ((ring)->is_tx ? "TX ring" : "RX ring") + + #define RING_FIRST_USABLE_HOPID 1 +- ++/* ++ * Used with QUIRK_E2E to specify an unused HopID the Rx credits are ++ * transferred. ++ */ ++#define RING_E2E_RESERVED_HOPID RING_FIRST_USABLE_HOPID + /* + * Minimal number of vectors when we use MSI-X. Two for control channel + * Rx/Tx and the rest four are for cross domain DMA paths. +@@ -38,7 +42,9 @@ + + #define NHI_MAILBOX_TIMEOUT 500 /* ms */ + ++/* Host interface quirks */ + #define QUIRK_AUTO_CLEAR_INT BIT(0) ++#define QUIRK_E2E BIT(1) + + static int ring_interrupt_index(struct tb_ring *ring) + { +@@ -458,8 +464,18 @@ static void ring_release_msix(struct tb_ring *ring) + + static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring) + { ++ unsigned int start_hop = RING_FIRST_USABLE_HOPID; + int ret = 0; + ++ if (nhi->quirks & QUIRK_E2E) { ++ start_hop = RING_FIRST_USABLE_HOPID + 1; ++ if (ring->flags & RING_FLAG_E2E && !ring->is_tx) { ++ dev_dbg(&nhi->pdev->dev, "quirking E2E TX HopID %u -> %u\n", ++ ring->e2e_tx_hop, RING_E2E_RESERVED_HOPID); ++ ring->e2e_tx_hop = RING_E2E_RESERVED_HOPID; ++ } ++ } ++ + spin_lock_irq(&nhi->lock); + + if (ring->hop < 0) { +@@ -469,7 +485,7 @@ static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring) + * Automatically allocate HopID from the non-reserved + * range 1 .. hop_count - 1. + */ +- for (i = RING_FIRST_USABLE_HOPID; i < nhi->hop_count; i++) { ++ for (i = start_hop; i < nhi->hop_count; i++) { + if (ring->is_tx) { + if (!nhi->tx_rings[i]) { + ring->hop = i; +@@ -484,6 +500,11 @@ static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring) + } + } + ++ if (ring->hop > 0 && ring->hop < start_hop) { ++ dev_warn(&nhi->pdev->dev, "invalid hop: %d\n", ring->hop); ++ ret = -EINVAL; ++ goto err_unlock; ++ } + if (ring->hop < 0 || ring->hop >= nhi->hop_count) { + dev_warn(&nhi->pdev->dev, "invalid hop: %d\n", ring->hop); + ret = -EINVAL; +@@ -1097,12 +1118,26 @@ static void nhi_shutdown(struct tb_nhi *nhi) + + static void nhi_check_quirks(struct tb_nhi *nhi) + { +- /* +- * Intel hardware supports auto clear of the interrupt status +- * reqister right after interrupt is being issued. +- */ +- if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL) ++ if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL) { ++ /* ++ * Intel hardware supports auto clear of the interrupt ++ * status register right after interrupt is being ++ * issued. ++ */ + nhi->quirks |= QUIRK_AUTO_CLEAR_INT; ++ ++ switch (nhi->pdev->device) { ++ case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI: ++ case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI: ++ /* ++ * Falcon Ridge controller needs the end-to-end ++ * flow control workaround to avoid losing Rx ++ * packets when RING_FLAG_E2E is set. ++ */ ++ nhi->quirks |= QUIRK_E2E; ++ break; ++ } ++ } + } + + static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data) +-- +2.35.1 + diff --git a/queue-5.19/tools-power-turbostat-separate-spr-from-icx.patch b/queue-5.19/tools-power-turbostat-separate-spr-from-icx.patch new file mode 100644 index 00000000000..56dc99a00d7 --- /dev/null +++ b/queue-5.19/tools-power-turbostat-separate-spr-from-icx.patch @@ -0,0 +1,144 @@ +From 23002bdda6c44918946a420e43e609ca4f60df04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Jul 2022 18:29:32 +0300 +Subject: tools/power turbostat: separate SPR from ICX + +From: Artem Bityutskiy + +[ Upstream commit 684e40e99e594e0da1dc1b358fbd51c03c606e75 ] + +Before this patch, SPR platform was considered identical to ICX platform. This +patch separates SPR support from ICX. + +This patch is a preparation for adding SPR-specific package C-state limits +support. + +Signed-off-by: Artem Bityutskiy +Reviewed-by: Chen Yu +Signed-off-by: Len Brown +Stable-dep-of: b2d433ae6376 ("tools/power turbostat: Use standard Energy Unit for SPR Dram RAPL domain") +Signed-off-by: Sasha Levin +--- + tools/power/x86/turbostat/turbostat.c | 31 ++++++++++++++++++++++----- + 1 file changed, 26 insertions(+), 5 deletions(-) + +diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c +index 2e9a751af260..c674d397a702 100644 +--- a/tools/power/x86/turbostat/turbostat.c ++++ b/tools/power/x86/turbostat/turbostat.c +@@ -2494,6 +2494,7 @@ int has_turbo_ratio_group_limits(int family, int model) + case INTEL_FAM6_ATOM_GOLDMONT: + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_ICELAKE_X: ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: + case INTEL_FAM6_ATOM_GOLDMONT_D: + case INTEL_FAM6_ATOM_TREMONT_D: + return 1; +@@ -3746,6 +3747,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model) + has_misc_feature_control = 1; + break; + case INTEL_FAM6_ICELAKE_X: /* ICX */ ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + pkg_cstate_limits = icx_pkg_cstate_limits; + has_misc_feature_control = 1; + break; +@@ -3871,6 +3873,22 @@ int is_icx(unsigned int family, unsigned int model) + return 0; + } + ++int is_spr(unsigned int family, unsigned int model) ++{ ++ ++ if (!genuine_intel) ++ return 0; ++ ++ if (family != 6) ++ return 0; ++ ++ switch (model) { ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: ++ return 1; ++ } ++ return 0; ++} ++ + int is_ehl(unsigned int family, unsigned int model) + { + if (!genuine_intel) +@@ -3988,6 +4006,7 @@ int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model) + case INTEL_FAM6_ATOM_GOLDMONT: + case INTEL_FAM6_SKYLAKE_X: + case INTEL_FAM6_ICELAKE_X: ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: + return 1; + default: + return 0; +@@ -4015,7 +4034,7 @@ int has_config_tdp(unsigned int family, unsigned int model) + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_ICELAKE_X: /* ICX */ +- ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */ + return 1; + default: +@@ -4486,6 +4505,7 @@ static double rapl_dram_energy_units_probe(int model, double rapl_energy_units) + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ + case INTEL_FAM6_ICELAKE_X: /* ICX */ ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + return (rapl_dram_energy_units = 15.3 / 1000000); + default: + return (rapl_energy_units); +@@ -4575,6 +4595,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model) + case INTEL_FAM6_BROADWELL_X: /* BDX */ + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_ICELAKE_X: /* ICX */ ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ + do_rapl = + RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | +@@ -4740,13 +4761,13 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model) + + void automatic_cstate_conversion_probe(unsigned int family, unsigned int model) + { +- if (is_skx(family, model) || is_bdx(family, model) || is_icx(family, model)) ++ if (is_skx(family, model) || is_bdx(family, model) || is_icx(family, model) || is_spr(family, model)) + has_automatic_cstate_conversion = 1; + } + + void prewake_cstate_probe(unsigned int family, unsigned int model) + { +- if (is_icx(family, model)) ++ if (is_icx(family, model) || is_spr(family, model)) + dis_cstate_prewake = 1; + } + +@@ -4975,6 +4996,7 @@ int has_snb_msrs(unsigned int family, unsigned int model) + case INTEL_FAM6_CANNONLAKE_L: /* CNL */ + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_ICELAKE_X: /* ICX */ ++ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */ + case INTEL_FAM6_ATOM_GOLDMONT_PLUS: + case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */ +@@ -5367,7 +5389,6 @@ unsigned int intel_model_duplicates(unsigned int model) + return INTEL_FAM6_ATOM_TREMONT; + + case INTEL_FAM6_ICELAKE_D: +- case INTEL_FAM6_SAPPHIRERAPIDS_X: + return INTEL_FAM6_ICELAKE_X; + } + return model; +@@ -5654,7 +5675,7 @@ void process_cpuid() + BIC_NOT_PRESENT(BIC_Pkgpc7); + use_c1_residency_msr = 1; + } +- if (is_skx(family, model) || is_icx(family, model)) { ++ if (is_skx(family, model) || is_icx(family, model) || is_spr(family, model)) { + BIC_NOT_PRESENT(BIC_CPU_c3); + BIC_NOT_PRESENT(BIC_Pkgpc3); + BIC_NOT_PRESENT(BIC_CPU_c7); +-- +2.35.1 + diff --git a/queue-5.19/tools-power-turbostat-use-standard-energy-unit-for-s.patch b/queue-5.19/tools-power-turbostat-use-standard-energy-unit-for-s.patch new file mode 100644 index 00000000000..1fd2d76d5ed --- /dev/null +++ b/queue-5.19/tools-power-turbostat-use-standard-energy-unit-for-s.patch @@ -0,0 +1,40 @@ +From 6b16a104e789ae18df740c3d5ed7343d70616c3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 13:47:38 +0800 +Subject: tools/power turbostat: Use standard Energy Unit for SPR Dram RAPL + domain + +From: Zhang Rui + +[ Upstream commit b2d433ae637626d44c9d4a75dd3330cf68fed9de ] + +Intel Xeon servers used to use a fixed energy resolution (15.3uj) for +Dram RAPL domain. But on SPR, Dram RAPL domain follows the standard +energy resolution as described in MSR_RAPL_POWER_UNIT. + +Remove the SPR rapl_dram_energy_units quirk. + +Fixes: e7af1ed3fa47 ("tools/power turbostat: Support additional CPU model numbers") +Signed-off-by: Zhang Rui +Tested-by: Wang Wendy +Signed-off-by: Len Brown +Signed-off-by: Sasha Levin +--- + tools/power/x86/turbostat/turbostat.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c +index c674d397a702..cd60bc4d4300 100644 +--- a/tools/power/x86/turbostat/turbostat.c ++++ b/tools/power/x86/turbostat/turbostat.c +@@ -4505,7 +4505,6 @@ static double rapl_dram_energy_units_probe(int model, double rapl_energy_units) + case INTEL_FAM6_SKYLAKE_X: /* SKX */ + case INTEL_FAM6_XEON_PHI_KNL: /* KNL */ + case INTEL_FAM6_ICELAKE_X: /* ICX */ +- case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */ + return (rapl_dram_energy_units = 15.3 / 1000000); + default: + return (rapl_energy_units); +-- +2.35.1 + diff --git a/queue-5.19/tracing-kprobe-fix-kprobe-event-gen-test-module-on-e.patch b/queue-5.19/tracing-kprobe-fix-kprobe-event-gen-test-module-on-e.patch new file mode 100644 index 00000000000..818cea257e4 --- /dev/null +++ b/queue-5.19/tracing-kprobe-fix-kprobe-event-gen-test-module-on-e.patch @@ -0,0 +1,47 @@ +From 4300aad8acc6da727b10711fc6afa29c39a37308 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 20:56:28 +0800 +Subject: tracing: kprobe: Fix kprobe event gen test module on exit + +From: Yipeng Zou + +[ Upstream commit ac48e189527fae87253ef2bf58892e782fb36874 ] + +Correct gen_kretprobe_test clr event para on module exit. +This will make it can't to delete. + +Link: https://lkml.kernel.org/r/20220919125629.238242-2-zouyipeng@huawei.com + +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Fixes: 64836248dda2 ("tracing: Add kprobe event command generation test module") +Signed-off-by: Yipeng Zou +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/kprobe_event_gen_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/trace/kprobe_event_gen_test.c b/kernel/trace/kprobe_event_gen_test.c +index 18b0f1cbb947..e023154be0f8 100644 +--- a/kernel/trace/kprobe_event_gen_test.c ++++ b/kernel/trace/kprobe_event_gen_test.c +@@ -206,7 +206,7 @@ static void __exit kprobe_event_gen_test_exit(void) + WARN_ON(kprobe_event_delete("gen_kprobe_test")); + + /* Disable the event or you can't remove it */ +- WARN_ON(trace_array_set_clr_event(gen_kprobe_test->tr, ++ WARN_ON(trace_array_set_clr_event(gen_kretprobe_test->tr, + "kprobes", + "gen_kretprobe_test", false)); + +-- +2.35.1 + diff --git a/queue-5.19/tracing-kprobe-make-gen-test-module-work-in-arm-and-.patch b/queue-5.19/tracing-kprobe-make-gen-test-module-work-in-arm-and-.patch new file mode 100644 index 00000000000..b90a307d89a --- /dev/null +++ b/queue-5.19/tracing-kprobe-make-gen-test-module-work-in-arm-and-.patch @@ -0,0 +1,113 @@ +From f92271e0b43a796cf0303d0f419a6a4c640848dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 20:56:29 +0800 +Subject: tracing: kprobe: Make gen test module work in arm and riscv + +From: Yipeng Zou + +[ Upstream commit d8ef45d66c01425ff748e13ef7dd1da7a91cc93c ] + +For now, this selftest module can only work in x86 because of the +kprobe cmd was fixed use of x86 registers. +This patch adapted to register names under arm and riscv, So that +this module can be worked on those platform. + +Link: https://lkml.kernel.org/r/20220919125629.238242-3-zouyipeng@huawei.com + +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Cc: +Fixes: 64836248dda2 ("tracing: Add kprobe event command generation test module") +Signed-off-by: Yipeng Zou +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/kprobe_event_gen_test.c | 47 +++++++++++++++++++++++++--- + 1 file changed, 43 insertions(+), 4 deletions(-) + +diff --git a/kernel/trace/kprobe_event_gen_test.c b/kernel/trace/kprobe_event_gen_test.c +index e023154be0f8..80e04a1e1977 100644 +--- a/kernel/trace/kprobe_event_gen_test.c ++++ b/kernel/trace/kprobe_event_gen_test.c +@@ -35,6 +35,45 @@ + static struct trace_event_file *gen_kprobe_test; + static struct trace_event_file *gen_kretprobe_test; + ++#define KPROBE_GEN_TEST_FUNC "do_sys_open" ++ ++/* X86 */ ++#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32) ++#define KPROBE_GEN_TEST_ARG0 "dfd=%ax" ++#define KPROBE_GEN_TEST_ARG1 "filename=%dx" ++#define KPROBE_GEN_TEST_ARG2 "flags=%cx" ++#define KPROBE_GEN_TEST_ARG3 "mode=+4($stack)" ++ ++/* ARM64 */ ++#elif defined(CONFIG_ARM64) ++#define KPROBE_GEN_TEST_ARG0 "dfd=%x0" ++#define KPROBE_GEN_TEST_ARG1 "filename=%x1" ++#define KPROBE_GEN_TEST_ARG2 "flags=%x2" ++#define KPROBE_GEN_TEST_ARG3 "mode=%x3" ++ ++/* ARM */ ++#elif defined(CONFIG_ARM) ++#define KPROBE_GEN_TEST_ARG0 "dfd=%r0" ++#define KPROBE_GEN_TEST_ARG1 "filename=%r1" ++#define KPROBE_GEN_TEST_ARG2 "flags=%r2" ++#define KPROBE_GEN_TEST_ARG3 "mode=%r3" ++ ++/* RISCV */ ++#elif defined(CONFIG_RISCV) ++#define KPROBE_GEN_TEST_ARG0 "dfd=%a0" ++#define KPROBE_GEN_TEST_ARG1 "filename=%a1" ++#define KPROBE_GEN_TEST_ARG2 "flags=%a2" ++#define KPROBE_GEN_TEST_ARG3 "mode=%a3" ++ ++/* others */ ++#else ++#define KPROBE_GEN_TEST_ARG0 NULL ++#define KPROBE_GEN_TEST_ARG1 NULL ++#define KPROBE_GEN_TEST_ARG2 NULL ++#define KPROBE_GEN_TEST_ARG3 NULL ++#endif ++ ++ + /* + * Test to make sure we can create a kprobe event, then add more + * fields. +@@ -58,14 +97,14 @@ static int __init test_gen_kprobe_cmd(void) + * fields. + */ + ret = kprobe_event_gen_cmd_start(&cmd, "gen_kprobe_test", +- "do_sys_open", +- "dfd=%ax", "filename=%dx"); ++ KPROBE_GEN_TEST_FUNC, ++ KPROBE_GEN_TEST_ARG0, KPROBE_GEN_TEST_ARG1); + if (ret) + goto free; + + /* Use kprobe_event_add_fields to add the rest of the fields */ + +- ret = kprobe_event_add_fields(&cmd, "flags=%cx", "mode=+4($stack)"); ++ ret = kprobe_event_add_fields(&cmd, KPROBE_GEN_TEST_ARG2, KPROBE_GEN_TEST_ARG3); + if (ret) + goto free; + +@@ -128,7 +167,7 @@ static int __init test_gen_kretprobe_cmd(void) + * Define the kretprobe event. + */ + ret = kretprobe_event_gen_cmd_start(&cmd, "gen_kretprobe_test", +- "do_sys_open", ++ KPROBE_GEN_TEST_FUNC, + "$retval"); + if (ret) + goto free; +-- +2.35.1 + diff --git a/queue-5.19/tracing-osnoise-fix-possible-recursive-locking-in-st.patch b/queue-5.19/tracing-osnoise-fix-possible-recursive-locking-in-st.patch new file mode 100644 index 00000000000..4ab4d495e3a --- /dev/null +++ b/queue-5.19/tracing-osnoise-fix-possible-recursive-locking-in-st.patch @@ -0,0 +1,78 @@ +From c6441ec1a079718f41c9e5d3137e2f449c1e05b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 08:49:32 -0600 +Subject: tracing/osnoise: Fix possible recursive locking in + stop_per_cpu_kthreads + +From: Nico Pache + +[ Upstream commit 99ee9317a1305cd5626736785c8cb38b0e47686c ] + +There is a recursive lock on the cpu_hotplug_lock. + +In kernel/trace/trace_osnoise.c:_per_cpu_kthreads: + - start_per_cpu_kthreads calls cpus_read_lock() and if + start_kthreads returns a error it will call stop_per_cpu_kthreads. + - stop_per_cpu_kthreads then calls cpus_read_lock() again causing + deadlock. + +Fix this by calling cpus_read_unlock() before calling +stop_per_cpu_kthreads. This behavior can also be seen in commit +f46b16520a08 ("trace/hwlat: Implement the per-cpu mode"). + +This error was noticed during the LTP ftrace-stress-test: + +WARNING: possible recursive locking detected +-------------------------------------------- +sh/275006 is trying to acquire lock: +ffffffffb02f5400 (cpu_hotplug_lock){++++}-{0:0}, at: stop_per_cpu_kthreads + +but task is already holding lock: +ffffffffb02f5400 (cpu_hotplug_lock){++++}-{0:0}, at: start_per_cpu_kthreads + +other info that might help us debug this: + Possible unsafe locking scenario: + + CPU0 + ---- + lock(cpu_hotplug_lock); + lock(cpu_hotplug_lock); + + *** DEADLOCK *** + +May be due to missing lock nesting notation + +3 locks held by sh/275006: + #0: ffff8881023f0470 (sb_writers#24){.+.+}-{0:0}, at: ksys_write + #1: ffffffffb084f430 (trace_types_lock){+.+.}-{3:3}, at: rb_simple_write + #2: ffffffffb02f5400 (cpu_hotplug_lock){++++}-{0:0}, at: start_per_cpu_kthreads + +Link: https://lkml.kernel.org/r/20220919144932.3064014-1-npache@redhat.com + +Fixes: c8895e271f79 ("trace/osnoise: Support hotplug operations") +Signed-off-by: Nico Pache +Acked-by: Daniel Bristot de Oliveira +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + kernel/trace/trace_osnoise.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/trace/trace_osnoise.c b/kernel/trace/trace_osnoise.c +index 313439920a8c..78d536d3ff3d 100644 +--- a/kernel/trace/trace_osnoise.c ++++ b/kernel/trace/trace_osnoise.c +@@ -1786,8 +1786,9 @@ static int start_per_cpu_kthreads(void) + for_each_cpu(cpu, current_mask) { + retval = start_kthread(cpu); + if (retval) { ++ cpus_read_unlock(); + stop_per_cpu_kthreads(); +- break; ++ return retval; + } + } + +-- +2.35.1 + diff --git a/queue-5.19/tsnep-fix-tsnep_info_tx_time-register-define.patch b/queue-5.19/tsnep-fix-tsnep_info_tx_time-register-define.patch new file mode 100644 index 00000000000..85e48d128d1 --- /dev/null +++ b/queue-5.19/tsnep-fix-tsnep_info_tx_time-register-define.patch @@ -0,0 +1,37 @@ +From add842cff15e09c4fd93579e0bb05b45d94936a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Aug 2022 21:30:13 +0200 +Subject: tsnep: Fix TSNEP_INFO_TX_TIME register define + +From: Gerhard Engleder + +[ Upstream commit 7d8dd6b5cd1d67dd96c132f91d7ad29c49ed3c59 ] + +Fixed register define is not used, but register definition shall be kept +in sync. + +Fixes: 403f69bbdbad ("tsnep: Add TSN endpoint Ethernet MAC driver") +Signed-off-by: Gerhard Engleder +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/engleder/tsnep_hw.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/engleder/tsnep_hw.h b/drivers/net/ethernet/engleder/tsnep_hw.h +index 916ceac3ada2..e03aaafab559 100644 +--- a/drivers/net/ethernet/engleder/tsnep_hw.h ++++ b/drivers/net/ethernet/engleder/tsnep_hw.h +@@ -92,8 +92,7 @@ + + /* tsnep register */ + #define TSNEP_INFO 0x0100 +-#define TSNEP_INFO_RX_ASSIGN 0x00010000 +-#define TSNEP_INFO_TX_TIME 0x00020000 ++#define TSNEP_INFO_TX_TIME 0x00010000 + #define TSNEP_CONTROL 0x0108 + #define TSNEP_CONTROL_TX_RESET 0x00000001 + #define TSNEP_CONTROL_TX_ENABLE 0x00000002 +-- +2.35.1 + diff --git a/queue-5.19/tty-serial-fsl_lpuart-disable-dma-rx-tx-use-flags-in.patch b/queue-5.19/tty-serial-fsl_lpuart-disable-dma-rx-tx-use-flags-in.patch new file mode 100644 index 00000000000..eedb7d5f159 --- /dev/null +++ b/queue-5.19/tty-serial-fsl_lpuart-disable-dma-rx-tx-use-flags-in.patch @@ -0,0 +1,103 @@ +From 39f85dac80b14ca3aaa473f843943f6c9eec8a4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 19:17:03 +0800 +Subject: tty: serial: fsl_lpuart: disable dma rx/tx use flags in + lpuart_dma_shutdown +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Sherry Sun + +[ Upstream commit 316ae95c175a7d770d1bfe4c011192712f57aa4a ] + +lpuart_dma_shutdown tears down lpuart dma, but lpuart_flush_buffer can +still occur which in turn tries to access dma apis if lpuart_dma_tx_use +flag is true. At this point since dma is torn down, these dma apis can +abort. Set lpuart_dma_tx_use and the corresponding rx flag +lpuart_dma_rx_use to false in lpuart_dma_shutdown so that dmas are not +accessed after they are relinquished. + +Otherwise, when try to kill btattach, kernel may panic. This patch may +fix this issue. +root@imx8ulpevk:~# btattach -B /dev/ttyLP2 -S 115200 +^C[ 90.182296] Internal error: synchronous external abort: 96000210 [#1] PREEMPT SMP +[ 90.189806] Modules linked in: moal(O) mlan(O) +[ 90.194258] CPU: 0 PID: 503 Comm: btattach Tainted: G O 5.15.32-06136-g34eecdf2f9e4 #37 +[ 90.203554] Hardware name: NXP i.MX8ULP 9X9 EVK (DT) +[ 90.208513] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 90.215470] pc : fsl_edma3_disable_request+0x8/0x60 +[ 90.220358] lr : fsl_edma3_terminate_all+0x34/0x20c +[ 90.225237] sp : ffff800013f0bac0 +[ 90.228548] x29: ffff800013f0bac0 x28: 0000000000000001 x27: ffff000008404800 +[ 90.235681] x26: ffff000008404960 x25: ffff000008404a08 x24: ffff000008404a00 +[ 90.242813] x23: ffff000008404a60 x22: 0000000000000002 x21: 0000000000000000 +[ 90.249946] x20: ffff800013f0baf8 x19: ffff00000559c800 x18: 0000000000000000 +[ 90.257078] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000 +[ 90.264211] x14: 0000000000000003 x13: 0000000000000000 x12: 0000000000000040 +[ 90.271344] x11: ffff00000600c248 x10: ffff800013f0bb10 x9 : ffff000057bcb090 +[ 90.278477] x8 : fffffc0000241a08 x7 : ffff00000534ee00 x6 : ffff000008404804 +[ 90.285609] x5 : 0000000000000000 x4 : 0000000000000000 x3 : ffff0000055b3480 +[ 90.292742] x2 : ffff8000135c0000 x1 : ffff00000534ee00 x0 : ffff00000559c800 +[ 90.299876] Call trace: +[ 90.302321] fsl_edma3_disable_request+0x8/0x60 +[ 90.306851] lpuart_flush_buffer+0x40/0x160 +[ 90.311037] uart_flush_buffer+0x88/0x120 +[ 90.315050] tty_driver_flush_buffer+0x20/0x30 +[ 90.319496] hci_uart_flush+0x44/0x90 +[ 90.323162] +0x34/0x12c +[ 90.327253] tty_ldisc_close+0x38/0x70 +[ 90.331005] tty_ldisc_release+0xa8/0x190 +[ 90.335018] tty_release_struct+0x24/0x8c +[ 90.339022] tty_release+0x3ec/0x4c0 +[ 90.342593] __fput+0x70/0x234 +[ 90.345652] ____fput+0x14/0x20 +[ 90.348790] task_work_run+0x84/0x17c +[ 90.352455] do_exit+0x310/0x96c +[ 90.355688] do_group_exit+0x3c/0xa0 +[ 90.359259] __arm64_sys_exit_group+0x1c/0x20 +[ 90.363609] invoke_syscall+0x48/0x114 +[ 90.367362] el0_svc_common.constprop.0+0xd4/0xfc +[ 90.372068] do_el0_svc+0x2c/0x94 +[ 90.375379] el0_svc+0x28/0x80 +[ 90.378438] el0t_64_sync_handler+0xa8/0x130 +[ 90.382711] el0t_64_sync+0x1a0/0x1a4 +[ 90.386376] Code: 17ffffda d503201f d503233f f9409802 (b9400041) +[ 90.392467] ---[ end trace 2f60524b4a43f1f6 ]--- +[ 90.397073] note: btattach[503] exited with preempt_count 1 +[ 90.402636] Fixing recursive fault but reboot is needed! + +Fixes: 6250cc30c4c4 ("tty: serial: fsl_lpuart: Use scatter/gather DMA for Tx") +Reviewed-by: Ilpo Järvinen +Signed-off-by: Thara Gopinath +Signed-off-by: Sherry Sun +Link: https://lore.kernel.org/r/20220920111703.1532-1-sherry.sun@nxp.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/fsl_lpuart.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c +index cb83c66bd8a8..a6471af9653c 100644 +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -1768,6 +1768,7 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport) + if (sport->lpuart_dma_rx_use) { + del_timer_sync(&sport->lpuart_timer); + lpuart_dma_rx_free(&sport->port); ++ sport->lpuart_dma_rx_use = false; + } + + if (sport->lpuart_dma_tx_use) { +@@ -1776,6 +1777,7 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport) + sport->dma_tx_in_progress = false; + dmaengine_terminate_all(sport->dma_tx_chan); + } ++ sport->lpuart_dma_tx_use = false; + } + + if (sport->dma_tx_chan) +-- +2.35.1 + diff --git a/queue-5.19/tty-xilinx_uartps-fix-the-ignore_status.patch b/queue-5.19/tty-xilinx_uartps-fix-the-ignore_status.patch new file mode 100644 index 00000000000..4236f0b23e7 --- /dev/null +++ b/queue-5.19/tty-xilinx_uartps-fix-the-ignore_status.patch @@ -0,0 +1,37 @@ +From 89cbb9b268c8f2c0054814d737be649e1e3663b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 17:17:45 +0530 +Subject: tty: xilinx_uartps: Fix the ignore_status + +From: Shubhrajyoti Datta + +[ Upstream commit b8a6c3b3d4654fba19881cc77da61eac29f57cae ] + +Currently the ignore_status is not considered in the isr. +Add a check to add the ignore_status. + +Fixes: 61ec9016988f ("tty/serial: add support for Xilinx PS UART") +Signed-off-by: Shubhrajyoti Datta +Link: https://lore.kernel.org/r/20220729114748.18332-5-shubhrajyoti.datta@xilinx.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/tty/serial/xilinx_uartps.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c +index 9e01fe6c0ab8..e08d2c3305ba 100644 +--- a/drivers/tty/serial/xilinx_uartps.c ++++ b/drivers/tty/serial/xilinx_uartps.c +@@ -361,6 +361,8 @@ static irqreturn_t cdns_uart_isr(int irq, void *dev_id) + isrstatus &= ~CDNS_UART_IXR_TXEMPTY; + } + ++ isrstatus &= port->read_status_mask; ++ isrstatus &= ~port->ignore_status_mask; + /* + * Skip RX processing if RX is disabled as RXEMPTY will never be set + * as read bytes will not be removed from the FIFO. +-- +2.35.1 + diff --git a/queue-5.19/udmabuf-set-ubuf-sg-null-if-the-creation-of-sg-table.patch b/queue-5.19/udmabuf-set-ubuf-sg-null-if-the-creation-of-sg-table.patch new file mode 100644 index 00000000000..0627707db01 --- /dev/null +++ b/queue-5.19/udmabuf-set-ubuf-sg-null-if-the-creation-of-sg-table.patch @@ -0,0 +1,115 @@ +From 43179d3cb6b88300a8758656244599a2e807022a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 23:35:22 -0700 +Subject: udmabuf: Set ubuf->sg = NULL if the creation of sg table fails + +From: Vivek Kasireddy + +[ Upstream commit d9c04a1b7a15b5e74b2977461d9511e497f05d8f ] + +When userspace tries to map the dmabuf and if for some reason +(e.g. OOM) the creation of the sg table fails, ubuf->sg needs to be +set to NULL. Otherwise, when the userspace subsequently closes the +dmabuf fd, we'd try to erroneously free the invalid sg table from +release_udmabuf resulting in the following crash reported by syzbot: + +general protection fault, probably for non-canonical address +0xdffffc0000000000: 0000 [#1] PREEMPT SMP KASAN +KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] +CPU: 0 PID: 3609 Comm: syz-executor487 Not tainted +5.19.0-syzkaller-13930-g7ebfc85e2cd7 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 07/22/2022 +RIP: 0010:dma_unmap_sgtable include/linux/dma-mapping.h:378 [inline] +RIP: 0010:put_sg_table drivers/dma-buf/udmabuf.c:89 [inline] +RIP: 0010:release_udmabuf+0xcb/0x4f0 drivers/dma-buf/udmabuf.c:114 +Code: 48 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 2b 04 00 00 48 8d 7d 0c 4c +8b 63 30 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 14 +02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 e2 +RSP: 0018:ffffc900037efd30 EFLAGS: 00010246 +RAX: dffffc0000000000 RBX: ffffffff8cb67800 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: ffffffff84ad27e0 RDI: 0000000000000000 +RBP: fffffffffffffff4 R08: 0000000000000005 R09: 0000000000000000 +R10: 0000000000000000 R11: 000000000008c07c R12: ffff88801fa05000 +R13: ffff888073db07e8 R14: ffff888025c25440 R15: 0000000000000000 +FS: 0000555555fc4300(0000) GS:ffff8880b9a00000(0000) +knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fc1c0ce06e4 CR3: 00000000715e6000 CR4: 00000000003506f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + + dma_buf_release+0x157/0x2d0 drivers/dma-buf/dma-buf.c:78 + __dentry_kill+0x42b/0x640 fs/dcache.c:612 + dentry_kill fs/dcache.c:733 [inline] + dput+0x806/0xdb0 fs/dcache.c:913 + __fput+0x39c/0x9d0 fs/file_table.c:333 + task_work_run+0xdd/0x1a0 kernel/task_work.c:177 + ptrace_notify+0x114/0x140 kernel/signal.c:2353 + ptrace_report_syscall include/linux/ptrace.h:420 [inline] + ptrace_report_syscall_exit include/linux/ptrace.h:482 [inline] + syscall_exit_work kernel/entry/common.c:249 [inline] + syscall_exit_to_user_mode_prepare+0x129/0x280 kernel/entry/common.c:276 + __syscall_exit_to_user_mode_work kernel/entry/common.c:281 [inline] + syscall_exit_to_user_mode+0x9/0x50 kernel/entry/common.c:294 + do_syscall_64+0x42/0xb0 arch/x86/entry/common.c:86 + entry_SYSCALL_64_after_hwframe+0x63/0xcd +RIP: 0033:0x7fc1c0c35b6b +Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 83 ec 18 89 7c 24 +0c e8 63 fc ff ff 8b 7c 24 0c 41 89 c0 b8 03 00 00 00 0f 05 <48> 3d 00 +f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 a1 fc ff ff 8b 44 +RSP: 002b:00007ffd78a06090 EFLAGS: 00000293 ORIG_RAX: 0000000000000003 +RAX: 0000000000000000 RBX: 0000000000000007 RCX: 00007fc1c0c35b6b +RDX: 0000000020000280 RSI: 0000000040086200 RDI: 0000000000000006 +RBP: 0000000000000007 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000293 R12: 000000000000000c +R13: 0000000000000003 R14: 00007fc1c0cfe4a0 R15: 00007ffd78a06140 + +Modules linked in: +---[ end trace 0000000000000000 ]--- +RIP: 0010:dma_unmap_sgtable include/linux/dma-mapping.h:378 [inline] +RIP: 0010:put_sg_table drivers/dma-buf/udmabuf.c:89 [inline] +RIP: 0010:release_udmabuf+0xcb/0x4f0 drivers/dma-buf/udmabuf.c:114 + +Reported-by: syzbot+c80e9ef5d8bb45894db0@syzkaller.appspotmail.com +Cc: Gerd Hoffmann +Signed-off-by: Vivek Kasireddy +Link: http://patchwork.freedesktop.org/patch/msgid/20220825063522.801264-1-vivek.kasireddy@intel.com +Signed-off-by: Gerd Hoffmann +Signed-off-by: Sasha Levin +--- + drivers/dma-buf/udmabuf.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c +index 38e8767ec371..bf11d32205f3 100644 +--- a/drivers/dma-buf/udmabuf.c ++++ b/drivers/dma-buf/udmabuf.c +@@ -124,17 +124,20 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, + { + struct udmabuf *ubuf = buf->priv; + struct device *dev = ubuf->device->this_device; ++ int ret = 0; + + if (!ubuf->sg) { + ubuf->sg = get_sg_table(dev, buf, direction); +- if (IS_ERR(ubuf->sg)) +- return PTR_ERR(ubuf->sg); ++ if (IS_ERR(ubuf->sg)) { ++ ret = PTR_ERR(ubuf->sg); ++ ubuf->sg = NULL; ++ } + } else { + dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, + direction); + } + +- return 0; ++ return ret; + } + + static int end_cpu_udmabuf(struct dma_buf *buf, +-- +2.35.1 + diff --git a/queue-5.19/usb-common-debug-check-non-standard-control-requests.patch b/queue-5.19/usb-common-debug-check-non-standard-control-requests.patch new file mode 100644 index 00000000000..90bd317da0e --- /dev/null +++ b/queue-5.19/usb-common-debug-check-non-standard-control-requests.patch @@ -0,0 +1,139 @@ +From b5ecb542b2d9f8c4694641256e3ff6524fbfabab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 18:38:01 -0700 +Subject: usb: common: debug: Check non-standard control requests + +From: Thinh Nguyen + +[ Upstream commit b6155eaf6b05e558218b44b88a6cad03f15a586c ] + +Previously usb_decode_ctrl() only decodes standard control requests, but +it was used for non-standard requests also. If it's non-standard or +unknown standard bRequest, print the Setup data values. + +Fixes: af32423a2d86 ("usb: dwc3: trace: decode ctrl request") +Signed-off-by: Thinh Nguyen +Link: https://lore.kernel.org/r/8d6a30f2f2f953eff833a5bc5aac640a4cc2fc9f.1658971571.git.Thinh.Nguyen@synopsys.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/common/debug.c | 96 +++++++++++++++++++++++++------------- + 1 file changed, 64 insertions(+), 32 deletions(-) + +diff --git a/drivers/usb/common/debug.c b/drivers/usb/common/debug.c +index 075f6b1b2a1a..f204cec8d380 100644 +--- a/drivers/usb/common/debug.c ++++ b/drivers/usb/common/debug.c +@@ -208,30 +208,28 @@ static void usb_decode_set_isoch_delay(__u8 wValue, char *str, size_t size) + snprintf(str, size, "Set Isochronous Delay(Delay = %d ns)", wValue); + } + +-/** +- * usb_decode_ctrl - Returns human readable representation of control request. +- * @str: buffer to return a human-readable representation of control request. +- * This buffer should have about 200 bytes. +- * @size: size of str buffer. +- * @bRequestType: matches the USB bmRequestType field +- * @bRequest: matches the USB bRequest field +- * @wValue: matches the USB wValue field (CPU byte order) +- * @wIndex: matches the USB wIndex field (CPU byte order) +- * @wLength: matches the USB wLength field (CPU byte order) +- * +- * Function returns decoded, formatted and human-readable description of +- * control request packet. +- * +- * The usage scenario for this is for tracepoints, so function as a return +- * use the same value as in parameters. This approach allows to use this +- * function in TP_printk +- * +- * Important: wValue, wIndex, wLength parameters before invoking this function +- * should be processed by le16_to_cpu macro. +- */ +-const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, +- __u8 bRequest, __u16 wValue, __u16 wIndex, +- __u16 wLength) ++static void usb_decode_ctrl_generic(char *str, size_t size, __u8 bRequestType, ++ __u8 bRequest, __u16 wValue, __u16 wIndex, ++ __u16 wLength) ++{ ++ u8 recip = bRequestType & USB_RECIP_MASK; ++ u8 type = bRequestType & USB_TYPE_MASK; ++ ++ snprintf(str, size, ++ "Type=%s Recipient=%s Dir=%s bRequest=%u wValue=%u wIndex=%u wLength=%u", ++ (type == USB_TYPE_STANDARD) ? "Standard" : ++ (type == USB_TYPE_VENDOR) ? "Vendor" : ++ (type == USB_TYPE_CLASS) ? "Class" : "Unknown", ++ (recip == USB_RECIP_DEVICE) ? "Device" : ++ (recip == USB_RECIP_INTERFACE) ? "Interface" : ++ (recip == USB_RECIP_ENDPOINT) ? "Endpoint" : "Unknown", ++ (bRequestType & USB_DIR_IN) ? "IN" : "OUT", ++ bRequest, wValue, wIndex, wLength); ++} ++ ++static void usb_decode_ctrl_standard(char *str, size_t size, __u8 bRequestType, ++ __u8 bRequest, __u16 wValue, __u16 wIndex, ++ __u16 wLength) + { + switch (bRequest) { + case USB_REQ_GET_STATUS: +@@ -272,14 +270,48 @@ const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, + usb_decode_set_isoch_delay(wValue, str, size); + break; + default: +- snprintf(str, size, "%02x %02x %02x %02x %02x %02x %02x %02x", +- bRequestType, bRequest, +- (u8)(cpu_to_le16(wValue) & 0xff), +- (u8)(cpu_to_le16(wValue) >> 8), +- (u8)(cpu_to_le16(wIndex) & 0xff), +- (u8)(cpu_to_le16(wIndex) >> 8), +- (u8)(cpu_to_le16(wLength) & 0xff), +- (u8)(cpu_to_le16(wLength) >> 8)); ++ usb_decode_ctrl_generic(str, size, bRequestType, bRequest, ++ wValue, wIndex, wLength); ++ break; ++ } ++} ++ ++/** ++ * usb_decode_ctrl - Returns human readable representation of control request. ++ * @str: buffer to return a human-readable representation of control request. ++ * This buffer should have about 200 bytes. ++ * @size: size of str buffer. ++ * @bRequestType: matches the USB bmRequestType field ++ * @bRequest: matches the USB bRequest field ++ * @wValue: matches the USB wValue field (CPU byte order) ++ * @wIndex: matches the USB wIndex field (CPU byte order) ++ * @wLength: matches the USB wLength field (CPU byte order) ++ * ++ * Function returns decoded, formatted and human-readable description of ++ * control request packet. ++ * ++ * The usage scenario for this is for tracepoints, so function as a return ++ * use the same value as in parameters. This approach allows to use this ++ * function in TP_printk ++ * ++ * Important: wValue, wIndex, wLength parameters before invoking this function ++ * should be processed by le16_to_cpu macro. ++ */ ++const char *usb_decode_ctrl(char *str, size_t size, __u8 bRequestType, ++ __u8 bRequest, __u16 wValue, __u16 wIndex, ++ __u16 wLength) ++{ ++ switch (bRequestType & USB_TYPE_MASK) { ++ case USB_TYPE_STANDARD: ++ usb_decode_ctrl_standard(str, size, bRequestType, bRequest, ++ wValue, wIndex, wLength); ++ break; ++ case USB_TYPE_VENDOR: ++ case USB_TYPE_CLASS: ++ default: ++ usb_decode_ctrl_generic(str, size, bRequestType, bRequest, ++ wValue, wIndex, wLength); ++ break; + } + + return str; +-- +2.35.1 + diff --git a/queue-5.19/usb-dwc3-core-add-gfladj_refclk_lpm_sel-quirk.patch b/queue-5.19/usb-dwc3-core-add-gfladj_refclk_lpm_sel-quirk.patch new file mode 100644 index 00000000000..a37a88bf2ad --- /dev/null +++ b/queue-5.19/usb-dwc3-core-add-gfladj_refclk_lpm_sel-quirk.patch @@ -0,0 +1,78 @@ +From 43856d383c7003d1052bf10452ecda8a6743f8b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Sep 2022 08:28:53 +0200 +Subject: usb: dwc3: core: add gfladj_refclk_lpm_sel quirk + +From: Alexander Stein + +[ Upstream commit a6fc2f1b092787e9d7dbe472d720cede81680315 ] + +This selects the SOF/ITP counter be running on ref_clk. As documented +U2_FREECLK_EXISTS has to be set to 0 as well. + +Reviewed-by: Li Jun +Signed-off-by: Alexander Stein +Link: https://lore.kernel.org/r/20220915062855.751881-3-alexander.stein@ew.tq-group.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.c | 8 +++++++- + drivers/usb/dwc3/core.h | 2 ++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 2419ef828f9b..02733b6a9061 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -407,6 +407,10 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc) + reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj) + | FIELD_PREP(DWC3_GFLADJ_240MHZDECR, decr >> 1) + | FIELD_PREP(DWC3_GFLADJ_240MHZDECR_PLS1, decr & 1); ++ ++ if (dwc->gfladj_refclk_lpm_sel) ++ reg |= DWC3_GFLADJ_REFCLK_LPM_SEL; ++ + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); + } + +@@ -788,7 +792,7 @@ static int dwc3_phy_setup(struct dwc3 *dwc) + else + reg |= DWC3_GUSB2PHYCFG_ENBLSLPM; + +- if (dwc->dis_u2_freeclk_exists_quirk) ++ if (dwc->dis_u2_freeclk_exists_quirk || dwc->gfladj_refclk_lpm_sel) + reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; + + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); +@@ -1490,6 +1494,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) + "snps,dis-tx-ipgap-linecheck-quirk"); + dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, + "snps,parkmode-disable-ss-quirk"); ++ dwc->gfladj_refclk_lpm_sel = device_property_read_bool(dev, ++ "snps,gfladj-refclk-lpm-sel-quirk"); + + dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, + "snps,tx_de_emphasis_quirk"); +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 81c486b3941c..725fb17e4a9e 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -390,6 +390,7 @@ + #define DWC3_GFLADJ_30MHZ_SDBND_SEL BIT(7) + #define DWC3_GFLADJ_30MHZ_MASK 0x3f + #define DWC3_GFLADJ_REFCLK_FLADJ_MASK GENMASK(21, 8) ++#define DWC3_GFLADJ_REFCLK_LPM_SEL BIT(23) + #define DWC3_GFLADJ_240MHZDECR GENMASK(30, 24) + #define DWC3_GFLADJ_240MHZDECR_PLS1 BIT(31) + +@@ -1309,6 +1310,7 @@ struct dwc3 { + unsigned dis_del_phy_power_chg_quirk:1; + unsigned dis_tx_ipgap_linecheck_quirk:1; + unsigned parkmode_disable_ss_quirk:1; ++ unsigned gfladj_refclk_lpm_sel:1; + + unsigned tx_de_emphasis_quirk:1; + unsigned tx_de_emphasis:2; +-- +2.35.1 + diff --git a/queue-5.19/usb-dwc3-core-enable-guctl1-bit-10-for-fixing-termin.patch b/queue-5.19/usb-dwc3-core-enable-guctl1-bit-10-for-fixing-termin.patch new file mode 100644 index 00000000000..9616f270f26 --- /dev/null +++ b/queue-5.19/usb-dwc3-core-enable-guctl1-bit-10-for-fixing-termin.patch @@ -0,0 +1,98 @@ +From 016474eae0772c15614ae6476c7cd177fe5b4f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 10:52:35 +0530 +Subject: usb: dwc3: core: Enable GUCTL1 bit 10 for fixing termination error + after resume bug + +From: Piyush Mehta + +[ Upstream commit 63d7f9810a38102cdb8cad214fac98682081e1a7 ] + +When configured in HOST mode, after issuing U3/L2 exit controller fails +to send proper CRC checksum in CRC5 field. Because of this behavior +Transaction Error is generated, resulting in reset and re-enumeration of +usb device attached. Enabling chicken bit 10 of GUCTL1 will correct this +problem. + +When this bit is set to '1', the UTMI/ULPI opmode will be changed to +"normal" along with HS terminations, term, and xcvr signals after EOR. +This option is to support certain legacy UTMI/ULPI PHYs. + +Added "snps,resume-hs-terminations" quirk to resolved the above issue. + +Signed-off-by: Piyush Mehta +Link: https://lore.kernel.org/r/20220920052235.194272-3-piyush.mehta@amd.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.c | 17 +++++++++++++++++ + drivers/usb/dwc3/core.h | 4 ++++ + 2 files changed, 21 insertions(+) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index 02733b6a9061..21fa2e2795d8 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1149,6 +1149,21 @@ static int dwc3_core_init(struct dwc3 *dwc) + dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + } + ++ /* ++ * When configured in HOST mode, after issuing U3/L2 exit controller ++ * fails to send proper CRC checksum in CRC5 feild. Because of this ++ * behaviour Transaction Error is generated, resulting in reset and ++ * re-enumeration of usb device attached. All the termsel, xcvrsel, ++ * opmode becomes 0 during end of resume. Enabling bit 10 of GUCTL1 ++ * will correct this problem. This option is to support certain ++ * legacy ULPI PHYs. ++ */ ++ if (dwc->resume_hs_terminations) { ++ reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); ++ reg |= DWC3_GUCTL1_RESUME_OPMODE_HS_HOST; ++ dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); ++ } ++ + if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) { + reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); + +@@ -1492,6 +1507,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) + "snps,dis-del-phy-power-chg-quirk"); + dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, + "snps,dis-tx-ipgap-linecheck-quirk"); ++ dwc->resume_hs_terminations = device_property_read_bool(dev, ++ "snps,resume-hs-terminations"); + dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, + "snps,parkmode-disable-ss-quirk"); + dwc->gfladj_refclk_lpm_sel = device_property_read_bool(dev, +diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h +index 725fb17e4a9e..b9fa0fa5ba7c 100644 +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -262,6 +262,7 @@ + #define DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK BIT(26) + #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW BIT(24) + #define DWC3_GUCTL1_PARKMODE_DISABLE_SS BIT(17) ++#define DWC3_GUCTL1_RESUME_OPMODE_HS_HOST BIT(10) + + /* Global Status Register */ + #define DWC3_GSTS_OTG_IP BIT(10) +@@ -1094,6 +1095,8 @@ struct dwc3_scratchpad_array { + * change quirk. + * @dis_tx_ipgap_linecheck_quirk: set if we disable u2mac linestate + * check during HS transmit. ++ * @resume-hs-terminations: Set if we enable quirk for fixing improper crc ++ * generation after resume from suspend. + * @parkmode_disable_ss_quirk: set if we need to disable all SuperSpeed + * instances in park mode. + * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk +@@ -1309,6 +1312,7 @@ struct dwc3 { + unsigned dis_u2_freeclk_exists_quirk:1; + unsigned dis_del_phy_power_chg_quirk:1; + unsigned dis_tx_ipgap_linecheck_quirk:1; ++ unsigned resume_hs_terminations:1; + unsigned parkmode_disable_ss_quirk:1; + unsigned gfladj_refclk_lpm_sel:1; + +-- +2.35.1 + diff --git a/queue-5.19/usb-dwc3-core-fix-some-leaks-in-probe.patch b/queue-5.19/usb-dwc3-core-fix-some-leaks-in-probe.patch new file mode 100644 index 00000000000..65eb277bf6c --- /dev/null +++ b/queue-5.19/usb-dwc3-core-fix-some-leaks-in-probe.patch @@ -0,0 +1,130 @@ +From 2c076a446d68e4d8ab1befde779e63d87e8e3cce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 14:22:08 +0300 +Subject: usb: dwc3: core: fix some leaks in probe + +From: Dan Carpenter + +[ Upstream commit 2a735e4b5580a2a6bbd6572109b4c4f163c57462 ] + +The dwc3_get_properties() function calls: + + dwc->usb_psy = power_supply_get_by_name(usb_psy_name); + +so there is some additional clean up required on these error paths. + +Fixes: 6f0764b5adea ("usb: dwc3: add a power supply for current control") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/YyxFYFnP53j9sCg+@kili +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/core.c | 58 +++++++++++++++++++++++++---------------- + 1 file changed, 36 insertions(+), 22 deletions(-) + +diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c +index ebf3afad378b..2419ef828f9b 100644 +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1678,8 +1678,10 @@ static int dwc3_probe(struct platform_device *pdev) + dwc3_get_properties(dwc); + + dwc->reset = devm_reset_control_array_get_optional_shared(dev); +- if (IS_ERR(dwc->reset)) +- return PTR_ERR(dwc->reset); ++ if (IS_ERR(dwc->reset)) { ++ ret = PTR_ERR(dwc->reset); ++ goto put_usb_psy; ++ } + + if (dev->of_node) { + /* +@@ -1689,45 +1691,57 @@ static int dwc3_probe(struct platform_device *pdev) + * check for them to retain backwards compatibility. + */ + dwc->bus_clk = devm_clk_get_optional(dev, "bus_early"); +- if (IS_ERR(dwc->bus_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), +- "could not get bus clock\n"); ++ if (IS_ERR(dwc->bus_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk), ++ "could not get bus clock\n"); ++ goto put_usb_psy; ++ } + + if (dwc->bus_clk == NULL) { + dwc->bus_clk = devm_clk_get_optional(dev, "bus_clk"); +- if (IS_ERR(dwc->bus_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->bus_clk), +- "could not get bus clock\n"); ++ if (IS_ERR(dwc->bus_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->bus_clk), ++ "could not get bus clock\n"); ++ goto put_usb_psy; ++ } + } + + dwc->ref_clk = devm_clk_get_optional(dev, "ref"); +- if (IS_ERR(dwc->ref_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), +- "could not get ref clock\n"); ++ if (IS_ERR(dwc->ref_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk), ++ "could not get ref clock\n"); ++ goto put_usb_psy; ++ } + + if (dwc->ref_clk == NULL) { + dwc->ref_clk = devm_clk_get_optional(dev, "ref_clk"); +- if (IS_ERR(dwc->ref_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->ref_clk), +- "could not get ref clock\n"); ++ if (IS_ERR(dwc->ref_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->ref_clk), ++ "could not get ref clock\n"); ++ goto put_usb_psy; ++ } + } + + dwc->susp_clk = devm_clk_get_optional(dev, "suspend"); +- if (IS_ERR(dwc->susp_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), +- "could not get suspend clock\n"); ++ if (IS_ERR(dwc->susp_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk), ++ "could not get suspend clock\n"); ++ goto put_usb_psy; ++ } + + if (dwc->susp_clk == NULL) { + dwc->susp_clk = devm_clk_get_optional(dev, "suspend_clk"); +- if (IS_ERR(dwc->susp_clk)) +- return dev_err_probe(dev, PTR_ERR(dwc->susp_clk), +- "could not get suspend clock\n"); ++ if (IS_ERR(dwc->susp_clk)) { ++ ret = dev_err_probe(dev, PTR_ERR(dwc->susp_clk), ++ "could not get suspend clock\n"); ++ goto put_usb_psy; ++ } + } + } + + ret = reset_control_deassert(dwc->reset); + if (ret) +- return ret; ++ goto put_usb_psy; + + ret = dwc3_clk_enable(dwc); + if (ret) +@@ -1827,7 +1841,7 @@ static int dwc3_probe(struct platform_device *pdev) + dwc3_clk_disable(dwc); + assert_reset: + reset_control_assert(dwc->reset); +- ++put_usb_psy: + if (dwc->usb_psy) + power_supply_put(dwc->usb_psy); + +-- +2.35.1 + diff --git a/queue-5.19/usb-gadget-f_fs-stricter-integer-overflow-checks.patch b/queue-5.19/usb-gadget-f_fs-stricter-integer-overflow-checks.patch new file mode 100644 index 00000000000..f9734d4ea29 --- /dev/null +++ b/queue-5.19/usb-gadget-f_fs-stricter-integer-overflow-checks.patch @@ -0,0 +1,47 @@ +From a3366292f5582c9f301fde16db3674fb14af4026 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 17:59:42 +0300 +Subject: usb: gadget: f_fs: stricter integer overflow checks + +From: Dan Carpenter + +[ Upstream commit f57004b9d96755cd6a243b51c267be4016b4563c ] + +This from static analysis. The vla_item() takes a size and adds it to +the total. It has a built in integer overflow check so if it encounters +an integer overflow anywhere then it records the total as SIZE_MAX. + +However there is an issue here because the "lang_count*(needed_count+1)" +multiplication can overflow. Technically the "lang_count + 1" addition +could overflow too, but that would be detected and is harmless. Fix +both using the new size_add() and size_mul() functions. + +Fixes: e6f3862fa1ec ("usb: gadget: FunctionFS: Remove VLAIS usage from gadget code") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/YxDI3lMYomE7WCjn@kili +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/f_fs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c +index e0fa4b186ec6..36184a762527 100644 +--- a/drivers/usb/gadget/function/f_fs.c ++++ b/drivers/usb/gadget/function/f_fs.c +@@ -2645,10 +2645,10 @@ static int __ffs_data_got_strings(struct ffs_data *ffs, + unsigned i = 0; + vla_group(d); + vla_item(d, struct usb_gadget_strings *, stringtabs, +- lang_count + 1); ++ size_add(lang_count, 1)); + vla_item(d, struct usb_gadget_strings, stringtab, lang_count); + vla_item(d, struct usb_string, strings, +- lang_count*(needed_count+1)); ++ size_mul(lang_count, (needed_count + 1))); + + char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL); + +-- +2.35.1 + diff --git a/queue-5.19/usb-gadget-function-fix-dangling-pnp_string-in-f_pri.patch b/queue-5.19/usb-gadget-function-fix-dangling-pnp_string-in-f_pri.patch new file mode 100644 index 00000000000..36d5516eea8 --- /dev/null +++ b/queue-5.19/usb-gadget-function-fix-dangling-pnp_string-in-f_pri.patch @@ -0,0 +1,76 @@ +From af03cb182d2f43aab998b5dba7efebc025335026 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 11 Sep 2022 15:37:55 -0700 +Subject: usb: gadget: function: fix dangling pnp_string in f_printer.c + +From: Albert Briscoe + +[ Upstream commit 24b7ba2f88e04800b54d462f376512e8c41b8a3c ] + +When opts->pnp_string is changed with configfs, new memory is allocated for +the string. It does not, however, update dev->pnp_string, even though the +memory is freed. When rquesting the string, the host then gets old or +corrupted data rather than the new string. The ieee 1284 id string should +be allowed to change while the device is connected. + +The bug was introduced in commit fdc01cc286be ("usb: gadget: printer: +Remove pnp_string static buffer"), which changed opts->pnp_string from a +char[] to a char*. +This patch changes dev->pnp_string from a char* to a char** pointing to +opts->pnp_string. + +Fixes: fdc01cc286be ("usb: gadget: printer: Remove pnp_string static buffer") +Signed-off-by: Albert Briscoe +Link: https://lore.kernel.org/r/20220911223753.20417-1-albertsbriscoe@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/f_printer.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c +index abec5c58f525..a881c69b1f2b 100644 +--- a/drivers/usb/gadget/function/f_printer.c ++++ b/drivers/usb/gadget/function/f_printer.c +@@ -89,7 +89,7 @@ struct printer_dev { + u8 printer_cdev_open; + wait_queue_head_t wait; + unsigned q_len; +- char *pnp_string; /* We don't own memory! */ ++ char **pnp_string; /* We don't own memory! */ + struct usb_function function; + }; + +@@ -1000,16 +1000,16 @@ static int printer_func_setup(struct usb_function *f, + if ((wIndex>>8) != dev->interface) + break; + +- if (!dev->pnp_string) { ++ if (!*dev->pnp_string) { + value = 0; + break; + } +- value = strlen(dev->pnp_string); ++ value = strlen(*dev->pnp_string); + buf[0] = (value >> 8) & 0xFF; + buf[1] = value & 0xFF; +- memcpy(buf + 2, dev->pnp_string, value); ++ memcpy(buf + 2, *dev->pnp_string, value); + DBG(dev, "1284 PNP String: %x %s\n", value, +- dev->pnp_string); ++ *dev->pnp_string); + break; + + case GET_PORT_STATUS: /* Get Port Status */ +@@ -1475,7 +1475,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi) + kref_init(&dev->kref); + ++opts->refcnt; + dev->minor = opts->minor; +- dev->pnp_string = opts->pnp_string; ++ dev->pnp_string = &opts->pnp_string; + dev->q_len = opts->q_len; + mutex_unlock(&opts->lock); + +-- +2.35.1 + diff --git a/queue-5.19/usb-gadget-uvc-increase-worker-prio-to-wq_highpri.patch b/queue-5.19/usb-gadget-uvc-increase-worker-prio-to-wq_highpri.patch new file mode 100644 index 00000000000..e2a12040e4d --- /dev/null +++ b/queue-5.19/usb-gadget-uvc-increase-worker-prio-to-wq_highpri.patch @@ -0,0 +1,107 @@ +From 01c0737d860b906da5e4033484ad06ffbcf57778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 23:58:18 +0200 +Subject: usb: gadget: uvc: increase worker prio to WQ_HIGHPRI + +From: Michael Grzeschik + +[ Upstream commit 9b91a65230784a9ef644b8bdbb82a79ba4ae9456 ] + +This patch is changing the simple workqueue in the gadget driver to be +allocated as async_wq with a higher priority. The pump worker, that is +filling the usb requests, will have a higher priority and will not be +scheduled away so often while the video stream is handled. This will +lead to fewer streaming underruns. + +Signed-off-by: Michael Grzeschik +Link: https://lore.kernel.org/r/20220907215818.2670097-1-m.grzeschik@pengutronix.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/gadget/function/f_uvc.c | 4 ++++ + drivers/usb/gadget/function/uvc.h | 1 + + drivers/usb/gadget/function/uvc_v4l2.c | 2 +- + drivers/usb/gadget/function/uvc_video.c | 9 +++++++-- + 4 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c +index 86bb0098fb66..7ec223849d94 100644 +--- a/drivers/usb/gadget/function/f_uvc.c ++++ b/drivers/usb/gadget/function/f_uvc.c +@@ -897,10 +897,14 @@ static void uvc_function_unbind(struct usb_configuration *c, + { + struct usb_composite_dev *cdev = c->cdev; + struct uvc_device *uvc = to_uvc(f); ++ struct uvc_video *video = &uvc->video; + long wait_ret = 1; + + uvcg_info(f, "%s()\n", __func__); + ++ if (video->async_wq) ++ destroy_workqueue(video->async_wq); ++ + /* + * If we know we're connected via v4l2, then there should be a cleanup + * of the device from userspace either via UVC_EVENT_DISCONNECT or +diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h +index 58e383afdd44..1a31e6c6a5ff 100644 +--- a/drivers/usb/gadget/function/uvc.h ++++ b/drivers/usb/gadget/function/uvc.h +@@ -88,6 +88,7 @@ struct uvc_video { + struct usb_ep *ep; + + struct work_struct pump; ++ struct workqueue_struct *async_wq; + + /* Frame parameters */ + u8 bpp; +diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c +index fd8f73bb726d..fddc392b8ab9 100644 +--- a/drivers/usb/gadget/function/uvc_v4l2.c ++++ b/drivers/usb/gadget/function/uvc_v4l2.c +@@ -170,7 +170,7 @@ uvc_v4l2_qbuf(struct file *file, void *fh, struct v4l2_buffer *b) + return ret; + + if (uvc->state == UVC_STATE_STREAMING) +- schedule_work(&video->pump); ++ queue_work(video->async_wq, &video->pump); + + return ret; + } +diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c +index c00ce0e91f5d..bb037fcc90e6 100644 +--- a/drivers/usb/gadget/function/uvc_video.c ++++ b/drivers/usb/gadget/function/uvc_video.c +@@ -277,7 +277,7 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) + spin_unlock_irqrestore(&video->req_lock, flags); + + if (uvc->state == UVC_STATE_STREAMING) +- schedule_work(&video->pump); ++ queue_work(video->async_wq, &video->pump); + } + + static int +@@ -485,7 +485,7 @@ int uvcg_video_enable(struct uvc_video *video, int enable) + + video->req_int_count = 0; + +- schedule_work(&video->pump); ++ queue_work(video->async_wq, &video->pump); + + return ret; + } +@@ -499,6 +499,11 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) + spin_lock_init(&video->req_lock); + INIT_WORK(&video->pump, uvcg_video_pump); + ++ /* Allocate a work queue for asynchronous video pump handler. */ ++ video->async_wq = alloc_workqueue("uvcgadget", WQ_UNBOUND | WQ_HIGHPRI, 0); ++ if (!video->async_wq) ++ return -EINVAL; ++ + video->uvc = uvc; + video->fcc = V4L2_PIX_FMT_YUYV; + video->bpp = 16; +-- +2.35.1 + diff --git a/queue-5.19/usb-host-xhci-fix-potential-memory-leak-in-xhci_allo.patch b/queue-5.19/usb-host-xhci-fix-potential-memory-leak-in-xhci_allo.patch new file mode 100644 index 00000000000..e2b4ed0daab --- /dev/null +++ b/queue-5.19/usb-host-xhci-fix-potential-memory-leak-in-xhci_allo.patch @@ -0,0 +1,56 @@ +From 626e3665dbe6af9b28719bc4859388a00e38b67d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 15:34:45 +0300 +Subject: usb: host: xhci: Fix potential memory leak in + xhci_alloc_stream_info() + +From: Jianglei Nie + +[ Upstream commit 7e271f42a5cc3768cd2622b929ba66859ae21f97 ] + +xhci_alloc_stream_info() allocates stream context array for stream_info +->stream_ctx_array with xhci_alloc_stream_ctx(). When some error occurs, +stream_info->stream_ctx_array is not released, which will lead to a +memory leak. + +We can fix it by releasing the stream_info->stream_ctx_array with +xhci_free_stream_ctx() on the error path to avoid the potential memory +leak. + +Signed-off-by: Jianglei Nie +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220921123450.671459-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-mem.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c +index 8c19e151a945..9e56aa28efcd 100644 +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -641,7 +641,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, + num_stream_ctxs, &stream_info->ctx_array_dma, + mem_flags); + if (!stream_info->stream_ctx_array) +- goto cleanup_ctx; ++ goto cleanup_ring_array; + memset(stream_info->stream_ctx_array, 0, + sizeof(struct xhci_stream_ctx)*num_stream_ctxs); + +@@ -702,6 +702,11 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, + } + xhci_free_command(xhci, stream_info->free_streams_command); + cleanup_ctx: ++ xhci_free_stream_ctx(xhci, ++ stream_info->num_stream_ctxs, ++ stream_info->stream_ctx_array, ++ stream_info->ctx_array_dma); ++cleanup_ring_array: + kfree(stream_info->stream_rings); + cleanup_info: + kfree(stream_info); +-- +2.35.1 + diff --git a/queue-5.19/usb-host-xhci-plat-suspend-and-resume-clocks.patch b/queue-5.19/usb-host-xhci-plat-suspend-and-resume-clocks.patch new file mode 100644 index 00000000000..3999c53d538 --- /dev/null +++ b/queue-5.19/usb-host-xhci-plat-suspend-and-resume-clocks.patch @@ -0,0 +1,72 @@ +From 2adc34e8ea3b57826b437bdad232efa11aeec4b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Aug 2022 15:27:34 -0700 +Subject: usb: host: xhci-plat: suspend and resume clocks + +From: Justin Chen + +[ Upstream commit 8bd954c56197caf5e3a804d989094bc3fe6329aa ] + +Introduce XHCI_SUSPEND_RESUME_CLKS quirk as a means to suspend and resume +clocks if the hardware is capable of doing so. We assume that clocks will +be needed if the device may wake. + +Reviewed-by: Florian Fainelli +Signed-off-by: Justin Chen +Link: https://lore.kernel.org/r/1660170455-15781-2-git-send-email-justinpopo6@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-plat.c | 16 +++++++++++++++- + drivers/usb/host/xhci.h | 1 + + 2 files changed, 16 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index a8641b6536ee..ef10982ad482 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -437,7 +437,16 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) + * xhci_suspend() needs `do_wakeup` to know whether host is allowed + * to do wakeup during suspend. + */ +- return xhci_suspend(xhci, device_may_wakeup(dev)); ++ ret = xhci_suspend(xhci, device_may_wakeup(dev)); ++ if (ret) ++ return ret; ++ ++ if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) { ++ clk_disable_unprepare(xhci->clk); ++ clk_disable_unprepare(xhci->reg_clk); ++ } ++ ++ return 0; + } + + static int __maybe_unused xhci_plat_resume(struct device *dev) +@@ -446,6 +455,11 @@ static int __maybe_unused xhci_plat_resume(struct device *dev) + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + int ret; + ++ if (!device_may_wakeup(dev) && (xhci->quirks & XHCI_SUSPEND_RESUME_CLKS)) { ++ clk_prepare_enable(xhci->clk); ++ clk_prepare_enable(xhci->reg_clk); ++ } ++ + ret = xhci_priv_resume_quirk(hcd); + if (ret) + return ret; +diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h +index 7caa0db5e826..6dfbf73ee840 100644 +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1899,6 +1899,7 @@ struct xhci_hcd { + #define XHCI_NO_SOFT_RETRY BIT_ULL(40) + #define XHCI_BROKEN_D3COLD BIT_ULL(41) + #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) ++#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) + + unsigned int num_active_eps; + unsigned int limit_active_eps; +-- +2.35.1 + diff --git a/queue-5.19/usb-host-xhci-plat-suspend-resume-clks-for-brcm.patch b/queue-5.19/usb-host-xhci-plat-suspend-resume-clks-for-brcm.patch new file mode 100644 index 00000000000..d39a7f3cd5d --- /dev/null +++ b/queue-5.19/usb-host-xhci-plat-suspend-resume-clks-for-brcm.patch @@ -0,0 +1,38 @@ +From d14d257f3f632a03fc832b81b397e975fcc763c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Aug 2022 15:27:35 -0700 +Subject: usb: host: xhci-plat: suspend/resume clks for brcm + +From: Justin Chen + +[ Upstream commit c69400b09e471a3f1167adead55a808f0da6534a ] + +The xhci_plat_brcm xhci block can enter suspend with clock disabled to save +power and re-enable them on resume. Make use of the XHCI_SUSPEND_RESUME_CLKS +quirk to do so. + +Reviewed-by: Florian Fainelli +Signed-off-by: Justin Chen +Link: https://lore.kernel.org/r/1660170455-15781-3-git-send-email-justinpopo6@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci-plat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c +index ef10982ad482..5fb55bf19493 100644 +--- a/drivers/usb/host/xhci-plat.c ++++ b/drivers/usb/host/xhci-plat.c +@@ -123,7 +123,7 @@ static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = { + }; + + static const struct xhci_plat_priv xhci_plat_brcm = { +- .quirks = XHCI_RESET_ON_RESUME, ++ .quirks = XHCI_RESET_ON_RESUME | XHCI_SUSPEND_RESUME_CLKS, + }; + + static const struct of_device_id usb_xhci_of_match[] = { +-- +2.35.1 + diff --git a/queue-5.19/usb-idmouse-fix-an-uninit-value-in-idmouse_open.patch b/queue-5.19/usb-idmouse-fix-an-uninit-value-in-idmouse_open.patch new file mode 100644 index 00000000000..56627ad50cf --- /dev/null +++ b/queue-5.19/usb-idmouse-fix-an-uninit-value-in-idmouse_open.patch @@ -0,0 +1,59 @@ +From 62934d9a1a7756c691be05e697dfd66d68817438 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 21:48:44 +0800 +Subject: usb: idmouse: fix an uninit-value in idmouse_open + +From: Dongliang Mu + +[ Upstream commit bce2b0539933e485d22d6f6f076c0fcd6f185c4c ] + +In idmouse_create_image, if any ftip_command fails, it will +go to the reset label. However, this leads to the data in +bulk_in_buffer[HEADER..IMGSIZE] uninitialized. And the check +for valid image incurs an uninitialized dereference. + +Fix this by moving the check before reset label since this +check only be valid if the data after bulk_in_buffer[HEADER] +has concrete data. + +Note that this is found by KMSAN, so only kernel compilation +is tested. + +Reported-by: syzbot+79832d33eb89fb3cd092@syzkaller.appspotmail.com +Signed-off-by: Dongliang Mu +Link: https://lore.kernel.org/r/20220922134847.1101921-1-dzm91@hust.edu.cn +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/misc/idmouse.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c +index e9437a176518..ea39243efee3 100644 +--- a/drivers/usb/misc/idmouse.c ++++ b/drivers/usb/misc/idmouse.c +@@ -177,10 +177,6 @@ static int idmouse_create_image(struct usb_idmouse *dev) + bytes_read += bulk_read; + } + +- /* reset the device */ +-reset: +- ftip_command(dev, FTIP_RELEASE, 0, 0); +- + /* check for valid image */ + /* right border should be black (0x00) */ + for (bytes_read = sizeof(HEADER)-1 + WIDTH-1; bytes_read < IMGSIZE; bytes_read += WIDTH) +@@ -192,6 +188,10 @@ static int idmouse_create_image(struct usb_idmouse *dev) + if (dev->bulk_in_buffer[bytes_read] != 0xFF) + return -EAGAIN; + ++ /* reset the device */ ++reset: ++ ftip_command(dev, FTIP_RELEASE, 0, 0); ++ + /* should be IMGSIZE == 65040 */ + dev_dbg(&dev->interface->dev, "read %d bytes fingerprint data\n", + bytes_read); +-- +2.35.1 + diff --git a/queue-5.19/usb-mtu3-fix-failed-runtime-suspend-in-host-only-mod.patch b/queue-5.19/usb-mtu3-fix-failed-runtime-suspend-in-host-only-mod.patch new file mode 100644 index 00000000000..5a1d5130884 --- /dev/null +++ b/queue-5.19/usb-mtu3-fix-failed-runtime-suspend-in-host-only-mod.patch @@ -0,0 +1,55 @@ +From 8735dbc91c7027bfd7471d02a8d8dba7e993d862 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Sep 2022 14:44:59 +0800 +Subject: usb: mtu3: fix failed runtime suspend in host only mode + +From: Chunfeng Yun + +[ Upstream commit 1c703e29da5efac6180e4c189029fa34b7e48e97 ] + +When the dr_mode is "host", after the host enter runtime suspend, +the mtu3 can't do it, because the mtu3's device wakeup function is +not enabled, instead it's enabled in gadget init function, to fix +the issue, init wakeup early in mtu3's probe() + +Fixes: 6b587394c65c ("usb: mtu3: support suspend/resume for dual-role mode") +Reviewed-by: AngeloGioacchino Del Regno +Reported-by: Tianping Fang +Signed-off-by: Chunfeng Yun +Link: https://lore.kernel.org/r/20220929064459.32522-1-chunfeng.yun@mediatek.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/mtu3/mtu3_core.c | 2 -- + drivers/usb/mtu3/mtu3_plat.c | 2 ++ + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c +index c4a2c37abf62..3ea5145a842b 100644 +--- a/drivers/usb/mtu3/mtu3_core.c ++++ b/drivers/usb/mtu3/mtu3_core.c +@@ -971,8 +971,6 @@ int ssusb_gadget_init(struct ssusb_mtk *ssusb) + goto irq_err; + } + +- device_init_wakeup(dev, true); +- + /* power down device IP for power saving by default */ + mtu3_stop(mtu); + +diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c +index 4309ed939178..845b25320fd2 100644 +--- a/drivers/usb/mtu3/mtu3_plat.c ++++ b/drivers/usb/mtu3/mtu3_plat.c +@@ -332,6 +332,8 @@ static int mtu3_probe(struct platform_device *pdev) + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + ++ device_init_wakeup(dev, true); ++ + ret = ssusb_rscs_init(ssusb); + if (ret) + goto comm_init_err; +-- +2.35.1 + diff --git a/queue-5.19/usb-musb-fix-musb_gadget.c-rxstate-overflow-bug.patch b/queue-5.19/usb-musb-fix-musb_gadget.c-rxstate-overflow-bug.patch new file mode 100644 index 00000000000..7d1d122eb38 --- /dev/null +++ b/queue-5.19/usb-musb-fix-musb_gadget.c-rxstate-overflow-bug.patch @@ -0,0 +1,42 @@ +From 1ba497173523877e92f51f0c98ab2bace1856a3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 10:21:19 +0800 +Subject: usb: musb: Fix musb_gadget.c rxstate overflow bug + +From: Robin Guo + +[ Upstream commit eea4c860c3b366369eff0489d94ee4f0571d467d ] + +The usb function device call musb_gadget_queue() adds the passed +request to musb_ep::req_list,If the (request->length > musb_ep->packet_sz) +and (is_buffer_mapped(req) return false),the rxstate() will copy all data +in fifo to request->buf which may cause request->buf out of bounds. + +Fix it by add the length check : +fifocnt = min_t(unsigned, request->length - request->actual, fifocnt); + +Signed-off-by: Robin Guo +Link: https://lore.kernel.org/r/20220906102119.1b071d07a8391ff115e6d1ef@inspur.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/musb/musb_gadget.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c +index 51274b87f46c..dc67fff8e941 100644 +--- a/drivers/usb/musb/musb_gadget.c ++++ b/drivers/usb/musb/musb_gadget.c +@@ -760,6 +760,9 @@ static void rxstate(struct musb *musb, struct musb_request *req) + musb_writew(epio, MUSB_RXCSR, csr); + + buffer_aint_mapped: ++ fifo_count = min_t(unsigned int, ++ request->length - request->actual, ++ (unsigned int)fifo_count); + musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) + (request->buf + request->actual)); + request->actual += fifo_count; +-- +2.35.1 + diff --git a/queue-5.19/usb-serial-console-move-mutex_unlock-before-usb_seri.patch b/queue-5.19/usb-serial-console-move-mutex_unlock-before-usb_seri.patch new file mode 100644 index 00000000000..6d05a955bda --- /dev/null +++ b/queue-5.19/usb-serial-console-move-mutex_unlock-before-usb_seri.patch @@ -0,0 +1,39 @@ +From a3d6eb0e59c646e0f627088507c2074e03d08b01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 18:48:24 +0800 +Subject: USB: serial: console: move mutex_unlock() before usb_serial_put() + +From: Liang He + +[ Upstream commit 61dfa797c731754642d1ac500a6ac42f9b47f920 ] + +While in current version there is no use-after-free as USB serial +core holds another reference when the console is registered, we +should better unlock before dropping the reference in +usb_console_setup(). + +Fixes: 7bd032dc2793 ("USB serial: update the console driver") +Signed-off-by: Liang He +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/usb/serial/console.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c +index b97aa40ca4d1..da19a5fa414f 100644 +--- a/drivers/usb/serial/console.c ++++ b/drivers/usb/serial/console.c +@@ -189,8 +189,8 @@ static int usb_console_setup(struct console *co, char *options) + info->port = NULL; + usb_autopm_put_interface(serial->interface); + error_get_interface: +- usb_serial_put(serial); + mutex_unlock(&serial->disc_mutex); ++ usb_serial_put(serial); + return retval; + } + +-- +2.35.1 + diff --git a/queue-5.19/usb-typec-ucsi-don-t-warn-on-probe-deferral.patch b/queue-5.19/usb-typec-ucsi-don-t-warn-on-probe-deferral.patch new file mode 100644 index 00000000000..6f865225bc6 --- /dev/null +++ b/queue-5.19/usb-typec-ucsi-don-t-warn-on-probe-deferral.patch @@ -0,0 +1,50 @@ +From 6f541fb6111bf866cf92abcd4f2c06d2e18aea42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 27 Sep 2022 21:45:12 +0800 +Subject: usb: typec: ucsi: Don't warn on probe deferral + +From: Wayne Chang + +[ Upstream commit fce703a991b7e8c7e1371de95b9abaa832ecf9c3 ] + +Deferred probe is an expected return value for fwnode_usb_role_switch_get(). +Given that the driver deals with it properly, there's no need to output a +warning that may potentially confuse users. + +-- +V2 -> V3: remove the Fixes and Cc +V1 -> V2: adjust the coding style for better reading format. + drivers/usb/typec/ucsi/ucsi.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +Signed-off-by: Wayne Chang +Acked-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20220927134512.2651067-1-waynec@nvidia.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/typec/ucsi/ucsi.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c +index 6364f0d467ea..74fb5a4c6f21 100644 +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1067,11 +1067,9 @@ static int ucsi_register_port(struct ucsi *ucsi, int index) + + cap->fwnode = ucsi_find_fwnode(con); + con->usb_role_sw = fwnode_usb_role_switch_get(cap->fwnode); +- if (IS_ERR(con->usb_role_sw)) { +- dev_err(ucsi->dev, "con%d: failed to get usb role switch\n", +- con->num); +- return PTR_ERR(con->usb_role_sw); +- } ++ if (IS_ERR(con->usb_role_sw)) ++ return dev_err_probe(ucsi->dev, PTR_ERR(con->usb_role_sw), ++ "con%d: failed to get usb role switch\n", con->num); + + /* Delay other interactions with the con until registration is complete */ + mutex_lock(&con->lock); +-- +2.35.1 + diff --git a/queue-5.19/userfaultfd-open-userfaultfds-with-o_rdonly.patch b/queue-5.19/userfaultfd-open-userfaultfds-with-o_rdonly.patch new file mode 100644 index 00000000000..5b785883dde --- /dev/null +++ b/queue-5.19/userfaultfd-open-userfaultfds-with-o_rdonly.patch @@ -0,0 +1,57 @@ +From 9afcacde396ba8af5288b9294846611c50fde099 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Jul 2022 11:34:51 +0200 +Subject: userfaultfd: open userfaultfds with O_RDONLY + +From: Ondrej Mosnacek + +[ Upstream commit abec3d015fdfb7c63105c7e1c956188bf381aa55 ] + +Since userfaultfd doesn't implement a write operation, it is more +appropriate to open it read-only. + +When userfaultfds are opened read-write like it is now, and such fd is +passed from one process to another, SELinux will check both read and +write permissions for the target process, even though it can't actually +do any write operation on the fd later. + +Inspired by the following bug report, which has hit the SELinux scenario +described above: +https://bugzilla.redhat.com/show_bug.cgi?id=1974559 + +Reported-by: Robert O'Callahan +Fixes: 86039bd3b4e6 ("userfaultfd: add new syscall to provide memory externalization") +Signed-off-by: Ondrej Mosnacek +Acked-by: Peter Xu +Acked-by: Christian Brauner (Microsoft) +Signed-off-by: Paul Moore +Signed-off-by: Sasha Levin +--- + fs/userfaultfd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index ab0576d372d6..fa0a2fa5debb 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -991,7 +991,7 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *new, + int fd; + + fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, new, +- O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS), inode); ++ O_RDONLY | (new->flags & UFFD_SHARED_FCNTL_FLAGS), inode); + if (fd < 0) + return fd; + +@@ -2096,7 +2096,7 @@ SYSCALL_DEFINE1(userfaultfd, int, flags) + mmgrab(ctx->mm); + + fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, ctx, +- O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS), NULL); ++ O_RDONLY | (flags & UFFD_SHARED_FCNTL_FLAGS), NULL); + if (fd < 0) { + mmdrop(ctx->mm); + kmem_cache_free(userfaultfd_ctx_cachep, ctx); +-- +2.35.1 + diff --git a/queue-5.19/vhost-vsock-use-kvmalloc-kvfree-for-larger-packets.patch b/queue-5.19/vhost-vsock-use-kvmalloc-kvfree-for-larger-packets.patch new file mode 100644 index 00000000000..ff560551f9d --- /dev/null +++ b/queue-5.19/vhost-vsock-use-kvmalloc-kvfree-for-larger-packets.patch @@ -0,0 +1,73 @@ +From 54ace58c5ba3f2cd9865c73d5f3555a9cce60e27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 28 Sep 2022 15:45:38 +0900 +Subject: vhost/vsock: Use kvmalloc/kvfree for larger packets. + +From: Junichi Uekawa + +[ Upstream commit 0e3f72931fc47bb81686020cc643cde5d9cd0bb8 ] + +When copying a large file over sftp over vsock, data size is usually 32kB, +and kmalloc seems to fail to try to allocate 32 32kB regions. + + vhost-5837: page allocation failure: order:4, mode:0x24040c0 + Call Trace: + [] dump_stack+0x97/0xdb + [] warn_alloc_failed+0x10f/0x138 + [] ? __alloc_pages_direct_compact+0x38/0xc8 + [] __alloc_pages_nodemask+0x84c/0x90d + [] alloc_kmem_pages+0x17/0x19 + [] kmalloc_order_trace+0x2b/0xdb + [] __kmalloc+0x177/0x1f7 + [] ? copy_from_iter+0x8d/0x31d + [] vhost_vsock_handle_tx_kick+0x1fa/0x301 [vhost_vsock] + [] vhost_worker+0xf7/0x157 [vhost] + [] kthread+0xfd/0x105 + [] ? vhost_dev_set_owner+0x22e/0x22e [vhost] + [] ? flush_kthread_worker+0xf3/0xf3 + [] ret_from_fork+0x4e/0x80 + [] ? flush_kthread_worker+0xf3/0xf3 + +Work around by doing kvmalloc instead. + +Fixes: 433fc58e6bf2 ("VSOCK: Introduce vhost_vsock.ko") +Signed-off-by: Junichi Uekawa +Reviewed-by: Stefano Garzarella +Acked-by: Michael S. Tsirkin +Link: https://lore.kernel.org/r/20220928064538.667678-1-uekawa@chromium.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/vhost/vsock.c | 2 +- + net/vmw_vsock/virtio_transport_common.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c +index 368330417bde..5703775af129 100644 +--- a/drivers/vhost/vsock.c ++++ b/drivers/vhost/vsock.c +@@ -393,7 +393,7 @@ vhost_vsock_alloc_pkt(struct vhost_virtqueue *vq, + return NULL; + } + +- pkt->buf = kmalloc(pkt->len, GFP_KERNEL); ++ pkt->buf = kvmalloc(pkt->len, GFP_KERNEL); + if (!pkt->buf) { + kfree(pkt); + return NULL; +diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c +index ec2c2afbf0d0..3a12aee33e92 100644 +--- a/net/vmw_vsock/virtio_transport_common.c ++++ b/net/vmw_vsock/virtio_transport_common.c +@@ -1342,7 +1342,7 @@ EXPORT_SYMBOL_GPL(virtio_transport_recv_pkt); + + void virtio_transport_free_pkt(struct virtio_vsock_pkt *pkt) + { +- kfree(pkt->buf); ++ kvfree(pkt->buf); + kfree(pkt); + } + EXPORT_SYMBOL_GPL(virtio_transport_free_pkt); +-- +2.35.1 + diff --git a/queue-5.19/virtio-gpu-fix-shift-wrapping-bug-in-virtio_gpu_fenc.patch b/queue-5.19/virtio-gpu-fix-shift-wrapping-bug-in-virtio_gpu_fenc.patch new file mode 100644 index 00000000000..1fce2fbb464 --- /dev/null +++ b/queue-5.19/virtio-gpu-fix-shift-wrapping-bug-in-virtio_gpu_fenc.patch @@ -0,0 +1,41 @@ +From b1b2edac81abae4d87ac7b60e6e5e158e1fae2d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 09:36:30 +0300 +Subject: virtio-gpu: fix shift wrapping bug in virtio_gpu_fence_event_create() + +From: Dan Carpenter + +[ Upstream commit 37a78445763a5921bb54e9bad01937d0dfa521c1 ] + +The ->ring_idx_mask variable is a u64 so static checkers, Smatch in +this case, complain if the BIT() is not also a u64. + +drivers/gpu/drm/virtio/virtgpu_ioctl.c:50 virtio_gpu_fence_event_create() +warn: should '(1 << ring_idx)' be a 64 bit type? + +Fixes: cd7f5ca33585 ("drm/virtio: implement context init: add virtio_gpu_fence_event") +Signed-off-by: Dan Carpenter +Reviewed-by: Chia-I Wu +Link: http://patchwork.freedesktop.org/patch/msgid/YygN7jY0GdUSQSy0@kili +Signed-off-by: Gerd Hoffmann +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/virtio/virtgpu_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +index 3b1701607aae..5d05093014ac 100644 +--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c ++++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c +@@ -47,7 +47,7 @@ static int virtio_gpu_fence_event_create(struct drm_device *dev, + struct virtio_gpu_fence_event *e = NULL; + int ret; + +- if (!(vfpriv->ring_idx_mask & (1 << ring_idx))) ++ if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx))) + return 0; + + e = kzalloc(sizeof(*e), GFP_KERNEL); +-- +2.35.1 + diff --git a/queue-5.19/wan-fix-syntax-errors-in-comments.patch b/queue-5.19/wan-fix-syntax-errors-in-comments.patch new file mode 100644 index 00000000000..92944bd27a1 --- /dev/null +++ b/queue-5.19/wan-fix-syntax-errors-in-comments.patch @@ -0,0 +1,36 @@ +From d892f48c82226f8775171ee6c23ebb6a81a977bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Jun 2022 12:09:17 +0800 +Subject: WAN: Fix syntax errors in comments + +From: Xiang wangx + +[ Upstream commit 6fa4a6d20c168fa83810f03b1c43e0cec69bbdbc ] + +Delete the redundant word 'the'. + +Signed-off-by: Xiang wangx +Link: https://lore.kernel.org/r/20220604040917.8926-1-wangxiang@cdjrlc.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 93fbc1ebd978 ("wifi: rtlwifi: 8192de: correct checking of IQK reload") +Signed-off-by: Sasha Levin +--- + drivers/net/wan/farsync.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wan/farsync.h b/drivers/net/wan/farsync.h +index 5f43568a9715..63908dbbb02d 100644 +--- a/drivers/net/wan/farsync.h ++++ b/drivers/net/wan/farsync.h +@@ -43,7 +43,7 @@ + * This version number is incremented with each official release of the + * package and is a simplified number for normal user reference. + * Individual files are tracked by the version control system and may +- * have individual versions (or IDs) that move much faster than the ++ * have individual versions (or IDs) that move much faster than + * the release version as individual updates are tracked. + */ + #define FST_USER_VERSION "1.04" +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath10k-add-peer-map-clean-up-for-peer-delete-in.patch b/queue-5.19/wifi-ath10k-add-peer-map-clean-up-for-peer-delete-in.patch new file mode 100644 index 00000000000..5d87c093bb6 --- /dev/null +++ b/queue-5.19/wifi-ath10k-add-peer-map-clean-up-for-peer-delete-in.patch @@ -0,0 +1,206 @@ +From f6d907e85169948f76179a80177af1b4c1b9fedd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 10:19:30 -0400 +Subject: wifi: ath10k: add peer map clean up for peer delete in + ath10k_sta_state() + +From: Wen Gong + +[ Upstream commit f020d9570a04df0762a2ac5c50cf1d8c511c9164 ] + +When peer delete failed in a disconnect operation, use-after-free +detected by KFENCE in below log. It is because for each vdev_id and +address, it has only one struct ath10k_peer, it is allocated in +ath10k_peer_map_event(). When connected to an AP, it has more than +one HTT_T2H_MSG_TYPE_PEER_MAP reported from firmware, then the +array peer_map of struct ath10k will be set muti-elements to the +same ath10k_peer in ath10k_peer_map_event(). When peer delete failed +in ath10k_sta_state(), the ath10k_peer will be free for the 1st peer +id in array peer_map of struct ath10k, and then use-after-free happened +for the 2nd peer id because they map to the same ath10k_peer. + +And clean up all peers in array peer_map for the ath10k_peer, then +user-after-free disappeared + +peer map event log: +[ 306.911021] wlan0: authenticate with b0:2a:43:e6:75:0e +[ 306.957187] ath10k_pci 0000:01:00.0: mac vdev 0 peer create b0:2a:43:e6:75:0e (new sta) sta 1 / 32 peer 1 / 33 +[ 306.957395] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 246 +[ 306.957404] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 198 +[ 306.986924] ath10k_pci 0000:01:00.0: htt peer map vdev 0 peer b0:2a:43:e6:75:0e id 166 + +peer unmap event log: +[ 435.715691] wlan0: deauthenticating from b0:2a:43:e6:75:0e by local choice (Reason: 3=DEAUTH_LEAVING) +[ 435.716802] ath10k_pci 0000:01:00.0: mac vdev 0 peer delete b0:2a:43:e6:75:0e sta ffff990e0e9c2b50 (sta gone) +[ 435.717177] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 246 +[ 435.717186] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 198 +[ 435.717193] ath10k_pci 0000:01:00.0: htt peer unmap vdev 0 peer b0:2a:43:e6:75:0e id 166 + +use-after-free log: +[21705.888627] wlan0: deauthenticating from d0:76:8f:82:be:75 by local choice (Reason: 3=DEAUTH_LEAVING) +[21713.799910] ath10k_pci 0000:01:00.0: failed to delete peer d0:76:8f:82:be:75 for vdev 0: -110 +[21713.799925] ath10k_pci 0000:01:00.0: found sta peer d0:76:8f:82:be:75 (ptr 0000000000000000 id 102) entry on vdev 0 after it was supposedly removed +[21713.799968] ================================================================== +[21713.799991] BUG: KFENCE: use-after-free read in ath10k_sta_state+0x265/0xb8a [ath10k_core] +[21713.799991] +[21713.799997] Use-after-free read at 0x00000000abe1c75e (in kfence-#69): +[21713.800010] ath10k_sta_state+0x265/0xb8a [ath10k_core] +[21713.800041] drv_sta_state+0x115/0x677 [mac80211] +[21713.800059] __sta_info_destroy_part2+0xb1/0x133 [mac80211] +[21713.800076] __sta_info_flush+0x11d/0x162 [mac80211] +[21713.800093] ieee80211_set_disassoc+0x12d/0x2f4 [mac80211] +[21713.800110] ieee80211_mgd_deauth+0x26c/0x29b [mac80211] +[21713.800137] cfg80211_mlme_deauth+0x13f/0x1bb [cfg80211] +[21713.800153] nl80211_deauthenticate+0xf8/0x121 [cfg80211] +[21713.800161] genl_rcv_msg+0x38e/0x3be +[21713.800166] netlink_rcv_skb+0x89/0xf7 +[21713.800171] genl_rcv+0x28/0x36 +[21713.800176] netlink_unicast+0x179/0x24b +[21713.800181] netlink_sendmsg+0x3a0/0x40e +[21713.800187] sock_sendmsg+0x72/0x76 +[21713.800192] ____sys_sendmsg+0x16d/0x1e3 +[21713.800196] ___sys_sendmsg+0x95/0xd1 +[21713.800200] __sys_sendmsg+0x85/0xbf +[21713.800205] do_syscall_64+0x43/0x55 +[21713.800210] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +[21713.800213] +[21713.800219] kfence-#69: 0x000000009149b0d5-0x000000004c0697fb, size=1064, cache=kmalloc-2k +[21713.800219] +[21713.800224] allocated by task 13 on cpu 0 at 21705.501373s: +[21713.800241] ath10k_peer_map_event+0x7e/0x154 [ath10k_core] +[21713.800254] ath10k_htt_t2h_msg_handler+0x586/0x1039 [ath10k_core] +[21713.800265] ath10k_htt_htc_t2h_msg_handler+0x12/0x28 [ath10k_core] +[21713.800277] ath10k_htc_rx_completion_handler+0x14c/0x1b5 [ath10k_core] +[21713.800283] ath10k_pci_process_rx_cb+0x195/0x1df [ath10k_pci] +[21713.800294] ath10k_ce_per_engine_service+0x55/0x74 [ath10k_core] +[21713.800305] ath10k_ce_per_engine_service_any+0x76/0x84 [ath10k_core] +[21713.800310] ath10k_pci_napi_poll+0x49/0x144 [ath10k_pci] +[21713.800316] net_rx_action+0xdc/0x361 +[21713.800320] __do_softirq+0x163/0x29a +[21713.800325] asm_call_irq_on_stack+0x12/0x20 +[21713.800331] do_softirq_own_stack+0x3c/0x48 +[21713.800337] __irq_exit_rcu+0x9b/0x9d +[21713.800342] common_interrupt+0xc9/0x14d +[21713.800346] asm_common_interrupt+0x1e/0x40 +[21713.800351] ksoftirqd_should_run+0x5/0x16 +[21713.800357] smpboot_thread_fn+0x148/0x211 +[21713.800362] kthread+0x150/0x15f +[21713.800367] ret_from_fork+0x22/0x30 +[21713.800370] +[21713.800374] freed by task 708 on cpu 1 at 21713.799953s: +[21713.800498] ath10k_sta_state+0x2c6/0xb8a [ath10k_core] +[21713.800515] drv_sta_state+0x115/0x677 [mac80211] +[21713.800532] __sta_info_destroy_part2+0xb1/0x133 [mac80211] +[21713.800548] __sta_info_flush+0x11d/0x162 [mac80211] +[21713.800565] ieee80211_set_disassoc+0x12d/0x2f4 [mac80211] +[21713.800581] ieee80211_mgd_deauth+0x26c/0x29b [mac80211] +[21713.800598] cfg80211_mlme_deauth+0x13f/0x1bb [cfg80211] +[21713.800614] nl80211_deauthenticate+0xf8/0x121 [cfg80211] +[21713.800619] genl_rcv_msg+0x38e/0x3be +[21713.800623] netlink_rcv_skb+0x89/0xf7 +[21713.800628] genl_rcv+0x28/0x36 +[21713.800632] netlink_unicast+0x179/0x24b +[21713.800637] netlink_sendmsg+0x3a0/0x40e +[21713.800642] sock_sendmsg+0x72/0x76 +[21713.800646] ____sys_sendmsg+0x16d/0x1e3 +[21713.800651] ___sys_sendmsg+0x95/0xd1 +[21713.800655] __sys_sendmsg+0x85/0xbf +[21713.800659] do_syscall_64+0x43/0x55 +[21713.800663] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00288-QCARMSWPZ-1 + +Fixes: d0eeafad1189 ("ath10k: Clean up peer when sta goes away.") +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220801141930.16794-1-quic_wgong@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/mac.c | 54 ++++++++++++++------------- + 1 file changed, 29 insertions(+), 25 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c +index 6407f509e91b..9a1c970f8f55 100644 +--- a/drivers/net/wireless/ath/ath10k/mac.c ++++ b/drivers/net/wireless/ath/ath10k/mac.c +@@ -864,11 +864,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) + return 0; + } + ++static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer) ++{ ++ int peer_id, i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ for_each_set_bit(peer_id, peer->peer_ids, ++ ATH10K_MAX_NUM_PEER_IDS) { ++ ar->peer_map[peer_id] = NULL; ++ } ++ ++ /* Double check that peer is properly un-referenced from ++ * the peer_map ++ */ ++ for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { ++ if (ar->peer_map[i] == peer) { ++ ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", ++ peer->addr, peer, i); ++ ar->peer_map[i] = NULL; ++ } ++ } ++ ++ list_del(&peer->list); ++ kfree(peer); ++ ar->num_peers--; ++} ++ + static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) + { + struct ath10k_peer *peer, *tmp; +- int peer_id; +- int i; + + lockdep_assert_held(&ar->conf_mutex); + +@@ -880,25 +905,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) + ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n", + peer->addr, vdev_id); + +- for_each_set_bit(peer_id, peer->peer_ids, +- ATH10K_MAX_NUM_PEER_IDS) { +- ar->peer_map[peer_id] = NULL; +- } +- +- /* Double check that peer is properly un-referenced from +- * the peer_map +- */ +- for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { +- if (ar->peer_map[i] == peer) { +- ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", +- peer->addr, peer, i); +- ar->peer_map[i] = NULL; +- } +- } +- +- list_del(&peer->list); +- kfree(peer); +- ar->num_peers--; ++ ath10k_peer_map_cleanup(ar, peer); + } + spin_unlock_bh(&ar->data_lock); + } +@@ -7586,10 +7593,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, + /* Clean up the peer object as well since we + * must have failed to do this above. + */ +- list_del(&peer->list); +- ar->peer_map[i] = NULL; +- kfree(peer); +- ar->num_peers--; ++ ath10k_peer_map_cleanup(ar, peer); + } + } + spin_unlock_bh(&ar->data_lock); +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath10k-reset-pointer-after-memory-free-to-avoid.patch b/queue-5.19/wifi-ath10k-reset-pointer-after-memory-free-to-avoid.patch new file mode 100644 index 00000000000..6353b944050 --- /dev/null +++ b/queue-5.19/wifi-ath10k-reset-pointer-after-memory-free-to-avoid.patch @@ -0,0 +1,64 @@ +From 2ba0df8d117035d1b05d2db337b39e9c07b24cdc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 18:23:54 +0300 +Subject: wifi: ath10k: reset pointer after memory free to avoid potential + use-after-free + +From: Wen Gong + +[ Upstream commit 1e1cb8e0b73e6f39a9d4a7a15d940b1265387eb5 ] + +When running suspend test, kernel crash happened in ath10k, and it is +fixed by commit b72a4aff947b ("ath10k: skip ath10k_halt during suspend +for driver state RESTARTING"). + +Currently the crash is fixed, but as a common code style, it is better +to set the pointer to NULL after memory is free. + +This is to address the code style and it will avoid potential bug of +use-after-free. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220505092248.787-1-quic_wgong@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c +index fe34fcc00af0..55a520237263 100644 +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -301,12 +301,16 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) + ath10k_htt_get_vaddr_ring(htt), + htt->rx_ring.base_paddr); + ++ ath10k_htt_config_paddrs_ring(htt, NULL); ++ + dma_free_coherent(htt->ar->dev, + sizeof(*htt->rx_ring.alloc_idx.vaddr), + htt->rx_ring.alloc_idx.vaddr, + htt->rx_ring.alloc_idx.paddr); ++ htt->rx_ring.alloc_idx.vaddr = NULL; + + kfree(htt->rx_ring.netbufs_ring); ++ htt->rx_ring.netbufs_ring = NULL; + } + + static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) +@@ -846,8 +850,10 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) + ath10k_htt_get_rx_ring_size(htt), + vaddr_ring, + htt->rx_ring.base_paddr); ++ ath10k_htt_config_paddrs_ring(htt, NULL); + err_dma_ring: + kfree(htt->rx_ring.netbufs_ring); ++ htt->rx_ring.netbufs_ring = NULL; + err_netbuf: + return -ENOMEM; + } +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath10k-set-tx-credit-to-one-for-wcn3990-snoc-ba.patch b/queue-5.19/wifi-ath10k-set-tx-credit-to-one-for-wcn3990-snoc-ba.patch new file mode 100644 index 00000000000..af8a11e150d --- /dev/null +++ b/queue-5.19/wifi-ath10k-set-tx-credit-to-one-for-wcn3990-snoc-ba.patch @@ -0,0 +1,210 @@ +From 4b126fd3898e500b510f18d5d2d27c9785d30b52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 19:19:41 +0530 +Subject: wifi: ath10k: Set tx credit to one for WCN3990 snoc based devices +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Youghandhar Chintala + +[ Upstream commit d81bbb684c250a637186d9286d75b1cb04d2986c ] + +Currently host can send two WMI commands at once. There is possibility to +cause SMMU issues or corruption, if host wants to initiate 2 DMA +transfers, it is possible when copy complete interrupt for first DMA +reaches host, CE has already updated SRRI (Source ring read index) for +both DMA transfers and is in the middle of 2nd DMA. Host uses SRRI +(Source ring read index) to interpret how many DMA’s have been completed +and tries to unmap/free both the DMA entries. Hence now it is limiting to +one.Because CE is still in the middle of 2nd DMA which can cause these +issues when handling two DMA transfers. + +This change will not impact other targets, as it is only for WCN3990. + +Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.2.0-01387-QCAHLSWMTPLZ-1 + +Signed-off-by: Youghandhar Chintala +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220801134941.15216-1-quic_youghand@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/core.c | 16 ++++++++++++++++ + drivers/net/wireless/ath/ath10k/htc.c | 11 ++++++++--- + drivers/net/wireless/ath/ath10k/hw.h | 2 ++ + 3 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c +index 688177453b07..07c4a4f0ed33 100644 +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c +@@ -95,6 +95,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = true, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA988X_HW_2_0_VERSION, +@@ -133,6 +134,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = true, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9887_HW_1_0_VERSION, +@@ -172,6 +174,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA6174_HW_3_2_VERSION, +@@ -206,6 +209,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .supports_peer_stats_info = true, + .dynamic_sar_support = true, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA6174_HW_2_1_VERSION, +@@ -244,6 +248,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA6174_HW_2_1_VERSION, +@@ -282,6 +287,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA6174_HW_3_0_VERSION, +@@ -320,6 +326,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA6174_HW_3_2_VERSION, +@@ -362,6 +369,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .supports_peer_stats_info = true, + .dynamic_sar_support = true, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA99X0_HW_2_0_DEV_VERSION, +@@ -406,6 +414,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9984_HW_1_0_DEV_VERSION, +@@ -457,6 +466,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9888_HW_2_0_DEV_VERSION, +@@ -505,6 +515,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9377_HW_1_0_DEV_VERSION, +@@ -543,6 +554,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9377_HW_1_1_DEV_VERSION, +@@ -583,6 +595,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA9377_HW_1_1_DEV_VERSION, +@@ -614,6 +627,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .credit_size_workaround = true, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = QCA4019_HW_1_0_DEV_VERSION, +@@ -659,6 +673,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = false, + .hw_restart_disconnect = false, ++ .use_fw_tx_credits = true, + }, + { + .id = WCN3990_HW_1_0_DEV_VERSION, +@@ -690,6 +705,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { + .tx_stats_over_pktlog = false, + .dynamic_sar_support = true, + .hw_restart_disconnect = true, ++ .use_fw_tx_credits = false, + }, + }; + +diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c +index fab398046a3f..6d1784f74bea 100644 +--- a/drivers/net/wireless/ath/ath10k/htc.c ++++ b/drivers/net/wireless/ath/ath10k/htc.c +@@ -947,13 +947,18 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) + return -ECOMM; + } + +- htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); ++ if (ar->hw_params.use_fw_tx_credits) ++ htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count); ++ else ++ htc->total_transmit_credits = 1; ++ + htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size); + + ath10k_dbg(ar, ATH10K_DBG_HTC, +- "Target ready! transmit resources: %d size:%d\n", ++ "Target ready! transmit resources: %d size:%d actual credits:%d\n", + htc->total_transmit_credits, +- htc->target_credit_size); ++ htc->target_credit_size, ++ msg->ready.credit_count); + + if ((htc->total_transmit_credits == 0) || + (htc->target_credit_size == 0)) { +diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h +index 93acf0dd580a..1b99f3a39a11 100644 +--- a/drivers/net/wireless/ath/ath10k/hw.h ++++ b/drivers/net/wireless/ath/ath10k/hw.h +@@ -635,6 +635,8 @@ struct ath10k_hw_params { + bool dynamic_sar_support; + + bool hw_restart_disconnect; ++ ++ bool use_fw_tx_credits; + }; + + struct htt_resp; +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-fix-failed-to-find-the-peer-with-peer_id.patch b/queue-5.19/wifi-ath11k-fix-failed-to-find-the-peer-with-peer_id.patch new file mode 100644 index 00000000000..41bc4ad4bc3 --- /dev/null +++ b/queue-5.19/wifi-ath11k-fix-failed-to-find-the-peer-with-peer_id.patch @@ -0,0 +1,98 @@ +From a187920cfdb36cb38d175b012a49eca3eacd35c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 18:23:41 +0300 +Subject: wifi: ath11k: fix failed to find the peer with peer_id 0 when + disconnected + +From: Wen Gong + +[ Upstream commit a20ed60bb357776301c2dad7b4a4f0db97e143e9 ] + +It has a fail log which is ath11k_dbg in ath11k_dp_rx_process_mon_status(), +as below, it will not print when debug_mask is not set ATH11K_DBG_DATA. + ath11k_dbg(ab, ATH11K_DBG_DATA, + "failed to find the peer with peer_id %d\n", + ppdu_info.peer_id); + +When run scan with station disconnected, the peer_id is 0 for case +HAL_RX_MPDU_START in ath11k_hal_rx_parse_mon_status_tlv() which called +from ath11k_dp_rx_process_mon_status(), and the peer_id of ppdu_info is +reset to 0 in the while loop, so it does not match condition of the +check "if (ppdu_info->peer_id == HAL_INVALID_PEERID" in the loop, and +then the log "failed to find the peer with peer_id 0" print after the +check in the loop, it is below call stack when debug_mask is set +ATH11K_DBG_DATA. + +The reason is this commit 01d2f285e3e5 ("ath11k: decode HE status tlv") +add "memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info))" in +ath11k_dp_rx_process_mon_status(), but the commit does not initialize +the peer_id to HAL_INVALID_PEERID, then lead the check mis-match. + +Callstack of the failed log: +[12335.689072] RIP: 0010:ath11k_dp_rx_process_mon_status+0x9ea/0x1020 [ath11k] +[12335.689157] Code: 89 ff e8 f9 10 00 00 be 01 00 00 00 4c 89 f7 e8 dc 4b 4e de 48 8b 85 38 ff ff ff c7 80 e4 07 00 00 01 00 00 00 e9 20 f8 ff ff <0f> 0b 41 0f b7 96 be 06 00 00 48 c7 c6 b8 50 44 c1 4c 89 ff e8 fd +[12335.689180] RSP: 0018:ffffb874001a4ca0 EFLAGS: 00010246 +[12335.689210] RAX: 0000000000000000 RBX: ffff995642cbd100 RCX: 0000000000000000 +[12335.689229] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff99564212cd18 +[12335.689248] RBP: ffffb874001a4dc0 R08: 0000000000000001 R09: 0000000000000000 +[12335.689268] R10: 0000000000000220 R11: ffffb874001a48e8 R12: ffff995642473d40 +[12335.689286] R13: ffff99564212c5b8 R14: ffff9956424736a0 R15: ffff995642120000 +[12335.689303] FS: 0000000000000000(0000) GS:ffff995739000000(0000) knlGS:0000000000000000 +[12335.689323] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[12335.689341] CR2: 00007f43c5d5e039 CR3: 000000011c012005 CR4: 00000000000606e0 +[12335.689360] Call Trace: +[12335.689377] +[12335.689418] ? rcu_read_lock_held_common+0x12/0x50 +[12335.689447] ? rcu_read_lock_sched_held+0x25/0x80 +[12335.689471] ? rcu_read_lock_held_common+0x12/0x50 +[12335.689504] ath11k_dp_rx_process_mon_rings+0x8d/0x4f0 [ath11k] +[12335.689578] ? ath11k_dp_rx_process_mon_rings+0x8d/0x4f0 [ath11k] +[12335.689653] ? lock_acquire+0xef/0x360 +[12335.689681] ? rcu_read_lock_sched_held+0x25/0x80 +[12335.689713] ath11k_dp_service_mon_ring+0x38/0x60 [ath11k] +[12335.689784] ? ath11k_dp_rx_process_mon_rings+0x4f0/0x4f0 [ath11k] +[12335.689860] call_timer_fn+0xb2/0x2f0 +[12335.689897] ? ath11k_dp_rx_process_mon_rings+0x4f0/0x4f0 [ath11k] +[12335.689970] run_timer_softirq+0x21f/0x540 +[12335.689999] ? ktime_get+0xad/0x160 +[12335.690025] ? lapic_next_deadline+0x2c/0x40 +[12335.690053] ? clockevents_program_event+0x82/0x100 +[12335.690093] __do_softirq+0x151/0x4a8 +[12335.690135] irq_exit_rcu+0xc9/0x100 +[12335.690165] sysvec_apic_timer_interrupt+0xa8/0xd0 +[12335.690189] +[12335.690204] +[12335.690225] asm_sysvec_apic_timer_interrupt+0x12/0x20 + +Reset the default value to HAL_INVALID_PEERID each time after memset +of ppdu_info as well as others memset which existed in function +ath11k_dp_rx_process_mon_status(), then the failed log disappeared. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Fixes: 01d2f285e3e5 ("ath11k: decode HE status tlv") +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220518033556.31940-1-quic_wgong@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index b3e133add1ce..1459e3b1c4f5 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -5194,7 +5194,8 @@ int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, + if (log_type != ATH11K_PKTLOG_TYPE_INVALID) + trace_ath11k_htt_rxdesc(ar, skb->data, log_type, rx_buf_sz); + +- memset(ppdu_info, 0, sizeof(struct hal_rx_mon_ppdu_info)); ++ memset(ppdu_info, 0, sizeof(*ppdu_info)); ++ ppdu_info->peer_id = HAL_INVALID_PEERID; + hal_status = ath11k_hal_rx_parse_mon_status(ab, ppdu_info, skb); + + if (test_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags) && +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-fix-incorrect-qmi-message-id-mappings.patch b/queue-5.19/wifi-ath11k-fix-incorrect-qmi-message-id-mappings.patch new file mode 100644 index 00000000000..8861f99dec6 --- /dev/null +++ b/queue-5.19/wifi-ath11k-fix-incorrect-qmi-message-id-mappings.patch @@ -0,0 +1,152 @@ +From 00c05ef3bccbd763f775f81941e15f3d9e599262 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 09:04:19 +0300 +Subject: wifi: ath11k: Fix incorrect QMI message ID mappings + +From: Manikanta Pubbisetty + +[ Upstream commit b3ca32308e46b6384fdcb7e64b3fca4f61aff14b ] + +QMI message IDs for some of the QMI messages were incorrectly +defined in the original implementation. These have to be corrected +to enable cold boot support on WCN6750. These corrections are +applicable for all chipsets and will not impact them. Refactor the +code accordingly. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220720134909.15626-2-quic_mpubbise@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 38 ++++++++++++++++++++++++--- + drivers/net/wireless/ath/ath11k/qmi.h | 10 +++++-- + 2 files changed, 43 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 61ead37a944a..109f4b618428 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1696,6 +1696,13 @@ static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { + }, + }; + ++static struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { ++ { ++ .data_type = QMI_EOTI, ++ .array_type = NO_ARRAY, ++ }, ++}; ++ + static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) + { + struct qmi_wlanfw_host_cap_req_msg_v01 req; +@@ -3006,6 +3013,10 @@ static void ath11k_qmi_msg_fw_ready_cb(struct qmi_handle *qmi_hdl, + struct ath11k_base *ab = qmi->ab; + + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware ready\n"); ++ ++ ab->qmi.cal_done = 1; ++ wake_up(&ab->qmi.cold_boot_waitq); ++ + ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_READY, NULL); + } + +@@ -3018,11 +3029,22 @@ static void ath11k_qmi_msg_cold_boot_cal_done_cb(struct qmi_handle *qmi_hdl, + struct ath11k_qmi, handle); + struct ath11k_base *ab = qmi->ab; + +- ab->qmi.cal_done = 1; +- wake_up(&ab->qmi.cold_boot_waitq); + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cold boot calibration done\n"); + } + ++static void ath11k_qmi_msg_fw_init_done_cb(struct qmi_handle *qmi_hdl, ++ struct sockaddr_qrtr *sq, ++ struct qmi_txn *txn, ++ const void *decoded) ++{ ++ struct ath11k_qmi *qmi = container_of(qmi_hdl, ++ struct ath11k_qmi, handle); ++ struct ath11k_base *ab = qmi->ab; ++ ++ ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_FW_INIT_DONE, NULL); ++ ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi firmware init done\n"); ++} ++ + static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { + { + .type = QMI_INDICATION, +@@ -3053,6 +3075,14 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { + sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01), + .fn = ath11k_qmi_msg_cold_boot_cal_done_cb, + }, ++ { ++ .type = QMI_INDICATION, ++ .msg_id = QMI_WLFW_FW_INIT_DONE_IND_V01, ++ .ei = qmi_wlfw_fw_init_done_ind_msg_v01_ei, ++ .decoded_size = ++ sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01), ++ .fn = ath11k_qmi_msg_fw_init_done_cb, ++ }, + }; + + static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, +@@ -3145,7 +3175,7 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + } + + break; +- case ATH11K_QMI_EVENT_FW_READY: ++ case ATH11K_QMI_EVENT_FW_INIT_DONE: + clear_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); + if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { + ath11k_hal_dump_srng_stats(ab); +@@ -3168,6 +3198,8 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); + } + ++ break; ++ case ATH11K_QMI_EVENT_FW_READY: + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +diff --git a/drivers/net/wireless/ath/ath11k/qmi.h b/drivers/net/wireless/ath/ath11k/qmi.h +index c83cf822be81..2ec56a34fa81 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.h ++++ b/drivers/net/wireless/ath/ath11k/qmi.h +@@ -31,8 +31,9 @@ + + #define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035 + #define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037 +-#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x0021 +-#define QMI_WLFW_FW_READY_IND_V01 0x0038 ++#define QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01 0x003E ++#define QMI_WLFW_FW_READY_IND_V01 0x0021 ++#define QMI_WLFW_FW_INIT_DONE_IND_V01 0x0038 + + #define QMI_WLANFW_MAX_DATA_SIZE_V01 6144 + #define ATH11K_FIRMWARE_MODE_OFF 4 +@@ -69,6 +70,7 @@ enum ath11k_qmi_event_type { + ATH11K_QMI_EVENT_FORCE_FW_ASSERT, + ATH11K_QMI_EVENT_POWER_UP, + ATH11K_QMI_EVENT_POWER_DOWN, ++ ATH11K_QMI_EVENT_FW_INIT_DONE, + ATH11K_QMI_EVENT_MAX, + }; + +@@ -291,6 +293,10 @@ struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01 { + char placeholder; + }; + ++struct qmi_wlfw_fw_init_done_ind_msg_v01 { ++ char placeholder; ++}; ++ + #define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0 + #define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 235 + #define QMI_WLANFW_CAP_REQ_V01 0x0024 +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-fix-number-of-vht-beamformee-spatial-str.patch b/queue-5.19/wifi-ath11k-fix-number-of-vht-beamformee-spatial-str.patch new file mode 100644 index 00000000000..ae3baff3a4f --- /dev/null +++ b/queue-5.19/wifi-ath11k-fix-number-of-vht-beamformee-spatial-str.patch @@ -0,0 +1,101 @@ +From bd4e4a7d38b007920245913a6c9f4d9ae4d1adc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 10:35:14 +0300 +Subject: wifi: ath11k: fix number of VHT beamformee spatial streams + +From: Jesus Fernandez Manzano + +[ Upstream commit 55b5ee3357d7bb98ee578cf9b84a652e7a1bc199 ] + +The number of spatial streams used when acting as a beamformee in VHT +mode are reported by the firmware as 7 (8 sts - 1) both in IPQ6018 and +IPQ8074 which respectively have 2 and 4 sts each. So the firmware should +report 1 (2 - 1) and 3 (4 - 1). + +Fix this by checking that the number of VHT beamformee sts reported by +the firmware is not greater than the number of receiving antennas - 1. +The fix is based on the same approach used in this same function for +sanitizing the number of sounding dimensions reported by the firmware. + +Without this change, acting as a beamformee in VHT mode is not working +properly. + +Tested-on: IPQ6018 hw1.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Jesus Fernandez Manzano +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220616173947.21901-1-jesus.manzano@galgus.net +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mac.c | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c +index 06b86dcc3826..94d9a7190953 100644 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4949,6 +4949,8 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif) + if (vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)) { + nsts = vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ if (nsts > (ar->num_rx_chains - 1)) ++ nsts = ar->num_rx_chains - 1; + value |= SM(nsts, WMI_TXBF_STS_CAP_OFFSET); + } + +@@ -4989,7 +4991,7 @@ static int ath11k_mac_set_txbf_conf(struct ath11k_vif *arvif) + static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) + { + bool subfer, subfee; +- int sound_dim = 0; ++ int sound_dim = 0, nsts = 0; + + subfer = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)); + subfee = !!(*vht_cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)); +@@ -4999,6 +5001,11 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) + subfer = false; + } + ++ if (ar->num_rx_chains < 2) { ++ *vht_cap &= ~(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE); ++ subfee = false; ++ } ++ + /* If SU Beaformer is not set, then disable MU Beamformer Capability */ + if (!subfer) + *vht_cap &= ~(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE); +@@ -5011,7 +5018,9 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) + sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT; + *vht_cap &= ~IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK; + +- /* TODO: Need to check invalid STS and Sound_dim values set by FW? */ ++ nsts = (*vht_cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK); ++ nsts >>= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ *vht_cap &= ~IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; + + /* Enable Sounding Dimension Field only if SU BF is enabled */ + if (subfer) { +@@ -5023,9 +5032,15 @@ static void ath11k_set_vht_txbf_cap(struct ath11k *ar, u32 *vht_cap) + *vht_cap |= sound_dim; + } + +- /* Use the STS advertised by FW unless SU Beamformee is not supported*/ +- if (!subfee) +- *vht_cap &= ~(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK); ++ /* Enable Beamformee STS Field only if SU BF is enabled */ ++ if (subfee) { ++ if (nsts > (ar->num_rx_chains - 1)) ++ nsts = ar->num_rx_chains - 1; ++ ++ nsts <<= IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT; ++ nsts &= IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; ++ *vht_cap |= nsts; ++ } + } + + static struct ieee80211_sta_vht_cap +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-fix-peer-addition-deletion-error-on-sta-.patch b/queue-5.19/wifi-ath11k-fix-peer-addition-deletion-error-on-sta-.patch new file mode 100644 index 00000000000..bfb5d797c3e --- /dev/null +++ b/queue-5.19/wifi-ath11k-fix-peer-addition-deletion-error-on-sta-.patch @@ -0,0 +1,119 @@ +From e0958982a065092466e273b724e577514dc06da2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 10:35:14 +0300 +Subject: wifi: ath11k: fix peer addition/deletion error on sta band migration + +From: Christian 'Ansuel' Marangi + +[ Upstream commit d673cb6fe6c03b2be157cc6c5db40481828d282d ] + +This patch try to fix the following error. + +Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.561227] ath11k c000000.wifi: peer already added vdev id 0 req, vdev id 1 present +Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.561282] ath11k c000000.wifi: Failed to add peer: 28:c2:1f:xx:xx:xx for VDEV: 0 +Wed Jun 1 22:19:30 2022 kern.warn kernel: [ 119.568053] ath11k c000000.wifi: Failed to add station: 28:c2:1f:xx:xx:xx for VDEV: 0 +Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan2: STA 28:c2:1f:xx:xx:xx IEEE 802.11: Could not add STA to kernel driver +Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan2: STA 28:c2:1f:xx:xx:xx IEEE 802.11: did not acknowledge authentication response +Wed Jun 1 22:19:31 2022 daemon.notice hostapd: wlan1: AP-STA-DISCONNECTED 28:c2:1f:xx:xx:xx +Wed Jun 1 22:19:31 2022 daemon.info hostapd: wlan1: STA 28:c2:1f:xx:xx:xx IEEE 802.11: disassociated due to inactivity +Wed Jun 1 22:19:32 2022 daemon.info hostapd: wlan1: STA 28:c2:1f:xx:xx:xx IEEE 802.11: deauthenticated due to inactivity (timer DEAUTH/REMOVE) + +To repro this: +- Have 2 Wifi with the same bssid and pass on different band (2.4 and +5GHz) +- Enable 802.11r Fast Transaction with same mobility domain +- FT Protocol: FT over the Air +From a openwrt system issue the command (with the correct mac) +ubus call hostapd.wlan1 wnm_disassoc_imminent '{"addr":"28:C2:1F:xx:xx:xx"}' +Notice the log printing the errors. + +The cause of this error has been investigated and we found that this is +related to the WiFi Fast Transaction feature. We observed that this is +triggered when the router tells the device to change band. In this case +the device first auth to the other band and then the disconnect path +from the prev band is triggered. +This is problematic with the current rhash implementation since the +addrs is used as key and the logic of "adding first, delete later" +conflicts with the rhash logic. +In fact peer addition will fail since the peer is already added and with +that fixed a peer deletion will cause unitended effect by removing the +peer just added. + +Current solution to this is to add additional logic to the peer delete, +make sure we are deleting the correct peer taken from the rhash +table (and fallback to the peer list) and for the peer add logic delete +the peer entry for the rhash list before adding the new one (counting as +an error only when a peer with the same vlan_id is asked to be added). + +With this change, a sta can correctly transition from 2.4GHz and 5GHZ +with no drop and no error are printed. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01208-QCAHKSWPL_SILICONZ-1 + +Fixes: 7b0c70d92a43 ("ath11k: Add peer rhash table support") +Signed-off-by: Christian 'Ansuel' Marangi +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220603164559.27769-1-ansuelsmth@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/peer.c | 30 ++++++++++++++++++++++---- + 1 file changed, 26 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c +index 9e22aaf34b88..1ae7af02c364 100644 +--- a/drivers/net/wireless/ath/ath11k/peer.c ++++ b/drivers/net/wireless/ath/ath11k/peer.c +@@ -302,6 +302,21 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr) + spin_lock_bh(&ab->base_lock); + + peer = ath11k_peer_find_by_addr(ab, addr); ++ /* Check if the found peer is what we want to remove. ++ * While the sta is transitioning to another band we may ++ * have 2 peer with the same addr assigned to different ++ * vdev_id. Make sure we are deleting the correct peer. ++ */ ++ if (peer && peer->vdev_id == vdev_id) ++ ath11k_peer_rhash_delete(ab, peer); ++ ++ /* Fallback to peer list search if the correct peer can't be found. ++ * Skip the deletion of the peer from the rhash since it has already ++ * been deleted in peer add. ++ */ ++ if (!peer) ++ peer = ath11k_peer_find(ab, vdev_id, addr); ++ + if (!peer) { + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); +@@ -312,8 +327,6 @@ static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr) + return -EINVAL; + } + +- ath11k_peer_rhash_delete(ab, peer); +- + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); + +@@ -372,8 +385,17 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, + spin_lock_bh(&ar->ab->base_lock); + peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); + if (peer) { +- spin_unlock_bh(&ar->ab->base_lock); +- return -EINVAL; ++ if (peer->vdev_id == param->vdev_id) { ++ spin_unlock_bh(&ar->ab->base_lock); ++ return -EINVAL; ++ } ++ ++ /* Assume sta is transitioning to another band. ++ * Remove here the peer from rhash. ++ */ ++ mutex_lock(&ar->ab->tbl_mtx_lock); ++ ath11k_peer_rhash_delete(ar->ab, peer); ++ mutex_unlock(&ar->ab->tbl_mtx_lock); + } + spin_unlock_bh(&ar->ab->base_lock); + +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-include-sta_keepalive_arp_response-tlv-h.patch b/queue-5.19/wifi-ath11k-include-sta_keepalive_arp_response-tlv-h.patch new file mode 100644 index 00000000000..5332eca0f5a --- /dev/null +++ b/queue-5.19/wifi-ath11k-include-sta_keepalive_arp_response-tlv-h.patch @@ -0,0 +1,71 @@ +From 5c74b9c68e95d3f99bcc949a5167c0ddb5a1c207 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Sep 2022 12:43:58 +0800 +Subject: wifi: ath11k: Include STA_KEEPALIVE_ARP_RESPONSE TLV header by + default + +From: Baochen Qiang + +[ Upstream commit b7b6f86149a7e06269d61a7a5206360f5b642f80 ] + +In current code STA_KEEPALIVE_ARP_RESPONSE TLV header is included only +when ARP method is used, this causes firmware always to crash when wowlan +is enabled because firmware needs it to be present no matter ARP method +is used or not. + +Fix this issue by including STA_KEEPALIVE_ARP_RESPONSE TLV header by +default. + +Also fix below typo: + s/WMI_TAG_STA_KEEPALVE_ARP_RESPONSE/WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE/ + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Fixes: 0f84a156aa3b ("ath11k: Handle keepalive during WoWLAN suspend and resume") +Signed-off-by: Baochen Qiang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220913044358.2037-1-quic_bqiang@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/wmi.c | 9 +++++---- + drivers/net/wireless/ath/ath11k/wmi.h | 2 +- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c +index cc84bd53ddae..1c8aa503e614 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -9003,12 +9003,13 @@ int ath11k_wmi_sta_keepalive(struct ath11k *ar, + cmd->interval = arg->interval; + cmd->method = arg->method; + ++ arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1); ++ arp->tlv_header = FIELD_PREP(WMI_TLV_TAG, ++ WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE) | ++ FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE); ++ + if (arg->method == WMI_STA_KEEPALIVE_METHOD_UNSOLICITED_ARP_RESPONSE || + arg->method == WMI_STA_KEEPALIVE_METHOD_GRATUITOUS_ARP_REQUEST) { +- arp = (struct wmi_sta_keepalive_arp_resp *)(cmd + 1); +- arp->tlv_header = FIELD_PREP(WMI_TLV_TAG, +- WMI_TAG_STA_KEEPALVE_ARP_RESPONSE) | +- FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE); + arp->src_ip4_addr = arg->src_ip4_addr; + arp->dest_ip4_addr = arg->dest_ip4_addr; + ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr); +diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h +index b1fad4707dc6..ca3b9a384d60 100644 +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -1214,7 +1214,7 @@ enum wmi_tlv_tag { + WMI_TAG_NS_OFFLOAD_TUPLE, + WMI_TAG_FTM_INTG_CMD, + WMI_TAG_STA_KEEPALIVE_CMD, +- WMI_TAG_STA_KEEPALVE_ARP_RESPONSE, ++ WMI_TAG_STA_KEEPALIVE_ARP_RESPONSE, + WMI_TAG_P2P_SET_VENDOR_IE_DATA_CMD, + WMI_TAG_AP_PS_PEER_CMD, + WMI_TAG_PEER_RATE_RETRY_SCHED_CMD, +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-mhi-fix-potential-memory-leak-in-ath11k_.patch b/queue-5.19/wifi-ath11k-mhi-fix-potential-memory-leak-in-ath11k_.patch new file mode 100644 index 00000000000..52298cb6968 --- /dev/null +++ b/queue-5.19/wifi-ath11k-mhi-fix-potential-memory-leak-in-ath11k_.patch @@ -0,0 +1,79 @@ +From 3b4543fb98ec1f6b99622f72c254e04776e4a992 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 15:37:04 +0800 +Subject: wifi: ath11k: mhi: fix potential memory leak in ath11k_mhi_register() + +From: Jianglei Nie + +[ Upstream commit 43e7c3505ec70db3d3c6458824d5fa40f62e3e7b ] + +mhi_alloc_controller() allocates a memory space for mhi_ctrl. When gets +some error, mhi_ctrl should be freed with mhi_free_controller(). But +when ath11k_mhi_read_addr_from_dt() fails, the function returns without +calling mhi_free_controller(), which will lead to a memory leak. + +We can fix it by calling mhi_free_controller() when +ath11k_mhi_read_addr_from_dt() fails. + +Signed-off-by: Jianglei Nie +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220907073704.58806-1-niejianglei2021@163.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/mhi.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c +index c44df17719f6..86995e8dc913 100644 +--- a/drivers/net/wireless/ath/ath11k/mhi.c ++++ b/drivers/net/wireless/ath/ath11k/mhi.c +@@ -402,8 +402,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) + ret = ath11k_mhi_get_msi(ab_pci); + if (ret) { + ath11k_err(ab, "failed to get msi for mhi\n"); +- mhi_free_controller(mhi_ctrl); +- return ret; ++ goto free_controller; + } + + if (!test_bit(ATH11K_FLAG_MULTI_MSI_VECTORS, &ab->dev_flags)) +@@ -412,7 +411,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) + if (test_bit(ATH11K_FLAG_FIXED_MEM_RGN, &ab->dev_flags)) { + ret = ath11k_mhi_read_addr_from_dt(mhi_ctrl); + if (ret < 0) +- return ret; ++ goto free_controller; + } else { + mhi_ctrl->iova_start = 0; + mhi_ctrl->iova_stop = 0xFFFFFFFF; +@@ -440,18 +439,22 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci) + default: + ath11k_err(ab, "failed assign mhi_config for unknown hw rev %d\n", + ab->hw_rev); +- mhi_free_controller(mhi_ctrl); +- return -EINVAL; ++ ret = -EINVAL; ++ goto free_controller; + } + + ret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config); + if (ret) { + ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret); +- mhi_free_controller(mhi_ctrl); +- return ret; ++ goto free_controller; + } + + return 0; ++ ++free_controller: ++ mhi_free_controller(mhi_ctrl); ++ ab_pci->mhi_ctrl = NULL; ++ return ret; + } + + void ath11k_mhi_unregister(struct ath11k_pci *ab_pci) +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath11k-register-shutdown-handler-for-wcn6750.patch b/queue-5.19/wifi-ath11k-register-shutdown-handler-for-wcn6750.patch new file mode 100644 index 00000000000..0ccd92534c2 --- /dev/null +++ b/queue-5.19/wifi-ath11k-register-shutdown-handler-for-wcn6750.patch @@ -0,0 +1,148 @@ +From 1b286e4e2b5a7870eef6679a2de4de8ddd045bf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 09:04:19 +0300 +Subject: wifi: ath11k: Register shutdown handler for WCN6750 + +From: Manikanta Pubbisetty + +[ Upstream commit ac41c2b642b136a1e633379fcb87a9db0ee07f5b ] + +When the system shuts down, SMMU driver will be stopped and +will not assist in IOVA translations. SMMU driver expects all +of its consumers to shutdown before shutting down itself. +WCN6750 being one of the consumer device should not perform any +DMA operations after the SMMU has shutdown which will otherwise +result in SMMU faults. + +SMMU driver will call the shutdown() callback of all its +consumer devices and the consumers shall stop further DMA +activity after the invocation of their respective shutdown() +callbacks. + +Register the shutdown() callback to the platform core for WCN6750. +Change will not impact other AHB ath11k devices. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Manikanta Pubbisetty +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220720134710.15523-1-quic_mpubbise@quicinc.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/ahb.c | 58 ++++++++++++++++++++------ + drivers/net/wireless/ath/ath11k/core.c | 2 + + 2 files changed, 47 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c +index c47414710138..911eee9646a4 100644 +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1088,20 +1088,10 @@ static int ath11k_ahb_probe(struct platform_device *pdev) + return ret; + } + +-static int ath11k_ahb_remove(struct platform_device *pdev) ++static void ath11k_ahb_remove_prepare(struct ath11k_base *ab) + { +- struct ath11k_base *ab = platform_get_drvdata(pdev); + unsigned long left; + +- if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { +- ath11k_ahb_power_down(ab); +- ath11k_debugfs_soc_destroy(ab); +- ath11k_qmi_deinit_service(ab); +- goto qmi_fail; +- } +- +- reinit_completion(&ab->driver_recovery); +- + if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags)) { + left = wait_for_completion_timeout(&ab->driver_recovery, + ATH11K_AHB_RECOVERY_TIMEOUT); +@@ -1111,19 +1101,60 @@ static int ath11k_ahb_remove(struct platform_device *pdev) + + set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags); + cancel_work_sync(&ab->restart_work); ++ cancel_work_sync(&ab->qmi.event_work); ++} ++ ++static void ath11k_ahb_free_resources(struct ath11k_base *ab) ++{ ++ struct platform_device *pdev = ab->pdev; + +- ath11k_core_deinit(ab); +-qmi_fail: + ath11k_ahb_free_irq(ab); + ath11k_hal_srng_deinit(ab); + ath11k_ahb_fw_resource_deinit(ab); + ath11k_ce_free_pipes(ab); + ath11k_core_free(ab); + platform_set_drvdata(pdev, NULL); ++} ++ ++static int ath11k_ahb_remove(struct platform_device *pdev) ++{ ++ struct ath11k_base *ab = platform_get_drvdata(pdev); ++ ++ if (test_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags)) { ++ ath11k_ahb_power_down(ab); ++ ath11k_debugfs_soc_destroy(ab); ++ ath11k_qmi_deinit_service(ab); ++ goto qmi_fail; ++ } ++ ++ ath11k_ahb_remove_prepare(ab); ++ ath11k_core_deinit(ab); ++ ++qmi_fail: ++ ath11k_ahb_free_resources(ab); + + return 0; + } + ++static void ath11k_ahb_shutdown(struct platform_device *pdev) ++{ ++ struct ath11k_base *ab = platform_get_drvdata(pdev); ++ ++ /* platform shutdown() & remove() are mutually exclusive. ++ * remove() is invoked during rmmod & shutdown() during ++ * system reboot/shutdown. ++ */ ++ ath11k_ahb_remove_prepare(ab); ++ ++ if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) ++ goto free_resources; ++ ++ ath11k_core_deinit(ab); ++ ++free_resources: ++ ath11k_ahb_free_resources(ab); ++} ++ + static struct platform_driver ath11k_ahb_driver = { + .driver = { + .name = "ath11k", +@@ -1131,6 +1162,7 @@ static struct platform_driver ath11k_ahb_driver = { + }, + .probe = ath11k_ahb_probe, + .remove = ath11k_ahb_remove, ++ .shutdown = ath11k_ahb_shutdown, + }; + + static int ath11k_ahb_init(void) +diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c +index 6ddc698f4a2d..209345bedd09 100644 +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1635,6 +1635,8 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) + + wake_up(&ab->wmi_ab.tx_credits_wq); + wake_up(&ab->peer_mapping_wq); ++ ++ reinit_completion(&ab->driver_recovery); + } + + static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab) +-- +2.35.1 + diff --git a/queue-5.19/wifi-ath9k-avoid-uninit-memory-read-in-ath9k_htc_rx_.patch b/queue-5.19/wifi-ath9k-avoid-uninit-memory-read-in-ath9k_htc_rx_.patch new file mode 100644 index 00000000000..55a87540564 --- /dev/null +++ b/queue-5.19/wifi-ath9k-avoid-uninit-memory-read-in-ath9k_htc_rx_.patch @@ -0,0 +1,152 @@ +From 6fccd5a3c414c90ee37a45b1ca1502b03ae51414 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 23:46:13 +0900 +Subject: wifi: ath9k: avoid uninit memory read in ath9k_htc_rx_msg() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Tetsuo Handa + +[ Upstream commit b383e8abed41cc6ff1a3b34de75df9397fa4878c ] + +syzbot is reporting uninit value at ath9k_htc_rx_msg() [1], for +ioctl(USB_RAW_IOCTL_EP_WRITE) can call ath9k_hif_usb_rx_stream() with +pkt_len = 0 but ath9k_hif_usb_rx_stream() uses +__dev_alloc_skb(pkt_len + 32, GFP_ATOMIC) based on an assumption that +pkt_len is valid. As a result, ath9k_hif_usb_rx_stream() allocates skb +with uninitialized memory and ath9k_htc_rx_msg() is reading from +uninitialized memory. + +Since bytes accessed by ath9k_htc_rx_msg() is not known until +ath9k_htc_rx_msg() is called, it would be difficult to check minimal valid +pkt_len at "if (pkt_len > 2 * MAX_RX_BUF_SIZE) {" line in +ath9k_hif_usb_rx_stream(). + +We have two choices. One is to workaround by adding __GFP_ZERO so that +ath9k_htc_rx_msg() sees 0 if pkt_len is invalid. The other is to let +ath9k_htc_rx_msg() validate pkt_len before accessing. This patch chose +the latter. + +Note that I'm not sure threshold condition is correct, for I can't find +details on possible packet length used by this protocol. + +Link: https://syzkaller.appspot.com/bug?extid=2ca247c2d60c7023de7f [1] +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Acked-by: Toke Høiland-Jørgensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/7acfa1be-4b5c-b2ce-de43-95b0593fb3e5@I-love.SAKURA.ne.jp +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/htc_hst.c | 43 +++++++++++++++--------- + 1 file changed, 28 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c +index 994ec48b2f66..ca05b07a45e6 100644 +--- a/drivers/net/wireless/ath/ath9k/htc_hst.c ++++ b/drivers/net/wireless/ath/ath9k/htc_hst.c +@@ -364,33 +364,27 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, + } + + static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle, +- struct sk_buff *skb) ++ struct sk_buff *skb, u32 len) + { + uint32_t *pattern = (uint32_t *)skb->data; + +- switch (*pattern) { +- case 0x33221199: +- { ++ if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) { + struct htc_panic_bad_vaddr *htc_panic; + htc_panic = (struct htc_panic_bad_vaddr *) skb->data; + dev_err(htc_handle->dev, "ath: firmware panic! " + "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n", + htc_panic->exccause, htc_panic->pc, + htc_panic->badvaddr); +- break; +- } +- case 0x33221299: +- { ++ return; ++ } ++ if (*pattern == 0x33221299) { + struct htc_panic_bad_epid *htc_panic; + htc_panic = (struct htc_panic_bad_epid *) skb->data; + dev_err(htc_handle->dev, "ath: firmware panic! " + "bad epid: 0x%08x\n", htc_panic->epid); +- break; +- } +- default: +- dev_err(htc_handle->dev, "ath: unknown panic pattern!\n"); +- break; ++ return; + } ++ dev_err(htc_handle->dev, "ath: unknown panic pattern!\n"); + } + + /* +@@ -411,16 +405,26 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, + if (!htc_handle || !skb) + return; + ++ /* A valid message requires len >= 8. ++ * ++ * sizeof(struct htc_frame_hdr) == 8 ++ * sizeof(struct htc_ready_msg) == 8 ++ * sizeof(struct htc_panic_bad_vaddr) == 16 ++ * sizeof(struct htc_panic_bad_epid) == 8 ++ */ ++ if (unlikely(len < sizeof(struct htc_frame_hdr))) ++ goto invalid; + htc_hdr = (struct htc_frame_hdr *) skb->data; + epid = htc_hdr->endpoint_id; + + if (epid == 0x99) { +- ath9k_htc_fw_panic_report(htc_handle, skb); ++ ath9k_htc_fw_panic_report(htc_handle, skb, len); + kfree_skb(skb); + return; + } + + if (epid < 0 || epid >= ENDPOINT_MAX) { ++invalid: + if (pipe_id != USB_REG_IN_PIPE) + dev_kfree_skb_any(skb); + else +@@ -432,21 +436,30 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, + + /* Handle trailer */ + if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { +- if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) ++ if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) { + /* Move past the Watchdog pattern */ + htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); ++ len -= 4; ++ } + } + + /* Get the message ID */ ++ if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16))) ++ goto invalid; + msg_id = (__be16 *) ((void *) htc_hdr + + sizeof(struct htc_frame_hdr)); + + /* Now process HTC messages */ + switch (be16_to_cpu(*msg_id)) { + case HTC_MSG_READY_ID: ++ if (unlikely(len < sizeof(struct htc_ready_msg))) ++ goto invalid; + htc_process_target_rdy(htc_handle, htc_hdr); + break; + case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID: ++ if (unlikely(len < sizeof(struct htc_frame_hdr) + ++ sizeof(struct htc_conn_svc_rspmsg))) ++ goto invalid; + htc_process_conn_rsp(htc_handle, htc_hdr); + break; + default: +-- +2.35.1 + diff --git a/queue-5.19/wifi-brcmfmac-fix-invalid-address-access-when-enabli.patch b/queue-5.19/wifi-brcmfmac-fix-invalid-address-access-when-enabli.patch new file mode 100644 index 00000000000..09980d4fa71 --- /dev/null +++ b/queue-5.19/wifi-brcmfmac-fix-invalid-address-access-when-enabli.patch @@ -0,0 +1,110 @@ +From 0195592c6b231181d04735819c423d63900f3f67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 13:56:28 +0200 +Subject: wifi: brcmfmac: fix invalid address access when enabling SCAN log + level +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wright Feng + +[ Upstream commit aa666b68e73fc06d83c070d96180b9010cf5a960 ] + +The variable i is changed when setting random MAC address and causes +invalid address access when printing the value of pi->reqs[i]->reqid. + +We replace reqs index with ri to fix the issue. + +[ 136.726473] Unable to handle kernel access to user memory outside uaccess routines at virtual address 0000000000000000 +[ 136.737365] Mem abort info: +[ 136.740172] ESR = 0x96000004 +[ 136.743359] Exception class = DABT (current EL), IL = 32 bits +[ 136.749294] SET = 0, FnV = 0 +[ 136.752481] EA = 0, S1PTW = 0 +[ 136.755635] Data abort info: +[ 136.758514] ISV = 0, ISS = 0x00000004 +[ 136.762487] CM = 0, WnR = 0 +[ 136.765522] user pgtable: 4k pages, 48-bit VAs, pgdp = 000000005c4e2577 +[ 136.772265] [0000000000000000] pgd=0000000000000000 +[ 136.777160] Internal error: Oops: 96000004 [#1] PREEMPT SMP +[ 136.782732] Modules linked in: brcmfmac(O) brcmutil(O) cfg80211(O) compat(O) +[ 136.789788] Process wificond (pid: 3175, stack limit = 0x00000000053048fb) +[ 136.796664] CPU: 3 PID: 3175 Comm: wificond Tainted: G O 4.19.42-00001-g531a5f5 #1 +[ 136.805532] Hardware name: Freescale i.MX8MQ EVK (DT) +[ 136.810584] pstate: 60400005 (nZCv daif +PAN -UAO) +[ 136.815429] pc : brcmf_pno_config_sched_scans+0x6cc/0xa80 [brcmfmac] +[ 136.821811] lr : brcmf_pno_config_sched_scans+0x67c/0xa80 [brcmfmac] +[ 136.828162] sp : ffff00000e9a3880 +[ 136.831475] x29: ffff00000e9a3890 x28: ffff800020543400 +[ 136.836786] x27: ffff8000b1008880 x26: ffff0000012bf6a0 +[ 136.842098] x25: ffff80002054345c x24: ffff800088d22400 +[ 136.847409] x23: ffff0000012bf638 x22: ffff0000012bf6d8 +[ 136.852721] x21: ffff8000aced8fc0 x20: ffff8000ac164400 +[ 136.858032] x19: ffff00000e9a3946 x18: 0000000000000000 +[ 136.863343] x17: 0000000000000000 x16: 0000000000000000 +[ 136.868655] x15: ffff0000093f3b37 x14: 0000000000000050 +[ 136.873966] x13: 0000000000003135 x12: 0000000000000000 +[ 136.879277] x11: 0000000000000000 x10: ffff000009a61888 +[ 136.884589] x9 : 000000000000000f x8 : 0000000000000008 +[ 136.889900] x7 : 303a32303d726464 x6 : ffff00000a1f957d +[ 136.895211] x5 : 0000000000000000 x4 : ffff00000e9a3942 +[ 136.900523] x3 : 0000000000000000 x2 : ffff0000012cead8 +[ 136.905834] x1 : ffff0000012bf6d8 x0 : 0000000000000000 +[ 136.911146] Call trace: +[ 136.913623] brcmf_pno_config_sched_scans+0x6cc/0xa80 [brcmfmac] +[ 136.919658] brcmf_pno_start_sched_scan+0xa4/0x118 [brcmfmac] +[ 136.925430] brcmf_cfg80211_sched_scan_start+0x80/0xe0 [brcmfmac] +[ 136.931636] nl80211_start_sched_scan+0x140/0x308 [cfg80211] +[ 136.937298] genl_rcv_msg+0x358/0x3f4 +[ 136.940960] netlink_rcv_skb+0xb4/0x118 +[ 136.944795] genl_rcv+0x34/0x48 +[ 136.947935] netlink_unicast+0x264/0x300 +[ 136.951856] netlink_sendmsg+0x2e4/0x33c +[ 136.955781] __sys_sendto+0x120/0x19c + +Signed-off-by: Wright Feng +Signed-off-by: Chi-hsien Lin +Signed-off-by: Ahmad Fatoum +Signed-off-by: Alvin Å ipraga +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220722115632.620681-4-alvin@pqrs.dk +Signed-off-by: Sasha Levin +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/pno.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +index fabfbb0b40b0..d0a7465be586 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c +@@ -158,12 +158,12 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) + struct brcmf_pno_macaddr_le pfn_mac; + u8 *mac_addr = NULL; + u8 *mac_mask = NULL; +- int err, i; ++ int err, i, ri; + +- for (i = 0; i < pi->n_reqs; i++) +- if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { +- mac_addr = pi->reqs[i]->mac_addr; +- mac_mask = pi->reqs[i]->mac_addr_mask; ++ for (ri = 0; ri < pi->n_reqs; ri++) ++ if (pi->reqs[ri]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { ++ mac_addr = pi->reqs[ri]->mac_addr; ++ mac_mask = pi->reqs[ri]->mac_addr_mask; + break; + } + +@@ -185,7 +185,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi) + pfn_mac.mac[0] |= 0x02; + + brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n", +- pi->reqs[i]->reqid, pfn_mac.mac); ++ pi->reqs[ri]->reqid, pfn_mac.mac); + err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac, + sizeof(pfn_mac)); + if (err) +-- +2.35.1 + diff --git a/queue-5.19/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_netdev.patch b/queue-5.19/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_netdev.patch new file mode 100644 index 00000000000..67f278692fc --- /dev/null +++ b/queue-5.19/wifi-brcmfmac-fix-use-after-free-bug-in-brcmf_netdev.patch @@ -0,0 +1,140 @@ +From 4a307d0ecff3399d8424af131f4496d9ca533267 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Aug 2022 10:49:26 -0700 +Subject: wifi: brcmfmac: fix use-after-free bug in brcmf_netdev_start_xmit() + +From: Alexander Coffin + +[ Upstream commit 3f42faf6db431e04bf942d2ebe3ae88975723478 ] + +> ret = brcmf_proto_tx_queue_data(drvr, ifp->ifidx, skb); + +may be schedule, and then complete before the line + +> ndev->stats.tx_bytes += skb->len; + +[ 46.912801] ================================================================== +[ 46.920552] BUG: KASAN: use-after-free in brcmf_netdev_start_xmit+0x718/0x8c8 [brcmfmac] +[ 46.928673] Read of size 4 at addr ffffff803f5882e8 by task systemd-resolve/328 +[ 46.935991] +[ 46.937514] CPU: 1 PID: 328 Comm: systemd-resolve Tainted: G O 5.4.199-[REDACTED] #1 +[ 46.947255] Hardware name: [REDACTED] +[ 46.954568] Call trace: +[ 46.957037] dump_backtrace+0x0/0x2b8 +[ 46.960719] show_stack+0x24/0x30 +[ 46.964052] dump_stack+0x128/0x194 +[ 46.967557] print_address_description.isra.0+0x64/0x380 +[ 46.972877] __kasan_report+0x1d4/0x240 +[ 46.976723] kasan_report+0xc/0x18 +[ 46.980138] __asan_report_load4_noabort+0x18/0x20 +[ 46.985027] brcmf_netdev_start_xmit+0x718/0x8c8 [brcmfmac] +[ 46.990613] dev_hard_start_xmit+0x1bc/0xda0 +[ 46.994894] sch_direct_xmit+0x198/0xd08 +[ 46.998827] __qdisc_run+0x37c/0x1dc0 +[ 47.002500] __dev_queue_xmit+0x1528/0x21f8 +[ 47.006692] dev_queue_xmit+0x24/0x30 +[ 47.010366] neigh_resolve_output+0x37c/0x678 +[ 47.014734] ip_finish_output2+0x598/0x2458 +[ 47.018927] __ip_finish_output+0x300/0x730 +[ 47.023118] ip_output+0x2e0/0x430 +[ 47.026530] ip_local_out+0x90/0x140 +[ 47.030117] igmpv3_sendpack+0x14c/0x228 +[ 47.034049] igmpv3_send_cr+0x384/0x6b8 +[ 47.037895] igmp_ifc_timer_expire+0x4c/0x118 +[ 47.042262] call_timer_fn+0x1cc/0xbe8 +[ 47.046021] __run_timers+0x4d8/0xb28 +[ 47.049693] run_timer_softirq+0x24/0x40 +[ 47.053626] __do_softirq+0x2c0/0x117c +[ 47.057387] irq_exit+0x2dc/0x388 +[ 47.060715] __handle_domain_irq+0xb4/0x158 +[ 47.064908] gic_handle_irq+0x58/0xb0 +[ 47.068581] el0_irq_naked+0x50/0x5c +[ 47.072162] +[ 47.073665] Allocated by task 328: +[ 47.077083] save_stack+0x24/0xb0 +[ 47.080410] __kasan_kmalloc.isra.0+0xc0/0xe0 +[ 47.084776] kasan_slab_alloc+0x14/0x20 +[ 47.088622] kmem_cache_alloc+0x15c/0x468 +[ 47.092643] __alloc_skb+0xa4/0x498 +[ 47.096142] igmpv3_newpack+0x158/0xd78 +[ 47.099987] add_grhead+0x210/0x288 +[ 47.103485] add_grec+0x6b0/0xb70 +[ 47.106811] igmpv3_send_cr+0x2e0/0x6b8 +[ 47.110657] igmp_ifc_timer_expire+0x4c/0x118 +[ 47.115027] call_timer_fn+0x1cc/0xbe8 +[ 47.118785] __run_timers+0x4d8/0xb28 +[ 47.122457] run_timer_softirq+0x24/0x40 +[ 47.126389] __do_softirq+0x2c0/0x117c +[ 47.130142] +[ 47.131643] Freed by task 180: +[ 47.134712] save_stack+0x24/0xb0 +[ 47.138041] __kasan_slab_free+0x108/0x180 +[ 47.142146] kasan_slab_free+0x10/0x18 +[ 47.145904] slab_free_freelist_hook+0xa4/0x1b0 +[ 47.150444] kmem_cache_free+0x8c/0x528 +[ 47.154292] kfree_skbmem+0x94/0x108 +[ 47.157880] consume_skb+0x10c/0x5a8 +[ 47.161466] __dev_kfree_skb_any+0x88/0xa0 +[ 47.165598] brcmu_pkt_buf_free_skb+0x44/0x68 [brcmutil] +[ 47.171023] brcmf_txfinalize+0xec/0x190 [brcmfmac] +[ 47.176016] brcmf_proto_bcdc_txcomplete+0x1c0/0x210 [brcmfmac] +[ 47.182056] brcmf_sdio_sendfromq+0x8dc/0x1e80 [brcmfmac] +[ 47.187568] brcmf_sdio_dpc+0xb48/0x2108 [brcmfmac] +[ 47.192529] brcmf_sdio_dataworker+0xc8/0x238 [brcmfmac] +[ 47.197859] process_one_work+0x7fc/0x1a80 +[ 47.201965] worker_thread+0x31c/0xc40 +[ 47.205726] kthread+0x2d8/0x370 +[ 47.208967] ret_from_fork+0x10/0x18 +[ 47.212546] +[ 47.214051] The buggy address belongs to the object at ffffff803f588280 +[ 47.214051] which belongs to the cache skbuff_head_cache of size 208 +[ 47.227086] The buggy address is located 104 bytes inside of +[ 47.227086] 208-byte region [ffffff803f588280, ffffff803f588350) +[ 47.238814] The buggy address belongs to the page: +[ 47.243618] page:ffffffff00dd6200 refcount:1 mapcount:0 mapping:ffffff804b6bf800 index:0xffffff803f589900 compound_mapcount: 0 +[ 47.255007] flags: 0x10200(slab|head) +[ 47.258689] raw: 0000000000010200 ffffffff00dfa980 0000000200000002 ffffff804b6bf800 +[ 47.266439] raw: ffffff803f589900 0000000080190018 00000001ffffffff 0000000000000000 +[ 47.274180] page dumped because: kasan: bad access detected +[ 47.279752] +[ 47.281251] Memory state around the buggy address: +[ 47.286051] ffffff803f588180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 47.293277] ffffff803f588200: fb fb fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 47.300502] >ffffff803f588280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb +[ 47.307723] ^ +[ 47.314343] ffffff803f588300: fb fb fb fb fb fb fb fb fb fb fc fc fc fc fc fc +[ 47.321569] ffffff803f588380: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb +[ 47.328789] ================================================================== + +Signed-off-by: Alexander Coffin +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220808174925.3922558-1-alex.coffin@matician.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +index 87aef211b35f..12ee8b7163fd 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -296,6 +296,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, + struct brcmf_pub *drvr = ifp->drvr; + struct ethhdr *eh; + int head_delta; ++ unsigned int tx_bytes = skb->len; + + brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx); + +@@ -370,7 +371,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, + ndev->stats.tx_dropped++; + } else { + ndev->stats.tx_packets++; +- ndev->stats.tx_bytes += skb->len; ++ ndev->stats.tx_bytes += tx_bytes; + } + + /* Return ok: we always eat the packet */ +-- +2.35.1 + diff --git a/queue-5.19/wifi-cfg80211-get-correct-ap-link-chandef.patch b/queue-5.19/wifi-cfg80211-get-correct-ap-link-chandef.patch new file mode 100644 index 00000000000..ade6f5d49f7 --- /dev/null +++ b/queue-5.19/wifi-cfg80211-get-correct-ap-link-chandef.patch @@ -0,0 +1,38 @@ +From 29973120777145e19af414d3db971148a7d1218c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 14:12:29 +0300 +Subject: wifi: cfg80211: get correct AP link chandef + +From: Shaul Triebitz + +[ Upstream commit bc1857619cc7612117d2ee1ed05b5bfeb638614b ] + +When checking for channel regulatory validity, use the +AP link chandef (and not mesh's chandef). + +Fixes: 7b0a0e3c3a88 ("wifi: cfg80211: do some rework towards MLO link APIs") +Signed-off-by: Shaul Triebitz +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/wireless/reg.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/wireless/reg.c b/net/wireless/reg.c +index c7383ede794f..d5c7a5aa6853 100644 +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -2389,6 +2389,10 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_P2P_GO: ++ if (!wdev->links[link].ap.beacon_interval) ++ continue; ++ chandef = wdev->links[link].ap.chandef; ++ break; + case NL80211_IFTYPE_MESH_POINT: + if (!wdev->u.mesh.beacon_interval) + continue; +-- +2.35.1 + diff --git a/queue-5.19/wifi-mac80211-allow-bw-change-during-channel-switch-.patch b/queue-5.19/wifi-mac80211-allow-bw-change-during-channel-switch-.patch new file mode 100644 index 00000000000..65acde42b8a --- /dev/null +++ b/queue-5.19/wifi-mac80211-allow-bw-change-during-channel-switch-.patch @@ -0,0 +1,47 @@ +From 163186d11168fbc3cfcdbb109a3a76a471d4f76d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 12:02:29 +0530 +Subject: wifi: mac80211: allow bw change during channel switch in mesh + +From: Hari Chandrakanthan + +[ Upstream commit 6b75f133fe05c36c52d691ff21545d5757fff721 ] + +From 'IEEE Std 802.11-2020 section 11.8.8.4.1': + The mesh channel switch may be triggered by the need to avoid + interference to a detected radar signal, or to reassign mesh STA + channels to ensure the MBSS connectivity. + + A 20/40 MHz MBSS may be changed to a 20 MHz MBSS and a 20 MHz + MBSS may be changed to a 20/40 MHz MBSS. + +Since the standard allows the change of bandwidth during +the channel switch in mesh, remove the bandwidth check present in +ieee80211_set_csa_beacon. + +Fixes: c6da674aff94 ("{nl,cfg,mac}80211: enable the triggering of CSA frame in mesh") +Signed-off-by: Hari Chandrakanthan +Link: https://lore.kernel.org/r/1658903549-21218-1-git-send-email-quic_haric@quicinc.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 9ca25ae503b0..37484c26259d 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -3545,9 +3545,6 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, + case NL80211_IFTYPE_MESH_POINT: { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + +- if (params->chandef.width != sdata->vif.bss_conf.chandef.width) +- return -EINVAL; +- + /* changes into another band are not supported */ + if (sdata->vif.bss_conf.chandef.chan->band != + params->chandef.chan->band) +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-connac-fix-possible-unaligned-access-in-mt.patch b/queue-5.19/wifi-mt76-connac-fix-possible-unaligned-access-in-mt.patch new file mode 100644 index 00000000000..c8c1e68ebb3 --- /dev/null +++ b/queue-5.19/wifi-mt76-connac-fix-possible-unaligned-access-in-mt.patch @@ -0,0 +1,42 @@ +From 9fdcf2e7244432fa38ee461be17686bcfbb0ab92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 16:12:06 +0200 +Subject: wifi: mt76: connac: fix possible unaligned access in + mt76_connac_mcu_add_nested_tlv + +From: Lorenzo Bianconi + +[ Upstream commit 0a4860f627f1f2b2b777f54f993de1638a79da9f ] + +Fix possible unaligned pointer in mt76_connac_mcu_add_nested_tlv +routine. + +Reported-by: kernel test robot +Fixes: 25702d9c55dc5 ("mt76: connac: rely on le16_add_cpu in mt76_connac_mcu_add_nested_tlv") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 7eb23805aa94..d10b441eac4f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -258,8 +258,10 @@ mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len, + ntlv = le16_to_cpu(ntlv_hdr->tlv_num); + ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1); + +- if (sta_hdr) +- le16_add_cpu(&sta_hdr->len, len); ++ if (sta_hdr) { ++ len += le16_to_cpu(sta_hdr->len); ++ sta_hdr->len = cpu_to_le16(len); ++ } + + return ptlv; + } +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7615-add-mt7615_mutex_acquire-release-in.patch b/queue-5.19/wifi-mt76-mt7615-add-mt7615_mutex_acquire-release-in.patch new file mode 100644 index 00000000000..308735a2c98 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7615-add-mt7615_mutex_acquire-release-in.patch @@ -0,0 +1,46 @@ +From de9d77b06e60ec5b0b18b7c8f830a27934c0db4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 10:26:40 +0200 +Subject: wifi: mt76: mt7615: add mt7615_mutex_acquire/release in + mt7615_sta_set_decap_offload + +From: Lorenzo Bianconi + +[ Upstream commit 765c69d477a44c088e5d19e7758dfa4db418e3ba ] + +Similar to mt7921 driver, introduce mt7615_mutex_acquire/release in +mt7615_sta_set_decap_offload in order to avoid sending mcu commands +while the device is in low-power state. + +Fixes: d4b98c63d7a77 ("mt76: mt7615: add support for rx decapsulation offload") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7615/main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +index d722c3c177be..4a1e6b92ff73 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c +@@ -1194,12 +1194,16 @@ static void mt7615_sta_set_decap_offload(struct ieee80211_hw *hw, + struct mt7615_dev *dev = mt7615_hw_dev(hw); + struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv; + ++ mt7615_mutex_acquire(dev); ++ + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else + clear_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + + mt7615_mcu_set_sta_decap_offload(dev, vif, sta); ++ ++ mt7615_mutex_release(dev); + } + + #ifdef CONFIG_PM +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7915-do-not-check-state-before-configuri.patch b/queue-5.19/wifi-mt76-mt7915-do-not-check-state-before-configuri.patch new file mode 100644 index 00000000000..009013b6a7f --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7915-do-not-check-state-before-configuri.patch @@ -0,0 +1,43 @@ +From 79a861cc8f2869d4945d50f631f373efa309e85c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Aug 2022 10:44:07 +0800 +Subject: wifi: mt76: mt7915: do not check state before configuring implicit + beamform + +From: Howard Hsu + +[ Upstream commit d2b5bb6dfab29fe32bedefaade88dcd182c03a00 ] + +Do not need to check running state before configuring implicit Tx +beamform. It is okay to configure implicit Tx beamform in run time. +Noted that the existing connected stations will be applied for new +configuration only if they reconnected to the interface. + +Fixes: 6d6dc980e07d ("mt76: mt7915: add implicit Tx beamforming support") +Signed-off-by: Howard Hsu +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +index fd76db8f5269..6ef3431cad64 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +@@ -23,9 +23,9 @@ mt7915_implicit_txbf_set(void *data, u64 val) + { + struct mt7915_dev *dev = data; + +- if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) +- return -EBUSY; +- ++ /* The existing connected stations shall reconnect to apply ++ * new implicit txbf configuration. ++ */ + dev->ibf = !!val; + + return mt7915_mcu_set_txbf(dev, MT_BF_TYPE_UPDATE); +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7915-fix-mcs-value-in-ht-mode.patch b/queue-5.19/wifi-mt76-mt7915-fix-mcs-value-in-ht-mode.patch new file mode 100644 index 00000000000..c662c669c26 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7915-fix-mcs-value-in-ht-mode.patch @@ -0,0 +1,56 @@ +From bdcfbe5d07df73a668c04fd0e651cc8bb44cfca2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Aug 2022 11:29:31 +0800 +Subject: wifi: mt76: mt7915: fix mcs value in ht mode + +From: Howard Hsu + +[ Upstream commit c6d3e16ad4362502e804a6ca01e955612f3b8222 ] + +Fix the error that mcs will be reduced to a range of 0 to 7 in ht mode. + +Fixes: 70fd1333cd32 ("mt76: mt7915: rework .set_bitrate_mask() to support more options") +Signed-off-by: Howard Hsu +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 17fa2acc0d07..ec8a5083466f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -1460,7 +1460,7 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, + struct sta_phy phy = {}; + int ret, nrates = 0; + +-#define __sta_phy_bitrate_mask_check(_mcs, _gi, _he) \ ++#define __sta_phy_bitrate_mask_check(_mcs, _gi, _ht, _he) \ + do { \ + u8 i, gi = mask->control[band]._gi; \ + gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI; \ +@@ -1473,15 +1473,17 @@ mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev, + continue; \ + nrates += hweight16(mask->control[band]._mcs[i]); \ + phy.mcs = ffs(mask->control[band]._mcs[i]) - 1; \ ++ if (_ht) \ ++ phy.mcs += 8 * i; \ + } \ + } while (0) + + if (sta->deflink.he_cap.has_he) { +- __sta_phy_bitrate_mask_check(he_mcs, he_gi, 1); ++ __sta_phy_bitrate_mask_check(he_mcs, he_gi, 0, 1); + } else if (sta->deflink.vht_cap.vht_supported) { +- __sta_phy_bitrate_mask_check(vht_mcs, gi, 0); ++ __sta_phy_bitrate_mask_check(vht_mcs, gi, 0, 0); + } else if (sta->deflink.ht_cap.ht_supported) { +- __sta_phy_bitrate_mask_check(ht_mcs, gi, 0); ++ __sta_phy_bitrate_mask_check(ht_mcs, gi, 1, 0); + } else { + nrates = hweight32(mask->control[band].legacy); + phy.mcs = ffs(mask->control[band].legacy) - 1; +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7915-fix-possible-unaligned-access-in-mt.patch b/queue-5.19/wifi-mt76-mt7915-fix-possible-unaligned-access-in-mt.patch new file mode 100644 index 00000000000..fef667ef3d7 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7915-fix-possible-unaligned-access-in-mt.patch @@ -0,0 +1,52 @@ +From e60de9fad47b4a60657d2a6d215116b3c1fcd7cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Jul 2022 11:50:03 +0200 +Subject: wifi: mt76: mt7915: fix possible unaligned access in + mt7915_mac_add_twt_setup + +From: Lorenzo Bianconi + +[ Upstream commit 3d9aa54355d863e5412a7e08180f50a8f1827b7f ] + +Fix possible unaligned pointer in mt7915_mac_add_twt_setup routine. + +Reported-by: kernel test robot +Fixes: 3782b69d03e71 ("mt76: mt7915: introduce mt7915_mac_add_twt_setup routine") +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +index 89f10bf885ba..4f3a3a88f086 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +@@ -2536,8 +2536,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, + } + + flowid = ffs(~msta->twt.flowid_mask) - 1; +- le16p_replace_bits(&twt_agrt->req_type, flowid, +- IEEE80211_TWT_REQTYPE_FLOWID); ++ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID); ++ twt_agrt->req_type |= le16_encode_bits(flowid, ++ IEEE80211_TWT_REQTYPE_FLOWID); + + table_id = ffs(~dev->twt.table_mask) - 1; + exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type); +@@ -2587,8 +2588,9 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw, + unlock: + mutex_unlock(&dev->mt76.mutex); + out: +- le16p_replace_bits(&twt_agrt->req_type, setup_cmd, +- IEEE80211_TWT_REQTYPE_SETUP_CMD); ++ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD); ++ twt_agrt->req_type |= ++ le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD); + twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) | + (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED); + } +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch b/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch new file mode 100644 index 00000000000..847522bedb6 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch @@ -0,0 +1,77 @@ +From 3b6ac4c3fdfb54efdca701b8a0060f27cdedb8a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 22:44:56 +0800 +Subject: wifi: mt76: mt7921: add mt7921_mutex_acquire at mt7921_[start, + stop]_ap + +From: Sean Wang + +[ Upstream commit 52b44015f031f629f1ce1d73415a2017593c7ade ] + +Add mt7921_mutex_acquire at mt7921_[start, stop]_ap to fix the race +with the context holding dev->muxtex and the driver might access the +device in low power state. + +Fixes: 9d958b60ebc2 ("mt76: mt7921: fix command timeout in AP stop period") +Tested-by: AngeloGioacchino Del Regno +Signed-off-by: Sean Wang +Acked-by: Lorenzo Bianconi +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7921/main.c | 21 ++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index d3f310877248..22c9793e4a40 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -1499,17 +1499,23 @@ mt7921_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) + struct mt7921_dev *dev = mt7921_hw_dev(hw); + int err; + ++ mt7921_mutex_acquire(dev); ++ + err = mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, + true); + if (err) +- return err; ++ goto out; + + err = mt7921_mcu_set_bss_pm(dev, vif, true); + if (err) +- return err; ++ goto out; ++ ++ err = mt7921_mcu_sta_update(dev, NULL, vif, true, ++ MT76_STA_INFO_STATE_NONE); ++out: ++ mt7921_mutex_release(dev); + +- return mt7921_mcu_sta_update(dev, NULL, vif, true, +- MT76_STA_INFO_STATE_NONE); ++ return err; + } + + static void +@@ -1520,11 +1526,16 @@ mt7921_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) + struct mt7921_dev *dev = mt7921_hw_dev(hw); + int err; + ++ mt7921_mutex_acquire(dev); ++ + err = mt7921_mcu_set_bss_pm(dev, vif, false); + if (err) +- return; ++ goto out; + + mt76_connac_mcu_uni_add_bss(phy->mt76, vif, &mvif->sta.wcid, false); ++ ++out: ++ mt7921_mutex_release(dev); + } + + const struct ieee80211_ops mt7921_ops = { +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch-23501 b/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch-23501 new file mode 100644 index 00000000000..3b97db93e6c --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921-add-mt7921_mutex_acquire-at-mt7921_.patch-23501 @@ -0,0 +1,49 @@ +From 52591a56708a74654ca46a9e06f72a56f3bea76b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jul 2022 22:44:57 +0800 +Subject: wifi: mt76: mt7921: add mt7921_mutex_acquire at + mt7921_sta_set_decap_offload + +From: Sean Wang + +[ Upstream commit 59c20b91786d5f140ee7be2f24c242b5f8986046 ] + +Add mt7921_mutex_acquire at mt7921_[start, stop]_ap to fix the race +with the context holding dev->muxtex and the driver might access the +device in low power state. + +Fixes: 24299fc869f7 ("mt76: mt7921: enable rx header traslation offload") +Tested-by: AngeloGioacchino Del Regno +Acked-by: Lorenzo Bianconi +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index 22c9793e4a40..0316d226e38d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -1390,6 +1390,8 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, + struct mt7921_sta *msta = (struct mt7921_sta *)sta->drv_priv; + struct mt7921_dev *dev = mt7921_hw_dev(hw); + ++ mt7921_mutex_acquire(dev); ++ + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &msta->wcid.flags); + else +@@ -1397,6 +1399,8 @@ static void mt7921_sta_set_decap_offload(struct ieee80211_hw *hw, + + mt76_connac_mcu_sta_update_hdr_trans(&dev->mt76, vif, &msta->wcid, + MCU_UNI_CMD(STA_REC_UPDATE)); ++ ++ mt7921_mutex_release(dev); + } + + #if IS_ENABLED(CONFIG_IPV6) +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921-reset-msta-airtime_ac-while-clearin.patch b/queue-5.19/wifi-mt76-mt7921-reset-msta-airtime_ac-while-clearin.patch new file mode 100644 index 00000000000..27c5a4daef7 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921-reset-msta-airtime_ac-while-clearin.patch @@ -0,0 +1,37 @@ +From 2ba0a2d29a1861dd02b5b9d20435a13deb2e0abd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 06:57:44 +0800 +Subject: wifi: mt76: mt7921: reset msta->airtime_ac while clearing up hw value + +From: Sean Wang + +[ Upstream commit 1bf66dc31032ff5292f4d5b76436653f269fcfbd ] + +We should reset mstat->airtime_ac along with clear up the entries in the +hardware WLAN table for the Rx and Rx accumulative airtime. Otherwsie, the +value msta->airtime_ac - [tx, rx]_last may be a negative and that is not +the actual airtime the device took in the last run. + +Reported-by: YN Chen +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +index 0316d226e38d..94dd0c1d4cb8 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c +@@ -738,6 +738,7 @@ void mt7921_mac_sta_assoc(struct mt76_dev *mdev, struct ieee80211_vif *vif, + + mt7921_mac_wtbl_update(dev, msta->wcid.idx, + MT_WTBL_UPDATE_ADM_COUNT_CLEAR); ++ memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac)); + + mt7921_mcu_sta_update(dev, sta, vif, true, MT76_STA_INFO_STATE_ASSOC); + +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921e-fix-race-issue-between-reset-and-s.patch b/queue-5.19/wifi-mt76-mt7921e-fix-race-issue-between-reset-and-s.patch new file mode 100644 index 00000000000..6eb26222d91 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921e-fix-race-issue-between-reset-and-s.patch @@ -0,0 +1,106 @@ +From dcb04af4f0efc0821b2a6cd1facc1435506b0abf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 06:25:37 +0800 +Subject: wifi: mt76: mt7921e: fix race issue between reset and suspend/resume + +From: Sean Wang + +[ Upstream commit ff6c4a6449793e9718ef2e9ad46864b63022648e ] + +It is unexpected that the reset work is running simultaneously with +the suspend or resume context and it is possible that reset work is still +running even after mt7921 is suspended if we don't fix the race issue. + +Thus, the suspend procedure should be waiting until the reset is completed +at the beginning and ignore the subsequent the reset requests. + +In case there is an error that happens during either suspend or resume +handler, we will schedule a reset task to recover the error before +returning the error code to ensure we can immediately fix the error there. + +Fixes: 0c1ce9884607 ("mt76: mt7921: add wifi reset support") +Co-developed-by: YN Chen +Signed-off-by: YN Chen +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 +++++ + drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 13 +++++++++---- + 2 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +index 2a2ea7b9977a..7e0cddc2aeab 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c +@@ -1215,6 +1215,7 @@ void mt7921_mac_reset_work(struct work_struct *work) + void mt7921_reset(struct mt76_dev *mdev) + { + struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); ++ struct mt76_connac_pm *pm = &dev->pm; + + if (!dev->hw_init_done) + return; +@@ -1222,8 +1223,12 @@ void mt7921_reset(struct mt76_dev *mdev) + if (dev->hw_full_reset) + return; + ++ if (pm->suspended) ++ return; ++ + queue_work(dev->mt76.wq, &dev->reset_work); + } ++EXPORT_SYMBOL_GPL(mt7921_reset); + + void mt7921_mac_update_mib_stats(struct mt7921_phy *phy) + { +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +index b5fb22b8e086..295c21586273 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +@@ -368,6 +368,7 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) + int i, err; + + pm->suspended = true; ++ flush_work(&dev->reset_work); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + +@@ -433,6 +434,9 @@ static int mt7921_pci_suspend(struct pci_dev *pdev, pm_message_t state) + restore_suspend: + pm->suspended = false; + ++ if (err < 0) ++ mt7921_reset(&dev->mt76); ++ + return err; + } + +@@ -451,7 +455,7 @@ static int mt7921_pci_resume(struct pci_dev *pdev) + + err = mt7921_mcu_drv_pmctrl(dev); + if (err < 0) +- return err; ++ goto failed; + + mt7921_wpdma_reinit_cond(dev); + +@@ -481,11 +485,12 @@ static int mt7921_pci_resume(struct pci_dev *pdev) + mt76_connac_mcu_set_deep_sleep(&dev->mt76, false); + + err = mt76_connac_mcu_set_hif_suspend(mdev, false); +- if (err) +- return err; +- ++failed: + pm->suspended = false; + ++ if (err < 0) ++ mt7921_reset(&dev->mt76); ++ + return err; + } + #endif /* CONFIG_PM */ +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921e-fix-rmmod-crash-in-driver-reload-t.patch b/queue-5.19/wifi-mt76-mt7921e-fix-rmmod-crash-in-driver-reload-t.patch new file mode 100644 index 00000000000..7f447cad325 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921e-fix-rmmod-crash-in-driver-reload-t.patch @@ -0,0 +1,70 @@ +From e55190d5be7ee52b023853ac20b4f7063338fb78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Sep 2022 20:39:43 +0800 +Subject: wifi: mt76: mt7921e: fix rmmod crash in driver reload test + +From: Deren Wu + +[ Upstream commit b5a62d612b7baf6e09884e4de94decb6391d6a9d ] + +In insmod/rmmod stress test, the following crash dump shows up immediately. +The problem is caused by missing mt76_dev in mt7921_pci_remove(). We +should make sure the drvdata is ready before probe() finished. + +[168.862789] ================================================================== +[168.862797] BUG: KASAN: user-memory-access in try_to_grab_pending+0x59/0x480 +[168.862805] Write of size 8 at addr 0000000000006df0 by task rmmod/5361 +[168.862812] CPU: 7 PID: 5361 Comm: rmmod Tainted: G OE 5.19.0-rc6 #1 +[168.862816] Hardware name: Intel(R) Client Systems NUC8i7BEH/NUC8BEB, 05/04/2020 +[168.862820] Call Trace: +[168.862822] +[168.862825] dump_stack_lvl+0x49/0x63 +[168.862832] print_report.cold+0x493/0x6b7 +[168.862845] kasan_report+0xa7/0x120 +[168.862857] kasan_check_range+0x163/0x200 +[168.862861] __kasan_check_write+0x14/0x20 +[168.862866] try_to_grab_pending+0x59/0x480 +[168.862870] __cancel_work_timer+0xbb/0x340 +[168.862898] cancel_work_sync+0x10/0x20 +[168.862902] mt7921_pci_remove+0x61/0x1c0 [mt7921e] +[168.862909] pci_device_remove+0xa3/0x1d0 +[168.862914] device_remove+0xc4/0x170 +[168.862920] device_release_driver_internal+0x163/0x300 +[168.862925] driver_detach+0xc7/0x1a0 +[168.862930] bus_remove_driver+0xeb/0x2d0 +[168.862935] driver_unregister+0x71/0xb0 +[168.862939] pci_unregister_driver+0x30/0x230 +[168.862944] mt7921_pci_driver_exit+0x10/0x1b [mt7921e] +[168.862949] __x64_sys_delete_module+0x2f9/0x4b0 +[168.862968] do_syscall_64+0x38/0x90 +[168.862973] entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Test steps: +1. insmode +2. do not ifup +3. rmmod quickly (within 1 second) + +Fixes: 1c71e03afe4b ("mt76: mt7921: move mt7921_init_hw in a dedicated work") +Signed-off-by: Deren Wu +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +index 295c21586273..d8347b33641e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c +@@ -289,6 +289,8 @@ static int mt7921_pci_probe(struct pci_dev *pdev, + goto err_free_pci_vec; + } + ++ pci_set_drvdata(pdev, mdev); ++ + dev = container_of(mdev, struct mt7921_dev, mt76); + dev->hif_ops = &mt7921_pcie_ops; + +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921s-fix-race-issue-between-reset-and-s.patch b/queue-5.19/wifi-mt76-mt7921s-fix-race-issue-between-reset-and-s.patch new file mode 100644 index 00000000000..47cece35de8 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921s-fix-race-issue-between-reset-and-s.patch @@ -0,0 +1,80 @@ +From 4bcd9aa5f3a92ff3878e6b4180885742b1cf6469 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 06:25:38 +0800 +Subject: wifi: mt76: mt7921s: fix race issue between reset and suspend/resume + +From: Sean Wang + +[ Upstream commit e86f10e6809add9132ecc2c6b3184ed59db7ca71 ] + +It is unexpected that the reset work is running simultaneously with +the suspend or resume context and it is possible that reset work is still +running even after mt7921 is suspended if we don't fix the race issue. + +Thus, the suspend procedure should be waiting until the reset is completed +at the beginning and ignore the subsequent the reset requests. + +In case there is an error that happens during either suspend or resume +handler, we will schedule a reset task to recover the error before +returning the error code to ensure we can immediately fix the error there. + +Fixes: ca74b9b907f9 ("mt76: mt7921s: add reset support") +Co-developed-by: YN Chen +Signed-off-by: YN Chen +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7921/sdio.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +index af26d59fa2f0..5610c63fe1e6 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/sdio.c +@@ -206,6 +206,7 @@ static int mt7921s_suspend(struct device *__dev) + pm->suspended = true; + set_bit(MT76_STATE_SUSPEND, &mdev->phy.state); + ++ flush_work(&dev->reset_work); + cancel_delayed_work_sync(&pm->ps_work); + cancel_work_sync(&pm->wake_work); + +@@ -261,6 +262,9 @@ static int mt7921s_suspend(struct device *__dev) + clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state); + pm->suspended = false; + ++ if (err < 0) ++ mt7921_reset(&dev->mt76); ++ + return err; + } + +@@ -276,7 +280,7 @@ static int mt7921s_resume(struct device *__dev) + + err = mt7921_mcu_drv_pmctrl(dev); + if (err < 0) +- return err; ++ goto failed; + + mt76_worker_enable(&mdev->tx_worker); + mt76_worker_enable(&mdev->sdio.txrx_worker); +@@ -288,11 +292,12 @@ static int mt7921s_resume(struct device *__dev) + mt76_connac_mcu_set_deep_sleep(mdev, false); + + err = mt76_connac_mcu_set_hif_suspend(mdev, false); +- if (err) +- return err; +- ++failed: + pm->suspended = false; + ++ if (err < 0) ++ mt7921_reset(&dev->mt76); ++ + return err; + } + +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-mt7921u-fix-race-issue-between-reset-and-s.patch b/queue-5.19/wifi-mt76-mt7921u-fix-race-issue-between-reset-and-s.patch new file mode 100644 index 00000000000..6bf41016884 --- /dev/null +++ b/queue-5.19/wifi-mt76-mt7921u-fix-race-issue-between-reset-and-s.patch @@ -0,0 +1,102 @@ +From de4db08997de4b13ac79156541ae4e8b4ef3bc90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Jul 2022 06:25:39 +0800 +Subject: wifi: mt76: mt7921u: fix race issue between reset and suspend/resume + +From: Sean Wang + +[ Upstream commit 86f15d043ba7f13211d5c3e41961c3381fb12880 ] + +It is unexpected that the reset work is running simultaneously with +the suspend or resume context and it is possible that reset work is still +running even after mt7921 is suspended if we don't fix the race issue. + +Thus, the suspend procedure should be waiting until the reset is completed +at the beginning and ignore the subsequent the reset requests. + +In case there is an error that happens during either suspend or resume +handler, we will schedule a reset task to recover the error before +returning the error code to ensure we can immediately fix the error there. + +Fixes: df3e4143ba8a ("mt76: mt7921u: add suspend/resume support") +Co-developed-by: YN Chen +Signed-off-by: YN Chen +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7921/usb.c | 28 ++++++++++++++++--- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +index dc38baef273a..25b4a8001b9e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c +@@ -292,11 +292,15 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf) + static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) + { + struct mt7921_dev *dev = usb_get_intfdata(intf); ++ struct mt76_connac_pm *pm = &dev->pm; + int err; + ++ pm->suspended = true; ++ flush_work(&dev->reset_work); ++ + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true); + if (err) +- return err; ++ goto failed; + + mt76u_stop_rx(&dev->mt76); + mt76u_stop_tx(&dev->mt76); +@@ -304,11 +308,20 @@ static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state) + set_bit(MT76_STATE_SUSPEND, &dev->mphy.state); + + return 0; ++ ++failed: ++ pm->suspended = false; ++ ++ if (err < 0) ++ mt7921_reset(&dev->mt76); ++ ++ return err; + } + + static int mt7921u_resume(struct usb_interface *intf) + { + struct mt7921_dev *dev = usb_get_intfdata(intf); ++ struct mt76_connac_pm *pm = &dev->pm; + bool reinit = true; + int err, i; + +@@ -330,16 +343,23 @@ static int mt7921u_resume(struct usb_interface *intf) + if (reinit || mt7921_dma_need_reinit(dev)) { + err = mt7921u_dma_init(dev, true); + if (err) +- return err; ++ goto failed; + } + + clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state); + + err = mt76u_resume_rx(&dev->mt76); + if (err < 0) +- return err; ++ goto failed; ++ ++ err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); ++failed: ++ pm->suspended = false; ++ ++ if (err < 0) ++ mt7921_reset(&dev->mt76); + +- return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false); ++ return err; + } + #endif /* CONFIG_PM */ + +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-sdio-fix-the-deadlock-caused-by-sdio-stat_.patch b/queue-5.19/wifi-mt76-sdio-fix-the-deadlock-caused-by-sdio-stat_.patch new file mode 100644 index 00000000000..ea9e1a25a54 --- /dev/null +++ b/queue-5.19/wifi-mt76-sdio-fix-the-deadlock-caused-by-sdio-stat_.patch @@ -0,0 +1,51 @@ +From d3588a0c6d85431d51c468b725294e3679621f40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 06:39:35 +0800 +Subject: wifi: mt76: sdio: fix the deadlock caused by sdio->stat_work + +From: Sean Wang + +[ Upstream commit e5d78fd998be94fb459a3d625df7367849b997b8 ] + +Because wake_work and sdio->stat_work share the same workqueue mt76->wq, +if sdio->stat_work cannot acquire the mutex lock such as that was possibly +held up by [mt7615, mt7921]_mutex_acquire. Additionally, if +[mt7615, mt7921]_mutex_acquire was called by sdio->stat_work self, the wake +would be blocked by itself. Thus, we move the stat_work into +ieee80211_workqueue instead to break the deadlock. + +Fixes: d39b52e31aa6 ("mt76: introduce mt76_sdio module") +Co-developed-by: YN Chen +Signed-off-by: YN Chen +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/sdio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c +index def7f325f5c5..574687ca93a9 100644 +--- a/drivers/net/wireless/mediatek/mt76/sdio.c ++++ b/drivers/net/wireless/mediatek/mt76/sdio.c +@@ -483,7 +483,7 @@ static void mt76s_status_worker(struct mt76_worker *w) + if (dev->drv->tx_status_data && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state) && + !test_bit(MT76_STATE_SUSPEND, &dev->phy.state)) +- queue_work(dev->wq, &dev->sdio.stat_work); ++ ieee80211_queue_work(dev->hw, &dev->sdio.stat_work); + } while (nframes > 0); + + if (resched) +@@ -510,7 +510,7 @@ static void mt76s_tx_status_data(struct work_struct *work) + } + + if (count && test_bit(MT76_STATE_RUNNING, &dev->phy.state)) +- queue_work(dev->wq, &sdio->stat_work); ++ ieee80211_queue_work(dev->hw, &sdio->stat_work); + else + clear_bit(MT76_READING_STATS, &dev->phy.state); + } +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-sdio-fix-transmitting-packet-hangs.patch b/queue-5.19/wifi-mt76-sdio-fix-transmitting-packet-hangs.patch new file mode 100644 index 00000000000..b8d44601bdb --- /dev/null +++ b/queue-5.19/wifi-mt76-sdio-fix-transmitting-packet-hangs.patch @@ -0,0 +1,37 @@ +From fe89ccf0c23754d5e55297df94ef7351b947b5d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Jul 2022 05:59:23 +0800 +Subject: wifi: mt76: sdio: fix transmitting packet hangs + +From: YN Chen + +[ Upstream commit 250b1827205846ff346a76044955cb79d4963f70 ] + +Fix transmitting packets hangs with continuing to pull the pending packet +from mac80211 queues when receiving Tx status notification from the device. + +Fixes: aac5104bf631 ("mt76: sdio: do not run mt76_txq_schedule directly") +Acked-by: Sean Wang +Signed-off-by: YN Chen +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c +index fa54ee112b0b..140145e03f12 100644 +--- a/drivers/net/wireless/mediatek/mt76/sdio.c ++++ b/drivers/net/wireless/mediatek/mt76/sdio.c +@@ -487,7 +487,7 @@ static void mt76s_status_worker(struct mt76_worker *w) + } while (nframes > 0); + + if (resched) +- mt76_worker_schedule(&dev->sdio.txrx_worker); ++ mt76_worker_schedule(&dev->tx_worker); + } + + static void mt76s_tx_status_data(struct work_struct *work) +-- +2.35.1 + diff --git a/queue-5.19/wifi-mt76-sdio-poll-sta-stat-when-device-transmits-d.patch b/queue-5.19/wifi-mt76-sdio-poll-sta-stat-when-device-transmits-d.patch new file mode 100644 index 00000000000..c6ed4c10a08 --- /dev/null +++ b/queue-5.19/wifi-mt76-sdio-poll-sta-stat-when-device-transmits-d.patch @@ -0,0 +1,41 @@ +From f08334086dc99242c2ed915a92fcd64f71a0cb0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Jul 2022 06:39:36 +0800 +Subject: wifi: mt76: sdio: poll sta stat when device transmits data + +From: Sean Wang + +[ Upstream commit a323e5f041dd11af5e3de19ed7ea95a97d588c11 ] + +It is not meaningful to poll sta stat when there is no data traffic. +So polling sta stat when the device has transmitted data instead to save +CPU power. + +That implies that it is unallowed the stat_work to work while MCU is being +initialized in the really early stage to fix the possible time to time MCU +initialization failure. + +Fixes: d39b52e31aa6 ("mt76: introduce mt76_sdio module") +Signed-off-by: Sean Wang +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/sdio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/sdio.c b/drivers/net/wireless/mediatek/mt76/sdio.c +index 574687ca93a9..fa54ee112b0b 100644 +--- a/drivers/net/wireless/mediatek/mt76/sdio.c ++++ b/drivers/net/wireless/mediatek/mt76/sdio.c +@@ -480,7 +480,7 @@ static void mt76s_status_worker(struct mt76_worker *w) + if (ndata_frames > 0) + resched = true; + +- if (dev->drv->tx_status_data && ++ if (dev->drv->tx_status_data && ndata_frames > 0 && + !test_and_set_bit(MT76_READING_STATS, &dev->phy.state) && + !test_bit(MT76_STATE_SUSPEND, &dev->phy.state)) + ieee80211_queue_work(dev->hw, &dev->sdio.stat_work); +-- +2.35.1 + diff --git a/queue-5.19/wifi-rt2x00-correctly-set-bbp-register-86-for-mt7620.patch b/queue-5.19/wifi-rt2x00-correctly-set-bbp-register-86-for-mt7620.patch new file mode 100644 index 00000000000..a4d70d3f2aa --- /dev/null +++ b/queue-5.19/wifi-rt2x00-correctly-set-bbp-register-86-for-mt7620.patch @@ -0,0 +1,40 @@ +From 3698f28d88792f701b7806a5fd22767e1c575b5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 21:30:09 +0100 +Subject: wifi: rt2x00: correctly set BBP register 86 for MT7620 + +From: Daniel Golle + +[ Upstream commit c9aada64fe6493461127f1522d7e2f01792d2424 ] + +Instead of 0 set the correct value for BBP register 86 for MT7620. + +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/257267247ee4fa7ebc6a5d0c4948b3f8119c0d77.1663445157.git.daniel@makrotopia.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +index 1efb80a98397..cf3ef44f18f2 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -4164,7 +4164,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +- rt2800_bbp_write(rt2x00dev, 86, 0); ++ if (rt2x00_rt(rt2x00dev, RT6352)) ++ rt2800_bbp_write(rt2x00dev, 86, 0x38); ++ else ++ rt2800_bbp_write(rt2x00dev, 86, 0); + } + + if (rf->channel <= 14) { +-- +2.35.1 + diff --git a/queue-5.19/wifi-rt2x00-don-t-run-rt5592-iq-calibration-on-mt762.patch b/queue-5.19/wifi-rt2x00-don-t-run-rt5592-iq-calibration-on-mt762.patch new file mode 100644 index 00000000000..df2522d5aa0 --- /dev/null +++ b/queue-5.19/wifi-rt2x00-don-t-run-rt5592-iq-calibration-on-mt762.patch @@ -0,0 +1,38 @@ +From 9bb8b4c5d07031d254c51135c14db1ed29ae250d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 21:28:29 +0100 +Subject: wifi: rt2x00: don't run Rt5592 IQ calibration on MT7620 + +From: Daniel Golle + +[ Upstream commit d3aad83d05aec0cfd7670cf0028f2ad4b81de92e ] + +The function rt2800_iq_calibrate is intended for Rt5592 only. +Don't call it for MT7620 which has it's own calibration functions. + +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/31a1c34ddbd296b82f38c18c9ae7339059215fdc.1663445157.git.daniel@makrotopia.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +index cbdaf7992f98..b4fb4d1bff57 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -4365,7 +4365,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain; + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +- rt2800_iq_calibrate(rt2x00dev, rf->channel); ++ if (rt2x00_rt(rt2x00dev, RT5592)) ++ rt2800_iq_calibrate(rt2x00dev, rf->channel); + } + + bbp = rt2800_bbp_read(rt2x00dev, 4); +-- +2.35.1 + diff --git a/queue-5.19/wifi-rt2x00-set-correct-tx_sw_cfg1-mac-register-for-.patch b/queue-5.19/wifi-rt2x00-set-correct-tx_sw_cfg1-mac-register-for-.patch new file mode 100644 index 00000000000..5ac851d1b95 --- /dev/null +++ b/queue-5.19/wifi-rt2x00-set-correct-tx_sw_cfg1-mac-register-for-.patch @@ -0,0 +1,39 @@ +From c2752056d984042e562175eb7dacdb911f81dc06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 21:29:26 +0100 +Subject: wifi: rt2x00: set correct TX_SW_CFG1 MAC register for MT7620 + +From: Daniel Golle + +[ Upstream commit eeb50acf15762b61921f9df18663f839f387c054 ] + +Set correct TX_SW_CFG1 MAC register as it is done also in v3 of the +vendor driver[1]. + +[1]: https://gitlab.com/dm38/padavan-ng/-/blob/master/trunk/proprietary/rt_wifi/rtpci/3.0.X.X/mt76x2/chips/rt6352.c#L531 +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/4be38975ce600a34249e12d09a3cb758c6e71071.1663445157.git.daniel@makrotopia.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +index b4fb4d1bff57..854637b1db49 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -5868,7 +5868,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + } else if (rt2x00_rt(rt2x00dev, RT6352)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401); +- rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000); ++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); + rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000); + rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0); +-- +2.35.1 + diff --git a/queue-5.19/wifi-rt2x00-set-soc-wmac-clock-register.patch b/queue-5.19/wifi-rt2x00-set-soc-wmac-clock-register.patch new file mode 100644 index 00000000000..2979303361c --- /dev/null +++ b/queue-5.19/wifi-rt2x00-set-soc-wmac-clock-register.patch @@ -0,0 +1,58 @@ +From b758d0afaf67021f87823e7b36b2a837ed2a3d12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 21:29:55 +0100 +Subject: wifi: rt2x00: set SoC wmac clock register + +From: Daniel Golle + +[ Upstream commit cbde6ed406a51092d9e8a2df058f5f8490f27443 ] + +Instead of using the default value 33 (pci), set US_CYC_CNT init based +on Programming guide: +If available, set chipset bus clock with fallback to cpu clock/3. + +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/3e275d259f476f597dab91a9c395015ef3fe3284.1663445157.git.daniel@makrotopia.org +Signed-off-by: Sasha Levin +--- + .../net/wireless/ralink/rt2x00/rt2800lib.c | 21 +++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +index c8fd4a1f9ed1..1efb80a98397 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -6131,6 +6131,27 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) + reg = rt2800_register_read(rt2x00dev, US_CYC_CNT); + rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125); + rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); ++ } else if (rt2x00_is_soc(rt2x00dev)) { ++ struct clk *clk = clk_get_sys("bus", NULL); ++ int rate; ++ ++ if (IS_ERR(clk)) { ++ clk = clk_get_sys("cpu", NULL); ++ ++ if (IS_ERR(clk)) { ++ rate = 125; ++ } else { ++ rate = clk_get_rate(clk) / 3000000; ++ clk_put(clk); ++ } ++ } else { ++ rate = clk_get_rate(clk) / 1000000; ++ clk_put(clk); ++ } ++ ++ reg = rt2800_register_read(rt2x00dev, US_CYC_CNT); ++ rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, rate); ++ rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); + } + + reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG0); +-- +2.35.1 + diff --git a/queue-5.19/wifi-rt2x00-set-vgc-gain-for-both-chains-of-mt7620.patch b/queue-5.19/wifi-rt2x00-set-vgc-gain-for-both-chains-of-mt7620.patch new file mode 100644 index 00000000000..f230a99ea3a --- /dev/null +++ b/queue-5.19/wifi-rt2x00-set-vgc-gain-for-both-chains-of-mt7620.patch @@ -0,0 +1,38 @@ +From a1b6fa302924719de8cb43b2a834ed12ba186768 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Sep 2022 21:29:40 +0100 +Subject: wifi: rt2x00: set VGC gain for both chains of MT7620 + +From: Daniel Golle + +[ Upstream commit 0e09768c085709e10ece3b68f6ac921d3f6a9caa ] + +Set bbp66 for all chains of the MT7620. + +Reported-by: Serge Vasilugin +Signed-off-by: Daniel Golle +Acked-by: Stanislaw Gruszka +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/29e161397e5c9d9399da0fe87d44458aa2b90a78.1663445157.git.daniel@makrotopia.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +index 854637b1db49..c8fd4a1f9ed1 100644 +--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +@@ -5645,7 +5645,8 @@ static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev, + if (qual->vgc_level != vgc_level) { + if (rt2x00_rt(rt2x00dev, RT3572) || + rt2x00_rt(rt2x00dev, RT3593) || +- rt2x00_rt(rt2x00dev, RT3883)) { ++ rt2x00_rt(rt2x00dev, RT3883) || ++ rt2x00_rt(rt2x00dev, RT6352)) { + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, + vgc_level); + } else if (rt2x00_rt(rt2x00dev, RT5592)) { +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-fix-aifs-written-to-reg_edca_-_param.patch b/queue-5.19/wifi-rtl8xxxu-fix-aifs-written-to-reg_edca_-_param.patch new file mode 100644 index 00000000000..003877adb88 --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-fix-aifs-written-to-reg_edca_-_param.patch @@ -0,0 +1,98 @@ +From 888f8bef70394e494eac215029d45f79f47d5d87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Sep 2022 15:42:25 +0300 +Subject: wifi: rtl8xxxu: Fix AIFS written to REG_EDCA_*_PARAM + +From: Bitterblue Smith + +[ Upstream commit 5574d3290449916397f3092dcd2bac92415498e1 ] + +ieee80211_tx_queue_params.aifs is not supposed to be written directly +to the REG_EDCA_*_PARAM registers. Instead process it like the vendor +drivers do. It's kinda hacky but it works. + +This change boosts the download speed and makes it more stable. + +Tested with RTL8188FU but all the other supported chips should also +benefit. + +Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") +Signed-off-by: Bitterblue Smith +Acked-by: Jes Sorensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/038cc03f-3567-77ba-a7bd-c4930e3b2fad@gmail.com +Signed-off-by: Sasha Levin +--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 49 +++++++++++++++++++ + 1 file changed, 49 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 5f9d6cce1114..57b5370a256b 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4560,6 +4560,53 @@ rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta) + return network_type; + } + ++static void rtl8xxxu_set_aifs(struct rtl8xxxu_priv *priv, u8 slot_time) ++{ ++ u32 reg_edca_param[IEEE80211_NUM_ACS] = { ++ [IEEE80211_AC_VO] = REG_EDCA_VO_PARAM, ++ [IEEE80211_AC_VI] = REG_EDCA_VI_PARAM, ++ [IEEE80211_AC_BE] = REG_EDCA_BE_PARAM, ++ [IEEE80211_AC_BK] = REG_EDCA_BK_PARAM, ++ }; ++ u32 val32; ++ u16 wireless_mode = 0; ++ u8 aifs, aifsn, sifs; ++ int i; ++ ++ if (priv->vif) { ++ struct ieee80211_sta *sta; ++ ++ rcu_read_lock(); ++ sta = ieee80211_find_sta(priv->vif, priv->vif->bss_conf.bssid); ++ if (sta) ++ wireless_mode = rtl8xxxu_wireless_mode(priv->hw, sta); ++ rcu_read_unlock(); ++ } ++ ++ if (priv->hw->conf.chandef.chan->band == NL80211_BAND_5GHZ || ++ (wireless_mode & WIRELESS_MODE_N_24G)) ++ sifs = 16; ++ else ++ sifs = 10; ++ ++ for (i = 0; i < IEEE80211_NUM_ACS; i++) { ++ val32 = rtl8xxxu_read32(priv, reg_edca_param[i]); ++ ++ /* It was set in conf_tx. */ ++ aifsn = val32 & 0xff; ++ ++ /* aifsn not set yet or already fixed */ ++ if (aifsn < 2 || aifsn > 15) ++ continue; ++ ++ aifs = aifsn * slot_time + sifs; ++ ++ val32 &= ~0xff; ++ val32 |= aifs; ++ rtl8xxxu_write32(priv, reg_edca_param[i], val32); ++ } ++} ++ + static void + rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf, u32 changed) +@@ -4679,6 +4726,8 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + else + val8 = 20; + rtl8xxxu_write8(priv, REG_SLOT, val8); ++ ++ rtl8xxxu_set_aifs(priv, val8); + } + + if (changed & BSS_CHANGED_BSSID) { +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-fix-skb-misuse-in-tx-queue-selection.patch b/queue-5.19/wifi-rtl8xxxu-fix-skb-misuse-in-tx-queue-selection.patch new file mode 100644 index 00000000000..f379de49659 --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-fix-skb-misuse-in-tx-queue-selection.patch @@ -0,0 +1,47 @@ +From 0cdcc55241bae3328f43967a21bb719c243d5f92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Aug 2022 19:12:36 +0300 +Subject: wifi: rtl8xxxu: Fix skb misuse in TX queue selection + +From: Bitterblue Smith + +[ Upstream commit edd5747aa12ed61a5ecbfa58d3908623fddbf1e8 ] + +rtl8xxxu_queue_select() selects the wrong TX queues because it's +reading memory from the wrong address. It expects to find ieee80211_hdr +at skb->data, but that's not the case after skb_push(). Move the call +to rtl8xxxu_queue_select() before the call to skb_push(). + +Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") +Signed-off-by: Bitterblue Smith +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/7fa4819a-4f20-b2af-b7a6-8ee01ac49295@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 7f09359a238f..03b04d6913d7 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -5062,6 +5062,8 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, + if (control && control->sta) + sta = control->sta; + ++ queue = rtl8xxxu_queue_select(hw, skb); ++ + tx_desc = skb_push(skb, tx_desc_size); + + memset(tx_desc, 0, tx_desc_size); +@@ -5074,7 +5076,6 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, + is_broadcast_ether_addr(ieee80211_get_DA(hdr))) + tx_desc->txdw0 |= TXDESC_BROADMULTICAST; + +- queue = rtl8xxxu_queue_select(hw, skb); + tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT); + + if (tx_info->control.hw_key) { +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-gen2-enable-40-mhz-channel-width.patch b/queue-5.19/wifi-rtl8xxxu-gen2-enable-40-mhz-channel-width.patch new file mode 100644 index 00000000000..085f3fe2ed1 --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-gen2-enable-40-mhz-channel-width.patch @@ -0,0 +1,123 @@ +From 8b6ad23bc6a861ee6cf72f2f2050a4f081487bb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 18 Sep 2022 15:40:56 +0300 +Subject: wifi: rtl8xxxu: gen2: Enable 40 MHz channel width + +From: Bitterblue Smith + +[ Upstream commit a8b5aef2cca15b7fa533421d462e4e0a3429bd6f ] + +The module parameter ht40_2g was supposed to enable 40 MHz operation, +but it didn't. + +Tell the firmware about the channel width when updating the rate mask. +This makes it work with my gen 2 chip RTL8188FU. + +I'm not sure if anything needs to be done for the gen 1 chips, if 40 +MHz channel width already works or not. They update the rate mask with +a different structure which doesn't have a field for the channel width. + +Also set the channel width correctly for sta_statistics. + +Fixes: f653e69009c6 ("rtl8xxxu: Implement basic 8723b specific update_rate_mask() function") +Fixes: bd917b3d28c9 ("rtl8xxxu: fill up txrate info for gen1 chips") +Signed-off-by: Bitterblue Smith +Acked-by: Jes Sorensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/3a950997-7580-8a6b-97a0-e0a81a135456@gmail.com +Signed-off-by: Sasha Levin +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 6 +++--- + .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 21 +++++++++++++------ + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +index 7ddce3c3f0c4..782b089a2e1b 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +@@ -1425,7 +1425,7 @@ struct rtl8xxxu_fileops { + void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel, + bool ht40); + void (*update_rate_mask) (struct rtl8xxxu_priv *priv, +- u32 ramask, u8 rateid, int sgi); ++ u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + void (*report_connect) (struct rtl8xxxu_priv *priv, + u8 macid, bool connect); + void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, +@@ -1511,9 +1511,9 @@ void rtl8xxxu_gen2_config_channel(struct ieee80211_hw *hw); + void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv); + void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv); + void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, +- u32 ramask, u8 rateid, int sgi); ++ u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, +- u32 ramask, u8 rateid, int sgi); ++ u32 ramask, u8 rateid, int sgi, int txbw_40mhz); + void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv, + u8 macid, bool connect); + void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv, +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 472b00c70781..5f9d6cce1114 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4320,7 +4320,7 @@ static void rtl8xxxu_sw_scan_complete(struct ieee80211_hw *hw, + } + + void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, +- u32 ramask, u8 rateid, int sgi) ++ u32 ramask, u8 rateid, int sgi, int txbw_40mhz) + { + struct h2c_cmd h2c; + +@@ -4340,10 +4340,15 @@ void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, + } + + void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, +- u32 ramask, u8 rateid, int sgi) ++ u32 ramask, u8 rateid, int sgi, int txbw_40mhz) + { + struct h2c_cmd h2c; +- u8 bw = RTL8XXXU_CHANNEL_WIDTH_20; ++ u8 bw; ++ ++ if (txbw_40mhz) ++ bw = RTL8XXXU_CHANNEL_WIDTH_40; ++ else ++ bw = RTL8XXXU_CHANNEL_WIDTH_20; + + memset(&h2c, 0, sizeof(struct h2c_cmd)); + +@@ -4621,7 +4626,11 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + RATE_INFO_FLAGS_SHORT_GI; + } + +- rarpt->txrate.bw |= RATE_INFO_BW_20; ++ if (rtl8xxxu_ht40_2g && ++ (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) ++ rarpt->txrate.bw = RATE_INFO_BW_40; ++ else ++ rarpt->txrate.bw = RATE_INFO_BW_20; + } + bit_rate = cfg80211_calculate_bitrate(&rarpt->txrate); + rarpt->bit_rate = bit_rate; +@@ -4630,7 +4639,7 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + priv->vif = vif; + priv->rssi_level = RTL8XXXU_RATR_STA_INIT; + +- priv->fops->update_rate_mask(priv, ramask, 0, sgi); ++ priv->fops->update_rate_mask(priv, ramask, 0, sgi, rarpt->txrate.bw == RATE_INFO_BW_40); + + rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff); + +@@ -6343,7 +6352,7 @@ static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv, + } + + priv->rssi_level = rssi_level; +- priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi); ++ priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi, txbw_40mhz); + } + } + +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-gen2-fix-mistake-in-path-b-iq-calibrat.patch b/queue-5.19/wifi-rtl8xxxu-gen2-fix-mistake-in-path-b-iq-calibrat.patch new file mode 100644 index 00000000000..86e467eaf37 --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-gen2-fix-mistake-in-path-b-iq-calibrat.patch @@ -0,0 +1,46 @@ +From 1636f408d8b2c6bc86505f2d54498669f88c5600 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 14:48:32 +0300 +Subject: wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration + +From: Bitterblue Smith + +[ Upstream commit e963a19c64ac0d2f8785d36a27391abd91ac77aa ] + +Found by comparing with the vendor driver. Currently this affects +only the RTL8192EU, which is the only gen2 chip with 2 TX paths +supported by this driver. It's unclear what kind of effect the +mistake had in practice, since I don't have any RTL8192EU devices +to test it. + +Fixes: e1547c535ede ("rtl8xxxu: First stab at adding IQK calibration for 8723bu parts") +Signed-off-by: Bitterblue Smith +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/30a59f3a-cfa9-8379-7af0-78a8f4c77cfd@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 03b04d6913d7..780a485eafd9 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -2929,12 +2929,12 @@ bool rtl8xxxu_gen2_simularity_compare(struct rtl8xxxu_priv *priv, + } + + if (!(simubitmap & 0x30) && priv->tx_paths > 1) { +- /* path B RX OK */ ++ /* path B TX OK */ + for (i = 4; i < 6; i++) + result[3][i] = result[c1][i]; + } + +- if (!(simubitmap & 0x30) && priv->tx_paths > 1) { ++ if (!(simubitmap & 0xc0) && priv->tx_paths > 1) { + /* path B RX OK */ + for (i = 6; i < 8; i++) + result[3][i] = result[c1][i]; +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-remove-copy-paste-leftover-in-gen2_upd.patch b/queue-5.19/wifi-rtl8xxxu-remove-copy-paste-leftover-in-gen2_upd.patch new file mode 100644 index 00000000000..403ea825b83 --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-remove-copy-paste-leftover-in-gen2_upd.patch @@ -0,0 +1,49 @@ +From a4e0854afc11b9df8c8f175603c21c1c0768997c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 16:15:30 +0300 +Subject: wifi: rtl8xxxu: Remove copy-paste leftover in gen2_update_rate_mask + +From: Bitterblue Smith + +[ Upstream commit d5350756c03cdf18696295c6b11d7acc4dbf825c ] + +It looks like a leftover from copying rtl8xxxu_update_rate_mask, +which is used with the gen1 chips. + +It wasn't causing any problems for my RTL8188FU test device, but it's +clearly a mistake, so remove it. + +Fixes: f653e69009c6 ("rtl8xxxu: Implement basic 8723b specific update_rate_mask() function") +Signed-off-by: Bitterblue Smith +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/d5544fe8-9798-28f1-54bd-6839a1974b10@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 780a485eafd9..472b00c70781 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -4353,15 +4353,14 @@ void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv, + h2c.b_macid_cfg.ramask2 = (ramask >> 16) & 0xff; + h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff; + +- h2c.ramask.arg = 0x80; + h2c.b_macid_cfg.data1 = rateid; + if (sgi) + h2c.b_macid_cfg.data1 |= BIT(7); + + h2c.b_macid_cfg.data2 = bw; + +- dev_dbg(&priv->udev->dev, "%s: rate mask %08x, arg %02x, size %zi\n", +- __func__, ramask, h2c.ramask.arg, sizeof(h2c.b_macid_cfg)); ++ dev_dbg(&priv->udev->dev, "%s: rate mask %08x, rateid %02x, sgi %d, size %zi\n", ++ __func__, ramask, rateid, sgi, sizeof(h2c.b_macid_cfg)); + rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.b_macid_cfg)); + } + +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtl8xxxu-tighten-bounds-checking-in-rtl8xxxu_re.patch b/queue-5.19/wifi-rtl8xxxu-tighten-bounds-checking-in-rtl8xxxu_re.patch new file mode 100644 index 00000000000..1b4eca252ee --- /dev/null +++ b/queue-5.19/wifi-rtl8xxxu-tighten-bounds-checking-in-rtl8xxxu_re.patch @@ -0,0 +1,59 @@ +From f8f9e10e059489f47fae6357fed049f4d39ff60e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 08:22:32 +0300 +Subject: wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse() + +From: Dan Carpenter + +[ Upstream commit 620d5eaeb9059636864bda83ca1c68c20ede34a5 ] + +There some bounds checking to ensure that "map_addr" is not out of +bounds before the start of the loop. But the checking needs to be +done as we iterate through the loop because "map_addr" gets larger as +we iterate. + +Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") +Signed-off-by: Dan Carpenter +Acked-by: Jes Sorensen +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/Yv8eGLdBslLAk3Ct@kili +Signed-off-by: Sasha Levin +--- + .../net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +index 8b2ca9e8eac6..7f09359a238f 100644 +--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c ++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +@@ -1878,13 +1878,6 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) + + /* We have 8 bits to indicate validity */ + map_addr = offset * 8; +- if (map_addr >= EFUSE_MAP_LEN) { +- dev_warn(dev, "%s: Illegal map_addr (%04x), " +- "efuse corrupt!\n", +- __func__, map_addr); +- ret = -EINVAL; +- goto exit; +- } + for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { + /* Check word enable condition in the section */ + if (word_mask & BIT(i)) { +@@ -1895,6 +1888,13 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv) + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8); + if (ret) + goto exit; ++ if (map_addr >= EFUSE_MAP_LEN - 1) { ++ dev_warn(dev, "%s: Illegal map_addr (%04x), " ++ "efuse corrupt!\n", ++ __func__, map_addr); ++ ret = -EINVAL; ++ goto exit; ++ } + priv->efuse_wifi.raw[map_addr++] = val8; + + ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8); +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtlwifi-8192de-correct-checking-of-iqk-reload.patch b/queue-5.19/wifi-rtlwifi-8192de-correct-checking-of-iqk-reload.patch new file mode 100644 index 00000000000..b92418246e2 --- /dev/null +++ b/queue-5.19/wifi-rtlwifi-8192de-correct-checking-of-iqk-reload.patch @@ -0,0 +1,52 @@ +From 17caafde9bbe50a7e751c2d66b65060644425a80 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Aug 2022 19:33:45 +0800 +Subject: wifi: rtlwifi: 8192de: correct checking of IQK reload + +From: Ping-Ke Shih + +[ Upstream commit 93fbc1ebd978cf408ef5765e9c1630fce9a8621b ] + +Since IQK could spend time, we make a cache of IQK result matrix that looks +like iqk_matrix[channel_idx].val[x][y], and we can reload the matrix if we +have made a cache. To determine a cache is made, we check +iqk_matrix[channel_idx].val[0][0]. + +The initial commit 7274a8c22980 ("rtlwifi: rtl8192de: Merge phy routines") +make a mistake that checks incorrect iqk_matrix[channel_idx].val[0] that +is always true, and this mistake is found by commit ee3db469dd31 +("wifi: rtlwifi: remove always-true condition pointed out by GCC 12"), so +I recall the vendor driver to find fix and apply the correctness. + +Fixes: 7274a8c22980 ("rtlwifi: rtl8192de: Merge phy routines") +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220801113345.42016-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +index 15e6a6aded31..d18c092b6142 100644 +--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c ++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c +@@ -2386,11 +2386,10 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel) + rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, + "Just Read IQK Matrix reg for channel:%d....\n", + channel); +- _rtl92d_phy_patha_fill_iqk_matrix(hw, true, +- rtlphy->iqk_matrix[ +- indexforchannel].value, 0, +- (rtlphy->iqk_matrix[ +- indexforchannel].value[0][2] == 0)); ++ if (rtlphy->iqk_matrix[indexforchannel].value[0][0] != 0) ++ _rtl92d_phy_patha_fill_iqk_matrix(hw, true, ++ rtlphy->iqk_matrix[indexforchannel].value, 0, ++ rtlphy->iqk_matrix[indexforchannel].value[0][2] == 0); + if (IS_92D_SINGLEPHY(rtlhal->version)) { + if ((rtlphy->iqk_matrix[ + indexforchannel].value[0][4] != 0) +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw88-add-missing-destroy_workqueue-on-error-pa.patch b/queue-5.19/wifi-rtw88-add-missing-destroy_workqueue-on-error-pa.patch new file mode 100644 index 00000000000..7fc2d3b169a --- /dev/null +++ b/queue-5.19/wifi-rtw88-add-missing-destroy_workqueue-on-error-pa.patch @@ -0,0 +1,56 @@ +From dfdfceeea4eec2e7635a527c22bb0bfa4d7a4bae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 10:38:17 +0800 +Subject: wifi: rtw88: add missing destroy_workqueue() on error path in + rtw_core_init() + +From: Yang Yingliang + +[ Upstream commit b0ea758b30bbdf7c4323c78b7c50c05d2e1224d5 ] + +Add the missing destroy_workqueue() before return from rtw_core_init() +in error path. + +Fixes: fe101716c7c9 ("rtw88: replace tx tasklet with work queue") +Signed-off-by: Yang Yingliang +Reviewed-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220826023817.3908255-1-yangyingliang@huawei.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/main.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c +index 645ef1d01895..c364482ab331 100644 +--- a/drivers/net/wireless/realtek/rtw88/main.c ++++ b/drivers/net/wireless/realtek/rtw88/main.c +@@ -2037,7 +2037,7 @@ int rtw_core_init(struct rtw_dev *rtwdev) + ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW); + if (ret) { + rtw_warn(rtwdev, "no firmware loaded\n"); +- return ret; ++ goto out; + } + + if (chip->wow_fw_name) { +@@ -2047,11 +2047,15 @@ int rtw_core_init(struct rtw_dev *rtwdev) + wait_for_completion(&rtwdev->fw.completion); + if (rtwdev->fw.firmware) + release_firmware(rtwdev->fw.firmware); +- return ret; ++ goto out; + } + } + + return 0; ++ ++out: ++ destroy_workqueue(rtwdev->tx_wq); ++ return ret; + } + EXPORT_SYMBOL(rtw_core_init); + +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw88-phy-fix-warning-of-possible-buffer-overfl.patch b/queue-5.19/wifi-rtw88-phy-fix-warning-of-possible-buffer-overfl.patch new file mode 100644 index 00000000000..5fb1b8fe046 --- /dev/null +++ b/queue-5.19/wifi-rtw88-phy-fix-warning-of-possible-buffer-overfl.patch @@ -0,0 +1,68 @@ +From 595e6963b3c99ffe2b76c2f62a1d896f3215fc46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Jul 2022 14:50:03 +0800 +Subject: wifi: rtw88: phy: fix warning of possible buffer overflow + +From: Zong-Zhe Yang + +[ Upstream commit 86331c7e0cd819bf0c1d0dcf895e0c90b0aa9a6f ] + +reported by smatch + +phy.c:854 rtw_phy_linear_2_db() error: buffer overflow 'db_invert_table[i]' +8 <= 8 (assuming for loop doesn't break) + +However, it seems to be a false alarm because we prevent it originally via + if (linear >= db_invert_table[11][7]) + return 96; /* maximum 96 dB */ + +Still, we adjust the code to be more readable and avoid smatch warning. + +Signed-off-by: Zong-Zhe Yang +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220727065003.28340-5-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw88/phy.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c +index 8982e0c98dac..da1efec0aa85 100644 +--- a/drivers/net/wireless/realtek/rtw88/phy.c ++++ b/drivers/net/wireless/realtek/rtw88/phy.c +@@ -816,23 +816,18 @@ static u8 rtw_phy_linear_2_db(u64 linear) + u8 j; + u32 dB; + +- if (linear >= db_invert_table[11][7]) +- return 96; /* maximum 96 dB */ +- + for (i = 0; i < 12; i++) { +- if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][7]) +- break; +- else if (i > 2 && linear <= db_invert_table[i][7]) +- break; ++ for (j = 0; j < 8; j++) { ++ if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) ++ goto cnt; ++ else if (i > 2 && linear <= db_invert_table[i][j]) ++ goto cnt; ++ } + } + +- for (j = 0; j < 8; j++) { +- if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) +- break; +- else if (i > 2 && linear <= db_invert_table[i][j]) +- break; +- } ++ return 96; /* maximum 96 dB */ + ++cnt: + if (j == 0 && i == 0) + goto end; + +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw89-fix-rx-filter-after-scan.patch b/queue-5.19/wifi-rtw89-fix-rx-filter-after-scan.patch new file mode 100644 index 00000000000..6d9e477e0dc --- /dev/null +++ b/queue-5.19/wifi-rtw89-fix-rx-filter-after-scan.patch @@ -0,0 +1,65 @@ +From 756a9c7cdadf5e1e6cfb39d3fe52f69579ef2b46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 11:38:10 +0800 +Subject: wifi: rtw89: fix rx filter after scan + +From: Po-Hao Huang + +[ Upstream commit 812825c2b204c491f1a5586c602e4ac75060493a ] + +In monitor mode we should be able to received all packets even if it's not +destined to us. But after scan, the configuration was wrongly set, so we +fix it. + +Signed-off-by: Po-Hao Huang +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220916033811.13862-7-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/fw.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c +index 4718aced1428..e7f86d84d91d 100644 +--- a/drivers/net/wireless/realtek/rtw89/fw.c ++++ b/drivers/net/wireless/realtek/rtw89/fw.c +@@ -2288,6 +2288,7 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + { + struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + struct cfg80211_scan_request *req = &scan_req->req; ++ u32 rx_fltr = rtwdev->hal.rx_fltr; + u8 mac_addr[ETH_ALEN]; + + rtwdev->scan_info.scanning_vif = vif; +@@ -2302,13 +2303,13 @@ void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + ether_addr_copy(mac_addr, vif->addr); + rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, true); + +- rtwdev->hal.rx_fltr &= ~B_AX_A_BCN_CHK_EN; +- rtwdev->hal.rx_fltr &= ~B_AX_A_BC; +- rtwdev->hal.rx_fltr &= ~B_AX_A_A1_MATCH; ++ rx_fltr &= ~B_AX_A_BCN_CHK_EN; ++ rx_fltr &= ~B_AX_A_BC; ++ rx_fltr &= ~B_AX_A_A1_MATCH; + rtw89_write32_mask(rtwdev, + rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + B_AX_RX_FLTR_CFG_MASK, +- rtwdev->hal.rx_fltr); ++ rx_fltr); + } + + void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, +@@ -2322,9 +2323,6 @@ void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, + if (!vif) + return; + +- rtwdev->hal.rx_fltr |= B_AX_A_BCN_CHK_EN; +- rtwdev->hal.rx_fltr |= B_AX_A_BC; +- rtwdev->hal.rx_fltr |= B_AX_A_A1_MATCH; + rtw89_write32_mask(rtwdev, + rtw89_mac_reg_by_idx(R_AX_RX_FLTR_OPT, RTW89_MAC_0), + B_AX_RX_FLTR_CFG_MASK, +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw89-free-unused-skb-to-prevent-memory-leak.patch b/queue-5.19/wifi-rtw89-free-unused-skb-to-prevent-memory-leak.patch new file mode 100644 index 00000000000..8656c28cd15 --- /dev/null +++ b/queue-5.19/wifi-rtw89-free-unused-skb-to-prevent-memory-leak.patch @@ -0,0 +1,35 @@ +From bb988ef1645d62cd7d5e69db1804da95ab677eee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Sep 2022 11:38:09 +0800 +Subject: wifi: rtw89: free unused skb to prevent memory leak + +From: Po-Hao Huang + +[ Upstream commit eae672f386049146058b9e5d3d33e9e4af9dca1d ] + +This avoid potential memory leak under power saving mode. + +Signed-off-by: Po-Hao Huang +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220916033811.13862-6-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c +index a6a90572e74b..7313eb80fb1e 100644 +--- a/drivers/net/wireless/realtek/rtw89/core.c ++++ b/drivers/net/wireless/realtek/rtw89/core.c +@@ -860,6 +860,7 @@ int rtw89_h2c_tx(struct rtw89_dev *rtwdev, + rtw89_debug(rtwdev, RTW89_DBG_FW, + "ignore h2c due to power is off with firmware state=%d\n", + test_bit(RTW89_FLAG_FW_RDY, rtwdev->flags)); ++ dev_kfree_skb(skb); + return 0; + } + +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw89-pci-correct-tx-resource-checking-in-low-p.patch b/queue-5.19/wifi-rtw89-pci-correct-tx-resource-checking-in-low-p.patch new file mode 100644 index 00000000000..421fbb6beac --- /dev/null +++ b/queue-5.19/wifi-rtw89-pci-correct-tx-resource-checking-in-low-p.patch @@ -0,0 +1,41 @@ +From 878d434261e7c9febe545eb0eddf4c25aa141508 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 14:33:12 +0800 +Subject: wifi: rtw89: pci: correct TX resource checking in low power mode + +From: Ping-Ke Shih + +[ Upstream commit 4a29213cd775cabcbe395229d175903accedbb9d ] + +Number of TX resource must be minimum of TX_BD and TX_WD. Only considering +TX_BD could drop TX packets pulled from mac80211 if TX_WD is unavailable. + +Fixes: 52edbb9fb78a ("rtw89: ps: access TX/RX rings via another registers in low power mode") +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220824063312.15784-2-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/pci.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c +index 622f95bc3ffc..bc8132e91992 100644 +--- a/drivers/net/wireless/realtek/rtw89/pci.c ++++ b/drivers/net/wireless/realtek/rtw89/pci.c +@@ -922,10 +922,12 @@ u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev, + { + struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv; + struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch]; ++ struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring; + u32 cnt; + + spin_lock_bh(&rtwpci->trx_lock); + cnt = rtw89_pci_get_avail_txbd_num(tx_ring); ++ cnt = min(cnt, wd_ring->curr_num); + spin_unlock_bh(&rtwpci->trx_lock); + + return cnt; +-- +2.35.1 + diff --git a/queue-5.19/wifi-rtw89-pci-fix-interrupt-stuck-after-leaving-low.patch b/queue-5.19/wifi-rtw89-pci-fix-interrupt-stuck-after-leaving-low.patch new file mode 100644 index 00000000000..4f01b1ff2e0 --- /dev/null +++ b/queue-5.19/wifi-rtw89-pci-fix-interrupt-stuck-after-leaving-low.patch @@ -0,0 +1,42 @@ +From cfe86ddf3786dfe9b1db6b06f5ede16f56daae7a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 14:33:11 +0800 +Subject: wifi: rtw89: pci: fix interrupt stuck after leaving low power mode + +From: Ping-Ke Shih + +[ Upstream commit b7e715d3dcd2e9fa3a689ba0dd7ab85f8aaf6e9a ] + +We turn off interrupt in ISR, and re-enable interrupt in threadfn or +napi_poll according to the mode it stays. If we are turning off interrupt, +rtwpci->running flag is unset and interrupt handler stop processing even +if it was called, so disallow to re-enable interrupt in this situation. +Or, wifi chip doesn't trigger interrupt events anymore because interrupt +status (ISR) isn't clear by interrupt handler anymore. + +Fixes: c83dcd0508e2 ("rtw89: pci: add a separate interrupt handler for low power mode") +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220824063312.15784-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/realtek/rtw89/pci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c +index 0ef7821b2e0f..622f95bc3ffc 100644 +--- a/drivers/net/wireless/realtek/rtw89/pci.c ++++ b/drivers/net/wireless/realtek/rtw89/pci.c +@@ -756,7 +756,8 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev) + + enable_intr: + spin_lock_irqsave(&rtwpci->irq_lock, flags); +- rtw89_chip_enable_intr(rtwdev, rtwpci); ++ if (likely(rtwpci->running)) ++ rtw89_chip_enable_intr(rtwdev, rtwpci); + spin_unlock_irqrestore(&rtwpci->irq_lock, flags); + return IRQ_HANDLED; + } +-- +2.35.1 + diff --git a/queue-5.19/wifi-wfx-prevent-underflow-in-wfx_send_pds.patch b/queue-5.19/wifi-wfx-prevent-underflow-in-wfx_send_pds.patch new file mode 100644 index 00000000000..216d83e62b1 --- /dev/null +++ b/queue-5.19/wifi-wfx-prevent-underflow-in-wfx_send_pds.patch @@ -0,0 +1,44 @@ +From 87d1401f7f6a3e998da9483aabbce4c57c9e5546 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Aug 2022 08:23:43 +0300 +Subject: wifi: wfx: prevent underflow in wfx_send_pds() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dan Carpenter + +[ Upstream commit f97c81f5b7f8047810b0d79a8f759a83951210a0 ] + +This does a "chunk_len - 4" subtraction later when it calls: + + ret = wfx_hif_configuration(wdev, buf + 4, chunk_len - 4); + +so check for "chunk_len" is less than 4. + +Fixes: dcbecb497908 ("staging: wfx: allow new PDS format") +Signed-off-by: Dan Carpenter +Reviewed-by: Jérôme Pouiller +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/Yv8eX7Xv2ubUOvW7@kili +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/silabs/wfx/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/silabs/wfx/main.c b/drivers/net/wireless/silabs/wfx/main.c +index e015bfb8d221..84d82ddded56 100644 +--- a/drivers/net/wireless/silabs/wfx/main.c ++++ b/drivers/net/wireless/silabs/wfx/main.c +@@ -181,7 +181,7 @@ int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) + while (len > 0) { + chunk_type = get_unaligned_le16(buf + 0); + chunk_len = get_unaligned_le16(buf + 2); +- if (chunk_len > len) { ++ if (chunk_len < 4 || chunk_len > len) { + dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num); + return -EINVAL; + } +-- +2.35.1 + diff --git a/queue-5.19/x86-apic-don-t-disable-x2apic-if-locked.patch b/queue-5.19/x86-apic-don-t-disable-x2apic-if-locked.patch new file mode 100644 index 00000000000..b150d7ce532 --- /dev/null +++ b/queue-5.19/x86-apic-don-t-disable-x2apic-if-locked.patch @@ -0,0 +1,227 @@ +From eb7ee8a1ffaf4f75d805a1a16874c40098d71a0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Aug 2022 16:19:42 -0700 +Subject: x86/apic: Don't disable x2APIC if locked + +From: Daniel Sneddon + +[ Upstream commit b8d1d163604bd1e600b062fb00de5dc42baa355f ] + +The APIC supports two modes, legacy APIC (or xAPIC), and Extended APIC +(or x2APIC). X2APIC mode is mostly compatible with legacy APIC, but +it disables the memory-mapped APIC interface in favor of one that uses +MSRs. The APIC mode is controlled by the EXT bit in the APIC MSR. + +The MMIO/xAPIC interface has some problems, most notably the APIC LEAK +[1]. This bug allows an attacker to use the APIC MMIO interface to +extract data from the SGX enclave. + +Introduce support for a new feature that will allow the BIOS to lock +the APIC in x2APIC mode. If the APIC is locked in x2APIC mode and the +kernel tries to disable the APIC or revert to legacy APIC mode a GP +fault will occur. + +Introduce support for a new MSR (IA32_XAPIC_DISABLE_STATUS) and handle +the new locked mode when the LEGACY_XAPIC_DISABLED bit is set by +preventing the kernel from trying to disable the x2APIC. + +On platforms with the IA32_XAPIC_DISABLE_STATUS MSR, if SGX or TDX are +enabled the LEGACY_XAPIC_DISABLED will be set by the BIOS. If +legacy APIC is required, then it SGX and TDX need to be disabled in the +BIOS. + +[1]: https://aepicleak.com/aepicleak.pdf + +Signed-off-by: Daniel Sneddon +Signed-off-by: Dave Hansen +Acked-by: Dave Hansen +Tested-by: Neelima Krishnan +Link: https://lkml.kernel.org/r/20220816231943.1152579-1-daniel.sneddon@linux.intel.com +Signed-off-by: Sasha Levin +--- + .../admin-guide/kernel-parameters.txt | 4 ++ + arch/x86/Kconfig | 7 ++- + arch/x86/include/asm/cpu.h | 2 + + arch/x86/include/asm/msr-index.h | 13 ++++++ + arch/x86/kernel/apic/apic.c | 44 +++++++++++++++++-- + 5 files changed, 65 insertions(+), 5 deletions(-) + +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 1b38d0f70677..5ef5d727ca34 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -3765,6 +3765,10 @@ + + nox2apic [X86-64,APIC] Do not enable x2APIC mode. + ++ NOTE: this parameter will be ignored on systems with the ++ LEGACY_XAPIC_DISABLED bit set in the ++ IA32_XAPIC_DISABLE_STATUS MSR. ++ + nps_mtm_hs_ctr= [KNL,ARC] + This parameter sets the maximum duration, in + cycles, each HW thread of the CTOP can run +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 25e2b8b75e40..1cccedfc2a48 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -450,6 +450,11 @@ config X86_X2APIC + This allows 32-bit apic IDs (so it can support very large systems), + and accesses the local apic via MSRs not via mmio. + ++ Some Intel systems circa 2022 and later are locked into x2APIC mode ++ and can not fall back to the legacy APIC modes if SGX or TDX are ++ enabled in the BIOS. They will be unable to boot without enabling ++ this option. ++ + If you don't know what to do here, say N. + + config X86_MPPARSE +@@ -1930,7 +1935,7 @@ endchoice + + config X86_SGX + bool "Software Guard eXtensions (SGX)" +- depends on X86_64 && CPU_SUP_INTEL ++ depends on X86_64 && CPU_SUP_INTEL && X86_X2APIC + depends on CRYPTO=y + depends on CRYPTO_SHA256=y + select SRCU +diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h +index 8cbf623f0ecf..b472ef76826a 100644 +--- a/arch/x86/include/asm/cpu.h ++++ b/arch/x86/include/asm/cpu.h +@@ -94,4 +94,6 @@ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1, + return p1 & p2; + } + ++extern u64 x86_read_arch_cap_msr(void); ++ + #endif /* _ASM_X86_CPU_H */ +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index e057e039173c..9267bfe3c33f 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -155,6 +155,11 @@ + * Return Stack Buffer Predictions. + */ + ++#define ARCH_CAP_XAPIC_DISABLE BIT(21) /* ++ * IA32_XAPIC_DISABLE_STATUS MSR ++ * supported ++ */ ++ + #define MSR_IA32_FLUSH_CMD 0x0000010b + #define L1D_FLUSH BIT(0) /* + * Writeback and invalidate the +@@ -1046,4 +1051,12 @@ + #define MSR_IA32_HW_FEEDBACK_PTR 0x17d0 + #define MSR_IA32_HW_FEEDBACK_CONFIG 0x17d1 + ++/* x2APIC locked status */ ++#define MSR_IA32_XAPIC_DISABLE_STATUS 0xBD ++#define LEGACY_XAPIC_DISABLED BIT(0) /* ++ * x2APIC mode is locked and ++ * disabling x2APIC will cause ++ * a #GP ++ */ ++ + #endif /* _ASM_X86_MSR_INDEX_H */ +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index 189d3a5e471a..665993b2e80d 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + + unsigned int num_processors; + +@@ -1756,11 +1757,26 @@ EXPORT_SYMBOL_GPL(x2apic_mode); + + enum { + X2APIC_OFF, +- X2APIC_ON, + X2APIC_DISABLED, ++ /* All states below here have X2APIC enabled */ ++ X2APIC_ON, ++ X2APIC_ON_LOCKED + }; + static int x2apic_state; + ++static bool x2apic_hw_locked(void) ++{ ++ u64 ia32_cap; ++ u64 msr; ++ ++ ia32_cap = x86_read_arch_cap_msr(); ++ if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) { ++ rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr); ++ return (msr & LEGACY_XAPIC_DISABLED); ++ } ++ return false; ++} ++ + static void __x2apic_disable(void) + { + u64 msr; +@@ -1798,6 +1814,10 @@ static int __init setup_nox2apic(char *str) + apicid); + return 0; + } ++ if (x2apic_hw_locked()) { ++ pr_warn("APIC locked in x2apic mode, can't disable\n"); ++ return 0; ++ } + pr_warn("x2apic already enabled.\n"); + __x2apic_disable(); + } +@@ -1812,10 +1832,18 @@ early_param("nox2apic", setup_nox2apic); + void x2apic_setup(void) + { + /* +- * If x2apic is not in ON state, disable it if already enabled ++ * Try to make the AP's APIC state match that of the BSP, but if the ++ * BSP is unlocked and the AP is locked then there is a state mismatch. ++ * Warn about the mismatch in case a GP fault occurs due to a locked AP ++ * trying to be turned off. ++ */ ++ if (x2apic_state != X2APIC_ON_LOCKED && x2apic_hw_locked()) ++ pr_warn("x2apic lock mismatch between BSP and AP.\n"); ++ /* ++ * If x2apic is not in ON or LOCKED state, disable it if already enabled + * from BIOS. + */ +- if (x2apic_state != X2APIC_ON) { ++ if (x2apic_state < X2APIC_ON) { + __x2apic_disable(); + return; + } +@@ -1836,6 +1864,11 @@ static __init void x2apic_disable(void) + if (x2apic_id >= 255) + panic("Cannot disable x2apic, id: %08x\n", x2apic_id); + ++ if (x2apic_hw_locked()) { ++ pr_warn("Cannot disable locked x2apic, id: %08x\n", x2apic_id); ++ return; ++ } ++ + __x2apic_disable(); + register_lapic_address(mp_lapic_addr); + } +@@ -1894,7 +1927,10 @@ void __init check_x2apic(void) + if (x2apic_enabled()) { + pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n"); + x2apic_mode = 1; +- x2apic_state = X2APIC_ON; ++ if (x2apic_hw_locked()) ++ x2apic_state = X2APIC_ON_LOCKED; ++ else ++ x2apic_state = X2APIC_ON; + } else if (!boot_cpu_has(X86_FEATURE_X2APIC)) { + x2apic_state = X2APIC_DISABLED; + } +-- +2.35.1 + diff --git a/queue-5.19/x86-cpu-include-the-header-of-init_ia32_feat_ctl-s-p.patch b/queue-5.19/x86-cpu-include-the-header-of-init_ia32_feat_ctl-s-p.patch new file mode 100644 index 00000000000..b1fa230a9ed --- /dev/null +++ b/queue-5.19/x86-cpu-include-the-header-of-init_ia32_feat_ctl-s-p.patch @@ -0,0 +1,66 @@ +From c687913db890955eb536b92e0930844954dd7406 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Sep 2022 17:00:54 -0300 +Subject: x86/cpu: Include the header of init_ia32_feat_ctl()'s prototype +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Luciano Leão + +[ Upstream commit 30ea703a38ef76ca119673cd8bdd05c6e068e2ac ] + +Include the header containing the prototype of init_ia32_feat_ctl(), +solving the following warning: + + $ make W=1 arch/x86/kernel/cpu/feat_ctl.o + arch/x86/kernel/cpu/feat_ctl.c:112:6: warning: no previous prototype for ‘init_ia32_feat_ctl’ [-Wmissing-prototypes] + 112 | void init_ia32_feat_ctl(struct cpuinfo_x86 *c) + +This warning appeared after commit + + 5d5103595e9e5 ("x86/cpu: Reinitialize IA32_FEAT_CTL MSR on BSP during wakeup") + +had moved the function init_ia32_feat_ctl()'s prototype from +arch/x86/kernel/cpu/cpu.h to arch/x86/include/asm/cpu.h. + +Note that, before the commit mentioned above, the header include "cpu.h" +(arch/x86/kernel/cpu/cpu.h) was added by commit + + 0e79ad863df43 ("x86/cpu: Fix a -Wmissing-prototypes warning for init_ia32_feat_ctl()") + +solely to fix init_ia32_feat_ctl()'s missing prototype. So, the header +include "cpu.h" is no longer necessary. + + [ bp: Massage commit message. ] + +Fixes: 5d5103595e9e5 ("x86/cpu: Reinitialize IA32_FEAT_CTL MSR on BSP during wakeup") +Signed-off-by: Luciano Leão +Signed-off-by: Borislav Petkov +Reviewed-by: Nícolas F. R. A. Prado +Link: https://lore.kernel.org/r/20220922200053.1357470-1-lucianorsleao@gmail.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/feat_ctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/cpu/feat_ctl.c b/arch/x86/kernel/cpu/feat_ctl.c +index da696eb4821a..e77032c5f85c 100644 +--- a/arch/x86/kernel/cpu/feat_ctl.c ++++ b/arch/x86/kernel/cpu/feat_ctl.c +@@ -1,11 +1,11 @@ + // SPDX-License-Identifier: GPL-2.0 + #include + ++#include + #include + #include + #include + #include +-#include "cpu.h" + + #undef pr_fmt + #define pr_fmt(fmt) "x86/cpu: " fmt +-- +2.35.1 + diff --git a/queue-5.19/x86-entry-work-around-clang-__bdos-bug.patch b/queue-5.19/x86-entry-work-around-clang-__bdos-bug.patch new file mode 100644 index 00000000000..6e1947cc09a --- /dev/null +++ b/queue-5.19/x86-entry-work-around-clang-__bdos-bug.patch @@ -0,0 +1,66 @@ +From f3ae9cbacef25c9346dabec5faffd458f03ab731 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Sep 2022 19:45:14 -0700 +Subject: x86/entry: Work around Clang __bdos() bug + +From: Kees Cook + +[ Upstream commit 3e1730842f142add55dc658929221521a9ea62b6 ] + +Clang produces a false positive when building with CONFIG_FORTIFY_SOURCE=y +and CONFIG_UBSAN_BOUNDS=y when operating on an array with a dynamic +offset. Work around this by using a direct assignment of an empty +instance. Avoids this warning: + +../include/linux/fortify-string.h:309:4: warning: call to __write_overflow_field declared with 'warn +ing' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Wat +tribute-warning] + __write_overflow_field(p_size_field, size); + ^ + +which was isolated to the memset() call in xen_load_idt(). + +Note that this looks very much like another bug that was worked around: +https://github.com/ClangBuiltLinux/linux/issues/1592 + +Cc: Juergen Gross +Cc: Boris Ostrovsky +Cc: Thomas Gleixner +Cc: Ingo Molnar +Cc: Borislav Petkov +Cc: Dave Hansen +Cc: x86@kernel.org +Cc: "H. Peter Anvin" +Cc: xen-devel@lists.xenproject.org +Reviewed-by: Boris Ostrovsky +Link: https://lore.kernel.org/lkml/41527d69-e8ab-3f86-ff37-6b298c01d5bc@oracle.com +Signed-off-by: Kees Cook +Signed-off-by: Sasha Levin +--- + arch/x86/xen/enlighten_pv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c +index 0ed2e487a693..9b1a58dda935 100644 +--- a/arch/x86/xen/enlighten_pv.c ++++ b/arch/x86/xen/enlighten_pv.c +@@ -765,6 +765,7 @@ static void xen_load_idt(const struct desc_ptr *desc) + { + static DEFINE_SPINLOCK(lock); + static struct trap_info traps[257]; ++ static const struct trap_info zero = { }; + unsigned out; + + trace_xen_cpu_load_idt(desc); +@@ -774,7 +775,7 @@ static void xen_load_idt(const struct desc_ptr *desc) + memcpy(this_cpu_ptr(&idt_desc), desc, sizeof(idt_desc)); + + out = xen_convert_trap_info(desc, traps, false); +- memset(&traps[out], 0, sizeof(traps[0])); ++ traps[out] = zero; + + xen_mc_flush(); + if (HYPERVISOR_set_trap_table(traps)) +-- +2.35.1 + diff --git a/queue-5.19/x86-hyperv-fix-struct-hv_enlightened_vmcs-definition.patch b/queue-5.19/x86-hyperv-fix-struct-hv_enlightened_vmcs-definition.patch new file mode 100644 index 00000000000..8f9b0d0de71 --- /dev/null +++ b/queue-5.19/x86-hyperv-fix-struct-hv_enlightened_vmcs-definition.patch @@ -0,0 +1,68 @@ +From 5c93350f2ab0782fd287e046b7a099e73d2b756f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 15:37:05 +0200 +Subject: x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition + +From: Vitaly Kuznetsov + +[ Upstream commit ea9da788a61e47e7ab9cbad397453e51cd82ac0d ] + +Section 1.9 of TLFS v6.0b says: + +"All structures are padded in such a way that fields are aligned +naturally (that is, an 8-byte field is aligned to an offset of 8 bytes +and so on)". + +'struct enlightened_vmcs' has a glitch: + +... + struct { + u32 nested_flush_hypercall:1; /* 836: 0 4 */ + u32 msr_bitmap:1; /* 836: 1 4 */ + u32 reserved:30; /* 836: 2 4 */ + } hv_enlightenments_control; /* 836 4 */ + u32 hv_vp_id; /* 840 4 */ + u64 hv_vm_id; /* 844 8 */ + u64 partition_assist_page; /* 852 8 */ +... + +And the observed values in 'partition_assist_page' make no sense at +all. Fix the layout by padding the structure properly. + +Fixes: 68d1eb72ee99 ("x86/hyper-v: define struct hv_enlightened_vmcs and clean field bits") +Reviewed-by: Maxim Levitsky +Reviewed-by: Michael Kelley +Signed-off-by: Vitaly Kuznetsov +Signed-off-by: Sean Christopherson +Link: https://lore.kernel.org/r/20220830133737.1539624-2-vkuznets@redhat.com +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/hyperv-tlfs.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h +index 0a9407dc0859..6f0acc45e67a 100644 +--- a/arch/x86/include/asm/hyperv-tlfs.h ++++ b/arch/x86/include/asm/hyperv-tlfs.h +@@ -546,7 +546,7 @@ struct hv_enlightened_vmcs { + u64 guest_rip; + + u32 hv_clean_fields; +- u32 hv_padding_32; ++ u32 padding32_1; + u32 hv_synthetic_controls; + struct { + u32 nested_flush_hypercall:1; +@@ -554,7 +554,7 @@ struct hv_enlightened_vmcs { + u32 reserved:30; + } __packed hv_enlightenments_control; + u32 hv_vp_id; +- ++ u32 padding32_2; + u64 hv_vm_id; + u64 partition_assist_page; + u64 padding64_4[4]; +-- +2.35.1 + diff --git a/queue-5.19/x86-mce-retrieve-poison-range-from-hardware.patch b/queue-5.19/x86-mce-retrieve-poison-range-from-hardware.patch new file mode 100644 index 00000000000..9ae89afd54b --- /dev/null +++ b/queue-5.19/x86-mce-retrieve-poison-range-from-hardware.patch @@ -0,0 +1,72 @@ +From 8b3a58c290e02ff6362a923638d9e7b111e716c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Aug 2022 17:38:51 -0600 +Subject: x86/mce: Retrieve poison range from hardware + +From: Jane Chu + +[ Upstream commit f9781bb18ed828e7b83b7bac4a4ad7cd497ee7d7 ] + +When memory poison consumption machine checks fire, MCE notifier +handlers like nfit_handle_mce() record the impacted physical address +range which is reported by the hardware in the MCi_MISC MSR. The error +information includes data about blast radius, i.e. how many cachelines +did the hardware determine are impacted. A recent change + + 7917f9cdb503 ("acpi/nfit: rely on mce->misc to determine poison granularity") + +updated nfit_handle_mce() to stop hard coding the blast radius value of +1 cacheline, and instead rely on the blast radius reported in 'struct +mce' which can be up to 4K (64 cachelines). + +It turns out that apei_mce_report_mem_error() had a similar problem in +that it hard coded a blast radius of 4K rather than reading the blast +radius from the error information. Fix apei_mce_report_mem_error() to +convey the proper poison granularity. + +Signed-off-by: Jane Chu +Signed-off-by: Borislav Petkov +Reviewed-by: Dan Williams +Reviewed-by: Ingo Molnar +Link: https://lore.kernel.org/r/7ed50fd8-521e-cade-77b1-738b8bfb8502@oracle.com +Link: https://lore.kernel.org/r/20220826233851.1319100-1-jane.chu@oracle.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/mce/apei.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c +index 717192915f28..8ed341714686 100644 +--- a/arch/x86/kernel/cpu/mce/apei.c ++++ b/arch/x86/kernel/cpu/mce/apei.c +@@ -29,15 +29,26 @@ + void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err) + { + struct mce m; ++ int lsb; + + if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) + return; + ++ /* ++ * Even if the ->validation_bits are set for address mask, ++ * to be extra safe, check and reject an error radius '0', ++ * and fall back to the default page size. ++ */ ++ if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK) ++ lsb = find_first_bit((void *)&mem_err->physical_addr_mask, PAGE_SHIFT); ++ else ++ lsb = PAGE_SHIFT; ++ + mce_setup(&m); + m.bank = -1; + /* Fake a memory read error with unknown channel */ + m.status = MCI_STATUS_VAL | MCI_STATUS_EN | MCI_STATUS_ADDRV | MCI_STATUS_MISCV | 0x9f; +- m.misc = (MCI_MISC_ADDR_PHYS << 6) | PAGE_SHIFT; ++ m.misc = (MCI_MISC_ADDR_PHYS << 6) | lsb; + + if (severity >= GHES_SEV_RECOVERABLE) + m.status |= MCI_STATUS_UC; +-- +2.35.1 + diff --git a/queue-5.19/x86-microcode-amd-track-patch-allocation-size-explic.patch b/queue-5.19/x86-microcode-amd-track-patch-allocation-size-explic.patch new file mode 100644 index 00000000000..36a0429ca03 --- /dev/null +++ b/queue-5.19/x86-microcode-amd-track-patch-allocation-size-explic.patch @@ -0,0 +1,64 @@ +From 4d5ae13adb7c3b16809e90b6436112dbd94df7ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 20:10:10 -0700 +Subject: x86/microcode/AMD: Track patch allocation size explicitly + +From: Kees Cook + +[ Upstream commit 712f210a457d9c32414df246a72781550bc23ef6 ] + +In preparation for reducing the use of ksize(), record the actual +allocation size for later memcpy(). This avoids copying extra +(uninitialized!) bytes into the patch buffer when the requested +allocation size isn't exactly the size of a kmalloc bucket. +Additionally, fix potential future issues where runtime bounds checking +will notice that the buffer was allocated to a smaller value than +returned by ksize(). + +Fixes: 757885e94a22 ("x86, microcode, amd: Early microcode patch loading support for AMD") +Suggested-by: Daniel Micay +Signed-off-by: Kees Cook +Signed-off-by: Borislav Petkov +Link: https://lore.kernel.org/lkml/CA+DvKQ+bp7Y7gmaVhacjv9uF6Ar-o4tet872h4Q8RPYPJjcJQA@mail.gmail.com/ +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/microcode.h | 1 + + arch/x86/kernel/cpu/microcode/amd.c | 3 ++- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h +index 0c3d3440fe27..aa675783412f 100644 +--- a/arch/x86/include/asm/microcode.h ++++ b/arch/x86/include/asm/microcode.h +@@ -9,6 +9,7 @@ + struct ucode_patch { + struct list_head plist; + void *data; /* Intel uses only this one */ ++ unsigned int size; + u32 patch_id; + u16 equiv_cpu; + }; +diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c +index 8b2fcdfa6d31..615bc6efa1dd 100644 +--- a/arch/x86/kernel/cpu/microcode/amd.c ++++ b/arch/x86/kernel/cpu/microcode/amd.c +@@ -788,6 +788,7 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover, + kfree(patch); + return -EINVAL; + } ++ patch->size = *patch_size; + + mc_hdr = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE); + proc_id = mc_hdr->processor_rev_id; +@@ -869,7 +870,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size) + return ret; + + memset(amd_ucode_patch, 0, PATCH_MAX_SIZE); +- memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), PATCH_MAX_SIZE)); ++ memcpy(amd_ucode_patch, p->data, min_t(u32, p->size, PATCH_MAX_SIZE)); + + return ret; + } +-- +2.35.1 + diff --git a/queue-5.19/x86-paravirt-add-extra-clobbers-with-zero_call_used_.patch b/queue-5.19/x86-paravirt-add-extra-clobbers-with-zero_call_used_.patch new file mode 100644 index 00000000000..e86c6c7e948 --- /dev/null +++ b/queue-5.19/x86-paravirt-add-extra-clobbers-with-zero_call_used_.patch @@ -0,0 +1,108 @@ +From 3679a868217f485008bc8b2abd0c68623b96e9c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Sep 2022 21:37:50 +0000 +Subject: x86/paravirt: add extra clobbers with ZERO_CALL_USED_REGS enabled + +From: Bill Wendling + +[ Upstream commit 8c86f29bfb18465d15b05cfd26a6454ec787b793 ] + +The ZERO_CALL_USED_REGS feature may zero out caller-saved registers +before returning. + +In spurious_kernel_fault(), the "pte_offset_kernel()" call results in +this assembly code: + +.Ltmp151: + #APP + # ALT: oldnstr +.Ltmp152: +.Ltmp153: +.Ltmp154: + .section .discard.retpoline_safe,"",@progbits + .quad .Ltmp154 + .text + + callq *pv_ops+536(%rip) + +.Ltmp155: + .section .parainstructions,"a",@progbits + .p2align 3, 0x0 + .quad .Ltmp153 + .byte 67 + .byte .Ltmp155-.Ltmp153 + .short 1 + .text +.Ltmp156: + # ALT: padding + .zero (-(((.Ltmp157-.Ltmp158)-(.Ltmp156-.Ltmp152))>0))*((.Ltmp157-.Ltmp158)-(.Ltmp156-.Ltmp152)),144 +.Ltmp159: + .section .altinstructions,"a",@progbits +.Ltmp160: + .long .Ltmp152-.Ltmp160 +.Ltmp161: + .long .Ltmp158-.Ltmp161 + .short 33040 + .byte .Ltmp159-.Ltmp152 + .byte .Ltmp157-.Ltmp158 + .text + + .section .altinstr_replacement,"ax",@progbits + # ALT: replacement 1 +.Ltmp158: + movq %rdi, %rax +.Ltmp157: + .text + #NO_APP +.Ltmp162: + testb $-128, %dil + +The "testb" here is using %dil, but the %rdi register was cleared before +returning from "callq *pv_ops+536(%rip)". Adding the proper constraints +results in the use of a different register: + + movq %r11, %rdi + + # Similar to above. + + testb $-128, %r11b + +Link: https://github.com/KSPP/linux/issues/192 +Signed-off-by: Bill Wendling +Reported-and-tested-by: Nathan Chancellor +Fixes: 035f7f87b729 ("randstruct: Enable Clang support") +Reviewed-by: Juergen Gross +Link: https://lore.kernel.org/lkml/fa6df43b-8a1a-8ad1-0236-94d2a0b588fa@suse.com/ +Signed-off-by: Kees Cook +Link: https://lore.kernel.org/r/20220902213750.1124421-3-morbo@google.com +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/paravirt_types.h | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h +index 89df6c6617f5..bc2e1b67319d 100644 +--- a/arch/x86/include/asm/paravirt_types.h ++++ b/arch/x86/include/asm/paravirt_types.h +@@ -414,8 +414,17 @@ int paravirt_disable_iospace(void); + "=c" (__ecx) + #define PVOP_CALL_CLOBBERS PVOP_VCALL_CLOBBERS, "=a" (__eax) + +-/* void functions are still allowed [re]ax for scratch */ ++/* ++ * void functions are still allowed [re]ax for scratch. ++ * ++ * The ZERO_CALL_USED REGS feature may end up zeroing out callee-saved ++ * registers. Make sure we model this with the appropriate clobbers. ++ */ ++#ifdef CONFIG_ZERO_CALL_USED_REGS ++#define PVOP_VCALLEE_CLOBBERS "=a" (__eax), PVOP_VCALL_CLOBBERS ++#else + #define PVOP_VCALLEE_CLOBBERS "=a" (__eax) ++#endif + #define PVOP_CALLEE_CLOBBERS PVOP_VCALLEE_CLOBBERS + + #define EXTRA_CLOBBERS , "r8", "r9", "r10", "r11" +-- +2.35.1 + diff --git a/queue-5.19/x86-resctrl-fix-to-restore-to-original-value-when-re.patch b/queue-5.19/x86-resctrl-fix-to-restore-to-original-value-when-re.patch new file mode 100644 index 00000000000..560886c7d14 --- /dev/null +++ b/queue-5.19/x86-resctrl-fix-to-restore-to-original-value-when-re.patch @@ -0,0 +1,108 @@ +From e087e39b65ccff3aa347863abea5e365b9ff58fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 09:44:10 -0700 +Subject: x86/resctrl: Fix to restore to original value when re-enabling + hardware prefetch register + +From: Kohei Tarumizu + +[ Upstream commit 499c8bb4693d1c8d8f3d6dd38e5bdde3ff5bd906 ] + +The current pseudo_lock.c code overwrites the value of the +MSR_MISC_FEATURE_CONTROL to 0 even if the original value is not 0. +Therefore, modify it to save and restore the original values. + +Fixes: 018961ae5579 ("x86/intel_rdt: Pseudo-lock region creation/removal core") +Fixes: 443810fe6160 ("x86/intel_rdt: Create debugfs files for pseudo-locking testing") +Fixes: 8a2fc0e1bc0c ("x86/intel_rdt: More precise L2 hit/miss measurements") +Signed-off-by: Kohei Tarumizu +Signed-off-by: Dave Hansen +Acked-by: Reinette Chatre +Link: https://lkml.kernel.org/r/eb660f3c2010b79a792c573c02d01e8e841206ad.1661358182.git.reinette.chatre@intel.com +Signed-off-by: Sasha Levin +--- + arch/x86/kernel/cpu/resctrl/pseudo_lock.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +index db813f819ad6..4d8398986f78 100644 +--- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c ++++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +@@ -420,6 +420,7 @@ static int pseudo_lock_fn(void *_rdtgrp) + struct pseudo_lock_region *plr = rdtgrp->plr; + u32 rmid_p, closid_p; + unsigned long i; ++ u64 saved_msr; + #ifdef CONFIG_KASAN + /* + * The registers used for local register variables are also used +@@ -463,6 +464,7 @@ static int pseudo_lock_fn(void *_rdtgrp) + * the buffer and evict pseudo-locked memory read earlier from the + * cache. + */ ++ saved_msr = __rdmsr(MSR_MISC_FEATURE_CONTROL); + __wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); + closid_p = this_cpu_read(pqr_state.cur_closid); + rmid_p = this_cpu_read(pqr_state.cur_rmid); +@@ -514,7 +516,7 @@ static int pseudo_lock_fn(void *_rdtgrp) + __wrmsr(IA32_PQR_ASSOC, rmid_p, closid_p); + + /* Re-enable the hardware prefetcher(s) */ +- wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0); ++ wrmsrl(MSR_MISC_FEATURE_CONTROL, saved_msr); + local_irq_enable(); + + plr->thread_done = 1; +@@ -871,6 +873,7 @@ bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d) + static int measure_cycles_lat_fn(void *_plr) + { + struct pseudo_lock_region *plr = _plr; ++ u32 saved_low, saved_high; + unsigned long i; + u64 start, end; + void *mem_r; +@@ -879,6 +882,7 @@ static int measure_cycles_lat_fn(void *_plr) + /* + * Disable hardware prefetchers. + */ ++ rdmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high); + wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); + mem_r = READ_ONCE(plr->kmem); + /* +@@ -895,7 +899,7 @@ static int measure_cycles_lat_fn(void *_plr) + end = rdtsc_ordered(); + trace_pseudo_lock_mem_latency((u32)(end - start)); + } +- wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0); ++ wrmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high); + local_irq_enable(); + plr->thread_done = 1; + wake_up_interruptible(&plr->lock_thread_wq); +@@ -940,6 +944,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr, + u64 hits_before = 0, hits_after = 0, miss_before = 0, miss_after = 0; + struct perf_event *miss_event, *hit_event; + int hit_pmcnum, miss_pmcnum; ++ u32 saved_low, saved_high; + unsigned int line_size; + unsigned int size; + unsigned long i; +@@ -973,6 +978,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr, + /* + * Disable hardware prefetchers. + */ ++ rdmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high); + wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0); + + /* Initialize rest of local variables */ +@@ -1031,7 +1037,7 @@ static int measure_residency_fn(struct perf_event_attr *miss_attr, + */ + rmb(); + /* Re-enable hardware prefetchers */ +- wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0); ++ wrmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high); + local_irq_enable(); + out_hit: + perf_event_release_kernel(hit_event); +-- +2.35.1 + diff --git a/queue-5.19/xfrm-reinject-transport-mode-packets-through-workque.patch b/queue-5.19/xfrm-reinject-transport-mode-packets-through-workque.patch new file mode 100644 index 00000000000..83dcd7a5850 --- /dev/null +++ b/queue-5.19/xfrm-reinject-transport-mode-packets-through-workque.patch @@ -0,0 +1,210 @@ +From 84c9c815a9712701703eb5ca82190c90af7af7df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 24 Sep 2022 16:01:57 +0800 +Subject: xfrm: Reinject transport-mode packets through workqueue + +From: Liu Jian + +[ Upstream commit 4f4920669d21e1060b7243e5118dc3b71ced1276 ] + +The following warning is displayed when the tcp6-multi-diffip11 stress +test case of the LTP test suite is tested: + +watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [ns-tcpserver:48198] +CPU: 0 PID: 48198 Comm: ns-tcpserver Kdump: loaded Not tainted 6.0.0-rc6+ #39 +Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 +pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) +pc : des3_ede_encrypt+0x27c/0x460 [libdes] +lr : 0x3f +sp : ffff80000ceaa1b0 +x29: ffff80000ceaa1b0 x28: ffff0000df056100 x27: ffff0000e51e5280 +x26: ffff80004df75030 x25: ffff0000e51e4600 x24: 000000000000003b +x23: 0000000000802080 x22: 000000000000003d x21: 0000000000000038 +x20: 0000000080000020 x19: 000000000000000a x18: 0000000000000033 +x17: ffff0000e51e4780 x16: ffff80004e2d1448 x15: ffff80004e2d1248 +x14: ffff0000e51e4680 x13: ffff80004e2d1348 x12: ffff80004e2d1548 +x11: ffff80004e2d1848 x10: ffff80004e2d1648 x9 : ffff80004e2d1748 +x8 : ffff80004e2d1948 x7 : 000000000bcaf83d x6 : 000000000000001b +x5 : ffff80004e2d1048 x4 : 00000000761bf3bf x3 : 000000007f1dd0a3 +x2 : ffff0000e51e4780 x1 : ffff0000e3b9a2f8 x0 : 00000000db44e872 +Call trace: + des3_ede_encrypt+0x27c/0x460 [libdes] + crypto_des3_ede_encrypt+0x1c/0x30 [des_generic] + crypto_cbc_encrypt+0x148/0x190 + crypto_skcipher_encrypt+0x2c/0x40 + crypto_authenc_encrypt+0xc8/0xfc [authenc] + crypto_aead_encrypt+0x2c/0x40 + echainiv_encrypt+0x144/0x1a0 [echainiv] + crypto_aead_encrypt+0x2c/0x40 + esp6_output_tail+0x1c8/0x5d0 [esp6] + esp6_output+0x120/0x278 [esp6] + xfrm_output_one+0x458/0x4ec + xfrm_output_resume+0x6c/0x1f0 + xfrm_output+0xac/0x4ac + __xfrm6_output+0x130/0x270 + xfrm6_output+0x60/0xec + ip6_xmit+0x2ec/0x5bc + inet6_csk_xmit+0xbc/0x10c + __tcp_transmit_skb+0x460/0x8c0 + tcp_write_xmit+0x348/0x890 + __tcp_push_pending_frames+0x44/0x110 + tcp_rcv_established+0x3c8/0x720 + tcp_v6_do_rcv+0xdc/0x4a0 + tcp_v6_rcv+0xc24/0xcb0 + ip6_protocol_deliver_rcu+0xf0/0x574 + ip6_input_finish+0x48/0x7c + ip6_input+0x48/0xc0 + ip6_rcv_finish+0x80/0x9c + xfrm_trans_reinject+0xb0/0xf4 + tasklet_action_common.constprop.0+0xf8/0x134 + tasklet_action+0x30/0x3c + __do_softirq+0x128/0x368 + do_softirq+0xb4/0xc0 + __local_bh_enable_ip+0xb0/0xb4 + put_cpu_fpsimd_context+0x40/0x70 + kernel_neon_end+0x20/0x40 + sha1_base_do_update.constprop.0.isra.0+0x11c/0x140 [sha1_ce] + sha1_ce_finup+0x94/0x110 [sha1_ce] + crypto_shash_finup+0x34/0xc0 + hmac_finup+0x48/0xe0 + crypto_shash_finup+0x34/0xc0 + shash_digest_unaligned+0x74/0x90 + crypto_shash_digest+0x4c/0x9c + shash_ahash_digest+0xc8/0xf0 + shash_async_digest+0x28/0x34 + crypto_ahash_digest+0x48/0xcc + crypto_authenc_genicv+0x88/0xcc [authenc] + crypto_authenc_encrypt+0xd8/0xfc [authenc] + crypto_aead_encrypt+0x2c/0x40 + echainiv_encrypt+0x144/0x1a0 [echainiv] + crypto_aead_encrypt+0x2c/0x40 + esp6_output_tail+0x1c8/0x5d0 [esp6] + esp6_output+0x120/0x278 [esp6] + xfrm_output_one+0x458/0x4ec + xfrm_output_resume+0x6c/0x1f0 + xfrm_output+0xac/0x4ac + __xfrm6_output+0x130/0x270 + xfrm6_output+0x60/0xec + ip6_xmit+0x2ec/0x5bc + inet6_csk_xmit+0xbc/0x10c + __tcp_transmit_skb+0x460/0x8c0 + tcp_write_xmit+0x348/0x890 + __tcp_push_pending_frames+0x44/0x110 + tcp_push+0xb4/0x14c + tcp_sendmsg_locked+0x71c/0xb64 + tcp_sendmsg+0x40/0x6c + inet6_sendmsg+0x4c/0x80 + sock_sendmsg+0x5c/0x6c + __sys_sendto+0x128/0x15c + __arm64_sys_sendto+0x30/0x40 + invoke_syscall+0x50/0x120 + el0_svc_common.constprop.0+0x170/0x194 + do_el0_svc+0x38/0x4c + el0_svc+0x28/0xe0 + el0t_64_sync_handler+0xbc/0x13c + el0t_64_sync+0x180/0x184 + +Get softirq info by bcc tool: +./softirqs -NT 10 +Tracing soft irq event time... Hit Ctrl-C to end. + +15:34:34 +SOFTIRQ TOTAL_nsecs +block 158990 +timer 20030920 +sched 46577080 +net_rx 676746820 +tasklet 9906067650 + +15:34:45 +SOFTIRQ TOTAL_nsecs +block 86100 +sched 38849790 +net_rx 676532470 +timer 1163848790 +tasklet 9409019620 + +15:34:55 +SOFTIRQ TOTAL_nsecs +sched 58078450 +net_rx 475156720 +timer 533832410 +tasklet 9431333300 + +The tasklet software interrupt takes too much time. Therefore, the +xfrm_trans_reinject executor is changed from tasklet to workqueue. Add add +spin lock to protect the queue. This reduces the processing flow of the +tcp_sendmsg function in this scenario. + +Fixes: acf568ee859f0 ("xfrm: Reinject transport-mode packets through tasklet") +Signed-off-by: Liu Jian +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_input.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c +index b2f4ec9c537f..aa5220565763 100644 +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@ -24,7 +24,8 @@ + #include "xfrm_inout.h" + + struct xfrm_trans_tasklet { +- struct tasklet_struct tasklet; ++ struct work_struct work; ++ spinlock_t queue_lock; + struct sk_buff_head queue; + }; + +@@ -760,18 +761,22 @@ int xfrm_input_resume(struct sk_buff *skb, int nexthdr) + } + EXPORT_SYMBOL(xfrm_input_resume); + +-static void xfrm_trans_reinject(struct tasklet_struct *t) ++static void xfrm_trans_reinject(struct work_struct *work) + { +- struct xfrm_trans_tasklet *trans = from_tasklet(trans, t, tasklet); ++ struct xfrm_trans_tasklet *trans = container_of(work, struct xfrm_trans_tasklet, work); + struct sk_buff_head queue; + struct sk_buff *skb; + + __skb_queue_head_init(&queue); ++ spin_lock_bh(&trans->queue_lock); + skb_queue_splice_init(&trans->queue, &queue); ++ spin_unlock_bh(&trans->queue_lock); + ++ local_bh_disable(); + while ((skb = __skb_dequeue(&queue))) + XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net, + NULL, skb); ++ local_bh_enable(); + } + + int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, +@@ -789,8 +794,10 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, + + XFRM_TRANS_SKB_CB(skb)->finish = finish; + XFRM_TRANS_SKB_CB(skb)->net = net; ++ spin_lock_bh(&trans->queue_lock); + __skb_queue_tail(&trans->queue, skb); +- tasklet_schedule(&trans->tasklet); ++ spin_unlock_bh(&trans->queue_lock); ++ schedule_work(&trans->work); + return 0; + } + EXPORT_SYMBOL(xfrm_trans_queue_net); +@@ -817,7 +824,8 @@ void __init xfrm_input_init(void) + struct xfrm_trans_tasklet *trans; + + trans = &per_cpu(xfrm_trans_tasklet, i); ++ spin_lock_init(&trans->queue_lock); + __skb_queue_head_init(&trans->queue); +- tasklet_setup(&trans->tasklet, xfrm_trans_reinject); ++ INIT_WORK(&trans->work, xfrm_trans_reinject); + } + } +-- +2.35.1 + diff --git a/queue-5.19/xfrm-update-ipcomp_scratches-with-null-when-freed.patch b/queue-5.19/xfrm-update-ipcomp_scratches-with-null-when-freed.patch new file mode 100644 index 00000000000..55dc9b014fc --- /dev/null +++ b/queue-5.19/xfrm-update-ipcomp_scratches-with-null-when-freed.patch @@ -0,0 +1,72 @@ +From 51b9cfc6f9f7300c767963b9e5e0ffeaa22594b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 1 Sep 2022 13:12:10 +0600 +Subject: xfrm: Update ipcomp_scratches with NULL when freed + +From: Khalid Masum + +[ Upstream commit 8a04d2fc700f717104bfb95b0f6694e448a4537f ] + +Currently if ipcomp_alloc_scratches() fails to allocate memory +ipcomp_scratches holds obsolete address. So when we try to free the +percpu scratches using ipcomp_free_scratches() it tries to vfree non +existent vm area. Described below: + +static void * __percpu *ipcomp_alloc_scratches(void) +{ + ... + scratches = alloc_percpu(void *); + if (!scratches) + return NULL; +ipcomp_scratches does not know about this allocation failure. +Therefore holding the old obsolete address. + ... +} + +So when we free, + +static void ipcomp_free_scratches(void) +{ + ... + scratches = ipcomp_scratches; +Assigning obsolete address from ipcomp_scratches + + if (!scratches) + return; + + for_each_possible_cpu(i) + vfree(*per_cpu_ptr(scratches, i)); +Trying to free non existent page, causing warning: trying to vfree +existent vm area. + ... +} + +Fix this breakage by updating ipcomp_scrtches with NULL when scratches +is freed + +Suggested-by: Herbert Xu +Reported-by: syzbot+5ec9bb042ddfe9644773@syzkaller.appspotmail.com +Tested-by: syzbot+5ec9bb042ddfe9644773@syzkaller.appspotmail.com +Signed-off-by: Khalid Masum +Acked-by: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Sasha Levin +--- + net/xfrm/xfrm_ipcomp.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/xfrm/xfrm_ipcomp.c b/net/xfrm/xfrm_ipcomp.c +index cb40ff0ff28d..92ad336a83ab 100644 +--- a/net/xfrm/xfrm_ipcomp.c ++++ b/net/xfrm/xfrm_ipcomp.c +@@ -203,6 +203,7 @@ static void ipcomp_free_scratches(void) + vfree(*per_cpu_ptr(scratches, i)); + + free_percpu(scratches); ++ ipcomp_scratches = NULL; + } + + static void * __percpu *ipcomp_alloc_scratches(void) +-- +2.35.1 + diff --git a/queue-5.19/xhci-don-t-show-warning-for-reinit-on-known-broken-s.patch b/queue-5.19/xhci-don-t-show-warning-for-reinit-on-known-broken-s.patch new file mode 100644 index 00000000000..398fb6c4baf --- /dev/null +++ b/queue-5.19/xhci-don-t-show-warning-for-reinit-on-known-broken-s.patch @@ -0,0 +1,48 @@ +From 2de78028d15b912f73da400f4f389e131459a412 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Sep 2022 15:34:47 +0300 +Subject: xhci: Don't show warning for reinit on known broken suspend + +From: Mario Limonciello + +[ Upstream commit 484d6f7aa3283d082c87654b7fe7a7f725423dfb ] + +commit 8b328f8002bc ("xhci: re-initialize the HC during resume if HCE was +set") introduced a new warning message when the host controller error +was set and re-initializing. + +This is expected behavior on some designs which already set +`xhci->broken_suspend` so the new warning is alarming to some users. + +Modify the code to only show the warning if this was a surprising behavior +to the XHCI driver. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216470 +Fixes: 8b328f8002bc ("xhci: re-initialize the HC during resume if HCE was set") +Reported-by: Artem S. Tashkinov +Signed-off-by: Mario Limonciello +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20220921123450.671459-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/host/xhci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c +index 38649284ff88..a7ef675f00fd 100644 +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1183,7 +1183,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + /* re-initialize the HC on Restore Error, or Host Controller Error */ + if (temp & (STS_SRE | STS_HCE)) { + reinit_xhc = true; +- xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); ++ if (!xhci->broken_suspend) ++ xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp); + } + + if (reinit_xhc) { +-- +2.35.1 + diff --git a/queue-5.19/xsk-fix-backpressure-mechanism-on-tx.patch b/queue-5.19/xsk-fix-backpressure-mechanism-on-tx.patch new file mode 100644 index 00000000000..fc63815adc4 --- /dev/null +++ b/queue-5.19/xsk-fix-backpressure-mechanism-on-tx.patch @@ -0,0 +1,171 @@ +From 08578d62f75c9a8d421c87d4fe6f349e670ecb2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Aug 2022 14:17:05 +0200 +Subject: xsk: Fix backpressure mechanism on Tx + +From: Maciej Fijalkowski + +[ Upstream commit c00c4461689e15ac2cc3b9a595a54e4d8afd3d77 ] + +Commit d678cbd2f867 ("xsk: Fix handling of invalid descriptors in XSK TX +batching API") fixed batch API usage against set of descriptors with +invalid ones but introduced a problem when AF_XDP SW rings are smaller +than HW ones. Mismatch of reported Tx'ed frames between HW generator and +user space app was observed. It turned out that backpressure mechanism +became a bottleneck when the amount of produced descriptors to CQ is +lower than what we grabbed from XSK Tx ring. + +Say that 512 entries had been taken from XSK Tx ring but we had only 490 +free entries in CQ. Then callsite (ZC driver) will produce only 490 +entries onto HW Tx ring but 512 entries will be released from Tx ring +and this is what will be seen by the user space. + +In order to fix this case, mix XSK Tx/CQ ring interractions by moving +around internal functions and changing call order: + +* pull out xskq_prod_nb_free() from xskq_prod_reserve_addr_batch() + up to xsk_tx_peek_release_desc_batch(); +** move xskq_cons_release_n() into xskq_cons_read_desc_batch() + +After doing so, algorithm can be described as follows: + +1. lookup Tx entries +2. use value from 1. to reserve space in CQ (*) +3. Read from Tx ring as much descriptors as value from 2 + 3a. release descriptors from XSK Tx ring (**) +4. Finally produce addresses to CQ + +Fixes: d678cbd2f867 ("xsk: Fix handling of invalid descriptors in XSK TX batching API") +Signed-off-by: Magnus Karlsson +Signed-off-by: Maciej Fijalkowski +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20220830121705.8618-1-maciej.fijalkowski@intel.com +Signed-off-by: Sasha Levin +--- + net/xdp/xsk.c | 22 +++++++++++----------- + net/xdp/xsk_queue.h | 22 ++++++++++------------ + 2 files changed, 21 insertions(+), 23 deletions(-) + +diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c +index 7e311420aab9..e24d62f8883a 100644 +--- a/net/xdp/xsk.c ++++ b/net/xdp/xsk.c +@@ -355,16 +355,15 @@ static u32 xsk_tx_peek_release_fallback(struct xsk_buff_pool *pool, u32 max_entr + return nb_pkts; + } + +-u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) ++u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 nb_pkts) + { + struct xdp_sock *xs; +- u32 nb_pkts; + + rcu_read_lock(); + if (!list_is_singular(&pool->xsk_tx_list)) { + /* Fallback to the non-batched version */ + rcu_read_unlock(); +- return xsk_tx_peek_release_fallback(pool, max_entries); ++ return xsk_tx_peek_release_fallback(pool, nb_pkts); + } + + xs = list_first_or_null_rcu(&pool->xsk_tx_list, struct xdp_sock, tx_list); +@@ -373,12 +372,7 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) + goto out; + } + +- max_entries = xskq_cons_nb_entries(xs->tx, max_entries); +- nb_pkts = xskq_cons_read_desc_batch(xs->tx, pool, max_entries); +- if (!nb_pkts) { +- xs->tx->queue_empty_descs++; +- goto out; +- } ++ nb_pkts = xskq_cons_nb_entries(xs->tx, nb_pkts); + + /* This is the backpressure mechanism for the Tx path. Try to + * reserve space in the completion queue for all packets, but +@@ -386,12 +380,18 @@ u32 xsk_tx_peek_release_desc_batch(struct xsk_buff_pool *pool, u32 max_entries) + * packets. This avoids having to implement any buffering in + * the Tx path. + */ +- nb_pkts = xskq_prod_reserve_addr_batch(pool->cq, pool->tx_descs, nb_pkts); ++ nb_pkts = xskq_prod_nb_free(pool->cq, nb_pkts); + if (!nb_pkts) + goto out; + +- xskq_cons_release_n(xs->tx, max_entries); ++ nb_pkts = xskq_cons_read_desc_batch(xs->tx, pool, nb_pkts); ++ if (!nb_pkts) { ++ xs->tx->queue_empty_descs++; ++ goto out; ++ } ++ + __xskq_cons_release(xs->tx); ++ xskq_prod_write_addr_batch(pool->cq, pool->tx_descs, nb_pkts); + xs->sk.sk_write_space(&xs->sk); + + out: +diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h +index fb20bf7207cf..c6fb6b763658 100644 +--- a/net/xdp/xsk_queue.h ++++ b/net/xdp/xsk_queue.h +@@ -205,6 +205,11 @@ static inline bool xskq_cons_read_desc(struct xsk_queue *q, + return false; + } + ++static inline void xskq_cons_release_n(struct xsk_queue *q, u32 cnt) ++{ ++ q->cached_cons += cnt; ++} ++ + static inline u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff_pool *pool, + u32 max) + { +@@ -226,6 +231,8 @@ static inline u32 xskq_cons_read_desc_batch(struct xsk_queue *q, struct xsk_buff + cached_cons++; + } + ++ /* Release valid plus any invalid entries */ ++ xskq_cons_release_n(q, cached_cons - q->cached_cons); + return nb_entries; + } + +@@ -291,11 +298,6 @@ static inline void xskq_cons_release(struct xsk_queue *q) + q->cached_cons++; + } + +-static inline void xskq_cons_release_n(struct xsk_queue *q, u32 cnt) +-{ +- q->cached_cons += cnt; +-} +- + static inline u32 xskq_cons_present_entries(struct xsk_queue *q) + { + /* No barriers needed since data is not accessed */ +@@ -350,21 +352,17 @@ static inline int xskq_prod_reserve_addr(struct xsk_queue *q, u64 addr) + return 0; + } + +-static inline u32 xskq_prod_reserve_addr_batch(struct xsk_queue *q, struct xdp_desc *descs, +- u32 max) ++static inline void xskq_prod_write_addr_batch(struct xsk_queue *q, struct xdp_desc *descs, ++ u32 nb_entries) + { + struct xdp_umem_ring *ring = (struct xdp_umem_ring *)q->ring; +- u32 nb_entries, i, cached_prod; +- +- nb_entries = xskq_prod_nb_free(q, max); ++ u32 i, cached_prod; + + /* A, matches D */ + cached_prod = q->cached_prod; + for (i = 0; i < nb_entries; i++) + ring->desc[cached_prod++ & q->ring_mask] = descs[i].addr; + q->cached_prod = cached_prod; +- +- return nb_entries; + } + + static inline int xskq_prod_reserve_desc(struct xsk_queue *q, +-- +2.35.1 +