mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
coresight: switch to use coresight core layer code
Switch all CoreSight drivers to start using the new CoreSight core layer code. Remove obsolete qdss code. Change-Id: I2d4496aea0ffd918e0bfbf4b4e58ad82ea634a59 Signed-off-by: Pratik Patel <pratikp@codeaurora.org>
This commit is contained in:
parent
51b53a1897
commit
f264c3258c
15 changed files with 1040 additions and 1158 deletions
|
@ -2277,11 +2277,13 @@ static struct platform_device *common_devices[] __initdata = {
|
|||
&msm8960_device_ebi1_ch0_erp,
|
||||
&msm8960_device_ebi1_ch1_erp,
|
||||
&epm_adc_device,
|
||||
&apq8064_qdss_device,
|
||||
&msm_etb_device,
|
||||
&msm_tpiu_device,
|
||||
&msm_funnel_device,
|
||||
&apq8064_etm_device,
|
||||
&coresight_tpiu_device,
|
||||
&coresight_etb_device,
|
||||
&apq8064_coresight_funnel_device,
|
||||
&coresight_etm0_device,
|
||||
&coresight_etm1_device,
|
||||
&coresight_etm2_device,
|
||||
&coresight_etm3_device,
|
||||
&apq_cpudai_slim_4_rx,
|
||||
&apq_cpudai_slim_4_tx,
|
||||
#ifdef CONFIG_MSM_GEMINI
|
||||
|
|
|
@ -2239,14 +2239,11 @@ static struct platform_device *common_devices[] __initdata = {
|
|||
&msm8930_ion_dev,
|
||||
#endif
|
||||
&msm_device_tz_log,
|
||||
|
||||
#ifdef CONFIG_MSM_QDSS
|
||||
&msm_qdss_device,
|
||||
&msm_etb_device,
|
||||
&msm_tpiu_device,
|
||||
&msm_funnel_device,
|
||||
&msm_etm_device,
|
||||
#endif
|
||||
&coresight_tpiu_device,
|
||||
&coresight_etb_device,
|
||||
&coresight_funnel_device,
|
||||
&coresight_etm0_device,
|
||||
&coresight_etm1_device,
|
||||
&msm_device_dspcrashd_8960,
|
||||
&msm8960_device_watchdog,
|
||||
#ifdef MSM8930_PHASE_2
|
||||
|
|
|
@ -2664,13 +2664,11 @@ static struct platform_device *common_devices[] __initdata = {
|
|||
&msm8960_rpm_log_device,
|
||||
&msm8960_rpm_stat_device,
|
||||
&msm_device_tz_log,
|
||||
#ifdef CONFIG_MSM_QDSS
|
||||
&msm_qdss_device,
|
||||
&msm_etb_device,
|
||||
&msm_tpiu_device,
|
||||
&msm_funnel_device,
|
||||
&msm_etm_device,
|
||||
#endif
|
||||
&coresight_tpiu_device,
|
||||
&coresight_etb_device,
|
||||
&coresight_funnel_device,
|
||||
&coresight_etm0_device,
|
||||
&coresight_etm1_device,
|
||||
&msm_device_dspcrashd_8960,
|
||||
&msm8960_device_watchdog,
|
||||
&msm8960_rtb_device,
|
||||
|
|
|
@ -5176,11 +5176,13 @@ static struct clk_lookup msm_clocks_8064[] = {
|
|||
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
|
||||
|
||||
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, ""),
|
||||
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""),
|
||||
|
@ -5515,11 +5517,13 @@ static struct clk_lookup msm_clocks_8960_common[] __initdata = {
|
|||
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
|
||||
|
||||
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
|
||||
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
|
||||
|
@ -5861,11 +5865,13 @@ static struct clk_lookup msm_clocks_8930[] = {
|
|||
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
|
||||
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
|
||||
CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
|
||||
|
||||
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
|
||||
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
|
||||
|
|
|
@ -2666,43 +2666,105 @@ struct platform_device apq8064_device_cache_erp = {
|
|||
.resource = msm_cache_erp_resources,
|
||||
};
|
||||
|
||||
#define MSM_QDSS_PHYS_BASE 0x01A00000
|
||||
#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
|
||||
#define CORESIGHT_PHYS_BASE 0x01A00000
|
||||
#define CORESIGHT_FUNNEL_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x4000)
|
||||
#define CORESIGHT_ETM2_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1E000)
|
||||
#define CORESIGHT_ETM3_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1F000)
|
||||
|
||||
#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
|
||||
|
||||
static struct qdss_source msm_qdss_sources[] = {
|
||||
QDSS_SOURCE("msm_etm", 0x33),
|
||||
QDSS_SOURCE("msm_oxili", 0x80),
|
||||
};
|
||||
|
||||
static struct msm_qdss_platform_data qdss_pdata = {
|
||||
.src_table = msm_qdss_sources,
|
||||
.size = ARRAY_SIZE(msm_qdss_sources),
|
||||
.afamily = 1,
|
||||
};
|
||||
|
||||
struct platform_device apq8064_qdss_device = {
|
||||
.name = "msm_qdss",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &qdss_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_etm_resources[] = {
|
||||
static struct resource coresight_funnel_resources[] = {
|
||||
{
|
||||
.start = MSM_ETM_PHYS_BASE,
|
||||
.end = MSM_ETM_PHYS_BASE + (SZ_4K * 4) - 1,
|
||||
.start = CORESIGHT_FUNNEL_PHYS_BASE,
|
||||
.end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device apq8064_etm_device = {
|
||||
.name = "msm_etm",
|
||||
static const int coresight_funnel_outports[] = { 0, 1 };
|
||||
static const int coresight_funnel_child_ids[] = { 0, 1 };
|
||||
static const int coresight_funnel_child_ports[] = { 0, 0 };
|
||||
|
||||
static struct coresight_platform_data coresight_funnel_pdata = {
|
||||
.id = 2,
|
||||
.name = "coresight-funnel",
|
||||
.nr_inports = 4,
|
||||
.outports = coresight_funnel_outports,
|
||||
.child_ids = coresight_funnel_child_ids,
|
||||
.child_ports = coresight_funnel_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_funnel_outports),
|
||||
};
|
||||
|
||||
struct platform_device apq8064_coresight_funnel_device = {
|
||||
.name = "coresight-funnel",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_etm_resources),
|
||||
.resource = msm_etm_resources,
|
||||
.num_resources = ARRAY_SIZE(coresight_funnel_resources),
|
||||
.resource = coresight_funnel_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_funnel_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_etm2_resources[] = {
|
||||
{
|
||||
.start = CORESIGHT_ETM2_PHYS_BASE,
|
||||
.end = CORESIGHT_ETM2_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static const int coresight_etm2_outports[] = { 0 };
|
||||
static const int coresight_etm2_child_ids[] = { 2 };
|
||||
static const int coresight_etm2_child_ports[] = { 4 };
|
||||
|
||||
static struct coresight_platform_data coresight_etm2_pdata = {
|
||||
.id = 6,
|
||||
.name = "coresight-etm2",
|
||||
.nr_inports = 1,
|
||||
.outports = coresight_etm2_outports,
|
||||
.child_ids = coresight_etm2_child_ids,
|
||||
.child_ports = coresight_etm2_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_etm2_outports),
|
||||
};
|
||||
|
||||
struct platform_device coresight_etm2_device = {
|
||||
.name = "coresight-etm",
|
||||
.id = 2,
|
||||
.num_resources = ARRAY_SIZE(coresight_etm2_resources),
|
||||
.resource = coresight_etm2_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_etm2_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_etm3_resources[] = {
|
||||
{
|
||||
.start = CORESIGHT_ETM3_PHYS_BASE,
|
||||
.end = CORESIGHT_ETM3_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static const int coresight_etm3_outports[] = { 0 };
|
||||
static const int coresight_etm3_child_ids[] = { 2 };
|
||||
static const int coresight_etm3_child_ports[] = { 5 };
|
||||
|
||||
static struct coresight_platform_data coresight_etm3_pdata = {
|
||||
.id = 7,
|
||||
.name = "coresight-etm3",
|
||||
.nr_inports = 3,
|
||||
.outports = coresight_etm3_outports,
|
||||
.child_ids = coresight_etm3_child_ids,
|
||||
.child_ports = coresight_etm3_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_etm3_outports),
|
||||
};
|
||||
|
||||
struct platform_device coresight_etm3_device = {
|
||||
.name = "coresight-etm",
|
||||
.id = 3,
|
||||
.num_resources = ARRAY_SIZE(coresight_etm3_resources),
|
||||
.resource = coresight_etm3_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_etm3_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
|
||||
|
|
|
@ -3457,95 +3457,199 @@ struct platform_device msm_dsps_device = {
|
|||
|
||||
#endif /* CONFIG_MSM_DSPS */
|
||||
|
||||
#ifdef CONFIG_MSM_QDSS
|
||||
#define CORESIGHT_PHYS_BASE 0x01A00000
|
||||
#define CORESIGHT_TPIU_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x3000)
|
||||
#define CORESIGHT_ETB_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1000)
|
||||
#define CORESIGHT_FUNNEL_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x4000)
|
||||
#define CORESIGHT_STM_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x6000)
|
||||
#define CORESIGHT_ETM0_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1C000)
|
||||
#define CORESIGHT_ETM1_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1D000)
|
||||
|
||||
#define MSM_QDSS_PHYS_BASE 0x01A00000
|
||||
#define MSM_ETB_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1000)
|
||||
#define MSM_TPIU_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x3000)
|
||||
#define MSM_FUNNEL_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x4000)
|
||||
#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
|
||||
#define CORESIGHT_STM_CHANNEL_PHYS_BASE (0x14000000 + 0x280000)
|
||||
|
||||
#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
|
||||
|
||||
static struct qdss_source msm_qdss_sources[] = {
|
||||
QDSS_SOURCE("msm_etm", 0x3),
|
||||
};
|
||||
|
||||
static struct msm_qdss_platform_data qdss_pdata = {
|
||||
.src_table = msm_qdss_sources,
|
||||
.size = ARRAY_SIZE(msm_qdss_sources),
|
||||
.afamily = 1,
|
||||
};
|
||||
|
||||
struct platform_device msm_qdss_device = {
|
||||
.name = "msm_qdss",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &qdss_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_etb_resources[] = {
|
||||
static struct resource coresight_tpiu_resources[] = {
|
||||
{
|
||||
.start = MSM_ETB_PHYS_BASE,
|
||||
.end = MSM_ETB_PHYS_BASE + SZ_4K - 1,
|
||||
.start = CORESIGHT_TPIU_PHYS_BASE,
|
||||
.end = CORESIGHT_TPIU_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_etb_device = {
|
||||
.name = "msm_etb",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_etb_resources),
|
||||
.resource = msm_etb_resources,
|
||||
static struct coresight_platform_data coresight_tpiu_pdata = {
|
||||
.id = 0,
|
||||
.name = "coresight-tpiu",
|
||||
.nr_inports = 1,
|
||||
.nr_outports = 0,
|
||||
};
|
||||
|
||||
static struct resource msm_tpiu_resources[] = {
|
||||
struct platform_device coresight_tpiu_device = {
|
||||
.name = "coresight-tpiu",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(coresight_tpiu_resources),
|
||||
.resource = coresight_tpiu_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_tpiu_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_etb_resources[] = {
|
||||
{
|
||||
.start = MSM_TPIU_PHYS_BASE,
|
||||
.end = MSM_TPIU_PHYS_BASE + SZ_4K - 1,
|
||||
.start = CORESIGHT_ETB_PHYS_BASE,
|
||||
.end = CORESIGHT_ETB_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_tpiu_device = {
|
||||
.name = "msm_tpiu",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_tpiu_resources),
|
||||
.resource = msm_tpiu_resources,
|
||||
static struct coresight_platform_data coresight_etb_pdata = {
|
||||
.id = 1,
|
||||
.name = "coresight-etb",
|
||||
.nr_inports = 1,
|
||||
.nr_outports = 0,
|
||||
.default_sink = true,
|
||||
};
|
||||
|
||||
static struct resource msm_funnel_resources[] = {
|
||||
struct platform_device coresight_etb_device = {
|
||||
.name = "coresight-etb",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(coresight_etb_resources),
|
||||
.resource = coresight_etb_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_etb_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_funnel_resources[] = {
|
||||
{
|
||||
.start = MSM_FUNNEL_PHYS_BASE,
|
||||
.end = MSM_FUNNEL_PHYS_BASE + SZ_4K - 1,
|
||||
.start = CORESIGHT_FUNNEL_PHYS_BASE,
|
||||
.end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_funnel_device = {
|
||||
.name = "msm_funnel",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_funnel_resources),
|
||||
.resource = msm_funnel_resources,
|
||||
static const int coresight_funnel_outports[] = { 0, 1 };
|
||||
static const int coresight_funnel_child_ids[] = { 0, 1 };
|
||||
static const int coresight_funnel_child_ports[] = { 0, 0 };
|
||||
|
||||
static struct coresight_platform_data coresight_funnel_pdata = {
|
||||
.id = 2,
|
||||
.name = "coresight-funnel",
|
||||
.nr_inports = 4,
|
||||
.outports = coresight_funnel_outports,
|
||||
.child_ids = coresight_funnel_child_ids,
|
||||
.child_ports = coresight_funnel_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_funnel_outports),
|
||||
};
|
||||
|
||||
static struct resource msm_etm_resources[] = {
|
||||
struct platform_device coresight_funnel_device = {
|
||||
.name = "coresight-funnel",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(coresight_funnel_resources),
|
||||
.resource = coresight_funnel_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_funnel_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_stm_resources[] = {
|
||||
{
|
||||
.start = MSM_ETM_PHYS_BASE,
|
||||
.end = MSM_ETM_PHYS_BASE + (SZ_4K * 2) - 1,
|
||||
.start = CORESIGHT_STM_PHYS_BASE,
|
||||
.end = CORESIGHT_STM_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = CORESIGHT_STM_CHANNEL_PHYS_BASE,
|
||||
.end = CORESIGHT_STM_CHANNEL_PHYS_BASE + SZ_1M + SZ_512K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device msm_etm_device = {
|
||||
.name = "msm_etm",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(msm_etm_resources),
|
||||
.resource = msm_etm_resources,
|
||||
static const int coresight_stm_outports[] = { 0 };
|
||||
static const int coresight_stm_child_ids[] = { 2 };
|
||||
static const int coresight_stm_child_ports[] = { 2 };
|
||||
|
||||
static struct coresight_platform_data coresight_stm_pdata = {
|
||||
.id = 3,
|
||||
.name = "coresight-stm",
|
||||
.nr_inports = 0,
|
||||
.outports = coresight_stm_outports,
|
||||
.child_ids = coresight_stm_child_ids,
|
||||
.child_ports = coresight_stm_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_stm_outports),
|
||||
};
|
||||
|
||||
#endif
|
||||
struct platform_device coresight_stm_device = {
|
||||
.name = "coresight-stm",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(coresight_stm_resources),
|
||||
.resource = coresight_stm_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_stm_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_etm0_resources[] = {
|
||||
{
|
||||
.start = CORESIGHT_ETM0_PHYS_BASE,
|
||||
.end = CORESIGHT_ETM0_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static const int coresight_etm0_outports[] = { 0 };
|
||||
static const int coresight_etm0_child_ids[] = { 2 };
|
||||
static const int coresight_etm0_child_ports[] = { 0 };
|
||||
|
||||
static struct coresight_platform_data coresight_etm0_pdata = {
|
||||
.id = 4,
|
||||
.name = "coresight-etm0",
|
||||
.nr_inports = 0,
|
||||
.outports = coresight_etm0_outports,
|
||||
.child_ids = coresight_etm0_child_ids,
|
||||
.child_ports = coresight_etm0_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_etm0_outports),
|
||||
};
|
||||
|
||||
struct platform_device coresight_etm0_device = {
|
||||
.name = "coresight-etm",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(coresight_etm0_resources),
|
||||
.resource = coresight_etm0_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_etm0_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource coresight_etm1_resources[] = {
|
||||
{
|
||||
.start = CORESIGHT_ETM1_PHYS_BASE,
|
||||
.end = CORESIGHT_ETM1_PHYS_BASE + SZ_4K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static const int coresight_etm1_outports[] = { 0 };
|
||||
static const int coresight_etm1_child_ids[] = { 2 };
|
||||
static const int coresight_etm1_child_ports[] = { 1 };
|
||||
|
||||
static struct coresight_platform_data coresight_etm1_pdata = {
|
||||
.id = 5,
|
||||
.name = "coresight-etm1",
|
||||
.nr_inports = 0,
|
||||
.outports = coresight_etm1_outports,
|
||||
.child_ids = coresight_etm1_child_ids,
|
||||
.child_ports = coresight_etm1_child_ports,
|
||||
.nr_outports = ARRAY_SIZE(coresight_etm1_outports),
|
||||
};
|
||||
|
||||
struct platform_device coresight_etm1_device = {
|
||||
.name = "coresight-etm",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(coresight_etm1_resources),
|
||||
.resource = coresight_etm1_resources,
|
||||
.dev = {
|
||||
.platform_data = &coresight_etm1_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_ebi1_ch0_erp_resources[] = {
|
||||
{
|
||||
|
|
|
@ -363,13 +363,14 @@ extern struct platform_device msm8064_device_watchdog;
|
|||
extern struct platform_device msm9615_device_watchdog;
|
||||
extern struct platform_device fsm9xxx_device_watchdog;
|
||||
|
||||
extern struct platform_device apq8064_qdss_device;
|
||||
extern struct platform_device msm_qdss_device;
|
||||
extern struct platform_device msm_etb_device;
|
||||
extern struct platform_device msm_tpiu_device;
|
||||
extern struct platform_device msm_funnel_device;
|
||||
extern struct platform_device msm_etm_device;
|
||||
extern struct platform_device apq8064_etm_device;
|
||||
extern struct platform_device coresight_tpiu_device;
|
||||
extern struct platform_device coresight_etb_device;
|
||||
extern struct platform_device coresight_funnel_device;
|
||||
extern struct platform_device apq8064_coresight_funnel_device;
|
||||
extern struct platform_device coresight_etm0_device;
|
||||
extern struct platform_device coresight_etm1_device;
|
||||
extern struct platform_device coresight_etm2_device;
|
||||
extern struct platform_device coresight_etm3_device;
|
||||
#endif
|
||||
|
||||
extern struct platform_device msm_bus_8064_apps_fabric;
|
||||
|
|
|
@ -23,15 +23,28 @@
|
|||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
|
||||
#define etb_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
|
||||
#define etb_readl(drvdata, off) __raw_readl(drvdata->base + off)
|
||||
|
||||
#define ETB_LOCK(drvdata) \
|
||||
do { \
|
||||
mb(); \
|
||||
etb_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define ETB_UNLOCK(drvdata) \
|
||||
do { \
|
||||
etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define ETB_RAM_DEPTH_REG (0x004)
|
||||
#define ETB_STATUS_REG (0x00C)
|
||||
#define ETB_RAM_READ_DATA_REG (0x010)
|
||||
|
@ -55,37 +68,27 @@
|
|||
#define ETB_SIZE_WORDS 4096
|
||||
#define FRAME_SIZE_WORDS 4
|
||||
|
||||
#define ETB_LOCK() \
|
||||
do { \
|
||||
mb(); \
|
||||
etb_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define ETB_UNLOCK() \
|
||||
do { \
|
||||
etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
struct etb_drvdata {
|
||||
uint8_t *buf;
|
||||
void __iomem *base;
|
||||
bool enabled;
|
||||
bool reading;
|
||||
spinlock_t spinlock;
|
||||
atomic_t in_use;
|
||||
struct device *dev;
|
||||
struct kobject *kobj;
|
||||
struct clk *clk;
|
||||
uint32_t trigger_cntr;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct miscdevice miscdev;
|
||||
struct clk *clk;
|
||||
spinlock_t spinlock;
|
||||
bool reading;
|
||||
atomic_t in_use;
|
||||
uint8_t *buf;
|
||||
bool enable;
|
||||
uint32_t trigger_cntr;
|
||||
};
|
||||
|
||||
static struct etb_drvdata *drvdata;
|
||||
|
||||
static void __etb_enable(void)
|
||||
static void __etb_enable(struct etb_drvdata *drvdata)
|
||||
{
|
||||
int i;
|
||||
|
||||
ETB_UNLOCK();
|
||||
ETB_UNLOCK(drvdata);
|
||||
|
||||
etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
|
||||
for (i = 0; i < ETB_SIZE_WORDS; i++)
|
||||
|
@ -98,11 +101,12 @@ static void __etb_enable(void)
|
|||
etb_writel(drvdata, BIT(13) | BIT(0), ETB_FFCR);
|
||||
etb_writel(drvdata, BIT(0), ETB_CTL_REG);
|
||||
|
||||
ETB_LOCK();
|
||||
ETB_LOCK(drvdata);
|
||||
}
|
||||
|
||||
int etb_enable(void)
|
||||
static int etb_enable(struct coresight_device *csdev)
|
||||
{
|
||||
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -111,25 +115,24 @@ int etb_enable(void)
|
|||
return ret;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
__etb_enable();
|
||||
drvdata->enabled = true;
|
||||
dev_info(drvdata->dev, "ETB enabled\n");
|
||||
__etb_enable(drvdata);
|
||||
drvdata->enable = true;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_info(drvdata->dev, "ETB enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __etb_disable(void)
|
||||
static void __etb_disable(struct etb_drvdata *drvdata)
|
||||
{
|
||||
int count;
|
||||
uint32_t ffcr;
|
||||
|
||||
ETB_UNLOCK();
|
||||
ETB_UNLOCK(drvdata);
|
||||
|
||||
ffcr = etb_readl(drvdata, ETB_FFCR);
|
||||
ffcr |= (BIT(12) | BIT(6));
|
||||
etb_writel(drvdata, ffcr, ETB_FFCR);
|
||||
|
||||
for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFCR), 6) != 0
|
||||
&& count > 0; count--)
|
||||
udelay(1);
|
||||
|
@ -137,30 +140,16 @@ static void __etb_disable(void)
|
|||
etb_readl(drvdata, ETB_FFCR));
|
||||
|
||||
etb_writel(drvdata, 0x0, ETB_CTL_REG);
|
||||
|
||||
for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFSR), 1) != 1
|
||||
&& count > 0; count--)
|
||||
udelay(1);
|
||||
WARN(count == 0, "timeout while disabling DRVDATA, ETB_FFSR: %#x\n",
|
||||
etb_readl(drvdata, ETB_FFSR));
|
||||
|
||||
ETB_LOCK();
|
||||
ETB_LOCK(drvdata);
|
||||
}
|
||||
|
||||
void etb_disable(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
__etb_disable();
|
||||
drvdata->enabled = false;
|
||||
dev_info(drvdata->dev, "ETB disabled\n");
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
}
|
||||
|
||||
static void __etb_dump(void)
|
||||
static void __etb_dump(struct etb_drvdata *drvdata)
|
||||
{
|
||||
int i;
|
||||
uint8_t *buf_ptr;
|
||||
|
@ -170,7 +159,7 @@ static void __etb_dump(void)
|
|||
uint32_t frame_off;
|
||||
uint32_t frame_endoff;
|
||||
|
||||
ETB_UNLOCK();
|
||||
ETB_UNLOCK(drvdata);
|
||||
|
||||
read_ptr = etb_readl(drvdata, ETB_RAM_READ_POINTER);
|
||||
write_ptr = etb_readl(drvdata, ETB_RAM_WRITE_POINTER);
|
||||
|
@ -211,26 +200,54 @@ static void __etb_dump(void)
|
|||
|
||||
etb_writel(drvdata, read_ptr, ETB_RAM_READ_POINTER);
|
||||
|
||||
ETB_LOCK();
|
||||
ETB_LOCK(drvdata);
|
||||
}
|
||||
|
||||
void etb_dump(void)
|
||||
static void etb_disable(struct coresight_device *csdev)
|
||||
{
|
||||
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
__etb_disable(drvdata);
|
||||
__etb_dump(drvdata);
|
||||
drvdata->enable = false;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "ETB disabled\n");
|
||||
}
|
||||
|
||||
static const struct coresight_ops_sink etb_sink_ops = {
|
||||
.enable = etb_enable,
|
||||
.disable = etb_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops etb_cs_ops = {
|
||||
.sink_ops = &etb_sink_ops,
|
||||
};
|
||||
|
||||
static void etb_dump(struct etb_drvdata *drvdata)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (drvdata->enabled) {
|
||||
__etb_disable();
|
||||
__etb_dump();
|
||||
__etb_enable();
|
||||
|
||||
dev_info(drvdata->dev, "ETB dumped\n");
|
||||
if (drvdata->enable) {
|
||||
__etb_disable(drvdata);
|
||||
__etb_dump(drvdata);
|
||||
__etb_enable(drvdata);
|
||||
}
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_info(drvdata->dev, "ETB dumped\n");
|
||||
}
|
||||
|
||||
static int etb_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct etb_drvdata *drvdata = container_of(file->private_data,
|
||||
struct etb_drvdata, miscdev);
|
||||
|
||||
if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
|
||||
return -EBUSY;
|
||||
|
||||
|
@ -241,8 +258,11 @@ static int etb_open(struct inode *inode, struct file *file)
|
|||
static ssize_t etb_read(struct file *file, char __user *data,
|
||||
size_t len, loff_t *ppos)
|
||||
{
|
||||
struct etb_drvdata *drvdata = container_of(file->private_data,
|
||||
struct etb_drvdata, miscdev);
|
||||
|
||||
if (drvdata->reading == false) {
|
||||
etb_dump();
|
||||
etb_dump(drvdata);
|
||||
drvdata->reading = true;
|
||||
}
|
||||
|
||||
|
@ -258,38 +278,35 @@ static ssize_t etb_read(struct file *file, char __user *data,
|
|||
|
||||
dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
|
||||
__func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int etb_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
drvdata->reading = false;
|
||||
struct etb_drvdata *drvdata = container_of(file->private_data,
|
||||
struct etb_drvdata, miscdev);
|
||||
|
||||
drvdata->reading = false;
|
||||
atomic_set(&drvdata->in_use, 0);
|
||||
|
||||
dev_dbg(drvdata->dev, "%s: released\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations etb_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = etb_open,
|
||||
.read = etb_read,
|
||||
.release = etb_release,
|
||||
};
|
||||
|
||||
static struct miscdevice etb_misc = {
|
||||
.name = "msm_etb",
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.fops = &etb_fops,
|
||||
.owner = THIS_MODULE,
|
||||
.open = etb_open,
|
||||
.read = etb_read,
|
||||
.release = etb_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static ssize_t etb_show_trigger_cntr(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val = drvdata->trigger_cntr;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
}
|
||||
|
||||
|
@ -297,6 +314,7 @@ static ssize_t etb_store_trigger_cntr(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (sscanf(buf, "%lx", &val) != 1)
|
||||
|
@ -308,61 +326,44 @@ static ssize_t etb_store_trigger_cntr(struct device *dev,
|
|||
static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, etb_show_trigger_cntr,
|
||||
etb_store_trigger_cntr);
|
||||
|
||||
static int __devinit etb_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
static struct attribute *etb_attrs[] = {
|
||||
&dev_attr_trigger_cntr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
drvdata->kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
|
||||
if (!drvdata->kobj) {
|
||||
dev_err(drvdata->dev, "failed to create ETB sysfs kobject\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_create;
|
||||
}
|
||||
static struct attribute_group etb_attr_grp = {
|
||||
.attrs = etb_attrs,
|
||||
};
|
||||
|
||||
ret = sysfs_create_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
|
||||
if (ret) {
|
||||
dev_err(drvdata->dev, "failed to create ETB sysfs trigger_cntr"
|
||||
" attribute\n");
|
||||
goto err_file;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_file:
|
||||
kobject_put(drvdata->kobj);
|
||||
err_create:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit etb_sysfs_exit(void)
|
||||
{
|
||||
sysfs_remove_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
|
||||
kobject_put(drvdata->kobj);
|
||||
}
|
||||
static const struct attribute_group *etb_attr_grps[] = {
|
||||
&etb_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __devinit etb_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct etb_drvdata *drvdata;
|
||||
struct resource *res;
|
||||
struct coresight_desc *desc;
|
||||
|
||||
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_drvdata;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -EINVAL;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
drvdata->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!drvdata->base) {
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
drvdata->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
spin_lock_init(&drvdata->spinlock);
|
||||
|
||||
|
@ -376,24 +377,47 @@ static int __devinit etb_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_clk_rate;
|
||||
|
||||
ret = misc_register(&etb_misc);
|
||||
if (ret)
|
||||
goto err_misc;
|
||||
|
||||
drvdata->buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
|
||||
if (!drvdata->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
goto err_kzalloc_buf;
|
||||
}
|
||||
drvdata->miscdev.name = ((struct coresight_platform_data *)
|
||||
(pdev->dev.platform_data))->name;
|
||||
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
drvdata->miscdev.fops = &etb_fops;
|
||||
ret = misc_register(&drvdata->miscdev);
|
||||
if (ret)
|
||||
goto err_misc_register;
|
||||
|
||||
etb_sysfs_init();
|
||||
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_desc;
|
||||
}
|
||||
desc->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
|
||||
desc->ops = &etb_cs_ops;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
desc->groups = etb_attr_grps;
|
||||
desc->owner = THIS_MODULE;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto err_coresight_register;
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
dev_info(drvdata->dev, "ETB initialized\n");
|
||||
return 0;
|
||||
|
||||
err_alloc:
|
||||
misc_deregister(&etb_misc);
|
||||
err_misc:
|
||||
err_coresight_register:
|
||||
kfree(desc);
|
||||
err_kzalloc_desc:
|
||||
misc_deregister(&drvdata->miscdev);
|
||||
err_misc_register:
|
||||
kfree(drvdata->buf);
|
||||
err_kzalloc_buf:
|
||||
err_clk_rate:
|
||||
clk_put(drvdata->clk);
|
||||
err_clk_get:
|
||||
|
@ -408,20 +432,19 @@ err_kzalloc_drvdata:
|
|||
|
||||
static int __devexit etb_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (drvdata->enabled)
|
||||
etb_disable();
|
||||
etb_sysfs_exit();
|
||||
struct etb_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
misc_deregister(&drvdata->miscdev);
|
||||
kfree(drvdata->buf);
|
||||
misc_deregister(&etb_misc);
|
||||
clk_put(drvdata->clk);
|
||||
iounmap(drvdata->base);
|
||||
kfree(drvdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id etb_match[] = {
|
||||
{.compatible = "qcom,msm-etb"},
|
||||
{.compatible = "coresight-etb"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -429,7 +452,7 @@ static struct platform_driver etb_driver = {
|
|||
.probe = etb_probe,
|
||||
.remove = __devexit_p(etb_remove),
|
||||
.driver = {
|
||||
.name = "msm_etb",
|
||||
.name = "coresight-etb",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = etb_match,
|
||||
},
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,109 +24,118 @@
|
|||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define funnel_writel(drvdata, id, val, off) \
|
||||
__raw_writel((val), drvdata->base + (SZ_4K * id) + off)
|
||||
#define funnel_readl(drvdata, id, off) \
|
||||
__raw_readl(drvdata->base + (SZ_4K * id) + off)
|
||||
|
||||
#define FUNNEL_FUNCTL (0x000)
|
||||
#define FUNNEL_PRICTL (0x004)
|
||||
#define FUNNEL_ITATBDATA0 (0xEEC)
|
||||
#define FUNNEL_ITATBCTR2 (0xEF0)
|
||||
#define FUNNEL_ITATBCTR1 (0xEF4)
|
||||
#define FUNNEL_ITATBCTR0 (0xEF8)
|
||||
#define funnel_writel(drvdata, val, off) \
|
||||
__raw_writel((val), drvdata->base + off)
|
||||
#define funnel_readl(drvdata, off) \
|
||||
__raw_readl(drvdata->base + off)
|
||||
|
||||
|
||||
#define FUNNEL_LOCK(id) \
|
||||
#define FUNNEL_LOCK(drvdata) \
|
||||
do { \
|
||||
mb(); \
|
||||
funnel_writel(drvdata, id, 0x0, CORESIGHT_LAR); \
|
||||
funnel_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define FUNNEL_UNLOCK(id) \
|
||||
#define FUNNEL_UNLOCK(drvdata) \
|
||||
do { \
|
||||
funnel_writel(drvdata, id, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
funnel_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
#define FUNNEL_HOLDTIME_MASK (0xF00)
|
||||
#define FUNNEL_HOLDTIME_SHFT (0x8)
|
||||
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
|
||||
|
||||
#define FUNNEL_FUNCTL (0x000)
|
||||
#define FUNNEL_PRICTL (0x004)
|
||||
#define FUNNEL_ITATBDATA0 (0xEEC)
|
||||
#define FUNNEL_ITATBCTR2 (0xEF0)
|
||||
#define FUNNEL_ITATBCTR1 (0xEF4)
|
||||
#define FUNNEL_ITATBCTR0 (0xEF8)
|
||||
|
||||
|
||||
#define FUNNEL_HOLDTIME_MASK (0xF00)
|
||||
#define FUNNEL_HOLDTIME_SHFT (0x8)
|
||||
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
|
||||
|
||||
|
||||
struct funnel_drvdata {
|
||||
void __iomem *base;
|
||||
bool enabled;
|
||||
struct mutex mutex;
|
||||
struct device *dev;
|
||||
struct kobject *kobj;
|
||||
struct clk *clk;
|
||||
uint32_t priority;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct clk *clk;
|
||||
uint32_t priority;
|
||||
};
|
||||
|
||||
static struct funnel_drvdata *drvdata;
|
||||
|
||||
static void __funnel_enable(uint8_t id, uint32_t port_mask)
|
||||
static void __funnel_enable(struct funnel_drvdata *drvdata, int port)
|
||||
{
|
||||
uint32_t functl;
|
||||
|
||||
FUNNEL_UNLOCK(id);
|
||||
FUNNEL_UNLOCK(drvdata);
|
||||
|
||||
functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
|
||||
functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
|
||||
functl &= ~FUNNEL_HOLDTIME_MASK;
|
||||
functl |= FUNNEL_HOLDTIME;
|
||||
functl |= port_mask;
|
||||
funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
|
||||
funnel_writel(drvdata, id, drvdata->priority, FUNNEL_PRICTL);
|
||||
functl |= (1 << port);
|
||||
funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
|
||||
funnel_writel(drvdata, drvdata->priority, FUNNEL_PRICTL);
|
||||
|
||||
FUNNEL_LOCK(id);
|
||||
FUNNEL_LOCK(drvdata);
|
||||
}
|
||||
|
||||
int funnel_enable(uint8_t id, uint32_t port_mask)
|
||||
static int funnel_enable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&drvdata->mutex);
|
||||
__funnel_enable(id, port_mask);
|
||||
drvdata->enabled = true;
|
||||
dev_info(drvdata->dev, "FUNNEL port mask 0x%lx enabled\n",
|
||||
(unsigned long) port_mask);
|
||||
mutex_unlock(&drvdata->mutex);
|
||||
__funnel_enable(drvdata, inport);
|
||||
|
||||
dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __funnel_disable(uint8_t id, uint32_t port_mask)
|
||||
static void __funnel_disable(struct funnel_drvdata *drvdata, int inport)
|
||||
{
|
||||
uint32_t functl;
|
||||
|
||||
FUNNEL_UNLOCK(id);
|
||||
FUNNEL_UNLOCK(drvdata);
|
||||
|
||||
functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
|
||||
functl &= ~port_mask;
|
||||
funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
|
||||
functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
|
||||
functl &= ~(1 << inport);
|
||||
funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
|
||||
|
||||
FUNNEL_LOCK(id);
|
||||
FUNNEL_LOCK(drvdata);
|
||||
}
|
||||
|
||||
void funnel_disable(uint8_t id, uint32_t port_mask)
|
||||
static void funnel_disable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
mutex_lock(&drvdata->mutex);
|
||||
__funnel_disable(id, port_mask);
|
||||
drvdata->enabled = false;
|
||||
dev_info(drvdata->dev, "FUNNEL port mask 0x%lx disabled\n",
|
||||
(unsigned long) port_mask);
|
||||
mutex_unlock(&drvdata->mutex);
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
__funnel_disable(drvdata, inport);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
|
||||
}
|
||||
|
||||
static const struct coresight_ops_link funnel_link_ops = {
|
||||
.enable = funnel_enable,
|
||||
.disable = funnel_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops funnel_cs_ops = {
|
||||
.link_ops = &funnel_link_ops,
|
||||
};
|
||||
|
||||
static ssize_t funnel_show_priority(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val = drvdata->priority;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
}
|
||||
|
||||
|
@ -134,6 +143,7 @@ static ssize_t funnel_store_priority(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (sscanf(buf, "%lx", &val) != 1)
|
||||
|
@ -145,63 +155,44 @@ static ssize_t funnel_store_priority(struct device *dev,
|
|||
static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, funnel_show_priority,
|
||||
funnel_store_priority);
|
||||
|
||||
static int __devinit funnel_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
static struct attribute *funnel_attrs[] = {
|
||||
&dev_attr_priority.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
drvdata->kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
|
||||
if (!drvdata->kobj) {
|
||||
dev_err(drvdata->dev, "failed to create FUNNEL sysfs kobject\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_create;
|
||||
}
|
||||
static struct attribute_group funnel_attr_grp = {
|
||||
.attrs = funnel_attrs,
|
||||
};
|
||||
|
||||
ret = sysfs_create_file(drvdata->kobj, &dev_attr_priority.attr);
|
||||
if (ret) {
|
||||
dev_err(drvdata->dev, "failed to create FUNNEL sysfs priority"
|
||||
" attribute\n");
|
||||
goto err_file;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_file:
|
||||
kobject_put(drvdata->kobj);
|
||||
err_create:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit funnel_sysfs_exit(void)
|
||||
{
|
||||
sysfs_remove_file(drvdata->kobj, &dev_attr_priority.attr);
|
||||
kobject_put(drvdata->kobj);
|
||||
}
|
||||
static const struct attribute_group *funnel_attr_grps[] = {
|
||||
&funnel_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __devinit funnel_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct funnel_drvdata *drvdata;
|
||||
struct resource *res;
|
||||
struct coresight_desc *desc;
|
||||
|
||||
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_drvdata;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -EINVAL;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
drvdata->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!drvdata->base) {
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
drvdata->dev = &pdev->dev;
|
||||
|
||||
mutex_init(&drvdata->mutex);
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
drvdata->clk = clk_get(drvdata->dev, "core_clk");
|
||||
if (IS_ERR(drvdata->clk)) {
|
||||
|
@ -213,15 +204,33 @@ static int __devinit funnel_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_clk_rate;
|
||||
|
||||
funnel_sysfs_init();
|
||||
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_desc;
|
||||
}
|
||||
desc->type = CORESIGHT_DEV_TYPE_LINK;
|
||||
desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
|
||||
desc->ops = &funnel_cs_ops;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
desc->groups = funnel_attr_grps;
|
||||
desc->owner = THIS_MODULE;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto err_coresight_register;
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
dev_info(drvdata->dev, "FUNNEL initialized\n");
|
||||
return 0;
|
||||
|
||||
err_coresight_register:
|
||||
kfree(desc);
|
||||
err_kzalloc_desc:
|
||||
err_clk_rate:
|
||||
clk_put(drvdata->clk);
|
||||
err_clk_get:
|
||||
mutex_destroy(&drvdata->mutex);
|
||||
iounmap(drvdata->base);
|
||||
err_ioremap:
|
||||
err_res:
|
||||
|
@ -233,19 +242,17 @@ err_kzalloc_drvdata:
|
|||
|
||||
static int __devexit funnel_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (drvdata->enabled)
|
||||
funnel_disable(0x0, 0xFF);
|
||||
funnel_sysfs_exit();
|
||||
struct funnel_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
clk_put(drvdata->clk);
|
||||
mutex_destroy(&drvdata->mutex);
|
||||
iounmap(drvdata->base);
|
||||
kfree(drvdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id funnel_match[] = {
|
||||
{.compatible = "qcom,msm-funnel"},
|
||||
{.compatible = "coresight-funnel"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -253,7 +260,7 @@ static struct platform_driver funnel_driver = {
|
|||
.probe = funnel_probe,
|
||||
.remove = __devexit_p(funnel_remove),
|
||||
.driver = {
|
||||
.name = "msm_funnel",
|
||||
.name = "coresight-funnel",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = funnel_match,
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/bitops.h>
|
||||
|
||||
|
||||
/* Coresight management registers (0xF00-0xFCC)
|
||||
* 0xFA0 - 0xFA4: Management registers in PFTv1.0
|
||||
* Trace registers in PFTv1.1
|
||||
|
@ -28,6 +29,7 @@
|
|||
#define CORESIGHT_DEVID (0xFC8)
|
||||
#define CORESIGHT_DEVTYPE (0xFCC)
|
||||
|
||||
|
||||
#define CORESIGHT_UNLOCK (0xC5ACCE55)
|
||||
|
||||
#define TIMEOUT_US (100)
|
||||
|
@ -36,13 +38,4 @@
|
|||
#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
|
||||
#define BVAL(val, n) ((val & BIT(n)) >> n)
|
||||
|
||||
int etb_enable(void);
|
||||
void etb_disable(void);
|
||||
void etb_dump(void);
|
||||
void tpiu_disable(void);
|
||||
int funnel_enable(uint8_t id, uint32_t port_mask);
|
||||
void funnel_disable(uint8_t id, uint32_t port_mask);
|
||||
|
||||
struct kobject *qdss_get_modulekobj(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/miscdevice.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/coresight-stm.h>
|
||||
|
@ -29,15 +30,36 @@
|
|||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define stm_writel(drvdata, val, off) \
|
||||
__raw_writel((val), drvdata->base + off)
|
||||
#define stm_readl(drvdata, val, off) \
|
||||
__raw_readl(drvdata->base + off)
|
||||
|
||||
#define stm_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
|
||||
#define stm_readl(drvdata, off) __raw_readl(drvdata->base + off)
|
||||
|
||||
#define STM_LOCK(drvdata) \
|
||||
do { \
|
||||
mb(); \
|
||||
stm_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define STM_UNLOCK(drvdata) \
|
||||
do { \
|
||||
stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define STMSPER (0xE00)
|
||||
#define STMSPTER (0xE20)
|
||||
#define STMTCSR (0xE80)
|
||||
#define STMSYNCR (0xE90)
|
||||
|
||||
|
||||
#define NR_STM_CHANNEL (32)
|
||||
#define BYTES_PER_CHANNEL (256)
|
||||
#define STM_TRACE_BUF_SIZE (1024)
|
||||
|
||||
enum {
|
||||
#define OST_START_TOKEN (0x30)
|
||||
#define OST_VERSION (0x1)
|
||||
|
||||
enum stm_pkt_type {
|
||||
STM_PKT_TYPE_DATA = 0x98,
|
||||
STM_PKT_TYPE_FLAG = 0xE8,
|
||||
STM_PKT_TYPE_TRIG = 0xF8,
|
||||
|
@ -47,45 +69,25 @@ enum {
|
|||
STM_OPTION_MARKED = 0x10,
|
||||
};
|
||||
|
||||
#define STM_TRACE_BUF_SIZE (1024)
|
||||
|
||||
#define OST_START_TOKEN (0x30)
|
||||
#define OST_VERSION (0x1)
|
||||
|
||||
#define stm_channel_addr(ch) \
|
||||
(drvdata->chs.base + (ch * BYTES_PER_CHANNEL))
|
||||
#define stm_channel_addr(drvdata, ch) (drvdata->chs.base + \
|
||||
(ch * BYTES_PER_CHANNEL))
|
||||
#define stm_channel_off(type, opts) (type & ~opts)
|
||||
|
||||
#define STM_LOCK() \
|
||||
do { \
|
||||
mb(); \
|
||||
stm_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define STM_UNLOCK() \
|
||||
do { \
|
||||
stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
#define STMSPER (0xE00)
|
||||
#define STMSPTER (0xE20)
|
||||
#define STMTCSR (0xE80)
|
||||
#define STMSYNCR (0xE90)
|
||||
|
||||
#ifdef CONFIG_MSM_QDSS_STM_DEFAULT_ENABLE
|
||||
static int stm_boot_enable = 1;
|
||||
static int boot_enable = 1;
|
||||
#else
|
||||
static int stm_boot_enable;
|
||||
static int boot_enable;
|
||||
#endif
|
||||
|
||||
module_param_named(
|
||||
stm_boot_enable, stm_boot_enable, int, S_IRUGO
|
||||
boot_enable, boot_enable, int, S_IRUGO
|
||||
);
|
||||
|
||||
static int stm_boot_nr_channel;
|
||||
static int boot_nr_channel;
|
||||
|
||||
module_param_named(
|
||||
stm_boot_nr_channel, stm_boot_nr_channel, int, S_IRUGO
|
||||
boot_nr_channel, boot_nr_channel, int, S_IRUGO
|
||||
);
|
||||
|
||||
struct channel_space {
|
||||
|
@ -95,99 +97,83 @@ struct channel_space {
|
|||
|
||||
struct stm_drvdata {
|
||||
void __iomem *base;
|
||||
bool enabled;
|
||||
struct qdss_source *src;
|
||||
struct device *dev;
|
||||
struct kobject *kobj;
|
||||
struct coresight_device *csdev;
|
||||
struct miscdevice miscdev;
|
||||
struct clk *clk;
|
||||
uint32_t entity;
|
||||
struct channel_space chs;
|
||||
bool enable;
|
||||
uint32_t entity;
|
||||
};
|
||||
|
||||
static struct stm_drvdata *drvdata;
|
||||
static struct stm_drvdata *stmdrvdata;
|
||||
|
||||
static void __stm_enable(void)
|
||||
|
||||
static void __stm_enable(struct stm_drvdata *drvdata)
|
||||
{
|
||||
STM_UNLOCK();
|
||||
STM_UNLOCK(drvdata);
|
||||
|
||||
stm_writel(drvdata, 0x80, STMSYNCR);
|
||||
stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
|
||||
stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
|
||||
stm_writel(drvdata, 0x30003, STMTCSR);
|
||||
|
||||
STM_LOCK();
|
||||
STM_LOCK(drvdata);
|
||||
}
|
||||
|
||||
static int stm_enable(void)
|
||||
static int stm_enable(struct coresight_device *csdev)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
if (drvdata->enabled) {
|
||||
dev_err(drvdata->dev, "STM tracing already enabled\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
return ret;
|
||||
|
||||
ret = qdss_enable(drvdata->src);
|
||||
if (ret)
|
||||
goto err_qdss;
|
||||
|
||||
__stm_enable();
|
||||
|
||||
drvdata->enabled = true;
|
||||
__stm_enable(drvdata);
|
||||
drvdata->enable = true;
|
||||
|
||||
dev_info(drvdata->dev, "STM tracing enabled\n");
|
||||
return 0;
|
||||
|
||||
err_qdss:
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
err_clk:
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __stm_disable(void)
|
||||
static void __stm_disable(struct stm_drvdata *drvdata)
|
||||
{
|
||||
STM_UNLOCK();
|
||||
STM_UNLOCK(drvdata);
|
||||
|
||||
stm_writel(drvdata, 0x30000, STMTCSR);
|
||||
stm_writel(drvdata, 0x0, STMSPER);
|
||||
stm_writel(drvdata, 0x0, STMSPTER);
|
||||
|
||||
STM_LOCK();
|
||||
STM_LOCK(drvdata);
|
||||
}
|
||||
|
||||
static int stm_disable(void)
|
||||
static void stm_disable(struct coresight_device *csdev)
|
||||
{
|
||||
int ret;
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
if (!drvdata->enabled) {
|
||||
dev_err(drvdata->dev, "STM tracing already disabled\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
__stm_disable();
|
||||
|
||||
drvdata->enabled = false;
|
||||
|
||||
qdss_disable(drvdata->src);
|
||||
__stm_disable(drvdata);
|
||||
drvdata->enable = false;
|
||||
/* Wait for 100ms so that pending data has been written to HW */
|
||||
msleep(100);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "STM tracing disabled\n");
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct coresight_ops_source stm_source_ops = {
|
||||
.enable = stm_enable,
|
||||
.disable = stm_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops stm_cs_ops = {
|
||||
.source_ops = &stm_source_ops,
|
||||
};
|
||||
|
||||
static uint32_t stm_channel_alloc(uint32_t off)
|
||||
{
|
||||
struct stm_drvdata *drvdata = stmdrvdata;
|
||||
uint32_t ch;
|
||||
|
||||
do {
|
||||
|
@ -201,6 +187,8 @@ static uint32_t stm_channel_alloc(uint32_t off)
|
|||
|
||||
static void stm_channel_free(uint32_t ch)
|
||||
{
|
||||
struct stm_drvdata *drvdata = stmdrvdata;
|
||||
|
||||
clear_bit(ch, drvdata->chs.bitmap);
|
||||
}
|
||||
|
||||
|
@ -301,13 +289,14 @@ static int stm_trace_ost_tail(unsigned long ch_addr, uint32_t options)
|
|||
static inline int __stm_trace(uint32_t options, uint8_t entity_id,
|
||||
uint8_t proto_id, const void *data, uint32_t size)
|
||||
{
|
||||
struct stm_drvdata *drvdata = stmdrvdata;
|
||||
int len = 0;
|
||||
uint32_t ch;
|
||||
unsigned long ch_addr;
|
||||
|
||||
/* allocate channel and get the channel address */
|
||||
ch = stm_channel_alloc(0);
|
||||
ch_addr = (unsigned long)stm_channel_addr(ch);
|
||||
ch_addr = (unsigned long)stm_channel_addr(drvdata, ch);
|
||||
|
||||
/* send the ost header */
|
||||
len += stm_trace_ost_header(ch_addr, options, entity_id, proto_id, data,
|
||||
|
@ -344,21 +333,25 @@ static inline int __stm_trace(uint32_t options, uint8_t entity_id,
|
|||
int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
|
||||
const void *data, uint32_t size)
|
||||
{
|
||||
struct stm_drvdata *drvdata = stmdrvdata;
|
||||
|
||||
/* we don't support sizes more than 24bits (0 to 23) */
|
||||
if (!(drvdata->enabled && (drvdata->entity & entity_id) &&
|
||||
if (!(drvdata && drvdata->enable && (drvdata->entity & entity_id) &&
|
||||
(size < 0x1000000)))
|
||||
return 0;
|
||||
|
||||
return __stm_trace(options, entity_id, proto_id, data, size);
|
||||
}
|
||||
EXPORT_SYMBOL(stm_trace);
|
||||
EXPORT_SYMBOL_GPL(stm_trace);
|
||||
|
||||
static ssize_t stm_write(struct file *file, const char __user *data,
|
||||
size_t size, loff_t *ppos)
|
||||
{
|
||||
struct stm_drvdata *drvdata = container_of(file->private_data,
|
||||
struct stm_drvdata, miscdev);
|
||||
char *buf;
|
||||
|
||||
if (!drvdata->enabled)
|
||||
if (!drvdata->enable)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
|
||||
|
@ -386,49 +379,17 @@ static ssize_t stm_write(struct file *file, const char __user *data,
|
|||
|
||||
static const struct file_operations stm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = nonseekable_open,
|
||||
.write = stm_write,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static struct miscdevice stm_misc = {
|
||||
.name = "msm_stm",
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.fops = &stm_fops,
|
||||
};
|
||||
|
||||
static ssize_t stm_show_enabled(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
unsigned long val = drvdata->enabled;
|
||||
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
}
|
||||
|
||||
static ssize_t stm_store_enabled(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val;
|
||||
|
||||
if (sscanf(buf, "%lx", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (val)
|
||||
ret = stm_enable();
|
||||
else
|
||||
ret = stm_disable();
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, stm_show_enabled,
|
||||
stm_store_enabled);
|
||||
|
||||
static ssize_t stm_show_entity(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val = drvdata->entity;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
}
|
||||
|
||||
|
@ -436,6 +397,7 @@ static ssize_t stm_store_entity(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val;
|
||||
|
||||
if (sscanf(buf, "%lx", &val) != 1)
|
||||
|
@ -447,103 +409,72 @@ static ssize_t stm_store_entity(struct device *dev,
|
|||
static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
|
||||
stm_store_entity);
|
||||
|
||||
static int __devinit stm_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
static struct attribute *stm_attrs[] = {
|
||||
&dev_attr_entity.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
drvdata->kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
|
||||
if (!drvdata->kobj) {
|
||||
dev_err(drvdata->dev, "failed to create STM sysfs kobject\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_create;
|
||||
}
|
||||
static struct attribute_group stm_attr_grp = {
|
||||
.attrs = stm_attrs,
|
||||
};
|
||||
|
||||
ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
|
||||
if (ret) {
|
||||
dev_err(drvdata->dev, "failed to create STM sysfs enabled attr\n");
|
||||
goto err_file;
|
||||
}
|
||||
|
||||
if (sysfs_create_file(drvdata->kobj, &dev_attr_entity.attr))
|
||||
dev_err(drvdata->dev, "failed to create STM sysfs entity attr\n");
|
||||
|
||||
return 0;
|
||||
err_file:
|
||||
kobject_put(drvdata->kobj);
|
||||
err_create:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit stm_sysfs_exit(void)
|
||||
{
|
||||
sysfs_remove_file(drvdata->kobj, &dev_attr_entity.attr);
|
||||
sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
|
||||
kobject_put(drvdata->kobj);
|
||||
}
|
||||
static const struct attribute_group *stm_attr_grps[] = {
|
||||
&stm_attr_grp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __devinit stm_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct stm_drvdata *drvdata;
|
||||
struct resource *res;
|
||||
size_t res_size, bitmap_size;
|
||||
struct coresight_desc *desc;
|
||||
|
||||
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_drvdata;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -EINVAL;
|
||||
goto err_res0;
|
||||
}
|
||||
|
||||
drvdata->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!drvdata->base) {
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap0;
|
||||
}
|
||||
drvdata->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!res) {
|
||||
ret = -EINVAL;
|
||||
goto err_res1;
|
||||
}
|
||||
|
||||
if (stm_boot_nr_channel) {
|
||||
res_size = min((resource_size_t)(stm_boot_nr_channel *
|
||||
if (boot_nr_channel) {
|
||||
res_size = min((resource_size_t)(boot_nr_channel *
|
||||
BYTES_PER_CHANNEL), resource_size(res));
|
||||
bitmap_size = stm_boot_nr_channel * sizeof(long);
|
||||
bitmap_size = boot_nr_channel * sizeof(long);
|
||||
} else {
|
||||
res_size = min((resource_size_t)(NR_STM_CHANNEL *
|
||||
BYTES_PER_CHANNEL), resource_size(res));
|
||||
bitmap_size = NR_STM_CHANNEL * sizeof(long);
|
||||
}
|
||||
|
||||
drvdata->chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
|
||||
if (!drvdata->chs.bitmap) {
|
||||
ret = -ENOMEM;
|
||||
goto err_bitmap;
|
||||
goto err_kzalloc_bitmap;
|
||||
}
|
||||
|
||||
drvdata->chs.base = ioremap_nocache(res->start, res_size);
|
||||
if (!drvdata->chs.base) {
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap1;
|
||||
}
|
||||
|
||||
drvdata->dev = &pdev->dev;
|
||||
|
||||
ret = misc_register(&stm_misc);
|
||||
if (ret)
|
||||
goto err_misc;
|
||||
|
||||
drvdata->src = qdss_get("msm_stm");
|
||||
if (IS_ERR(drvdata->src)) {
|
||||
ret = PTR_ERR(drvdata->src);
|
||||
goto err_qdssget;
|
||||
}
|
||||
/* Store the driver data pointer for use in exported functions */
|
||||
stmdrvdata = drvdata;
|
||||
|
||||
drvdata->clk = clk_get(drvdata->dev, "core_clk");
|
||||
if (IS_ERR(drvdata->clk)) {
|
||||
|
@ -555,59 +486,79 @@ static int __devinit stm_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_clk_rate;
|
||||
|
||||
drvdata->miscdev.name = ((struct coresight_platform_data *)
|
||||
(pdev->dev.platform_data))->name;
|
||||
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
drvdata->miscdev.fops = &stm_fops;
|
||||
ret = misc_register(&drvdata->miscdev);
|
||||
if (ret)
|
||||
goto err_misc_register;
|
||||
|
||||
drvdata->entity = OST_ENTITY_ALL;
|
||||
|
||||
ret = stm_sysfs_init();
|
||||
if (ret)
|
||||
goto err_sysfs;
|
||||
|
||||
if (stm_boot_enable)
|
||||
stm_enable();
|
||||
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_desc;
|
||||
}
|
||||
desc->type = CORESIGHT_DEV_TYPE_SOURCE;
|
||||
desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
|
||||
desc->ops = &stm_cs_ops;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
desc->groups = stm_attr_grps;
|
||||
desc->owner = THIS_MODULE;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto err_coresight_register;
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
dev_info(drvdata->dev, "STM initialized\n");
|
||||
return 0;
|
||||
|
||||
err_sysfs:
|
||||
if (boot_enable)
|
||||
coresight_enable(drvdata->csdev);
|
||||
|
||||
return 0;
|
||||
err_coresight_register:
|
||||
kfree(desc);
|
||||
err_kzalloc_desc:
|
||||
misc_deregister(&drvdata->miscdev);
|
||||
err_misc_register:
|
||||
err_clk_rate:
|
||||
clk_put(drvdata->clk);
|
||||
err_clk_get:
|
||||
qdss_put(drvdata->src);
|
||||
err_qdssget:
|
||||
misc_deregister(&stm_misc);
|
||||
err_misc:
|
||||
iounmap(drvdata->chs.base);
|
||||
err_ioremap1:
|
||||
kfree(drvdata->chs.bitmap);
|
||||
err_bitmap:
|
||||
err_kzalloc_bitmap:
|
||||
err_res1:
|
||||
iounmap(drvdata->base);
|
||||
err_ioremap0:
|
||||
err_res0:
|
||||
kfree(drvdata);
|
||||
err_kzalloc_drvdata:
|
||||
|
||||
dev_err(drvdata->dev, "STM init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit stm_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (drvdata->enabled)
|
||||
stm_disable();
|
||||
stm_sysfs_exit();
|
||||
struct stm_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
misc_deregister(&drvdata->miscdev);
|
||||
clk_put(drvdata->clk);
|
||||
qdss_put(drvdata->src);
|
||||
misc_deregister(&stm_misc);
|
||||
iounmap(drvdata->chs.base);
|
||||
kfree(drvdata->chs.bitmap);
|
||||
iounmap(drvdata->base);
|
||||
kfree(drvdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id stm_match[] = {
|
||||
{.compatible = "qcom,msm-stm"},
|
||||
{.compatible = "coresight-stm"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -615,7 +566,7 @@ static struct platform_driver stm_driver = {
|
|||
.probe = stm_probe,
|
||||
.remove = __devexit_p(stm_remove),
|
||||
.driver = {
|
||||
.name = "msm_stm",
|
||||
.name = "coresight-stm",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = stm_match,
|
||||
},
|
||||
|
|
|
@ -23,91 +23,129 @@
|
|||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
|
||||
#define tpiu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
|
||||
#define tpiu_readl(drvdata, off) __raw_readl(drvdata->base + off)
|
||||
|
||||
#define TPIU_SUPP_PORTSZ (0x000)
|
||||
#define TPIU_CURR_PORTSZ (0x004)
|
||||
#define TPIU_SUPP_TRIGMODES (0x100)
|
||||
#define TPIU_TRIG_CNTRVAL (0x104)
|
||||
#define TPIU_TRIG_MULT (0x108)
|
||||
#define TPIU_SUPP_TESTPATM (0x200)
|
||||
#define TPIU_CURR_TESTPATM (0x204)
|
||||
#define TPIU_TEST_PATREPCNTR (0x208)
|
||||
#define TPIU_FFSR (0x300)
|
||||
#define TPIU_FFCR (0x304)
|
||||
#define TPIU_FSYNC_CNTR (0x308)
|
||||
#define TPIU_EXTCTL_INPORT (0x400)
|
||||
#define TPIU_EXTCTL_OUTPORT (0x404)
|
||||
#define TPIU_ITTRFLINACK (0xEE4)
|
||||
#define TPIU_ITTRFLIN (0xEE8)
|
||||
#define TPIU_ITATBDATA0 (0xEEC)
|
||||
#define TPIU_ITATBCTR2 (0xEF0)
|
||||
#define TPIU_ITATBCTR1 (0xEF4)
|
||||
#define TPIU_ITATBCTR0 (0xEF8)
|
||||
|
||||
|
||||
#define TPIU_LOCK() \
|
||||
#define TPIU_LOCK(drvdata) \
|
||||
do { \
|
||||
mb(); \
|
||||
tpiu_writel(drvdata, 0x0, CORESIGHT_LAR); \
|
||||
} while (0)
|
||||
#define TPIU_UNLOCK() \
|
||||
#define TPIU_UNLOCK(drvdata) \
|
||||
do { \
|
||||
tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
|
||||
mb(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define TPIU_SUPP_PORTSZ (0x000)
|
||||
#define TPIU_CURR_PORTSZ (0x004)
|
||||
#define TPIU_SUPP_TRIGMODES (0x100)
|
||||
#define TPIU_TRIG_CNTRVAL (0x104)
|
||||
#define TPIU_TRIG_MULT (0x108)
|
||||
#define TPIU_SUPP_TESTPATM (0x200)
|
||||
#define TPIU_CURR_TESTPATM (0x204)
|
||||
#define TPIU_TEST_PATREPCNTR (0x208)
|
||||
#define TPIU_FFSR (0x300)
|
||||
#define TPIU_FFCR (0x304)
|
||||
#define TPIU_FSYNC_CNTR (0x308)
|
||||
#define TPIU_EXTCTL_INPORT (0x400)
|
||||
#define TPIU_EXTCTL_OUTPORT (0x404)
|
||||
#define TPIU_ITTRFLINACK (0xEE4)
|
||||
#define TPIU_ITTRFLIN (0xEE8)
|
||||
#define TPIU_ITATBDATA0 (0xEEC)
|
||||
#define TPIU_ITATBCTR2 (0xEF0)
|
||||
#define TPIU_ITATBCTR1 (0xEF4)
|
||||
#define TPIU_ITATBCTR0 (0xEF8)
|
||||
|
||||
|
||||
struct tpiu_drvdata {
|
||||
void __iomem *base;
|
||||
bool enabled;
|
||||
struct device *dev;
|
||||
struct clk *clk;
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static struct tpiu_drvdata *drvdata;
|
||||
|
||||
static void __tpiu_disable(void)
|
||||
static void __tpiu_enable(struct tpiu_drvdata *drvdata)
|
||||
{
|
||||
TPIU_UNLOCK();
|
||||
TPIU_UNLOCK(drvdata);
|
||||
|
||||
/* TODO: fill this up */
|
||||
|
||||
TPIU_LOCK(drvdata);
|
||||
}
|
||||
|
||||
static int tpiu_enable(struct coresight_device *csdev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
__tpiu_enable(drvdata);
|
||||
|
||||
dev_info(drvdata->dev, "TPIU enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __tpiu_disable(struct tpiu_drvdata *drvdata)
|
||||
{
|
||||
TPIU_UNLOCK(drvdata);
|
||||
|
||||
tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
|
||||
tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
|
||||
|
||||
TPIU_LOCK();
|
||||
TPIU_LOCK(drvdata);
|
||||
}
|
||||
|
||||
void tpiu_disable(void)
|
||||
static void tpiu_disable(struct coresight_device *csdev)
|
||||
{
|
||||
__tpiu_disable();
|
||||
drvdata->enabled = false;
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
__tpiu_disable(drvdata);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "TPIU disabled\n");
|
||||
}
|
||||
|
||||
static const struct coresight_ops_sink tpiu_sink_ops = {
|
||||
.enable = tpiu_enable,
|
||||
.disable = tpiu_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops tpiu_cs_ops = {
|
||||
.sink_ops = &tpiu_sink_ops,
|
||||
};
|
||||
|
||||
static int __devinit tpiu_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct tpiu_drvdata *drvdata;
|
||||
struct resource *res;
|
||||
struct coresight_desc *desc;
|
||||
|
||||
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_drvdata;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
ret = -EINVAL;
|
||||
goto err_res;
|
||||
}
|
||||
|
||||
drvdata->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!drvdata->base) {
|
||||
ret = -EINVAL;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
drvdata->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
drvdata->clk = clk_get(drvdata->dev, "core_clk");
|
||||
if (IS_ERR(drvdata->clk)) {
|
||||
|
@ -123,12 +161,32 @@ static int __devinit tpiu_probe(struct platform_device *pdev)
|
|||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
goto err_clk_enable;
|
||||
__tpiu_disable();
|
||||
__tpiu_disable(drvdata);
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_desc;
|
||||
}
|
||||
desc->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
|
||||
desc->ops = &tpiu_cs_ops;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
desc->owner = THIS_MODULE;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto err_coresight_register;
|
||||
}
|
||||
kfree(desc);
|
||||
|
||||
dev_info(drvdata->dev, "TPIU initialized\n");
|
||||
return 0;
|
||||
|
||||
err_coresight_register:
|
||||
kfree(desc);
|
||||
err_kzalloc_desc:
|
||||
err_clk_enable:
|
||||
err_clk_rate:
|
||||
clk_put(drvdata->clk);
|
||||
|
@ -144,17 +202,17 @@ err_kzalloc_drvdata:
|
|||
|
||||
static int __devexit tpiu_remove(struct platform_device *pdev)
|
||||
{
|
||||
if (drvdata->enabled)
|
||||
tpiu_disable();
|
||||
struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
clk_put(drvdata->clk);
|
||||
iounmap(drvdata->base);
|
||||
kfree(drvdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id tpiu_match[] = {
|
||||
{.compatible = "qcom,msm-tpiu"},
|
||||
{.compatible = "coresight-tpiu"},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -162,7 +220,7 @@ static struct platform_driver tpiu_driver = {
|
|||
.probe = tpiu_probe,
|
||||
.remove = __devexit_p(tpiu_remove),
|
||||
.driver = {
|
||||
.name = "msm_tpiu",
|
||||
.name = "coresight-tpiu",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tpiu_match,
|
||||
},
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
|
||||
#define NO_SINK (-1)
|
||||
#define MAX_STR_LEN (65535)
|
||||
|
||||
|
||||
static int curr_sink = NO_SINK;
|
||||
|
@ -343,7 +342,7 @@ out:
|
|||
up(&coresight_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_enable);
|
||||
EXPORT_SYMBOL_GPL(coresight_enable);
|
||||
|
||||
void coresight_disable(struct coresight_device *csdev)
|
||||
{
|
||||
|
@ -366,7 +365,7 @@ void coresight_disable(struct coresight_device *csdev)
|
|||
out:
|
||||
up(&coresight_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_disable);
|
||||
EXPORT_SYMBOL_GPL(coresight_disable);
|
||||
|
||||
static ssize_t coresight_show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -626,7 +625,7 @@ err_kzalloc_refcnts:
|
|||
err_kzalloc_csdev:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_register);
|
||||
EXPORT_SYMBOL_GPL(coresight_register);
|
||||
|
||||
void coresight_unregister(struct coresight_device *csdev)
|
||||
{
|
||||
|
@ -638,7 +637,7 @@ void coresight_unregister(struct coresight_device *csdev)
|
|||
put_device(&csdev->dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(coresight_unregister);
|
||||
EXPORT_SYMBOL_GPL(coresight_unregister);
|
||||
|
||||
static int __init coresight_init(void)
|
||||
{
|
||||
|
@ -653,300 +652,3 @@ static void __exit coresight_exit(void)
|
|||
module_exit(coresight_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
/*
|
||||
* Exclusion rules for structure fields.
|
||||
*
|
||||
* S: qdss.sources_mutex protected.
|
||||
* I: qdss.sink_mutex protected.
|
||||
* C: qdss.clk_mutex protected.
|
||||
*/
|
||||
struct qdss_ctx {
|
||||
struct kobject *modulekobj;
|
||||
uint8_t afamily;
|
||||
struct list_head sources; /* S: sources list */
|
||||
struct mutex sources_mutex;
|
||||
uint8_t sink_count; /* I: sink count */
|
||||
struct mutex sink_mutex;
|
||||
uint8_t max_clk;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static struct qdss_ctx qdss;
|
||||
|
||||
/**
|
||||
* qdss_get - get the qdss source handle
|
||||
* @name: name of the qdss source
|
||||
*
|
||||
* Searches the sources list to get the qdss source handle for this source.
|
||||
*
|
||||
* CONTEXT:
|
||||
* Typically called from init or probe functions
|
||||
*
|
||||
* RETURNS:
|
||||
* pointer to struct qdss_source on success, %NULL on failure
|
||||
*/
|
||||
struct qdss_source *qdss_get(const char *name)
|
||||
{
|
||||
struct qdss_source *src, *source = NULL;
|
||||
|
||||
mutex_lock(&qdss.sources_mutex);
|
||||
list_for_each_entry(src, &qdss.sources, link) {
|
||||
if (src->name) {
|
||||
if (strncmp(src->name, name, MAX_STR_LEN))
|
||||
continue;
|
||||
source = src;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&qdss.sources_mutex);
|
||||
|
||||
return source ? source : ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL(qdss_get);
|
||||
|
||||
/**
|
||||
* qdss_put - release the qdss source handle
|
||||
* @name: name of the qdss source
|
||||
*
|
||||
* CONTEXT:
|
||||
* Typically called from driver remove or exit functions
|
||||
*/
|
||||
void qdss_put(struct qdss_source *src)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(qdss_put);
|
||||
|
||||
/**
|
||||
* qdss_enable - enable qdss for the source
|
||||
* @src: handle for the source making the call
|
||||
*
|
||||
* Enables qdss block (relevant funnel ports and sink) if not already
|
||||
* enabled, otherwise increments the reference count
|
||||
*
|
||||
* CONTEXT:
|
||||
* Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, non-zero on failure
|
||||
*/
|
||||
int qdss_enable(struct qdss_source *src)
|
||||
{
|
||||
if (!src)
|
||||
return -EINVAL;
|
||||
|
||||
if (qdss.afamily) {
|
||||
mutex_lock(&qdss.sink_mutex);
|
||||
if (qdss.sink_count == 0) {
|
||||
tpiu_disable();
|
||||
/* enable ETB first to avoid losing any trace data */
|
||||
etb_enable();
|
||||
}
|
||||
qdss.sink_count++;
|
||||
mutex_unlock(&qdss.sink_mutex);
|
||||
}
|
||||
|
||||
funnel_enable(0x0, src->fport_mask);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qdss_enable);
|
||||
|
||||
/**
|
||||
* qdss_disable - disable qdss for the source
|
||||
* @src: handle for the source making the call
|
||||
*
|
||||
* Disables qdss block (relevant funnel ports and sink) if the reference count
|
||||
* is one, otherwise decrements the reference count
|
||||
*
|
||||
* CONTEXT:
|
||||
* Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
|
||||
*/
|
||||
void qdss_disable(struct qdss_source *src)
|
||||
{
|
||||
if (!src)
|
||||
return;
|
||||
|
||||
if (qdss.afamily) {
|
||||
mutex_lock(&qdss.sink_mutex);
|
||||
if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
|
||||
goto out;
|
||||
if (qdss.sink_count == 1) {
|
||||
etb_dump();
|
||||
etb_disable();
|
||||
}
|
||||
qdss.sink_count--;
|
||||
mutex_unlock(&qdss.sink_mutex);
|
||||
}
|
||||
|
||||
funnel_disable(0x0, src->fport_mask);
|
||||
return;
|
||||
out:
|
||||
mutex_unlock(&qdss.sink_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(qdss_disable);
|
||||
|
||||
/**
|
||||
* qdss_disable_sink - force disable the current qdss sink(s)
|
||||
*
|
||||
* Force disable the current qdss sink(s) to stop the sink from accepting any
|
||||
* trace generated subsequent to this call. This function should only be used
|
||||
* as a way to stop the sink from getting polluted with trace data that is
|
||||
* uninteresting after an event of interest has occured.
|
||||
*
|
||||
* CONTEXT:
|
||||
* Can be called from atomic or non-atomic context.
|
||||
*/
|
||||
void qdss_disable_sink(void)
|
||||
{
|
||||
if (qdss.afamily) {
|
||||
etb_dump();
|
||||
etb_disable();
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(qdss_disable_sink);
|
||||
|
||||
struct kobject *qdss_get_modulekobj(void)
|
||||
{
|
||||
return qdss.modulekobj;
|
||||
}
|
||||
|
||||
#define QDSS_ATTR(name) \
|
||||
static struct kobj_attribute name##_attr = \
|
||||
__ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
|
||||
|
||||
static ssize_t max_clk_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t n)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
if (sscanf(buf, "%lx", &val) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
qdss.max_clk = val;
|
||||
return n;
|
||||
}
|
||||
static ssize_t max_clk_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
unsigned long val = qdss.max_clk;
|
||||
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
|
||||
}
|
||||
QDSS_ATTR(max_clk);
|
||||
|
||||
static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
|
||||
{
|
||||
mutex_lock(&qdss.sources_mutex);
|
||||
while (num--) {
|
||||
list_add_tail(&srcs->link, &qdss.sources);
|
||||
srcs++;
|
||||
}
|
||||
mutex_unlock(&qdss.sources_mutex);
|
||||
}
|
||||
|
||||
static int __init qdss_sysfs_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
|
||||
if (!qdss.modulekobj) {
|
||||
pr_err("failed to find QDSS sysfs module kobject\n");
|
||||
ret = -ENOENT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
|
||||
if (ret) {
|
||||
pr_err("failed to create QDSS sysfs max_clk attribute\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __devexit qdss_sysfs_exit(void)
|
||||
{
|
||||
sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
|
||||
}
|
||||
|
||||
static int __devinit qdss_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct msm_qdss_platform_data *pdata;
|
||||
|
||||
mutex_init(&qdss.sources_mutex);
|
||||
mutex_init(&qdss.sink_mutex);
|
||||
|
||||
INIT_LIST_HEAD(&qdss.sources);
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata)
|
||||
goto err_pdata;
|
||||
|
||||
qdss.afamily = pdata->afamily;
|
||||
qdss_add_sources(pdata->src_table, pdata->size);
|
||||
|
||||
pr_info("QDSS arch initialized\n");
|
||||
return 0;
|
||||
err_pdata:
|
||||
mutex_destroy(&qdss.sink_mutex);
|
||||
mutex_destroy(&qdss.sources_mutex);
|
||||
pr_err("QDSS init failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit qdss_remove(struct platform_device *pdev)
|
||||
{
|
||||
qdss_sysfs_exit();
|
||||
mutex_destroy(&qdss.sink_mutex);
|
||||
mutex_destroy(&qdss.sources_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id qdss_match[] = {
|
||||
{.compatible = "qcom,msm-qdss"},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver qdss_driver = {
|
||||
.probe = qdss_probe,
|
||||
.remove = __devexit_p(qdss_remove),
|
||||
.driver = {
|
||||
.name = "msm_qdss",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = qdss_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init qdss_init(void)
|
||||
{
|
||||
return platform_driver_register(&qdss_driver);
|
||||
}
|
||||
arch_initcall(qdss_init);
|
||||
|
||||
static int __init qdss_module_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = qdss_sysfs_init();
|
||||
if (ret)
|
||||
goto err_sysfs;
|
||||
|
||||
pr_info("QDSS module initialized\n");
|
||||
return 0;
|
||||
err_sysfs:
|
||||
return ret;
|
||||
}
|
||||
module_init(qdss_module_init);
|
||||
|
||||
static void __exit qdss_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&qdss_driver);
|
||||
}
|
||||
module_exit(qdss_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/device.h>
|
||||
|
||||
|
||||
/* Peripheral id registers (0xFD0-0xFEC) */
|
||||
#define CORESIGHT_PERIPHIDR4 (0xFD0)
|
||||
#define CORESIGHT_PERIPHIDR5 (0xFD4)
|
||||
|
@ -30,6 +31,7 @@
|
|||
#define CORESIGHT_COMPIDR2 (0xFF8)
|
||||
#define CORESIGHT_COMPIDR3 (0xFFC)
|
||||
|
||||
|
||||
/* DBGv7 with baseline CP14 registers implemented */
|
||||
#define ARM_DEBUG_ARCH_V7B (0x3)
|
||||
/* DBGv7 with all CP14 registers implemented */
|
||||
|
@ -150,36 +152,13 @@ struct coresight_ops {
|
|||
const struct coresight_ops_source *source_ops;
|
||||
};
|
||||
|
||||
struct qdss_source {
|
||||
struct list_head link;
|
||||
const char *name;
|
||||
uint32_t fport_mask;
|
||||
};
|
||||
|
||||
struct msm_qdss_platform_data {
|
||||
struct qdss_source *src_table;
|
||||
size_t size;
|
||||
uint8_t afamily;
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_MSM_QDSS
|
||||
extern struct qdss_source *qdss_get(const char *name);
|
||||
extern void qdss_put(struct qdss_source *src);
|
||||
extern int qdss_enable(struct qdss_source *src);
|
||||
extern void qdss_disable(struct qdss_source *src);
|
||||
extern void qdss_disable_sink(void);
|
||||
extern struct coresight_device *
|
||||
coresight_register(struct coresight_desc *desc);
|
||||
extern void coresight_unregister(struct coresight_device *csdev);
|
||||
extern int coresight_enable(struct coresight_device *csdev);
|
||||
extern void coresight_disable(struct coresight_device *csdev);
|
||||
#else
|
||||
static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
|
||||
static inline void qdss_put(struct qdss_source *src) {}
|
||||
static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
|
||||
static inline void qdss_disable(struct qdss_source *src) {}
|
||||
static inline void qdss_disable_sink(void) {}
|
||||
static inline struct coresight_device *
|
||||
coresight_register(struct coresight_desc *desc) { return NULL; }
|
||||
static inline void coresight_unregister(struct coresight_device *csdev) {}
|
||||
|
|
Loading…
Reference in a new issue