33 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
44 */
55
6+ #include <linux/acpi.h>
67#include <linux/bitops.h>
78#include <linux/kernel.h>
89#include <linux/moduleparam.h>
3031#include <linux/platform_device.h>
3132#include <linux/pm_runtime.h>
3233#include <linux/property.h>
34+ #include <linux/clk/clk-conf.h>
3335
3436#include <asm/barrier.h>
3537#include <asm/sections.h>
@@ -66,7 +68,6 @@ static u64 etm4_get_access_type(struct etmv4_config *config);
6668static enum cpuhp_state hp_online ;
6769
6870struct etm4_init_arg {
69- unsigned int pid ;
7071 struct device * dev ;
7172 struct csdev_access * csa ;
7273};
@@ -370,9 +371,17 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
370371}
371372
372373static void etm4_check_arch_features (struct etmv4_drvdata * drvdata ,
373- unsigned int id )
374+ struct csdev_access * csa )
374375{
375- if (etm4_hisi_match_pid (id ))
376+ /*
377+ * TRCPIDR* registers are not required for ETMs with system
378+ * instructions. They must be identified by the MIDR+REVIDRs.
379+ * Skip the TRCPID checks for now.
380+ */
381+ if (!csa -> io_mem )
382+ return ;
383+
384+ if (etm4_hisi_match_pid (coresight_get_pid (csa )))
376385 set_bit (ETM4_IMPDEF_HISI_CORE_COMMIT , drvdata -> arch_features );
377386}
378387#else
@@ -385,7 +394,7 @@ static void etm4_disable_arch_specific(struct etmv4_drvdata *drvdata)
385394}
386395
387396static void etm4_check_arch_features (struct etmv4_drvdata * drvdata ,
388- unsigned int id )
397+ struct csdev_access * csa )
389398{
390399}
391400#endif /* CONFIG_ETM4X_IMPDEF_FEATURE */
@@ -1066,11 +1075,21 @@ static bool etm4_init_sysreg_access(struct etmv4_drvdata *drvdata,
10661075 return true;
10671076}
10681077
1078+ static bool is_devtype_cpu_trace (void __iomem * base )
1079+ {
1080+ u32 devtype = readl (base + TRCDEVTYPE );
1081+
1082+ return (devtype == CS_DEVTYPE_PE_TRACE );
1083+ }
1084+
10691085static bool etm4_init_iomem_access (struct etmv4_drvdata * drvdata ,
10701086 struct csdev_access * csa )
10711087{
10721088 u32 devarch = readl_relaxed (drvdata -> base + TRCDEVARCH );
10731089
1090+ if (!is_coresight_device (drvdata -> base ) || !is_devtype_cpu_trace (drvdata -> base ))
1091+ return false;
1092+
10741093 /*
10751094 * All ETMs must implement TRCDEVARCH to indicate that
10761095 * the component is an ETMv4. Even though TRCIDR1 also
@@ -1161,7 +1180,7 @@ static void etm4_init_arch_data(void *info)
11611180 etm4_os_unlock_csa (drvdata , csa );
11621181 etm4_cs_unlock (drvdata , csa );
11631182
1164- etm4_check_arch_features (drvdata , init_arg -> pid );
1183+ etm4_check_arch_features (drvdata , csa );
11651184
11661185 /* find all capabilities of the tracing unit */
11671186 etmidr0 = etm4x_relaxed_read32 (csa , TRCIDR0 );
@@ -2044,19 +2063,16 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
20442063 return 0 ;
20452064}
20462065
2047- static int etm4_probe (struct device * dev , void __iomem * base , u32 etm_pid )
2066+ static int etm4_probe (struct device * dev )
20482067{
2049- struct etmv4_drvdata * drvdata ;
2068+ struct etmv4_drvdata * drvdata = dev_get_drvdata ( dev ) ;
20502069 struct csdev_access access = { 0 };
20512070 struct etm4_init_arg init_arg = { 0 };
20522071 struct etm4_init_arg * delayed ;
20532072
2054- drvdata = devm_kzalloc (dev , sizeof (* drvdata ), GFP_KERNEL );
2055- if (!drvdata )
2073+ if (WARN_ON (!drvdata ))
20562074 return - ENOMEM ;
20572075
2058- dev_set_drvdata (dev , drvdata );
2059-
20602076 if (pm_save_enable == PARAM_PM_SAVE_FIRMWARE )
20612077 pm_save_enable = coresight_loses_context_with_cpu (dev ) ?
20622078 PARAM_PM_SAVE_SELF_HOSTED : PARAM_PM_SAVE_NEVER ;
@@ -2068,8 +2084,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
20682084 return - ENOMEM ;
20692085 }
20702086
2071- drvdata -> base = base ;
2072-
20732087 spin_lock_init (& drvdata -> spinlock );
20742088
20752089 drvdata -> cpu = coresight_get_cpu (dev );
@@ -2078,7 +2092,6 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
20782092
20792093 init_arg .dev = dev ;
20802094 init_arg .csa = & access ;
2081- init_arg .pid = etm_pid ;
20822095
20832096 /*
20842097 * Serialize against CPUHP callbacks to avoid race condition
@@ -2108,6 +2121,7 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
21082121
21092122static int etm4_probe_amba (struct amba_device * adev , const struct amba_id * id )
21102123{
2124+ struct etmv4_drvdata * drvdata ;
21112125 void __iomem * base ;
21122126 struct device * dev = & adev -> dev ;
21132127 struct resource * res = & adev -> res ;
@@ -2118,7 +2132,13 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
21182132 if (IS_ERR (base ))
21192133 return PTR_ERR (base );
21202134
2121- ret = etm4_probe (dev , base , id -> id );
2135+ drvdata = devm_kzalloc (dev , sizeof (* drvdata ), GFP_KERNEL );
2136+ if (!drvdata )
2137+ return - ENOMEM ;
2138+
2139+ drvdata -> base = base ;
2140+ dev_set_drvdata (dev , drvdata );
2141+ ret = etm4_probe (dev );
21222142 if (!ret )
21232143 pm_runtime_put (& adev -> dev );
21242144
@@ -2127,18 +2147,32 @@ static int etm4_probe_amba(struct amba_device *adev, const struct amba_id *id)
21272147
21282148static int etm4_probe_platform_dev (struct platform_device * pdev )
21292149{
2150+ struct resource * res = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
2151+ struct etmv4_drvdata * drvdata ;
21302152 int ret ;
21312153
2154+ drvdata = devm_kzalloc (& pdev -> dev , sizeof (* drvdata ), GFP_KERNEL );
2155+ if (!drvdata )
2156+ return - ENOMEM ;
2157+
2158+ drvdata -> pclk = coresight_get_enable_apb_pclk (& pdev -> dev );
2159+ if (IS_ERR (drvdata -> pclk ))
2160+ return - ENODEV ;
2161+
2162+ if (res ) {
2163+ drvdata -> base = devm_ioremap_resource (& pdev -> dev , res );
2164+ if (IS_ERR (drvdata -> base )) {
2165+ clk_put (drvdata -> pclk );
2166+ return PTR_ERR (drvdata -> base );
2167+ }
2168+ }
2169+
2170+ dev_set_drvdata (& pdev -> dev , drvdata );
21322171 pm_runtime_get_noresume (& pdev -> dev );
21332172 pm_runtime_set_active (& pdev -> dev );
21342173 pm_runtime_enable (& pdev -> dev );
21352174
2136- /*
2137- * System register based devices could match the
2138- * HW by reading appropriate registers on the HW
2139- * and thus we could skip the PID.
2140- */
2141- ret = etm4_probe (& pdev -> dev , NULL , 0 );
2175+ ret = etm4_probe (& pdev -> dev );
21422176
21432177 pm_runtime_put (& pdev -> dev );
21442178 return ret ;
@@ -2178,7 +2212,7 @@ static struct amba_cs_uci_id uci_id_etm4[] = {
21782212 /* ETMv4 UCI data */
21792213 .devarch = ETM_DEVARCH_ETMv4x_ARCH ,
21802214 .devarch_mask = ETM_DEVARCH_ID_MASK ,
2181- .devtype = 0x00000013 ,
2215+ .devtype = CS_DEVTYPE_PE_TRACE ,
21822216 }
21832217};
21842218
@@ -2234,6 +2268,10 @@ static int __exit etm4_remove_platform_dev(struct platform_device *pdev)
22342268 if (drvdata )
22352269 etm4_remove_dev (drvdata );
22362270 pm_runtime_disable (& pdev -> dev );
2271+
2272+ if (drvdata && !IS_ERR_OR_NULL (drvdata -> pclk ))
2273+ clk_put (drvdata -> pclk );
2274+
22372275 return 0 ;
22382276}
22392277
@@ -2278,19 +2316,55 @@ static struct amba_driver etm4x_amba_driver = {
22782316 .id_table = etm4_ids ,
22792317};
22802318
2319+ #ifdef CONFIG_PM
2320+ static int etm4_runtime_suspend (struct device * dev )
2321+ {
2322+ struct etmv4_drvdata * drvdata = dev_get_drvdata (dev );
2323+
2324+ if (drvdata -> pclk && !IS_ERR (drvdata -> pclk ))
2325+ clk_disable_unprepare (drvdata -> pclk );
2326+
2327+ return 0 ;
2328+ }
2329+
2330+ static int etm4_runtime_resume (struct device * dev )
2331+ {
2332+ struct etmv4_drvdata * drvdata = dev_get_drvdata (dev );
2333+
2334+ if (drvdata -> pclk && !IS_ERR (drvdata -> pclk ))
2335+ clk_prepare_enable (drvdata -> pclk );
2336+
2337+ return 0 ;
2338+ }
2339+ #endif
2340+
2341+ static const struct dev_pm_ops etm4_dev_pm_ops = {
2342+ SET_RUNTIME_PM_OPS (etm4_runtime_suspend , etm4_runtime_resume , NULL )
2343+ };
2344+
22812345static const struct of_device_id etm4_sysreg_match [] = {
22822346 { .compatible = "arm,coresight-etm4x-sysreg" },
22832347 { .compatible = "arm,embedded-trace-extension" },
22842348 {}
22852349};
22862350
2351+ #ifdef CONFIG_ACPI
2352+ static const struct acpi_device_id etm4x_acpi_ids [] = {
2353+ {"ARMHC500" , 0 }, /* ARM CoreSight ETM4x */
2354+ {}
2355+ };
2356+ MODULE_DEVICE_TABLE (acpi , etm4x_acpi_ids );
2357+ #endif
2358+
22872359static struct platform_driver etm4_platform_driver = {
22882360 .probe = etm4_probe_platform_dev ,
22892361 .remove = etm4_remove_platform_dev ,
22902362 .driver = {
22912363 .name = "coresight-etm4x" ,
22922364 .of_match_table = etm4_sysreg_match ,
2365+ .acpi_match_table = ACPI_PTR (etm4x_acpi_ids ),
22932366 .suppress_bind_attrs = true,
2367+ .pm = & etm4_dev_pm_ops ,
22942368 },
22952369};
22962370
0 commit comments