aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra/tegra_fiq_debugger.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /arch/arm/mach-tegra/tegra_fiq_debugger.c
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'arch/arm/mach-tegra/tegra_fiq_debugger.c')
-rw-r--r--arch/arm/mach-tegra/tegra_fiq_debugger.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/tegra_fiq_debugger.c b/arch/arm/mach-tegra/tegra_fiq_debugger.c
new file mode 100644
index 00000000000..2a19a214acb
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_fiq_debugger.c
@@ -0,0 +1,206 @@
1/*
2 * arch/arm/mach-tegra/fiq_debugger.c
3 *
4 * Serial Debugger Interface for Tegra
5 *
6 * Copyright (C) 2008 Google, Inc.
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <stdarg.h>
19#include <linux/module.h>
20#include <linux/io.h>
21#include <linux/interrupt.h>
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <linux/irq.h>
25#include <linux/serial_reg.h>
26#include <linux/slab.h>
27#include <linux/stacktrace.h>
28#include <asm/fiq_debugger.h>
29#include <mach/tegra_fiq_debugger.h>
30#include <mach/system.h>
31#include <mach/fiq.h>
32
33#include <linux/uaccess.h>
34
35struct tegra_fiq_debugger {
36 struct fiq_debugger_pdata pdata;
37 void __iomem *debug_port_base;
38 bool break_seen;
39};
40
41static inline void tegra_write(struct tegra_fiq_debugger *t,
42 unsigned int val, unsigned int off)
43{
44 __raw_writeb(val, t->debug_port_base + off * 4);
45}
46
47static inline unsigned int tegra_read(struct tegra_fiq_debugger *t,
48 unsigned int off)
49{
50 return __raw_readb(t->debug_port_base + off * 4);
51}
52
53static inline unsigned int tegra_read_lsr(struct tegra_fiq_debugger *t)
54{
55 unsigned int lsr;
56
57 lsr = tegra_read(t, UART_LSR);
58 if (lsr & UART_LSR_BI)
59 t->break_seen = true;
60
61 return lsr;
62}
63
64static int debug_port_init(struct platform_device *pdev)
65{
66 struct tegra_fiq_debugger *t;
67 t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
68
69 if (tegra_read(t, UART_LSR) & UART_LSR_DR)
70 (void)tegra_read(t, UART_RX);
71 /* enable rx and lsr interrupt */
72 tegra_write(t, UART_IER_RLSI | UART_IER_RDI, UART_IER);
73 /* interrupt on every character */
74 tegra_write(t, 0, UART_IIR);
75
76 return 0;
77}
78
79static int debug_getc(struct platform_device *pdev)
80{
81 unsigned int lsr;
82 struct tegra_fiq_debugger *t;
83 t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
84
85 lsr = tegra_read_lsr(t);
86
87 if (lsr & UART_LSR_BI || t->break_seen) {
88 t->break_seen = false;
89 return FIQ_DEBUGGER_BREAK;
90 }
91
92 if (lsr & UART_LSR_DR)
93 return tegra_read(t, UART_RX);
94
95 return FIQ_DEBUGGER_NO_CHAR;
96}
97
98static void debug_putc(struct platform_device *pdev, unsigned int c)
99{
100 struct tegra_fiq_debugger *t;
101 t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
102
103 while (!(tegra_read_lsr(t) & UART_LSR_THRE))
104 cpu_relax();
105
106 tegra_write(t, c, UART_TX);
107}
108
109static void debug_flush(struct platform_device *pdev)
110{
111 struct tegra_fiq_debugger *t;
112 t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
113
114 while (!(tegra_read_lsr(t) & UART_LSR_TEMT))
115 cpu_relax();
116}
117
118static void fiq_enable(struct platform_device *pdev, unsigned int irq, bool on)
119{
120 if (on)
121 tegra_fiq_enable(irq);
122 else
123 tegra_fiq_disable(irq);
124}
125
126static int tegra_fiq_debugger_id;
127
128void tegra_serial_debug_init(unsigned int base, int irq,
129 struct clk *clk, int signal_irq, int wakeup_irq)
130{
131 struct tegra_fiq_debugger *t;
132 struct platform_device *pdev;
133 struct resource *res;
134 int res_count;
135
136 t = kzalloc(sizeof(struct tegra_fiq_debugger), GFP_KERNEL);
137 if (!t) {
138 pr_err("Failed to allocate for fiq debugger\n");
139 return;
140 }
141
142 t->pdata.uart_init = debug_port_init;
143 t->pdata.uart_getc = debug_getc;
144 t->pdata.uart_putc = debug_putc;
145 t->pdata.uart_flush = debug_flush;
146 t->pdata.fiq_enable = fiq_enable;
147
148 t->debug_port_base = ioremap(base, PAGE_SIZE);
149 if (!t->debug_port_base) {
150 pr_err("Failed to ioremap for fiq debugger\n");
151 goto out1;
152 }
153
154 res = kzalloc(sizeof(struct resource) * 3, GFP_KERNEL);
155 if (!res) {
156 pr_err("Failed to alloc fiq debugger resources\n");
157 goto out2;
158 }
159
160 pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
161 if (!pdev) {
162 pr_err("Failed to alloc fiq debugger platform device\n");
163 goto out3;
164 };
165
166 res[0].flags = IORESOURCE_IRQ;
167 res[0].start = irq;
168 res[0].end = irq;
169 res[0].name = "fiq";
170
171 res[1].flags = IORESOURCE_IRQ;
172 res[1].start = signal_irq;
173 res[1].end = signal_irq;
174 res[1].name = "signal";
175 res_count = 2;
176
177 if (wakeup_irq >= 0) {
178 res[2].flags = IORESOURCE_IRQ;
179 res[2].start = wakeup_irq;
180 res[2].end = wakeup_irq;
181 res[2].name = "wakeup";
182 res_count++;
183 }
184
185 pdev->name = "fiq_debugger";
186 pdev->id = tegra_fiq_debugger_id++;
187 pdev->dev.platform_data = &t->pdata;
188 pdev->resource = res;
189 pdev->num_resources = res_count;
190
191 if (platform_device_register(pdev)) {
192 pr_err("Failed to register fiq debugger\n");
193 goto out4;
194 }
195
196 return;
197
198out4:
199 kfree(pdev);
200out3:
201 kfree(res);
202out2:
203 iounmap(t->debug_port_base);
204out1:
205 kfree(t);
206}