#include <linux/of_reserved_mem.h>
#include <linux/pm_runtime.h>
#include <linux/sched/clock.h>
+#include <linux/mm_types.h>
+#include <asm/cacheflush.h>
#include "abox_dbg.h"
#include "abox_gic.h"
struct abox_dbg_dump_min {
char sram[SZ_512K];
char iva[IVA_FIRMWARE_SIZE];
+ void *dram;
+ struct page **pages;
u32 sfr[SZ_64K / sizeof(u32)];
u32 sfr_gic_gicd[SZ_4K / sizeof(u32)];
unsigned int gpr[17];
RESERVEDMEM_OF_DECLARE(abox_rmem, "exynos,abox_rmem", abox_rmem_setup);
+static void *abox_dbg_alloc_mem_atomic(struct device *dev, struct abox_dbg_dump_min *p_dump)
+{
+ int i, j;
+ int npages = DRAM_FIRMWARE_SIZE / PAGE_SIZE;
+ struct page **tmp;
+ gfp_t alloc_gfp_flag = GFP_KERNEL | GFP_ATOMIC;
+
+ p_dump->pages = kzalloc(sizeof(struct page *) * npages, alloc_gfp_flag);
+ if (!p_dump->pages) {
+ dev_info(dev, "Failed to allocate array of struct pages\n");
+ return NULL;
+ }
+
+ tmp = p_dump->pages;
+ for (i = 0; i < npages; i++, tmp++) {
+ *tmp = alloc_page(alloc_gfp_flag);
+ if (*tmp == NULL) {
+ pr_err("Failed to allocate pages for abox debug\n");
+ goto free_pg;
+ }
+ }
+
+ return vm_map_ram(p_dump->pages, npages, -1, PAGE_KERNEL);
+
+free_pg:
+ tmp = p_dump->pages;
+ for (j = 0; j < i; j++, tmp++)
+ __free_pages(*tmp, 0);
+ kfree(p_dump->pages);
+ p_dump->pages = NULL;
+ return NULL;
+}
+
void abox_dbg_dump_gpr_from_addr(struct device *dev, unsigned int *addr,
enum abox_dbg_dump_src src, const char *reason)
{
sizeof(p_dump->sfr_gic_gicd));
} else if (p_abox_dbg_dump_min) {
struct abox_dbg_dump_min *p_dump = &(*p_abox_dbg_dump_min)[src];
-
p_dump->time = sched_clock();
strncpy(p_dump->reason, reason, sizeof(p_dump->reason) - 1);
memcpy_fromio(p_dump->sram, data->sram_base, data->sram_size);
memcpy_fromio(p_dump->sfr, data->sfr_base, sizeof(p_dump->sfr));
memcpy_fromio(p_dump->sfr_gic_gicd, gic_data->gicd_base,
sizeof(p_dump->sfr_gic_gicd));
+ if (!p_dump->dram) {
+ if (src == ABOX_DBG_DUMP_KERNEL)
+ p_dump->dram = vzalloc(DRAM_FIRMWARE_SIZE);
+ else if (src == ABOX_DBG_DUMP_FIRMWARE)
+ p_dump->dram = abox_dbg_alloc_mem_atomic(dev, p_dump);
+ }
+ if (!IS_ERR_OR_NULL(p_dump->dram)) {
+ memcpy(p_dump->dram, data->dram_base, DRAM_FIRMWARE_SIZE);
+ flush_cache_all();
+ } else {
+ dev_info(dev, "Failed to save ABOX dram\n");
+ }
}
}
abox_rmem->size, 0);
data->dump_base = phys_to_virt(abox_rmem->base);
data->dump_base_phys = abox_rmem->base;
+ memset(data->dump_base, 0x0, abox_rmem->size);
ret = device_create_file(dev, &dev_attr_gpr);
bin_attr_calliope_sram.size = data->sram_size;
bin_attr_calliope_sram.private = data->sram_base;
static int samsung_abox_debug_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
+ int i;
dev_dbg(dev, "%s\n", __func__);
+ for (i = 0; i < ABOX_DBG_DUMP_COUNT; i++) {
+ if (i == ABOX_DBG_DUMP_KERNEL) {
+ vfree(p_abox_dbg_dump_min[i]->dram);
+ } else if (i == ABOX_DBG_DUMP_FIRMWARE) {
+ struct page **tmp = p_abox_dbg_dump_min[i]->pages;
+ if (p_abox_dbg_dump_min[i]->dram)
+ vm_unmap_ram(p_abox_dbg_dump_min[i]->dram,
+ DRAM_FIRMWARE_SIZE);
+ if (tmp) {
+ int j;
+ for (j = 0; j < DRAM_FIRMWARE_SIZE / PAGE_SIZE; j++, tmp++)
+ __free_pages(*tmp, 0);
+ kfree(p_abox_dbg_dump_min[i]->pages);
+ p_abox_dbg_dump_min[i]->pages = NULL;
+ }
+ }
+ }
return 0;
}