Merge remote branch 'tegra/linux-tegra-2.6.36' into android-tegra-2.6.36
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-tegra / tegra_fiq_debugger.c
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
35 #include <mach/legacy_irq.h>
36
37 struct tegra_fiq_debugger {
38         struct fiq_debugger_pdata pdata;
39         void __iomem *debug_port_base;
40         bool break_seen;
41 };
42
43 static inline void tegra_write(struct tegra_fiq_debugger *t,
44         unsigned int val, unsigned int off)
45 {
46         __raw_writeb(val, t->debug_port_base + off * 4);
47 }
48
49 static inline unsigned int tegra_read(struct tegra_fiq_debugger *t,
50         unsigned int off)
51 {
52         return __raw_readb(t->debug_port_base + off * 4);
53 }
54
55 static inline unsigned int tegra_read_lsr(struct tegra_fiq_debugger *t)
56 {
57         unsigned int lsr;
58
59         lsr = tegra_read(t, UART_LSR);
60         if (lsr & UART_LSR_BI)
61                 t->break_seen = true;
62
63         return lsr;
64 }
65
66 static int debug_port_init(struct platform_device *pdev)
67 {
68         struct tegra_fiq_debugger *t;
69         t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
70
71         if (tegra_read(t, UART_LSR) & UART_LSR_DR)
72                 (void)tegra_read(t, UART_RX);
73         /* enable rx and lsr interrupt */
74         tegra_write(t, UART_IER_RLSI | UART_IER_RDI, UART_IER);
75         /* interrupt on every character */
76         tegra_write(t, 0, UART_IIR);
77
78         return 0;
79 }
80
81 static int debug_getc(struct platform_device *pdev)
82 {
83         unsigned int lsr;
84         struct tegra_fiq_debugger *t;
85         t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
86
87         lsr = tegra_read_lsr(t);
88
89         if (lsr & UART_LSR_BI || t->break_seen) {
90                 t->break_seen = false;
91                 return FIQ_DEBUGGER_BREAK;
92         }
93
94         if (lsr & UART_LSR_DR)
95                 return tegra_read(t, UART_RX);
96
97         return FIQ_DEBUGGER_NO_CHAR;
98 }
99
100 static void debug_putc(struct platform_device *pdev, unsigned int c)
101 {
102         struct tegra_fiq_debugger *t;
103         t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
104
105         while (!(tegra_read_lsr(t) & UART_LSR_THRE))
106                 cpu_relax();
107
108         tegra_write(t, c, UART_TX);
109 }
110
111 static void debug_flush(struct platform_device *pdev)
112 {
113         struct tegra_fiq_debugger *t;
114         t = container_of(dev_get_platdata(&pdev->dev), typeof(*t), pdata);
115
116         while (!(tegra_read_lsr(t) & UART_LSR_TEMT))
117                 cpu_relax();
118 }
119
120 static void fiq_enable(struct platform_device *pdev, unsigned int irq, bool on)
121 {
122         if (on)
123                 tegra_fiq_enable(irq);
124         else
125                 tegra_fiq_disable(irq);
126 }
127
128 static int tegra_fiq_debugger_id;
129
130 void tegra_serial_debug_init(unsigned int base, int irq,
131                            struct clk *clk, int signal_irq, int wakeup_irq)
132 {
133         struct tegra_fiq_debugger *t;
134         struct platform_device *pdev;
135         struct resource *res;
136         int res_count;
137
138         t = kzalloc(sizeof(struct tegra_fiq_debugger), GFP_KERNEL);
139         if (!t) {
140                 pr_err("Failed to allocate for fiq debugger\n");
141                 return;
142         }
143
144         t->pdata.uart_init = debug_port_init;
145         t->pdata.uart_getc = debug_getc;
146         t->pdata.uart_putc = debug_putc;
147         t->pdata.uart_flush = debug_flush;
148         t->pdata.fiq_enable = fiq_enable;
149
150         t->debug_port_base = ioremap(base, PAGE_SIZE);
151         if (!t->debug_port_base) {
152                 pr_err("Failed to ioremap for fiq debugger\n");
153                 goto out1;
154         }
155
156         res = kzalloc(sizeof(struct resource) * 3, GFP_KERNEL);
157         if (!res) {
158                 pr_err("Failed to alloc fiq debugger resources\n");
159                 goto out2;
160         }
161
162         pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
163         if (!pdev) {
164                 pr_err("Failed to alloc fiq debugger platform device\n");
165                 goto out3;
166         };
167
168         res[0].flags = IORESOURCE_IRQ;
169         res[0].start = irq;
170         res[0].end = irq;
171         res[0].name = "fiq";
172
173         res[1].flags = IORESOURCE_IRQ;
174         res[1].start = signal_irq;
175         res[1].end = signal_irq;
176         res[1].name = "signal";
177         res_count = 2;
178
179         if (wakeup_irq >= 0) {
180                 res[2].flags = IORESOURCE_IRQ;
181                 res[2].start = wakeup_irq;
182                 res[2].end = wakeup_irq;
183                 res[2].name = "wakeup";
184                 res_count++;
185         }
186
187         pdev->name = "fiq_debugger";
188         pdev->id = tegra_fiq_debugger_id++;
189         pdev->dev.platform_data = &t->pdata;
190         pdev->resource = res;
191         pdev->num_resources = res_count;
192
193         if (platform_device_register(pdev)) {
194                 pr_err("Failed to register fiq debugger\n");
195                 goto out4;
196         }
197
198         return;
199
200 out4:
201         kfree(pdev);
202 out3:
203         kfree(res);
204 out2:
205         iounmap(t->debug_port_base);
206 out1:
207         kfree(t);
208 }