ath10k: add memory dump support QCA9984
authorAnilkumar Kolli <akolli@codeaurora.org>
Tue, 27 Mar 2018 08:26:52 +0000 (11:26 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 29 Mar 2018 08:54:32 +0000 (11:54 +0300)
QCA9984/QCA99X0/QCA4019 chipsets have 8 memory regions, dump all of them to the
firmware coredump file. Some of the regions need to be read using ioread() so
add new region types for them.

Signed-off-by: Anilkumar Kolli <akolli@codeaurora.org>
[kvalo: refactoring etc]
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/ath10k/coredump.c
drivers/net/wireless/ath/ath10k/coredump.h
drivers/net/wireless/ath/ath10k/pci.c

index 7173b3743b43b8256a28ce7df97d239e28d728bf..f90cec0ebb1ce02d40088f1bdd03a303d41f1c6c 100644 (file)
@@ -701,6 +701,89 @@ static const struct ath10k_mem_region qca988x_hw20_mem_regions[] = {
        },
 };
 
+static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
+       {
+               .type = ATH10K_MEM_REGION_TYPE_DRAM,
+               .start = 0x400000,
+               .len = 0x80000,
+               .name = "DRAM",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_REG,
+               .start = 0x98000,
+               .len = 0x50000,
+               .name = "IRAM",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOSRAM,
+               .start = 0xC0000,
+               .len = 0x40000,
+               .name = "SRAM",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOREG,
+               .start = 0x30000,
+               .len = 0x7000,
+               .name = "APB REG 1",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOREG,
+               .start = 0x3f000,
+               .len = 0x3000,
+               .name = "APB REG 2",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOREG,
+               .start = 0x43000,
+               .len = 0x3000,
+               .name = "WIFI REG",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOREG,
+               .start = 0x4A000,
+               .len = 0x5000,
+               .name = "CE REG",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+       {
+               .type = ATH10K_MEM_REGION_TYPE_IOREG,
+               .start = 0x80000,
+               .len = 0x6000,
+               .name = "SOC REG",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+};
+
 static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
        {
                .hw_id = QCA6174_HW_1_0_VERSION,
@@ -758,6 +841,13 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
                        .size = ARRAY_SIZE(qca988x_hw20_mem_regions),
                },
        },
+       {
+               .hw_id = QCA9984_HW_1_0_DEV_VERSION,
+               .region_table = {
+                       .regions = qca9984_hw10_mem_regions,
+                       .size = ARRAY_SIZE(qca9984_hw10_mem_regions),
+               },
+       },
 };
 
 static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
index bfee13038e5925beb78c94d0e94535d434cb22c5..3baaf9d2cbcd4c7946797a8af55c27b51c1ca252 100644 (file)
@@ -124,6 +124,8 @@ enum ath10k_mem_region_type {
        ATH10K_MEM_REGION_TYPE_AXI      = 3,
        ATH10K_MEM_REGION_TYPE_IRAM1    = 4,
        ATH10K_MEM_REGION_TYPE_IRAM2    = 5,
+       ATH10K_MEM_REGION_TYPE_IOSRAM   = 6,
+       ATH10K_MEM_REGION_TYPE_IOREG    = 7,
 };
 
 /* Define a section of the region which should be copied. As not all parts
index ad2a14678be7e464465ecafc09d59e81ae102fcc..fd1566cd7d2ba847b467829b598512dfb8beccdf 100644 (file)
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
  */
 #define ATH10K_DIAG_TRANSFER_LIMIT     0x5000
 
+#define QCA99X0_PCIE_BAR0_START_REG    0x81030
+#define QCA99X0_CPU_MEM_ADDR_REG       0x4d00c
+#define QCA99X0_CPU_MEM_DATA_REG       0x4d010
+
 static const struct pci_device_id ath10k_pci_id_table[] = {
        /* PCI-E QCA988X V2 (Ubiquiti branded) */
        { PCI_VDEVICE(UBIQUITI, QCA988X_2_0_DEVICE_ID_UBNT) },
@@ -1584,6 +1588,39 @@ static int ath10k_pci_set_ram_config(struct ath10k *ar, u32 config)
        return 0;
 }
 
+/* if an error happened returns < 0, otherwise the length */
+static int ath10k_pci_dump_memory_sram(struct ath10k *ar,
+                                      const struct ath10k_mem_region *region,
+                                      u8 *buf)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 base_addr, i;
+
+       base_addr = ioread32(ar_pci->mem + QCA99X0_PCIE_BAR0_START_REG);
+       base_addr += region->start;
+
+       for (i = 0; i < region->len; i += 4) {
+               iowrite32(base_addr + i, ar_pci->mem + QCA99X0_CPU_MEM_ADDR_REG);
+               *(u32 *)(buf + i) = ioread32(ar_pci->mem + QCA99X0_CPU_MEM_DATA_REG);
+       }
+
+       return region->len;
+}
+
+/* if an error happened returns < 0, otherwise the length */
+static int ath10k_pci_dump_memory_reg(struct ath10k *ar,
+                                     const struct ath10k_mem_region *region,
+                                     u8 *buf)
+{
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       u32 i;
+
+       for (i = 0; i < region->len; i += 4)
+               *(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i);
+
+       return region->len;
+}
+
 /* if an error happened returns < 0, otherwise the length */
 static int ath10k_pci_dump_memory_generic(struct ath10k *ar,
                                          const struct ath10k_mem_region *current_region,
@@ -1673,6 +1710,12 @@ static void ath10k_pci_dump_memory(struct ath10k *ar,
                buf_len -= sizeof(*hdr);
 
                switch (current_region->type) {
+               case ATH10K_MEM_REGION_TYPE_IOSRAM:
+                       count = ath10k_pci_dump_memory_sram(ar, current_region, buf);
+                       break;
+               case ATH10K_MEM_REGION_TYPE_IOREG:
+                       count = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+                       break;
                default:
                        ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
                        if (ret < 0)