Commit 6df9d999 authored by Roman Tereshonkov's avatar Roman Tereshonkov Committed by Tony Lindgren

Support for OMAP3 SDTI (Serial Debug Trace Interface).

Signed-off-by: default avatarRoman Tereshonkov <roman.tereshonkov@nokia.com>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent a57ed579
......@@ -319,9 +319,12 @@ config INTEL_MENLOW
If unsure, say N.
config OMAP_STI
bool "STI/XTI support"
depends on ARCH_OMAP16XX || ARCH_OMAP24XX
default n
bool "Serial Trace Interface support"
depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX
default n
help
Serial Trace Interface. The protocols suported for OMAP1/2/3 are
STI/CSTI/XTIv2 correspondingly.
config OMAP_STI_CONSOLE
bool "STI console support"
......
obj-y += sti.o sti-fifo.o
ifeq ($(CONFIG_ARCH_OMAP3),y)
obj-$(CONFIG_OMAP_STI) += sdti.o
else
obj-$(CONFIG_OMAP_STI) += sti.o sti-fifo.o
obj-$(CONFIG_NET) += sti-netlink.o
endif
obj-$(CONFIG_OMAP_STI_CONSOLE) += sti-console.o
obj-$(CONFIG_NET) += sti-netlink.o
/*
* Support functions for OMAP3 SDTI (Serial Debug Tracing Interface)
*
* Copyright (C) 2008 Nokia Corporation
* Written by: Roman Tereshonkov <roman.tereshonkov@nokia.com>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/arch/sti.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#define SDTI_REVISION 0x000
#define SDTI_SYSCONFIG 0x010
#define SDTI_SYSSTATUS 0x014
#define SDTI_WINCTRL 0x024
#define SDTI_SCONFIG 0x028
#define SDTI_TESTCTRL 0x02C
#define SDTI_LOCK_ACCESS 0xFB0
#define CPU1_TRACE_EN 0x01
#define CPU2_TRACE_EN 0x02
#define EPM_BASE 0x5401D000
#define EPM_CONTROL_0 0x50
#define EPM_CONTROL_1 0x54
#define EPM_CONTROL_2 0x58
static struct clk *sdti_ck;
unsigned long sti_base, sti_channel_base, epm_base;
static DEFINE_SPINLOCK(sdti_lock);
void omap_sti_channel_write_trace(int len, int id, void *data,
unsigned int channel)
{
const u8 *tpntr = data;
spin_lock_irq(&sdti_lock);
sti_channel_writeb(id, channel);
while (len--)
sti_channel_writeb(*tpntr++, channel);
sti_channel_flush(channel);
spin_unlock_irq(&sdti_lock);
}
EXPORT_SYMBOL(omap_sti_channel_write_trace);
static void omap_sdti_reset(void)
{
int i;
sti_writel(0x02, SDTI_SYSCONFIG);
for (i = 0; i < 10000; i++)
if (sti_readl(SDTI_SYSSTATUS) & 1)
break;
if (i == 10000)
printk(KERN_WARNING "XTI: no real reset\n");
}
void init_epm(void)
{
epm_base = (unsigned long)ioremap(EPM_BASE, 256);
if (unlikely(!epm_base)) {
printk(KERN_ERR "EPM cannot be ioremapped\n");
return;
}
__raw_writel(1<<30, epm_base + EPM_CONTROL_2);
__raw_writel(0x78, epm_base + EPM_CONTROL_0);
__raw_writel(0x80000000, epm_base + EPM_CONTROL_1);
__raw_writel(1<<31 | 0x00007770, epm_base + EPM_CONTROL_2);
}
static int __init omap_sdti_init(void)
{
char buf[64];
int i;
sdti_ck = clk_get(NULL, "emu_per_alwon_ck");
if (IS_ERR(sdti_ck)) {
printk(KERN_ERR "Cannot get clk emu_per_alwon_ck\n");
return PTR_ERR(sdti_ck);
}
clk_enable(sdti_ck);
/* Init emulation pin manager */
init_epm();
omap_sdti_reset();
sti_writel(0xC5ACCE55, SDTI_LOCK_ACCESS);
/* Claim SDTI */
sti_writel(1 << 30, SDTI_WINCTRL);
i = sti_readl(SDTI_WINCTRL);
if (!(i & (1 << 30)))
printk(KERN_WARNING "SDTI: cannot claim SDTI\n");
/* 4 bits dual, fclk/3 */
sti_writel(0x43, SDTI_SCONFIG);
/* CPU1 trace enable */
sti_writel(i | CPU2_TRACE_EN, SDTI_WINCTRL);
i = sti_readl(SDTI_WINCTRL);
/* Enable SDTI */
sti_writel((1 << 31) | (i & 0x3FFFFFFF), SDTI_WINCTRL);
i = sti_readl(SDTI_REVISION);
snprintf(buf, sizeof(buf), "OMAP SDTI support loaded (HW v%u.%u)\n",
(i >> 4) & 0x0f, i & 0x0f);
printk(KERN_INFO, "%s", buf);
omap_sti_channel_write_trace(strlen(buf), 0xc3, buf, 239);
return 0;
}
static void omap_sdti_exit(void)
{
sti_writel(0, SDTI_WINCTRL);
clk_disable(sdti_ck);
clk_put(sdti_ck);
}
static int __devinit omap_sdti_probe(struct platform_device *pdev)
{
struct resource *res, *cres;
unsigned int size;
if (pdev->num_resources != 2) {
dev_err(&pdev->dev, "invalid number of resources: %d\n",
pdev->num_resources);
return -ENODEV;
}
/* SDTI base */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!res)) {
dev_err(&pdev->dev, "invalid mem resource\n");
return -ENODEV;
}
/* Channel base */
cres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (unlikely(!cres)) {
dev_err(&pdev->dev, "invalid channel mem resource\n");
return -ENODEV;
}
size = res->end - res->start;
sti_base = (unsigned long)ioremap(res->start, size);
if (unlikely(!sti_base))
return -ENODEV;
size = cres->end - cres->start;
sti_channel_base = (unsigned long)ioremap(cres->start, size);
if (unlikely(!sti_channel_base)) {
iounmap((void *)sti_base);
return -ENODEV;
}
return omap_sdti_init();
}
static int __devexit omap_sdti_remove(struct platform_device *pdev)
{
iounmap((void *)sti_channel_base);
iounmap((void *)sti_base);
iounmap((void *)epm_base);
omap_sdti_exit();
return 0;
}
static struct platform_driver omap_sdti_driver = {
.probe = omap_sdti_probe,
.remove = __devexit_p(omap_sdti_remove),
.driver = {
.name = "sti",
.owner = THIS_MODULE,
},
};
static int __init omap_sdti_module_init(void)
{
return platform_driver_register(&omap_sdti_driver);
}
static void __exit omap_sdti_module_exit(void)
{
platform_driver_unregister(&omap_sdti_driver);
}
subsys_initcall(omap_sdti_module_init);
module_exit(omap_sdti_module_exit);
MODULE_AUTHOR("Roman Tereshonkov");
MODULE_LICENSE("GPL");
......@@ -4,7 +4,7 @@
#include <asm/io.h>
/*
* STI/XTI
* STI/SDTI
*/
#define STI_REVISION 0x00
#define STI_SYSCONFIG 0x10
......@@ -38,7 +38,6 @@
#define STI_NR_IRQS 10
#define STI_IRQSTATUS_MASK 0x2ff
#define STI_PERCHANNEL_SIZE 4
#define STI_RXFIFO_EMPTY (1 << 0)
......@@ -64,6 +63,12 @@ enum {
MemDumpEn = (1 << 14), /* System memory dump */
STIEn = (1 << 15), /* Global trace enable */
};
#define STI_PERCHANNEL_SIZE 4
#define to_channel_address(channel) \
(sti_channel_base + STI_PERCHANNEL_SIZE * (channel))
#elif defined(CONFIG_ARCH_OMAP2)
/* XTI interrupt bits */
......@@ -110,6 +115,15 @@ enum {
#define STI_RXFIFO_EMPTY (1 << 8)
#define to_channel_address(channel) \
(sti_channel_base + STI_PERCHANNEL_SIZE * (channel))
#elif defined(CONFIG_ARCH_OMAP3)
#define STI_PERCHANNEL_SIZE 0x1000
#define to_channel_address(channel) \
(sti_channel_base + STI_PERCHANNEL_SIZE * (channel) + 0x800)
#endif
/* arch/arm/plat-omap/sti/sti.c */
......@@ -139,9 +153,6 @@ static inline void sti_writel(unsigned long data, unsigned long reg)
__raw_writel(data, sti_base + reg);
}
#define to_channel_address(channel) \
(sti_channel_base + STI_PERCHANNEL_SIZE * (channel))
static inline void sti_channel_writeb(unsigned char data, unsigned int channel)
{
__raw_writeb(data, to_channel_address(channel));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment