Hi team,
My customer needs to implement timer interrupt in uboot which is used to driver a LED periodically to monitor the progress of FTP downloading. We ported the codes from starterware, please see attachment. Current issue is that it can go to ISR periodically as designed but the progress can't run back to main progress.
And whether we already have the patch for such kind of user case?
Could someone help look at this issue?
/* * (C) Copyright 2003 * Texas Instruments <www.ti.com> * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Alex Zuepke <azu@sysgo.de> * * (C) Copyright 2002-2004 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> * * (C) Copyright 2004 * Philippe Robin, ARM Ltd. <philippe.robin@arm.com> * * See file CREDITS for list of people who contributed to this * project. * * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include <common.h> #include <asm/proc-armv/ptrace.h> #include <hw_intc.h> #include <soc_AM335x.h> #include <hw_types.h> #include <hw_dmtimer.h> #include <dmtimer.h> /****************************************************************************** ** INTERNAL MACRO DEFINITIONS ******************************************************************************/ #define REG_IDX_SHIFT (0x05) #define REG_BIT_MASK (0x1F) #define NUM_INTERRUPTS (128u) /****************************************************************************** ** INTERNAL MACRO DEFINITIONS *******************************************************************************/ #define TIMER_INITIAL_COUNT (0xFF000000u) #define TIMER_RLD_COUNT (0xFF000000u) //#define TIMER_RLD_COUNT (0xFFFF0000u) /**************** ************************************************************* ** STATIC VARIABLE DEFINITIONS ******************************************************************************/ void (*fnRAMVectors[NUM_INTERRUPTS])(void); static void IntDefaultHandler(void) { /* Go Back. Nothing to be done */ ; } DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_USE_IRQ int interrupt_init (void) { /* * setup up stacks if necessary */ #if 1 IRQ_STACK_START = gd->irq_sp - 4; IRQ_STACK_START_IN = gd->irq_sp + 8; FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; #else IRQ_STACK_START = 0x80f00000 - 4; IRQ_STACK_START_IN = 0x80f00000 + 8; FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ; #endif return arch_interrupt_init(); } int arch_interrupt_init (void) { #if 1 printf("IRQ__STACK_START:0x%x\n",IRQ_STACK_START); DMTimer2ModuleClkConfig(); /* Enable IRQ in CPSR */ IntMasterIRQEnable(); /* Register DMTimer2 interrupts on to AINTC */ DMTimerAintcConfigure(); /* Perform the necessary configurations for DMTimer */ DMTimerSetUp(); /* Enable the DMTimer interrupts */ DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Start the DMTimer */ DMTimerEnable(SOC_DMTIMER_2_REGS); //disable_interrupts(); // DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); while(0) { printf("arch_interrupt_init....\n"); } reset_timer_masked(); // DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Stop the DMTimer */ //DMTimerDisable(SOC_DMTIMER_2_REGS); while(0) { printfcctr(); } #endif return 0; } /* enable IRQ interrupts */ void enable_interrupts (void) { unsigned long temp; __asm__ __volatile__("mrs %0, cpsr\n" "bic %0, %0, #0x80\n" "msr cpsr_c, %0" : "=r" (temp) : : "memory"); } /* * disable IRQ/FIQ interrupts * returns true if interrupts had been enabled before we disabled them */ int disable_interrupts (void) { unsigned long old,temp; __asm__ __volatile__("mrs %0, cpsr\n" "orr %1, %0, #0xc0\n" "msr cpsr_c, %1" : "=r" (old), "=r" (temp) : : "memory"); return (old & 0x80) == 0; } #else int interrupt_init (void) { /* * setup up stacks if necessary */ IRQ_STACK_START_IN = gd->irq_sp + 8; return 0; } void enable_interrupts (void) { return; } int disable_interrupts (void) { return 0; } #endif void CPUirqe(void) { /* Enable IRQ in CPSR */ #if 1 asm(" mrs r0, CPSR\n\t" " bic r0, r0, #0x80\n\t" " msr CPSR_c, r0"); #else unsigned long temp; __asm__ __volatile__("mrs %0, cpsr\n" "bic %0, %0, #0x80\n" "msr cpsr_c, %0" : "=r" (temp) : : "memory"); #endif } void IntAINTCInit(void) { unsigned int intrNum; /* Reset the ARM interrupt controller */ HWREG(SOC_AINTC_REGS + INTC_SYSCONFIG) = INTC_SYSCONFIG_SOFTRESET; /* Wait for the reset to complete */ while((HWREG(SOC_AINTC_REGS + INTC_SYSSTATUS) & INTC_SYSSTATUS_RESETDONE) != INTC_SYSSTATUS_RESETDONE); /* Enable any interrupt generation by setting priority threshold */ HWREG(SOC_AINTC_REGS + INTC_THRESHOLD) = INTC_THRESHOLD_PRIORITYTHRESHOLD; /* Register the default handler for all interrupts */ for(intrNum = 0; intrNum < NUM_INTERRUPTS; intrNum++) { fnRAMVectors[intrNum] = IntDefaultHandler; } } void IntPrioritySet(unsigned int intrNum, unsigned int priority, unsigned int hostIntRoute) { HWREG(SOC_AINTC_REGS + INTC_ILR(intrNum)) = ((priority << INTC_ILR_PRIORITY_SHIFT) & INTC_ILR_PRIORITY) | hostIntRoute ; } void IntSystemEnable(unsigned int intrNum) { //asm(" dsb"); /* Disable the system interrupt in the corresponding MIR_CLEAR register */ HWREG(SOC_AINTC_REGS + INTC_MIR_CLEAR(intrNum >> REG_IDX_SHIFT)) = (0x01 << (intrNum & REG_BIT_MASK)); } void IntSystemDisable(unsigned int intrNum) { //__asm(" dsb"); /* Enable the system interrupt in the corresponding MIR_SET register */ HWREG(SOC_AINTC_REGS + INTC_MIR_SET(intrNum >> REG_IDX_SHIFT)) = (0x01 << (intrNum & REG_BIT_MASK)); } void IntControlDisable() { //__asm(" dsb"); /* Enable the system interrupt in the corresponding MIR_SET register */ HWREG(SOC_AINTC_REGS + INTC_CONTROL) = 0x01 ; } /** * \brief Registers an interrupt Handler in the interrupt vector table for * system interrupts. * * \param intrNum - Interrupt Number * \param fnHandler - Function pointer to the ISR * * Note: When the interrupt occurs for the sytem interrupt number indicated, * the control goes to the ISR given as the parameter. * * \return None. **/ void IntRegister(unsigned int intrNum, void (*fnHandler)(void)) { /* Assign ISR */ fnRAMVectors[intrNum] = fnHandler; } /** * \brief This API will stop the timer. * * \param baseAdd Base Address of the DMTimer Module Register. * * \return None. * **/ /* ** Setup the timer for one-shot and compare mode. */ void DMTimerSetUp(void) { /* Load the counter with the initial count value */ DMTimerCounterSet(SOC_DMTIMER_2_REGS, TIMER_INITIAL_COUNT); /* Load the load register with the reload count value */ DMTimerReloadSet(SOC_DMTIMER_2_REGS, TIMER_RLD_COUNT); /* Configure the DMTimer for Auto-reload and compare mode */ DMTimerModeConfigure(SOC_DMTIMER_2_REGS, DMTIMER_AUTORLD_NOCMP_ENABLE); } void bad_mode (void) { panic ("Resetting CPU ...\n"); reset_cpu (0); } void show_regs (struct pt_regs *regs) { unsigned long flags; const char *processor_modes[] = { "USER_26", "FIQ_26", "IRQ_26", "SVC_26", "UK4_26", "UK5_26", "UK6_26", "UK7_26", "UK8_26", "UK9_26", "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", "USER_32", "FIQ_32", "IRQ_32", "SVC_32", "UK4_32", "UK5_32", "UK6_32", "ABT_32", "UK8_32", "UK9_32", "UK10_32", "UND_32", "UK12_32", "UK13_32", "UK14_32", "SYS_32", }; flags = condition_codes (regs); printf ("pc : [<%08lx>] lr : [<%08lx>]\n" "sp : %08lx ip : %08lx fp : %08lx\n", instruction_pointer (regs), regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); printf ("Flags: %c%c%c%c", flags & CC_N_BIT ? 'N' : 'n', flags & CC_Z_BIT ? 'Z' : 'z', flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); printf (" IRQs %s FIQs %s Mode %s%s\n", interrupts_enabled (regs) ? "on" : "off", fast_interrupts_enabled (regs) ? "on" : "off", processor_modes[processor_mode (regs)], thumb_mode (regs) ? " (T)" : ""); } void do_undefined_instruction (struct pt_regs *pt_regs) { printf ("undefined instruction\n"); show_regs (pt_regs); bad_mode (); } void do_software_interrupt (struct pt_regs *pt_regs) { printf ("software interrupt\n"); show_regs (pt_regs); bad_mode (); } void do_prefetch_abort (struct pt_regs *pt_regs) { printf ("prefetch abort\n"); show_regs (pt_regs); bad_mode (); } void do_data_abort (struct pt_regs *pt_regs) { printf ("data abort\n"); show_regs (pt_regs); bad_mode (); } void do_not_used (struct pt_regs *pt_regs) { printf ("not used\n"); show_regs (pt_regs); bad_mode (); } void do_fiq (struct pt_regs *pt_regs) { printf ("fast interrupt request\n"); show_regs (pt_regs); bad_mode (); } //#ifndef CONFIG_USE_IRQ #if 0 ulong timestamp = 0; extern struct gptimer *timer_base; void kw_timer_interrupt(void) { unsigned int temp = 0; int ret = 0; //MV_REG_WRITE(0x20304, ~(0x00000100)); //ret = disable_interrupts(); DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Clear the status of the interrupt flags */ DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG); /* Stop the DMTimer */ DMTimerDisable(SOC_DMTIMER_2_REGS); printf("kw_timer_interrupt#####....:0x%x\n",readl(&timer_base->tcrr)); timestamp++; timer_server(timestamp); return ; } #endif void do_irq (struct pt_regs *pt_regs) { //puts ("interrupt request.....\n"); //show_regs (pt_regs); //bad_mode (); //disable_interrupts(); // DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG); #if 0 int temp = 0; __asm__ __volatile__("mov %0, sp\n" : "=r" (temp) : : "memory"); printf("\nInterrupt sp = 0x%x\n",temp); #endif kw_timer_interrupt(); //printf("do_irq end ..\n"); } //#endif
/* * (C) Copyright 2008 * Texas Instruments * * Richard Woodruff <r-woodruff2@ti.com> * Syed Moahmmed Khasim <khasim@ti.com> * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * Alex Zuepke <azu@sysgo.de> * * (C) Copyright 2002 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> * * See file CREDITS for list of people who contributed to this * project. * * 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., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include <common.h> #include <asm/io.h> #include <soc_AM335x.h> #include <hw_types.h> #include <hw_cm_per.h> #include <interrupt.h> #include <dmtimer.h> DECLARE_GLOBAL_DATA_PTR; static volatile unsigned int flagIsr = 0; struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE; /* * Nothing really to do with interrupts, just starts up a counter. */ #define TIMER_CLOCK (V_SCLK / (2 << CONFIG_SYS_PTV)) #define TIMER_OVERFLOW_VAL 0xffffffff #define TIMER_LOAD_VAL 0 ulong timestamp = 0; extern struct gptimer *timer_base; extern int mainCnt; void kw_timer_interrupt(void) { unsigned int temp = 0; int ret = 0; //MV_REG_WRITE(0x20304, ~(0x00000100)); //ret = disable_interrupts(); DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG); IntControlDisable(); #if 1 __asm__ __volatile__("mov %0, sp\n" : "=r" (temp) : : "memory"); printf("Interrupt sp = 0x%x,timestamp:%d\n",temp,timestamp++); #endif DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); // printf("\nmianCnt = %d\n",mainCnt); /* Clear the status of the interrupt flags */ // DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG); #if 1 /* Stop the DMTimer */ // IntSystemDisable(SYS_INT_TINT2); //IntControlDisable(); // printf("IntStatusClear:0x%x\n",readl(&timer_base->tistat)); // DMTimerDisable(SOC_DMTIMER_2_REGS); #endif #if 0 // printf("---:0x%x\n",readl(&timer_base->tcrr)); if( timestamp%2 == 0) { lightRunAlmLed(); } else { turnoffRunAlmLed(); } timestamp++; timer_server(timestamp); #endif //flush_dcache_all(); //invalidate_dcache_all(); //IntControlDisable(); /* Perform the necessary configurations for DMTimer */ //DMTimerSetUp(); /* Enable the DMTimer interrupts */ // DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Start the DMTimer */ //DMTimerEnable(SOC_DMTIMER_2_REGS); //disable_interrupts(); //DMTimerEnable(SOC_DMTIMER_2_REGS); //printf("kw_timer_interrupt++++++++++++++++++++++++++++:0x%x\n",readl(&timer_base->tcrr)); return ; } void printfcctr() { // char szArryay[2048] ={0}; int temp = 0; ulong ret = readl(&timer_base->tcrr); __asm__ __volatile__("mov %0, sp\n" : "=r" (temp) : : "memory"); // if (ret >0xff000000 && ret < 0xff000100 && doneirq !=1) printf("\n777While######sp:0x%x\n",temp); // else if(ret > 0xffffff00 && ret < 0xffffffff) // printf("CCTR*******....:0x%x\n",readl(&timer_base->tcrr)); } void printfcctr1() { // char szArryay[2048] ={0}; int temp = 0; ulong ret = readl(&timer_base->tcrr); __asm__ __volatile__("mov %0, sp\n" : "=r" (temp) : : "memory"); // if (ret >0xff000000 && ret < 0xff000100 && doneirq !=1) printf("\nWhile######sp:0x%x\n",temp); // else if(ret > 0xffffff00 && ret < 0xffffffff) // printf("CCTR*******....:0x%x\n",readl(&timer_base->tcrr)); } int timer_init(void) { #if 1 /* start the counter ticking up, reload value on overflow */ writel(TIMER_LOAD_VAL, &timer_base->tldr); /* enable timer */ writel((CONFIG_SYS_PTV << 2) | TCLR_PRE | TCLR_AR | TCLR_ST, &timer_base->tclr); /* reset time, capture current incrementer value time */ gd->lastinc = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ); gd->tbl = 0; /* start "advancing" time stamp from 0 */ #else //printf("timer_inittimer_init:0x%x\n",IRQ_STACK_START); DMTimer2ModuleClkConfig(); /* Enable IRQ in CPSR */ IntMasterIRQEnable(); /* Register DMTimer2 interrupts on to AINTC */ DMTimerAintcConfigure(); /* Perform the necessary configurations for DMTimer */ DMTimerSetUp(); /* Enable the DMTimer interrupts */ DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Start the DMTimer */ DMTimerEnable(SOC_DMTIMER_2_REGS); while(0) { printf("timer_init.....****..\n"); } reset_timer_masked(); #endif return 0; } void EnableTimer2Interrupt(void) { writel(0x7, &timer_base->tisr); writel(0x7, &timer_base->twer); } #if 1 void DMTimer2ModuleClkConfig(void) { HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) = CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP; while((HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) & CM_PER_L3S_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3S_CLKSTCTRL_CLKTRCTRL_SW_WKUP); HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) = CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP; while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) & CM_PER_L3_CLKSTCTRL_CLKTRCTRL) != CM_PER_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP); HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) = CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE; while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_INSTR_CLKCTRL) & CM_PER_L3_INSTR_CLKCTRL_MODULEMODE) != CM_PER_L3_INSTR_CLKCTRL_MODULEMODE_ENABLE); HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) = CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE; while((HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKCTRL) & CM_PER_L3_CLKCTRL_MODULEMODE) != CM_PER_L3_CLKCTRL_MODULEMODE_ENABLE); HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) = CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP; while((HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) & CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL) != CM_PER_OCPWP_L3_CLKSTCTRL_CLKTRCTRL_SW_WKUP); HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) = CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP; while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) & CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL) != CM_PER_L4LS_CLKSTCTRL_CLKTRCTRL_SW_WKUP); HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) = CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE; while((HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKCTRL) & CM_PER_L4LS_CLKCTRL_MODULEMODE) != CM_PER_L4LS_CLKCTRL_MODULEMODE_ENABLE); /* Select the clock source for the Timer2 instance. */ HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) &= ~(CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL); HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) |= CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL_CLK_M_OSC; while((HWREG(SOC_CM_DPLL_REGS + CM_DPLL_CLKSEL_TIMER2_CLK) & CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL) != CM_DPLL_CLKSEL_TIMER2_CLK_CLKSEL_CLK_M_OSC); HWREG(SOC_CM_PER_REGS + CM_PER_TIMER2_CLKCTRL) |= CM_PER_TIMER2_CLKCTRL_MODULEMODE_ENABLE; while((HWREG(SOC_CM_PER_REGS + CM_PER_TIMER2_CLKCTRL) & CM_PER_TIMER2_CLKCTRL_MODULEMODE) != CM_PER_TIMER2_CLKCTRL_MODULEMODE_ENABLE); while((HWREG(SOC_CM_PER_REGS + CM_PER_TIMER2_CLKCTRL) & CM_PER_TIMER2_CLKCTRL_IDLEST) != CM_PER_TIMER2_CLKCTRL_IDLEST_FUNC); while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3S_CLKSTCTRL) & CM_PER_L3S_CLKSTCTRL_CLKACTIVITY_L3S_GCLK)); while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L3_CLKSTCTRL) & CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK)); while(!(HWREG(SOC_CM_PER_REGS + CM_PER_OCPWP_L3_CLKSTCTRL) & (CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L3_GCLK | CM_PER_OCPWP_L3_CLKSTCTRL_CLKACTIVITY_OCPWP_L4_GCLK))); while(!(HWREG(SOC_CM_PER_REGS + CM_PER_L4LS_CLKSTCTRL) & (CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_L4LS_GCLK | CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_TIMER2_GCLK))); } void IntMasterIRQEnable(void) { /* Enable IRQ in CPSR.*/ CPUirqe(); } /* ** DMTimer interrupt service routine. This will send a character to serial ** console. */ void DMTimerIsr(void) { /* Disable the DMTimer interrupts */ DMTimerIntDisable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); /* Clear the status of the interrupt flags */ DMTimerIntStatusClear(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_IT_FLAG); flagIsr = 1; /* Enable the DMTimer interrupts */ DMTimerIntEnable(SOC_DMTIMER_2_REGS, DMTIMER_INT_OVF_EN_FLAG); } /** Do the necessary DMTimer configurations on to AINTC. */ void DMTimerAintcConfigure(void) { /* Initialize the ARM interrupt control */ IntAINTCInit(); /* Registering DMTimerIsr */ //IntRegister(SYS_INT_TINT2, DMTimerIsr); /* Set the priority */ IntPrioritySet(SYS_INT_TINT2, 0, AINTC_HOSTINT_ROUTE_IRQ); /* Enable the system interrupt */ IntSystemEnable(SYS_INT_TINT2); } #endif /* * timer without interrupts */ ulong get_timer(ulong base) { return get_timer_masked() - base; } /* delay x useconds */ void __udelay(unsigned long usec) { long tmo = usec * (TIMER_CLOCK / 1000) / 1000; unsigned long now, last = readl(&timer_base->tcrr); while (tmo > 0) { now = readl(&timer_base->tcrr); if (last > now) /* count up timer overflow */ tmo -= TIMER_OVERFLOW_VAL - last + now + 1; else tmo -= now - last; last = now; } } extern ulong timestamp; void reset_timer_masked (void) { /* reset time */ //printf("tcrr:0x%x\n",readl(&timer_base->tcrr)); gd->lastinc = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ); /* capure current decrementer value time */ gd->tbl = 0; } ulong get_timer_masked(void) { /* current tick value */ ulong now = readl(&timer_base->tcrr) / (TIMER_CLOCK / CONFIG_SYS_HZ); //printf("tcrr###### :0x%x\n",readl(&timer_base->tcrr)); // printf("#######mask time = 0x%x,gd->lastinc= 0x%x\n",now,gd->lastinc); if (now >= gd->lastinc) /* normal mode (non roll) */ /* move stamp fordward with absoulte diff ticks */ { // printf("++++++\n"); gd->tbl += (now - gd->lastinc); } else /* we have rollover of incrementer */ { // printf("-----------\n"); gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLOCK / CONFIG_SYS_HZ)) - gd->lastinc) + now; } gd->lastinc = now; //printf("gd->tbl:%d\n",gd->tbl); return gd->tbl; } /* * This function is derived from PowerPC code (read timebase as long long). * On ARM it just returns the timer value. */ unsigned long long get_ticks(void) { return get_timer(0); } /* * This function is derived from PowerPC code (timebase clock frequency). * On ARM it returns the number of timer ticks per second. */ ulong get_tbclk(void) { return CONFIG_SYS_HZ; }