blob: a7e8b8515b4d3563bb01fe0683e8b0d62efc7982 [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 Patel27086d92012-05-17 23:21:43 -070022#include <linux/clk.h>
Pratik Patel74929432011-12-26 12:03:41 -080023
Pratik Patelb27a9352012-03-17 22:37:21 -070024#include "qdss-priv.h"
Pratik Patel74929432011-12-26 12:03:41 -080025
Pratik Patel1403f2a2012-03-21 10:10:00 -070026#define MAX_STR_LEN (65535)
27
Pratik Patel74929432011-12-26 12:03:41 -080028enum {
29 QDSS_CLK_OFF,
30 QDSS_CLK_ON_DBG,
31 QDSS_CLK_ON_HSDBG,
32};
33
Pratik Patel1403f2a2012-03-21 10:10:00 -070034/*
35 * Exclusion rules for structure fields.
36 *
37 * S: qdss.sources_mutex protected.
38 * I: qdss.sink_mutex protected.
39 * C: qdss.clk_mutex protected.
40 */
Pratik Patel6630ebe2012-03-06 16:44:22 -080041struct qdss_ctx {
Pratik Patel1403f2a2012-03-21 10:10:00 -070042 struct kobject *modulekobj;
Pratik Patel132d62b2012-05-14 17:37:23 -070043 uint8_t afamily;
Pratik Patel1403f2a2012-03-21 10:10:00 -070044 struct list_head sources; /* S: sources list */
45 struct mutex sources_mutex;
46 uint8_t sink_count; /* I: sink count */
47 struct mutex sink_mutex;
48 uint8_t max_clk;
Pratik Patel27086d92012-05-17 23:21:43 -070049 struct clk *clk;
Pratik Patel6630ebe2012-03-06 16:44:22 -080050};
51
52static struct qdss_ctx qdss;
53
Pratik Patel1403f2a2012-03-21 10:10:00 -070054/**
55 * qdss_get - get the qdss source handle
56 * @name: name of the qdss source
57 *
58 * Searches the sources list to get the qdss source handle for this source.
59 *
60 * CONTEXT:
61 * Typically called from init or probe functions
62 *
63 * RETURNS:
64 * pointer to struct qdss_source on success, %NULL on failure
65 */
66struct qdss_source *qdss_get(const char *name)
Pratik Patel6630ebe2012-03-06 16:44:22 -080067{
Pratik Patel1403f2a2012-03-21 10:10:00 -070068 struct qdss_source *src, *source = NULL;
69
70 mutex_lock(&qdss.sources_mutex);
71 list_for_each_entry(src, &qdss.sources, link) {
72 if (src->name) {
73 if (strncmp(src->name, name, MAX_STR_LEN))
74 continue;
75 source = src;
76 break;
77 }
78 }
79 mutex_unlock(&qdss.sources_mutex);
80
81 return source ? source : ERR_PTR(-ENOENT);
Pratik Patel6630ebe2012-03-06 16:44:22 -080082}
Pratik Patel1403f2a2012-03-21 10:10:00 -070083EXPORT_SYMBOL(qdss_get);
84
85/**
86 * qdss_put - release the qdss source handle
87 * @name: name of the qdss source
88 *
89 * CONTEXT:
90 * Typically called from driver remove or exit functions
91 */
92void qdss_put(struct qdss_source *src)
93{
94}
95EXPORT_SYMBOL(qdss_put);
96
97/**
98 * qdss_enable - enable qdss for the source
99 * @src: handle for the source making the call
100 *
101 * Enables qdss block (relevant funnel ports and sink) if not already
102 * enabled, otherwise increments the reference count
103 *
104 * CONTEXT:
105 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
106 *
107 * RETURNS:
108 * 0 on success, non-zero on failure
109 */
110int qdss_enable(struct qdss_source *src)
111{
112 int ret;
113
114 if (!src)
115 return -EINVAL;
116
117 ret = qdss_clk_enable();
118 if (ret)
119 goto err;
120
Pratik Patel132d62b2012-05-14 17:37:23 -0700121 if (qdss.afamily) {
Pratik Patel1403f2a2012-03-21 10:10:00 -0700122 mutex_lock(&qdss.sink_mutex);
123 if (qdss.sink_count == 0) {
124 etb_disable();
125 tpiu_disable();
126 /* enable ETB first to avoid losing any trace data */
127 etb_enable();
128 }
129 qdss.sink_count++;
130 mutex_unlock(&qdss.sink_mutex);
131 }
132
133 funnel_enable(0x0, src->fport_mask);
134 return 0;
135err:
136 return ret;
137}
138EXPORT_SYMBOL(qdss_enable);
139
140/**
141 * qdss_disable - disable qdss for the source
142 * @src: handle for the source making the call
143 *
144 * Disables qdss block (relevant funnel ports and sink) if the reference count
145 * is one, otherwise decrements the reference count
146 *
147 * CONTEXT:
148 * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
149 */
150void qdss_disable(struct qdss_source *src)
151{
152 if (!src)
153 return;
154
Pratik Patel132d62b2012-05-14 17:37:23 -0700155 if (qdss.afamily) {
Pratik Patel1403f2a2012-03-21 10:10:00 -0700156 mutex_lock(&qdss.sink_mutex);
157 if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
158 goto out;
159 if (qdss.sink_count == 1) {
160 etb_dump();
161 etb_disable();
162 }
163 qdss.sink_count--;
164 mutex_unlock(&qdss.sink_mutex);
165 }
166
167 funnel_disable(0x0, src->fport_mask);
168 qdss_clk_disable();
169 return;
170out:
171 mutex_unlock(&qdss.sink_mutex);
172}
173EXPORT_SYMBOL(qdss_disable);
Pratik Patel74929432011-12-26 12:03:41 -0800174
Pratik Patelbf3e77442012-03-18 18:30:43 -0700175/**
Pratik Patelf3adf032012-05-03 12:50:21 -0700176 * qdss_disable_sink - force disable the current qdss sink(s)
177 *
178 * Force disable the current qdss sink(s) to stop the sink from accepting any
179 * trace generated subsequent to this call. This function should only be used
180 * as a way to stop the sink from getting polluted with trace data that is
181 * uninteresting after an event of interest has occured.
182 *
183 * CONTEXT:
184 * Can be called from atomic or non-atomic context.
185 */
186void qdss_disable_sink(void)
187{
Pratik Patel132d62b2012-05-14 17:37:23 -0700188 if (qdss.afamily) {
Pratik Patelf3adf032012-05-03 12:50:21 -0700189 etb_dump();
190 etb_disable();
191 }
192}
193EXPORT_SYMBOL(qdss_disable_sink);
194
195/**
Pratik Patelbf3e77442012-03-18 18:30:43 -0700196 * qdss_clk_enable - enable qdss clocks
197 *
Pratik Patel27086d92012-05-17 23:21:43 -0700198 * Enables qdss clocks
Pratik Patelbf3e77442012-03-18 18:30:43 -0700199 *
200 * CONTEXT:
Pratik Patel27086d92012-05-17 23:21:43 -0700201 * Might sleep. Should be called from a non-atomic context.
Pratik Patelbf3e77442012-03-18 18:30:43 -0700202 *
203 * RETURNS:
204 * 0 on success, non-zero on failure
205 */
Pratik Patel74929432011-12-26 12:03:41 -0800206int qdss_clk_enable(void)
207{
Pratik Patel27086d92012-05-17 23:21:43 -0700208 return clk_prepare_enable(qdss.clk);
Pratik Patel74929432011-12-26 12:03:41 -0800209}
Pratik Patelbf3e77442012-03-18 18:30:43 -0700210EXPORT_SYMBOL(qdss_clk_enable);
Pratik Patel74929432011-12-26 12:03:41 -0800211
Pratik Patelbf3e77442012-03-18 18:30:43 -0700212/**
213 * qdss_clk_disable - disable qdss clocks
214 *
Pratik Patel27086d92012-05-17 23:21:43 -0700215 * Disables qdss clocks
Pratik Patelbf3e77442012-03-18 18:30:43 -0700216 *
217 * CONTEXT:
Pratik Patel27086d92012-05-17 23:21:43 -0700218 * Might sleep. Should be called from a non-atomic context.
Pratik Patelbf3e77442012-03-18 18:30:43 -0700219 */
Pratik Patel74929432011-12-26 12:03:41 -0800220void qdss_clk_disable(void)
221{
Pratik Patel27086d92012-05-17 23:21:43 -0700222 clk_disable_unprepare(qdss.clk);
Pratik Patel74929432011-12-26 12:03:41 -0800223}
Pratik Patelbf3e77442012-03-18 18:30:43 -0700224EXPORT_SYMBOL(qdss_clk_disable);
Pratik Patel59e29942011-12-27 10:31:33 -0800225
Pratik Patel1403f2a2012-03-21 10:10:00 -0700226struct kobject *qdss_get_modulekobj(void)
227{
228 return qdss.modulekobj;
229}
230
Pratik Patel6630ebe2012-03-06 16:44:22 -0800231#define QDSS_ATTR(name) \
232static struct kobj_attribute name##_attr = \
233 __ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
234
235static ssize_t max_clk_store(struct kobject *kobj,
236 struct kobj_attribute *attr,
237 const char *buf, size_t n)
238{
239 unsigned long val;
240
241 if (sscanf(buf, "%lx", &val) != 1)
242 return -EINVAL;
243
244 qdss.max_clk = val;
245 return n;
246}
247static ssize_t max_clk_show(struct kobject *kobj,
248 struct kobj_attribute *attr,
249 char *buf)
250{
251 unsigned long val = qdss.max_clk;
252 return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
253}
254QDSS_ATTR(max_clk);
255
Stephen Boyda9510502012-04-24 16:23:34 -0700256static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
Pratik Patel1403f2a2012-03-21 10:10:00 -0700257{
258 mutex_lock(&qdss.sources_mutex);
259 while (num--) {
260 list_add_tail(&srcs->link, &qdss.sources);
261 srcs++;
262 }
263 mutex_unlock(&qdss.sources_mutex);
264}
265
Pratik Patel6630ebe2012-03-06 16:44:22 -0800266static int __init qdss_sysfs_init(void)
267{
268 int ret;
269
270 qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
271 if (!qdss.modulekobj) {
272 pr_err("failed to find QDSS sysfs module kobject\n");
273 ret = -ENOENT;
274 goto err;
275 }
276
277 ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
278 if (ret) {
279 pr_err("failed to create QDSS sysfs max_clk attribute\n");
280 goto err;
281 }
282
283 return 0;
284err:
285 return ret;
286}
287
Stephen Boyda9510502012-04-24 16:23:34 -0700288static void __devexit qdss_sysfs_exit(void)
Pratik Patel6630ebe2012-03-06 16:44:22 -0800289{
290 sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
291}
292
Pratik Patel1403f2a2012-03-21 10:10:00 -0700293static int __devinit qdss_probe(struct platform_device *pdev)
Pratik Patel59e29942011-12-27 10:31:33 -0800294{
Pratik Patel27086d92012-05-17 23:21:43 -0700295 int ret = 0;
Pratik Patel132d62b2012-05-14 17:37:23 -0700296 struct msm_qdss_platform_data *pdata;
Pratik Patel59e29942011-12-27 10:31:33 -0800297
Pratik Patel1403f2a2012-03-21 10:10:00 -0700298 mutex_init(&qdss.sources_mutex);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700299 mutex_init(&qdss.sink_mutex);
300
Pratik Patel1403f2a2012-03-21 10:10:00 -0700301 INIT_LIST_HEAD(&qdss.sources);
Pratik Patel132d62b2012-05-14 17:37:23 -0700302
303 pdata = pdev->dev.platform_data;
304 if (!pdata)
305 goto err_pdata;
306
Pratik Patel27086d92012-05-17 23:21:43 -0700307 qdss.clk = clk_get(&pdev->dev, "core_clk");
308 if (IS_ERR(qdss.clk)) {
309 ret = PTR_ERR(qdss.clk);
310 pr_info("clk get failed\n");
311 goto err_clk_get;
312 }
313
314 ret = clk_set_rate(qdss.clk, QDSS_CLK_ON_DBG);
315 if (ret) {
316 pr_info("clk rate failed\n");
317 goto err_clk_rate;
318 }
319
Pratik Patel132d62b2012-05-14 17:37:23 -0700320 qdss.afamily = pdata->afamily;
321 qdss_add_sources(pdata->src_table, pdata->size);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700322
323 pr_info("QDSS arch initialized\n");
324 return 0;
Pratik Patel27086d92012-05-17 23:21:43 -0700325err_clk_rate:
326 clk_put(qdss.clk);
327err_clk_get:
Pratik Patel1403f2a2012-03-21 10:10:00 -0700328err_pdata:
329 mutex_destroy(&qdss.sink_mutex);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700330 mutex_destroy(&qdss.sources_mutex);
331 pr_err("QDSS init failed\n");
332 return ret;
333}
334
335static int __devexit qdss_remove(struct platform_device *pdev)
336{
337 qdss_sysfs_exit();
Pratik Patel27086d92012-05-17 23:21:43 -0700338 clk_put(qdss.clk);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700339 mutex_destroy(&qdss.sink_mutex);
Pratik Patel1403f2a2012-03-21 10:10:00 -0700340 mutex_destroy(&qdss.sources_mutex);
341
342 return 0;
343}
344
Pratik Patel9eae4822012-05-14 17:34:53 -0700345static struct of_device_id qdss_match[] = {
346 {.compatible = "qcom,msm-qdss"},
347 {}
348};
349
Pratik Patel1403f2a2012-03-21 10:10:00 -0700350static struct platform_driver qdss_driver = {
351 .probe = qdss_probe,
352 .remove = __devexit_p(qdss_remove),
353 .driver = {
354 .name = "msm_qdss",
Pratik Patel9eae4822012-05-14 17:34:53 -0700355 .owner = THIS_MODULE,
356 .of_match_table = qdss_match,
Pratik Patel1403f2a2012-03-21 10:10:00 -0700357 },
358};
359
360static int __init qdss_init(void)
361{
362 return platform_driver_register(&qdss_driver);
363}
364arch_initcall(qdss_init);
365
366static int __init qdss_module_init(void)
367{
368 int ret;
Pratik Patelbf3e77442012-03-18 18:30:43 -0700369
Pratik Patel6630ebe2012-03-06 16:44:22 -0800370 ret = qdss_sysfs_init();
371 if (ret)
372 goto err_sysfs;
Pratik Patel59e29942011-12-27 10:31:33 -0800373
Pratik Patel1403f2a2012-03-21 10:10:00 -0700374 pr_info("QDSS module initialized\n");
Pratik Patel59e29942011-12-27 10:31:33 -0800375 return 0;
Pratik Patel6630ebe2012-03-06 16:44:22 -0800376err_sysfs:
Pratik Patel59e29942011-12-27 10:31:33 -0800377 return ret;
378}
Pratik Patel1403f2a2012-03-21 10:10:00 -0700379module_init(qdss_module_init);
Pratik Patel59e29942011-12-27 10:31:33 -0800380
381static void __exit qdss_exit(void)
382{
Pratik Patel1403f2a2012-03-21 10:10:00 -0700383 platform_driver_unregister(&qdss_driver);
Pratik Patel59e29942011-12-27 10:31:33 -0800384}
385module_exit(qdss_exit);
386
387MODULE_LICENSE("GPL v2");
388MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");