]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/misc/sti/sdti.c
Tiny fix. No comma after KERN_INFO.
[linux-2.6-omap-h63xx.git] / drivers / misc / sti / sdti.c
1 /*
2  * Support functions for OMAP3 SDTI (Serial Debug Tracing Interface)
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Written by: Roman Tereshonkov <roman.tereshonkov@nokia.com>
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  */
11 #include <linux/init.h>
12 #include <linux/err.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/spinlock.h>
16 #include <linux/interrupt.h>
17 #include <linux/platform_device.h>
18 #include <linux/clk.h>
19 #include <asm/arch/sti.h>
20 #include <asm/byteorder.h>
21 #include <asm/io.h>
22
23 #define SDTI_REVISION           0x000
24 #define SDTI_SYSCONFIG          0x010
25 #define SDTI_SYSSTATUS          0x014
26 #define SDTI_WINCTRL            0x024
27 #define SDTI_SCONFIG            0x028
28 #define SDTI_TESTCTRL           0x02C
29 #define SDTI_LOCK_ACCESS        0xFB0
30
31 #define CPU1_TRACE_EN           0x01
32 #define CPU2_TRACE_EN           0x02
33
34 #define EPM_BASE                0x5401D000
35 #define EPM_CONTROL_0           0x50
36 #define EPM_CONTROL_1           0x54
37 #define EPM_CONTROL_2           0x58
38
39 static struct clk *sdti_ck;
40 unsigned long sti_base, sti_channel_base, epm_base;
41 static DEFINE_SPINLOCK(sdti_lock);
42
43 void omap_sti_channel_write_trace(int len, int id, void *data,
44                                 unsigned int channel)
45 {
46         const u8 *tpntr = data;
47
48         spin_lock_irq(&sdti_lock);
49
50         sti_channel_writeb(id, channel);
51         while (len--)
52                 sti_channel_writeb(*tpntr++, channel);
53         sti_channel_flush(channel);
54
55         spin_unlock_irq(&sdti_lock);
56 }
57 EXPORT_SYMBOL(omap_sti_channel_write_trace);
58
59 static void omap_sdti_reset(void)
60 {
61         int i;
62
63         sti_writel(0x02, SDTI_SYSCONFIG);
64
65         for (i = 0; i < 10000; i++)
66                 if (sti_readl(SDTI_SYSSTATUS) & 1)
67                         break;
68         if (i == 10000)
69                 printk(KERN_WARNING "XTI: no real reset\n");
70 }
71
72 void init_epm(void)
73 {
74         epm_base = (unsigned long)ioremap(EPM_BASE, 256);
75         if (unlikely(!epm_base)) {
76                 printk(KERN_ERR "EPM cannot be ioremapped\n");
77                 return;
78         }
79
80         __raw_writel(1<<30, epm_base + EPM_CONTROL_2);
81         __raw_writel(0x78, epm_base + EPM_CONTROL_0);
82         __raw_writel(0x80000000, epm_base + EPM_CONTROL_1);
83         __raw_writel(1<<31 | 0x00007770, epm_base + EPM_CONTROL_2);
84 }
85
86 static int __init omap_sdti_init(void)
87 {
88         char buf[64];
89         int i;
90
91         sdti_ck = clk_get(NULL, "emu_per_alwon_ck");
92         if (IS_ERR(sdti_ck)) {
93                 printk(KERN_ERR "Cannot get clk emu_per_alwon_ck\n");
94                 return PTR_ERR(sdti_ck);
95         }
96         clk_enable(sdti_ck);
97
98         /* Init emulation pin manager */
99         init_epm();
100
101         omap_sdti_reset();
102         sti_writel(0xC5ACCE55, SDTI_LOCK_ACCESS);
103
104         /* Claim SDTI */
105         sti_writel(1 << 30, SDTI_WINCTRL);
106         i = sti_readl(SDTI_WINCTRL);
107         if (!(i & (1 << 30)))
108                 printk(KERN_WARNING "SDTI: cannot claim SDTI\n");
109
110         /* 4 bits dual, fclk/3 */
111         sti_writel(0x43, SDTI_SCONFIG);
112
113         /* CPU1 trace enable */
114         sti_writel(i | CPU2_TRACE_EN, SDTI_WINCTRL);
115         i = sti_readl(SDTI_WINCTRL);
116
117         /* Enable SDTI */
118         sti_writel((1 << 31) | (i & 0x3FFFFFFF), SDTI_WINCTRL);
119
120         i = sti_readl(SDTI_REVISION);
121         snprintf(buf, sizeof(buf), "OMAP SDTI support loaded (HW v%u.%u)\n",
122                 (i >> 4) & 0x0f, i & 0x0f);
123         printk(KERN_INFO "%s", buf);
124         omap_sti_channel_write_trace(strlen(buf), 0xc3, buf, 239);
125
126         return 0;
127 }
128
129 static void omap_sdti_exit(void)
130 {
131         sti_writel(0, SDTI_WINCTRL);
132         clk_disable(sdti_ck);
133         clk_put(sdti_ck);
134 }
135
136 static int __devinit omap_sdti_probe(struct platform_device *pdev)
137 {
138         struct resource *res, *cres;
139         unsigned int size;
140
141         if (pdev->num_resources != 2) {
142                 dev_err(&pdev->dev, "invalid number of resources: %d\n",
143                         pdev->num_resources);
144                 return -ENODEV;
145         }
146
147         /* SDTI base */
148         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
149         if (unlikely(!res)) {
150                 dev_err(&pdev->dev, "invalid mem resource\n");
151                 return -ENODEV;
152         }
153
154         /* Channel base */
155         cres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
156         if (unlikely(!cres)) {
157                 dev_err(&pdev->dev, "invalid channel mem resource\n");
158                 return -ENODEV;
159         }
160
161         size = res->end - res->start;
162         sti_base = (unsigned long)ioremap(res->start, size);
163         if (unlikely(!sti_base))
164                 return -ENODEV;
165
166         size = cres->end - cres->start;
167         sti_channel_base = (unsigned long)ioremap(cres->start, size);
168         if (unlikely(!sti_channel_base)) {
169                 iounmap((void *)sti_base);
170                 return -ENODEV;
171         }
172
173         return omap_sdti_init();
174 }
175
176 static int __devexit omap_sdti_remove(struct platform_device *pdev)
177 {
178         iounmap((void *)sti_channel_base);
179         iounmap((void *)sti_base);
180         iounmap((void *)epm_base);
181         omap_sdti_exit();
182
183         return 0;
184 }
185
186 static struct platform_driver omap_sdti_driver = {
187         .probe          = omap_sdti_probe,
188         .remove         = __devexit_p(omap_sdti_remove),
189         .driver         = {
190                 .name   = "sti",
191                 .owner  = THIS_MODULE,
192         },
193 };
194
195 static int __init omap_sdti_module_init(void)
196 {
197         return platform_driver_register(&omap_sdti_driver);
198 }
199
200 static void __exit omap_sdti_module_exit(void)
201 {
202         platform_driver_unregister(&omap_sdti_driver);
203 }
204 subsys_initcall(omap_sdti_module_init);
205 module_exit(omap_sdti_module_exit);
206
207 MODULE_AUTHOR("Roman Tereshonkov");
208 MODULE_LICENSE("GPL");