2 * linux/arch/arm/mach-s5pv310/dev-fiqdbg.c
4 * Copyright (C) 2010 Google, Inc.
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.
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.
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>
22 #include <asm/hardware/vic.h>
23 #include <asm/fiq_debugger.h>
25 #include <mach/irqs.h>
27 #include <plat/regs-serial.h>
29 static void *s5pv310_fiqdbg_get_base(struct platform_device *pdev)
31 return S5P_VA_UART0 + S3C_UART_OFFSET * pdev->id;
34 static unsigned int s5pv310_fiqdbg_tx_empty(void *base)
36 unsigned long ufstat = readl(base + S3C2410_UFSTAT);
38 return !(ufstat & (S5PV210_UFSTAT_TXMASK | S5PV210_UFSTAT_TXFULL));
41 static void s5pv310_fiqdbg_wait_for_tx_empty(void *base)
43 unsigned int tmout = 10000;
46 if (s5pv310_fiqdbg_tx_empty(base))
54 static int s5pv310_fiqdbg_uart_getc(struct platform_device *pdev)
56 void *base = s5pv310_fiqdbg_get_base(pdev);
59 if (readl(base + S3C2410_UERSTAT) & S3C2410_UERSTAT_BREAK)
60 return FIQ_DEBUGGER_BREAK;
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);
68 static void s5pv310_fiqdbg_uart_putc(struct platform_device *pdev,
71 void *base = s5pv310_fiqdbg_get_base(pdev);
72 s5pv310_fiqdbg_wait_for_tx_empty(base);
73 writeb(c, base + S3C2410_UTXH);
75 s5pv310_fiqdbg_wait_for_tx_empty(base);
76 writeb(13, base + S3C2410_UTXH);
78 s5pv310_fiqdbg_wait_for_tx_empty(base);
81 static void fiq_enable(struct platform_device *pdev,
82 unsigned int fiq, bool enabled)
84 struct irq_chip *chip = get_irq_chip(fiq);
92 static void fiq_ack(struct platform_device *pdev, unsigned int fiq)
94 void *base = s5pv310_fiqdbg_get_base(pdev);
95 writel(0x7, base + S5P_UINTP);
98 static int s5pv310_fiqdbg_uart_init(struct platform_device *pdev)
100 void *base = s5pv310_fiqdbg_get_base(pdev);
102 writel(0x245, base + S3C2410_UCON);
103 writel(0x3, base + S3C2410_ULCON);
105 writel(0x35, base + S3C2410_UBRDIV);
106 writel(0x4, base + S3C2443_DIVSLOT);
107 writel(0xc, base + S5P_UINTM);
108 writel(0xf, base + S5P_UINTP);
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,
122 #define DEFINE_FIQDBG_UART(uart) \
123 static struct resource s5pv310_fiqdbg_uart##uart##_resource[] = { \
125 .start = IRQ_UART##uart, \
126 .end = IRQ_UART##uart, \
128 .flags = IORESOURCE_IRQ, \
131 .start = IRQ_NR_BOARD-uart, \
132 .end = IRQ_NR_BOARD-uart, \
134 .flags = IORESOURCE_IRQ, \
137 struct platform_device s5pv310_device_fiqdbg_uart##uart = { \
138 .name = "fiq_debugger", \
140 .num_resources = ARRAY_SIZE(s5pv310_fiqdbg_uart##uart##_resource), \
141 .resource = s5pv310_fiqdbg_uart##uart##_resource, \
143 .platform_data = &s5pv310_fiqdbg_pdata, \
147 DEFINE_FIQDBG_UART(0);
148 DEFINE_FIQDBG_UART(1);
149 DEFINE_FIQDBG_UART(2);
150 DEFINE_FIQDBG_UART(3);