diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c index 481cd3d0b1a..fa912491f31 100644 --- a/arch/arm/mach-msm/clock-8960.c +++ b/arch/arm/mach-msm/clock-8960.c @@ -5069,8 +5069,12 @@ static struct clk_lookup msm_clocks_8064[] = { CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"), 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_clk", qdss_clk.c, "msm_qdss"), - CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "msm_qdss"), + 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("ebi1_clk", ebi1_clk.c, ""), CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""), @@ -5395,8 +5399,12 @@ static struct clk_lookup msm_clocks_8960[] = { CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"), 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_clk", qdss_clk.c, "msm_qdss"), - CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "msm_qdss"), + 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("ebi1_clk", ebi1_clk.c, NULL), CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL), @@ -5713,8 +5721,12 @@ static struct clk_lookup msm_clocks_8930[] = { CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"), 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_clk", qdss_clk.c, "msm_qdss"), - CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "msm_qdss"), + 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("ebi1_clk", ebi1_clk.c, NULL), CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL), diff --git a/drivers/cs/cs-etb.c b/drivers/cs/cs-etb.c index 84d8e727a0d..0739057d733 100644 --- a/drivers/cs/cs-etb.c +++ b/drivers/cs/cs-etb.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "cs-priv.h" @@ -74,6 +75,7 @@ struct etb_ctx { atomic_t in_use; struct device *dev; struct kobject *kobj; + struct clk *clk; uint32_t trigger_cntr; }; @@ -99,15 +101,22 @@ static void __etb_enable(void) ETB_LOCK(); } -void etb_enable(void) +int etb_enable(void) { + int ret; unsigned long flags; + ret = clk_prepare_enable(etb.clk); + if (ret) + return ret; + spin_lock_irqsave(&etb.spinlock, flags); __etb_enable(); etb.enabled = true; dev_info(etb.dev, "ETB enabled\n"); spin_unlock_irqrestore(&etb.spinlock, flags); + + return 0; } static void __etb_disable(void) @@ -147,6 +156,8 @@ void etb_disable(void) etb.enabled = false; dev_info(etb.dev, "ETB disabled\n"); spin_unlock_irqrestore(&etb.spinlock, flags); + + clk_disable_unprepare(etb.clk); } static void __etb_dump(void) @@ -352,6 +363,16 @@ static int __devinit etb_probe(struct platform_device *pdev) spin_lock_init(&etb.spinlock); + etb.clk = clk_get(etb.dev, "core_clk"); + if (IS_ERR(etb.clk)) { + ret = PTR_ERR(etb.clk); + goto err_clk_get; + } + + ret = clk_set_rate(etb.clk, CS_CLK_RATE_TRACE); + if (ret) + goto err_clk_rate; + ret = misc_register(&etb_misc); if (ret) goto err_misc; @@ -370,6 +391,9 @@ static int __devinit etb_probe(struct platform_device *pdev) err_alloc: misc_deregister(&etb_misc); err_misc: +err_clk_rate: + clk_put(etb.clk); +err_clk_get: iounmap(etb.base); err_ioremap: err_res: @@ -384,6 +408,7 @@ static int __devexit etb_remove(struct platform_device *pdev) etb_sysfs_exit(); kfree(etb.buf); misc_deregister(&etb_misc); + clk_put(etb.clk); iounmap(etb.base); return 0; diff --git a/drivers/cs/cs-etm.c b/drivers/cs/cs-etm.c index 724cc71838d..da7fe0c430c 100644 --- a/drivers/cs/cs-etm.c +++ b/drivers/cs/cs-etm.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -161,6 +162,7 @@ struct etm_ctx { struct mutex mutex; struct device *dev; struct kobject *kobj; + struct clk *clk; uint8_t arch; uint8_t nr_addr_cmp; uint8_t nr_cntr; @@ -351,6 +353,10 @@ static int etm_enable(void) */ pm_qos_update_request(&etm.qos_req, 0); + ret = clk_prepare_enable(etm.clk); + if (ret) + goto err_clk; + ret = qdss_enable(etm.src); if (ret) goto err_qdss; @@ -367,6 +373,8 @@ static int etm_enable(void) return 0; err_qdss: + clk_disable_unprepare(etm.clk); +err_clk: pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE); wake_unlock(&etm.wake_lock); err: @@ -409,9 +417,11 @@ static int etm_disable(void) for_each_online_cpu(cpu) __etm_disable(cpu); + etm.enabled = false; + qdss_disable(etm.src); - etm.enabled = false; + clk_disable_unprepare(etm.clk); pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE); wake_unlock(&etm.wake_lock); @@ -1253,9 +1263,19 @@ static int __devinit etm_probe(struct platform_device *pdev) goto err_qdssget; } - ret = qdss_clk_enable(); + etm.clk = clk_get(etm.dev, "core_clk"); + if (IS_ERR(etm.clk)) { + ret = PTR_ERR(etm.clk); + goto err_clk_get; + } + + ret = clk_set_rate(etm.clk, CS_CLK_RATE_TRACE); if (ret) - goto err_clk; + goto err_clk_rate; + + ret = clk_prepare_enable(etm.clk); + if (ret) + goto err_clk_enable; ret = etm_arch_init(); if (ret) @@ -1267,7 +1287,7 @@ static int __devinit etm_probe(struct platform_device *pdev) etm.enabled = false; - qdss_clk_disable(); + clk_disable_unprepare(etm.clk); dev_info(etm.dev, "ETM initialized\n"); @@ -1278,8 +1298,11 @@ static int __devinit etm_probe(struct platform_device *pdev) err_sysfs: err_arch: - qdss_clk_disable(); -err_clk: + clk_disable_unprepare(etm.clk); +err_clk_enable: +err_clk_rate: + clk_put(etm.clk); +err_clk_get: qdss_put(etm.src); err_qdssget: pm_qos_remove_request(&etm.qos_req); @@ -1297,6 +1320,7 @@ static int __devexit etm_remove(struct platform_device *pdev) if (etm.enabled) etm_disable(); etm_sysfs_exit(); + clk_put(etm.clk); qdss_put(etm.src); pm_qos_remove_request(&etm.qos_req); wake_lock_destroy(&etm.wake_lock); diff --git a/drivers/cs/cs-funnel.c b/drivers/cs/cs-funnel.c index 2ae8ac95509..94d18f3312c 100644 --- a/drivers/cs/cs-funnel.c +++ b/drivers/cs/cs-funnel.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "cs-priv.h" @@ -56,6 +57,7 @@ struct funnel_ctx { struct mutex mutex; struct device *dev; struct kobject *kobj; + struct clk *clk; uint32_t priority; }; @@ -77,14 +79,22 @@ static void __funnel_enable(uint8_t id, uint32_t port_mask) FUNNEL_LOCK(id); } -void funnel_enable(uint8_t id, uint32_t port_mask) +int funnel_enable(uint8_t id, uint32_t port_mask) { + int ret; + + ret = clk_prepare_enable(funnel.clk); + if (ret) + return ret; + mutex_lock(&funnel.mutex); __funnel_enable(id, port_mask); funnel.enabled = true; dev_info(funnel.dev, "FUNNEL port mask 0x%lx enabled\n", (unsigned long) port_mask); mutex_unlock(&funnel.mutex); + + return 0; } static void __funnel_disable(uint8_t id, uint32_t port_mask) @@ -108,6 +118,8 @@ void funnel_disable(uint8_t id, uint32_t port_mask) dev_info(funnel.dev, "FUNNEL port mask 0x%lx disabled\n", (unsigned long) port_mask); mutex_unlock(&funnel.mutex); + + clk_disable_unprepare(funnel.clk); } #define FUNNEL_ATTR(__name) \ @@ -187,11 +199,26 @@ static int __devinit funnel_probe(struct platform_device *pdev) mutex_init(&funnel.mutex); + funnel.clk = clk_get(funnel.dev, "core_clk"); + if (IS_ERR(funnel.clk)) { + ret = PTR_ERR(funnel.clk); + goto err_clk_get; + } + + ret = clk_set_rate(funnel.clk, CS_CLK_RATE_TRACE); + if (ret) + goto err_clk_rate; + funnel_sysfs_init(); dev_info(funnel.dev, "FUNNEL initialized\n"); return 0; +err_clk_rate: + clk_put(funnel.clk); +err_clk_get: + mutex_destroy(&funnel.mutex); + iounmap(funnel.base); err_ioremap: err_res: dev_err(funnel.dev, "FUNNEL init failed\n"); @@ -203,6 +230,7 @@ static int __devexit funnel_remove(struct platform_device *pdev) if (funnel.enabled) funnel_disable(0x0, 0xFF); funnel_sysfs_exit(); + clk_put(funnel.clk); mutex_destroy(&funnel.mutex); iounmap(funnel.base); diff --git a/drivers/cs/cs-priv.h b/drivers/cs/cs-priv.h index d89f461890d..a4028f5d1de 100644 --- a/drivers/cs/cs-priv.h +++ b/drivers/cs/cs-priv.h @@ -36,11 +36,11 @@ #define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb) #define BVAL(val, n) ((val & BIT(n)) >> n) -void etb_enable(void); +int etb_enable(void); void etb_disable(void); void etb_dump(void); void tpiu_disable(void); -void funnel_enable(uint8_t id, uint32_t port_mask); +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); diff --git a/drivers/cs/cs-stm.c b/drivers/cs/cs-stm.c index ddc22a3d5d6..9c296be8c03 100644 --- a/drivers/cs/cs-stm.c +++ b/drivers/cs/cs-stm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -98,6 +99,7 @@ struct stm_ctx { struct qdss_source *src; struct device *dev; struct kobject *kobj; + struct clk *clk; uint32_t entity; struct channel_space chs; }; @@ -129,9 +131,13 @@ static int stm_enable(void) goto err; } + ret = clk_prepare_enable(stm.clk); + if (ret) + goto err_clk; + ret = qdss_enable(stm.src); if (ret) - goto err; + goto err_qdss; __stm_enable(); @@ -140,6 +146,9 @@ static int stm_enable(void) dev_info(stm.dev, "STM tracing enabled\n"); return 0; +err_qdss: + clk_disable_unprepare(stm.clk); +err_clk: err: return ret; } @@ -167,9 +176,11 @@ static int stm_disable(void) __stm_disable(); + stm.enabled = false; + qdss_disable(stm.src); - stm.enabled = false; + clk_disable_unprepare(stm.clk); dev_info(stm.dev, "STM tracing disabled\n"); return 0; @@ -531,6 +542,16 @@ static int __devinit stm_probe(struct platform_device *pdev) goto err_qdssget; } + stm.clk = clk_get(stm.dev, "core_clk"); + if (IS_ERR(stm.clk)) { + ret = PTR_ERR(stm.clk); + goto err_clk_get; + } + + ret = clk_set_rate(stm.clk, CS_CLK_RATE_TRACE); + if (ret) + goto err_clk_rate; + ret = stm_sysfs_init(); if (ret) goto err_sysfs; @@ -542,6 +563,9 @@ static int __devinit stm_probe(struct platform_device *pdev) return 0; err_sysfs: +err_clk_rate: + clk_put(stm.clk); +err_clk_get: qdss_put(stm.src); err_qdssget: misc_deregister(&stm_misc); @@ -563,6 +587,7 @@ static int __devexit stm_remove(struct platform_device *pdev) if (stm.enabled) stm_disable(); stm_sysfs_exit(); + clk_put(stm.clk); qdss_put(stm.src); misc_deregister(&stm_misc); iounmap(stm.chs.base); diff --git a/drivers/cs/cs-tpiu.c b/drivers/cs/cs-tpiu.c index c5e28ebb0fe..8191d2c959b 100644 --- a/drivers/cs/cs-tpiu.c +++ b/drivers/cs/cs-tpiu.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "cs-priv.h" @@ -60,6 +61,7 @@ struct tpiu_ctx { void __iomem *base; bool enabled; struct device *dev; + struct clk *clk; }; static struct tpiu_ctx tpiu; @@ -100,9 +102,23 @@ static int __devinit tpiu_probe(struct platform_device *pdev) tpiu.dev = &pdev->dev; + tpiu.clk = clk_get(tpiu.dev, "core_clk"); + if (IS_ERR(tpiu.clk)) { + ret = PTR_ERR(tpiu.clk); + goto err_clk_get; + } + + ret = clk_set_rate(tpiu.clk, CS_CLK_RATE_TRACE); + if (ret) + goto err_clk_rate; + dev_info(tpiu.dev, "TPIU initialized\n"); return 0; +err_clk_rate: + clk_put(tpiu.clk); +err_clk_get: + iounmap(tpiu.base); err_ioremap: err_res: dev_err(tpiu.dev, "TPIU init failed\n"); @@ -113,6 +129,7 @@ static int __devexit tpiu_remove(struct platform_device *pdev) { if (tpiu.enabled) tpiu_disable(); + clk_put(tpiu.clk); iounmap(tpiu.base); return 0; diff --git a/drivers/cs/cs.c b/drivers/cs/cs.c index acc22a4f74b..ee02f90045a 100644 --- a/drivers/cs/cs.c +++ b/drivers/cs/cs.c @@ -28,11 +28,6 @@ #define MAX_STR_LEN (65535) -enum { - QDSS_CLK_OFF, - QDSS_CLK_ON_DBG, - QDSS_CLK_ON_HSDBG, -}; static LIST_HEAD(cs_orph_conns); static DEFINE_MUTEX(cs_orph_conns_mutex); @@ -387,19 +382,12 @@ EXPORT_SYMBOL(qdss_put); */ int qdss_enable(struct qdss_source *src) { - int ret; - if (!src) return -EINVAL; - ret = qdss_clk_enable(); - if (ret) - goto err; - if (qdss.afamily) { mutex_lock(&qdss.sink_mutex); if (qdss.sink_count == 0) { - etb_disable(); tpiu_disable(); /* enable ETB first to avoid losing any trace data */ etb_enable(); @@ -410,8 +398,6 @@ int qdss_enable(struct qdss_source *src) funnel_enable(0x0, src->fport_mask); return 0; -err: - return ret; } EXPORT_SYMBOL(qdss_enable); @@ -443,7 +429,6 @@ void qdss_disable(struct qdss_source *src) } funnel_disable(0x0, src->fport_mask); - qdss_clk_disable(); return; out: mutex_unlock(&qdss.sink_mutex); @@ -470,37 +455,6 @@ void qdss_disable_sink(void) } EXPORT_SYMBOL(qdss_disable_sink); -/** - * qdss_clk_enable - enable qdss clocks - * - * Enables qdss clocks - * - * CONTEXT: - * Might sleep. Should be called from a non-atomic context. - * - * RETURNS: - * 0 on success, non-zero on failure - */ -int qdss_clk_enable(void) -{ - return clk_prepare_enable(qdss.clk); -} -EXPORT_SYMBOL(qdss_clk_enable); - -/** - * qdss_clk_disable - disable qdss clocks - * - * Disables qdss clocks - * - * CONTEXT: - * Might sleep. Should be called from a non-atomic context. - */ -void qdss_clk_disable(void) -{ - clk_disable_unprepare(qdss.clk); -} -EXPORT_SYMBOL(qdss_clk_disable); - struct kobject *qdss_get_modulekobj(void) { return qdss.modulekobj; @@ -582,27 +536,11 @@ static int __devinit qdss_probe(struct platform_device *pdev) if (!pdata) goto err_pdata; - qdss.clk = clk_get(&pdev->dev, "core_clk"); - if (IS_ERR(qdss.clk)) { - ret = PTR_ERR(qdss.clk); - pr_info("clk get failed\n"); - goto err_clk_get; - } - - ret = clk_set_rate(qdss.clk, QDSS_CLK_ON_DBG); - if (ret) { - pr_info("clk rate failed\n"); - goto err_clk_rate; - } - qdss.afamily = pdata->afamily; qdss_add_sources(pdata->src_table, pdata->size); pr_info("QDSS arch initialized\n"); return 0; -err_clk_rate: - clk_put(qdss.clk); -err_clk_get: err_pdata: mutex_destroy(&qdss.sink_mutex); mutex_destroy(&qdss.sources_mutex); @@ -613,7 +551,6 @@ err_pdata: static int __devexit qdss_remove(struct platform_device *pdev) { qdss_sysfs_exit(); - clk_put(qdss.clk); mutex_destroy(&qdss.sink_mutex); mutex_destroy(&qdss.sources_mutex); diff --git a/include/linux/cs.h b/include/linux/cs.h index 1a0094c6b27..0e494b02b9c 100644 --- a/include/linux/cs.h +++ b/include/linux/cs.h @@ -38,6 +38,12 @@ #define ETM_ARCH_V3_3 (0x23) #define PFT_ARCH_V1_1 (0x31) +enum cs_clk_rate { + CS_CLK_RATE_OFF, + CS_CLK_RATE_TRACE, + CS_CLK_RATE_HSTRACE, +}; + enum cs_device_type { CS_DEVICE_TYPE_SOURCE, CS_DEVICE_TYPE_LINK, @@ -114,16 +120,12 @@ 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 int qdss_clk_enable(void); -extern void qdss_clk_disable(void); #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 int qdss_clk_enable(void) { return -ENOSYS; } -static inline void qdss_clk_disable(void) {} #endif #endif