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
