* [Xenomai-help] Porting I-Pipe for new ARM board
@ 2009-11-03 15:00 Wael Showair
2009-11-03 15:13 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Wael Showair @ 2009-11-03 15:00 UTC (permalink / raw)
To: Xenomai-help; +Cc: didenkos
[-- Attachment #1: Type: text/plain, Size: 15806 bytes --]
Hi All,
i have TS-7800 board based on Marvell 88F5182 processor core. Unfortunately it is not supported by I-Pipe patch so according to the following link:
http://www.xenomai.org/index.php/I-pipe:ArmPorting
And with aid of this forum thread:
http://www.mail-archive.com/xenomai-help@gna.org/msg09486.html
I have now reached to the same error:
patched Linux is starting to boot as original kernel
and it hangs right after line
"ata2: SATA max UDMA/133 irq 29"
here is the time.c file that i have edited:
************************************************************************************
/*
* arch/arm/plat-orion/time.c
*
* Marvell Orion SoC timer handling.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*
* Timer 0 is used as free-running clocksource, while timer 1 is
* used as clock_event_device.
*/
#include <linux/kernel.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/mach/time.h>
#include <mach/hardware.h>
/*
* Number of timer ticks per jiffy.
*/
static u32 ticks_per_jiffy;
/*
* Timer block registers.
*/
#define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000)
#define TIMER0_EN 0x0001
#define TIMER0_RELOAD_EN 0x0002
#define TIMER1_EN 0x0004
#define TIMER1_RELOAD_EN 0x0008
#define TIMER0_RELOAD (TIMER_VIRT_BASE + 0x0010)
#define TIMER0_VAL (TIMER_VIRT_BASE + 0x0014)
#define TIMER1_RELOAD (TIMER_VIRT_BASE + 0x0018)
#define TIMER1_VAL (TIMER_VIRT_BASE + 0x001c)
#ifdef CONFIG_IPIPE
#define MIN_TIMER1_DELTA 1
#ifdef CONFIG_NO_IDLE_HZ
#error "dynamic tick timer not yet supported with IPIPE"
#endif /* CONFIG_NO_IDLE_HZ */
/* The implementation is instead of io_v2p since the addresses are virtual addresses*/
//# define __PREG(x) io_v2p(x)
/* #define __REG(x) (*(volatile unsigned long *)x)
#define OSCR_0 __REG(TIMER0_VAL)
*/
/*
*IRQ number of hardware timer
*According to the board manual, tables 59 & 61
*the timer0,1 interrupts are set in Local to System Bridge Interrupt Cause Register
*which in turn set bit number zero in the Main Interrupt Cause Register
*so the __ipipe_mach_timerint variable will be set to zero or one
*/
#define IRQ_MV88FXX_ORION_BRIDGE 0
int __ipipe_mach_timerint = IRQ_MV88FXX_ORION_BRIDGE;
EXPORT_SYMBOL(__ipipe_mach_timerint);
/*TODO: what is this value really represents? is it always intialized by zero?
* Initialized to 0, it became non zero when the hardware timer is handled by
* Xenomai.
*/
int __ipipe_mach_timerstolen = 0;
EXPORT_SYMBOL(__ipipe_mach_timerstolen);
/*
* Count of hardware timer ticks between two timer interrupts, same thing as
* the LATCH constant.
*/
unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
EXPORT_SYMBOL(__ipipe_mach_ticks_per_jiffy);
static int orion_timer_initialized = 0;
/* this union represents the shared tsc area */
union tsc_reg {
#ifdef __BIG_ENDIAN
struct {
unsigned long high;
unsigned long low;
};
#else /* __LITTLE_ENDIAN */
struct {
unsigned long low;
unsigned long high;
};
#endif /* __LITTLE_ENDIAN */
unsigned long long full;
};
#ifdef CONFIG_SMP
static union tsc_reg orion_tsc[NR_CPUS];
void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
{
info->type = IPIPE_TSC_TYPE_NONE;
}
#else /* !CONFIG_SMP */
static union tsc_reg *orion_tsc;
#endif /* !CONFIG_SMP */
static void ipipe_mach_update_tsc(void);
#endif /* CONFIG_IPIPE */
/*
* Clocksource handling.
*/
static cycle_t orion_clksrc_read(void)
{
return 0xffffffff - readl(TIMER0_VAL);
}
static struct clocksource orion_clksrc = {
.name = "orion_clocksource",
.shift = 20,
.rating = 300,
.read = orion_clksrc_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/*
* Clockevent handling.
*/
static int
orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
{
unsigned long flags;
u32 u;
if (delta == 0)
return -ETIME;
local_irq_save(flags);
/*
* Clear and enable clockevent timer interrupt.
*/
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
u = readl(BRIDGE_MASK);
u |= BRIDGE_INT_TIMER1;
writel(u, BRIDGE_MASK);
/*
* Setup new clockevent timer value.
*/
writel(delta, TIMER1_VAL);
/*
* Enable the timer.
*/
u = readl(TIMER_CTRL);
u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
writel(u, TIMER_CTRL);
local_irq_restore(flags);
return 0;
}
static void
orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
{
unsigned long flags;
u32 u;
local_irq_save(flags);
if (mode == CLOCK_EVT_MODE_PERIODIC) {
/*
* Setup timer to fire at 1/HZ intervals.
*/
writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
writel(ticks_per_jiffy - 1, TIMER1_VAL);
/*
* Enable timer interrupt.
*/
u = readl(BRIDGE_MASK);
writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
/*
* Enable timer.
*/
u = readl(TIMER_CTRL);
writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
} else {
/*
* Disable timer.
*/
u = readl(TIMER_CTRL);
writel(u & ~TIMER1_EN, TIMER_CTRL);
/*
* Disable timer interrupt.
*/
u = readl(BRIDGE_MASK);
writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
/*
* ACK pending timer interrupt.
*/
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
}
local_irq_restore(flags);
}
static struct clock_event_device orion_clkevt = {
.name = "orion_tick",
.features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
.shift = 32,
.rating = 300,
.set_next_event = orion_clkevt_next_event,
.set_mode = orion_clkevt_mode,
};
static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
{
#ifndef CONFIG_IPIPE
/*
* ACK timer interrupt and call event handler.
*/
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
#else
ipipe_mach_update_tsc();
#endif /* CONFIG_IPIPE */
/* hrtimer_interrupt is the event handle of the clock event device "orion_tick", i got by cat /proc/timer_list
* it is defined in krnl_src/kernel/hrtimer.c
* which does not use timer_tick in a while loop so the timer interrupt function is gonna be let as it is.
*/
orion_clkevt.event_handler(&orion_clkevt);
return IRQ_HANDLED;
}
static struct irqaction orion_timer_irq = {
.name = "orion_tick",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = orion_timer_interrupt
};
void __init orion_time_init(unsigned int irq, unsigned int tclk)
{
u32 u;
#ifdef CONFIG_IPIPE
#ifndef CONFIG_SMP
orion_tsc = (union tsc_reg *) __ipipe_tsc_area;
barrier();
#endif /* CONFIG_SMP */
orion_timer_initialized = 1;
#endif /* CONFIG_IPIPE */
ticks_per_jiffy = (tclk + HZ/2) / HZ;
/*
* Setup free-running clocksource timer (interrupts
* disabled.) using TIMER0
*/
writel(0xffffffff, TIMER0_VAL);
writel(0xffffffff, TIMER0_RELOAD);
u = readl(BRIDGE_MASK);
writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
u = readl(TIMER_CTRL);
writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
clocksource_register(&orion_clksrc);
/*
* Setup clockevent timer (interrupt-driven.) using TIMER1
*/
setup_irq(irq, &orion_timer_irq);
orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
orion_clkevt.max_delta_ns = clockevent_delta2ns(0xfffffffe, &orion_clkevt);
orion_clkevt.min_delta_ns = clockevent_delta2ns(MIN_TIMER1_DELTA, &orion_clkevt);
orion_clkevt.cpumask = cpumask_of(0);
clockevents_register_device(&orion_clkevt);
}
#ifdef CONFIG_IPIPE
/*
* Acknowledge the hardware timer interrupt at hardware timer level.
*/
void __ipipe_mach_acktimer(void)
{
/*
* ACK timer interrupt and call event handler.
*/
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
}
/*
* __ipipe_mach_get_tsc
* High resolution counter, or its emulation using the hardware decrementer or free-running counter
*/
notrace unsigned long long __ipipe_mach_get_tsc(void)
{
if (likely(orion_timer_initialized)) {
union tsc_reg *local_tsc, result;
unsigned long stamp;
local_tsc = orion_tsc;
__asm__ ("ldmia %1, %M0\n":
"=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
barrier();
stamp = readl(TIMER0_VAL);
if (unlikely(stamp < result.low))
/* 32 bit counter wrapped, increment high word. */
result.high++;
result.low = stamp;
return result.full;
}
return 0;
}
EXPORT_SYMBOL(__ipipe_mach_get_tsc);
/*
* __ipipe_mach_get_tscinfo
* export the tsc to user-space
*/
void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
{
/* info->type indicates that the tsc is based on a free-running counter */
info->type = IPIPE_TSC_TYPE_FREERUNNING;
/* info->u.fr.counter is set to the PHYSICAL address of the free-running counter
since we are using the free-running counter (i.e. TIMER0) for TSC emulation */
info->u.fr.counter = (unsigned *) TIMER0_VAL;
/* info->u.fr.mask is a mask indicating which bits in the free-running counter are valid */
info->u.fr.mask = 0xffffffff;
/* info->u.fr.tsc is a pointer to the shared tsc area */
info->u.fr.tsc = &orion_tsc->full;
}
EXPORT_SYMBOL(__ipipe_mach_get_tscinfo);
/* __ipipe_mach_get_dec
* Returns the count of hardware timer ticks remaining before the next timer interrupt.
*/
unsigned long __ipipe_mach_get_dec(void)
{
/* return OSMR0 - OSCR; */
/* since we are using clockevent timer(i.e. TIMER1) for hardware timer */
return (readl(TIMER1_RELOAD) - readl(TIMER1_VAL));
}
EXPORT_SYMBOL(__ipipe_mach_get_dec);
/*
* __ipipe_mach_set_dec
* Program the hardware timer to trig an interrupt in 'delay' hardware timer ticks.
*/
void __ipipe_mach_set_dec(unsigned long delay)
{
u32 u;
/* check if the required delay is greater than the min threshold ticks (delta) of TIMER1 */
if (delay > MIN_TIMER1_DELTA) {
unsigned long flags;
local_irq_save(flags);
/* load the relaod register of TIMER1 with the ner value */
writel(delay + readl(TIMER1_VAL), TIMER1_RELOAD);
/*
* Clear and enable clockevent timer interrupt.
*/
writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
u = readl(BRIDGE_MASK);
u |= BRIDGE_INT_TIMER1;
writel(u, BRIDGE_MASK);
local_irq_restore(flags);
} else
/* generate the interrupt now */
ipipe_trigger_irq(IRQ_MV88FXX_ORION_BRIDGE);
}
EXPORT_SYMBOL(__ipipe_mach_set_dec);
/*
* __ipipe_mach_release_timer
*/
void __ipipe_mach_release_timer(void)
{
orion_clkevt_mode(orion_clkevt.mode, &orion_clkevt);
if (orion_clkevt.mode == CLOCK_EVT_MODE_ONESHOT)
orion_clkevt_next_event(LATCH, &orion_clkevt);
}
int __ipipe_check_tickdev(const char *devname)
{
return !strcmp(devname, orion_clkevt.name);
}
/*
* ipipe_mach_update_tsc
* If the free-running counter wraps fast, the best place to do this is __ipipe_mach_acktimer.
* If the free-running counter wraps slowly, doing this from Linux timer interrupt will reduce the timer interrupt latency.
* Assume the implementation wraps slowly
*/
static void ipipe_mach_update_tsc(void)
{
union tsc_reg *local_tsc;
unsigned long stamp, flags;
local_irq_save_hw(flags);
local_tsc = &orion_tsc[ipipe_processor_id()];
/*local_tsc = orion_tsc;*/
/* since we are using the free-running counter (i.e. TIMER0) for TSC emulation */
stamp = readl(TIMER0_VAL);
if (unlikely(stamp < local_tsc->low))
/* 32 bit counter wrapped, increment high word. */
local_tsc->high++;
local_tsc->low = stamp;
local_irq_restore_hw(flags);
}
#endif /* CONFIG_IPIPE */
************************************************************************************
And here is the kernel booting output:
####################################################################################
Uncompressing Linux............................................................................................................................ done, bootin.
Linux version 2.6.29.5-xenomai (root@domain.hid) (gcc version 4.3.2 (Debian 4.3.2-1.1) ) #14 PREEMPT Tue Nov 3 16:11:38 EST 2009
CPU: Feroceon [41069260] revision 0 (ARMv5TEJ), cr=b0053177
CPU: VIVT data cache, VIVT instruction cache
Machine: Technologic Systems TS-78xx SBC
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 32512
Kernel command line: root=/dev/nfs rw nfsroot=172.25.25.100:/home/wael/LTE/exports/emdebian-rootfs ip=dhcp console=ttyS0,115200
PID hash table entries: 512 (order: 9, 2048 bytes)
I-pipe 1.13-03: pipeline enabled.
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 128MB = 128MB total
Memory: 121472KB available (3584K code, 452K data, 148K init)
SLUB: Genslabs=12, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
Calibrating delay loop... 331.77 BogoMIPS (lpj=1658880)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 520 bytes
NET: Registered protocol family 16
Orion ID: MV88F5182-A2. TCLK=166666667.
TS-78xx Info: FPGA rev=05, Board Magic=00b480, JP1=1, JP2=1
TS-78xx RTC not detected or enabled
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
NET: Registered protocol family 1
checking if image is initramfs...it isn't (bad gzip magic numbers); looks like an initrd
Freeing initrd memory: 4096K
NetWinder Floating Point Emulator V0.97 (double precision)
I-pipe: Domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.
JFFS2 version 2.2. (NAND) �© 2001-2006 Red Hat, Inc.
msgmni has been set to 245
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
Serial: 8250/16550 driver, 2 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0xf1012000 (irq = 3) is a 16550A
console [ttyS0] enabled
serial8250.1: ttyS1 at MMIO 0xf1012100 (irq = 4) is a 16550A
brd: module loaded
loop: module loaded
MV-643xx 10/100/1000 ethernet driver version 1.4
mv643xx_eth smi: probed
eth0 (mv643xx_eth_port): not using net_device_ops yet
net eth0: port 0 with MAC address 00:d0:69:41:cc:43
Driver 'sd' needs updating - please use bus_type methods
sata_mv sata_mv.0: version 1.25
sata_mv sata_mv.0: slots 32 ports 2
scsi0 : sata_mv
scsi1 : sata_mv
ata1: SATA max UDMA/133 irq 29
ata2: SATA max UDMA/133 irq 29
####################################################################################
I cant guess what is my error?
Is there any hint to solve this problem?
thanks,
Wael
[-- Attachment #2: Type: text/html, Size: 17594 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-03 15:00 [Xenomai-help] Porting I-Pipe for new ARM board Wael Showair
@ 2009-11-03 15:13 ` Gilles Chanteperdrix
2009-11-03 15:45 ` Didenko Sergey
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-03 15:13 UTC (permalink / raw)
To: Wael Showair; +Cc: Xenomai-help, didenkos
Wael Showair wrote:
> Hi All,
> i have TS-7800 board based on Marvell 88F5182 processor core.
> Unfortunately it is not supported by I-Pipe patch so according to the
> following link:
>
> http://www.xenomai.org/index.php/I-pipe:ArmPorting
>
> And with aid of this forum thread:
>
> http://www.mail-archive.com/xenomai@xenomai.org
If you follow that thread, you will see that I already told its author
that the code was not correct.
Fortunately Philippe did a port which was tested and works, I will fix
one or two details and send it tonight (european time).
--
Gilles
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-03 15:13 ` Gilles Chanteperdrix
@ 2009-11-03 15:45 ` Didenko Sergey
2009-11-03 15:48 ` Gilles Chanteperdrix
` (2 more replies)
0 siblings, 3 replies; 38+ messages in thread
From: Didenko Sergey @ 2009-11-03 15:45 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: Xenomai-help
[-- Attachment #1: Type: text/plain, Size: 939 bytes --]
Gilles, I gues you are talking about the code which I got for MV 88F6290.
With some changes it is working on my board now, so, Wael, if you want, I
can send it to you in 10 hours, it should work on your board.
Sergey
2009/11/4 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Wael Showair wrote:
> > Hi All,
> > i have TS-7800 board based on Marvell 88F5182 processor core.
> > Unfortunately it is not supported by I-Pipe patch so according to the
> > following link:
> >
> > http://www.xenomai.org/index.php/I-pipe:ArmPorting
> >
> > And with aid of this forum thread:
> >
> > http://www.mail-archive.com/xenomai@xenomai.org
>
> If you follow that thread, you will see that I already told its author
> that the code was not correct.
>
> Fortunately Philippe did a port which was tested and works, I will fix
> one or two details and send it tonight (european time).
>
> --
> Gilles
>
>
[-- Attachment #2: Type: text/html, Size: 1537 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-03 15:45 ` Didenko Sergey
@ 2009-11-03 15:48 ` Gilles Chanteperdrix
2009-11-04 6:58 ` Wael Showair
2009-11-04 10:54 ` Gilles Chanteperdrix
2 siblings, 0 replies; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-03 15:48 UTC (permalink / raw)
To: Didenko Sergey; +Cc: Xenomai-help
Didenko Sergey wrote:
> Gilles, I gues you are talking about the code which I got for MV 88F6290.
> With some changes it is working on my board now, so, Wael, if you
> want, I can send it to you in 10 hours, it should work on your board.
Please keep things public and post that code to the list. I intend to
include that code in the next release of Xenomai, and it would be a good
idea that the code we include is the code which works.
--
Gilles
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-03 15:45 ` Didenko Sergey
2009-11-03 15:48 ` Gilles Chanteperdrix
@ 2009-11-04 6:58 ` Wael Showair
2009-11-04 10:54 ` Gilles Chanteperdrix
2 siblings, 0 replies; 38+ messages in thread
From: Wael Showair @ 2009-11-04 6:58 UTC (permalink / raw)
To: Didenko Sergey, Gilles Chanteperdrix; +Cc: Xenomai-help
[-- Attachment #1: Type: text/plain, Size: 1348 bytes --]
Yes please Didenko i would like that you send your code to me & to the whole xenomai-help post.
thanks
________________________________
From: Didenko Sergey <didenkos@domain.hid>
To: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Cc: Wael Showair <showair2003@domain.hid>; Xenomai-help@domain.hid
Sent: Tue, November 3, 2009 5:45:06 PM
Subject: Re: [Xenomai-help] Porting I-Pipe for new ARM board
Gilles, I gues you are talking about the code which I got for MV 88F6290.
With some changes it is working on my board now, so, Wael, if you want, I can send it to you in 10 hours, it should work on your board.
Sergey
2009/11/4 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Wael Showair wrote:
>> Hi All,
>> i have TS-7800 board based on Marvell 88F5182 processor core.
>> Unfortunately it is not supported by I-Pipe patch so according to the
>> following link:
>>>
>> http://www.xenomai.org/index.php/I-pipe:ArmPorting
>>
>> And with aid of this forum thread:
>>
>> http://www.mail-archive.com/xenomai@xenomai.org
>
>>If you follow that thread, you will see that I already told its author
>>that the code was not correct.
>
>>Fortunately Philippe did a port which was tested and works, I will fix
>>one or two details and send it tonight (european time).
>
>--
> Gilles
>
>
[-- Attachment #2: Type: text/html, Size: 3283 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-03 15:45 ` Didenko Sergey
2009-11-03 15:48 ` Gilles Chanteperdrix
2009-11-04 6:58 ` Wael Showair
@ 2009-11-04 10:54 ` Gilles Chanteperdrix
2009-11-06 9:08 ` Wael Showair
2 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-04 10:54 UTC (permalink / raw)
To: Didenko Sergey; +Cc: Xenomai-help
Didenko Sergey wrote:
> Gilles, I gues you are talking about the code which I got for MV 88F6290.
> With some changes it is working on my board now, so, Wael, if you
> want, I can send it to you in 10 hours, it should work on your board.
Hi Sergey,
Do you intend to publish your patch, or should we restart from the one
which Philippe did?
Regards.
--
Gilles
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-04 10:54 ` Gilles Chanteperdrix
@ 2009-11-06 9:08 ` Wael Showair
2009-11-06 9:39 ` Sergey Didenko
0 siblings, 1 reply; 38+ messages in thread
From: Wael Showair @ 2009-11-06 9:08 UTC (permalink / raw)
To: Gilles Chanteperdrix, Didenko Sergey; +Cc: Xenomai-help
[-- Attachment #1: Type: text/plain, Size: 971 bytes --]
Hi Sergey & Gilles,
Could anyone of you please put any version of the patch on the mailing-list.
you said you can send it to me within 10 hours or on last Monday?
i really want to my kernel to boot on orion marvell processor.
thanks for your help
________________________________
From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
To: Didenko Sergey <didenkos@domain.hid>
Cc: Wael Showair <showair2003@domain.hid>; Xenomai-help@domain.hid
Sent: Wed, November 4, 2009 12:54:32 PM
Subject: Re: [Xenomai-help] Porting I-Pipe for new ARM board
Didenko Sergey wrote:
> Gilles, I gues you are talking about the code which I got for MV 88F6290.
> With some changes it is working on my board now, so, Wael, if you
> want, I can send it to you in 10 hours, it should work on your board.
Hi Sergey,
Do you intend to publish your patch, or should we restart from the one
which Philippe did?
Regards.
--
Gilles
[-- Attachment #2: Type: text/html, Size: 1869 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-06 9:08 ` Wael Showair
@ 2009-11-06 9:39 ` Sergey Didenko
2009-11-06 10:22 ` Gilles Chanteperdrix
` (2 more replies)
0 siblings, 3 replies; 38+ messages in thread
From: Sergey Didenko @ 2009-11-06 9:39 UTC (permalink / raw)
To: Wael Showair; +Cc: Xenomai-help
[-- Attachment #1.1: Type: text/plain, Size: 1590 bytes --]
Hello
Here it is!
I'm very sorry for this delay, it was related to 2 facts:
1) before publishing I wanted to put the code in order and to verify once
again
2) I was extremely busy these days, especially with the project on Xenoimai
and I could not do anything with that code except making my project work on
it.
I want to say only that it is working and you can use it with some changes
for your board.
One more time sorry for very late reply.
Gilles, did you get this code (I sent it to you 11.05) ?
Sergey
2009/11/6 Wael Showair <showair2003@domain.hid>
> Hi Sergey & Gilles,
> Could anyone of you please put any version of the patch on the
> mailing-list.
> you said you can send it to me within 10 hours or on last Monday?
>
> i really want to my kernel to boot on orion marvell processor.
> thanks for your help
>
> ------------------------------
> *From:* Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> *To:* Didenko Sergey <didenkos@domain.hid>
>
> *Cc:* Wael Showair <showair2003@domain.hid>; Xenomai-help@domain.hid
> *Sent:* Wed, November 4, 2009 12:54:32 PM
>
> *Subject:* Re: [Xenomai-help] Porting I-Pipe for new ARM board
>
> Didenko Sergey wrote:
> > Gilles, I gues you are talking about the code which I got for MV 88F6290.
> > With some changes it is working on my board now, so, Wael, if you
> > want, I can send it to you in 10 hours, it should work on your board.
>
> Hi Sergey,
>
> Do you intend to publish your patch, or should we restart from the one
> which Philippe did?
>
> Regards.
>
> --
> Gilles
>
>
>
[-- Attachment #1.2: Type: text/html, Size: 2959 bytes --]
[-- Attachment #2: mv88f6290.tar.bz2 --]
[-- Type: application/x-bzip2, Size: 5319 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-06 9:39 ` Sergey Didenko
@ 2009-11-06 10:22 ` Gilles Chanteperdrix
2009-12-15 19:37 ` Олександр Лаврущенко
[not found] ` <20091215213210.19d5b6a5@domain.hid>
2 siblings, 0 replies; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-11-06 10:22 UTC (permalink / raw)
To: Sergey Didenko; +Cc: Xenomai-help
Sergey Didenko wrote:
> Hello
>
> Here it is!
> I'm very sorry for this delay, it was related to 2 facts:
> 1) before publishing I wanted to put the code in order and to verify
> once again
> 2) I was extremely busy these days, especially with the project on
> Xenoimai and I could not do anything with that code except making my
> project work on it.
>
> I want to say only that it is working and you can use it with some
> changes for your board.
> One more time sorry for very late reply.
>
> Gilles, did you get this code (I sent it to you 11.05) ?
No, I did not receive anything. Anyway, please send your modifications a
patch against your kernel patched with the original I-pipe patch. That
is the only way for us to review your code efficiently.
--
Gilles
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-11-06 9:39 ` Sergey Didenko
2009-11-06 10:22 ` Gilles Chanteperdrix
@ 2009-12-15 19:37 ` Олександр Лаврущенко
2009-12-15 20:34 ` Gilles Chanteperdrix
[not found] ` <20091215213210.19d5b6a5@domain.hid>
2 siblings, 1 reply; 38+ messages in thread
From: Олександр Лаврущенко @ 2009-12-15 19:37 UTC (permalink / raw)
To: xenomai
On Fri, 6 Nov 2009 18:39:05 +0900
Sergey Didenko <didenkos@domain.hid> wrote:
> Hello
>
> Here it is!
> I'm very sorry for this delay, it was related to 2 facts:
> 1) before publishing I wanted to put the code in order and to verify
> once again
> 2) I was extremely busy these days, especially with the project on
> Xenoimai and I could not do anything with that code except making my
> project work on it.
>
> I want to say only that it is working and you can use it with some
> changes for your board.
> One more time sorry for very late reply.
Hi.
I want to ask some questions about patch.
For which kernel version (and kernel patches if any) and xenomai version
this patch. And how apply it right, since it's not common patch, rather
suite of files?
Thank you for answer.
--
WBR Lavruschenko Oleksandr
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-12-15 19:37 ` Олександр Лаврущенко
@ 2009-12-15 20:34 ` Gilles Chanteperdrix
0 siblings, 0 replies; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-12-15 20:34 UTC (permalink / raw)
To: Олександр
Лаврущенко
Cc: xenomai
Олександр Лаврущенко wrote:
> On Fri, 6 Nov 2009 18:39:05 +0900
> Sergey Didenko <didenkos@domain.hid> wrote:
>
>> Hello
>>
>> Here it is!
>> I'm very sorry for this delay, it was related to 2 facts:
>> 1) before publishing I wanted to put the code in order and to verify
>> once again
>> 2) I was extremely busy these days, especially with the project on
>> Xenoimai and I could not do anything with that code except making my
>> project work on it.
>>
>> I want to say only that it is working and you can use it with some
>> changes for your board.
>> One more time sorry for very late reply.
> Hi.
> I want to ask some questions about patch.
> For which kernel version (and kernel patches if any) and xenomai version
> this patch. And how apply it right, since it's not common patch, rather
> suite of files?
This has been sent as a patch, I sent some comments, but I do not
remember if Sergey answered.
The development on the I-pipe patches for ARM will be resumed as soon as
Xenomai 2.5.0 will have been released. This patch is one of the pending
tasks.
The patch should work with any recent version i.e. the I-pipe patches
which come with Xenomai 2.4.10 for instance. As for which kernel version
this patch applies to, I have no idea.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
[not found] ` <20091215213210.19d5b6a5@domain.hid>
@ 2009-12-16 1:15 ` Sergey Didenko
2009-12-31 12:52 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Sergey Didenko @ 2009-12-16 1:15 UTC (permalink / raw)
To: Aleksandr Lavrushchenko; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 1369 bytes --]
hi
you are right, this is not common patch, but still it is a patch and you can
apply it.
to do that, run the command
patch -p0 < new-patch
in you linux kernel folder
if you open the *.patch file with text editor, you will see the changes for
only 4 files.
This patch includes the changes to support Marvell SoC MV88F6290 with
Counting Down free running counter.
Kernel version is 2.6.29-v02.00.29
Xenomai version is 2.4.9.1
Sergey
2009/12/16 Aleksandr Lavrushchenko <aleksandr.lavrushchenko@domain.hid>
> On Fri, 6 Nov 2009 18:39:05 +0900
> Sergey Didenko <didenkos@domain.hid> wrote:
>
> > Hello
> >
> > Here it is!
> > I'm very sorry for this delay, it was related to 2 facts:
> > 1) before publishing I wanted to put the code in order and to verify
> > once again
> > 2) I was extremely busy these days, especially with the project on
> > Xenoimai and I could not do anything with that code except making my
> > project work on it.
> >
> > I want to say only that it is working and you can use it with some
> > changes for your board.
> > One more time sorry for very late reply.
> Hi.
> I want to ask some questions about patch.
> For which kernel version (and kernel patches if any) and xenomai version
> this patch. And how apply it right, since it's not common patch, rather
> suite of files?
>
> Thank you for answer.
> --
> WBR Lavruschenko Oleksandr
>
[-- Attachment #2: Type: text/html, Size: 2735 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-12-16 1:15 ` Sergey Didenko
@ 2009-12-31 12:52 ` Flavio de Castro Alves Filho
2009-12-31 15:41 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2009-12-31 12:52 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 2679 bytes --]
Hello,
I am currently working on the port of Xenomai for the TI OMAP L-138
processor (DaVinci platform). I didn't finish yet. As soon as I finish, I
will send the patch, and I intend to do so next week.
I followed the instructions from Xenomai's wiki page. Until now, I am able
to boot my ported kernel with the I-Pipe feature. When I build the kernel
with Xenomai feature, the kernel stops to boot.
I have some questions:
1) How is the better way to debug the boot process? When my kernel stops
booting, after the message "Uncompressing .........." the boot halts. I
don't know what is going on and I don't know what to do in order to follow
the processes internally. Both debuggers (kernel and i-ipipe) are enabled in
the kernel configuration.
2) How tested the code must be done in order to send you a patch? Is there
any minimal set of tests that I should perform just before sending you a
patch for revision?
Best regards,
Flavio
Flavio de Castro Alves Filho
Embedded Software Services
www.phiinnovations.com
+55 11 84 94 56 76
2009/12/15 Sergey Didenko <didenkos@domain.hid>
> hi
>
> you are right, this is not common patch, but still it is a patch and you
> can apply it.
> to do that, run the command
> patch -p0 < new-patch
> in you linux kernel folder
>
> if you open the *.patch file with text editor, you will see the changes for
> only 4 files.
> This patch includes the changes to support Marvell SoC MV88F6290 with
> Counting Down free running counter.
>
> Kernel version is 2.6.29-v02.00.29
> Xenomai version is 2.4.9.1
>
> Sergey
>
> 2009/12/16 Aleksandr Lavrushchenko <aleksandr.lavrushchenko@domain.hid>
>
>> On Fri, 6 Nov 2009 18:39:05 +0900
>> Sergey Didenko <didenkos@domain.hid> wrote:
>>
>> > Hello
>> >
>> > Here it is!
>> > I'm very sorry for this delay, it was related to 2 facts:
>> > 1) before publishing I wanted to put the code in order and to verify
>> > once again
>> > 2) I was extremely busy these days, especially with the project on
>> > Xenoimai and I could not do anything with that code except making my
>> > project work on it.
>> >
>> > I want to say only that it is working and you can use it with some
>> > changes for your board.
>> > One more time sorry for very late reply.
>> Hi.
>> I want to ask some questions about patch.
>> For which kernel version (and kernel patches if any) and xenomai version
>> this patch. And how apply it right, since it's not common patch, rather
>> suite of files?
>>
>> Thank you for answer.
>> --
>> WBR Lavruschenko Oleksandr
>>
>
>
> _______________________________________________
> Xenomai-help mailing list
> Xenomai-help@domain.hid
> https://mail.gna.org/listinfo/xenomai-help
>
>
[-- Attachment #2: Type: text/html, Size: 4463 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-12-31 12:52 ` Flavio de Castro Alves Filho
@ 2009-12-31 15:41 ` Gilles Chanteperdrix
2010-01-04 22:14 ` Flavio Alves
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2009-12-31 15:41 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Hello,
>
> I am currently working on the port of Xenomai for the TI OMAP L-138
> processor (DaVinci platform). I didn't finish yet. As soon as I finish,
> I will send the patch, and I intend to do so next week.
>
> I followed the instructions from Xenomai's wiki page. Until now, I am
> able to boot my ported kernel with the I-Pipe feature. When I build the
> kernel with Xenomai feature, the kernel stops to boot.
>
> I have some questions:
>
> 1) How is the better way to debug the boot process? When my kernel stops
> booting, after the message "Uncompressing .........." the boot halts. I
> don't know what is going on and I don't know what to do in order to
> follow the processes internally. Both debuggers (kernel and i-ipipe) are
> enabled in the kernel configuration.
This is tips and tricks number 1:
http://www.xenomai.org/index.php/I-pipe:ArmPorting#Tips_and_tricks.
>
> 2) How tested the code must be done in order to send you a patch? Is
> there any minimal set of tests that I should perform just before sending
> you a patch for revision?
The validation tool I use is LTP. You can check that LTP returns the
same results with a vanilla kernel, and with the Xenomai patched kernel
when running LTP while a latency test is running. Unfortunately, to run
ltp on low-end arms, I had to make a few local changes. Which means I am
using an out-dated, patched version of LTP:
http://sisyphus.hd.free.fr/~gilles/ltp-20081130-patched.tar.bz2
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2009-12-31 15:41 ` Gilles Chanteperdrix
@ 2010-01-04 22:14 ` Flavio Alves
2010-01-04 22:22 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio Alves @ 2010-01-04 22:14 UTC (permalink / raw)
To: xenomai
[-- Attachment #1.1: Type: text/plain, Size: 6295 bytes --]
Hello Gilles,
Thanks for your advice, now I could continue the porting.
After implementing the tips and tricks number 1, I could see again the
boot messages. The trace is the following:
<6>Xenomai: hal/arm
started.
<6>Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon)
loaded.
<1>Unable to handle kernel NULL pointer dereference at virtual address
00000000
<1>pgd =
c0004000
<1>[00000000]
*pgd=00000000
Internal error: Oops: 5 [#1]
PREEMPT
Modules linked
in:
CPU: 0 Not tainted (2.6.29-rc8-davinci1
#23)
PC is at __ipipe_mach_get_tsc
+0x28/0x64
LR is at xnarch_get_cpu_time
+0x10/0x18
pc : [<c0037514>] lr : [<c0077d24>] psr:
20000013
sp : c1c17e68 ip : c1c17e78 fp :
c1c17e74
r10: c03e0f90 r9 : 00000000 r8 :
c03b95e8
r7 : c03b95e8 r6 : 00000001 r5 : 00000000 r4 :
97a862f8
r3 : 00000001 r2 : 00000000 r1 : 00000000 r0 :
97a862f8
Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment
kernel
Control: 0005317f Table: c0004000 DAC:
00000017
Process swapper (pid: 1, stack limit =
0xc1c16268)
Stack: (0xc1c17e68 to
0xc1c18000)
7e60: c1c17e84 c1c17e78 c0077d24 c00374fc c1c17eb4
c1c17e88
7e80: c007a62c c0077d24 00000000 00000000 c1c17eb4 c1c17ea0 00000000
c03e0f90
7ea0: 00000001 c03e0fc8 c1c17f34 c1c17eb8 c007a9d4 c007a584 00500080
00000000
7ec0: 00000000 0000011c 736f685b 69742d74 5d72656d 019bfc00 c0014348
c035fc94
7ee0: 00000000 00000000 544f4f52 c1c17e00 c02d5d14 c0043a5c c1c17f1c
c1c17f2c
7f00: c0075664 c03e0f58 00000000 c03e2ccc c03e2cd8 c03e2ce4 c03e2cf0
c03e2cfc
7f20: 00000000 c03e2c80 c1c17f5c c1c17f38 c0083710 c007a700 c0024acc
00000000
7f40: 00000000 c0083658 00000001 00000000 c1c17fd4 c1c17f60 c002d464
c0083668
7f60: 00000000 c035c631 c03dc160 000000db c1c33000 00000000 00000000
00000000
7f80: c1c17fac c1c17f90 c0106158 c0105e38 00000000 c1c33180 c1c17fc4
c03dc160
7fa0: c1c17fc4 c1c17fb0 c0070f60 c01060e8 c0024978 c0024acc 00000000
00000000
7fc0: 00000000 00000000 c1c17ff4 c1c17fd8 c00085a4 c002d418 00000000
00000001
7fe0: 00000000 00000000 00000000 c1c17ff8 c0046638 c000852c fffdf7ff
ffeffedf
Backtrace:
[<c00374ec>] (__ipipe_mach_get_tsc+0x0/0x64) from [<c0077d24>]
(xnarch_get_cpu_)
[<c0077d14>] (xnarch_get_cpu_time+0x0/0x18) from [<c007a62c>]
(xnpod_enable_tim)
[<c007a574>] (xnpod_enable_timesource+0x0/0x17c) from [<c007a9d4>]
(xnpod_init+)
r7:c03e0fc8 r6:00000001 r5:c03e0f90
r4:00000000
[<c007a6f0>] (xnpod_init+0x0/0x35c) from [<c0083710>]
(__native_skin_init+0xb8/)
[<c0083658>] (__native_skin_init+0x0/0x278) from [<c002d464>]
(do_one_initcall+)
[<c002d408>] (do_one_initcall+0x0/0x1a4) from [<c00085a4>] (kernel_init
+0x88/0x)
r8:00000000 r7:00000000 r6:00000000 r5:00000000
r4:c0024acc
[<c000851c>] (kernel_init+0x0/0xfc) from [<c0046638>] (do_exit
+0x0/0x7e8)
r4:00000000
Code: 03a02000 03a03000 0a00000a e5922000
(e892000c)
<4>---[ end trace
da227214a82491b7 ]---
<0>Kernel panic - not syncing: Attempted to kill
init!
Looking at the code (and perform some analysis) I saw that the call that
is crashing the kernel is:
__asm__("ldmia %1, %M0\n":
"=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
And looking into the implementation of this function for other
platforms, I can see that it is the same instruction, without
difference.
In my implementation (port for the TI OMAP L-138 processor), I have
CONFIG_GENERIC_CLOCKEVENTS and CONFIG_GENERIC_TIME.
Could you please give me some advice about how to solve this issue?
Thank you for all your help.
Flavio
On Qui, 2009-12-31 at 16:41 +0100, Gilles Chanteperdrix wrote:
> Flavio de Castro Alves Filho wrote:
> > Hello,
> >
> > I am currently working on the port of Xenomai for the TI OMAP L-138
> > processor (DaVinci platform). I didn't finish yet. As soon as I finish,
> > I will send the patch, and I intend to do so next week.
> >
> > I followed the instructions from Xenomai's wiki page. Until now, I am
> > able to boot my ported kernel with the I-Pipe feature. When I build the
> > kernel with Xenomai feature, the kernel stops to boot.
> >
> > I have some questions:
> >
> > 1) How is the better way to debug the boot process? When my kernel stops
> > booting, after the message "Uncompressing .........." the boot halts. I
> > don't know what is going on and I don't know what to do in order to
> > follow the processes internally. Both debuggers (kernel and i-ipipe) are
> > enabled in the kernel configuration.
>
> This is tips and tricks number 1:
> http://www.xenomai.org/index.php/I-pipe:ArmPorting#Tips_and_tricks.
>
> >
> > 2) How tested the code must be done in order to send you a patch? Is
> > there any minimal set of tests that I should perform just before sending
> > you a patch for revision?
>
> The validation tool I use is LTP. You can check that LTP returns the
> same results with a vanilla kernel, and with the Xenomai patched kernel
> when running LTP while a latency test is running. Unfortunately, to run
> ltp on low-end arms, I had to make a few local changes. Which means I am
> using an out-dated, patched version of LTP:
> http://sisyphus.hd.free.fr/~gilles/ltp-20081130-patched.tar.bz2
>
Flavio de
Castro Alves
Filho
flavio.alves@domain.hid
Tel.: + 55 11
8494-5676
Embedded
Software
Services
www.phiinnovations.com
Escritórios::
São Paulo
Campinas
[-- Attachment #1.2: Type: text/html, Size: 13349 bytes --]
[-- Attachment #2: logo.gif --]
[-- Type: image/gif, Size: 5312 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-04 22:14 ` Flavio Alves
@ 2010-01-04 22:22 ` Gilles Chanteperdrix
2010-01-06 10:56 ` Flavio Alves
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-04 22:22 UTC (permalink / raw)
To: flavio.alves; +Cc: xenomai
Flavio Alves wrote:
> <1>Unable to handle kernel NULL pointer dereference at virtual address 00000000
> Looking at the code (and perform some analysis) I saw that the call that
> is crashing the kernel is:
>
> __asm__("ldmia %1, %M0\n":
> "=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
>
> And looking into the implementation of this function for other
> platforms, I can see that it is the same instruction, without
> difference.
On all other platforms the "local_tsc" pointer is not NULL...
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-04 22:22 ` Gilles Chanteperdrix
@ 2010-01-06 10:56 ` Flavio Alves
2010-01-06 11:01 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio Alves @ 2010-01-06 10:56 UTC (permalink / raw)
To: xenomai
[-- Attachment #1.1: Type: text/plain, Size: 7242 bytes --]
Indeed ...
Making this pointer not null (initializing the tsc pointer) solve this
issue. Thanks again for your help.
Now I have the following situation in my xenomai boot process:
Starting
kernel ...
Uncompressing
Linux.............................................................
Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version
4.3.3 (So0
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ),
cr=00053177
CPU: VIVT data cache, VIVT instruction
cache
Machine: DaVinci DA850
EVM
Memory policy: ECC disabled, Data cache
writeback
DA0850 variant
0x0
Built 1 zonelists in Zone order, mobility grouping on. Total pages:
8128
Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw
initrd=0x1
PID hash table entries: 128 (order: 7, 512
bytes)
I-pipe 1.13-03: pipeline
enabled.
Console: colour dummy device
80x30
Dentry cache hash table entries: 4096 (order: 2, 16384
bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192
bytes)
Memory: 32MB = 32MB
total
Memory: 24248KB available (3580K code, 368K data, 148K
init)
Calibrating delay loop... 149.09 BogoMIPS
(lpj=745472)
Mount-cache hash table entries:
512
CPU: Testing write buffer coherency:
ok
net_namespace: 880
bytes
NET: Registered protocol family
16
Pin I2C1_SCL already used for
UART2_RXD.
Pin I2C1_SDA already used for
UART2_TXD.
DaVinci: 144 gpio
irqs
bio: create slab <bio-0> at
0
SCSI subsystem
initialized
usbcore: registered new interface driver
usbfs
usbcore: registered new interface driver
hub
usbcore: registered new device driver
usb
musb_hdrc: version 6.0, cppi4.1-dma, host,
debug=0
Waiting for PHY clock
good...
musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ
58
musb_hdrc musb_hdrc: MUSB HDRC host
driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number
1
usb usb1: configuration #1 chosen from 1
choice
hub 1-0:1.0: USB hub
found
hub 1-0:1.0: 1 port
detected
NET: Registered protocol family
2
IP route cache hash table entries: 1024 (order: 0, 4096
bytes)
TCP established hash table entries: 1024 (order: 1, 8192
bytes)
TCP bind hash table entries: 1024 (order: 0, 4096
bytes)
TCP: Hash tables configured (established 1024 bind
1024)
TCP reno
registered
NET: Registered protocol family
1
checking if image is initramfs...it isn't (no cpio magic); looks like an
initrd
Freeing initrd memory:
4096K
I-pipe: Domain Xenomai
registered.
Xenomai: hal/arm
started.
Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon)
loaded.
Xenomai: starting native API
services.
Xenomai: starting POSIX
services.
Xenomai: starting RTDM
services.
msgmni has been set to
55
io scheduler noop
registered
io scheduler anticipatory registered
(default)
Serial: 8250/16550 driver, 3 ports, IRQ sharing
disabled
serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a
16550A
serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a
16550A
serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a
16550A
console [ttyS2]
enabled
brd: module
loaded
davinci_emac_probe: using random MAC addr:
6a:c9:27:5d:9b:5c
emac-mii:
probed
dm9000 Ethernet Driver,
V1.31
console [netcon0]
enabled
netconsole: network logging
started
Linux video capture interface:
v2.00
Driver 'sd' needs updating - please use bus_type
methods
ahci ahci: forcing PORTS_IMPL to
0x1
ahci ahci: AHCI 0001.0100 32 slots 1 ports 3 Gbps 0x1 impl SATA
mode
ahci ahci: flags: ncq sntf pm led clo only pmp pio slum
part
scsi0 :
ahci
ata1: SATA max UDMA/133 irq
67
I still cannot boot my kernel using xenomai.
I would like to ask you some advice about the reasons why the kernel
boot stops at this point?
Thanks again for all the help
Best regards,
Flavio
On Seg, 2010-01-04 at 23:22 +0100, Gilles Chanteperdrix wrote:
> Flavio Alves wrote:
> > <1>Unable to handle kernel NULL pointer dereference at virtual address 00000000
> > Looking at the code (and perform some analysis) I saw that the call that
> > is crashing the kernel is:
> >
> > __asm__("ldmia %1, %M0\n":
> > "=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
> >
> > And looking into the implementation of this function for other
> > platforms, I can see that it is the same instruction, without
> > difference.
>
> On all other platforms the "local_tsc" pointer is not NULL...
>
Flavio de
Castro Alves
Filho
flavio.alves@domain.hid
Tel.: + 55 11
8494-5676
Embedded
Software
Services
www.phiinnovations.com
Escritórios::
São Paulo
Campinas
[-- Attachment #1.2: Type: text/html, Size: 22872 bytes --]
[-- Attachment #2: logo.gif --]
[-- Type: image/gif, Size: 5312 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 10:56 ` Flavio Alves
@ 2010-01-06 11:01 ` Gilles Chanteperdrix
2010-01-06 11:38 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-06 11:01 UTC (permalink / raw)
To: flavio.alves; +Cc: xenomai
Flavio Alves wrote:
> Indeed ...
>
> Making this pointer not null (initializing the tsc pointer) solve this
> issue. Thanks again for your help.
>
> Now I have the following situation in my xenomai boot process:
Your boot log is unreadable, please tell your MUA no to wrap it or post
it to some pastebin.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 11:01 ` Gilles Chanteperdrix
@ 2010-01-06 11:38 ` Flavio de Castro Alves Filho
2010-01-06 14:01 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-06 11:38 UTC (permalink / raw)
To: xenomai
Hello Gilles,
The boot log is the following (I hope this time it works).
Starting kernel ...
Uncompressing Linux.............................................................
Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version 4.3.3 (So0
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: DaVinci DA850 EVM
Memory policy: ECC disabled, Data cache writeback
DA0850 variant 0x0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128
Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw initrd=0x1
PID hash table entries: 128 (order: 7, 512 bytes)
I-pipe 1.13-03: pipeline enabled.
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 24248KB available (3580K code, 368K data, 148K init)
Calibrating delay loop... 149.09 BogoMIPS (lpj=745472)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 880 bytes
NET: Registered protocol family 16
Pin I2C1_SCL already used for UART2_RXD.
Pin I2C1_SDA already used for UART2_TXD.
DaVinci: 144 gpio irqs
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
musb_hdrc: version 6.0, cppi4.1-dma, host, debug=0
Waiting for PHY clock good...
musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ 58
musb_hdrc musb_hdrc: MUSB HDRC host driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
NET: Registered protocol family 1
checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
Freeing initrd memory: 4096K
I-pipe: Domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
Xenomai: starting native API services.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.
msgmni has been set to 55
io scheduler noop registered
io scheduler anticipatory registered (default)
Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a 16550A
serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a 16550A
serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a 16550A
console [ttyS2] enabled
brd: module loaded
davinci_emac_probe: using random MAC addr: 6a:c9:27:5d:9b:5c
emac-mii: probed
dm9000 Ethernet Driver, V1.31
console [netcon0] enabled
netconsole: network logging started
Linux video capture interface: v2.00
Driver 'sd' needs updating - please use bus_type methods
ahci ahci: forcing PORTS_IMPL to 0x1
ahci ahci: AHCI 0001.0100 32 slots 1 ports 3 Gbps 0x1 impl SATA mode
ahci ahci: flags: ncq sntf pm led clo only pmp pio slum part
scsi0 : ahci
ata1: SATA max UDMA/133 irq 67
Thank you and best regards,
Flavio
Flavio de Castro Alves Filho
Embedded Software Services
www.phiinnovations.com
+55 11 84 94 56 76
2010/1/6 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
>
> Flavio Alves wrote:
> > Indeed ...
> >
> > Making this pointer not null (initializing the tsc pointer) solve this
> > issue. Thanks again for your help.
> >
> > Now I have the following situation in my xenomai boot process:
>
> Your boot log is unreadable, please tell your MUA no to wrap it or post
> it to some pastebin.
>
> --
> Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 11:38 ` Flavio de Castro Alves Filho
@ 2010-01-06 14:01 ` Gilles Chanteperdrix
2010-01-06 19:16 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-06 14:01 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Hello Gilles,
>
> The boot log is the following (I hope this time it works).
>
> Starting kernel ...
>
> Uncompressing Linux.............................................................
> Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version 4.3.3 (So0
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
> CPU: VIVT data cache, VIVT instruction cache
> Machine: DaVinci DA850 EVM
> Memory policy: ECC disabled, Data cache writeback
> DA0850 variant 0x0
> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128
> Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw initrd=0x1
> PID hash table entries: 128 (order: 7, 512 bytes)
> I-pipe 1.13-03: pipeline enabled.
> Console: colour dummy device 80x30
> Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
> Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
> Memory: 32MB = 32MB total
> Memory: 24248KB available (3580K code, 368K data, 148K init)
> Calibrating delay loop... 149.09 BogoMIPS (lpj=745472)
> Mount-cache hash table entries: 512
> CPU: Testing write buffer coherency: ok
> net_namespace: 880 bytes
> NET: Registered protocol family 16
> Pin I2C1_SCL already used for UART2_RXD.
> Pin I2C1_SDA already used for UART2_TXD.
> DaVinci: 144 gpio irqs
> bio: create slab <bio-0> at 0
> SCSI subsystem initialized
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> musb_hdrc: version 6.0, cppi4.1-dma, host, debug=0
> Waiting for PHY clock good...
> musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ 58
> musb_hdrc musb_hdrc: MUSB HDRC host driver
> musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
> usb usb1: configuration #1 chosen from 1 choice
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 1 port detected
> NET: Registered protocol family 2
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 1024 (order: 1, 8192 bytes)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> TCP: Hash tables configured (established 1024 bind 1024)
> TCP reno registered
> NET: Registered protocol family 1
> checking if image is initramfs...it isn't (no cpio magic); looks like an initrd
> Freeing initrd memory: 4096K
> I-pipe: Domain Xenomai registered.
> Xenomai: hal/arm started.
> Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
> Xenomai: starting native API services.
> Xenomai: starting POSIX services.
> Xenomai: starting RTDM services.
> msgmni has been set to 55
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
> serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a 16550A
> serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a 16550A
> serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a 16550A
> console [ttyS2] enabled
> brd: module loaded
> davinci_emac_probe: using random MAC addr: 6a:c9:27:5d:9b:5c
> emac-mii: probed
> dm9000 Ethernet Driver, V1.31
> console [netcon0] enabled
> netconsole: network logging started
> Linux video capture interface: v2.00
> Driver 'sd' needs updating - please use bus_type methods
> ahci ahci: forcing PORTS_IMPL to 0x1
> ahci ahci: AHCI 0001.0100 32 slots 1 ports 3 Gbps 0x1 impl SATA mode
> ahci ahci: flags: ncq sntf pm led clo only pmp pio slum part
> scsi0 : ahci
> ata1: SATA max UDMA/133 irq 67
>
> Thank you and best regards,
Well your log does not show any error. If there is a lockup, bisect to
find where it happens.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 14:01 ` Gilles Chanteperdrix
@ 2010-01-06 19:16 ` Flavio de Castro Alves Filho
2010-01-06 19:23 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-06 19:16 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 4547 bytes --]
I believe there is a lockup during the irq handling process.
I could not find where it is blocking.
I performed the following tests:
1) add traces in every function related to interrupt ... and none was called
2) add traces in every function in time.c file. After the last message
("ata1: SATA max UDMA/133 irq 67"), the following functions were called:
- read_cycles()
- timer32_read()
Looking at these functions, they seam to be fine. I have no clue about where
to start debugging.
Thank you for all your help.
Regards,
Flavio
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/6 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>:
> Flavio de Castro Alves Filho wrote:
>> Hello Gilles,
>>
>> The boot log is the following (I hope this time it works).
>>
>> Starting kernel ...
>>
>> Uncompressing
Linux.............................................................
>> Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version
4.3.3 (So0
>> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
>> CPU: VIVT data cache, VIVT instruction cache
>> Machine: DaVinci DA850 EVM
>> Memory policy: ECC disabled, Data cache writeback
>> DA0850 variant 0x0
>> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128
>> Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw
initrd=0x1
>> PID hash table entries: 128 (order: 7, 512 bytes)
>> I-pipe 1.13-03: pipeline enabled.
>> Console: colour dummy device 80x30
>> Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
>> Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
>> Memory: 32MB = 32MB total
>> Memory: 24248KB available (3580K code, 368K data, 148K init)
>> Calibrating delay loop... 149.09 BogoMIPS (lpj=745472)
>> Mount-cache hash table entries: 512
>> CPU: Testing write buffer coherency: ok
>> net_namespace: 880 bytes
>> NET: Registered protocol family 16
>> Pin I2C1_SCL already used for UART2_RXD.
>> Pin I2C1_SDA already used for UART2_TXD.
>> DaVinci: 144 gpio irqs
>> bio: create slab <bio-0> at 0
>> SCSI subsystem initialized
>> usbcore: registered new interface driver usbfs
>> usbcore: registered new interface driver hub
>> usbcore: registered new device driver usb
>> musb_hdrc: version 6.0, cppi4.1-dma, host, debug=0
>> Waiting for PHY clock good...
>> musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ 58
>> musb_hdrc musb_hdrc: MUSB HDRC host driver
>> musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
>> usb usb1: configuration #1 chosen from 1 choice
>> hub 1-0:1.0: USB hub found
>> hub 1-0:1.0: 1 port detected
>> NET: Registered protocol family 2
>> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
>> TCP established hash table entries: 1024 (order: 1, 8192 bytes)
>> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
>> TCP: Hash tables configured (established 1024 bind 1024)
>> TCP reno registered
>> NET: Registered protocol family 1
>> checking if image is initramfs...it isn't (no cpio magic); looks like an
initrd
>> Freeing initrd memory: 4096K
>> I-pipe: Domain Xenomai registered.
>> Xenomai: hal/arm started.
>> Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
>> Xenomai: starting native API services.
>> Xenomai: starting POSIX services.
>> Xenomai: starting RTDM services.
>> msgmni has been set to 55
>> io scheduler noop registered
>> io scheduler anticipatory registered (default)
>> Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
>> serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a 16550A
>> serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a 16550A
>> serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a 16550A
>> console [ttyS2] enabled
>> brd: module loaded
>> davinci_emac_probe: using random MAC addr: 6a:c9:27:5d:9b:5c
>> emac-mii: probed
>> dm9000 Ethernet Driver, V1.31
>> console [netcon0] enabled
>> netconsole: network logging started
>> Linux video capture interface: v2.00
>> Driver 'sd' needs updating - please use bus_type methods
>> ahci ahci: forcing PORTS_IMPL to 0x1
>> ahci ahci: AHCI 0001.0100 32 slots 1 ports 3 Gbps 0x1 impl SATA mode
>> ahci ahci: flags: ncq sntf pm led clo only pmp pio slum part
>> scsi0 : ahci
>> ata1: SATA max UDMA/133 irq 67
>>
>> Thank you and best regards,
>
> Well your log does not show any error. If there is a lockup, bisect to
> find where it happens.
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 5592 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 19:16 ` Flavio de Castro Alves Filho
@ 2010-01-06 19:23 ` Gilles Chanteperdrix
2010-01-08 14:11 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-06 19:23 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> I believe there is a lockup during the irq handling process.
>
> I could not find where it is blocking.
>
> I performed the following tests:
>
> 1) add traces in every function related to interrupt ... and none was called
Well, obviously, you missed some, because your boot logs indicate
clearly that at least the timer interrupt is working.
If you are interested in what happens at I-pipe level, the functions you
are interested in are ipipe_grab_irq, ipipe_handle_irq,
ipipe_mach_demux_irq, etc...
>
> 2) add traces in every function in time.c file. After the last message
> ("ata1: SATA max UDMA/133 irq 67"), the following functions were called:
> - read_cycles()
> - timer32_read()
>
> Looking at these functions, they seam to be fine. I have no clue about where
> to start debugging.
>
> Thank you for all your help.
Try this:
diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
index 5a324c9..22ddbe2 100644
--- a/arch/arm/mach-davinci/irq.c
+++ b/arch/arm/mach-davinci/irq.c
@@ -360,9 +360,11 @@ void __init davinci_irq_init(void)
for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
set_irq_chip(i, &davinci_irq_chip_0);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+#ifndef CONFIG_IPIPE
if (i != IRQ_TINT1_TINT34)
set_irq_handler(i, handle_edge_irq);
else
+#endif /* CONFIG_IPIPE */
set_irq_handler(i, handle_level_irq);
}
}
--
Gilles.
^ permalink raw reply related [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-06 19:23 ` Gilles Chanteperdrix
@ 2010-01-08 14:11 ` Flavio de Castro Alves Filho
2010-01-08 14:35 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 14:11 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 2478 bytes --]
Hello Gilles,
Unfortunately the patch didn't help... :-(
But ... adding more traces on the code, I can see the irq number when the
function __ipipe_grab_irq() is called.
When everything works fine, the irq number is 21 (IRQ_DA8XX_TINT12_0).
And, sometime, the irq number starts to be 22 (IRQ_DA8XX_TINT34_0). It is
the other timer present at the processor. I believe that, somehow, the
information about the timer (at least, the interrupt location) has been
changed by some code.
I will investigate more, according to these observations. I accept
suggestions :-)
Best regards,
Flavio
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/6 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > I believe there is a lockup during the irq handling process.
> >
> > I could not find where it is blocking.
> >
> > I performed the following tests:
> >
> > 1) add traces in every function related to interrupt ... and none was
> called
>
> Well, obviously, you missed some, because your boot logs indicate
> clearly that at least the timer interrupt is working.
>
> If you are interested in what happens at I-pipe level, the functions you
> are interested in are ipipe_grab_irq, ipipe_handle_irq,
> ipipe_mach_demux_irq, etc...
>
> >
> > 2) add traces in every function in time.c file. After the last message
> > ("ata1: SATA max UDMA/133 irq 67"), the following functions were called:
> > - read_cycles()
> > - timer32_read()
> >
> > Looking at these functions, they seam to be fine. I have no clue about
> where
> > to start debugging.
> >
> > Thank you for all your help.
>
> Try this:
>
> diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
> index 5a324c9..22ddbe2 100644
> --- a/arch/arm/mach-davinci/irq.c
> +++ b/arch/arm/mach-davinci/irq.c
> @@ -360,9 +360,11 @@ void __init davinci_irq_init(void)
> for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
> set_irq_chip(i, &davinci_irq_chip_0);
> set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
> +#ifndef CONFIG_IPIPE
> if (i != IRQ_TINT1_TINT34)
> set_irq_handler(i, handle_edge_irq);
> else
> +#endif /* CONFIG_IPIPE */
> set_irq_handler(i, handle_level_irq);
> }
> }
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 3200 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 14:11 ` Flavio de Castro Alves Filho
@ 2010-01-08 14:35 ` Gilles Chanteperdrix
2010-01-08 14:58 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 14:35 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Hello Gilles,
>
> Unfortunately the patch didn't help... :-(
>
> But ... adding more traces on the code, I can see the irq number when the
> function __ipipe_grab_irq() is called.
>
> When everything works fine, the irq number is 21 (IRQ_DA8XX_TINT12_0).
>
> And, sometime, the irq number starts to be 22 (IRQ_DA8XX_TINT34_0). It is
> the other timer present at the processor. I believe that, somehow, the
> information about the timer (at least, the interrupt location) has been
> changed by some code.
>
> I will investigate more, according to these observations. I accept
> suggestions :-)
Are you sure you recompiled the kernel ? This other timer's irq seems to
be the one for which the handle_edge_irq handler is used, which could
really cause a lockup.
Anyway, the reason why this other timer is used is probably because
clockevent decided it had a better score. But that should not cause a
lockup, unless handle_edge_irq is used.
So, you are probably better off using that timer for xenomai too. If you
do not want that, you will have to give a higher score to the timer you
want Linux to use.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 14:35 ` Gilles Chanteperdrix
@ 2010-01-08 14:58 ` Flavio de Castro Alves Filho
2010-01-08 15:36 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 14:58 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 1818 bytes --]
In fact,
The problem is not really related to the other timer, I believe.
Before the timer with irq 22 is called, another irq is called by
__ipipe_grab_irq(): the irq number 12 (IRQ_DA8XX_CCERRINT).
Now I'm looking for the place there this irq number is passed.
And thank you for this important information about the timers.
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > Hello Gilles,
> >
> > Unfortunately the patch didn't help... :-(
> >
> > But ... adding more traces on the code, I can see the irq number when the
> > function __ipipe_grab_irq() is called.
> >
> > When everything works fine, the irq number is 21 (IRQ_DA8XX_TINT12_0).
> >
> > And, sometime, the irq number starts to be 22 (IRQ_DA8XX_TINT34_0). It is
> > the other timer present at the processor. I believe that, somehow, the
> > information about the timer (at least, the interrupt location) has been
> > changed by some code.
> >
> > I will investigate more, according to these observations. I accept
> > suggestions :-)
>
> Are you sure you recompiled the kernel ? This other timer's irq seems to
> be the one for which the handle_edge_irq handler is used, which could
> really cause a lockup.
>
> Anyway, the reason why this other timer is used is probably because
> clockevent decided it had a better score. But that should not cause a
> lockup, unless handle_edge_irq is used.
>
> So, you are probably better off using that timer for xenomai too. If you
> do not want that, you will have to give a higher score to the timer you
> want Linux to use.
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 2430 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 14:58 ` Flavio de Castro Alves Filho
@ 2010-01-08 15:36 ` Gilles Chanteperdrix
2010-01-08 17:43 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 15:36 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> In fact,
>
> The problem is not really related to the other timer, I believe.
>
> Before the timer with irq 22 is called, another irq is called by
> __ipipe_grab_irq(): the irq number 12 (IRQ_DA8XX_CCERRINT).
>
> Now I'm looking for the place there this irq number is passed.
>
> And thank you for this important information about the timers.
I think your problem really is that irq22 uses handle_edge_irq, somehow.
Could you check whether this is the case, for instance by putting a
printk in the __ipipe_ack_edge_irq function, file kernel/irq/chip.c ?
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 15:36 ` Gilles Chanteperdrix
@ 2010-01-08 17:43 ` Flavio de Castro Alves Filho
2010-01-08 18:02 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 17:43 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 5014 bytes --]
Hello,
The functions level_egde_irq and __ipipe_ack_edge_irq are not called during
boot process.
I'm sending attached the boot log with my traces separated
irq = 21
__ipipe_mach_irq_mux_p false
Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version 4.3.3
(Sourcery G++ Lite 2009q1-203) ) #57 PREEMPT Fri Jan 8 13:58:39 BRST 2010
CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
CPU: VIVT data cache, VIVT instruction cache
Machine: DaVinci DA850 EVM
Memory policy: ECC disabled, Data cache writeback
DA0850 variant 0x0
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128
Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw
initrd=0xc1180000,4M ip=10.1.1.2:10.1.1.1
PID hash table entries: 128 (order: 7, 512 bytes)
I-pipe 1.13-03: pipeline enabled.
Console: colour dummy device 80x30
Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
Memory: 32MB = 32MB total
Memory: 24236KB available (3592K code, 367K data, 148K init)
Calibrating delay loop... 86.63 BogoMIPS (lpj=433152)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 880 bytes
NET: Registered protocol family 16
Pin I2C1_SCL already used for UART2_RXD.
Pin I2C1_SDA already used for UART2_TXD.
DaVinci: 144 gpio irqs
bio: create slab <bio-0> at 0
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
musb_hdrc: version 6.0, cppi4.1-dma, host, debug=0
Waiting for PHY clock good...
musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ 58
musb_hdrc musb_hdrc: MUSB HDRC host driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
NET: Registered protocol family 1
checking if image is initramfs...it isn't (no cpio magic); looks like an
initrd
Freeing initrd memory: 4096K
I-pipe: Domain Xenomai registered.
Xenomai: hal/arm started.
Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
Xenomai: starting native API services.
Xenomai: starting POSIX services.
Xenomai: starting RTDM services.
msgmni has been set to 55
io scheduler noop registered
io scheduler anticipatory registered (default)
Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a 16550A
serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a 16550A
serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a 16550A
console [ttyS2] enabled
brd: module loaded
davinci_emac_probe: using random MAC addr: fe:1e:01:fe:ce:b4
emac-mii: probed
dm9000 Ethernet Driver, V1.31
console [netcon0] enabled
netconsole: network logging started
Linux video capture interface: v2.00
Driver 'sd' needs updating - please use bus_type methods
davinci_nand davinci_nand.1: Using 4-bit hardware ECC - Syndrome
No NAND device found!!!
irq = 12
__ipipe_mach_irq_mux_p false
dma_ccerr_handler
IRQ_HANDLED
irq = 12
__ipipe_mach_irq_mux_p false
dma_ccerr_handler
IRQ_HANDLED
m25p80 spi1.0: m25p64 (8192 Kbytes)
Creating 3 MTD partitions on "m25p80":
0x000000000000-0x000000040000 : "U-Boot"
0x000000040000-0x000000044000 : "U-Boot Environment"
Moving partition 2: 0x000000044000 -> 0x000000050000
0x000000050000-0x000000800000 : "Linux"
dm_spi.1: davinci SPI Controller driver at 0xfef0e000 (irq = 56) use_dma=1
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
usb1 usb1: DA8XX OHCI
usb1 usb1: new USB bus registered, assigned bus number 2
usb1 usb1: irq 59, io mem 0x01e25000
<some time later ... a couple of minutes>
irq = 22
__ipipe_mach_irq_mux_p false
irq = 22
__ipipe_mach_irq_mux_p false
Best regards,
Flavio
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > In fact,
> >
> > The problem is not really related to the other timer, I believe.
> >
> > Before the timer with irq 22 is called, another irq is called by
> > __ipipe_grab_irq(): the irq number 12 (IRQ_DA8XX_CCERRINT).
> >
> > Now I'm looking for the place there this irq number is passed.
> >
> > And thank you for this important information about the timers.
>
> I think your problem really is that irq22 uses handle_edge_irq, somehow.
> Could you check whether this is the case, for instance by putting a
> printk in the __ipipe_ack_edge_irq function, file kernel/irq/chip.c ?
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 6057 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 17:43 ` Flavio de Castro Alves Filho
@ 2010-01-08 18:02 ` Flavio de Castro Alves Filho
2010-01-08 18:08 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 18:02 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 5685 bytes --]
Another interesting information: when I remove the Xenomai from the
compilation options, and still letting the i-pipe compilation, the boot
starts correctly.
Is it correct?
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Flavio de Castro Alves Filho <flavio.alves@domain.hid>
> Hello,
>
> The functions level_egde_irq and __ipipe_ack_edge_irq are not called during
> boot process.
>
> I'm sending attached the boot log with my traces separated
>
> irq = 21
> __ipipe_mach_irq_mux_p false
>
> Linux version 2.6.29-rc8-davinci1 (flavio@domain.hid) (gcc version
> 4.3.3 (Sourcery G++ Lite 2009q1-203) ) #57 PREEMPT Fri Jan 8 13:58:39 BRST
> 2010
>
> CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=00053177
> CPU: VIVT data cache, VIVT instruction cache
> Machine: DaVinci DA850 EVM
> Memory policy: ECC disabled, Data cache writeback
> DA0850 variant 0x0
> Built 1 zonelists in Zone order, mobility grouping on. Total pages: 8128
> Kernel command line: mem=32M console=ttyS2,115200n8 root=/dev/ram0 rw
> initrd=0xc1180000,4M ip=10.1.1.2:10.1.1.1
>
> PID hash table entries: 128 (order: 7, 512 bytes)
> I-pipe 1.13-03: pipeline enabled.
> Console: colour dummy device 80x30
> Dentry cache hash table entries: 4096 (order: 2, 16384 bytes)
> Inode-cache hash table entries: 2048 (order: 1, 8192 bytes)
> Memory: 32MB = 32MB total
> Memory: 24236KB available (3592K code, 367K data, 148K init)
> Calibrating delay loop... 86.63 BogoMIPS (lpj=433152)
>
> Mount-cache hash table entries: 512
> CPU: Testing write buffer coherency: ok
> net_namespace: 880 bytes
> NET: Registered protocol family 16
> Pin I2C1_SCL already used for UART2_RXD.
> Pin I2C1_SDA already used for UART2_TXD.
> DaVinci: 144 gpio irqs
> bio: create slab <bio-0> at 0
> SCSI subsystem initialized
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> musb_hdrc: version 6.0, cppi4.1-dma, host, debug=0
> Waiting for PHY clock good...
> musb_hdrc: USB Host mode controller at fee00000 using DMA, IRQ 58
> musb_hdrc musb_hdrc: MUSB HDRC host driver
> musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
> usb usb1: configuration #1 chosen from 1 choice
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 1 port detected
> NET: Registered protocol family 2
> IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
> TCP established hash table entries: 1024 (order: 1, 8192 bytes)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes)
> TCP: Hash tables configured (established 1024 bind 1024)
> TCP reno registered
> NET: Registered protocol family 1
> checking if image is initramfs...it isn't (no cpio magic); looks like an
> initrd
> Freeing initrd memory: 4096K
> I-pipe: Domain Xenomai registered.
> Xenomai: hal/arm started.
> Xenomai: real-time nucleus v2.4.9.1 (Big Bad Moon) loaded.
> Xenomai: starting native API services.
> Xenomai: starting POSIX services.
> Xenomai: starting RTDM services.
> msgmni has been set to 55
> io scheduler noop registered
> io scheduler anticipatory registered (default)
> Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
> serial8250.0: ttyS0 at MMIO 0x1c42000 (irq = 25) is a 16550A
> serial8250.0: ttyS1 at MMIO 0x1d0c000 (irq = 53) is a 16550A
> serial8250.0: ttyS2 at MMIO 0x1d0d000 (irq = 61) is a 16550A
> console [ttyS2] enabled
> brd: module loaded
> davinci_emac_probe: using random MAC addr: fe:1e:01:fe:ce:b4
>
> emac-mii: probed
> dm9000 Ethernet Driver, V1.31
> console [netcon0] enabled
> netconsole: network logging started
> Linux video capture interface: v2.00
> Driver 'sd' needs updating - please use bus_type methods
> davinci_nand davinci_nand.1: Using 4-bit hardware ECC - Syndrome
> No NAND device found!!!
>
> irq = 12
> __ipipe_mach_irq_mux_p false
> dma_ccerr_handler
> IRQ_HANDLED
> irq = 12
> __ipipe_mach_irq_mux_p false
> dma_ccerr_handler
> IRQ_HANDLED
>
> m25p80 spi1.0: m25p64 (8192 Kbytes)
> Creating 3 MTD partitions on "m25p80":
> 0x000000000000-0x000000040000 : "U-Boot"
> 0x000000040000-0x000000044000 : "U-Boot Environment"
> Moving partition 2: 0x000000044000 -> 0x000000050000
> 0x000000050000-0x000000800000 : "Linux"
> dm_spi.1: davinci SPI Controller driver at 0xfef0e000 (irq = 56) use_dma=1
> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> usb1 usb1: DA8XX OHCI
> usb1 usb1: new USB bus registered, assigned bus number 2
> usb1 usb1: irq 59, io mem 0x01e25000
>
> <some time later ... a couple of minutes>
>
> irq = 22
> __ipipe_mach_irq_mux_p false
> irq = 22
> __ipipe_mach_irq_mux_p false
>
>
> Best regards,
>
> Flavio
>
>
> Flavio de Castro Alves Filho
> Phi Innovations - Embedded Software Services
> www.phiinnovations.com
> Phone: +55 11 84 94 56 76
> Skype: flavio.de.castro.alves.filho
>
>
> 2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
>
>> Flavio de Castro Alves Filho wrote:
>> > In fact,
>> >
>> > The problem is not really related to the other timer, I believe.
>> >
>> > Before the timer with irq 22 is called, another irq is called by
>> > __ipipe_grab_irq(): the irq number 12 (IRQ_DA8XX_CCERRINT).
>> >
>> > Now I'm looking for the place there this irq number is passed.
>> >
>> > And thank you for this important information about the timers.
>>
>> I think your problem really is that irq22 uses handle_edge_irq, somehow.
>> Could you check whether this is the case, for instance by putting a
>> printk in the __ipipe_ack_edge_irq function, file kernel/irq/chip.c ?
>>
>> --
>> Gilles.
>>
>
>
[-- Attachment #2: Type: text/html, Size: 7066 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 18:02 ` Flavio de Castro Alves Filho
@ 2010-01-08 18:08 ` Gilles Chanteperdrix
2010-01-08 19:27 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 18:08 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Another interesting information: when I remove the Xenomai from the
> compilation options, and still letting the i-pipe compilation, the boot
> starts correctly.
>
> Is it correct?
It means that there is something wrong when Xenomai takes over the timer
management. And thinking more about it, the problem you have is probably
the one described in tips and tricks number 4.
http://www.xenomai.org/index.php/I-pipe:ArmPorting#Tips_and_tricks.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 18:08 ` Gilles Chanteperdrix
@ 2010-01-08 19:27 ` Flavio de Castro Alves Filho
2010-01-08 19:31 ` Gilles Chanteperdrix
2010-01-08 19:32 ` Gilles Chanteperdrix
0 siblings, 2 replies; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 19:27 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: xenomai
[-- Attachment #1: Type: text/plain, Size: 1105 bytes --]
Not this time :-(
I increased the value, but it didn't work.
I was thinking here. The problem related in the first message of this thread
is exactly the same problem that I am having:
http://www.mail-archive.com/xenomai@xenomai.org
How this problem was solved? I couldn't find (or understand) the answer.
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > Another interesting information: when I remove the Xenomai from the
> > compilation options, and still letting the i-pipe compilation, the boot
> > starts correctly.
> >
> > Is it correct?
>
> It means that there is something wrong when Xenomai takes over the timer
> management. And thinking more about it, the problem you have is probably
> the one described in tips and tricks number 4.
>
> http://www.xenomai.org/index.php/I-pipe:ArmPorting#Tips_and_tricks.
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 1825 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 19:27 ` Flavio de Castro Alves Filho
@ 2010-01-08 19:31 ` Gilles Chanteperdrix
2010-01-08 19:42 ` Flavio de Castro Alves Filho
2010-01-08 19:32 ` Gilles Chanteperdrix
1 sibling, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 19:31 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Not this time :-(
>
> I increased the value, but it didn't work.
>
> I was thinking here. The problem related in the first message of this thread
> is exactly the same problem that I am having:
>
> http://www.mail-archive.com/xenomai@xenomai.org
The answer is here:
http://www.mail-archive.com/xenomai@xenomai.org
Sergey copied the PXA hardware timer support (a free-running counter
with a match register) instead of writing the code for his real hardware
timer (a decrementer). This could not work.
So, now, the only thing I can suggest you is to show us your code.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 19:27 ` Flavio de Castro Alves Filho
2010-01-08 19:31 ` Gilles Chanteperdrix
@ 2010-01-08 19:32 ` Gilles Chanteperdrix
1 sibling, 0 replies; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 19:32 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Not this time :-(
>
> I increased the value, but it didn't work.
This is not what you should be doing. What you should be doing is read
the datasheet to know what the minimum value is.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 19:31 ` Gilles Chanteperdrix
@ 2010-01-08 19:42 ` Flavio de Castro Alves Filho
2010-01-08 19:45 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 19:42 UTC (permalink / raw)
To: xenomai
[-- Attachment #1.1: Type: text/plain, Size: 937 bytes --]
Of course :-)
As I don't know the best way to send it, I attached the files.
I hope everything is in there. I'm sorry if you find some ugly commented
debug code.
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > Not this time :-(
> >
> > I increased the value, but it didn't work.
> >
> > I was thinking here. The problem related in the first message of this
> thread
> > is exactly the same problem that I am having:
> >
> > http://www.mail-archive.com/xenomai@xenomai.org
>
> The answer is here:
> http://www.mail-archive.com/xenomai@xenomai.org
>
> Sergey copied the PXA hardware timer support (a free-running counter
> with a match register) instead of writing the code for his real hardware
> timer (a decrementer). This could not work.
>
> So, now, the only thing I can suggest you is to show us your code.
>
> --
> Gilles.
>
[-- Attachment #1.2: Type: text/html, Size: 1566 bytes --]
[-- Attachment #2: gpio.c --]
[-- Type: text/x-csrc, Size: 9854 bytes --]
/*
* TI DaVinci GPIO Support
*
* Copyright (c) 2006-2007 David Brownell
* Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/bitops.h>
#include <mach/cpu.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
#include <asm/mach/irq.h>
#include <asm/ipipe.h>
static DEFINE_SPINLOCK(gpio_lock);
struct davinci_gpio {
struct gpio_chip chip;
struct gpio_controller *__iomem regs;
};
static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
static unsigned __initdata ngpio;
/* create a non-inlined version */
static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio)
{
return __gpio_to_controller(gpio);
}
/*--------------------------------------------------------------------------*/
/*
* board setup code *MUST* set PINMUX0 and PINMUX1 as
* needed, and enable the GPIO clock.
*/
static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
struct gpio_controller *__iomem g = d->regs;
u32 temp;
spin_lock(&gpio_lock);
temp = __raw_readl(&g->dir);
temp |= (1 << offset);
__raw_writel(temp, &g->dir);
spin_unlock(&gpio_lock);
return 0;
}
/*
* Read the pin's value (works even if it's set up as output);
* returns zero/nonzero.
*
* Note that changes are synched to the GPIO clock, so reading values back
* right after you've set them may give old values.
*/
static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
struct gpio_controller *__iomem g = d->regs;
return (1 << offset) & __raw_readl(&g->in_data);
}
static int
davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
{
struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
struct gpio_controller *__iomem g = d->regs;
u32 temp;
u32 mask = 1 << offset;
spin_lock(&gpio_lock);
temp = __raw_readl(&g->dir);
temp &= ~mask;
__raw_writel(mask, value ? &g->set_data : &g->clr_data);
__raw_writel(temp, &g->dir);
spin_unlock(&gpio_lock);
return 0;
}
/*
* Assuming the pin is muxed as a gpio output, set its output value.
*/
static void
davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip);
struct gpio_controller *__iomem g = d->regs;
__raw_writel((1 << offset), value ? &g->set_data : &g->clr_data);
}
static int __init davinci_gpio_setup(void)
{
int i, base;
/* The gpio banks conceptually expose a segmented bitmap,
* and "ngpio" is one more than the largest zero-based
* bit index that's valid.
*/
if (cpu_is_davinci_dm355()) { /* or dm335() */
ngpio = 104;
} else if (cpu_is_davinci_dm644x()) { /* or dm337() */
ngpio = 71;
} else if (cpu_is_davinci_dm646x()) {
/* NOTE: each bank has several "reserved" bits,
* unusable as GPIOs. Only 33 of the GPIO numbers
* are usable, and we're not rejecting the others.
*/
ngpio = 43;
} else if (cpu_is_da830()) { /* or da830 */
ngpio = 128;
} else if (cpu_is_da850()) {
ngpio = 144;
} else {
/* if cpu_is_davinci_dm643x() ngpio = 111 */
pr_err("GPIO setup: how many GPIOs?\n");
return -EINVAL;
}
if (WARN_ON(DAVINCI_N_GPIO < ngpio))
ngpio = DAVINCI_N_GPIO;
for (i = 0, base = 0; base < ngpio; i++, base += 32) {
chips[i].chip.label = "DaVinci";
chips[i].chip.direction_input = davinci_direction_in;
chips[i].chip.get = davinci_gpio_get;
chips[i].chip.direction_output = davinci_direction_out;
chips[i].chip.set = davinci_gpio_set;
chips[i].chip.base = base;
chips[i].chip.ngpio = ngpio - base;
if (chips[i].chip.ngpio > 32)
chips[i].chip.ngpio = 32;
chips[i].regs = gpio2controller(base);
gpiochip_add(&chips[i].chip);
}
return 0;
}
pure_initcall(davinci_gpio_setup);
/*--------------------------------------------------------------------------*/
/*
* We expect irqs will normally be set up as input pins, but they can also be
* used as output pins ... which is convenient for testing.
*
* NOTE: The first few GPIOs also have direct INTC hookups in addition
* to their GPIOBNK0 irq, with a bit less overhead but less flexibility
* on triggering (e.g. no edge options). We don't try to use those.
*
* All those INTC hookups (direct, plus several IRQ banks) can also
* serve as EDMA event triggers.
*/
static void gpio_irq_disable(unsigned irq)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
u32 mask = __gpio_mask(irq_to_gpio(irq));
__raw_writel(mask, &g->clr_falling);
__raw_writel(mask, &g->clr_rising);
}
static void gpio_irq_enable(unsigned irq)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
u32 mask = __gpio_mask(irq_to_gpio(irq));
if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
__raw_writel(mask, &g->set_falling);
if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
__raw_writel(mask, &g->set_rising);
}
static int gpio_irq_type(unsigned irq, unsigned trigger)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
u32 mask = __gpio_mask(irq_to_gpio(irq));
if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
return -EINVAL;
irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
irq_desc[irq].status |= trigger;
__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
? &g->set_falling : &g->clr_falling);
__raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
? &g->set_rising : &g->clr_rising);
return 0;
}
static struct irq_chip gpio_irqchip = {
.name = "GPIO",
.enable = gpio_irq_enable,
.disable = gpio_irq_disable,
.set_type = gpio_irq_type,
};
static void
gpio_irq_handler(unsigned irq, struct irq_desc *desc)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
u32 mask = 0xffff;
/* we only care about one bank */
if (irq & 1)
mask <<= 16;
/* temporarily mask (level sensitive) parent IRQ */
desc->chip->ack(irq);
while (1) {
u32 status;
int n;
int res;
/* ack any irqs */
status = __raw_readl(&g->intstat) & mask;
if (!status)
break;
__raw_writel(status, &g->intstat);
if (irq & 1)
status >>= 16;
/* now demux them to the right lowlevel handler */
n = (int)get_irq_data(irq);
while (status) {
res = ffs(status);
n += res;
generic_handle_irq(n - 1);
status >>= res;
}
}
desc->chip->unmask(irq);
/* now it may re-trigger */
}
#ifdef CONFIG_IPIPE
/* Flavio Alves: for debugging */
extern void printascii(const char *);
void __ipipe_mach_demux_irq(unsigned irq, struct pt_regs *regs)
{
struct gpio_controller *__iomem g = get_irq_chip_data(irq);
struct irq_desc *desc;
u32 mask = 0xffff;
//printascii("1__ipipe_mach_demux_irq\n");
/* we only care about one bank */
if (irq & 1)
mask <<= 16;
desc = &irq_desc[irq];
/* temporarily mask (level sensitive) parent IRQ */
desc->chip->ack(irq);
while (1) {
u32 status;
int n;
int res;
/* ack any irqs */
status = __raw_readl(&g->intstat) & mask;
if (!status)
break;
__raw_writel(status, &g->intstat);
if (irq & 1)
status >>= 16;
/* now demux them to the right lowlevel handler */
n = (int)get_irq_data(irq);
while (status) {
res = ffs(status);
n += res;
__ipipe_handle_irq((n-1),regs);
status >>= res;
}
}
desc->chip->unmask(irq);
/* now it may re-trigger */
}
#endif /* CONFIG_IPIPE */
/*
* NOTE: for suspend/resume, probably best to make a platform_device with
* suspend_late/resume_resume calls hooking into results of the set_wake()
* calls ... so if no gpios are wakeup events the clock can be disabled,
* with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
* (dm6446) can be set appropriately for GPIOV33 pins.
*/
static int __init davinci_gpio_irq_setup(void)
{
unsigned gpio, irq, bank;
unsigned bank_irq;
struct clk *clk;
u32 binten = 0;
if (cpu_is_davinci_dm355()) { /* or dm335() */
bank_irq = IRQ_DM355_GPIOBNK0;
} else if (cpu_is_davinci_dm644x()) {
bank_irq = IRQ_GPIOBNK0;
} else if (cpu_is_davinci_dm646x()) {
bank_irq = IRQ_DM646X_GPIOBNK0;
} else if (cpu_is_da8xx()) {
bank_irq = IRQ_DA8XX_GPIO0;
} else {
printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
return -EINVAL;
}
clk = clk_get(NULL, "gpio");
if (IS_ERR(clk)) {
printk(KERN_ERR "Error %ld getting gpio clock?\n",
PTR_ERR(clk));
return PTR_ERR(clk);
}
clk_enable(clk);
for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
gpio < ngpio;
bank++, bank_irq++) {
struct gpio_controller *__iomem g = gpio2controller(gpio);
unsigned i;
__raw_writel(~0, &g->clr_falling);
__raw_writel(~0, &g->clr_rising);
/* set up all irqs in this bank */
set_irq_chained_handler(bank_irq, gpio_irq_handler);
set_irq_chip_data(bank_irq, g);
set_irq_data(bank_irq, (void *)irq);
for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
set_irq_chip(irq, &gpio_irqchip);
set_irq_chip_data(irq, g);
set_irq_handler(irq, handle_simple_irq);
set_irq_flags(irq, IRQF_VALID);
}
binten |= BIT(bank);
}
/* BINTEN -- per-bank interrupt enable. genirq would also let these
* bits be set/cleared dynamically.
*/
__raw_writel(binten, (void *__iomem)
IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
return 0;
}
arch_initcall(davinci_gpio_irq_setup);
[-- Attachment #3: irq.c --]
[-- Type: text/x-csrc, Size: 14712 bytes --]
/*
* Interrupt handler for DaVinci boards.
*
* Copyright (C) 2006 Texas Instruments.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/cpu.h>
#include <asm/io.h>
#include <asm/mach/irq.h>
#define IRQ_BIT(irq) ((irq) & 0x1f)
#define FIQ_REG0_OFFSET 0x0000
#define FIQ_REG1_OFFSET 0x0004
#define IRQ_REG0_OFFSET 0x0008
#define IRQ_REG1_OFFSET 0x000C
#define IRQ_ENT_REG0_OFFSET 0x0018
#define IRQ_ENT_REG1_OFFSET 0x001C
#define IRQ_INCTL_REG_OFFSET 0x0020
#define IRQ_EABASE_REG_OFFSET 0x0024
#define IRQ_INTPRI0_REG_OFFSET 0x0030
#define IRQ_INTPRI7_REG_OFFSET 0x004C
const u8 *davinci_def_priorities;
#define INTC_BASE IO_ADDRESS(DAVINCI_ARM_INTC_BASE)
static inline unsigned int davinci_irq_readl(int offset)
{
return __raw_readl(INTC_BASE + offset);
}
static inline void davinci_irq_writel(unsigned long value, int offset)
{
__raw_writel(value, INTC_BASE + offset);
}
/* Disable interrupt */
static void davinci_mask_irq(unsigned int irq)
{
unsigned int mask;
u32 l;
mask = 1 << IRQ_BIT(irq);
if (irq > 31) {
l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
l &= ~mask;
davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
} else {
l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
l &= ~mask;
davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
}
}
/* Enable interrupt */
static void davinci_unmask_irq(unsigned int irq)
{
unsigned int mask;
u32 l;
mask = 1 << IRQ_BIT(irq);
if (irq > 31) {
l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
l |= mask;
davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
} else {
l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
l |= mask;
davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
}
}
/* EOI interrupt */
static void davinci_ack_irq(unsigned int irq)
{
unsigned int mask;
mask = 1 << IRQ_BIT(irq);
if (irq > 31)
davinci_irq_writel(mask, IRQ_REG1_OFFSET);
else
davinci_irq_writel(mask, IRQ_REG0_OFFSET);
}
static struct irq_chip davinci_irq_chip_0 = {
.name = "AINTC",
.ack = davinci_ack_irq,
.mask = davinci_mask_irq,
#ifdef CONFIG_IPIPE
.mask_ack = davinci_mask_irq,
#endif /* CONFIG_IPIPE */
.unmask = davinci_unmask_irq,
};
#ifdef CONFIG_IPIPE
static const u8 da850_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
[IRQ_DA8XX_COMMTX] = 7,
[IRQ_DA8XX_COMMRX] = 7,
[IRQ_DA8XX_NINT] = 7,
[IRQ_DA8XX_EVTOUT0] = 7,
[IRQ_DA8XX_EVTOUT1] = 7,
[IRQ_DA8XX_EVTOUT2] = 7,
[IRQ_DA8XX_EVTOUT3] = 7,
[IRQ_DA8XX_EVTOUT4] = 7,
[IRQ_DA8XX_EVTOUT5] = 7,
[IRQ_DA8XX_EVTOUT6] = 7,
[IRQ_DA8XX_EVTOUT7] = 7,
[IRQ_DA8XX_CCINT0] = 7,
[IRQ_DA8XX_CCERRINT] = 7,
[IRQ_DA8XX_TCERRINT0] = 7,
[IRQ_DA8XX_AEMIFINT] = 7,
[IRQ_DA8XX_I2CINT0] = 5,
[IRQ_DA8XX_MMCSDINT0] = 5,
[IRQ_DA8XX_MMCSDINT1] = 5,
[IRQ_DA8XX_ALLINT0] = 5,
[IRQ_DA8XX_RTC] = 4,
[IRQ_DA8XX_SPINT0] = 5,
[IRQ_DA8XX_TINT12_0] = 2,
[IRQ_DA8XX_TINT34_0] = 5,
[IRQ_DA8XX_TINT12_1] = 5,
[IRQ_DA8XX_TINT34_1] = 5,
[IRQ_DA8XX_UARTINT0] = 5,
[IRQ_DA8XX_KEYMGRINT] = 7,
[IRQ_DA850_MIOPU_BOOTCFG_ERR] = 7,
[IRQ_DA8XX_CHIPINT0] = 7,
[IRQ_DA8XX_CHIPINT1] = 7,
[IRQ_DA8XX_CHIPINT2] = 7,
[IRQ_DA8XX_CHIPINT3] = 7,
[IRQ_DA8XX_TCERRINT1] = 7,
[IRQ_DA8XX_C0_RX_THRESH_PULSE] = 7,
[IRQ_DA8XX_C0_RX_PULSE] = 7,
[IRQ_DA8XX_C0_TX_PULSE] = 7,
[IRQ_DA8XX_C0_MISC_PULSE] = 7,
[IRQ_DA8XX_C1_RX_THRESH_PULSE] = 7,
[IRQ_DA8XX_C1_RX_PULSE] = 7,
[IRQ_DA8XX_C1_TX_PULSE] = 7,
[IRQ_DA8XX_C1_MISC_PULSE] = 7,
[IRQ_DA8XX_MEMERR] = 5,
[IRQ_DA8XX_GPIO0] = 6,
[IRQ_DA8XX_GPIO1] = 6,
[IRQ_DA8XX_GPIO2] = 6,
[IRQ_DA8XX_GPIO3] = 6,
[IRQ_DA8XX_GPIO4] = 6,
[IRQ_DA8XX_GPIO5] = 6,
[IRQ_DA8XX_GPIO6] = 6,
[IRQ_DA8XX_GPIO7] = 6,
[IRQ_DA8XX_GPIO8] = 6,
[IRQ_DA8XX_I2CINT1] = 5,
[IRQ_DA8XX_LCDINT] = 5,
[IRQ_DA8XX_UARTINT1] = 5,
[IRQ_DA8XX_MCASPINT] = 5,
[IRQ_DA8XX_ALLINT1] = 5,
[IRQ_DA8XX_SPINT1] = 5,
[IRQ_DA8XX_UHPI_INT1] = 5,
[IRQ_DA8XX_USB_INT] = 5,
[IRQ_DA8XX_IRQN] = 5,
[IRQ_DA8XX_RWAKEUP] = 5,
[IRQ_DA8XX_UARTINT2] = 5,
[IRQ_DA8XX_DFTSSINT] = 5,
[IRQ_DA8XX_EHRPWM0] = 7,
[IRQ_DA8XX_EHRPWM0TZ] = 7,
[IRQ_DA8XX_EHRPWM1] = 7,
[IRQ_DA8XX_EHRPWM1TZ] = 7,
[IRQ_DA850_SATAINT] = 5,
[IRQ_DA850_TINT12_2] = 5,
[IRQ_DA8XX_ECAP0] = 7,
[IRQ_DA8XX_ECAP1] = 7,
[IRQ_DA8XX_ECAP2] = 7,
[IRQ_DA850_MMCSDINT0_1] = 5,
[IRQ_DA850_MMCSDINT1_1] = 5,
[IRQ_DA850_T12CMPINT0_2] = 7,
[IRQ_DA850_T12CMPINT1_2] = 7,
[IRQ_DA850_T12CMPINT2_2] = 7,
[IRQ_DA850_T12CMPINT3_2] = 7,
[IRQ_DA850_T12CMPINT4_2] = 7,
[IRQ_DA850_T12CMPINT5_2] = 7,
[IRQ_DA850_T12CMPINT6_2] = 7,
[IRQ_DA850_T12CMPINT7_2] = 7,
[IRQ_DA850_T12CMPINT0_3] = 7,
[IRQ_DA850_T12CMPINT1_3] = 7,
[IRQ_DA850_T12CMPINT2_3] = 7,
[IRQ_DA850_T12CMPINT3_3] = 7,
[IRQ_DA850_T12CMPINT4_3] = 7,
[IRQ_DA850_T12CMPINT5_3] = 7,
[IRQ_DA850_T12CMPINT6_3] = 7,
[IRQ_DA850_T12CMPINT7_3] = 7,
[IRQ_DA8XX_ARMCLKSTOPREQ] = 7,
[IRQ_DA850_RPIINT] = 7,
[IRQ_DA850_VPIFINT] = 7,
[IRQ_DA850_CCINT1] = 7,
[IRQ_DA850_CCERRINT1] = 7,
[IRQ_DA850_TCERRINT2] = 7,
[IRQ_DA850_TINT12_3] = 5,
[IRQ_DA850_MCBSP0RINT] = 5,
[IRQ_DA850_MCBSP0XINT] = 5,
[IRQ_DA850_MCBSP1RINT] = 5,
[IRQ_DA850_MCBSP1XINT] = 5
};
#endif /* CONFIG_IPIPE */
/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
[IRQ_VDINT0] = 2,
[IRQ_VDINT1] = 6,
[IRQ_VDINT2] = 6,
[IRQ_HISTINT] = 6,
[IRQ_H3AINT] = 6,
[IRQ_PRVUINT] = 6,
[IRQ_RSZINT] = 6,
[7] = 7,
[IRQ_VENCINT] = 6,
[IRQ_ASQINT] = 6,
[IRQ_IMXINT] = 6,
[IRQ_VLCDINT] = 6,
[IRQ_USBINT] = 4,
[IRQ_EMACINT] = 4,
[14] = 7,
[15] = 7,
[IRQ_CCINT0] = 5, /* dma */
[IRQ_CCERRINT] = 5, /* dma */
[IRQ_TCERRINT0] = 5, /* dma */
[IRQ_TCERRINT] = 5, /* dma */
[IRQ_PSCIN] = 7,
[21] = 7,
[IRQ_IDE] = 4,
[23] = 7,
[IRQ_MBXINT] = 7,
[IRQ_MBRINT] = 7,
[IRQ_MMCINT] = 7,
[IRQ_SDIOINT] = 7,
[28] = 7,
[IRQ_DDRINT] = 7,
[IRQ_AEMIFINT] = 7,
[IRQ_VLQINT] = 4,
[IRQ_TINT0_TINT12] = 2, /* clockevent */
[IRQ_TINT0_TINT34] = 2, /* clocksource */
[IRQ_TINT1_TINT12] = 7, /* DSP timer */
[IRQ_TINT1_TINT34] = 7, /* system tick */
[IRQ_PWMINT0] = 7,
[IRQ_PWMINT1] = 7,
[IRQ_PWMINT2] = 7,
[IRQ_I2C] = 3,
[IRQ_UARTINT0] = 3,
[IRQ_UARTINT1] = 3,
[IRQ_UARTINT2] = 3,
[IRQ_SPINT0] = 3,
[IRQ_SPINT1] = 3,
[45] = 7,
[IRQ_DSP2ARM0] = 4,
[IRQ_DSP2ARM1] = 4,
[IRQ_GPIO0] = 7,
[IRQ_GPIO1] = 7,
[IRQ_GPIO2] = 7,
[IRQ_GPIO3] = 7,
[IRQ_GPIO4] = 7,
[IRQ_GPIO5] = 7,
[IRQ_GPIO6] = 7,
[IRQ_GPIO7] = 7,
[IRQ_GPIOBNK0] = 7,
[IRQ_GPIOBNK1] = 7,
[IRQ_GPIOBNK2] = 7,
[IRQ_GPIOBNK3] = 7,
[IRQ_GPIOBNK4] = 7,
[IRQ_COMMTX] = 7,
[IRQ_COMMRX] = 7,
[IRQ_EMUINT] = 7,
};
static const u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
[IRQ_DM646X_VP_VERTINT0] = 7,
[IRQ_DM646X_VP_VERTINT1] = 7,
[IRQ_DM646X_VP_VERTINT2] = 7,
[IRQ_DM646X_VP_VERTINT3] = 7,
[IRQ_DM646X_VP_ERRINT] = 7,
[IRQ_DM646X_RESERVED_1] = 7,
[IRQ_DM646X_RESERVED_2] = 7,
[IRQ_DM646X_WDINT] = 7,
[IRQ_DM646X_CRGENINT0] = 7,
[IRQ_DM646X_CRGENINT1] = 7,
[IRQ_DM646X_TSIFINT0] = 7,
[IRQ_DM646X_TSIFINT1] = 7,
[IRQ_DM646X_VDCEINT] = 7,
[IRQ_DM646X_USBINT] = 7,
[IRQ_DM646X_USBDMAINT] = 7,
[IRQ_DM646X_PCIINT] = 7,
[IRQ_CCINT0] = 7, /* dma */
[IRQ_CCERRINT] = 7, /* dma */
[IRQ_TCERRINT0] = 7, /* dma */
[IRQ_TCERRINT] = 7, /* dma */
[IRQ_DM646X_TCERRINT2] = 7,
[IRQ_DM646X_TCERRINT3] = 7,
[IRQ_DM646X_IDE] = 7,
[IRQ_DM646X_HPIINT] = 7,
[IRQ_DM646X_EMACRXTHINT] = 7,
[IRQ_DM646X_EMACRXINT] = 7,
[IRQ_DM646X_EMACTXINT] = 7,
[IRQ_DM646X_EMACMISCINT] = 7,
[IRQ_DM646X_MCASP0TXINT] = 7,
[IRQ_DM646X_MCASP0RXINT] = 7,
[IRQ_AEMIFINT] = 7,
[IRQ_DM646X_RESERVED_3] = 7,
[IRQ_DM646X_MCASP1TXINT] = 7, /* clockevent */
[IRQ_TINT0_TINT34] = 7, /* clocksource */
[IRQ_TINT1_TINT12] = 7, /* DSP timer */
[IRQ_TINT1_TINT34] = 7, /* system tick */
[IRQ_PWMINT0] = 7,
[IRQ_PWMINT1] = 7,
[IRQ_DM646X_VLQINT] = 7,
[IRQ_I2C] = 7,
[IRQ_UARTINT0] = 7,
[IRQ_UARTINT1] = 7,
[IRQ_DM646X_UARTINT2] = 7,
[IRQ_DM646X_SPINT0] = 7,
[IRQ_DM646X_SPINT1] = 7,
[IRQ_DM646X_DSP2ARMINT] = 7,
[IRQ_DM646X_RESERVED_4] = 7,
[IRQ_DM646X_PSCINT] = 7,
[IRQ_DM646X_GPIO0] = 7,
[IRQ_DM646X_GPIO1] = 7,
[IRQ_DM646X_GPIO2] = 7,
[IRQ_DM646X_GPIO3] = 7,
[IRQ_DM646X_GPIO4] = 7,
[IRQ_DM646X_GPIO5] = 7,
[IRQ_DM646X_GPIO6] = 7,
[IRQ_DM646X_GPIO7] = 7,
[IRQ_DM646X_GPIOBNK0] = 7,
[IRQ_DM646X_GPIOBNK1] = 7,
[IRQ_DM646X_GPIOBNK2] = 7,
[IRQ_DM646X_DDRINT] = 7,
[IRQ_DM646X_AEMIFINT] = 7,
[IRQ_COMMTX] = 7,
[IRQ_COMMRX] = 7,
[IRQ_EMUINT] = 7,
};
static const u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
[IRQ_DM355_CCDC_VDINT0] = 2,
[IRQ_DM355_CCDC_VDINT1] = 6,
[IRQ_DM355_CCDC_VDINT2] = 6,
[IRQ_DM355_IPIPE_HST] = 6,
[IRQ_DM355_H3AINT] = 6,
[IRQ_DM355_IPIPE_SDR] = 6,
[IRQ_DM355_IPIPEIFINT] = 6,
[IRQ_DM355_OSDINT] = 7,
[IRQ_DM355_VENCINT] = 6,
[IRQ_ASQINT] = 6,
[IRQ_IMXINT] = 6,
[IRQ_USBINT] = 4,
[IRQ_DM355_RTOINT] = 4,
[IRQ_DM355_UARTINT2] = 7,
[IRQ_DM355_TINT6] = 7,
[IRQ_CCINT0] = 5, /* dma */
[IRQ_CCERRINT] = 5, /* dma */
[IRQ_TCERRINT0] = 5, /* dma */
[IRQ_TCERRINT] = 5, /* dma */
[IRQ_DM355_SPINT2_1] = 7,
[IRQ_DM355_TINT7] = 4,
[IRQ_DM355_SDIOINT0] = 7,
[IRQ_MBXINT] = 7,
[IRQ_MBRINT] = 7,
[IRQ_MMCINT] = 7,
[IRQ_DM355_MMCINT1] = 7,
[IRQ_DM355_PWMINT3] = 7,
[IRQ_DDRINT] = 7,
[IRQ_AEMIFINT] = 7,
[IRQ_DM355_SDIOINT1] = 4,
[IRQ_TINT0_TINT12] = 2, /* clockevent */
[IRQ_TINT0_TINT34] = 2, /* clocksource */
[IRQ_TINT1_TINT12] = 7, /* DSP timer */
[IRQ_TINT1_TINT34] = 7, /* system tick */
[IRQ_PWMINT0] = 7,
[IRQ_PWMINT1] = 7,
[IRQ_PWMINT2] = 7,
[IRQ_I2C] = 3,
[IRQ_UARTINT0] = 3,
[IRQ_UARTINT1] = 3,
[IRQ_DM355_SPINT0_0] = 3,
[IRQ_DM355_SPINT0_1] = 3,
[IRQ_DM355_GPIO0] = 3,
[IRQ_DM355_GPIO1] = 7,
[IRQ_DM355_GPIO2] = 4,
[IRQ_DM355_GPIO3] = 4,
[IRQ_DM355_GPIO4] = 7,
[IRQ_DM355_GPIO5] = 7,
[IRQ_DM355_GPIO6] = 7,
[IRQ_DM355_GPIO7] = 7,
[IRQ_DM355_GPIO8] = 7,
[IRQ_DM355_GPIO9] = 7,
[IRQ_DM355_GPIOBNK0] = 7,
[IRQ_DM355_GPIOBNK1] = 7,
[IRQ_DM355_GPIOBNK2] = 7,
[IRQ_DM355_GPIOBNK3] = 7,
[IRQ_DM355_GPIOBNK4] = 7,
[IRQ_DM355_GPIOBNK5] = 7,
[IRQ_DM355_GPIOBNK6] = 7,
[IRQ_COMMTX] = 7,
[IRQ_COMMRX] = 7,
[IRQ_EMUINT] = 7,
};
/* ARM Interrupt Controller Initialization */
void __init davinci_irq_init(void)
{
unsigned i;
if (cpu_is_davinci_dm644x())
davinci_def_priorities = dm644x_default_priorities;
else if (cpu_is_davinci_dm646x())
davinci_def_priorities = dm646x_default_priorities;
else if (cpu_is_davinci_dm355())
davinci_def_priorities = dm355_default_priorities;
#ifdef CONFIG_IPIPE
else if (cpu_is_da850())
davinci_def_priorities = da850_default_priorities;
#endif /* CONFIG_IPIPE */
/* Clear all interrupt requests */
davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
/* Disable all interrupts */
davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET);
davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET);
/* Interrupts disabled immediately, IRQ entry reflects all */
davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET);
/* we don't use the hardware vector table, just its entry addresses */
davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET);
/* Clear all interrupt requests */
davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) {
unsigned j;
u32 pri;
for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++)
pri |= (*davinci_def_priorities & 0x07) << j;
davinci_irq_writel(pri, i);
}
/* set up genirq dispatch for ARM INTC */
for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
set_irq_chip(i, &davinci_irq_chip_0);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
#ifndef CONFIG_IPIPE
if (i != IRQ_TINT1_TINT34)
set_irq_handler(i, handle_edge_irq);
else
#endif /* CONFIG IPIPE */
set_irq_handler(i, handle_level_irq);
}
}
[-- Attachment #4: time.c --]
[-- Type: text/x-csrc, Size: 18565 bytes --]
/*
* DaVinci timer subsystem
*
* Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
*
* 2007 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/device.h>
#include <mach/da8xx.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/errno.h>
#include <mach/io.h>
#include <mach/cpu.h>
#include "clock.h"
#ifdef CONFIG_IPIPE
#ifdef CONFIG_NO_IDLE_HZ
#error "dynamic tick timer not yet supported with IPIPE"
#endif /* CONFIG_NO_IDLE_HZ */
#endif /* CONFIG_IPIPE */
static struct clock_event_device clockevent_davinci;
static unsigned int davinci_clock_tick_rate;
#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
#define DA8XX_TIMER64P0_BASE 0x01C20000
#define DA8XX_TIMER64P1_BASE 0x01C21000
enum {
T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
};
#define IS_TIMER1(id) (id & 0x2)
#define IS_TIMER0(id) (!IS_TIMER1(id))
#define IS_TIMER_TOP(id) ((id & 0x1))
#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
static int default_timer_irqs[NUM_TIMERS] = {
IRQ_TINT0_TINT12,
IRQ_TINT0_TINT34,
IRQ_TINT1_TINT12,
IRQ_TINT1_TINT34,
};
static int da8xx_timer_irqs[NUM_TIMERS] = {
IRQ_DA8XX_TINT12_0,
IRQ_DA8XX_TINT34_0,
IRQ_DA8XX_TINT12_1,
IRQ_DA8XX_TINT34_1
};
/* Compare registers are only available to the bottom timer 0 */
static int da830_cmp_irqs[NUM_TIMERS] = {
IRQ_DA830_T12CMPINT0_0,
};
static int tid_system;
static int tid_freerun;
#ifdef CONFIG_IPIPE
int __ipipe_mach_timerint = IRQ_DA8XX_TINT12_0;
int __ipipe_mach_timerstolen = 0;
unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
static int davinci_timer_initialized;
union tsc_reg {
#ifdef __BIG_ENDIAN
struct {
unsigned long high;
unsigned long low;
};
#else /* __LITTLE_ENDIAN */
struct {
unsigned long low;
unsigned long high;
};
#endif /* __LITTLE_ENDIAN */
unsigned long long full;
};
#endif /* CONFIG_IPIPE */
/*
* This driver configures the 2 64-bit count-up timers as 4 independent
* 32-bit count-up timers used as follows:
*
* T0_BOT: Timer 0, bottom: clockevent source for hrtimers
* T0_TOP: Timer 0, top : clocksource for generic timekeeping
* T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
* T1_TOP: Timer 1, top : <unused>
*/
#define TID_CLOCKEVENT T0_BOT
#define TID_CLOCKSOURCE T0_TOP
/* Timer register offsets */
#define PID12 0x0
#define TIM12 0x10
#define TIM34 0x14
#define PRD12 0x18
#define PRD34 0x1c
#define TCR 0x20
#define TGCR 0x24
#define WDTCR 0x28
#define CMP12(n) (0x60 + ((n) << 2))
#define INTCTLSTAT 0x44
/* Timer register bitfields */
#define TCR_ENAMODE_DISABLE 0x0
#define TCR_ENAMODE_ONESHOT 0x1
#define TCR_ENAMODE_PERIODIC 0x2
#define TCR_ENAMODE_MASK 0x3
#define TGCR_TIMMODE_SHIFT 2
#define TGCR_TIMMODE_64BIT_GP 0x0
#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
#define TGCR_TIMMODE_64BIT_WDOG 0x2
#define TGCR_TIMMODE_32BIT_CHAINED 0x3
#define TGCR_TIM12RS_SHIFT 0
#define TGCR_TIM34RS_SHIFT 1
#define TGCR_RESET 0x0
#define TGCR_UNRESET 0x1
#define TGCR_RESET_MASK 0x3
#define WDTCR_WDEN_SHIFT 14
#define WDTCR_WDEN_DISABLE 0x0
#define WDTCR_WDEN_ENABLE 0x1
#define WDTCR_WDKEY_SHIFT 16
#define WDTCR_WDKEY_SEQ0 0xa5c6
#define WDTCR_WDKEY_SEQ1 0xda7e
struct timer_s {
char *name;
unsigned int id;
unsigned long period;
unsigned long opts;
void __iomem *base;
unsigned long tim_off;
unsigned long prd_off;
unsigned long cmp_off;
unsigned long enamode_shift;
struct irqaction irqaction;
struct irqaction cmpaction;
};
/* values for 'opts' field of struct timer_s */
#define TIMER_OPTS_DISABLED 0x00
#define TIMER_OPTS_ONESHOT 0x01
#define TIMER_OPTS_PERIODIC 0x02
/* Flags to be set when it is necessary to clear the */
/* status register for timer interrupts */
#define TIMER12_CLEAR_PRDINT 0x02
#define TIMER12_CLEAR_EVTINT 0x04
#ifdef CONFIG_IPIPE
#ifdef CONFIG_SMP
static union tsc_reg tsc[NR_CPUS];
void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
{
info->type = IPIPE_TSC_TYPE_NONE;
}
#else /* !CONFIG_SMP */
static union tsc_reg *tsc;
void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
{
info->type = IPIPE_TSC_TYPE_FREERUNNING;
info->u.fr.counter = (unsigned *)(DAVINCI_TIMER0_BASE + TIM12);
info->u.fr.mask = 0xffffffff;
info->u.fr.tsc = &tsc->full;
}
#endif /* !CONFIG_SMP */
void __ipipe_mach_acktimer(void)
{
void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
unsigned long status;
status = __raw_readl(base + INTCTLSTAT);
status |= (TIMER12_CLEAR_PRDINT | TIMER12_CLEAR_EVTINT);
__raw_writel(status,base+INTCTLSTAT);
}
static void ipipe_mach_update_tsc(void)
{
union tsc_reg *local_tsc;
unsigned long stamp, flags;
void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
local_irq_save_hw(flags);
local_tsc = &tsc[ipipe_processor_id()];
stamp = __raw_readl(base + TIM12);
if (unlikely(stamp < local_tsc->low))
/* 32 bit counter wrapped, increment high word. */
local_tsc->high++;
local_tsc->low = stamp;
local_irq_restore_hw(flags);
}
notrace unsigned long long __ipipe_mach_get_tsc(void)
{
if (likely(davinci_timer_initialized)) {
union tsc_reg *local_tsc, result;
unsigned long stamp;
void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
local_tsc = &tsc[ipipe_processor_id()];
__asm__("ldmia %1, %M0\n":
"=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
barrier();
stamp = __raw_readl(base + TIM12);
if (unlikely(stamp < result.low))
result.high++;
result.low = stamp;
return result.full;
}
return 0;
}
EXPORT_SYMBOL(__ipipe_mach_get_tsc);
/*
* Reprogram the timer
*/
void __ipipe_mach_set_dec(unsigned long delay)
{
unsigned long flags;
unsigned int value;
void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
if (delay > 20) {
local_irq_save_hw(flags);
value = __raw_readl(base + TIM12) + delay;
__raw_writel(value,base + CMP12(0));
local_irq_restore_hw(flags);
} else {
ipipe_trigger_irq(IRQ_DA8XX_TINT12_0);
}
}
EXPORT_SYMBOL(__ipipe_mach_set_dec);
unsigned long __ipipe_mach_get_dec(void)
{
unsigned long value;
void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
value = __raw_readl(base + CMP12(0));
value -= __raw_readl(base + TIM12);
return value;
}
int __ipipe_check_tickdev(const char *devname)
{
return !strcmp(devname, clockevent_davinci.name);
}
#endif /* CONFIG_IPIPE */
static int timer32_config(struct timer_s *t)
{
u32 tcr = __raw_readl(t->base + TCR);
/* disable timer */
tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
__raw_writel(tcr, t->base + TCR);
/* reset counter to zero, set new period */
__raw_writel(0, t->base + t->tim_off);
__raw_writel(t->period, t->base + t->prd_off);
if (t->cmp_off)
__raw_writel(t->period, t->base + t->cmp_off);
/* Set enable mode */
if (t->opts & TIMER_OPTS_ONESHOT) {
tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
} else if (t->opts & TIMER_OPTS_PERIODIC) {
tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
}
__raw_writel(tcr, t->base + TCR);
return 0;
}
static inline u32 timer32_read(struct timer_s *t)
{
return __raw_readl(t->base + t->tim_off);
}
/* Flavio Alves: for debugging */
extern void printascii(const char *);
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_davinci;
// printascii("entrei\n");
#ifdef CONFIG_IPIPE
ipipe_mach_update_tsc();
#endif /* CONFIG_IPIPE */
evt->event_handler(evt);
return IRQ_HANDLED;
}
/* called when 32-bit counter wraps */
static irqreturn_t freerun_interrupt(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
static irqreturn_t cmp_interrupt(int irq, void *dev_id)
{
struct timer_s *t = dev_id;
struct clock_event_device *evt = &clockevent_davinci;
/* We have to emulate the periodic mode for the clockevents layer */
if (t->opts & TIMER_OPTS_PERIODIC) {
unsigned long tim, cmp = __raw_readl(t->base + t->cmp_off);
cmp += t->period;
__raw_writel(cmp, t->base + t->cmp_off);
/*
* The interrupts do happen to be disabled by the kernel for
* a long periods of time, thus the timer can go far ahead of
* the last set compare value...
*/
tim = __raw_readl(t->base + t->tim_off);
if (time_after(tim, cmp))
__raw_writel(tim + t->period, t->base + t->cmp_off);
}
clockevent_davinci.event_handler(evt);
return IRQ_HANDLED;
}
static struct timer_s davinci_system_timer = {
.name = "clockevent",
.opts = TIMER_OPTS_DISABLED,
.irqaction = {
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = timer_interrupt,
}
};
static struct timer_s davinci_freerun_timer = {
.name = "free-run counter",
.period = ~0,
.opts = TIMER_OPTS_PERIODIC,
.irqaction = {
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = freerun_interrupt,
},
.cmpaction = {
.name = "timer compare reg 0",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = cmp_interrupt,
}
};
static struct timer_s *timers[NUM_TIMERS];
static void __init timer_init(int num_timers, u32 *phys_bases,
int *timer_irqs, int *cmp_irqs)
{
int i;
/* Global init of each 64-bit timer as a whole */
for(i=0; i<num_timers; i++) {
u32 tgcr;
void __iomem *base = IO_ADDRESS(phys_bases[i]);
/* Disabled, Internal clock source */
__raw_writel(0, base + TCR);
/* reset both timers, no pre-scaler for timer34 */
tgcr = 0;
__raw_writel(tgcr, base + TGCR);
/* Set both timers to unchained 32-bit */
tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
__raw_writel(tgcr, base + TGCR);
/* Unreset timers */
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
__raw_writel(tgcr, base + TGCR);
/* Init both counters to zero */
__raw_writel(0, base + TIM12);
__raw_writel(0, base + TIM34);
}
/* Init of each timer as a 32-bit timer */
for (i=0; i< NUM_TIMERS; i++) {
struct timer_s *t = timers[i];
u32 phys_base;
if (t && t->name) {
t->id = i;
phys_base = phys_bases[i >> 1];
t->base = IO_ADDRESS(phys_base);
if (IS_TIMER_BOT(t->id)) {
t->enamode_shift = 6;
t->tim_off = TIM12;
t->prd_off = PRD12;
/* Check the compare register IRQ */
if (t->cmpaction.handler != NULL &&
cmp_irqs != NULL && cmp_irqs[t->id]) {
t->cmp_off = CMP12(0);
t->cmpaction.dev_id = (void *)t;
setup_irq(cmp_irqs[t->id],
&t->cmpaction);
}
} else {
t->enamode_shift = 22;
t->tim_off = TIM34;
t->prd_off = PRD34;
}
/* Register interrupt */
t->irqaction.name = t->name;
t->irqaction.dev_id = (void *)t;
if (t->irqaction.handler != NULL) {
setup_irq(timer_irqs[t->id], &t->irqaction);
}
timer32_config(timers[i]);
}
}
#ifdef CONFIG_IPIPE
#ifndef CONFIG_SMP
tsc = (union tsc_reg *)__ipipe_tsc_area;
barrier();
#endif /* CONFIG_SMP */
davinci_timer_initialized = 1;
#endif /* CONFIG_IPIPE */
}
/*
* clocksource
*/
static cycle_t read_cycles(void)
{
struct timer_s *t;
if (tid_freerun == -1) {
t = timers[tid_system];
}
else {
t = timers[tid_freerun];
}
return (cycles_t)timer32_read(t);
}
static struct clocksource clocksource_davinci = {
.name = "timer0_1",
.rating = 300,
.read = read_cycles,
.mask = CLOCKSOURCE_MASK(32),
.shift = 24,
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
/*
* clockevent
*/
static int davinci_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
struct timer_s *t = timers[tid_system];
t->period = cycles;
/*
* We need not (and must not) disable the timer and reprogram
* its mode/period when using the compare register...
*/
if (t->cmp_off)
__raw_writel(__raw_readl(t->base + t->tim_off) + cycles,
t->base + t->cmp_off);
else
timer32_config(t);
return 0;
}
static void davinci_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
struct timer_s *t = timers[tid_system];
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
t->period = davinci_clock_tick_rate / (HZ);
t->opts = TIMER_OPTS_PERIODIC;
if (t->cmp_off)
davinci_set_next_event(davinci_clock_tick_rate / HZ,
evt);
else
timer32_config(t);
break;
case CLOCK_EVT_MODE_ONESHOT:
t->opts = TIMER_OPTS_ONESHOT;
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
t->opts = TIMER_OPTS_DISABLED;
break;
case CLOCK_EVT_MODE_RESUME:
break;
}
}
static struct clock_event_device clockevent_davinci = {
.name = "timer0_0",
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.shift = 32,
.set_next_event = davinci_set_next_event,
.set_mode = davinci_set_mode,
};
static u32 davinci_bases[] = { DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE };
static u32 da8xx_bases[] = { DA8XX_TIMER64P0_BASE, DA8XX_TIMER64P1_BASE };
static void __init davinci_timer_init(void)
{
int num_timers;
int *timer_irqs = NULL, *cmp_irqs = NULL;
u32 *bases;
struct clk *timer_clk;
static char err[] __initdata = KERN_ERR
"%s: can't register clocksource!\n";
timer_clk = clk_get(NULL, "timer0");
BUG_ON(IS_ERR(timer_clk));
clk_enable(timer_clk);
num_timers = 2;
bases = davinci_bases;
timer_irqs = default_timer_irqs;
/*
* DA850 does not support compare IRQs for bottom two timers.
* It has 4 timers, so assume using compare registers is not
* really a necessity.
*/
if (cpu_is_da830())
cmp_irqs = da830_cmp_irqs;
if (cpu_is_da8xx()) {
/*
* Configure the 2 64-bit timer as 4 32-bit timers with
* following assignments.
*
* T0_BOT: Timer 0, bottom: free run counter and system clock.
* T0_TOP: Timer 0, top: Reserve for DSP
* T1_BOT: Timer 1, watch dog timer.
*/
tid_system = T0_BOT;
bases = da8xx_bases;
timer_irqs = da8xx_timer_irqs;
/* timer interrupt using compare reg so free-run not needed */
if (cmp_irqs != NULL)
tid_freerun = T0_BOT;
else
tid_freerun = T0_TOP;
} else if (cpu_is_davinci_dm646x()) {
/*
* Configure the 2 64-bit timer as 4 32-bit timers with
* following assignments.
*
* T0_BOT: Timer 0, bottom: AV Sync
* T0_TOP: Timer 0, top: free-running counter,
* used for cycle counter
* T1_BOT: Timer 1, bottom: reserved for DSP
* T1_TOP: Timer 1, top : Linux system tick
*/
tid_system = T1_TOP;
tid_freerun = T0_TOP;
} else if (cpu_is_davinci_dm644x()) {
/*
* Configure the 2 64-bit timer as 4 32-bit timers with
* following assignments.
*
* T0_BOT: Timer 0, bottom: clockevent source for hrtimers
* T0_TOP: Timer 0, top : clocksource for generic timekeeping
* T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code)
* T1_TOP: Timer 1, top : <unused>
*/
tid_system = T0_BOT;
tid_freerun = T0_TOP;
}
if (tid_system != -1)
timers[tid_system] = &davinci_system_timer;
if (tid_freerun != -1)
timers[tid_freerun] = &davinci_freerun_timer;
/* init timer hw */
timer_init(num_timers, bases, timer_irqs, cmp_irqs);
davinci_clock_tick_rate = clk_get_rate(timer_clk);
clk_put(timer_clk);
/* setup clocksource */
clocksource_davinci.mult =
clocksource_khz2mult(davinci_clock_tick_rate/1000,
clocksource_davinci.shift);
if (clocksource_register(&clocksource_davinci))
printk(err, clocksource_davinci.name);
/* setup clockevent */
clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
clockevent_davinci.shift);
clockevent_davinci.max_delta_ns =
clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
clockevent_davinci.min_delta_ns =
clockevent_delta2ns(1, &clockevent_davinci);
clockevent_davinci.cpumask = cpumask_of(0);
clockevents_register_device(&clockevent_davinci);
}
struct sys_timer davinci_timer = {
.init = davinci_timer_init,
};
/* reset board using watchdog timer */
void davinci_watchdog_reset(void) {
u32 tgcr, wdtcr;
void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE);
struct device dev;
struct clk *wd_clk;
dev_set_name(&dev, "watchdog");
wd_clk = clk_get(&dev, NULL);
if (WARN_ON(IS_ERR(wd_clk)))
return;
clk_enable(wd_clk);
if (cpu_is_da8xx())
base = IO_ADDRESS(DA8XX_TIMER64P1_BASE);
/* disable, internal clock source */
__raw_writel(0, base + TCR);
/* reset timer, set mode to 64-bit watchdog, and unreset */
tgcr = 0;
__raw_writel(tgcr, base + TGCR);
tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
__raw_writel(tgcr, base + TGCR);
/* clear counter and period regs */
__raw_writel(0, base + TIM12);
__raw_writel(0, base + TIM34);
__raw_writel(0, base + PRD12);
__raw_writel(0, base + PRD34);
/* enable */
wdtcr = __raw_readl(base + WDTCR);
wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT;
__raw_writel(wdtcr, base + WDTCR);
/* put watchdog in pre-active state */
wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
__raw_writel(wdtcr, base + WDTCR);
/* put watchdog in active state */
wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
__raw_writel(wdtcr, base + WDTCR);
/* write an invalid value to the WDKEY field to trigger
* a watchdog reset */
wdtcr = 0x00004000;
__raw_writel(wdtcr, base + WDTCR);
}
#ifdef CONFIG_IPIPE
void __ipipe_mach_release_timer(void)
{
davinci_set_mode(clockevent_davinci.mode, &clockevent_davinci);
if (clockevent_davinci.mode == CLOCK_EVT_MODE_ONESHOT)
davinci_set_next_event(LATCH, &clockevent_davinci);
}
EXPORT_SYMBOL(__ipipe_mach_release_timer);
#endif /* CONFIG_IPIPE */
[-- Attachment #5: irqs.h --]
[-- Type: text/x-chdr, Size: 13101 bytes --]
/*
* DaVinci interrupt controller definitions
*
* Copyright (C) 2006 Texas Instruments.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H
/* Base address */
#define DAVINCI_ARM_INTC_BASE 0x01C48000
/* Interrupt lines */
#define IRQ_VDINT0 0
#define IRQ_VDINT1 1
#define IRQ_VDINT2 2
#define IRQ_HISTINT 3
#define IRQ_H3AINT 4
#define IRQ_PRVUINT 5
#define IRQ_RSZINT 6
#define IRQ_VFOCINT 7
#define IRQ_VENCINT 8
#define IRQ_ASQINT 9
#define IRQ_IMXINT 10
#define IRQ_VLCDINT 11
#define IRQ_USBINT 12
#define IRQ_EMACINT 13
#define IRQ_CCINT0 16
#define IRQ_CCERRINT 17
#define IRQ_TCERRINT0 18
#define IRQ_TCERRINT 19
#define IRQ_PSCIN 20
#define IRQ_IDE 22
#define IRQ_HPIINT 23
#define IRQ_MBXINT 24
#define IRQ_MBRINT 25
#define IRQ_MMCINT 26
#define IRQ_SDIOINT 27
#define IRQ_MSINT 28
#define IRQ_DDRINT 29
#define IRQ_AEMIFINT 30
#define IRQ_VLQINT 31
#define IRQ_TINT0_TINT12 32
#define IRQ_TINT0_TINT34 33
#define IRQ_TINT1_TINT12 34
#define IRQ_TINT1_TINT34 35
#define IRQ_PWMINT0 36
#define IRQ_PWMINT1 37
#define IRQ_PWMINT2 38
#define IRQ_I2C 39
#define IRQ_UARTINT0 40
#define IRQ_UARTINT1 41
#define IRQ_UARTINT2 42
#define IRQ_SPINT0 43
#define IRQ_SPINT1 44
#define IRQ_DSP2ARM0 46
#define IRQ_DSP2ARM1 47
#define IRQ_GPIO0 48
#define IRQ_GPIO1 49
#define IRQ_GPIO2 50
#define IRQ_GPIO3 51
#define IRQ_GPIO4 52
#define IRQ_GPIO5 53
#define IRQ_GPIO6 54
#define IRQ_GPIO7 55
#define IRQ_GPIOBNK0 56
#define IRQ_GPIOBNK1 57
#define IRQ_GPIOBNK2 58
#define IRQ_GPIOBNK3 59
#define IRQ_GPIOBNK4 60
#define IRQ_COMMTX 61
#define IRQ_COMMRX 62
#define IRQ_EMUINT 63
/* da850 currently has the most irqs (101) */
#define DAVINCI_N_AINTC_IRQ 101
/* da850 currently has the most gpio pins (144) */
#define DAVINCI_N_GPIO 144
#define NR_IRQS (DAVINCI_N_AINTC_IRQ + DAVINCI_N_GPIO)
#define ARCH_TIMER_IRQ IRQ_TINT1_TINT34
/* DaVinci DM6467-specific Interrupts */
#define IRQ_DM646X_VP_VERTINT0 0
#define IRQ_DM646X_VP_VERTINT1 1
#define IRQ_DM646X_VP_VERTINT2 2
#define IRQ_DM646X_VP_VERTINT3 3
#define IRQ_DM646X_VP_ERRINT 4
#define IRQ_DM646X_RESERVED_1 5
#define IRQ_DM646X_RESERVED_2 6
#define IRQ_DM646X_WDINT 7
#define IRQ_DM646X_CRGENINT0 8
#define IRQ_DM646X_CRGENINT1 9
#define IRQ_DM646X_TSIFINT0 10
#define IRQ_DM646X_TSIFINT1 11
#define IRQ_DM646X_VDCEINT 12
#define IRQ_DM646X_USBINT 13
#define IRQ_DM646X_USBDMAINT 14
#define IRQ_DM646X_PCIINT 15
#define IRQ_DM646X_TCERRINT2 20
#define IRQ_DM646X_TCERRINT3 21
#define IRQ_DM646X_IDE 22
#define IRQ_DM646X_HPIINT 23
#define IRQ_DM646X_EMACRXTHINT 24
#define IRQ_DM646X_EMACRXINT 25
#define IRQ_DM646X_EMACTXINT 26
#define IRQ_DM646X_EMACMISCINT 27
#define IRQ_DM646X_MCASP0TXINT 28
#define IRQ_DM646X_MCASP0RXINT 29
#define IRQ_DM646X_RESERVED_3 31
#define IRQ_DM646X_MCASP1TXINT 32
#define IRQ_DM646X_VLQINT 38
#define IRQ_DM646X_UARTINT2 42
#define IRQ_DM646X_SPINT0 43
#define IRQ_DM646X_SPINT1 44
#define IRQ_DM646X_DSP2ARMINT 45
#define IRQ_DM646X_RESERVED_4 46
#define IRQ_DM646X_PSCINT 47
#define IRQ_DM646X_GPIO0 48
#define IRQ_DM646X_GPIO1 49
#define IRQ_DM646X_GPIO2 50
#define IRQ_DM646X_GPIO3 51
#define IRQ_DM646X_GPIO4 52
#define IRQ_DM646X_GPIO5 53
#define IRQ_DM646X_GPIO6 54
#define IRQ_DM646X_GPIO7 55
#define IRQ_DM646X_GPIOBNK0 56
#define IRQ_DM646X_GPIOBNK1 57
#define IRQ_DM646X_GPIOBNK2 58
#define IRQ_DM646X_DDRINT 59
#define IRQ_DM646X_AEMIFINT 60
/* DaVinci DM355-specific Interrupts */
#define IRQ_DM355_CCDC_VDINT0 0
#define IRQ_DM355_CCDC_VDINT1 1
#define IRQ_DM355_CCDC_VDINT2 2
#define IRQ_DM355_IPIPE_HST 3
#define IRQ_DM355_H3AINT 4
#define IRQ_DM355_IPIPE_SDR 5
#define IRQ_DM355_IPIPEIFINT 6
#define IRQ_DM355_OSDINT 7
#define IRQ_DM355_VENCINT 8
#define IRQ_DM355_IMCOPINT 11
#define IRQ_DM355_RTOINT 13
#define IRQ_DM355_TINT4 13
#define IRQ_DM355_TINT2_TINT12 13
#define IRQ_DM355_UARTINT2 14
#define IRQ_DM355_TINT5 14
#define IRQ_DM355_TINT2_TINT34 14
#define IRQ_DM355_TINT6 15
#define IRQ_DM355_TINT3_TINT12 15
#define IRQ_DM355_SPINT1_0 17
#define IRQ_DM355_SPINT1_1 18
#define IRQ_DM355_SPINT2_0 19
#define IRQ_DM355_SPINT2_1 21
#define IRQ_DM355_TINT7 22
#define IRQ_DM355_TINT3_TINT34 22
#define IRQ_DM355_SDIOINT0 23
#define IRQ_DM355_MMCINT0 26
#define IRQ_DM355_MSINT 26
#define IRQ_DM355_MMCINT1 27
#define IRQ_DM355_PWMINT3 28
#define IRQ_DM355_SDIOINT1 31
#define IRQ_DM355_SPINT0_0 42
#define IRQ_DM355_SPINT0_1 43
#define IRQ_DM355_GPIO0 44
#define IRQ_DM355_GPIO1 45
#define IRQ_DM355_GPIO2 46
#define IRQ_DM355_GPIO3 47
#define IRQ_DM355_GPIO4 48
#define IRQ_DM355_GPIO5 49
#define IRQ_DM355_GPIO6 50
#define IRQ_DM355_GPIO7 51
#define IRQ_DM355_GPIO8 52
#define IRQ_DM355_GPIO9 53
#define IRQ_DM355_GPIOBNK0 54
#define IRQ_DM355_GPIOBNK1 55
#define IRQ_DM355_GPIOBNK2 56
#define IRQ_DM355_GPIOBNK3 57
#define IRQ_DM355_GPIOBNK4 58
#define IRQ_DM355_GPIOBNK5 59
#define IRQ_DM355_GPIOBNK6 60
/* Interrupts common to DA830 and DA850*/
#define IRQ_DA8XX_COMMTX 0
#define IRQ_DA8XX_COMMRX 1
#define IRQ_DA8XX_NINT 2
#define IRQ_DA8XX_EVTOUT0 3
#define IRQ_DA8XX_EVTOUT1 4
#define IRQ_DA8XX_EVTOUT2 5
#define IRQ_DA8XX_EVTOUT3 6
#define IRQ_DA8XX_EVTOUT4 7
#define IRQ_DA8XX_EVTOUT5 8
#define IRQ_DA8XX_EVTOUT6 9
#define IRQ_DA8XX_EVTOUT7 10
#define IRQ_DA8XX_CCINT0 11
#define IRQ_DA8XX_CCERRINT 12
#define IRQ_DA8XX_TCERRINT0 13
#define IRQ_DA8XX_AEMIFINT 14
#define IRQ_DA8XX_I2CINT0 15
#define IRQ_DA8XX_MMCSDINT0 16
#define IRQ_DA8XX_MMCSDINT1 17
#define IRQ_DA8XX_ALLINT0 18
#define IRQ_DA8XX_RTC 19
#define IRQ_DA8XX_SPINT0 20
#define IRQ_DA8XX_TINT12_0 21
#define IRQ_DA8XX_TINT34_0 22
#define IRQ_DA8XX_TINT12_1 23
#define IRQ_DA8XX_TINT34_1 24
#define IRQ_DA8XX_UARTINT0 25
#define IRQ_DA8XX_KEYMGRINT 26
#define IRQ_DA8XX_SECINT 26
#define IRQ_DA8XX_SECKEYERR 26
#define IRQ_DA8XX_CHIPINT0 28
#define IRQ_DA8XX_CHIPINT1 29
#define IRQ_DA8XX_CHIPINT2 30
#define IRQ_DA8XX_CHIPINT3 31
#define IRQ_DA8XX_TCERRINT1 32
#define IRQ_DA8XX_C0_RX_THRESH_PULSE 33
#define IRQ_DA8XX_C0_RX_PULSE 34
#define IRQ_DA8XX_C0_TX_PULSE 35
#define IRQ_DA8XX_C0_MISC_PULSE 36
#define IRQ_DA8XX_C1_RX_THRESH_PULSE 37
#define IRQ_DA8XX_C1_RX_PULSE 38
#define IRQ_DA8XX_C1_TX_PULSE 39
#define IRQ_DA8XX_C1_MISC_PULSE 40
#define IRQ_DA8XX_MEMERR 41
#define IRQ_DA8XX_GPIO0 42
#define IRQ_DA8XX_GPIO1 43
#define IRQ_DA8XX_GPIO2 44
#define IRQ_DA8XX_GPIO3 45
#define IRQ_DA8XX_GPIO4 46
#define IRQ_DA8XX_GPIO5 47
#define IRQ_DA8XX_GPIO6 48
#define IRQ_DA8XX_GPIO7 49
#define IRQ_DA8XX_GPIO8 50
#define IRQ_DA8XX_I2CINT1 51
#define IRQ_DA8XX_LCDINT 52
#define IRQ_DA8XX_UARTINT1 53
#define IRQ_DA8XX_MCASPINT 54
#define IRQ_DA8XX_ALLINT1 55
#define IRQ_DA8XX_SPINT1 56
#define IRQ_DA8XX_UHPI_INT1 57
#define IRQ_DA8XX_USB_INT 58
#define IRQ_DA8XX_IRQN 59
#define IRQ_DA8XX_RWAKEUP 60
#define IRQ_DA8XX_UARTINT2 61
#define IRQ_DA8XX_DFTSSINT 62
#define IRQ_DA8XX_EHRPWM0 63
#define IRQ_DA8XX_EHRPWM0TZ 64
#define IRQ_DA8XX_EHRPWM1 65
#define IRQ_DA8XX_EHRPWM1TZ 66
#define IRQ_DA8XX_ECAP0 69
#define IRQ_DA8XX_ECAP1 70
#define IRQ_DA8XX_ECAP2 71
#define IRQ_DA8XX_ARMCLKSTOPREQ 90
/* DA830 specific interrupts */
#define IRQ_DA830_MPUERR 27
#define IRQ_DA830_IOPUERR 27
#define IRQ_DA830_BOOTCFGERR 27
#define IRQ_DA830_EHRPWM2 67
#define IRQ_DA830_EHRPWM2TZ 68
#define IRQ_DA830_EQEP0 72
#define IRQ_DA830_EQEP1 73
#define IRQ_DA830_T12CMPINT0_0 74
#define IRQ_DA830_T12CMPINT1_0 75
#define IRQ_DA830_T12CMPINT2_0 76
#define IRQ_DA830_T12CMPINT3_0 77
#define IRQ_DA830_T12CMPINT4_0 78
#define IRQ_DA830_T12CMPINT5_0 79
#define IRQ_DA830_T12CMPINT6_0 80
#define IRQ_DA830_T12CMPINT7_0 81
#define IRQ_DA830_T12CMPINT0_1 82
#define IRQ_DA830_T12CMPINT1_1 83
#define IRQ_DA830_T12CMPINT2_1 84
#define IRQ_DA830_T12CMPINT3_1 85
#define IRQ_DA830_T12CMPINT4_1 86
#define IRQ_DA830_T12CMPINT5_1 87
#define IRQ_DA830_T12CMPINT6_1 88
#define IRQ_DA830_T12CMPINT7_1 89
/* DA850 speicific interrupts */
#define IRQ_DA850_MPUADDRERR0 27
#define IRQ_DA850_MPUPROTERR0 27
#define IRQ_DA850_IOPUADDRERR0 27
#define IRQ_DA850_IOPUPROTERR0 27
#define IRQ_DA850_IOPUADDRERR1 27
#define IRQ_DA850_IOPUPROTERR1 27
#define IRQ_DA850_IOPUADDRERR2 27
#define IRQ_DA850_IOPUPROTERR2 27
#define IRQ_DA850_BOOTCFG_ADDR_ERR 27
#define IRQ_DA850_BOOTCFG_PROT_ERR 27
#define IRQ_DA850_MPUADDRERR1 27
#define IRQ_DA850_MPUPROTERR1 27
#define IRQ_DA850_IOPUADDRERR3 27
#define IRQ_DA850_IOPUPROTERR3 27
#define IRQ_DA850_IOPUADDRERR4 27
#define IRQ_DA850_IOPUPROTERR4 27
#define IRQ_DA850_IOPUADDRERR5 27
#define IRQ_DA850_IOPUPROTERR5 27
#define IRQ_DA850_MIOPU_BOOTCFG_ERR 27
#define IRQ_DA850_SATAINT 67
#define IRQ_DA850_TINT12_2 68
#define IRQ_DA850_TINT34_2 68
#define IRQ_DA850_TINTALL_2 68
#define IRQ_DA850_MMCSDINT0_1 72
#define IRQ_DA850_MMCSDINT1_1 73
#define IRQ_DA850_T12CMPINT0_2 74
#define IRQ_DA850_T12CMPINT1_2 75
#define IRQ_DA850_T12CMPINT2_2 76
#define IRQ_DA850_T12CMPINT3_2 77
#define IRQ_DA850_T12CMPINT4_2 78
#define IRQ_DA850_T12CMPINT5_2 79
#define IRQ_DA850_T12CMPINT6_2 80
#define IRQ_DA850_T12CMPINT7_2 81
#define IRQ_DA850_T12CMPINT0_3 82
#define IRQ_DA850_T12CMPINT1_3 83
#define IRQ_DA850_T12CMPINT2_3 84
#define IRQ_DA850_T12CMPINT3_3 85
#define IRQ_DA850_T12CMPINT4_3 86
#define IRQ_DA850_T12CMPINT5_3 87
#define IRQ_DA850_T12CMPINT6_3 88
#define IRQ_DA850_T12CMPINT7_3 89
#define IRQ_DA850_RPIINT 91
#define IRQ_DA850_VPIFINT 92
#define IRQ_DA850_CCINT1 93
#define IRQ_DA850_CCERRINT1 94
#define IRQ_DA850_TCERRINT2 95
#define IRQ_DA850_TINT12_3 96
#define IRQ_DA850_TINT34_3 96
#define IRQ_DA850_TINTALL_3 96
#define IRQ_DA850_MCBSP0RINT 97
#define IRQ_DA850_MCBSP0XINT 98
#define IRQ_DA850_MCBSP1RINT 99
#define IRQ_DA850_MCBSP1XINT 100
#ifdef CONFIG_IPIPE
#if 0
#define __ipipe_mach_irq_mux_p(irq) \
((unsigned) (irq - IRQ_DA8XX_GPIO0) \
<= (IRQ_DA8XX_GPIO7 - IRQ_DA8XX_GPIO0))
#endif
#define __ipipe_mach_irq_mux_p(irq) \
((irq) == IRQ_DA8XX_GPIO0 \
|| (irq) == IRQ_DA8XX_GPIO1 \
|| (irq) == IRQ_DA8XX_GPIO2 \
|| (irq) == IRQ_DA8XX_GPIO3 \
|| (irq) == IRQ_DA8XX_GPIO4 \
|| (irq) == IRQ_DA8XX_GPIO5 \
|| (irq) == IRQ_DA8XX_GPIO6 \
|| (irq) == IRQ_DA8XX_GPIO7)
#endif /* CONFIG_IPIPE */
#endif /* __ASM_ARCH_IRQS_H */
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 19:42 ` Flavio de Castro Alves Filho
@ 2010-01-08 19:45 ` Gilles Chanteperdrix
2010-01-08 21:54 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 19:45 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Of course :-)
>
> As I don't know the best way to send it, I attached the files.
>
> I hope everything is in there. I'm sorry if you find some ugly commented
> debug code.
Please send a diff.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 19:45 ` Gilles Chanteperdrix
@ 2010-01-08 21:54 ` Flavio de Castro Alves Filho
2010-01-08 22:26 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-08 21:54 UTC (permalink / raw)
To: xenomai
[-- Attachment #1: Type: text/plain, Size: 16053 bytes --]
In fact,
Much easier.
*** linux-03.20.00.05/arch/arm/mach-davinci/gpio.c 2009-07-29
02:53:15.000000000 -0300
--- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/gpio.c 2010-01-08
16:08:35.000000000 -0200
***************
*** 27,32 ****
--- 27,33 ----
#include <asm/mach/irq.h>
+ #include <asm/ipipe.h>
static DEFINE_SPINLOCK(gpio_lock);
***************
*** 261,266 ****
--- 262,315 ----
/* now it may re-trigger */
}
+ #ifdef CONFIG_IPIPE
+
+ /* Flavio Alves: for debugging */
+ extern void printascii(const char *);
+
+ void __ipipe_mach_demux_irq(unsigned irq, struct pt_regs *regs)
+ {
+ struct gpio_controller *__iomem g = get_irq_chip_data(irq);
+ struct irq_desc *desc;
+ u32 mask = 0xffff;
+
+ //printascii("1__ipipe_mach_demux_irq\n");
+
+ /* we only care about one bank */
+ if (irq & 1)
+ mask <<= 16;
+
+ desc = &irq_desc[irq];
+
+ /* temporarily mask (level sensitive) parent IRQ */
+ desc->chip->ack(irq);
+ while (1) {
+ u32 status;
+ int n;
+ int res;
+
+ /* ack any irqs */
+ status = __raw_readl(&g->intstat) & mask;
+ if (!status)
+ break;
+ __raw_writel(status, &g->intstat);
+ if (irq & 1)
+ status >>= 16;
+
+ /* now demux them to the right lowlevel handler */
+ n = (int)get_irq_data(irq);
+ while (status) {
+ res = ffs(status);
+ n += res;
+ __ipipe_handle_irq((n-1),regs);
+ status >>= res;
+ }
+ }
+ desc->chip->unmask(irq);
+ /* now it may re-trigger */
+ }
+ #endif /* CONFIG_IPIPE */
+
/*
* NOTE: for suspend/resume, probably best to make a platform_device with
* suspend_late/resume_resume calls hooking into results of the set_wake()
diff -crB linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
*** linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
2009-07-29 02:53:15.000000000 -0300
--- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
2010-01-06 16:45:56.000000000 -0200
***************
*** 359,362 ****
--- 359,381 ----
#define IRQ_DA850_MCBSP1RINT 99
#define IRQ_DA850_MCBSP1XINT 100
+ #ifdef CONFIG_IPIPE
+ #if 0
+ #define __ipipe_mach_irq_mux_p(irq) \
+ ((unsigned) (irq - IRQ_DA8XX_GPIO0) \
+ <= (IRQ_DA8XX_GPIO7 - IRQ_DA8XX_GPIO0))
+ #endif
+ #define __ipipe_mach_irq_mux_p(irq) \
+ ((irq) == IRQ_DA8XX_GPIO0 \
+ || (irq) == IRQ_DA8XX_GPIO1 \
+ || (irq) == IRQ_DA8XX_GPIO2 \
+ || (irq) == IRQ_DA8XX_GPIO3 \
+ || (irq) == IRQ_DA8XX_GPIO4 \
+ || (irq) == IRQ_DA8XX_GPIO5 \
+ || (irq) == IRQ_DA8XX_GPIO6 \
+ || (irq) == IRQ_DA8XX_GPIO7)
+
+
+ #endif /* CONFIG_IPIPE */
+
#endif /* __ASM_ARCH_IRQS_H */
diff -crB linux-03.20.00.05/arch/arm/mach-davinci/irq.c
linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c
*** linux-03.20.00.05/arch/arm/mach-davinci/irq.c 2009-07-29
02:53:15.000000000 -0300
--- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c 2010-01-08
15:22:13.000000000 -0200
***************
*** 111,119 ****
--- 111,228 ----
.name = "AINTC",
.ack = davinci_ack_irq,
.mask = davinci_mask_irq,
+ #ifdef CONFIG_IPIPE
+ .mask_ack = davinci_mask_irq,
+ #endif /* CONFIG_IPIPE */
.unmask = davinci_unmask_irq,
};
+ #ifdef CONFIG_IPIPE
+ static const u8 da850_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata =
{
+ [IRQ_DA8XX_COMMTX] = 7,
+ [IRQ_DA8XX_COMMRX] = 7,
+ [IRQ_DA8XX_NINT] = 7,
+ [IRQ_DA8XX_EVTOUT0] = 7,
+ [IRQ_DA8XX_EVTOUT1] = 7,
+ [IRQ_DA8XX_EVTOUT2] = 7,
+ [IRQ_DA8XX_EVTOUT3] = 7,
+ [IRQ_DA8XX_EVTOUT4] = 7,
+ [IRQ_DA8XX_EVTOUT5] = 7,
+ [IRQ_DA8XX_EVTOUT6] = 7,
+ [IRQ_DA8XX_EVTOUT7] = 7,
+ [IRQ_DA8XX_CCINT0] = 7,
+ [IRQ_DA8XX_CCERRINT] = 7,
+ [IRQ_DA8XX_TCERRINT0] = 7,
+ [IRQ_DA8XX_AEMIFINT] = 7,
+ [IRQ_DA8XX_I2CINT0] = 5,
+ [IRQ_DA8XX_MMCSDINT0] = 5,
+ [IRQ_DA8XX_MMCSDINT1] = 5,
+ [IRQ_DA8XX_ALLINT0] = 5,
+ [IRQ_DA8XX_RTC] = 4,
+ [IRQ_DA8XX_SPINT0] = 5,
+ [IRQ_DA8XX_TINT12_0] = 2,
+ [IRQ_DA8XX_TINT34_0] = 5,
+ [IRQ_DA8XX_TINT12_1] = 5,
+ [IRQ_DA8XX_TINT34_1] = 5,
+ [IRQ_DA8XX_UARTINT0] = 5,
+ [IRQ_DA8XX_KEYMGRINT] = 7,
+ [IRQ_DA850_MIOPU_BOOTCFG_ERR] = 7,
+ [IRQ_DA8XX_CHIPINT0] = 7,
+ [IRQ_DA8XX_CHIPINT1] = 7,
+ [IRQ_DA8XX_CHIPINT2] = 7,
+ [IRQ_DA8XX_CHIPINT3] = 7,
+ [IRQ_DA8XX_TCERRINT1] = 7,
+ [IRQ_DA8XX_C0_RX_THRESH_PULSE] = 7,
+ [IRQ_DA8XX_C0_RX_PULSE] = 7,
+ [IRQ_DA8XX_C0_TX_PULSE] = 7,
+ [IRQ_DA8XX_C0_MISC_PULSE] = 7,
+ [IRQ_DA8XX_C1_RX_THRESH_PULSE] = 7,
+ [IRQ_DA8XX_C1_RX_PULSE] = 7,
+ [IRQ_DA8XX_C1_TX_PULSE] = 7,
+ [IRQ_DA8XX_C1_MISC_PULSE] = 7,
+ [IRQ_DA8XX_MEMERR] = 5,
+ [IRQ_DA8XX_GPIO0] = 6,
+ [IRQ_DA8XX_GPIO1] = 6,
+ [IRQ_DA8XX_GPIO2] = 6,
+ [IRQ_DA8XX_GPIO3] = 6,
+ [IRQ_DA8XX_GPIO4] = 6,
+ [IRQ_DA8XX_GPIO5] = 6,
+ [IRQ_DA8XX_GPIO6] = 6,
+ [IRQ_DA8XX_GPIO7] = 6,
+ [IRQ_DA8XX_GPIO8] = 6,
+ [IRQ_DA8XX_I2CINT1] = 5,
+ [IRQ_DA8XX_LCDINT] = 5,
+ [IRQ_DA8XX_UARTINT1] = 5,
+ [IRQ_DA8XX_MCASPINT] = 5,
+ [IRQ_DA8XX_ALLINT1] = 5,
+ [IRQ_DA8XX_SPINT1] = 5,
+ [IRQ_DA8XX_UHPI_INT1] = 5,
+ [IRQ_DA8XX_USB_INT] = 5,
+ [IRQ_DA8XX_IRQN] = 5,
+ [IRQ_DA8XX_RWAKEUP] = 5,
+ [IRQ_DA8XX_UARTINT2] = 5,
+ [IRQ_DA8XX_DFTSSINT] = 5,
+ [IRQ_DA8XX_EHRPWM0] = 7,
+ [IRQ_DA8XX_EHRPWM0TZ] = 7,
+ [IRQ_DA8XX_EHRPWM1] = 7,
+ [IRQ_DA8XX_EHRPWM1TZ] = 7,
+ [IRQ_DA850_SATAINT] = 5,
+ [IRQ_DA850_TINT12_2] = 5,
+ [IRQ_DA8XX_ECAP0] = 7,
+ [IRQ_DA8XX_ECAP1] = 7,
+ [IRQ_DA8XX_ECAP2] = 7,
+ [IRQ_DA850_MMCSDINT0_1] = 5,
+ [IRQ_DA850_MMCSDINT1_1] = 5,
+ [IRQ_DA850_T12CMPINT0_2] = 7,
+ [IRQ_DA850_T12CMPINT1_2] = 7,
+ [IRQ_DA850_T12CMPINT2_2] = 7,
+ [IRQ_DA850_T12CMPINT3_2] = 7,
+ [IRQ_DA850_T12CMPINT4_2] = 7,
+ [IRQ_DA850_T12CMPINT5_2] = 7,
+ [IRQ_DA850_T12CMPINT6_2] = 7,
+ [IRQ_DA850_T12CMPINT7_2] = 7,
+ [IRQ_DA850_T12CMPINT0_3] = 7,
+ [IRQ_DA850_T12CMPINT1_3] = 7,
+ [IRQ_DA850_T12CMPINT2_3] = 7,
+ [IRQ_DA850_T12CMPINT3_3] = 7,
+ [IRQ_DA850_T12CMPINT4_3] = 7,
+ [IRQ_DA850_T12CMPINT5_3] = 7,
+ [IRQ_DA850_T12CMPINT6_3] = 7,
+ [IRQ_DA850_T12CMPINT7_3] = 7,
+ [IRQ_DA8XX_ARMCLKSTOPREQ] = 7,
+ [IRQ_DA850_RPIINT] = 7,
+ [IRQ_DA850_VPIFINT] = 7,
+ [IRQ_DA850_CCINT1] = 7,
+ [IRQ_DA850_CCERRINT1] = 7,
+ [IRQ_DA850_TCERRINT2] = 7,
+ [IRQ_DA850_TINT12_3] = 5,
+ [IRQ_DA850_MCBSP0RINT] = 5,
+ [IRQ_DA850_MCBSP0XINT] = 5,
+ [IRQ_DA850_MCBSP1RINT] = 5,
+ [IRQ_DA850_MCBSP1XINT] = 5
+ };
+ #endif /* CONFIG_IPIPE */
+
/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata
= {
[IRQ_VDINT0] = 2,
***************
*** 325,330 ****
--- 434,443 ----
davinci_def_priorities = dm646x_default_priorities;
else if (cpu_is_davinci_dm355())
davinci_def_priorities = dm355_default_priorities;
+ #ifdef CONFIG_IPIPE
+ else if (cpu_is_da850())
+ davinci_def_priorities = da850_default_priorities;
+ #endif /* CONFIG_IPIPE */
/* Clear all interrupt requests */
davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
***************
*** 361,369 ****
--- 474,484 ----
for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
set_irq_chip(i, &davinci_irq_chip_0);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+ #ifndef CONFIG_IPIPE
if (i != IRQ_TINT1_TINT34)
set_irq_handler(i, handle_edge_irq);
else
+ #endif /* CONFIG IPIPE */
set_irq_handler(i, handle_level_irq);
}
}
diff -crB linux-03.20.00.05/arch/arm/mach-davinci/time.c
linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c
*** linux-03.20.00.05/arch/arm/mach-davinci/time.c 2009-07-29
02:53:15.000000000 -0300
--- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c 2010-01-08
17:07:36.000000000 -0200
***************
*** 30,35 ****
--- 30,41 ----
#include <mach/cpu.h>
#include "clock.h"
+ #ifdef CONFIG_IPIPE
+ #ifdef CONFIG_NO_IDLE_HZ
+ #error "dynamic tick timer not yet supported with IPIPE"
+ #endif /* CONFIG_NO_IDLE_HZ */
+ #endif /* CONFIG_IPIPE */
+
static struct clock_event_device clockevent_davinci;
static unsigned int davinci_clock_tick_rate;
***************
*** 70,75 ****
--- 76,102 ----
static int tid_system;
static int tid_freerun;
+ #ifdef CONFIG_IPIPE
+ int __ipipe_mach_timerint = IRQ_DA8XX_TINT12_0;
+ int __ipipe_mach_timerstolen = 0;
+ unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
+ static int davinci_timer_initialized;
+ union tsc_reg {
+ #ifdef __BIG_ENDIAN
+ struct {
+ unsigned long high;
+ unsigned long low;
+ };
+ #else /* __LITTLE_ENDIAN */
+ struct {
+ unsigned long low;
+ unsigned long high;
+ };
+ #endif /* __LITTLE_ENDIAN */
+ unsigned long long full;
+ };
+ #endif /* CONFIG_IPIPE */
+
/*
* This driver configures the 2 64-bit count-up timers as 4 independent
* 32-bit count-up timers used as follows:
***************
*** 92,97 ****
--- 119,125 ----
#define TGCR 0x24
#define WDTCR 0x28
#define CMP12(n) (0x60 + ((n) << 2))
+ #define INTCTLSTAT 0x44
/* Timer register bitfields */
#define TCR_ENAMODE_DISABLE 0x0
***************
*** 137,142 ****
--- 165,283 ----
#define TIMER_OPTS_ONESHOT 0x01
#define TIMER_OPTS_PERIODIC 0x02
+ /* Flags to be set when it is necessary to clear the */
+ /* status register for timer interrupts */
+ #define TIMER12_CLEAR_PRDINT 0x02
+ #define TIMER12_CLEAR_EVTINT 0x04
+
+ #ifdef CONFIG_IPIPE
+ #ifdef CONFIG_SMP
+ static union tsc_reg tsc[NR_CPUS];
+
+ void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
+ {
+ info->type = IPIPE_TSC_TYPE_NONE;
+ }
+ #else /* !CONFIG_SMP */
+ static union tsc_reg *tsc;
+
+ void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
+ {
+ info->type = IPIPE_TSC_TYPE_FREERUNNING;
+ info->u.fr.counter = (unsigned *)(DAVINCI_TIMER0_BASE + TIM12);
+ info->u.fr.mask = 0xffffffff;
+ info->u.fr.tsc = &tsc->full;
+ }
+ #endif /* !CONFIG_SMP */
+
+ void __ipipe_mach_acktimer(void)
+ {
+ void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
+ unsigned long status;
+
+ status = __raw_readl(base + INTCTLSTAT);
+ status |= (TIMER12_CLEAR_PRDINT | TIMER12_CLEAR_EVTINT);
+
+ __raw_writel(status,base+INTCTLSTAT);
+ }
+
+ static void ipipe_mach_update_tsc(void)
+ {
+ union tsc_reg *local_tsc;
+ unsigned long stamp, flags;
+ void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
+
+ local_irq_save_hw(flags);
+ local_tsc = &tsc[ipipe_processor_id()];
+ stamp = __raw_readl(base + TIM12);
+ if (unlikely(stamp < local_tsc->low))
+ /* 32 bit counter wrapped, increment high word. */
+ local_tsc->high++;
+ local_tsc->low = stamp;
+ local_irq_restore_hw(flags);
+ }
+
+ notrace unsigned long long __ipipe_mach_get_tsc(void)
+ {
+ if (likely(davinci_timer_initialized)) {
+ union tsc_reg *local_tsc, result;
+ unsigned long stamp;
+ void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
+
+ local_tsc = &tsc[ipipe_processor_id()];
+
+ __asm__("ldmia %1, %M0\n":
+ "=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
+ barrier();
+ stamp = __raw_readl(base + TIM12);
+ if (unlikely(stamp < result.low))
+ result.high++;
+ result.low = stamp;
+ return result.full;
+ }
+ return 0;
+ }
+ EXPORT_SYMBOL(__ipipe_mach_get_tsc);
+
+ /*
+ * Reprogram the timer
+ */
+ void __ipipe_mach_set_dec(unsigned long delay)
+ {
+ unsigned long flags;
+ unsigned int value;
+ void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
+
+ if (delay > 20) {
+ local_irq_save_hw(flags);
+
+ value = __raw_readl(base + TIM12) + delay;
+ __raw_writel(value,base + CMP12(0));
+ local_irq_restore_hw(flags);
+ } else {
+ ipipe_trigger_irq(IRQ_DA8XX_TINT12_0);
+ }
+ }
+ EXPORT_SYMBOL(__ipipe_mach_set_dec);
+
+ unsigned long __ipipe_mach_get_dec(void)
+ {
+ unsigned long value;
+ void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
+
+ value = __raw_readl(base + CMP12(0));
+ value -= __raw_readl(base + TIM12);
+
+ return value;
+ }
+
+ int __ipipe_check_tickdev(const char *devname)
+ {
+ return !strcmp(devname, clockevent_davinci.name);
+ }
+
+ #endif /* CONFIG_IPIPE */
+
static int timer32_config(struct timer_s *t)
{
u32 tcr = __raw_readl(t->base + TCR);
***************
*** 167,176 ****
--- 308,324 ----
return __raw_readl(t->base + t->tim_off);
}
+ /* Flavio Alves: for debugging */
+ extern void printascii(const char *);
+
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *evt = &clockevent_davinci;
+ // printascii("entrei\n");
+ #ifdef CONFIG_IPIPE
+ ipipe_mach_update_tsc();
+ #endif /* CONFIG_IPIPE */
evt->event_handler(evt);
return IRQ_HANDLED;
}
***************
*** 302,307 ****
--- 449,463 ----
timer32_config(timers[i]);
}
}
+
+ #ifdef CONFIG_IPIPE
+ #ifndef CONFIG_SMP
+ tsc = (union tsc_reg *)__ipipe_tsc_area;
+ barrier();
+ #endif /* CONFIG_SMP */
+ davinci_timer_initialized = 1;
+ #endif /* CONFIG_IPIPE */
+
}
/*
***************
*** 311,321 ****
{
struct timer_s *t;
! if (tid_freerun == -1)
t = timers[tid_system];
! else
t = timers[tid_freerun];
!
return (cycles_t)timer32_read(t);
}
--- 467,478 ----
{
struct timer_s *t;
! if (tid_freerun == -1) {
t = timers[tid_system];
! }
! else {
t = timers[tid_freerun];
! }
return (cycles_t)timer32_read(t);
}
***************
*** 549,551 ****
--- 706,718 ----
wdtcr = 0x00004000;
__raw_writel(wdtcr, base + WDTCR);
}
+
+ #ifdef CONFIG_IPIPE
+ void __ipipe_mach_release_timer(void)
+ {
+ davinci_set_mode(clockevent_davinci.mode, &clockevent_davinci);
+ if (clockevent_davinci.mode == CLOCK_EVT_MODE_ONESHOT)
+ davinci_set_next_event(LATCH, &clockevent_davinci);
+ }
+ EXPORT_SYMBOL(__ipipe_mach_release_timer);
+ #endif /* CONFIG_IPIPE */
Best regards,
Flavio
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
> Flavio de Castro Alves Filho wrote:
> > Of course :-)
> >
> > As I don't know the best way to send it, I attached the files.
> >
> > I hope everything is in there. I'm sorry if you find some ugly commented
> > debug code.
>
> Please send a diff.
>
> --
> Gilles.
>
[-- Attachment #2: Type: text/html, Size: 18621 bytes --]
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 21:54 ` Flavio de Castro Alves Filho
@ 2010-01-08 22:26 ` Gilles Chanteperdrix
2010-01-13 8:50 ` Flavio de Castro Alves Filho
0 siblings, 1 reply; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-08 22:26 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
aFlavio de Castro Alves Filho wrote:
> In fact,
>
> Much easier.
>
> *** linux-03.20.00.05/arch/arm/mach-davinci/gpio.c 2009-07-29
> 02:53:15.000000000 -0300
> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/gpio.c 2010-01-08
> 16:08:35.000000000 -0200
> ***************
> *** 27,32 ****
> --- 27,33 ----
>
> #include <asm/mach/irq.h>
>
> + #include <asm/ipipe.h>
>
> static DEFINE_SPINLOCK(gpio_lock);
>
> ***************
> *** 261,266 ****
> --- 262,315 ----
> /* now it may re-trigger */
> }
>
> + #ifdef CONFIG_IPIPE
> +
> + /* Flavio Alves: for debugging */
> + extern void printascii(const char *);
> +
> + void __ipipe_mach_demux_irq(unsigned irq, struct pt_regs *regs)
> + {
> + struct gpio_controller *__iomem g = get_irq_chip_data(irq);
> + struct irq_desc *desc;
> + u32 mask = 0xffff;
> +
> + //printascii("1__ipipe_mach_demux_irq\n");
> +
> + /* we only care about one bank */
> + if (irq & 1)
> + mask <<= 16;
> +
> + desc = &irq_desc[irq];
> +
> + /* temporarily mask (level sensitive) parent IRQ */
> + desc->chip->ack(irq);
Wrong comment. ->ack does not mask the parent irq, it just acks it.
masking it would be wrong by the way, since demux should not be done
with parent irq masked, as you will find out in the linux-arm-kernel
mailing list archives
> + while (1) {
> + u32 status;
> + int n;
> + int res;
> +
> + /* ack any irqs */
> + status = __raw_readl(&g->intstat) & mask;
> + if (!status)
> + break;
> + __raw_writel(status, &g->intstat);
> + if (irq & 1)
> + status >>= 16;
> +
> + /* now demux them to the right lowlevel handler */
> + n = (int)get_irq_data(irq);
> + while (status) {
> + res = ffs(status);
> + n += res;
> + __ipipe_handle_irq((n-1),regs);
> + status >>= res;
> + }
This while loop should reread the hardware status at each iteration, to
take into account new interrupts which would have showed up while
handling the last interrupt.
> + }
> + desc->chip->unmask(irq);
Not needed since you did not mask the parent irq.
> + /* now it may re-trigger */
> + }
> + #endif /* CONFIG_IPIPE */
> +
> /*
> * NOTE: for suspend/resume, probably best to make a platform_device with
> * suspend_late/resume_resume calls hooking into results of the set_wake()
> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
> *** linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
> 2009-07-29 02:53:15.000000000 -0300
> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
> 2010-01-06 16:45:56.000000000 -0200
> ***************
> *** 359,362 ****
> --- 359,381 ----
> #define IRQ_DA850_MCBSP1RINT 99
> #define IRQ_DA850_MCBSP1XINT 100
>
> + #ifdef CONFIG_IPIPE
> + #if 0
> + #define __ipipe_mach_irq_mux_p(irq) \
> + ((unsigned) (irq - IRQ_DA8XX_GPIO0) \
> + <= (IRQ_DA8XX_GPIO7 - IRQ_DA8XX_GPIO0))
> + #endif
> + #define __ipipe_mach_irq_mux_p(irq) \
> + ((irq) == IRQ_DA8XX_GPIO0 \
> + || (irq) == IRQ_DA8XX_GPIO1 \
> + || (irq) == IRQ_DA8XX_GPIO2 \
> + || (irq) == IRQ_DA8XX_GPIO3 \
> + || (irq) == IRQ_DA8XX_GPIO4 \
> + || (irq) == IRQ_DA8XX_GPIO5 \
> + || (irq) == IRQ_DA8XX_GPIO6 \
> + || (irq) == IRQ_DA8XX_GPIO7)
Yuck. The "#if 0"ed one solution seems much better. You have to realize
that this macro is called for every interrupt so, it has to be pretty
fast. If the interrupts are not consecutive, then use a bit field
(s3cxxxx does it IIRC). But to get things working it is ok, you can fix
this later.
> +
> +
> + #endif /* CONFIG_IPIPE */
> +
> #endif /* __ASM_ARCH_IRQS_H */
> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/irq.c
> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c
> *** linux-03.20.00.05/arch/arm/mach-davinci/irq.c 2009-07-29
> 02:53:15.000000000 -0300
> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c 2010-01-08
> 15:22:13.000000000 -0200
> ***************
> *** 111,119 ****
> --- 111,228 ----
> .name = "AINTC",
> .ack = davinci_ack_irq,
> .mask = davinci_mask_irq,
> + #ifdef CONFIG_IPIPE
> + .mask_ack = davinci_mask_irq,
> + #endif /* CONFIG_IPIPE */
No, no, no. BIG BUG here. Your PIC has different ack and mask routines,
so, both should be called by mask_ack.
You did not get this idea from the porting howto. I made this on some
platforms whre the ack and mask routines were the same, so that mask_ack
ended up doing twice the same thing.
Anyway, this kind of optimization is to be left aside when starting the
port.
> .unmask = davinci_unmask_irq,
> };
>
> + #ifdef CONFIG_IPIPE
> + static const u8 da850_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata =
> {
> + [IRQ_DA8XX_COMMTX] = 7,
> + [IRQ_DA8XX_COMMRX] = 7,
> + [IRQ_DA8XX_NINT] = 7,
> + [IRQ_DA8XX_EVTOUT0] = 7,
> + [IRQ_DA8XX_EVTOUT1] = 7,
> + [IRQ_DA8XX_EVTOUT2] = 7,
> + [IRQ_DA8XX_EVTOUT3] = 7,
> + [IRQ_DA8XX_EVTOUT4] = 7,
> + [IRQ_DA8XX_EVTOUT5] = 7,
> + [IRQ_DA8XX_EVTOUT6] = 7,
> + [IRQ_DA8XX_EVTOUT7] = 7,
> + [IRQ_DA8XX_CCINT0] = 7,
> + [IRQ_DA8XX_CCERRINT] = 7,
> + [IRQ_DA8XX_TCERRINT0] = 7,
> + [IRQ_DA8XX_AEMIFINT] = 7,
> + [IRQ_DA8XX_I2CINT0] = 5,
> + [IRQ_DA8XX_MMCSDINT0] = 5,
> + [IRQ_DA8XX_MMCSDINT1] = 5,
> + [IRQ_DA8XX_ALLINT0] = 5,
> + [IRQ_DA8XX_RTC] = 4,
> + [IRQ_DA8XX_SPINT0] = 5,
> + [IRQ_DA8XX_TINT12_0] = 2,
> + [IRQ_DA8XX_TINT34_0] = 5,
> + [IRQ_DA8XX_TINT12_1] = 5,
> + [IRQ_DA8XX_TINT34_1] = 5,
> + [IRQ_DA8XX_UARTINT0] = 5,
> + [IRQ_DA8XX_KEYMGRINT] = 7,
> + [IRQ_DA850_MIOPU_BOOTCFG_ERR] = 7,
> + [IRQ_DA8XX_CHIPINT0] = 7,
> + [IRQ_DA8XX_CHIPINT1] = 7,
> + [IRQ_DA8XX_CHIPINT2] = 7,
> + [IRQ_DA8XX_CHIPINT3] = 7,
> + [IRQ_DA8XX_TCERRINT1] = 7,
> + [IRQ_DA8XX_C0_RX_THRESH_PULSE] = 7,
> + [IRQ_DA8XX_C0_RX_PULSE] = 7,
> + [IRQ_DA8XX_C0_TX_PULSE] = 7,
> + [IRQ_DA8XX_C0_MISC_PULSE] = 7,
> + [IRQ_DA8XX_C1_RX_THRESH_PULSE] = 7,
> + [IRQ_DA8XX_C1_RX_PULSE] = 7,
> + [IRQ_DA8XX_C1_TX_PULSE] = 7,
> + [IRQ_DA8XX_C1_MISC_PULSE] = 7,
> + [IRQ_DA8XX_MEMERR] = 5,
> + [IRQ_DA8XX_GPIO0] = 6,
> + [IRQ_DA8XX_GPIO1] = 6,
> + [IRQ_DA8XX_GPIO2] = 6,
> + [IRQ_DA8XX_GPIO3] = 6,
> + [IRQ_DA8XX_GPIO4] = 6,
> + [IRQ_DA8XX_GPIO5] = 6,
> + [IRQ_DA8XX_GPIO6] = 6,
> + [IRQ_DA8XX_GPIO7] = 6,
> + [IRQ_DA8XX_GPIO8] = 6,
> + [IRQ_DA8XX_I2CINT1] = 5,
> + [IRQ_DA8XX_LCDINT] = 5,
> + [IRQ_DA8XX_UARTINT1] = 5,
> + [IRQ_DA8XX_MCASPINT] = 5,
> + [IRQ_DA8XX_ALLINT1] = 5,
> + [IRQ_DA8XX_SPINT1] = 5,
> + [IRQ_DA8XX_UHPI_INT1] = 5,
> + [IRQ_DA8XX_USB_INT] = 5,
> + [IRQ_DA8XX_IRQN] = 5,
> + [IRQ_DA8XX_RWAKEUP] = 5,
> + [IRQ_DA8XX_UARTINT2] = 5,
> + [IRQ_DA8XX_DFTSSINT] = 5,
> + [IRQ_DA8XX_EHRPWM0] = 7,
> + [IRQ_DA8XX_EHRPWM0TZ] = 7,
> + [IRQ_DA8XX_EHRPWM1] = 7,
> + [IRQ_DA8XX_EHRPWM1TZ] = 7,
> + [IRQ_DA850_SATAINT] = 5,
> + [IRQ_DA850_TINT12_2] = 5,
> + [IRQ_DA8XX_ECAP0] = 7,
> + [IRQ_DA8XX_ECAP1] = 7,
> + [IRQ_DA8XX_ECAP2] = 7,
> + [IRQ_DA850_MMCSDINT0_1] = 5,
> + [IRQ_DA850_MMCSDINT1_1] = 5,
> + [IRQ_DA850_T12CMPINT0_2] = 7,
> + [IRQ_DA850_T12CMPINT1_2] = 7,
> + [IRQ_DA850_T12CMPINT2_2] = 7,
> + [IRQ_DA850_T12CMPINT3_2] = 7,
> + [IRQ_DA850_T12CMPINT4_2] = 7,
> + [IRQ_DA850_T12CMPINT5_2] = 7,
> + [IRQ_DA850_T12CMPINT6_2] = 7,
> + [IRQ_DA850_T12CMPINT7_2] = 7,
> + [IRQ_DA850_T12CMPINT0_3] = 7,
> + [IRQ_DA850_T12CMPINT1_3] = 7,
> + [IRQ_DA850_T12CMPINT2_3] = 7,
> + [IRQ_DA850_T12CMPINT3_3] = 7,
> + [IRQ_DA850_T12CMPINT4_3] = 7,
> + [IRQ_DA850_T12CMPINT5_3] = 7,
> + [IRQ_DA850_T12CMPINT6_3] = 7,
> + [IRQ_DA850_T12CMPINT7_3] = 7,
> + [IRQ_DA8XX_ARMCLKSTOPREQ] = 7,
> + [IRQ_DA850_RPIINT] = 7,
> + [IRQ_DA850_VPIFINT] = 7,
> + [IRQ_DA850_CCINT1] = 7,
> + [IRQ_DA850_CCERRINT1] = 7,
> + [IRQ_DA850_TCERRINT2] = 7,
> + [IRQ_DA850_TINT12_3] = 5,
> + [IRQ_DA850_MCBSP0RINT] = 5,
> + [IRQ_DA850_MCBSP0XINT] = 5,
> + [IRQ_DA850_MCBSP1RINT] = 5,
> + [IRQ_DA850_MCBSP1XINT] = 5
> + };
> + #endif /* CONFIG_IPIPE */
Fiddling with IRQ priorities is mostly useless if you send the EOI to
the interrupt controller at the beginning of the interrupt handling as
davinci_ack_irq seems to do it.
Besides, we have the (undocumented) PIC mute functionality wich is even
better than interrupt priorities. I need to document it sometimes.
> +
> /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
> static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata
> = {
> [IRQ_VDINT0] = 2,
> ***************
> *** 325,330 ****
> --- 434,443 ----
> davinci_def_priorities = dm646x_default_priorities;
> else if (cpu_is_davinci_dm355())
> davinci_def_priorities = dm355_default_priorities;
> + #ifdef CONFIG_IPIPE
> + else if (cpu_is_da850())
> + davinci_def_priorities = da850_default_priorities;
> + #endif /* CONFIG_IPIPE */
>
> /* Clear all interrupt requests */
> davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
> ***************
> *** 361,369 ****
> --- 474,484 ----
> for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
> set_irq_chip(i, &davinci_irq_chip_0);
> set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
> + #ifndef CONFIG_IPIPE
> if (i != IRQ_TINT1_TINT34)
> set_irq_handler(i, handle_edge_irq);
> else
> + #endif /* CONFIG IPIPE */
> set_irq_handler(i, handle_level_irq);
> }
> }
> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/time.c
> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c
> *** linux-03.20.00.05/arch/arm/mach-davinci/time.c 2009-07-29
> 02:53:15.000000000 -0300
> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c 2010-01-08
> 17:07:36.000000000 -0200
> ***************
> *** 30,35 ****
> --- 30,41 ----
> #include <mach/cpu.h>
> #include "clock.h"
>
> + #ifdef CONFIG_IPIPE
> + #ifdef CONFIG_NO_IDLE_HZ
> + #error "dynamic tick timer not yet supported with IPIPE"
> + #endif /* CONFIG_NO_IDLE_HZ */
> + #endif /* CONFIG_IPIPE */
> +
> static struct clock_event_device clockevent_davinci;
> static unsigned int davinci_clock_tick_rate;
>
> ***************
> *** 70,75 ****
> --- 76,102 ----
> static int tid_system;
> static int tid_freerun;
>
> + #ifdef CONFIG_IPIPE
> + int __ipipe_mach_timerint = IRQ_DA8XX_TINT12_0;
> + int __ipipe_mach_timerstolen = 0;
> + unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
> + static int davinci_timer_initialized;
> + union tsc_reg {
> + #ifdef __BIG_ENDIAN
> + struct {
> + unsigned long high;
> + unsigned long low;
> + };
> + #else /* __LITTLE_ENDIAN */
> + struct {
> + unsigned long low;
> + unsigned long high;
> + };
> + #endif /* __LITTLE_ENDIAN */
> + unsigned long long full;
> + };
> + #endif /* CONFIG_IPIPE */
> +
> /*
> * This driver configures the 2 64-bit count-up timers as 4 independent
> * 32-bit count-up timers used as follows:
> ***************
> *** 92,97 ****
> --- 119,125 ----
> #define TGCR 0x24
> #define WDTCR 0x28
> #define CMP12(n) (0x60 + ((n) << 2))
> + #define INTCTLSTAT 0x44
>
> /* Timer register bitfields */
> #define TCR_ENAMODE_DISABLE 0x0
> ***************
> *** 137,142 ****
> --- 165,283 ----
> #define TIMER_OPTS_ONESHOT 0x01
> #define TIMER_OPTS_PERIODIC 0x02
>
> + /* Flags to be set when it is necessary to clear the */
> + /* status register for timer interrupts */
> + #define TIMER12_CLEAR_PRDINT 0x02
> + #define TIMER12_CLEAR_EVTINT 0x04
> +
> + #ifdef CONFIG_IPIPE
> + #ifdef CONFIG_SMP
> + static union tsc_reg tsc[NR_CPUS];
> +
> + void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
> + {
> + info->type = IPIPE_TSC_TYPE_NONE;
> + }
> + #else /* !CONFIG_SMP */
> + static union tsc_reg *tsc;
> +
> + void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
> + {
> + info->type = IPIPE_TSC_TYPE_FREERUNNING;
> + info->u.fr.counter = (unsigned *)(DAVINCI_TIMER0_BASE + TIM12);
> + info->u.fr.mask = 0xffffffff;
> + info->u.fr.tsc = &tsc->full;
> + }
> + #endif /* !CONFIG_SMP */
> +
> + void __ipipe_mach_acktimer(void)
> + {
> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
> + unsigned long status;
> +
> + status = __raw_readl(base + INTCTLSTAT);
> + status |= (TIMER12_CLEAR_PRDINT | TIMER12_CLEAR_EVTINT);
> +
> + __raw_writel(status,base+INTCTLSTAT);
> + }
> +
> + static void ipipe_mach_update_tsc(void)
> + {
> + union tsc_reg *local_tsc;
> + unsigned long stamp, flags;
> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
> +
> + local_irq_save_hw(flags);
> + local_tsc = &tsc[ipipe_processor_id()];
> + stamp = __raw_readl(base + TIM12);
> + if (unlikely(stamp < local_tsc->low))
> + /* 32 bit counter wrapped, increment high word. */
> + local_tsc->high++;
> + local_tsc->low = stamp;
> + local_irq_restore_hw(flags);
> + }
> +
> + notrace unsigned long long __ipipe_mach_get_tsc(void)
> + {
> + if (likely(davinci_timer_initialized)) {
> + union tsc_reg *local_tsc, result;
> + unsigned long stamp;
> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
> +
> + local_tsc = &tsc[ipipe_processor_id()];
> +
> + __asm__("ldmia %1, %M0\n":
> + "=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
> + barrier();
> + stamp = __raw_readl(base + TIM12);
> + if (unlikely(stamp < result.low))
> + result.high++;
> + result.low = stamp;
> + return result.full;
> + }
> + return 0;
> + }
> + EXPORT_SYMBOL(__ipipe_mach_get_tsc);
> +
> + /*
> + * Reprogram the timer
> + */
> + void __ipipe_mach_set_dec(unsigned long delay)
> + {
> + unsigned long flags;
> + unsigned int value;
> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
> +
> + if (delay > 20) {
> + local_irq_save_hw(flags);
> +
> + value = __raw_readl(base + TIM12) + delay;
> + __raw_writel(value,base + CMP12(0));
> + local_irq_restore_hw(flags);
> + } else {
> + ipipe_trigger_irq(IRQ_DA8XX_TINT12_0);
> + }
> + }
I can not really comment on that, since I do not really know the
hardware details, though the code seems to indicate that the minimum is
1, not 20. 20 should be Ok for a first run though:
clockevent_davinci.min_delta_ns =
clockevent_delta2ns(1, &clockevent_davinci);
> + EXPORT_SYMBOL(__ipipe_mach_set_dec);
> +
> + unsigned long __ipipe_mach_get_dec(void)
> + {
> + unsigned long value;
> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
> +
> + value = __raw_readl(base + CMP12(0));
> + value -= __raw_readl(base + TIM12);
> +
> + return value;
> + }
> +
> + int __ipipe_check_tickdev(const char *devname)
> + {
> + return !strcmp(devname, clockevent_davinci.name);
> + }
> +
> + #endif /* CONFIG_IPIPE */
> +
> static int timer32_config(struct timer_s *t)
> {
> u32 tcr = __raw_readl(t->base + TCR);
> ***************
> *** 167,176 ****
> --- 308,324 ----
> return __raw_readl(t->base + t->tim_off);
> }
>
> + /* Flavio Alves: for debugging */
> + extern void printascii(const char *);
> +
> static irqreturn_t timer_interrupt(int irq, void *dev_id)
> {
> struct clock_event_device *evt = &clockevent_davinci;
>
> + // printascii("entrei\n");
> + #ifdef CONFIG_IPIPE
> + ipipe_mach_update_tsc();
> + #endif /* CONFIG_IPIPE */
> evt->event_handler(evt);
> return IRQ_HANDLED;
> }
Ah. You have to realize that if the clockevent framework chooses an
other clockevent than this one, timer_interrupt will no longer be
called, so the tsc will wrap instead of incrementing correctly. So, as
explained in a previous mail, you have to:
- either increment clockevent_davinci.rating (currently uninitialized if
I read the code correctly, so 0)
- or base Xenomai timer on the other clockevent,
- or call ipipe_mach_update_tsc() in __ipipe_mach_acktimer (not a good
long term solution, but good for a quick test)
> ***************
> *** 302,307 ****
> --- 449,463 ----
> timer32_config(timers[i]);
> }
> }
> +
> + #ifdef CONFIG_IPIPE
> + #ifndef CONFIG_SMP
> + tsc = (union tsc_reg *)__ipipe_tsc_area;
> + barrier();
> + #endif /* CONFIG_SMP */
> + davinci_timer_initialized = 1;
> + #endif /* CONFIG_IPIPE */
> +
> }
>
> /*
> ***************
> *** 311,321 ****
> {
> struct timer_s *t;
>
> ! if (tid_freerun == -1)
> t = timers[tid_system];
> ! else
> t = timers[tid_freerun];
> !
> return (cycles_t)timer32_read(t);
> }
>
> --- 467,478 ----
> {
> struct timer_s *t;
>
> ! if (tid_freerun == -1) {
> t = timers[tid_system];
> ! }
> ! else {
> t = timers[tid_freerun];
> ! }
> return (cycles_t)timer32_read(t);
> }
>
> ***************
> *** 549,551 ****
> --- 706,718 ----
> wdtcr = 0x00004000;
> __raw_writel(wdtcr, base + WDTCR);
> }
> +
> + #ifdef CONFIG_IPIPE
> + void __ipipe_mach_release_timer(void)
> + {
> + davinci_set_mode(clockevent_davinci.mode, &clockevent_davinci);
> + if (clockevent_davinci.mode == CLOCK_EVT_MODE_ONESHOT)
> + davinci_set_next_event(LATCH, &clockevent_davinci);
> + }
> + EXPORT_SYMBOL(__ipipe_mach_release_timer);
> + #endif /* CONFIG_IPIPE */
>
> Best regards,
Ok. I think the bug really comes from the ack_mask thing. Other than
that, great work, the patch looks fine. Good luck.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-08 22:26 ` Gilles Chanteperdrix
@ 2010-01-13 8:50 ` Flavio de Castro Alves Filho
2010-01-13 10:05 ` Gilles Chanteperdrix
0 siblings, 1 reply; 38+ messages in thread
From: Flavio de Castro Alves Filho @ 2010-01-13 8:50 UTC (permalink / raw)
To: xenomai
Hello Gilles,
First of all, really thank you for you revision. It was really helpful.
And ... about the changes. I implemented the corrections as you
suggested and it is still not working. It is blocking allways at the
same place.
I'm still working to find out a solution.
Thank you very much.
Flavio
Flavio de Castro Alves Filho
Phi Innovations - Embedded Software Services
www.phiinnovations.com
Phone: +55 11 84 94 56 76
Skype: flavio.de.castro.alves.filho
2010/1/8 Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>:
> aFlavio de Castro Alves Filho wrote:
>> In fact,
>>
>> Much easier.
>>
>> *** linux-03.20.00.05/arch/arm/mach-davinci/gpio.c 2009-07-29
>> 02:53:15.000000000 -0300
>> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/gpio.c 2010-01-08
>> 16:08:35.000000000 -0200
>> ***************
>> *** 27,32 ****
>> --- 27,33 ----
>>
>> #include <asm/mach/irq.h>
>>
>> + #include <asm/ipipe.h>
>>
>> static DEFINE_SPINLOCK(gpio_lock);
>>
>> ***************
>> *** 261,266 ****
>> --- 262,315 ----
>> /* now it may re-trigger */
>> }
>>
>> + #ifdef CONFIG_IPIPE
>> +
>> + /* Flavio Alves: for debugging */
>> + extern void printascii(const char *);
>> +
>> + void __ipipe_mach_demux_irq(unsigned irq, struct pt_regs *regs)
>> + {
>> + struct gpio_controller *__iomem g = get_irq_chip_data(irq);
>> + struct irq_desc *desc;
>> + u32 mask = 0xffff;
>> +
>> + //printascii("1__ipipe_mach_demux_irq\n");
>> +
>> + /* we only care about one bank */
>> + if (irq & 1)
>> + mask <<= 16;
>> +
>> + desc = &irq_desc[irq];
>> +
>> + /* temporarily mask (level sensitive) parent IRQ */
>> + desc->chip->ack(irq);
>
> Wrong comment. ->ack does not mask the parent irq, it just acks it.
> masking it would be wrong by the way, since demux should not be done
> with parent irq masked, as you will find out in the linux-arm-kernel
> mailing list archives
>
>> + while (1) {
>> + u32 status;
>> + int n;
>> + int res;
>> +
>> + /* ack any irqs */
>> + status = __raw_readl(&g->intstat) & mask;
>> + if (!status)
>> + break;
>> + __raw_writel(status, &g->intstat);
>> + if (irq & 1)
>> + status >>= 16;
>> +
>> + /* now demux them to the right lowlevel handler */
>> + n = (int)get_irq_data(irq);
>> + while (status) {
>> + res = ffs(status);
>> + n += res;
>> + __ipipe_handle_irq((n-1),regs);
>> + status >>= res;
>> + }
>
> This while loop should reread the hardware status at each iteration, to
> take into account new interrupts which would have showed up while
> handling the last interrupt.
>
>> + }
>> + desc->chip->unmask(irq);
>
> Not needed since you did not mask the parent irq.
>
>> + /* now it may re-trigger */
>> + }
>> + #endif /* CONFIG_IPIPE */
>> +
>> /*
>> * NOTE: for suspend/resume, probably best to make a platform_device with
>> * suspend_late/resume_resume calls hooking into results of the set_wake()
>> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
>> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
>> *** linux-03.20.00.05/arch/arm/mach-davinci/include/mach/irqs.h
>> 2009-07-29 02:53:15.000000000 -0300
>> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/include/mach/irqs.h
>> 2010-01-06 16:45:56.000000000 -0200
>> ***************
>> *** 359,362 ****
>> --- 359,381 ----
>> #define IRQ_DA850_MCBSP1RINT 99
>> #define IRQ_DA850_MCBSP1XINT 100
>>
>> + #ifdef CONFIG_IPIPE
>> + #if 0
>> + #define __ipipe_mach_irq_mux_p(irq) \
>> + ((unsigned) (irq - IRQ_DA8XX_GPIO0) \
>> + <= (IRQ_DA8XX_GPIO7 - IRQ_DA8XX_GPIO0))
>> + #endif
>> + #define __ipipe_mach_irq_mux_p(irq) \
>> + ((irq) == IRQ_DA8XX_GPIO0 \
>> + || (irq) == IRQ_DA8XX_GPIO1 \
>> + || (irq) == IRQ_DA8XX_GPIO2 \
>> + || (irq) == IRQ_DA8XX_GPIO3 \
>> + || (irq) == IRQ_DA8XX_GPIO4 \
>> + || (irq) == IRQ_DA8XX_GPIO5 \
>> + || (irq) == IRQ_DA8XX_GPIO6 \
>> + || (irq) == IRQ_DA8XX_GPIO7)
>
> Yuck. The "#if 0"ed one solution seems much better. You have to realize
> that this macro is called for every interrupt so, it has to be pretty
> fast. If the interrupts are not consecutive, then use a bit field
> (s3cxxxx does it IIRC). But to get things working it is ok, you can fix
> this later.
>
>> +
>> +
>> + #endif /* CONFIG_IPIPE */
>> +
>> #endif /* __ASM_ARCH_IRQS_H */
>> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/irq.c
>> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c
>> *** linux-03.20.00.05/arch/arm/mach-davinci/irq.c 2009-07-29
>> 02:53:15.000000000 -0300
>> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/irq.c 2010-01-08
>> 15:22:13.000000000 -0200
>> ***************
>> *** 111,119 ****
>> --- 111,228 ----
>> .name = "AINTC",
>> .ack = davinci_ack_irq,
>> .mask = davinci_mask_irq,
>> + #ifdef CONFIG_IPIPE
>> + .mask_ack = davinci_mask_irq,
>> + #endif /* CONFIG_IPIPE */
>
> No, no, no. BIG BUG here. Your PIC has different ack and mask routines,
> so, both should be called by mask_ack.
>
> You did not get this idea from the porting howto. I made this on some
> platforms whre the ack and mask routines were the same, so that mask_ack
> ended up doing twice the same thing.
>
> Anyway, this kind of optimization is to be left aside when starting the
> port.
>
>> .unmask = davinci_unmask_irq,
>> };
>>
>> + #ifdef CONFIG_IPIPE
>> + static const u8 da850_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata =
>> {
>> + [IRQ_DA8XX_COMMTX] = 7,
>> + [IRQ_DA8XX_COMMRX] = 7,
>> + [IRQ_DA8XX_NINT] = 7,
>> + [IRQ_DA8XX_EVTOUT0] = 7,
>> + [IRQ_DA8XX_EVTOUT1] = 7,
>> + [IRQ_DA8XX_EVTOUT2] = 7,
>> + [IRQ_DA8XX_EVTOUT3] = 7,
>> + [IRQ_DA8XX_EVTOUT4] = 7,
>> + [IRQ_DA8XX_EVTOUT5] = 7,
>> + [IRQ_DA8XX_EVTOUT6] = 7,
>> + [IRQ_DA8XX_EVTOUT7] = 7,
>> + [IRQ_DA8XX_CCINT0] = 7,
>> + [IRQ_DA8XX_CCERRINT] = 7,
>> + [IRQ_DA8XX_TCERRINT0] = 7,
>> + [IRQ_DA8XX_AEMIFINT] = 7,
>> + [IRQ_DA8XX_I2CINT0] = 5,
>> + [IRQ_DA8XX_MMCSDINT0] = 5,
>> + [IRQ_DA8XX_MMCSDINT1] = 5,
>> + [IRQ_DA8XX_ALLINT0] = 5,
>> + [IRQ_DA8XX_RTC] = 4,
>> + [IRQ_DA8XX_SPINT0] = 5,
>> + [IRQ_DA8XX_TINT12_0] = 2,
>> + [IRQ_DA8XX_TINT34_0] = 5,
>> + [IRQ_DA8XX_TINT12_1] = 5,
>> + [IRQ_DA8XX_TINT34_1] = 5,
>> + [IRQ_DA8XX_UARTINT0] = 5,
>> + [IRQ_DA8XX_KEYMGRINT] = 7,
>> + [IRQ_DA850_MIOPU_BOOTCFG_ERR] = 7,
>> + [IRQ_DA8XX_CHIPINT0] = 7,
>> + [IRQ_DA8XX_CHIPINT1] = 7,
>> + [IRQ_DA8XX_CHIPINT2] = 7,
>> + [IRQ_DA8XX_CHIPINT3] = 7,
>> + [IRQ_DA8XX_TCERRINT1] = 7,
>> + [IRQ_DA8XX_C0_RX_THRESH_PULSE] = 7,
>> + [IRQ_DA8XX_C0_RX_PULSE] = 7,
>> + [IRQ_DA8XX_C0_TX_PULSE] = 7,
>> + [IRQ_DA8XX_C0_MISC_PULSE] = 7,
>> + [IRQ_DA8XX_C1_RX_THRESH_PULSE] = 7,
>> + [IRQ_DA8XX_C1_RX_PULSE] = 7,
>> + [IRQ_DA8XX_C1_TX_PULSE] = 7,
>> + [IRQ_DA8XX_C1_MISC_PULSE] = 7,
>> + [IRQ_DA8XX_MEMERR] = 5,
>> + [IRQ_DA8XX_GPIO0] = 6,
>> + [IRQ_DA8XX_GPIO1] = 6,
>> + [IRQ_DA8XX_GPIO2] = 6,
>> + [IRQ_DA8XX_GPIO3] = 6,
>> + [IRQ_DA8XX_GPIO4] = 6,
>> + [IRQ_DA8XX_GPIO5] = 6,
>> + [IRQ_DA8XX_GPIO6] = 6,
>> + [IRQ_DA8XX_GPIO7] = 6,
>> + [IRQ_DA8XX_GPIO8] = 6,
>> + [IRQ_DA8XX_I2CINT1] = 5,
>> + [IRQ_DA8XX_LCDINT] = 5,
>> + [IRQ_DA8XX_UARTINT1] = 5,
>> + [IRQ_DA8XX_MCASPINT] = 5,
>> + [IRQ_DA8XX_ALLINT1] = 5,
>> + [IRQ_DA8XX_SPINT1] = 5,
>> + [IRQ_DA8XX_UHPI_INT1] = 5,
>> + [IRQ_DA8XX_USB_INT] = 5,
>> + [IRQ_DA8XX_IRQN] = 5,
>> + [IRQ_DA8XX_RWAKEUP] = 5,
>> + [IRQ_DA8XX_UARTINT2] = 5,
>> + [IRQ_DA8XX_DFTSSINT] = 5,
>> + [IRQ_DA8XX_EHRPWM0] = 7,
>> + [IRQ_DA8XX_EHRPWM0TZ] = 7,
>> + [IRQ_DA8XX_EHRPWM1] = 7,
>> + [IRQ_DA8XX_EHRPWM1TZ] = 7,
>> + [IRQ_DA850_SATAINT] = 5,
>> + [IRQ_DA850_TINT12_2] = 5,
>> + [IRQ_DA8XX_ECAP0] = 7,
>> + [IRQ_DA8XX_ECAP1] = 7,
>> + [IRQ_DA8XX_ECAP2] = 7,
>> + [IRQ_DA850_MMCSDINT0_1] = 5,
>> + [IRQ_DA850_MMCSDINT1_1] = 5,
>> + [IRQ_DA850_T12CMPINT0_2] = 7,
>> + [IRQ_DA850_T12CMPINT1_2] = 7,
>> + [IRQ_DA850_T12CMPINT2_2] = 7,
>> + [IRQ_DA850_T12CMPINT3_2] = 7,
>> + [IRQ_DA850_T12CMPINT4_2] = 7,
>> + [IRQ_DA850_T12CMPINT5_2] = 7,
>> + [IRQ_DA850_T12CMPINT6_2] = 7,
>> + [IRQ_DA850_T12CMPINT7_2] = 7,
>> + [IRQ_DA850_T12CMPINT0_3] = 7,
>> + [IRQ_DA850_T12CMPINT1_3] = 7,
>> + [IRQ_DA850_T12CMPINT2_3] = 7,
>> + [IRQ_DA850_T12CMPINT3_3] = 7,
>> + [IRQ_DA850_T12CMPINT4_3] = 7,
>> + [IRQ_DA850_T12CMPINT5_3] = 7,
>> + [IRQ_DA850_T12CMPINT6_3] = 7,
>> + [IRQ_DA850_T12CMPINT7_3] = 7,
>> + [IRQ_DA8XX_ARMCLKSTOPREQ] = 7,
>> + [IRQ_DA850_RPIINT] = 7,
>> + [IRQ_DA850_VPIFINT] = 7,
>> + [IRQ_DA850_CCINT1] = 7,
>> + [IRQ_DA850_CCERRINT1] = 7,
>> + [IRQ_DA850_TCERRINT2] = 7,
>> + [IRQ_DA850_TINT12_3] = 5,
>> + [IRQ_DA850_MCBSP0RINT] = 5,
>> + [IRQ_DA850_MCBSP0XINT] = 5,
>> + [IRQ_DA850_MCBSP1RINT] = 5,
>> + [IRQ_DA850_MCBSP1XINT] = 5
>> + };
>> + #endif /* CONFIG_IPIPE */
>
> Fiddling with IRQ priorities is mostly useless if you send the EOI to
> the interrupt controller at the beginning of the interrupt handling as
> davinci_ack_irq seems to do it.
>
> Besides, we have the (undocumented) PIC mute functionality wich is even
> better than interrupt priorities. I need to document it sometimes.
>
>> +
>> /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
>> static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata
>> = {
>> [IRQ_VDINT0] = 2,
>> ***************
>> *** 325,330 ****
>> --- 434,443 ----
>> davinci_def_priorities = dm646x_default_priorities;
>> else if (cpu_is_davinci_dm355())
>> davinci_def_priorities = dm355_default_priorities;
>> + #ifdef CONFIG_IPIPE
>> + else if (cpu_is_da850())
>> + davinci_def_priorities = da850_default_priorities;
>> + #endif /* CONFIG_IPIPE */
>>
>> /* Clear all interrupt requests */
>> davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
>> ***************
>> *** 361,369 ****
>> --- 474,484 ----
>> for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
>> set_irq_chip(i, &davinci_irq_chip_0);
>> set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
>> + #ifndef CONFIG_IPIPE
>> if (i != IRQ_TINT1_TINT34)
>> set_irq_handler(i, handle_edge_irq);
>> else
>> + #endif /* CONFIG IPIPE */
>> set_irq_handler(i, handle_level_irq);
>> }
>> }
>> diff -crB linux-03.20.00.05/arch/arm/mach-davinci/time.c
>> linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c
>> *** linux-03.20.00.05/arch/arm/mach-davinci/time.c 2009-07-29
>> 02:53:15.000000000 -0300
>> --- linux-03.20.00.05_xenomai/arch/arm/mach-davinci/time.c 2010-01-08
>> 17:07:36.000000000 -0200
>> ***************
>> *** 30,35 ****
>> --- 30,41 ----
>> #include <mach/cpu.h>
>> #include "clock.h"
>>
>> + #ifdef CONFIG_IPIPE
>> + #ifdef CONFIG_NO_IDLE_HZ
>> + #error "dynamic tick timer not yet supported with IPIPE"
>> + #endif /* CONFIG_NO_IDLE_HZ */
>> + #endif /* CONFIG_IPIPE */
>> +
>> static struct clock_event_device clockevent_davinci;
>> static unsigned int davinci_clock_tick_rate;
>>
>> ***************
>> *** 70,75 ****
>> --- 76,102 ----
>> static int tid_system;
>> static int tid_freerun;
>>
>> + #ifdef CONFIG_IPIPE
>> + int __ipipe_mach_timerint = IRQ_DA8XX_TINT12_0;
>> + int __ipipe_mach_timerstolen = 0;
>> + unsigned int __ipipe_mach_ticks_per_jiffy = LATCH;
>> + static int davinci_timer_initialized;
>> + union tsc_reg {
>> + #ifdef __BIG_ENDIAN
>> + struct {
>> + unsigned long high;
>> + unsigned long low;
>> + };
>> + #else /* __LITTLE_ENDIAN */
>> + struct {
>> + unsigned long low;
>> + unsigned long high;
>> + };
>> + #endif /* __LITTLE_ENDIAN */
>> + unsigned long long full;
>> + };
>> + #endif /* CONFIG_IPIPE */
>> +
>> /*
>> * This driver configures the 2 64-bit count-up timers as 4 independent
>> * 32-bit count-up timers used as follows:
>> ***************
>> *** 92,97 ****
>> --- 119,125 ----
>> #define TGCR 0x24
>> #define WDTCR 0x28
>> #define CMP12(n) (0x60 + ((n) << 2))
>> + #define INTCTLSTAT 0x44
>>
>> /* Timer register bitfields */
>> #define TCR_ENAMODE_DISABLE 0x0
>> ***************
>> *** 137,142 ****
>> --- 165,283 ----
>> #define TIMER_OPTS_ONESHOT 0x01
>> #define TIMER_OPTS_PERIODIC 0x02
>>
>> + /* Flags to be set when it is necessary to clear the */
>> + /* status register for timer interrupts */
>> + #define TIMER12_CLEAR_PRDINT 0x02
>> + #define TIMER12_CLEAR_EVTINT 0x04
>> +
>> + #ifdef CONFIG_IPIPE
>> + #ifdef CONFIG_SMP
>> + static union tsc_reg tsc[NR_CPUS];
>> +
>> + void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
>> + {
>> + info->type = IPIPE_TSC_TYPE_NONE;
>> + }
>> + #else /* !CONFIG_SMP */
>> + static union tsc_reg *tsc;
>> +
>> + void __ipipe_mach_get_tscinfo(struct __ipipe_tscinfo *info)
>> + {
>> + info->type = IPIPE_TSC_TYPE_FREERUNNING;
>> + info->u.fr.counter = (unsigned *)(DAVINCI_TIMER0_BASE + TIM12);
>> + info->u.fr.mask = 0xffffffff;
>> + info->u.fr.tsc = &tsc->full;
>> + }
>> + #endif /* !CONFIG_SMP */
>> +
>> + void __ipipe_mach_acktimer(void)
>> + {
>> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
>> + unsigned long status;
>> +
>> + status = __raw_readl(base + INTCTLSTAT);
>> + status |= (TIMER12_CLEAR_PRDINT | TIMER12_CLEAR_EVTINT);
>> +
>> + __raw_writel(status,base+INTCTLSTAT);
>> + }
>> +
>> + static void ipipe_mach_update_tsc(void)
>> + {
>> + union tsc_reg *local_tsc;
>> + unsigned long stamp, flags;
>> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
>> +
>> + local_irq_save_hw(flags);
>> + local_tsc = &tsc[ipipe_processor_id()];
>> + stamp = __raw_readl(base + TIM12);
>> + if (unlikely(stamp < local_tsc->low))
>> + /* 32 bit counter wrapped, increment high word. */
>> + local_tsc->high++;
>> + local_tsc->low = stamp;
>> + local_irq_restore_hw(flags);
>> + }
>> +
>> + notrace unsigned long long __ipipe_mach_get_tsc(void)
>> + {
>> + if (likely(davinci_timer_initialized)) {
>> + union tsc_reg *local_tsc, result;
>> + unsigned long stamp;
>> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
>> +
>> + local_tsc = &tsc[ipipe_processor_id()];
>> +
>> + __asm__("ldmia %1, %M0\n":
>> + "=r"(result.full): "r"(local_tsc), "m"(*local_tsc));
>> + barrier();
>> + stamp = __raw_readl(base + TIM12);
>> + if (unlikely(stamp < result.low))
>> + result.high++;
>> + result.low = stamp;
>> + return result.full;
>> + }
>> + return 0;
>> + }
>> + EXPORT_SYMBOL(__ipipe_mach_get_tsc);
>> +
>> + /*
>> + * Reprogram the timer
>> + */
>> + void __ipipe_mach_set_dec(unsigned long delay)
>> + {
>> + unsigned long flags;
>> + unsigned int value;
>> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
>> +
>> + if (delay > 20) {
>> + local_irq_save_hw(flags);
>> +
>> + value = __raw_readl(base + TIM12) + delay;
>> + __raw_writel(value,base + CMP12(0));
>> + local_irq_restore_hw(flags);
>> + } else {
>> + ipipe_trigger_irq(IRQ_DA8XX_TINT12_0);
>> + }
>> + }
>
> I can not really comment on that, since I do not really know the
> hardware details, though the code seems to indicate that the minimum is
> 1, not 20. 20 should be Ok for a first run though:
>
> clockevent_davinci.min_delta_ns =
> clockevent_delta2ns(1, &clockevent_davinci);
>
>> + EXPORT_SYMBOL(__ipipe_mach_set_dec);
>> +
>> + unsigned long __ipipe_mach_get_dec(void)
>> + {
>> + unsigned long value;
>> + void __iomem *base = IO_ADDRESS(DAVINCI_TIMER0_BASE);
>> +
>> + value = __raw_readl(base + CMP12(0));
>> + value -= __raw_readl(base + TIM12);
>> +
>> + return value;
>> + }
>> +
>> + int __ipipe_check_tickdev(const char *devname)
>> + {
>> + return !strcmp(devname, clockevent_davinci.name);
>> + }
>> +
>> + #endif /* CONFIG_IPIPE */
>> +
>> static int timer32_config(struct timer_s *t)
>> {
>> u32 tcr = __raw_readl(t->base + TCR);
>> ***************
>> *** 167,176 ****
>> --- 308,324 ----
>> return __raw_readl(t->base + t->tim_off);
>> }
>>
>> + /* Flavio Alves: for debugging */
>> + extern void printascii(const char *);
>> +
>> static irqreturn_t timer_interrupt(int irq, void *dev_id)
>> {
>> struct clock_event_device *evt = &clockevent_davinci;
>>
>> + // printascii("entrei\n");
>> + #ifdef CONFIG_IPIPE
>> + ipipe_mach_update_tsc();
>> + #endif /* CONFIG_IPIPE */
>> evt->event_handler(evt);
>> return IRQ_HANDLED;
>> }
>
> Ah. You have to realize that if the clockevent framework chooses an
> other clockevent than this one, timer_interrupt will no longer be
> called, so the tsc will wrap instead of incrementing correctly. So, as
> explained in a previous mail, you have to:
> - either increment clockevent_davinci.rating (currently uninitialized if
> I read the code correctly, so 0)
> - or base Xenomai timer on the other clockevent,
> - or call ipipe_mach_update_tsc() in __ipipe_mach_acktimer (not a good
> long term solution, but good for a quick test)
>
>
>
>> ***************
>> *** 302,307 ****
>> --- 449,463 ----
>> timer32_config(timers[i]);
>> }
>> }
>> +
>> + #ifdef CONFIG_IPIPE
>> + #ifndef CONFIG_SMP
>> + tsc = (union tsc_reg *)__ipipe_tsc_area;
>> + barrier();
>> + #endif /* CONFIG_SMP */
>> + davinci_timer_initialized = 1;
>> + #endif /* CONFIG_IPIPE */
>> +
>> }
>>
>> /*
>> ***************
>> *** 311,321 ****
>> {
>> struct timer_s *t;
>>
>> ! if (tid_freerun == -1)
>> t = timers[tid_system];
>> ! else
>> t = timers[tid_freerun];
>> !
>> return (cycles_t)timer32_read(t);
>> }
>>
>> --- 467,478 ----
>> {
>> struct timer_s *t;
>>
>> ! if (tid_freerun == -1) {
>> t = timers[tid_system];
>> ! }
>> ! else {
>> t = timers[tid_freerun];
>> ! }
>> return (cycles_t)timer32_read(t);
>> }
>>
>> ***************
>> *** 549,551 ****
>> --- 706,718 ----
>> wdtcr = 0x00004000;
>> __raw_writel(wdtcr, base + WDTCR);
>> }
>> +
>> + #ifdef CONFIG_IPIPE
>> + void __ipipe_mach_release_timer(void)
>> + {
>> + davinci_set_mode(clockevent_davinci.mode, &clockevent_davinci);
>> + if (clockevent_davinci.mode == CLOCK_EVT_MODE_ONESHOT)
>> + davinci_set_next_event(LATCH, &clockevent_davinci);
>> + }
>> + EXPORT_SYMBOL(__ipipe_mach_release_timer);
>> + #endif /* CONFIG_IPIPE */
>>
>> Best regards,
>
> Ok. I think the bug really comes from the ack_mask thing. Other than
> that, great work, the patch looks fine. Good luck.
>
> --
> Gilles.
>
^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [Xenomai-help] Porting I-Pipe for new ARM board
2010-01-13 8:50 ` Flavio de Castro Alves Filho
@ 2010-01-13 10:05 ` Gilles Chanteperdrix
0 siblings, 0 replies; 38+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-13 10:05 UTC (permalink / raw)
To: Flavio de Castro Alves Filho; +Cc: xenomai
Flavio de Castro Alves Filho wrote:
> Hello Gilles,
>
> First of all, really thank you for you revision. It was really helpful.
>
> And ... about the changes. I implemented the corrections as you
> suggested and it is still not working. It is blocking allways at the
> same place.
>
> I'm still working to find out a solution.
Ok. Do you know if the error happens around a multiplexed interrupt?
If that was the case, please try to get __ipipe_irq_mux_p to return
always 0, and modify Linux demuxer to call __ipipe_handle_irq instead of
handle_irq when CONFIG_IPIPE is on.
--
Gilles.
^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2010-01-13 10:05 UTC | newest]
Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-03 15:00 [Xenomai-help] Porting I-Pipe for new ARM board Wael Showair
2009-11-03 15:13 ` Gilles Chanteperdrix
2009-11-03 15:45 ` Didenko Sergey
2009-11-03 15:48 ` Gilles Chanteperdrix
2009-11-04 6:58 ` Wael Showair
2009-11-04 10:54 ` Gilles Chanteperdrix
2009-11-06 9:08 ` Wael Showair
2009-11-06 9:39 ` Sergey Didenko
2009-11-06 10:22 ` Gilles Chanteperdrix
2009-12-15 19:37 ` Олександр Лаврущенко
2009-12-15 20:34 ` Gilles Chanteperdrix
[not found] ` <20091215213210.19d5b6a5@domain.hid>
2009-12-16 1:15 ` Sergey Didenko
2009-12-31 12:52 ` Flavio de Castro Alves Filho
2009-12-31 15:41 ` Gilles Chanteperdrix
2010-01-04 22:14 ` Flavio Alves
2010-01-04 22:22 ` Gilles Chanteperdrix
2010-01-06 10:56 ` Flavio Alves
2010-01-06 11:01 ` Gilles Chanteperdrix
2010-01-06 11:38 ` Flavio de Castro Alves Filho
2010-01-06 14:01 ` Gilles Chanteperdrix
2010-01-06 19:16 ` Flavio de Castro Alves Filho
2010-01-06 19:23 ` Gilles Chanteperdrix
2010-01-08 14:11 ` Flavio de Castro Alves Filho
2010-01-08 14:35 ` Gilles Chanteperdrix
2010-01-08 14:58 ` Flavio de Castro Alves Filho
2010-01-08 15:36 ` Gilles Chanteperdrix
2010-01-08 17:43 ` Flavio de Castro Alves Filho
2010-01-08 18:02 ` Flavio de Castro Alves Filho
2010-01-08 18:08 ` Gilles Chanteperdrix
2010-01-08 19:27 ` Flavio de Castro Alves Filho
2010-01-08 19:31 ` Gilles Chanteperdrix
2010-01-08 19:42 ` Flavio de Castro Alves Filho
2010-01-08 19:45 ` Gilles Chanteperdrix
2010-01-08 21:54 ` Flavio de Castro Alves Filho
2010-01-08 22:26 ` Gilles Chanteperdrix
2010-01-13 8:50 ` Flavio de Castro Alves Filho
2010-01-13 10:05 ` Gilles Chanteperdrix
2010-01-08 19:32 ` Gilles Chanteperdrix
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.