upload tizen1.0 source
[kernel/linux-2.6.36.git] / arch / arm / mach-s5pv310 / dev-fiqdbg.c
1 /* 
2  * linux/arch/arm/mach-s5pv310/dev-fiqdbg.c
3  *
4  * Copyright (C) 2010 Google, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/platform_device.h>
17 #include <linux/delay.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/irq.h>
20 #include <linux/sysdev.h>
21
22 #include <asm/hardware/vic.h>
23 #include <asm/fiq_debugger.h>
24
25 #include <mach/irqs.h>
26 #include <mach/map.h>
27 #include <plat/regs-serial.h>
28
29 static void *s5pv310_fiqdbg_get_base(struct platform_device *pdev)
30 {
31         return S5P_VA_UART0 + S3C_UART_OFFSET * pdev->id;
32 }
33
34 static unsigned int s5pv310_fiqdbg_tx_empty(void *base)
35 {
36         unsigned long ufstat = readl(base + S3C2410_UFSTAT);
37
38         return !(ufstat & (S5PV210_UFSTAT_TXMASK | S5PV210_UFSTAT_TXFULL));
39 }
40
41 static void s5pv310_fiqdbg_wait_for_tx_empty(void *base)
42 {
43         unsigned int tmout = 10000;
44
45         while (true) {
46                 if (s5pv310_fiqdbg_tx_empty(base))
47                         return;
48                 if (--tmout == 0)
49                         break;
50                 udelay(1);
51         }
52 }
53
54 static int s5pv310_fiqdbg_uart_getc(struct platform_device *pdev)
55 {
56         void *base = s5pv310_fiqdbg_get_base(pdev);
57         unsigned int ufstat;
58
59         if (readl(base + S3C2410_UERSTAT) & S3C2410_UERSTAT_BREAK)
60                 return FIQ_DEBUGGER_BREAK;
61
62         ufstat = readl(base + S3C2410_UFSTAT);
63         if (!(ufstat & (S5PV210_UFSTAT_RXMASK | S5PV210_UFSTAT_RXFULL)))
64                 return FIQ_DEBUGGER_NO_CHAR;
65         return readb(base + S3C2410_URXH);
66 }
67
68 static void s5pv310_fiqdbg_uart_putc(struct platform_device *pdev,
69                 unsigned int c)
70 {
71         void *base = s5pv310_fiqdbg_get_base(pdev);
72         s5pv310_fiqdbg_wait_for_tx_empty(base);
73         writeb(c, base + S3C2410_UTXH);
74         if (c == 10) {
75                 s5pv310_fiqdbg_wait_for_tx_empty(base);
76                 writeb(13, base + S3C2410_UTXH);
77         }
78         s5pv310_fiqdbg_wait_for_tx_empty(base);
79 }
80
81 static void fiq_enable(struct platform_device *pdev,
82                 unsigned int fiq, bool enabled)
83 {
84         struct irq_chip *chip = get_irq_chip(fiq);
85
86         if (enabled)
87                 chip->unmask(fiq);
88         else
89                 chip->mask(fiq);
90 }
91
92 static void fiq_ack(struct platform_device *pdev, unsigned int fiq)
93 {
94         void *base = s5pv310_fiqdbg_get_base(pdev);
95         writel(0x7, base + S5P_UINTP);
96 }
97
98 static int s5pv310_fiqdbg_uart_init(struct platform_device *pdev)
99 {
100         void *base = s5pv310_fiqdbg_get_base(pdev);
101
102         writel(0x245, base + S3C2410_UCON);
103         writel(0x3, base + S3C2410_ULCON);
104         /* 115200 */
105         writel(0x35, base + S3C2410_UBRDIV);
106         writel(0x4, base + S3C2443_DIVSLOT);
107         writel(0xc, base + S5P_UINTM);
108         writel(0xf, base + S5P_UINTP);
109
110         return 0;
111 }
112
113 static struct fiq_debugger_pdata s5pv310_fiqdbg_pdata = {
114         .uart_init              = s5pv310_fiqdbg_uart_init,
115         .uart_resume            = s5pv310_fiqdbg_uart_init,
116         .uart_getc              = s5pv310_fiqdbg_uart_getc,
117         .uart_putc              = s5pv310_fiqdbg_uart_putc,
118         .fiq_enable             = fiq_enable,
119         .fiq_ack                = fiq_ack,
120 };
121
122 #define DEFINE_FIQDBG_UART(uart) \
123 static struct resource s5pv310_fiqdbg_uart##uart##_resource[] = { \
124         { \
125                 .start = IRQ_UART##uart, \
126                 .end   = IRQ_UART##uart, \
127                 .name  = "fiq", \
128                 .flags = IORESOURCE_IRQ, \
129         }, \
130         { \
131                 .start = IRQ_NR_BOARD-uart, \
132                 .end   = IRQ_NR_BOARD-uart, \
133                 .name  = "signal", \
134                 .flags = IORESOURCE_IRQ, \
135         }, \
136 }; \
137 struct platform_device s5pv310_device_fiqdbg_uart##uart = { \
138         .name             = "fiq_debugger", \
139         .id               = uart, \
140         .num_resources    = ARRAY_SIZE(s5pv310_fiqdbg_uart##uart##_resource), \
141         .resource         = s5pv310_fiqdbg_uart##uart##_resource, \
142         .dev = { \
143                 .platform_data = &s5pv310_fiqdbg_pdata, \
144         }, \
145 }
146
147 DEFINE_FIQDBG_UART(0);
148 DEFINE_FIQDBG_UART(1);
149 DEFINE_FIQDBG_UART(2);
150 DEFINE_FIQDBG_UART(3);