Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 219cc084 authored by Anilkumar Kolli's avatar Anilkumar Kolli Committed by Kalle Valo
Browse files

ath10k: add memory dump support QCA9984



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: default avatarAnilkumar Kolli <akolli@codeaurora.org>
[kvalo: refactoring etc]
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 10c22884
Loading
Loading
Loading
Loading
+90 −0
Original line number Original line Diff line number Diff line
@@ -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[] = {
static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
	{
	{
		.hw_id = QCA6174_HW_1_0_VERSION,
		.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),
			.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)
static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
+2 −0
Original line number Original line Diff line number Diff line
@@ -124,6 +124,8 @@ enum ath10k_mem_region_type {
	ATH10K_MEM_REGION_TYPE_AXI	= 3,
	ATH10K_MEM_REGION_TYPE_AXI	= 3,
	ATH10K_MEM_REGION_TYPE_IRAM1	= 4,
	ATH10K_MEM_REGION_TYPE_IRAM1	= 4,
	ATH10K_MEM_REGION_TYPE_IRAM2	= 5,
	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
/* Define a section of the region which should be copied. As not all parts
+43 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
 */
 */
#define ATH10K_DIAG_TRANSFER_LIMIT	0x5000
#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[] = {
static const struct pci_device_id ath10k_pci_id_table[] = {
	/* PCI-E QCA988X V2 (Ubiquiti branded) */
	/* PCI-E QCA988X V2 (Ubiquiti branded) */
	{ PCI_VDEVICE(UBIQUITI, QCA988X_2_0_DEVICE_ID_UBNT) },
	{ 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;
	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 */
/* if an error happened returns < 0, otherwise the length */
static int ath10k_pci_dump_memory_generic(struct ath10k *ar,
static int ath10k_pci_dump_memory_generic(struct ath10k *ar,
					  const struct ath10k_mem_region *current_region,
					  const struct ath10k_mem_region *current_region,
@@ -1673,6 +1710,12 @@ static void ath10k_pci_dump_memory(struct ath10k *ar,
		buf_len -= sizeof(*hdr);
		buf_len -= sizeof(*hdr);


		switch (current_region->type) {
		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:
		default:
			ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
			ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
			if (ret < 0)
			if (ret < 0)