Переглянути джерело

Merge 436eadfdaa2e740bfdbd1f2254df1412d75a6ebf on remote branch

Change-Id: Idba14b1dd5dbc3ca9f08275a8c08d37b01ef0629
Linux Build Service Account 2 роки тому
батько
коміт
2d33a8bc99
16 змінених файлів з 528 додано та 29 видалено
  1. 4 0
      Kbuild
  2. 6 2
      Makefile
  3. 2 1
      cnss2/bus.c
  4. 3 1
      cnss2/bus.h
  5. 108 1
      cnss2/main.c
  6. 12 1
      cnss2/main.h
  7. 93 5
      cnss2/pci.c
  8. 10 1
      cnss2/pci.h
  9. 8 14
      cnss2/qmi.c
  10. 16 2
      cnss2/reg.h
  11. 88 0
      cnss_utils/wlan_firmware_service_v01.c
  12. 38 0
      cnss_utils/wlan_firmware_service_v01.h
  13. 7 0
      icnss2/debug.c
  14. 103 1
      icnss2/main.c
  15. 7 0
      icnss2/main.h
  16. 23 0
      inc/cnss2.h

+ 4 - 0
Kbuild

@@ -40,6 +40,10 @@ ifeq ($(CONFIG_AUTO_PROJECT),y)
 KBUILD_CPPFLAGS += -DCONFIG_PULLDOWN_WLANEN
 endif
 
+ifeq ($(CONFIG_CNSS2_SSR_DRIVER_DUMP),y)
+KBUILD_CPPFLAGS += -DCONFIG_CNSS2_SSR_DRIVER_DUMP
+endif
+
 obj-$(CONFIG_CNSS2) += cnss2/
 obj-$(CONFIG_ICNSS2) += icnss2/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/

+ 6 - 2
Makefile

@@ -11,17 +11,21 @@ WLAN_PLATFORM_ROOT = $(shell pwd)
 KBUILD_OPTIONS := WLAN_PLATFORM_ROOT=$(WLAN_PLATFORM_ROOT)
 ifeq ($(USE_EXTERNAL_CONFIGS),)
 KBUILD_OPTIONS += CONFIG_CNSS_OUT_OF_TREE=y
+
+ifneq (,$(filter $(CONFIG_PCI_MSM),y m))
 KBUILD_OPTIONS += CONFIG_CNSS2=m
-KBUILD_OPTIONS += CONFIG_ICNSS2=m
 KBUILD_OPTIONS += CONFIG_CNSS2_QMI=y
-KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y
 KBUILD_OPTIONS += CONFIG_CNSS2_DEBUG=y
+endif
+KBUILD_OPTIONS += CONFIG_ICNSS2=m
+KBUILD_OPTIONS += CONFIG_ICNSS2_QMI=y
 KBUILD_OPTIONS += CONFIG_ICNSS2_DEBUG=y
 KBUILD_OPTIONS += CONFIG_CNSS_QMI_SVC=m
 KBUILD_OPTIONS += CONFIG_CNSS_PLAT_IPC_QMI_SVC=m
 KBUILD_OPTIONS += CONFIG_CNSS_GENL=m
 KBUILD_OPTIONS += CONFIG_WCNSS_MEM_PRE_ALLOC=m
 KBUILD_OPTIONS += CONFIG_CNSS_UTILS=m
+KBUILD_OPTIONS += CONFIG_CNSS2_SSR_DRIVER_DUMP=y
 endif
 endif
 

+ 2 - 1
cnss2/bus.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include "bus.h"
@@ -51,6 +51,7 @@ enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		return CNSS_BUS_PCI;
 	default:
 		cnss_pr_err("Unknown device_id: 0x%lx\n", plat_priv->device_id);

+ 3 - 1
cnss2/bus.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CNSS_BUS_H
@@ -25,6 +25,8 @@
 #define KIWI_DEVICE_ID			0x1107
 #define MANGO_VENDOR_ID			0x17CB
 #define MANGO_DEVICE_ID			0x110A
+#define PEACH_VENDOR_ID			0x17CB
+#define PEACH_DEVICE_ID			0x110E
 
 enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
 enum cnss_dev_bus_type cnss_get_bus_type(struct cnss_plat_data *plat_priv);

+ 108 - 1
cnss2/main.c

@@ -2111,6 +2111,7 @@ static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		cnss_pr_err("Not supported for device ID 0x%lx\n",
@@ -2923,6 +2924,106 @@ do_elf_dump:
 
 	return ret;
 }
+
+#ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
+int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
+			 struct cnss_ssr_driver_dump_entry *ssr_entry,
+			 size_t num_entries_loaded)
+{
+	struct qcom_dump_segment *seg;
+	struct cnss_host_dump_meta_info meta_info = {0};
+	struct list_head head;
+	int dev_ret = 0;
+	struct device *new_device;
+	static const char * const wlan_str[] = {
+		[CNSS_HOST_WLAN_LOGS] = "wlan_logs",
+		[CNSS_HOST_HTC_CREDIT] = "htc_credit",
+		[CNSS_HOST_WMI_TX_CMP] = "wmi_tx_cmp",
+		[CNSS_HOST_WMI_COMMAND_LOG] = "wmi_command_log",
+		[CNSS_HOST_WMI_EVENT_LOG] = "wmi_event_log",
+		[CNSS_HOST_WMI_RX_EVENT] = "wmi_rx_event",
+		[CNSS_HOST_HAL_SOC] = "hal_soc",
+		[CNSS_HOST_WMI_HANG_DATA] = "wmi_hang_data",
+		[CNSS_HOST_CE_HANG_EVT] = "ce_hang_evt",
+		[CNSS_HOST_PEER_MAC_ADDR_HANG_DATA] = "peer_mac_addr_hang_data",
+		[CNSS_HOST_CP_VDEV_INFO] = "cp_vdev_info",
+		[CNSS_HOST_GWLAN_LOGGING] = "gwlan_logging",
+		[CNSS_HOST_WMI_DEBUG_LOG_INFO] = "wmi_debug_log_info",
+		[CNSS_HOST_HTC_CREDIT_IDX] = "htc_credit_history_idx",
+		[CNSS_HOST_HTC_CREDIT_LEN] = "htc_credit_history_length",
+		[CNSS_HOST_WMI_TX_CMP_IDX] = "wmi_tx_cmp_idx",
+		[CNSS_HOST_WMI_COMMAND_LOG_IDX] = "wmi_command_log_idx",
+		[CNSS_HOST_WMI_EVENT_LOG_IDX] = "wmi_event_log_idx",
+		[CNSS_HOST_WMI_RX_EVENT_IDX] = "wmi_rx_event_idx"
+	};
+	int i, j;
+	int ret = 0;
+
+	if (!dump_enabled()) {
+		cnss_pr_info("Dump collection is not enabled\n");
+		return ret;
+	}
+
+	new_device = kcalloc(1, sizeof(*new_device), GFP_KERNEL);
+	if (!new_device) {
+		cnss_pr_err("Failed to alloc device mem\n");
+		return -ENOMEM;
+	}
+
+	device_initialize(new_device);
+	dev_set_name(new_device, "wlan_driver");
+	dev_ret = device_add(new_device);
+	if (dev_ret) {
+		cnss_pr_err("Failed to add new device\n");
+		goto put_device;
+	}
+
+	INIT_LIST_HEAD(&head);
+	for (i = 0; i < num_entries_loaded; i++) {
+		seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
+		if (!seg) {
+			cnss_pr_err("Failed to alloc seg entry %d\n", i);
+			continue;
+		}
+
+		seg->va = ssr_entry[i].buffer_pointer;
+		seg->da = (dma_addr_t)ssr_entry[i].buffer_pointer;
+		seg->size = ssr_entry[i].buffer_size;
+
+		for (j = 0; j < ARRAY_SIZE(wlan_str); j++) {
+			if (strncmp(ssr_entry[i].region_name, wlan_str[j],
+				    strlen(wlan_str[j])) == 0) {
+				meta_info.entry[i].type = j;
+			}
+		}
+		meta_info.entry[i].entry_start = i + 1;
+		meta_info.entry[i].entry_num++;
+
+		list_add_tail(&seg->node, &head);
+	}
+
+	seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
+	meta_info.magic = CNSS_RAMDUMP_MAGIC;
+	meta_info.version = CNSS_RAMDUMP_VERSION;
+	meta_info.chipset = plat_priv->device_id;
+	meta_info.total_entries = num_entries_loaded;
+	seg->va = &meta_info;
+	seg->da = (dma_addr_t)&meta_info;
+	seg->size = sizeof(meta_info);
+	list_add(&seg->node, &head);
+	ret = qcom_elf_dump(&head, new_device, ELF_CLASS);
+	while (!list_empty(&head)) {
+		seg = list_first_entry(&head, struct qcom_dump_segment, node);
+		list_del(&seg->node);
+		kfree(seg);
+	}
+	device_del(new_device);
+put_device:
+	put_device(new_device);
+	kfree(new_device);
+	return ret;
+}
+#endif
 #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
 
 #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2)
@@ -3127,6 +3228,7 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		ret = cnss_register_ramdump_v2(plat_priv);
 		break;
 	default:
@@ -3148,6 +3250,7 @@ void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		cnss_unregister_ramdump_v2(plat_priv);
 		break;
 	default:
@@ -4051,6 +4154,7 @@ static const struct platform_device_id cnss_platform_id_table[] = {
 	{ .name = "qca6490", .driver_data = QCA6490_DEVICE_ID, },
 	{ .name = "kiwi", .driver_data = KIWI_DEVICE_ID, },
 	{ .name = "mango", .driver_data = MANGO_DEVICE_ID, },
+	{ .name = "peach", .driver_data = PEACH_DEVICE_ID, },
 	{ .name = "qcaconv", .driver_data = 0, },
 	{ },
 };
@@ -4075,8 +4179,11 @@ static const struct of_device_id cnss_of_match_table[] = {
 		.compatible = "qcom,cnss-mango",
 		.data = (void *)&cnss_platform_id_table[5]},
 	{
-		.compatible = "qcom,cnss-qca-converged",
+		.compatible = "qcom,cnss-peach",
 		.data = (void *)&cnss_platform_id_table[6]},
+	{
+		.compatible = "qcom,cnss-qca-converged",
+		.data = (void *)&cnss_platform_id_table[7]},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, cnss_of_match_table);

+ 12 - 1
cnss2/main.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CNSS_MAIN_H
@@ -276,6 +276,14 @@ struct cnss_dump_meta_info {
 	struct cnss_dump_entry entry[CNSS_FW_DUMP_TYPE_MAX];
 };
 
+struct cnss_host_dump_meta_info {
+	u32 magic;
+	u32 version;
+	u32 chipset;
+	u32 total_entries;
+	struct cnss_dump_entry entry[CNSS_HOST_DUMP_TYPE_MAX];
+};
+
 enum cnss_driver_event_type {
 	CNSS_DRIVER_EVENT_SERVER_ARRIVE,
 	CNSS_DRIVER_EVENT_SERVER_EXIT,
@@ -630,6 +638,9 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv);
 void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv);
 int cnss_do_ramdump(struct cnss_plat_data *plat_priv);
 int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv);
+int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
+			 struct cnss_ssr_driver_dump_entry *ssr_entry,
+			 size_t num_entries_loaded);
 void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv);
 int cnss_get_cpr_info(struct cnss_plat_data *plat_priv);
 int cnss_update_cpr_info(struct cnss_plat_data *plat_priv);

+ 93 - 5
cnss2/pci.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/completion.h>
@@ -44,6 +44,7 @@
 #define QCA6490_PATH_PREFIX		"qca6490/"
 #define KIWI_PATH_PREFIX		"kiwi/"
 #define MANGO_PATH_PREFIX		"mango/"
+#define PEACH_PATH_PREFIX		"peach/"
 #define DEFAULT_PHY_M3_FILE_NAME	"m3.bin"
 #define DEFAULT_PHY_UCODE_FILE_NAME	"phy_ucode.elf"
 #define PHY_UCODE_V2_FILE_NAME		"phy_ucode20.elf"
@@ -817,8 +818,13 @@ static void cnss_pci_select_window(struct cnss_pci_data *pci_priv, u32 offset)
 	u32 window_enable = WINDOW_ENABLE_BIT | window;
 	u32 val;
 
-	writel_relaxed(window_enable, pci_priv->bar +
-		       QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET);
+	if (plat_priv->device_id == PEACH_DEVICE_ID) {
+		writel_relaxed(window_enable, pci_priv->bar +
+			       PEACH_PCIE_REMAP_BAR_CTRL_OFFSET);
+	} else {
+		writel_relaxed(window_enable, pci_priv->bar +
+			       QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET);
+	}
 
 	if (window != pci_priv->remap_window) {
 		pci_priv->remap_window = window;
@@ -827,7 +833,13 @@ static void cnss_pci_select_window(struct cnss_pci_data *pci_priv, u32 offset)
 	}
 
 	/* Read it back to make sure the write has taken effect */
-	val = readl_relaxed(pci_priv->bar + QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET);
+	if (plat_priv->device_id == PEACH_DEVICE_ID) {
+		val = readl_relaxed(pci_priv->bar +
+			PEACH_PCIE_REMAP_BAR_CTRL_OFFSET);
+	} else {
+		val = readl_relaxed(pci_priv->bar +
+			QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET);
+	}
 	if (val != window_enable) {
 		cnss_pr_err("Failed to config window register to 0x%x, current value: 0x%x\n",
 			    window_enable, val);
@@ -1159,6 +1171,7 @@ static void cnss_pci_soc_scratch_reg_dump(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return;
@@ -1277,6 +1290,7 @@ int cnss_pci_recover_link_down(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1517,6 +1531,12 @@ static void cnss_pci_dump_bl_sram_mem(struct cnss_pci_data *pci_priv)
 		pbl_log_max_size = MANGO_DEBUG_PBL_LOG_SRAM_MAX_SIZE;
 		sbl_log_max_size = MANGO_DEBUG_SBL_LOG_SRAM_MAX_SIZE;
 		break;
+	case PEACH_DEVICE_ID:
+		pbl_bootstrap_status_reg = PEACH_PBL_BOOTSTRAP_STATUS;
+		pbl_log_sram_start = PEACH_DEBUG_PBL_LOG_SRAM_START;
+		pbl_log_max_size = PEACH_DEBUG_PBL_LOG_SRAM_MAX_SIZE;
+		sbl_log_max_size = PEACH_DEBUG_SBL_LOG_SRAM_MAX_SIZE;
+		break;
 	default:
 		return;
 	}
@@ -2085,6 +2105,7 @@ static int cnss_pci_get_device_timestamp(struct cnss_pci_data *pci_priv,
 	switch (pci_priv->device_id) {
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		cnss_pci_reg_read(pci_priv, PCIE_MHI_TIME_LOW, &low);
 		cnss_pci_reg_read(pci_priv, PCIE_MHI_TIME_HIGH, &high);
 		break;
@@ -2106,6 +2127,7 @@ static void cnss_pci_enable_time_sync_counter(struct cnss_pci_data *pci_priv)
 	switch (pci_priv->device_id) {
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		return;
 	default:
 		break;
@@ -2120,6 +2142,7 @@ static void cnss_pci_clear_time_sync_counter(struct cnss_pci_data *pci_priv)
 	switch (pci_priv->device_id) {
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		return;
 	default:
 		break;
@@ -2139,6 +2162,7 @@ static void cnss_pci_time_sync_reg_update(struct cnss_pci_data *pci_priv,
 	switch (pci_priv->device_id) {
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		/* Use the next two shadow registers after host's usage */
 		time_reg_low = PCIE_SHADOW_REG_VALUE_0 +
 				(pci_priv->plat_priv->num_shadow_regs_v3 *
@@ -2256,6 +2280,7 @@ static int cnss_pci_start_time_sync_update(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -2278,6 +2303,7 @@ static void cnss_pci_stop_time_sync_update(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return;
@@ -2914,6 +2940,7 @@ int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		ret = cnss_qca6290_powerup(pci_priv);
 		break;
 	default:
@@ -2943,6 +2970,7 @@ int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		ret = cnss_qca6290_shutdown(pci_priv);
 		break;
 	default:
@@ -2972,6 +3000,7 @@ int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		cnss_qca6290_crash_shutdown(pci_priv);
 		break;
 	default:
@@ -3001,6 +3030,7 @@ int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		ret = cnss_qca6290_ramdump(pci_priv);
 		break;
 	default:
@@ -3897,6 +3927,7 @@ int cnss_pci_force_wake_request_sync(struct device *dev, int timeout_us)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return 0;
@@ -3939,6 +3970,7 @@ int cnss_pci_force_wake_request(struct device *dev)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return 0;
@@ -3975,6 +4007,7 @@ int cnss_pci_is_device_awake(struct device *dev)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return 0;
@@ -4003,6 +4036,7 @@ int cnss_pci_force_wake_release(struct device *dev)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		break;
 	default:
 		return 0;
@@ -4295,6 +4329,7 @@ int cnss_pci_load_m3(struct cnss_pci_data *pci_priv)
 		break;
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		switch (plat_priv->device_version.major_version) {
 		case FW_V2_NUMBER:
 			phy_filename = PHY_UCODE_V2_FILE_NAME;
@@ -4814,6 +4849,7 @@ static int cnss_pci_enable_bus(struct cnss_pci_data *pci_priv)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		pci_priv->dma_bit_mask = PCI_DMA_MASK_36_BIT;
 		break;
 	default:
@@ -5148,6 +5184,7 @@ static void cnss_pci_send_hang_event(struct cnss_pci_data *pci_priv)
 		break;
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		offset = plat_priv->hang_data_addr_offset;
 		length = plat_priv->hang_event_data_len;
 		break;
@@ -5188,6 +5225,37 @@ exit:
 		    plat_priv->hang_event_data_len);
 }
 
+#ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
+void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv)
+{
+	struct cnss_ssr_driver_dump_entry ssr_entry[CNSS_HOST_DUMP_TYPE_MAX] = {0};
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+	size_t num_entries_loaded = 0;
+	int x;
+	int ret = -1;
+
+	if (pci_priv->driver_ops &&
+	    pci_priv->driver_ops->collect_driver_dump) {
+		ret = pci_priv->driver_ops->collect_driver_dump(pci_priv->pci_dev,
+								ssr_entry,
+								&num_entries_loaded);
+	}
+
+	if (!ret) {
+		for (x = 0; x < num_entries_loaded; x++) {
+			cnss_pr_info("Idx:%d, ptr: %p, name: %s, size: %d\n",
+				     x, ssr_entry[x].buffer_pointer,
+				     ssr_entry[x].region_name,
+				     ssr_entry[x].buffer_size);
+		}
+
+		cnss_do_host_ramdump(plat_priv, ssr_entry, num_entries_loaded);
+	} else {
+		cnss_pr_info("Host SSR elf dump collection feature disabled\n");
+	}
+}
+#endif
+
 void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
 {
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -5367,9 +5435,21 @@ void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv)
 
 void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv)
 {
-	if (!pci_priv)
+	struct cnss_plat_data *plat_priv;
+
+	if (!pci_priv) {
+		cnss_pr_err("pci_priv is NULL\n");
+		return;
+	}
+
+	plat_priv = pci_priv->plat_priv;
+	if (!plat_priv) {
+		cnss_pr_err("plat_priv is NULL\n");
 		return;
+	}
 
+	if (plat_priv->recovery_enabled)
+		cnss_pci_collect_host_dump_info(pci_priv);
 	cnss_device_crashed(&pci_priv->pci_dev->dev);
 }
 
@@ -5419,6 +5499,10 @@ void cnss_pci_add_fw_prefix_name(struct cnss_pci_data *pci_priv,
 		scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
 			  MANGO_PATH_PREFIX "%s", name);
 		break;
+	case PEACH_DEVICE_ID:
+		scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN,
+			  PEACH_PATH_PREFIX "%s", name);
+		break;
 	default:
 		scnprintf(prefix_name, MAX_FIRMWARE_NAME_LEN, "%s", name);
 		break;
@@ -5466,6 +5550,7 @@ static int cnss_pci_update_fw_name(struct cnss_pci_data *pci_priv)
 		break;
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		switch (plat_priv->device_version.major_version) {
 		case FW_V2_NUMBER:
 			/*
@@ -6250,6 +6335,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false);
 		timer_setup(&pci_priv->dev_rddm_timer,
 			    cnss_dev_rddm_timeout_hdlr, 0);
@@ -6314,6 +6400,7 @@ static void cnss_pci_remove(struct pci_dev *pci_dev)
 	case QCA6490_DEVICE_ID:
 	case KIWI_DEVICE_ID:
 	case MANGO_DEVICE_ID:
+	case PEACH_DEVICE_ID:
 		cnss_pci_wake_gpio_deinit(pci_priv);
 		del_timer(&pci_priv->boot_debug_timer);
 		del_timer(&pci_priv->dev_rddm_timer);
@@ -6343,6 +6430,7 @@ static const struct pci_device_id cnss_pci_id_table[] = {
 	{ QCA6490_VENDOR_ID, QCA6490_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
 	{ KIWI_VENDOR_ID, KIWI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
 	{ MANGO_VENDOR_ID, MANGO_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
+	{ PEACH_VENDOR_ID, PEACH_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);

+ 10 - 1
cnss2/pci.h

@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CNSS_PCI_H
@@ -58,6 +58,7 @@ enum cnss_pci_reg_dev_mask {
 	REG_MASK_QCA6490,
 	REG_MASK_KIWI,
 	REG_MASK_MANGO,
+	REG_MASK_PEACH,
 };
 
 struct cnss_msi_user {
@@ -236,6 +237,14 @@ void cnss_pci_free_blob_mem(struct cnss_pci_data *pci_priv);
 int cnss_pci_handle_dev_sol_irq(struct cnss_pci_data *pci_priv);
 int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
 void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
+#ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
+void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv);
+#else
+static inline
+void cnss_pci_collect_host_dump_info(struct cnss_pci_data *pci_priv)
+{
+}
+#endif
 void cnss_pci_device_crashed(struct cnss_pci_data *pci_priv);
 void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
 u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);

+ 8 - 14
cnss2/qmi.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -237,7 +237,8 @@ static void cnss_wlfw_host_cap_parse_mlo(struct cnss_plat_data *plat_priv,
 					 struct wlfw_host_cap_req_msg_v01 *req)
 {
 	if (plat_priv->device_id == KIWI_DEVICE_ID ||
-	    plat_priv->device_id == MANGO_DEVICE_ID) {
+	    plat_priv->device_id == MANGO_DEVICE_ID ||
+	    plat_priv->device_id == PEACH_DEVICE_ID) {
 		req->mlo_capable_valid = 1;
 		req->mlo_capable = 1;
 		req->mlo_chip_id_valid = 1;
@@ -711,8 +712,6 @@ int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
 	unsigned int remaining;
 	bool backup_supported = false;
 
-	cnss_pr_info("INI File %u download\n", file_type);
-
 	req = kzalloc(sizeof(*req), GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
@@ -739,10 +738,6 @@ int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
 	/* Fetch the file */
 	ret = firmware_request_nowarn(&fw, filename, &plat_priv->plat_dev->dev);
 	if (ret) {
-		cnss_pr_err("Failed to get INI file %s (%d), Backup file: %s",
-			    filename, ret,
-			    backup_supported ? "Supported" : "Not Supported");
-
 		if (!backup_supported)
 			goto err_req_fw;
 
@@ -751,11 +746,8 @@ int cnss_wlfw_ini_file_send_sync(struct cnss_plat_data *plat_priv,
 
 		ret = firmware_request_nowarn(&fw, filename,
 					      &plat_priv->plat_dev->dev);
-		if (ret) {
-			cnss_pr_err("Failed to get INI file %s (%d)", filename,
-				    ret);
+		if (ret)
 			goto err_req_fw;
-		}
 	}
 
 	temp = fw->data;
@@ -1235,7 +1227,8 @@ void cnss_get_qdss_cfg_filename(struct cnss_plat_data *plat_priv,
 	char *debug_str = QDSS_DEBUG_FILE_STR;
 
 	if (plat_priv->device_id == KIWI_DEVICE_ID ||
-	    plat_priv->device_id == MANGO_DEVICE_ID)
+	    plat_priv->device_id == MANGO_DEVICE_ID ||
+	    plat_priv->device_id == PEACH_DEVICE_ID)
 		debug_str = "";
 
 	if (plat_priv->device_version.major_version == FW_V2_NUMBER)
@@ -1588,7 +1581,8 @@ int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
 	}
 
 	if (plat_priv->device_id != KIWI_DEVICE_ID &&
-	    plat_priv->device_id != MANGO_DEVICE_ID) {
+	    plat_priv->device_id != MANGO_DEVICE_ID &&
+	    plat_priv->device_id != PEACH_DEVICE_ID) {
 		req->shadow_reg_v2_valid = 1;
 		if (config->num_shadow_reg_v2_cfg >
 		    QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)

+ 16 - 2
cnss2/reg.h

@@ -1,13 +1,14 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CNSS_REG_H
 #define _CNSS_REG_H
 
 #define QCA6390_PCIE_REMAP_BAR_CTRL_OFFSET	0x310C
+#define PEACH_PCIE_REMAP_BAR_CTRL_OFFSET	0x3278
 
 #define QCA6390_CE_SRC_RING_REG_BASE		0xA00000
 #define QCA6390_CE_DST_RING_REG_BASE		0xA01000
@@ -99,6 +100,11 @@
 #define MANGO_DEBUG_SBL_LOG_SRAM_MAX_SIZE	48
 #define MANGO_PBL_BOOTSTRAP_STATUS		0x01A10008
 
+#define PEACH_DEBUG_PBL_LOG_SRAM_START		0x01403D98
+#define PEACH_DEBUG_PBL_LOG_SRAM_MAX_SIZE	40
+#define PEACH_DEBUG_SBL_LOG_SRAM_MAX_SIZE	48
+#define PEACH_PBL_BOOTSTRAP_STATUS		0x01A10008
+
 #define TCSR_PBL_LOGGING_REG			0x01B000F8
 #define PCIE_BHI_ERRDBG2_REG			0x01E0E238
 #define PCIE_BHI_ERRDBG3_REG			0x01E0E23C
@@ -110,10 +116,14 @@
 
 #define QCA6390_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG 0x01E04234
 #define QCA6390_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG_VAL 0xDEAD1234
+#define PEACH_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG 0x01E04334
+#define PEACH_PCIE_SOC_WDOG_DISC_BAD_DATA_LOW_CFG_SOC_PCIE_REG_VAL 0xDEAD1334
 #define QCA6390_PCIE_PCIE_WCSS_STATUS_FOR_DEBUG_LOW_PCIE_LOCAL_REG 0x01E03140
+#define PEACH_PCIE_PCIE_WCSS_STATUS_FOR_DEBUG_LOW_PCIE_LOCAL_REG 0x01E03284
 #define QCA6390_PCIE_SOC_PCIE_WRAP_INTR_MASK_SOC_PCIE_REG 0x1E04054
 #define QCA6390_PCIE_SOC_PCIE_WRAP_INTR_STATUS_SOC_PCIE_REG 0x1E04058
-#define QCA6390_PCIE_SOC_COMMIT_REPLAY_SOC_PCIE_REG 0x1E05090
+#define QCA6390_PCIE_SOC_COMMIT_REPLAY_SOC_PCIE_REG 0x01E05090
+#define PEACH_PCIE_SOC_COMMIT_REPLAY_SOC_PCIE_REG 0x01E01100
 #define QCA6390_PCIE_PCIE_PARF_LTSSM 0x01E081B0
 #define QCA6390_PCIE_PCIE_PARF_PM_STTS 0x01E08024
 #define QCA6390_PCIE_PCIE_PARF_PM_STTS_1 0x01E08028
@@ -137,6 +147,10 @@
 #define QCA6390_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_LOW 0x01E030CC
 #define QCA6390_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_HIGH 0x01E0313C
 #define QCA6390_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_LOW 0x01E03140
+#define PEACH_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_HIGH 0x01E03214
+#define PEACH_PCIE_PCIE_LOCAL_REG_WCSSAON_PCIE_SR_STATUS_LOW 0x01E03218
+#define PEACH_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_HIGH 0x01E03280
+#define PEACH_PCIE_PCIE_LOCAL_REG_WCSS_STATUS_FOR_DEBUG_LOW 0x01E03284
 #define QCA6390_PCIE_PCIE_BHI_EXECENV_REG 0x01E0E228
 
 #define QCA6390_GCC_DEBUG_CLK_CTL 0x001E4025C

+ 88 - 0
cnss_utils/wlan_firmware_service_v01.c

@@ -6301,6 +6301,94 @@ struct qmi_elem_info wlfw_wlan_hw_init_cfg_resp_msg_v01_ei[] = {
 };
 EXPORT_SYMBOL(wlfw_wlan_hw_init_cfg_resp_msg_v01_ei);
 
+struct qmi_elem_info wlfw_pcie_link_ctrl_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_SIGNED_4_BYTE_ENUM,
+		.elem_len       = 1,
+		.elem_size      = sizeof(enum wlfw_pcie_link_state_enum_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_pcie_link_ctrl_req_msg_v01,
+					   link_state_req),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_pcie_link_ctrl_req_msg_v01_ei);
+
+struct qmi_elem_info wlfw_pcie_link_ctrl_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_pcie_link_ctrl_resp_msg_v01,
+					   resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_pcie_link_ctrl_resp_msg_v01_ei);
+
+struct qmi_elem_info wlfw_aux_uc_info_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_UNSIGNED_8_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u64),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x01,
+		.offset         = offsetof(struct
+					   wlfw_aux_uc_info_req_msg_v01,
+					   addr),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_4_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u32),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_aux_uc_info_req_msg_v01,
+					   size),
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_aux_uc_info_req_msg_v01_ei);
+
+struct qmi_elem_info wlfw_aux_uc_info_resp_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_STRUCT,
+		.elem_len       = 1,
+		.elem_size      = sizeof(struct qmi_response_type_v01),
+		.array_type       = NO_ARRAY,
+		.tlv_type       = 0x02,
+		.offset         = offsetof(struct
+					   wlfw_aux_uc_info_resp_msg_v01,
+					   resp),
+		.ei_array      = qmi_response_type_v01_ei,
+	},
+	{
+		.data_type      = QMI_EOTI,
+		.array_type       = NO_ARRAY,
+		.tlv_type       = QMI_COMMON_TLV_TYPE,
+	},
+};
+EXPORT_SYMBOL(wlfw_aux_uc_info_resp_msg_v01_ei);
+
 /**
  * wlfw_is_valid_dt_node_found - Check if valid device tree node present
  *

+ 38 - 0
cnss_utils/wlan_firmware_service_v01.h

@@ -18,11 +18,13 @@
 #define QMI_WLFW_CAL_REPORT_REQ_V01 0x0026
 #define QMI_WLFW_M3_INFO_RESP_V01 0x003C
 #define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026
+#define QMI_WLFW_PCIE_LINK_CTRL_RESP_V01 0x0059
 #define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033
 #define QMI_WLFW_DYNAMIC_FEATURE_MASK_RESP_V01 0x003B
 #define QMI_WLFW_IND_REGISTER_REQ_V01 0x0020
 #define QMI_WLFW_DYNAMIC_FEATURE_MASK_REQ_V01 0x003B
 #define QMI_WLFW_QDSS_TRACE_MODE_RESP_V01 0x0045
+#define QMI_WLFW_AUX_UC_INFO_REQ_V01 0x005A
 #define QMI_WLFW_FW_READY_IND_V01 0x0021
 #define QMI_WLFW_QDSS_TRACE_MEM_INFO_RESP_V01 0x0040
 #define QMI_WLFW_CAL_UPDATE_REQ_V01 0x0029
@@ -35,6 +37,7 @@
 #define QMI_WLFW_CAL_DOWNLOAD_REQ_V01 0x0027
 #define QMI_WLFW_IND_REGISTER_RESP_V01 0x0020
 #define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029
+#define QMI_WLFW_AUX_UC_INFO_RESP_V01 0x005A
 #define QMI_WLFW_M3_INFO_REQ_V01 0x003C
 #define QMI_WLFW_PCIE_GEN_SWITCH_REQ_V01 0x0053
 #define QMI_WLFW_ANTENNA_GRANT_RESP_V01 0x0048
@@ -55,6 +58,7 @@
 #define QMI_WLFW_MSA_INFO_RESP_V01 0x002D
 #define QMI_WLFW_SHUTDOWN_REQ_V01 0x0043
 #define QMI_WLFW_VBATT_REQ_V01 0x0032
+#define QMI_WLFW_PCIE_LINK_CTRL_REQ_V01 0x0059
 #define QMI_WLFW_MAC_ADDR_REQ_V01 0x0033
 #define QMI_WLFW_WLAN_CFG_REQ_V01 0x0023
 #define QMI_WLFW_ANTENNA_GRANT_REQ_V01 0x0048
@@ -278,6 +282,7 @@ enum cnss_feature_v01 {
 	CNSS_QDSS_CFG_MISS_V01 = 3,
 	CNSS_PCIE_PERST_NO_PULL_V01 = 4,
 	CNSS_RC_EP_ULTRASHORT_CHANNEL_V01 = 5,
+	CNSS_AUX_UC_SUPPORT_V01 = 6,
 	CNSS_MAX_FEATURE_V01 = 64,
 	CNSS_FEATURE_MAX_VAL_V01 = INT_MAX,
 };
@@ -313,6 +318,13 @@ enum wlfw_wlan_rf_subtype_v01 {
 	WLFW_WLAN_RF_SUBTYPE_MAX_VAL_V01 = INT_MAX,
 };
 
+enum wlfw_pcie_link_state_enum_v01 {
+	WLFW_PCIE_LINK_STATE_ENUM_MIN_VAL_V01 = INT_MIN,
+	QMI_WLFW_PCIE_ALLOW_LOW_PWR_V01 = 0,
+	QMI_WLFW_PCIE_PREVENT_LOW_PWR_V01 = 1,
+	WLFW_PCIE_LINK_STATE_ENUM_MAX_VAL_V01 = INT_MAX,
+};
+
 #define QMI_WLFW_CE_ATTR_FLAGS_V01 ((u32)0x00)
 #define QMI_WLFW_CE_ATTR_NO_SNOOP_V01 ((u32)0x01)
 #define QMI_WLFW_CE_ATTR_BYTE_SWAP_DATA_V01 ((u32)0x02)
@@ -333,6 +345,7 @@ enum wlfw_wlan_rf_subtype_v01 {
 
 #define QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01 ((u64)0x01ULL)
 #define QMI_WLFW_DIRECT_LINK_SUPPORT_V01 ((u64)0x02ULL)
+#define QMI_WLFW_AUX_UC_SUPPORT_V01 ((u64)0x04ULL)
 
 struct wlfw_ce_tgt_pipe_cfg_s_v01 {
 	u32 pipe_num;
@@ -1404,4 +1417,29 @@ struct wlfw_wlan_hw_init_cfg_resp_msg_v01 {
 #define WLFW_WLAN_HW_INIT_CFG_RESP_MSG_V01_MAX_MSG_LEN 7
 extern struct qmi_elem_info wlfw_wlan_hw_init_cfg_resp_msg_v01_ei[];
 
+struct wlfw_pcie_link_ctrl_req_msg_v01 {
+	enum wlfw_pcie_link_state_enum_v01 link_state_req;
+};
+#define WLFW_PCIE_LINK_CTRL_REQ_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_pcie_link_ctrl_req_msg_v01_ei[];
+
+struct wlfw_pcie_link_ctrl_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+#define WLFW_PCIE_LINK_CTRL_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_pcie_link_ctrl_resp_msg_v01_ei[];
+
+struct wlfw_aux_uc_info_req_msg_v01 {
+	u64 addr;
+	u32 size;
+};
+#define WLFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
+extern struct qmi_elem_info wlfw_aux_uc_info_req_msg_v01_ei[];
+
+struct wlfw_aux_uc_info_resp_msg_v01 {
+	struct qmi_response_type_v01 resp;
+};
+#define WLFW_AUX_UC_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
+extern struct qmi_elem_info wlfw_aux_uc_info_resp_msg_v01_ei[];
+
 #endif

+ 7 - 0
icnss2/debug.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #include <linux/err.h>
 #include <linux/seq_file.h>
@@ -415,6 +416,12 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
 			continue;
 		case ICNSS_QMI_DMS_CONNECTED:
 			seq_puts(s, "DMS_CONNECTED");
+			continue;
+		case ICNSS_SLATE_SSR_REGISTERED:
+			seq_puts(s, "SLATE SSR REGISTERED");
+			continue;
+		case ICNSS_SLATE_UP:
+			seq_puts(s, "ICNSS SLATE UP");
 		}
 
 		seq_printf(s, "UNKNOWN-%d", i);

+ 103 - 1
icnss2/main.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2020, 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #define pr_fmt(fmt) "icnss2: " fmt
@@ -45,6 +45,7 @@
 #include <linux/soc/qcom/pdr.h>
 #include <linux/remoteproc.h>
 #include <trace/hooks/remoteproc.h>
+#include <../drivers/soc/qcom/slatecom_interface.h>
 #include "main.h"
 #include "qmi.h"
 #include "debug.h"
@@ -827,6 +828,18 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 
 	set_bit(ICNSS_WLFW_CONNECTED, &priv->state);
 
+	if (priv->is_slate_rfa) {
+		if (!test_bit(ICNSS_SLATE_UP, &priv->state)) {
+			reinit_completion(&priv->slate_boot_complete);
+			icnss_pr_dbg("Waiting for slate boot up notification, 0x%lx\n",
+				     priv->state);
+			wait_for_completion(&priv->slate_boot_complete);
+		}
+
+		send_wlan_state(GMI_MGR_WLAN_BOOT_INIT);
+		icnss_pr_info("sent wlan boot init command\n");
+	}
+
 	ret = wlfw_ind_register_send_sync_msg(priv);
 	if (ret < 0) {
 		if (ret == -EALREADY) {
@@ -1128,6 +1141,11 @@ static int icnss_driver_event_fw_ready_ind(struct icnss_priv *priv, void *data)
 		goto out;
 	}
 
+	if (priv->is_slate_rfa && test_bit(ICNSS_SLATE_UP, &priv->state)) {
+		send_wlan_state(GMI_MGR_WLAN_BOOT_COMPLETE);
+		icnss_pr_info("sent wlan boot complete command\n");
+	}
+
 	if (test_bit(ICNSS_PD_RESTART, &priv->state)) {
 		ret = icnss_pd_restart_complete(priv);
 	} else {
@@ -2200,6 +2218,74 @@ static int icnss_wpss_ssr_register_notifier(struct icnss_priv *priv)
 	return ret;
 }
 
+static int icnss_slate_notifier_nb(struct notifier_block *nb,
+				   unsigned long code,
+				   void *data)
+{
+	struct icnss_priv *priv = container_of(nb, struct icnss_priv,
+					       slate_ssr_nb);
+	int ret = 0;
+
+	icnss_pr_vdbg("Slate-subsys-notify: event %lu\n", code);
+
+	if (code == QCOM_SSR_AFTER_POWERUP) {
+		set_bit(ICNSS_SLATE_UP, &priv->state);
+		complete(&priv->slate_boot_complete);
+		icnss_pr_dbg("Slate boot complete, state: 0x%lx\n",
+			     priv->state);
+	} else if (code == QCOM_SSR_BEFORE_SHUTDOWN &&
+		   test_bit(ICNSS_SLATE_UP, &priv->state)) {
+		clear_bit(ICNSS_SLATE_UP, &priv->state);
+		if (test_bit(ICNSS_PD_RESTART, &priv->state)) {
+			icnss_pr_err("PD_RESTART in progress 0x%lx\n",
+				     priv->state);
+			goto skip_pdr;
+		}
+
+		icnss_pr_dbg("Initiating PDR 0x%lx\n", priv->state);
+		ret = icnss_trigger_recovery(&priv->pdev->dev);
+		if (ret < 0) {
+			icnss_fatal_err("Fail to trigger PDR: ret: %d, state: 0x%lx\n",
+					ret, priv->state);
+			goto skip_pdr;
+		}
+	}
+
+skip_pdr:
+	return NOTIFY_OK;
+}
+
+static int icnss_slate_ssr_register_notifier(struct icnss_priv *priv)
+{
+	int ret = 0;
+
+	priv->slate_ssr_nb.notifier_call = icnss_slate_notifier_nb;
+
+	priv->slate_notify_handler =
+		qcom_register_ssr_notifier("slatefw", &priv->slate_ssr_nb);
+
+	if (IS_ERR(priv->slate_notify_handler)) {
+		ret = PTR_ERR(priv->slate_notify_handler);
+		icnss_pr_err("SLATE register notifier failed: %d\n", ret);
+	}
+
+	set_bit(ICNSS_SLATE_SSR_REGISTERED, &priv->state);
+
+	return ret;
+}
+
+static int icnss_slate_ssr_unregister_notifier(struct icnss_priv *priv)
+{
+	if (!test_and_clear_bit(ICNSS_SLATE_SSR_REGISTERED, &priv->state))
+		return 0;
+
+	qcom_unregister_ssr_notifier(priv->slate_notify_handler,
+				     &priv->slate_ssr_nb);
+	priv->slate_notify_handler = NULL;
+
+	return 0;
+}
+
 static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv)
 {
 	int ret = 0;
@@ -2521,6 +2607,10 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
 	}
 
 	icnss_modem_ssr_register_notifier(priv);
+
+	if (priv->is_slate_rfa)
+		icnss_slate_ssr_register_notifier(priv);
+
 	if (test_bit(SSR_ONLY, &priv->ctrl_params.quirks)) {
 		icnss_pr_dbg("PDR disabled through module parameter\n");
 		return 0;
@@ -3905,6 +3995,12 @@ static int icnss_resource_parse(struct icnss_priv *priv)
 			priv->is_rf_subtype_valid = true;
 			icnss_pr_dbg("RF subtype 0x%x\n", priv->rf_subtype);
 		}
+
+		if (of_property_read_bool(pdev->dev.of_node,
+					  "qcom,is_slate_rfa")) {
+			priv->is_slate_rfa = true;
+			icnss_pr_err("SLATE rfa is enabled\n");
+		}
 	} else if (priv->device_id == WCN6750_DEVICE_ID) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "msi_addr");
@@ -4345,6 +4441,9 @@ static int icnss_probe(struct platform_device *pdev)
 
 	init_completion(&priv->unblock_shutdown);
 
+	if (priv->is_slate_rfa)
+		init_completion(&priv->slate_boot_complete);
+
 	if (priv->device_id == WCN6750_DEVICE_ID) {
 		priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event",
 						    WQ_UNBOUND|WQ_HIGHPRI, 1);
@@ -4439,6 +4538,9 @@ static int icnss_remove(struct platform_device *pdev)
 
 	complete_all(&priv->unblock_shutdown);
 
+	if (priv->is_slate_rfa)
+		icnss_slate_ssr_unregister_notifier(priv);
+
 	icnss_destroy_ramdump_device(priv->msa0_dump_dev);
 
 	if (priv->wpss_supported) {

+ 7 - 0
icnss2/main.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2020, 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef __MAIN_H__
@@ -124,6 +125,8 @@ enum icnss_driver_state {
 	ICNSS_DEL_SERVER,
 	ICNSS_COLD_BOOT_CAL,
 	ICNSS_QMI_DMS_CONNECTED,
+	ICNSS_SLATE_SSR_REGISTERED,
+	ICNSS_SLATE_UP,
 };
 
 struct ce_irq_list {
@@ -427,6 +430,8 @@ struct icnss_priv {
 	struct notifier_block modem_ssr_nb;
 	struct notifier_block wpss_ssr_nb;
 	struct notifier_block wpss_early_ssr_nb;
+	void *slate_notify_handler;
+	struct notifier_block slate_ssr_nb;
 	uint32_t diag_reg_read_addr;
 	uint32_t diag_reg_read_mem_type;
 	uint32_t diag_reg_read_len;
@@ -494,6 +499,8 @@ struct icnss_priv {
 	bool wpss_supported;
 	bool is_rf_subtype_valid;
 	u32 rf_subtype;
+	u8 is_slate_rfa;
+	struct completion slate_boot_complete;
 };
 
 struct icnss_reg_info {

+ 23 - 0
inc/cnss2.h

@@ -94,6 +94,29 @@ enum cnss_driver_status {
 	CNSS_BUS_EVENT,
 };
 
+enum cnss_host_dump_type {
+	CNSS_HOST_WLAN_LOGS,
+	CNSS_HOST_HTC_CREDIT,
+	CNSS_HOST_WMI_TX_CMP,
+	CNSS_HOST_WMI_COMMAND_LOG,
+	CNSS_HOST_WMI_EVENT_LOG,
+	CNSS_HOST_WMI_RX_EVENT,
+	CNSS_HOST_HAL_SOC,
+	CNSS_HOST_WMI_HANG_DATA,
+	CNSS_HOST_CE_HANG_EVT,
+	CNSS_HOST_PEER_MAC_ADDR_HANG_DATA,
+	CNSS_HOST_CP_VDEV_INFO,
+	CNSS_HOST_GWLAN_LOGGING,
+	CNSS_HOST_WMI_DEBUG_LOG_INFO,
+	CNSS_HOST_HTC_CREDIT_IDX,
+	CNSS_HOST_HTC_CREDIT_LEN,
+	CNSS_HOST_WMI_TX_CMP_IDX,
+	CNSS_HOST_WMI_COMMAND_LOG_IDX,
+	CNSS_HOST_WMI_EVENT_LOG_IDX,
+	CNSS_HOST_WMI_RX_EVENT_IDX,
+	CNSS_HOST_DUMP_TYPE_MAX,
+};
+
 enum cnss_bus_event_type {
 	BUS_EVENT_PCI_LINK_DOWN = 0,