blob: 83a6a369e4eab585a650d5f1f1ee5e2f4885f164 [file] [log] [blame]
Pratik Patel74929432011-12-26 12:03:41 -08001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/device.h>
18#include <linux/platform_device.h>
19#include <linux/io.h>
20#include <linux/err.h>
Pratik Patelbf3e77442012-03-18 18:30:43 -070021#include <linux/export.h>
Pratik Patel74929432011-12-26 12:03:41 -080022#include <mach/rpm.h>
23
24#include "rpm_resources.h"
Pratik Patelb27a9352012-03-17 22:37:21 -070025#include "qdss-priv.h"
Pratik Patel74929432011-12-26 12:03:41 -080026
Pratik Patel1403f2a2012-03-21 10:10:00 -070027#define MAX_STR_LEN (65535)
28
Pratik Patel74929432011-12-26 12:03:41 -080029enum {
30 QDSS_CLK_OFF,
31 QDSS_CLK_ON_DBG,
32 QDSS_CLK_ON_HSDBG,
33};
34
Pratik Patel1403f2a2012-03-21 10:10:00 -070035/*
36 * Exclusion rules for structure fields.
37 *
38 * S: qdss.sources_mutex protected.
39 * I: qdss.sink_mutex protected.
40 * C: qdss.clk_mutex protected.
41 */
Pratik Patel6630ebe2012-03-06 16:44:22 -080042struct qdss_ctx {
Pratik Patel1403f2a2012-03-21 10:10:00 -070043 struct kobject *modulekobj;
Pratik Patel132d62b2012-05-14 17:37:23 -070044 uint8_t afamily;
Pratik Patel1403f2a2012-03-21 10:10:00 -070045 struct list_head sources; /* S: sources list */
46 struct mutex sources_mutex;
47 uint8_t sink_count; /* I: sink count */
48 struct mutex sink_mutex;
49 uint8_t max_clk;
50 uint8_t clk_count; /* C: clk count */
51 struct mutex clk_mutex;
Pratik Patel6630ebe2012-03-06 16:44:22 -080052};
53
54static struct qdss_ctx qdss;
55
Pratik Patel1403f2a2012-03-21 10:10:00 -070056/**
57 * qdss_get - get the qdss source handle
58 * @name: name of the qdss source
59 *
60 * Searches the sources list to get the qdss source handle for this source.
61 *
62 * CONTEXT:
63 * Typically called from init or probe functions
64 *
65 * RETURNS:
66 * pointer to struct qdss_source on success, %NULL on failure
67 */
68struct qdss_source *qdss_get(const char *name)
Pratik Patel6630ebe2012-03-06 16:44:22 -080069{
Pratik Patel1403f2a2012-03-21 10:10:00 -070070 struct qdss_source *src, *source = NULL;
71
72 mutex_lock(&qdss.sources_mutex);
73 list_for_each_entry(src, &qdss.sources, link) {
74 if (src->name) {
75 if (strncmp(src->name, name, MAX_STR_LEN))
76 continue;
77 source = src;
78 break;
79 }
80 }
81 mutex_unlock(&qdss.sources_mutex);
82
83 return source ? source : ERR_PTR(-ENOENT);
Pratik Patel6630ebe2012-03-06 16:44:22 -080084}
Pratik Patel1403f2a2012-03-21 10:10:00 -070085EXPORT_SYMBOL(qdss_get);
86
87/**
88 * qdss_put - release the qdss source handle
89 * @name: name of the qdss source
90 *
91 * CONTEXT:
92 * Typically called from driver remove or exit functions
93 */
94void qdss_put(struct qdss_source *src)
95{
96}
97EXPORT_SYMBOL(qdss_put);
98
99/**
100 * qdss_enable - enable qdss for the source
101 * @src: handle for the source making the call
102 *
103 * Enables qdss block (relevant funnel ports and sink) if not already
104 * enabled, otherwise increments the reference count
105 *
106 * CONTEXT:
107 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
108 *
109 * RETURNS:
110 * 0 on success, non-zero on failure
111 */
112int qdss_enable(struct qdss_source *src)
113{
114 int ret;
115
116 if (!src)
117 return -EINVAL;
118
119 ret = qdss_clk_enable();
120 if (ret)
121 goto err;
122
Pratik Patel132d62b2012-05-14 17:37:23 -0700123 if (qdss.afamily) {
Pratik Patel1403f2a2012-03-21 10:10:00 -0700124 mutex_lock(&qdss.sink_mutex);
125 if (qdss.sink_count == 0) {
126 etb_disable();
127 tpiu_disable();
128 /* enable ETB first to avoid losing any trace data */
129 etb_enable();
130 }
131 qdss.sink_count++;
132 mutex_unlock(&qdss.sink_mutex);
133 }
134
135 funnel_enable(0x0, src->fport_mask);
136 return 0;
137err:
138 return ret;
139}
140EXPORT_SYMBOL(qdss_enable);
141
142/**
143 * qdss_disable - disable qdss for the source
144 * @src: handle for the source making the call
145 *
146 * Disables qdss block (relevant funnel ports and sink) if the reference count
147 * is one, otherwise decrements the reference count
148 *
149 * CONTEXT:
150 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
151 */
152void qdss_disable(struct qdss_source *src)
153{
154 if (!src)
155 return;
156
Pratik Patel132d62b2012-05-14 17:37:23 -0700157 if (qdss.afamily) {
Pratik Patel1403f2a2012-03-21 10:10:00 -0700158 mutex_lock(&qdss.sink_mutex);
159 if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
160 goto out;
161 if (qdss.sink_count == 1) {
162 etb_dump();
163 etb_disable();
164 }
165 qdss.sink_count--;
166 mutex_unlock(&qdss.sink_mutex);
167 }
168
169 funnel_disable(0x0, src->fport_mask);
170 qdss_clk_disable();
171 return;
172out:
173 mutex_unlock(&qdss.sink_mutex);
174}
175EXPORT_SYMBOL(qdss_disable);
Pratik Patel74929432011-12-26 12:03:41 -0800176
Pratik Patelbf3e77442012-03-18 18:30:43 -0700177/**
Pratik Patelf3adf032012-05-03 12:50:21 -0700178 * qdss_disable_sink - force disable the current qdss sink(s)
179 *
180 * Force disable the current qdss sink(s) to stop the sink from accepting any
181 * trace generated subsequent to this call. This function should only be used
182 * as a way to stop the sink from getting polluted with trace data that is
183 * uninteresting after an event of interest has occured.
184 *
185 * CONTEXT:
186 * Can be called from atomic or non-atomic context.
187 */
188void qdss_disable_sink(void)
189{
Pratik Patel132d62b2012-05-14 17:37:23 -0700190 if (qdss.afamily) {
Pratik Patelf3adf032012-05-03 12:50:21 -0700191 etb_dump();
192 etb_disable();
193 }
194}
195EXPORT_SYMBOL(qdss_disable_sink);
196
197/**
Pratik Patelbf3e77442012-03-18 18:30:43 -0700198 * qdss_clk_enable - enable qdss clocks
199 *
200 * Enables qdss clocks via RPM if they aren't already enabled, otherwise
201 * increments the reference count.
202 *
203 * CONTEXT:
204 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
205 *
206 * RETURNS:
207 * 0 on success, non-zero on failure
208 */
Pratik Patel74929432011-12-26 12:03:41 -0800209int qdss_clk_enable(void)
210{
211 int ret;
Pratik Patel74929432011-12-26 12:03:41 -0800212 struct msm_rpm_iv_pair iv;
Pratik Patel74929432011-12-26 12:03:41 -0800213
Pratik Patelbf3e77442012-03-18 18:30:43 -0700214 mutex_lock(&qdss.clk_mutex);
215 if (qdss.clk_count == 0) {
216 iv.id = MSM_RPM_ID_QDSS_CLK;
217 if (qdss.max_clk)
218 iv.value = QDSS_CLK_ON_HSDBG;
219 else
220 iv.value = QDSS_CLK_ON_DBG;
221 ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, &iv, 1);
222 if (WARN(ret, "qdss clks not enabled (%d)\n", ret))
223 goto err_clk;
224 }
225 qdss.clk_count++;
226 mutex_unlock(&qdss.clk_mutex);
Pratik Patel74929432011-12-26 12:03:41 -0800227 return 0;
Pratik Patel74929432011-12-26 12:03:41 -0800228err_clk:
Pratik Patelbf3e77442012-03-18 18:30:43 -0700229 mutex_unlock(&qdss.clk_mutex);
Pratik Patel74929432011-12-26 12:03:41 -0800230 return ret;
231}
Pratik Patelbf3e77442012-03-18 18:30:43 -0700232EXPORT_SYMBOL(qdss_clk_enable);
Pratik Patel74929432011-12-26 12:03:41 -0800233
Pratik Patelbf3e77442012-03-18 18:30:43 -0700234/**
235 * qdss_clk_disable - disable qdss clocks
236 *
237 * Disables qdss clocks via RPM if the reference count is one, otherwise
238 * decrements the reference count.
239 *
240 * CONTEXT:
241 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
242 */
Pratik Patel74929432011-12-26 12:03:41 -0800243void qdss_clk_disable(void)
244{
245 int ret;
246 struct msm_rpm_iv_pair iv;
247
Pratik Patelbf3e77442012-03-18 18:30:43 -0700248 mutex_lock(&qdss.clk_mutex);
249 if (WARN(qdss.clk_count == 0, "qdss clks are unbalanced\n"))
250 goto out;
251 if (qdss.clk_count == 1) {
252 iv.id = MSM_RPM_ID_QDSS_CLK;
253 iv.value = QDSS_CLK_OFF;
254 ret = msm_rpmrs_set(MSM_RPM_CTX_SET_0, &iv, 1);
255 WARN(ret, "qdss clks not disabled (%d)\n", ret);
256 }
257 qdss.clk_count--;
258out:
259 mutex_unlock(&qdss.clk_mutex);
Pratik Patel74929432011-12-26 12:03:41 -0800260}
Pratik Patelbf3e77442012-03-18 18:30:43 -0700261EXPORT_SYMBOL(qdss_clk_disable);
Pratik Patel59e29942011-12-27 10:31:33 -0800262
Pratik Patel1403f2a2012-03-21 10:10:00 -0700263struct kobject *qdss_get_modulekobj(void)
264{
265 return qdss.modulekobj;
266}
267
Pratik Patel6630ebe2012-03-06 16:44:22 -0800268#define QDSS_ATTR(name) \
269static struct kobj_attribute name##_attr = \
270 __ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
271
272static ssize_t max_clk_store(struct kobject *kobj,
273 struct kobj_attribute *attr,
274 const char *buf, size_t n)
275{
276 unsigned long val;
277
278 if (sscanf(buf, "%lx", &val) != 1)
279 return -EINVAL;
280
281 qdss.max_clk = val;
282 return n;
283}
284static ssize_t max_clk_show(struct kobject *kobj,
285 struct kobj_attribute *attr,
286 char *buf)
287{
288 unsigned long val = qdss.max_clk;
289 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
290}
291QDSS_ATTR(max_clk);
292
Stephen Boyda9510502012-04-24 16:23:34 -0700293static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
Pratik Patel1403f2a2012-03-21 10:10:00 -0700294{
295 mutex_lock(&qdss.sources_mutex);
296 while (num--) {
297 list_add_tail(&srcs->link, &qdss.sources);
298 srcs++;
299 }
300 mutex_unlock(&qdss.sources_mutex);
301}
302
Pratik Patel6630ebe2012-03-06 16:44:22 -0800303static int __init qdss_sysfs_init(void)
304{
305 int ret;
306
307 qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
308 if (!qdss.modulekobj) {
309 pr_err("failed to find QDSS sysfs module kobject\n");
310 ret = -ENOENT;
311 goto err;
312 }
313
314 ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
315 if (ret) {
316 pr_err("failed to create QDSS sysfs max_clk attribute\n");
317 goto err;
318 }
319
320 return 0;
321err:
322 return ret;
323}
324
Stephen Boyda9510502012-04-24 16:23:34 -0700325static void __devexit qdss_sysfs_exit(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800326{
327 sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
328}
329
Pratik Patel1403f2a2012-03-21 10:10:00 -0700330static int __devinit qdss_probe(struct platform_device *pdev)
Pratik Patel59e29942011-12-27 10:31:33 -0800331{
332 int ret;
Pratik Patel132d62b2012-05-14 17:37:23 -0700333 struct msm_qdss_platform_data *pdata;
Pratik Patel59e29942011-12-27 10:31:33 -0800334
Pratik Patel1403f2a2012-03-21 10:10:00 -0700335 mutex_init(&qdss.sources_mutex);
Pratik Patelbf3e77442012-03-18 18:30:43 -0700336 mutex_init(&qdss.clk_mutex);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700337 mutex_init(&qdss.sink_mutex);
338
Pratik Patel1403f2a2012-03-21 10:10:00 -0700339 INIT_LIST_HEAD(&qdss.sources);
Pratik Patel132d62b2012-05-14 17:37:23 -0700340
341 pdata = pdev->dev.platform_data;
342 if (!pdata)
343 goto err_pdata;
344
345 qdss.afamily = pdata->afamily;
346 qdss_add_sources(pdata->src_table, pdata->size);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700347
348 pr_info("QDSS arch initialized\n");
349 return 0;
350err_pdata:
351 mutex_destroy(&qdss.sink_mutex);
352 mutex_destroy(&qdss.clk_mutex);
353 mutex_destroy(&qdss.sources_mutex);
354 pr_err("QDSS init failed\n");
355 return ret;
356}
357
358static int __devexit qdss_remove(struct platform_device *pdev)
359{
360 qdss_sysfs_exit();
361 mutex_destroy(&qdss.sink_mutex);
362 mutex_destroy(&qdss.clk_mutex);
363 mutex_destroy(&qdss.sources_mutex);
364
365 return 0;
366}
367
Pratik Patel9eae4822012-05-14 17:34:53 -0700368static struct of_device_id qdss_match[] = {
369 {.compatible = "qcom,msm-qdss"},
370 {}
371};
372
Pratik Patel1403f2a2012-03-21 10:10:00 -0700373static struct platform_driver qdss_driver = {
374 .probe = qdss_probe,
375 .remove = __devexit_p(qdss_remove),
376 .driver = {
377 .name = "msm_qdss",
Pratik Patel9eae4822012-05-14 17:34:53 -0700378 .owner = THIS_MODULE,
379 .of_match_table = qdss_match,
Pratik Patel1403f2a2012-03-21 10:10:00 -0700380 },
381};
382
383static int __init qdss_init(void)
384{
385 return platform_driver_register(&qdss_driver);
386}
387arch_initcall(qdss_init);
388
389static int __init qdss_module_init(void)
390{
391 int ret;
Pratik Patelbf3e77442012-03-18 18:30:43 -0700392
Pratik Patel6630ebe2012-03-06 16:44:22 -0800393 ret = qdss_sysfs_init();
394 if (ret)
395 goto err_sysfs;
Pratik Patel59e29942011-12-27 10:31:33 -0800396
Pratik Patel1403f2a2012-03-21 10:10:00 -0700397 pr_info("QDSS module initialized\n");
Pratik Patel59e29942011-12-27 10:31:33 -0800398 return 0;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800399err_sysfs:
Pratik Patel59e29942011-12-27 10:31:33 -0800400 return ret;
401}
Pratik Patel1403f2a2012-03-21 10:10:00 -0700402module_init(qdss_module_init);
Pratik Patel59e29942011-12-27 10:31:33 -0800403
404static void __exit qdss_exit(void)
405{
Pratik Patel1403f2a2012-03-21 10:10:00 -0700406 platform_driver_unregister(&qdss_driver);
Pratik Patel59e29942011-12-27 10:31:33 -0800407}
408module_exit(qdss_exit);
409
410MODULE_LICENSE("GPL v2");
411MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");