blob: b2d38b1494617807fca4a5fad1bd20aa83b8d861 [file] [log] [blame]
Pratik Patelfd6f56a2011-10-10 17:47:55 -07001/* Copyright (c) 2011, 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>
21#include <linux/slab.h>
22#include <linux/smp.h>
23
24#include "qdss.h"
25
26#define debug_writel(debug, cpu, val, off) \
27 __raw_writel((val), debug.base[cpu] + off)
28#define debug_readl(debug, cpu, off) \
29 __raw_readl(debug.base[cpu] + off)
30
31#define DBGDIDR (0x000)
32#define DBGWFAR (0x018)
33#define DBGVCR (0x01C)
34#define DBGECR (0x024)
35#define DBGDTRRX (0x080)
36#define DBGITR (0x084)
37#define DBGDSCR (0x088)
38#define DBGDTRTX (0x08C)
39#define DBGDRCR (0x090)
40#define DBGEACR (0x094)
41#define DBGPCSR (0x0A0)
42#define DBGCIDSR (0x0A4)
43#define DBGVIDSR (0x0A8)
44#define DBGBVRm(n) (0x100 + (n * 4))
45#define DBGBCRm(n) (0x140 + (n * 4))
46#define DBGWVRm(n) (0x180 + (n * 4))
47#define DBGWCRm(n) (0x1C0 + (n * 4))
48#define DBGBXVRm(n) (0x240 + (n * 4))
49#define DBGOSLAR (0x300)
50#define DBGOSLSR (0x304)
51#define DBGPRCR (0x310)
52#define DBGPRSR (0x314)
53
54
55#define DEBUG_LOCK(cpu) \
56do { \
57 mb(); \
58 debug_writel(debug, cpu, MAGIC2, CS_LAR); \
59} while (0)
60#define DEBUG_UNLOCK(cpu) \
61do { \
62 debug_writel(debug, cpu, MAGIC1, CS_LAR); \
63 mb(); \
64} while (0)
65
66#define DEBUG_OS_LOCK(cpu) \
67do { \
68 debug_writel(debug, cpu, MAGIC1, DBGOSLAR); \
69 mb(); \
70} while (0)
71#define DEBUG_OS_UNLOCK(cpu) \
72do { \
73 mb(); \
74 debug_writel(debug, cpu, MAGIC2, DBGOSLAR); \
75 mb(); \
76} while (0)
77
78#define MAX_DEBUG_REGS (90)
79#define MAX_STATE_SIZE (MAX_DEBUG_REGS * num_possible_cpus())
80#define DBGDSCR_MASK (0x6C30FC3C)
81
82struct debug_config {
83 /* read only config register */
84 uint32_t dbg_id;
85 /* derived values */
86 uint8_t nr_watch_pts;
87 uint8_t nr_brk_pts;
88 uint8_t nr_ctx_comp;
89};
90
91struct debug_ctx {
92 struct debug_config cfg;
93 void __iomem **base;
94 uint32_t *state;
95 struct device *dev;
96};
97
98static struct debug_ctx debug;
99
100static void debug_save_reg(int cpu)
101{
102 uint32_t i;
103 int j;
104
105 DEBUG_UNLOCK(cpu);
106 DEBUG_OS_LOCK(cpu);
107
108 i = cpu * MAX_DEBUG_REGS;
109
110 debug.state[i++] = debug_readl(debug, cpu, DBGWFAR);
111 for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
112 debug.state[i++] = debug_readl(debug, cpu, DBGBCRm(j));
113 debug.state[i++] = debug_readl(debug, cpu, DBGBVRm(j));
114 }
115 for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
116 debug.state[i++] = debug_readl(debug, cpu, DBGBXVRm(j));
117 for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
118 debug.state[i++] = debug_readl(debug, cpu, DBGWVRm(j));
119 debug.state[i++] = debug_readl(debug, cpu, DBGWCRm(j));
120 }
121 debug.state[i++] = debug_readl(debug, cpu, DBGVCR);
122 debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMSET);
123 debug.state[i++] = debug_readl(debug, cpu, CS_CLAIMCLR);
124 debug.state[i++] = debug_readl(debug, cpu, DBGDTRTX);
125 debug.state[i++] = debug_readl(debug, cpu, DBGDTRRX);
126 debug.state[i++] = debug_readl(debug, cpu, DBGDSCR);
127
128 DEBUG_LOCK(cpu);
129}
130
131static void debug_restore_reg(int cpu)
132{
133 uint32_t i;
134 int j;
135
136 DEBUG_UNLOCK(cpu);
137 DEBUG_OS_LOCK(cpu);
138
139 i = cpu * MAX_DEBUG_REGS;
140
141 debug_writel(debug, cpu, debug.state[i++], DBGWFAR);
142 for (j = 0; j < debug.cfg.nr_brk_pts; j++) {
143 debug_writel(debug, cpu, debug.state[i++], DBGBCRm(j));
144 debug_writel(debug, cpu, debug.state[i++], DBGBVRm(j));
145 }
146 for (j = 0; j < debug.cfg.nr_ctx_comp; j++)
147 debug_writel(debug, cpu, debug.state[i++], DBGBXVRm(j));
148 for (j = 0; j < debug.cfg.nr_watch_pts; j++) {
149 debug_writel(debug, cpu, debug.state[i++], DBGWVRm(j));
150 debug_writel(debug, cpu, debug.state[i++], DBGWCRm(j));
151 }
152 debug_writel(debug, cpu, debug.state[i++], DBGVCR);
153 debug_writel(debug, cpu, debug.state[i++], CS_CLAIMSET);
154 debug_writel(debug, cpu, debug.state[i++], CS_CLAIMCLR);
155 debug_writel(debug, cpu, debug.state[i++], DBGDTRTX);
156 debug_writel(debug, cpu, debug.state[i++], DBGDTRRX);
157 debug_writel(debug, cpu, debug.state[i++] & DBGDSCR_MASK, DBGDSCR);
158
159 DEBUG_OS_UNLOCK(cpu);
160 DEBUG_LOCK(cpu);
161}
162
163/* msm_save_jtag_debug and msm_restore_jtag_debug should be fast
164 *
165 * These functions will be called either from:
166 * 1. per_cpu idle thread context for idle power collapses.
167 * 2. per_cpu idle thread context for hotplug/suspend power collapse for
168 * nonboot cpus.
169 * 3. suspend thread context for core0.
170 *
171 * In all cases we are guaranteed to be running on the same cpu for the
172 * entire duration.
173 */
174void msm_save_jtag_debug(void)
175{
176 int cpu = smp_processor_id();
177 debug_save_reg(cpu);
178}
179
180void msm_restore_jtag_debug(void)
181{
182 int cpu = smp_processor_id();
183 debug_restore_reg(cpu);
184}
185
186static void debug_cfg_ro_init(void)
187{
188 /* use cpu 0 for setup */
189 int cpu = 0;
190
191 DEBUG_UNLOCK(cpu);
192
193 debug.cfg.dbg_id = debug_readl(debug, cpu, DBGDIDR);
194 debug.cfg.nr_ctx_comp = BMVAL(debug.cfg.dbg_id, 20, 23) + 1;
195 debug.cfg.nr_brk_pts = BMVAL(debug.cfg.dbg_id, 24, 27) + 1;
196 debug.cfg.nr_watch_pts = BMVAL(debug.cfg.dbg_id, 28, 31) + 1;
197
198 DEBUG_LOCK(cpu);
199}
200
201static int __devinit debug_probe(struct platform_device *pdev)
202{
203 int i, ret;
204 struct resource *res;
205
206 debug.base = kzalloc(pdev->num_resources * sizeof(void *), GFP_KERNEL);
207 if (!debug.base) {
208 ret = -ENOMEM;
209 goto err_base_kzalloc;
210 }
211
212 for (i = 0; i < pdev->num_resources; i++) {
213 res = platform_get_resource(pdev, IORESOURCE_MEM, i);
214 if (!res) {
215 ret = -EINVAL;
216 goto err_res;
217 }
218
219 debug.base[i] = ioremap_nocache(res->start, resource_size(res));
220 if (!debug.base[i]) {
221 ret = -EINVAL;
222 goto err_ioremap;
223 }
224 }
225
226 debug.dev = &pdev->dev;
227
228 debug.state = kzalloc(MAX_STATE_SIZE * sizeof(uint32_t), GFP_KERNEL);
229 if (!debug.state) {
230 ret = -ENOMEM;
231 goto err_state_kzalloc;
232 }
233
234 debug_cfg_ro_init();
235
236 dev_info(debug.dev, "Debug intialized.\n");
237
238 return 0;
239
240err_state_kzalloc:
241err_ioremap:
242err_res:
243 while (i) {
244 iounmap(debug.base[i-1]);
245 i--;
246 }
247 kfree(debug.base);
248err_base_kzalloc:
249 return ret;
250}
251
252static int __devexit debug_remove(struct platform_device *pdev)
253{
254 int i;
255
256 kfree(debug.state);
257 for (i = pdev->num_resources; i > 0; i--)
258 iounmap(debug.base[i-1]);
259 kfree(debug.base);
260
261 return 0;
262}
263
264static struct platform_driver debug_driver = {
265 .probe = debug_probe,
266 .remove = __devexit_p(debug_remove),
267 .driver = {
268 .name = "msm_debug",
269 },
270};
271
272static int __init debug_init(void)
273{
274 return platform_driver_register(&debug_driver);
275}
276module_init(debug_init);
277
278static void __exit debug_exit(void)
279{
280 platform_driver_unregister(&debug_driver);
281}
282module_exit(debug_exit);
283
284MODULE_LICENSE("GPL v2");
285MODULE_DESCRIPTION("Coresight Debug driver");