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/[email protected]/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 (r...@debian-ws) (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


      
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to