703 lines
20 KiB
C
Executable File
703 lines
20 KiB
C
Executable File
/*
|
|
* Copyright (c) 2018 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include <soc/samsung/exynos-bcm_dbg.h>
|
|
#include <soc/samsung/exynos-bcm_dbg-dt.h>
|
|
|
|
static const char *list[BCM_PD_INFO_MAX];
|
|
|
|
static void print_bcm_dbg_data(struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int i, j;
|
|
|
|
BCM_DBG("IPC node name: %s\n", data->ipc_node->name);
|
|
BCM_DBG("\n");
|
|
|
|
BCM_DBG("pd_size: %u, pd_sync_init: %d\n", data->pd_size, data->pd_sync_init);
|
|
for (i = 0; i < data->pd_size; i++)
|
|
BCM_DBG("pd_name: %s, pd_index: %u, pd_on: %d, cal_pdid: 0x%08x\n",
|
|
data->pd_info[i]->pd_name, data->pd_info[i]->pd_index,
|
|
data->pd_info[i]->on, data->pd_info[i]->cal_pdid);
|
|
BCM_DBG("\n");
|
|
|
|
for (i = 0; i < data->define_event_max; i++) {
|
|
BCM_DBG("Pre-defined Event index: %u\n", data->define_event[i].index);
|
|
for (j = 0; j < data->bcm_cnt_nr; j++)
|
|
BCM_DBG(" Event[%d]: 0x%02x\n", j, data->define_event[i].event[j]);
|
|
}
|
|
BCM_DBG("\n");
|
|
|
|
BCM_DBG("Default Pre-defined Event index: %u\n", data->default_define_event);
|
|
BCM_DBG("Pre-defined Event Max NR: %u\n", data->define_event_max);
|
|
BCM_DBG("\n");
|
|
|
|
for (i = 0; i < data->define_event_max; i++) {
|
|
BCM_DBG("Pre-defined Event index: %u\n", data->define_event[i].index);
|
|
BCM_DBG(" Filter ID mask: 0x%08x\n", data->define_filter_id[i].sm_id_mask);
|
|
BCM_DBG(" Filter ID value: 0x%08x\n", data->define_filter_id[i].sm_id_value);
|
|
BCM_DBG(" Filter ID active\n");
|
|
for (j = 0; j < data->bcm_cnt_nr; j++)
|
|
BCM_DBG(" Event[%d]: %u\n", j, data->define_filter_id[i].sm_id_active[j]);
|
|
}
|
|
BCM_DBG("\n");
|
|
|
|
for (i = 0; i < data->define_event_max; i++) {
|
|
BCM_DBG("Pre-defined Event index: %u\n", data->define_event[i].index);
|
|
for (j = 0; j < BCM_EVT_FLT_OTHR_MAX; j++) {
|
|
BCM_DBG(" Filter others type[%d]: 0x%02x\n",
|
|
j, data->define_filter_others[i].sm_other_type[j]);
|
|
BCM_DBG(" Filter others mask[%d]: 0x%02x\n",
|
|
j, data->define_filter_others[i].sm_other_mask[j]);
|
|
BCM_DBG(" Filter others value[%d]: 0x%02x\n",
|
|
j, data->define_filter_others[i].sm_other_value[j]);
|
|
}
|
|
BCM_DBG(" Filter others active\n");
|
|
for (j = 0; j < data->bcm_cnt_nr; j++)
|
|
BCM_DBG(" Event[%d]: %u\n",
|
|
j, data->define_filter_others[i].sm_other_active[j]);
|
|
}
|
|
BCM_DBG("\n");
|
|
|
|
for (i = 0; i < data->define_event_max; i++) {
|
|
BCM_DBG("Pre-defined Event index: %u\n", data->define_event[i].index);
|
|
BCM_DBG(" Sample ID peak mask: 0x%08x\n", data->define_sample_id[i].peak_mask);
|
|
BCM_DBG(" Sample ID peak id: 0x%08x\n", data->define_sample_id[i].peak_id);
|
|
BCM_DBG(" Sample ID active\n");
|
|
for (j = 0; j < data->bcm_cnt_nr; j++)
|
|
BCM_DBG(" Event[%d]: %u\n", j, data->define_sample_id[i].peak_enable[j]);
|
|
}
|
|
BCM_DBG("\n");
|
|
|
|
BCM_DBG("Available stop owner:\n");
|
|
for (i = 0; i < STOP_OWNER_MAX; i++)
|
|
BCM_DBG(" stop owner[%d]: %s\n", i,
|
|
data->available_stop_owner[i] ? "true" : "false");
|
|
BCM_DBG("\n");
|
|
|
|
BCM_DBG("Initial BCM run: %u\n", data->initial_bcm_run);
|
|
BCM_DBG("Initial monitor period: %u\n", data->initial_period);
|
|
BCM_DBG("Initial BCM mode: %u\n", data->initial_bcm_mode);
|
|
BCM_DBG("BCM Buffer size: 0x%x\n", data->dump_addr.buff_size);
|
|
|
|
BCM_DBG("Initial Run IPs\n");
|
|
for (i = 0; i < data->bcm_ip_nr; i++)
|
|
BCM_DBG(" BCM IP[%d]: %u\n", i, data->initial_run_ip[i]);
|
|
BCM_DBG("\n");
|
|
}
|
|
|
|
#ifdef CONFIG_OF
|
|
#ifndef CONFIG_EXYNOS_BCM_DBG_GNR
|
|
static int exynos_bcm_ipc_node_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
struct device_node *child_np;
|
|
|
|
for_each_child_of_node(np, child_np) {
|
|
const char *node_name;
|
|
|
|
node_name = child_np->name;
|
|
BCM_DBG("%s: child node name: %s\n", __func__, node_name);
|
|
if (!strcmp(node_name, "ipc_bcm_event")) {
|
|
data->ipc_node = child_np;
|
|
} else {
|
|
BCM_ERR("%s: No device node name: %s\n", __func__, node_name);
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
static int exynos_bcm_pd_info_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
unsigned int pd_index = 0;
|
|
int size;
|
|
|
|
size = of_property_count_strings(np, "pd-name");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of pd-name\n", __func__);
|
|
return size;
|
|
}
|
|
data->pd_size = size;
|
|
|
|
size = of_property_read_string_array(np, "pd-name", list, size);
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get pd-name\n", __func__);
|
|
return size;
|
|
}
|
|
|
|
for (pd_index = 0; pd_index < size; pd_index++) {
|
|
data->pd_info[pd_index] =
|
|
kzalloc(sizeof(struct exynos_bcm_pd_info), GFP_KERNEL);
|
|
data->pd_info[pd_index]->pd_name = (char *)list[pd_index];
|
|
data->pd_info[pd_index]->pd_index = pd_index;
|
|
data->pd_info[pd_index]->cal_pdid = pd_index;
|
|
BCM_DBG("%s: get pd-name: %s(%u)\n", __func__,
|
|
data->pd_info[pd_index]->pd_name,
|
|
data->pd_info[pd_index]->pd_index);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_init_run_ip_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int size, ret, i;
|
|
unsigned int run_ip;
|
|
|
|
ret = of_property_read_u32(np, "bcm_ip_nr", &data->bcm_ip_nr);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get bcm_ip_nr\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
data->initial_run_ip =
|
|
kzalloc(sizeof(unsigned int) * data->bcm_ip_nr, GFP_KERNEL);
|
|
if (data->initial_run_ip == NULL) {
|
|
BCM_ERR("%s: failed to allocate BCM IPs\n", __func__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
size = of_property_count_u32_elems(np, "initial_run_bcm_ip");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of initial run BCM IPs\n",
|
|
__func__);
|
|
kfree(data->initial_run_ip);
|
|
return size;
|
|
}
|
|
|
|
if (size > data->bcm_ip_nr) {
|
|
BCM_ERR("%s: Invalid BCM IPs size, size(%d):ip_nr(%u)\n",
|
|
__func__, size, data->bcm_ip_nr);
|
|
kfree(data->initial_run_ip);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (i = 0; i < size; i++) {
|
|
ret = of_property_read_u32_index(np,
|
|
"initial_run_bcm_ip", i, &run_ip);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get initial run BCM IP(%d)\n",
|
|
__func__, i);
|
|
kfree(data->initial_run_ip);
|
|
return ret;
|
|
}
|
|
|
|
data->initial_run_ip[run_ip] = BCM_IP_EN;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_define_event_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int i, size, ret;
|
|
int event_cnt, nr_event;
|
|
const unsigned int *event_addr;
|
|
unsigned int event_get_len, event_len;
|
|
unsigned int *event_data;
|
|
|
|
ret = of_property_read_u32(np, "max_define_event", &data->define_event_max);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get max define event\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "bcm_cnt_nr", &data->bcm_cnt_nr);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get bcm cnt nr\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
size = of_property_count_u32_elems(np, "define_events");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined events\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
event_len = data->bcm_cnt_nr + 1;
|
|
|
|
/*
|
|
* Element number of define_event is (bcm_cnt_nr + 1).
|
|
* calculation number of array
|
|
*/
|
|
if (size % event_len) {
|
|
BCM_ERR("%s: Invalid define event size, size(%d):event_len(%d)\n",
|
|
__func__, size, event_len);
|
|
return -EINVAL;
|
|
}
|
|
|
|
nr_event = size / event_len;
|
|
|
|
if (nr_event != data->define_event_max) {
|
|
BCM_ERR("%s: Invalid define event nr, nr_event(%d):nr_max(%u)\n",
|
|
__func__, nr_event, data->define_event_max);
|
|
return -EINVAL;
|
|
}
|
|
|
|
event_addr = of_get_property(np, "define_events", &event_get_len);
|
|
if (event_addr == NULL) {
|
|
BCM_ERR("%s: Failed get defined events length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
for (i = 0; i < nr_event; i++) {
|
|
event_data = (unsigned int *)&event_addr[i * event_len];
|
|
|
|
if ((size - (i * event_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined event range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->define_event[i].index = be32_to_cpu(event_data[0]);
|
|
for (event_cnt = 0; event_cnt < data->bcm_cnt_nr; event_cnt++)
|
|
data->define_event[i].event[event_cnt] =
|
|
be32_to_cpu(event_data[event_cnt + 1]);
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "default_define_event",
|
|
&data->default_define_event);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get default define event\n", __func__);
|
|
data->default_define_event = PEAK_LATENCY_FMT_EVT;
|
|
BCM_INFO("%s: replaced default define event: %u\n",
|
|
__func__, data->default_define_event);
|
|
} else {
|
|
if (data->default_define_event >= data->define_event_max) {
|
|
BCM_ERR("%s: Invalid default define event(%u), max(%u)\n",
|
|
__func__, data->default_define_event,
|
|
data->define_event_max);
|
|
data->default_define_event = PEAK_LATENCY_FMT_EVT;
|
|
BCM_INFO("%s: replaced default define event: %u\n",
|
|
__func__, data->default_define_event);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_filter_id_info_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int i, size;
|
|
int active_cnt;
|
|
const unsigned int *filter_id_addr;
|
|
const unsigned int *filter_id_active_addr;
|
|
unsigned int filter_id_len, active_len;
|
|
unsigned int filter_id_get_len, active_get_len;
|
|
unsigned int *id_data;
|
|
unsigned int *active_data;
|
|
|
|
/* sm_id_mask and sm_id_value */
|
|
size = of_property_count_u32_elems(np, "define_filter_id");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined filter_id\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
filter_id_addr = of_get_property(np, "define_filter_id", &filter_id_get_len);
|
|
if (filter_id_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define filter id length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
filter_id_len = 3;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
id_data = (unsigned int *)&filter_id_addr[i * filter_id_len];
|
|
|
|
if ((size - (i * filter_id_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined filter id range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->define_filter_id[i].sm_id_mask = be32_to_cpu(id_data[1]);
|
|
data->define_filter_id[i].sm_id_value = be32_to_cpu(id_data[2]);
|
|
}
|
|
|
|
/* sm_id_active */
|
|
size = of_property_count_u32_elems(np, "define_filter_id_active");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined filter_id_active\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
filter_id_active_addr = of_get_property(np, "define_filter_id_active",
|
|
&active_get_len);
|
|
if (filter_id_active_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define filter id active length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
active_len = data->bcm_cnt_nr + 1;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
active_data = (unsigned int *)&filter_id_active_addr[i * active_len];
|
|
|
|
if ((size - (i * active_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined filter id active range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (active_cnt = 0; active_cnt < data->bcm_cnt_nr; active_cnt++)
|
|
data->define_filter_id[i].sm_id_active[active_cnt] =
|
|
be32_to_cpu(active_data[active_cnt + 1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_filter_others_info_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int i, size;
|
|
int active_cnt;
|
|
const unsigned int *filter_other_0_addr;
|
|
const unsigned int *filter_other_1_addr;
|
|
const unsigned int *filter_other_active_addr;
|
|
unsigned int filter_other_0_len, filter_other_1_len, active_len;
|
|
unsigned int filter_other_0_get_len, filter_other_1_get_len, active_get_len;
|
|
unsigned int *other0_data;
|
|
unsigned int *other1_data;
|
|
unsigned int *active_data;
|
|
|
|
/* sm_other_type, sm_other_mask and sm_other_value */
|
|
size = of_property_count_u32_elems(np, "define_filter_other_0");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined filter_other_0\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
filter_other_0_addr = of_get_property(np, "define_filter_other_0",
|
|
&filter_other_0_get_len);
|
|
if (filter_other_0_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define filter_other_0 length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
filter_other_0_len = 4;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
other0_data = (unsigned int *)&filter_other_0_addr[i * filter_other_0_len];
|
|
|
|
if ((size - (i * filter_other_0_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined filter_other_0 range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->define_filter_others[i].sm_other_type[0] =
|
|
be32_to_cpu(other0_data[1]);
|
|
data->define_filter_others[i].sm_other_mask[0] =
|
|
be32_to_cpu(other0_data[2]);
|
|
data->define_filter_others[i].sm_other_value[0] =
|
|
be32_to_cpu(other0_data[3]);
|
|
}
|
|
|
|
size = of_property_count_u32_elems(np, "define_filter_other_1");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined filter_other_1\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
filter_other_1_addr = of_get_property(np, "define_filter_other_1",
|
|
&filter_other_1_get_len);
|
|
if (filter_other_1_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define filter_other_1 length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
filter_other_1_len = 4;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
other1_data = (unsigned int *)&filter_other_1_addr[i * filter_other_1_len];
|
|
|
|
if ((size - (i * filter_other_1_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined filter_other_1 range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->define_filter_others[i].sm_other_type[1] =
|
|
be32_to_cpu(other1_data[1]);
|
|
data->define_filter_others[i].sm_other_mask[1] =
|
|
be32_to_cpu(other1_data[2]);
|
|
data->define_filter_others[i].sm_other_value[1] =
|
|
be32_to_cpu(other1_data[3]);
|
|
}
|
|
|
|
/* sm_other_active */
|
|
size = of_property_count_u32_elems(np, "define_filter_other_active");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined filter_other_active\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
filter_other_active_addr = of_get_property(np, "define_filter_other_active",
|
|
&active_get_len);
|
|
if (filter_other_active_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define filter_other_active length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
active_len = data->bcm_cnt_nr + 1;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
active_data = (unsigned int *)&filter_other_active_addr[i * active_len];
|
|
|
|
if ((size - (i * active_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined filter_other_active range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (active_cnt = 0; active_cnt < data->bcm_cnt_nr; active_cnt++)
|
|
data->define_filter_others[i].sm_other_active[active_cnt] =
|
|
be32_to_cpu(active_data[active_cnt + 1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_sample_id_info_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int i, size;
|
|
int active_cnt;
|
|
const unsigned int *sample_id_addr;
|
|
const unsigned int *sample_active_addr;
|
|
unsigned int sample_id_len, active_len;
|
|
unsigned int sample_id_get_len, active_get_len;
|
|
unsigned int *id_data;
|
|
unsigned int *active_data;
|
|
|
|
/* peak_mask and peak_id */
|
|
size = of_property_count_u32_elems(np, "define_sample_id");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined sample_id\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
sample_id_addr = of_get_property(np, "define_sample_id", &sample_id_get_len);
|
|
if (sample_id_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define_sample_id length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
sample_id_len = 3;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
id_data = (unsigned int *)&sample_id_addr[i * sample_id_len];
|
|
|
|
if ((size - (i * sample_id_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined sample id range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->define_sample_id[i].peak_mask = be32_to_cpu(id_data[1]);
|
|
data->define_sample_id[i].peak_id = be32_to_cpu(id_data[2]);
|
|
}
|
|
|
|
/* peak_enable */
|
|
size = of_property_count_u32_elems(np, "define_sample_id_enable");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of defined sample_id_enable\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
sample_active_addr = of_get_property(np, "define_sample_id_enable",
|
|
&active_get_len);
|
|
if (sample_active_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define sample_id_enable length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
active_len = data->bcm_cnt_nr + 1;
|
|
|
|
for (i = 0; i < PRE_DEFINE_EVT_MAX; i++) {
|
|
active_data = (unsigned int *)&sample_active_addr[i * active_len];
|
|
|
|
if ((size - (i * active_len)) <= 0) {
|
|
BCM_ERR("%s: Invalid defined sample_id_enable range\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
for (active_cnt = 0; active_cnt < data->bcm_cnt_nr; active_cnt++)
|
|
data->define_sample_id[i].peak_enable[active_cnt] =
|
|
be32_to_cpu(active_data[active_cnt + 1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int exynos_bcm_init_control_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int ret;
|
|
int i, size;
|
|
const unsigned int *stop_owner_addr;
|
|
unsigned int stop_owner_get_len, owner_index;
|
|
unsigned int *stop_owner_data;
|
|
|
|
|
|
ret = of_property_read_u32(np, "initial_bcm_run", &data->initial_bcm_run);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get initial BCM run state\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "initial_period", &data->initial_period);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get initial sampling period\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "initial_bcm_mode", &data->initial_bcm_mode);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get initial BCM measure mode\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
ret = of_property_read_u32(np, "buff_size", &data->dump_addr.buff_size);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed get buffer size\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
if (data->initial_bcm_mode >= BCM_MODE_MAX) {
|
|
BCM_ERR("%s: Invalid initial BCM measure mode(%u), max(%u)\n",
|
|
__func__, data->initial_bcm_mode,
|
|
BCM_MODE_MAX);
|
|
return -EINVAL;
|
|
}
|
|
|
|
size = of_property_count_u32_elems(np, "available_stop_owner");
|
|
if (size < 0) {
|
|
BCM_ERR("%s: Failed get number of available_stop_owner\n",
|
|
__func__);
|
|
return size;
|
|
}
|
|
|
|
if (size > STOP_OWNER_MAX) {
|
|
BCM_ERR("%s: Invalid stop owner size (%u)\n", __func__, size);
|
|
return -EINVAL;
|
|
}
|
|
|
|
stop_owner_addr = of_get_property(np, "available_stop_owner", &stop_owner_get_len);
|
|
if (stop_owner_addr == NULL) {
|
|
BCM_ERR("%s: Failed get define stop owner length\n", __func__);
|
|
return -ENODEV;
|
|
}
|
|
|
|
stop_owner_data = (unsigned int *)stop_owner_addr;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
owner_index = be32_to_cpu(stop_owner_data[i]);
|
|
if (owner_index >= STOP_OWNER_MAX) {
|
|
BCM_ERR("%s: Invalid stop owner (%d:%u)\n",
|
|
__func__, i, owner_index);
|
|
return -EINVAL;
|
|
}
|
|
data->available_stop_owner[owner_index] = true;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int exynos_bcm_dbg_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (!np)
|
|
return -ENODEV;
|
|
#ifndef CONFIG_EXYNOS_BCM_DBG_GNR
|
|
/* get IPC type */
|
|
ret = exynos_bcm_ipc_node_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse IPC node\n", __func__);
|
|
return ret;
|
|
}
|
|
#endif
|
|
/* get Local Power domain names and set power domain index */
|
|
ret = exynos_bcm_pd_info_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Power domain info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get initial run BCM IPs information */
|
|
ret = exynos_bcm_init_run_ip_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse initial run BCM IPs info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get Pre-defined Event information */
|
|
ret = exynos_bcm_define_event_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Pre-defined Event info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get define Filter ID information */
|
|
ret = exynos_bcm_filter_id_info_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Filter ID info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get define Filter Others information */
|
|
ret = exynos_bcm_filter_others_info_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Filter Others info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get define Sample ID information */
|
|
ret = exynos_bcm_sample_id_info_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Sample ID info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* Get initial Control information */
|
|
ret = exynos_bcm_init_control_parse_dt(np, data);
|
|
if (ret) {
|
|
BCM_ERR("%s: Failed parse Control info\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/* printing BCM data for debug */
|
|
print_bcm_dbg_data(data);
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
int exynos_bcm_dbg_parse_dt(struct device_node *np,
|
|
struct exynos_bcm_dbg_data *data)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
#endif
|