This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Reading RTC time in u-boot

Hi,

I am writing a test code for RTC Test in u-boot where i am reading the RTC time as below.

        tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
        tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
        tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
        tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
        tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
        tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);

                printf( "Get DATE: %04d-%02d-%02d TIME: %02d:%02d:%02d\n",
                tm->tm_year, tm->tm_mon, tm->tm_mday,
                tm->tm_hour, tm->tm_min, tm->tm_sec);
       

        bcd2tm(tm);

                printf( "Get DATE: %4d-%02d-%02d TIME: %2d:%02d:%02d\n",
                tm->tm_year, tm->tm_mon, tm->tm_mday,
                tm->tm_hour, tm->tm_min, tm->tm_sec);
     

But the return RTC time is always coming as 100-00-00 00:00:00.

It is not getting increase.

I am using the ti8148EVM to run this code.

what i am doing wrong here and how can i get the updated RTC time.

  • hi,

    here i am posting the full code, if anybody can help me to know what i am doing wrong.

    #define TI8148_RTC_BASE        0x480C0000//            0xfffb4800  //0x480C1000

    #define OMAP_RTC_SECONDS_REG        0x00
    #define OMAP_RTC_MINUTES_REG        0x04
    #define OMAP_RTC_HOURS_REG        0x08
    #define OMAP_RTC_DAYS_REG        0x0C
    #define OMAP_RTC_MONTHS_REG        0x10
    #define OMAP_RTC_YEARS_REG        0x14
    #define OMAP_RTC_WEEKS_REG        0x18
    #define OMAP_RTC_STATUS_REG             0x44
    #define OMAP_RTC_STATUS_BUSY            (1<<0)


    #define FEBRUARY        2
    #define    STARTOFTIME        1970
    #define SECDAY            86400L
    #define SECYR            (SECDAY * 365)
    #define    leapyear(year)        ((year) % 4 == 0)
    #define    days_in_year(a)        (leapyear(a) ? 366 : 365)
    #define    days_in_month(a)    (month_days[(a) - 1])

    static int month_days[12] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };


    static const unsigned char rtc_days_in_month[] = {
            31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };

    static const unsigned short rtc_ydays[2][13] = {
            /* Normal years */
            { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
            /* Leap years */
            { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
    };

    #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)

    int is_leap_year(unsigned int year)
    {
            return (!(year % 4) && (year % 100)) || !(year % 400);
    }


    /*
     * The number of days in the month.
     */
    int rtc_month_days(unsigned int month, unsigned int year)
    {
            return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
    }



    int rtc_valid_tm(struct rtc_time *tm)
    {
            if (tm->tm_year < 70
                    || ((unsigned)tm->tm_mon) >= 12
                    || tm->tm_mday < 1
                    || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
                    || ((unsigned)tm->tm_hour) >= 24
                    || ((unsigned)tm->tm_min) >= 60
                    || ((unsigned)tm->tm_sec) >= 60)
                    return -1;
            
            return 0;
    }   

    static int tm2bcd(struct rtc_time *tm)
    {
        if (rtc_valid_tm(tm) != 0)
            return -1;

        tm->tm_sec = bin2bcd(tm->tm_sec);
        tm->tm_min = bin2bcd(tm->tm_min);
        tm->tm_hour = bin2bcd(tm->tm_hour);
        tm->tm_mday = bin2bcd(tm->tm_mday);

        tm->tm_mon = bin2bcd(tm->tm_mon + 1);

        /* epoch == 1900 */
        if (tm->tm_year < 100 || tm->tm_year > 199)
            return -1;//EINVAL;
        tm->tm_year = bin2bcd(tm->tm_year - 100);

        return 0;
    }

    static void bcd2tm(struct rtc_time *tm)
    {
        printf("VIMAL -- in bcd2tm \n");

        tm->tm_sec = bcd2bin(tm->tm_sec);
        tm->tm_min = bcd2bin(tm->tm_min);
        tm->tm_hour = bcd2bin(tm->tm_hour);
        tm->tm_mday = bcd2bin(tm->tm_mday);
        tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
        /* epoch == 1900 */
        tm->tm_year = bcd2bin(tm->tm_year) + 100;
    }

    #define rtc_read(addr)        __raw_readb( TI8148_RTC_BASE + (addr))
    #define rtc_write(val, addr)    __raw_writeb(val, TI8148_RTC_BASE + (addr))


    /* we rely on the rtc framework to handle locking (rtc->ops_lock),
     * so the only other requirement is that register accesses which
     * require BUSY to be clear are made with IRQs locally disabled
     */
    static void rtc_wait_not_busy(void)
    {
            int     count = 0;
            u8      status;

            /* BUSY may stay active for 1/32768 second (~30 usec) */
            for (count = 0; count < 50; count++) {
                    status = rtc_read(OMAP_RTC_STATUS_REG);
                    if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
                            break;
                    udelay(1);
            }
            /* now we have ~15 usec to read/write various registers */
    }


    int omap_rtc_read_time(struct rtc_time *tm)
    {
        /* we don't report wday/yday/isdst ... */
        local_irq_disable();
        rtc_wait_not_busy();

        tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
        tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
        tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
        tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
        tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
        tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);

                    printf( "Get DATE: %04d-%02d-%02d TIME: %02d:%02d:%02d\n",
                    tm->tm_year, tm->tm_mon, tm->tm_mday,
                    tm->tm_hour, tm->tm_min, tm->tm_sec);
        local_irq_enable();

        bcd2tm(tm);

                printf( "Get DATE: %4d-%02d-%02d TIME: %2d:%02d:%02d\n",
                    tm->tm_year, tm->tm_mon, tm->tm_mday,
                    tm->tm_hour, tm->tm_min, tm->tm_sec);
        return 0;
    }


    static int omap_rtc_set_time(struct rtc_time *tm)
    {
        if (tm2bcd(tm) < 0)
            return -1;

        rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
        rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
        rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
        rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
        rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
        rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);


        return 0;
    }


    void rtc_reset (void)
    {
        return;    // nothing to do
    }


    int post_log (char *format, ...)
    {
        va_list args;
        uint i;
        char printbuffer[CONFIG_SYS_PBSIZE];

        va_start (args, format);

        /* For this to work, printbuffer must be larger than
         * anything we ever want to print.
         */
        i = vsprintf (printbuffer, format, args);
        va_end (args);

    #ifdef CONFIG_LOGBUFFER
        /* Send to the logbuffer */
        logbuff_log (printbuffer);
    #else
        /* Send to the stdout file */
        puts (printbuffer);
    #endif

        return 0;
    }

    static int rtc_post_skip (ulong * diff)
    {
        struct rtc_time tm1;
        struct rtc_time tm2;
        ulong start1;
        ulong start2;

        
        omap_rtc_read_time(&tm1);
        start1 = get_timer (0);

        while (1) {
            
            omap_rtc_read_time(&tm2);
            start2 = get_timer (0);
            if (tm1.tm_sec != tm2.tm_sec)
                break;
            if (start2 - start1 > 1500)
                break;
        }

        if (tm1.tm_sec != tm2.tm_sec) {
            *diff = start2 - start1;

            return 0;
        } else {
            return -1;
        }
    }

    static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
    {
        time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
                           tm->tm_min, tm->tm_sec) + sec;
        struct rtc_time ntm;

        to_tm (t, &ntm);

        omap_rtc_set_time(&ntm);
    }

    static int rtc_post_test ()
    {
        ulong diff;
        unsigned int i;
        struct rtc_time svtm;
        static unsigned int daysnl[] =
                { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        static unsigned int daysl[] =
                { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        unsigned int ynl = 1999;
        unsigned int yl = 2000;
        unsigned int skipped = 0;
        int reliable;

        /* Time reliability */
        reliable = omap_rtc_read_time(&svtm);
        
        /* Time uniformity */
        if (rtc_post_skip (&diff) != 0) {
            post_log ("Timeout while waiting for a new second !\n");

            return -1;
        }

        
        for (i = 0; i < 5; i++) {
            if (rtc_post_skip (&diff) != 0) {
                post_log ("Timeout while waiting for a new second !\n");

                return -1;
            }

            if (diff < 950 || diff > 1050) {
                post_log ("Invalid second duration !\n");

                return -1;
            }
        }

        
        /* Passing month boundaries */

        if (rtc_post_skip (&diff) != 0) {
            post_log ("Timeout while waiting for a new second !\n");

            return -1;
        }

        omap_rtc_read_time(&svtm);
        
        for (i = 0; i < 12; i++) {
            time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
            struct rtc_time tm;

            to_tm (t, &tm);
            omap_rtc_set_time(&tm);

            skipped++;
            if (rtc_post_skip (&diff) != 0) {
                rtc_post_restore (&svtm, skipped);
                post_log ("Timeout while waiting for a new second !\n");

                return -1;
            }

            omap_rtc_read_time(&tm);
            if (tm.tm_mon == i + 1) {
                rtc_post_restore (&svtm, skipped);
                post_log ("Month %d boundary is not passed !\n", i + 1);

                return -1;
            }
        }

        for (i = 0; i < 12; i++) {
            time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
            struct rtc_time tm;

            to_tm (t, &tm);
        
            omap_rtc_set_time(&tm);

            skipped++;
            if (rtc_post_skip (&diff) != 0) {
                rtc_post_restore (&svtm, skipped);
                post_log ("Timeout while waiting for a new second !\n");

                return -1;
            }

            omap_rtc_read_time(&tm);
            if (tm.tm_mon == i + 1) {
                rtc_post_restore (&svtm, skipped);
                post_log ("Month %d boundary is not passed !\n", i + 1);

                return -1;
            }
        }
        rtc_post_restore (&svtm, skipped);

        /* If come here, then RTC operates correcty, check the correctness
         * of the time it reports.
         */

        
        if (reliable < 0) {
            post_log ("RTC Time is not reliable! Power fault? \n");

            return -1;
        }

        return 0;
    }

    thanks.

  • Vimal,

    Please refer to the RTC initialization/configuration in linux kernel. You should reuse it for the u-boot:

    ti-ezsdk_dm814x-evm_5_05_02_00/board-support/linux-2.6.37-psp04.04.00.01/arch/arm/mach-omap2/devices.c

    ti81xx_rtc_init(void)

    Regards,
    Pavel

  • Hi Pavel,

    I have used the initialization too but still it is not giving the output.

    kindly suggest me what else can be done to achieve it.

    thanks.

  • Vimal,

    In EZSDK u-boot (u-boot-2010.06-psp04.04.00.01) the RTC is disabled by default. This is what I have when reading the Seconds Register (SECONDS_REG) with the u-boot md (memory display) command:

    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000000    ....
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000000    ....
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000000    ....
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000000    ....
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000000    ....

    I have modified the evm.c file as below:

    ti-ezsdk_dm814x-evm_5_05_02_00/board-support/u-boot-2010.06-psp04.04.00.01/board/ti/ti8148/evm.c

    #define PLL_BASE_ADDRESS         0x481C5000
    #define TIMER_CLKSRC          (PLL_BASE_ADDRESS + 0x02E0)
    unsigned int TIMER_NUM = 3;

    +#define TI81XX_RTC_BASE 0x480C0000

    +#define SECONDS_REG     0x00
    +#define MINUTES_REG     0x04
    +#define HOURS_REG       0x08
    +#define DAYS_REG        0x0C
    +#define MONTHS_REG      0x10
    +#define YEARS_REG       0x14
    +#define WEEK_REG        0x18

    +#define RTC_CTRL_REG    0x40
    +#define RTC_STATUS_REG  0x44
    +#define OSC_REG        0x54

    +#define KICK0_REG    0x6c
    +#define KICK1_REG    0x70

    +#define KICK0_REG_VAL    0x83e70b13
    +#define KICK1_REG_VAL    0x95a4f1e0
    +#define RESET_VAL    BIT(5)

    #ifdef CONFIG_TI814X_CONFIG_DDR

    /*
     * Basic board specific setup
     */
    int board_init(void)
    {
        u32 regVal;

    .............

    #endif

        ti814x_rtc_init();    
        
        return 0;
    }

    int ti814x_rtc_init(void)
    {
        u32 base;
        
        base = TI81XX_RTC_BASE;    
        
        /* Unlock the rtc's registers*/
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        /* Reset the RTC */
        __raw_writel(RESET_VAL, base + OSC_REG);

        /*
         * After setting the SW_RESET bit, RTC registers must not be accessed
         * for 3 32kHz clock cycles (roughly 2200 OCP cycles).*/
        
       udelay(100);

        /*
         * Unlock the rtc's registers again as the registers would have been
         * locked due to reset*/
        
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        
         /* Initialize Calender to day 1, 12:00:00 */
        __raw_writel(0x01, base + SECONDS_REG); //SECONDS_REG = 0x01;                    
        __raw_writel(0x30, base + MINUTES_REG); //MINUTES_REG = 0x30;                    
        __raw_writel(0x01, base + HOURS_REG); //HOURS_REG = 0x01;
        __raw_writel(0x08, base + DAYS_REG); //DAYS_REG = 0x08;
        __raw_writel(0x07, base + MONTHS_REG); //MONTHS_REG = 0x07;
        __raw_writel(0x84, base + YEARS_REG); //YEARS_REG  = 0x84;
        __raw_writel(0x01, base + WEEK_REG); //WEEK_REG  = 0x01;
        
        /* Start RTC */
        __raw_writel(0x01, base + RTC_CTRL_REG); //RTC_CTRL_REG = 0x01;
        
        return 0;

    }

    With this modified u-boot, when reading the Seconds Register (SECONDS_REG) with the u-boot md (memory display) command:

    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000021    !...
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000029    )...
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000034    4...
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000039    9...
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000044    D...
    TI8148_EVM#md 0x480C0000 1
    480c0000: 00000052    R...

    The values (seconds) increase on every read (21,29,34,39,44,52).

    Regards

  • Hi Pavel,

    Thanks for your answer. i am able to get it.

    Regards,

    Vimal

  • Hi Pavel,

    I am able to pass first two test but it is failing in the third test where it is giving me the following print.

    "Month 6 boundary is not passed"

    it is passing Time reliability and Time uniformity test but failing in Passing month boundaries test with above print.

    kindly help me out to overcome it.

    Thanks,

    Vimal

  • Vimal,

    Vimal Gupta said:
    I am able to pass first two test but it is failing in the third test

    Vimal Gupta said:
    it is passing Time reliability and Time uniformity test but failing in Passing month boundaries test

    I am not familiar with your tests. Can you provide some info about your tests?

    Best regards,
    Pavel

  • Hi pavel,

    Please find the attached code of rtc test.

    #include <common.h>
    #include <command.h>
    #include <bcd.h>
    #include <rtc.h>
    #include <asm/io.h>
    
    #define TI8148_RTC_BASE		0x480C0000//			0xfffb4800  //0x480C1000
    
    #define OMAP_RTC_SECONDS_REG		0x00
    #define OMAP_RTC_MINUTES_REG		0x04
    #define OMAP_RTC_HOURS_REG		0x08
    #define OMAP_RTC_DAYS_REG		0x0C
    #define OMAP_RTC_MONTHS_REG		0x10
    #define OMAP_RTC_YEARS_REG		0x14
    #define OMAP_RTC_WEEKS_REG		0x18
    #define OMAP_RTC_STATUS_REG             0x44
    #define OMAP_RTC_STATUS_BUSY            (1<<0)
    
    
    #define FEBRUARY		2
    #define	STARTOFTIME		1970
    #define SECDAY			86400L
    #define SECYR			(SECDAY * 365)
    #define	leapyear(year)		((year) % 4 == 0)
    #define	days_in_year(a)		(leapyear(a) ? 366 : 365)
    #define	days_in_month(a)	(month_days[(a) - 1])
    
    
    #define BIT(nr)                 (1UL << (nr))
    
    #define KICK0_REG       0x6c
    #define KICK1_REG       0x70
    #define OSC_REG         0x54
    
    #define KICK0_REG_VAL   0x83e70b13
    #define KICK1_REG_VAL   0x95a4f1e0
    #define RESET_VAL       BIT(5)
    
    
    
    static int month_days[12] = {
    	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    
    /*
     * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
     */
    void GregorianDay(struct rtc_time * tm)
    {
    	int leapsToDate;
    	int lastYear;
    	int day;
    	int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
    
    	lastYear=tm->tm_year-1;
    
    	/*
    	 * Number of leap corrections to apply up to end of last year
    	 */
    	leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
    
    	/*
    	 * This year is a leap year if it is divisible by 4 except when it is
    	 * divisible by 100 unless it is divisible by 400
    	 *
    	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
    	 */
    	if((tm->tm_year%4==0) &&
    	   ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
    	   (tm->tm_mon>2)) {
    		/*
    		 * We are past Feb. 29 in a leap year
    		 */
    		day=1;
    	} else {
    		day=0;
    	}
    
    	day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
    
    	tm->tm_wday=day%7;
    }
    
    void to_tm(int tim, struct rtc_time * tm)
    {
    	register int    i;
    	register long   hms, day;
    
    	day = tim / SECDAY;
    	hms = tim % SECDAY;
    
    	/* Hours, minutes, seconds are easy */
    	tm->tm_hour = hms / 3600;
    	tm->tm_min = (hms % 3600) / 60;
    	tm->tm_sec = (hms % 3600) % 60;
    
    	/* Number of years in days */
    	for (i = STARTOFTIME; day >= days_in_year(i); i++) {
    		day -= days_in_year(i);
    	}
    	tm->tm_year = i;
    
    	/* Number of months in days left */
    	if (leapyear(tm->tm_year)) {
    		days_in_month(FEBRUARY) = 29;
    	}
    	for (i = 1; day >= days_in_month(i); i++) {
    		day -= days_in_month(i);
    	}
    	days_in_month(FEBRUARY) = 28;
    	tm->tm_mon = i;
    
    	/* Days are what is left over (+1) from all that. */
    	tm->tm_mday = day + 1;
    
    	/*
    	 * Determine the day of week
    	 */
    	GregorianDay(tm);
    }
    
    /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
     * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
     * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
     *
     * [For the Julian calendar (which was used in Russia before 1917,
     * Britain & colonies before 1752, anywhere else before 1582,
     * and is still in use by some communities) leave out the
     * -year/100+year/400 terms, and add 10.]
     *
     * This algorithm was first published by Gauss (I think).
     *
     * WARNING: this function will overflow on 2106-02-07 06:28:16 on
     * machines were long is 32-bit! (However, as time_t is signed, we
     * will already get problems at other places on 2038-01-19 03:14:08)
     */
    unsigned long
    mktime (unsigned int year, unsigned int mon,
    	unsigned int day, unsigned int hour,
    	unsigned int min, unsigned int sec)
    {
    	if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
    		mon += 12;		/* Puts Feb last since it has leap day */
    		year -= 1;
    	}
    
    	return (((
    		(unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
    			year*365 - 719499
    	    )*24 + hour /* now have hours */
    	  )*60 + min /* now have minutes */
    	)*60 + sec; /* finally seconds */
    }
    
    
    static const unsigned char rtc_days_in_month[] = {
            31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    
    static const unsigned short rtc_ydays[2][13] = {
            /* Normal years */
            { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
            /* Leap years */
            { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
    };
    
    #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
    
    int is_leap_year(unsigned int year)
    {
            return (!(year % 4) && (year % 100)) || !(year % 400);
    }
    
    
    /*
     * The number of days in the month.
     */
    int rtc_month_days(unsigned int month, unsigned int year)
    {
            return rtc_days_in_month[month] + (is_leap_year(year) && month == 1);
    }
    
    
    
    int rtc_valid_tm(struct rtc_time *tm)
    {
    	if (tm->tm_year < 70
                    || ((unsigned)tm->tm_mon) >= 12
                    || tm->tm_mday < 1
                    || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900)
                    || ((unsigned)tm->tm_hour) >= 24
                    || ((unsigned)tm->tm_min) >= 60
                    || ((unsigned)tm->tm_sec) >= 60)
                    return -1;
            
            return 0;
    }   
    
    static int tm2bcd(struct rtc_time *tm)
    {
    	if (rtc_valid_tm(tm) != 0)
    	{
    		return -1;
    	}
    	tm->tm_sec = bin2bcd(tm->tm_sec);
    	tm->tm_min = bin2bcd(tm->tm_min);
    	tm->tm_hour = bin2bcd(tm->tm_hour);
    	tm->tm_mday = bin2bcd(tm->tm_mday);
    
    	tm->tm_mon = bin2bcd(tm->tm_mon + 1);
    
    	/* epoch == 1900 */
    	if (tm->tm_year < 100 || tm->tm_year > 199)
    		return -1;//EINVAL;
    	tm->tm_year = bin2bcd(tm->tm_year - 100);
    
    	return 0;
    }
    
    static void bcd2tm(struct rtc_time *tm)
    {
    //	printf("VIMAL -- in bcd2tm \n");
    
    	tm->tm_sec = bcd2bin(tm->tm_sec);
    	tm->tm_min = bcd2bin(tm->tm_min);
    	tm->tm_hour = bcd2bin(tm->tm_hour);
    	tm->tm_mday = bcd2bin(tm->tm_mday);
    	tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
    	/* epoch == 1900 */
    	tm->tm_year = bcd2bin(tm->tm_year) + 100;
    }
    
    #define rtc_read(addr)		__raw_readb( TI8148_RTC_BASE + (addr))
    #define rtc_write(val, addr)	__raw_writeb(val, TI8148_RTC_BASE + (addr))
    
    
    /* we rely on the rtc framework to handle locking (rtc->ops_lock),
     * so the only other requirement is that register accesses which
     * require BUSY to be clear are made with IRQs locally disabled
     */
    static void rtc_wait_not_busy(void)
    {
            int     count = 0;
            u8      status;
    
            /* BUSY may stay active for 1/32768 second (~30 usec) */
            for (count = 0; count < 50; count++) {
                    status = rtc_read(OMAP_RTC_STATUS_REG);
                    if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
                            break;
                    udelay(1);
            }
            /* now we have ~15 usec to read/write various registers */
    }
    
    
    int omap_rtc_read_time(struct rtc_time *tm)
    {
    	/* we don't report wday/yday/isdst ... */
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
    	tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
    	tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
    	tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
    	tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
    	tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
    
     	local_irq_enable();
    
    	bcd2tm(tm);
    
    	return 0;
    }
    
    
    static int omap_rtc_set_time(struct rtc_time *tm)
    {
    	if (tm2bcd(tm) < 0)
    	{
    		printf("\n Failed in omap_rtc_set_time \n");
    		return -1;
    	}
    	local_irq_disable();
    	rtc_wait_not_busy();
    
    	rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
    	rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
    	rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
    	rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
    	rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
    	rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
    
    	local_irq_enable();
    
    	return 0;
    }
    
    
    void rtc_reset (void)
    {
    	return;	// nothing to do
    }
    
    
    int post_log (char *format, ...)
    {
    	va_list args;
    	uint i;
    	char printbuffer[CONFIG_SYS_PBSIZE];
    
    	va_start (args, format);
    
    	/* For this to work, printbuffer must be larger than
    	 * anything we ever want to print.
    	 */
    	i = vsprintf (printbuffer, format, args);
    	va_end (args);
    
    #ifdef CONFIG_LOGBUFFER
    	/* Send to the logbuffer */
    	logbuff_log (printbuffer);
    #else
    	/* Send to the stdout file */
    	puts (printbuffer);
    #endif
    
    	return 0;
    }
    
    static int rtc_post_skip (ulong * diff)
    {
    	struct rtc_time tm1;
    	struct rtc_time tm2;
    	ulong start1;
    	ulong start2;
    
    	omap_rtc_read_time(&tm1);
    	start1 = get_timer (0);
    
    	while (1) {
    		
    		omap_rtc_read_time(&tm2);
    		start2 = get_timer (0);
    		if (tm1.tm_sec != tm2.tm_sec)
    			break;
    		if (start2 - start1 > 1500)
    			break;
    	}
    
    	if (tm1.tm_sec != tm2.tm_sec) {
    		*diff = start2 - start1;
    
    		return 0;
    	} else {
    		return -1;
    	}
    }
    
    static void rtc_post_restore (struct rtc_time *tm, unsigned int sec)
    {
    	time_t t = mktime (tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
    					   tm->tm_min, tm->tm_sec) + sec;
    	struct rtc_time ntm;
    
    	to_tm (t, &ntm);
    
    	omap_rtc_set_time(&ntm);
    }
    
    static int rtc_post_test (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    {
    	ulong diff;
    	unsigned int i;
    	struct rtc_time svtm;
    	static unsigned int daysnl[] =
    			{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    	static unsigned int daysl[] =
    			{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    	unsigned int ynl = 1999;
    	unsigned int yl = 2000;
    	unsigned int skipped = 0;
    	int reliable;
    
    	/* Time reliability */
    	reliable = omap_rtc_read_time(&svtm);//rtc_get (&svtm);
    
    	/* Time uniformity */
    	if (rtc_post_skip (&diff) != 0) {
    		post_log ("Timeout while waiting for a new second !\n");
    
    		return -1;
    	}
    
    	for (i = 0; i < 5; i++) {
    		if (rtc_post_skip (&diff) != 0) {
    			post_log ("Timeout while waiting for a new second !\n");
    
    			return -1;
    		}
    
    		if (diff < 950 || diff > 1050) {
    			post_log ("Invalid second duration !\n");
    
    			return -1;
    		}
    	}
    
    	/* Passing month boundaries */
    
    	if (rtc_post_skip (&diff) != 0) {
    		post_log ("Timeout while waiting for a new second !\n");
    
    		return -1;
    	}
    
    	omap_rtc_read_time(&svtm);
    	printf("\n RTC TEST 3......... \n");
    	for (i = 0; i < 12; i++) {
    		
    		time_t t = mktime (ynl, i + 1, daysnl[i], 23, 59, 59);
    		struct rtc_time tm;
    
    		to_tm (t, &tm);
    			
    		omap_rtc_set_time(&tm);
    
    		skipped++;
    		if (rtc_post_skip (&diff) != 0) {
    			rtc_post_restore (&svtm, skipped);
    			post_log ("Timeout while waiting for a new second !\n");
    
    			return -1;
    		}
    
    		
    		omap_rtc_read_time(&tm);
    		
    		if (tm.tm_mon == i + 1) {
    			rtc_post_restore (&svtm, skipped);
    			post_log ("Month %d boundary is not passed !\n", i + 1);
    
    			return -1;
    		}
    	}
    
    	 printf("\n RTC TEST 4......... \n");
    	for (i = 0; i < 12; i++) {
    		time_t t = mktime (yl, i + 1, daysl[i], 23, 59, 59);
    		struct rtc_time tm;
    
    		to_tm (t, &tm);
    		
    		omap_rtc_set_time(&tm);
    
    		skipped++;
    		if (rtc_post_skip (&diff) != 0) {
    			rtc_post_restore (&svtm, skipped);
    			post_log ("Timeout while waiting for a new second !\n");
    
    			return -1;
    		}
    
    		
    		omap_rtc_read_time(&tm);
    		if (tm.tm_mon == i + 1) {
    			rtc_post_restore (&svtm, skipped);
    			post_log ("Month %d boundary is not passed !\n", i + 1);
    
    			return -1;
    		}
    	}
    	rtc_post_restore (&svtm, skipped);
    
    	/* If come here, then RTC operates correcty, check the correctness
    	 * of the time it reports.
    	 */
    
    	 printf("\n RTC TEST OK......... \n");
    
    
    	if (reliable < 0) {
    		post_log ("RTC Time is not reliable! Power fault? \n");
    
    		return -1;
    	}
    
    	return 0;
    }
    
    
    U_BOOT_CMD(UU_RTC, 3, 0,rtc_post_test,"RTC POST TEST",0);
    
    
    
    
    
    

    I have done the initialization as suggested by you in the board file with following code.

    int ti814x_rtc_init(void)
    {
        u32 base;
        
        base = TI81XX_RTC_BASE;    
        
        /* Unlock the rtc's registers*/
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        /* Reset the RTC */
        __raw_writel(RESET_VAL, base + OSC_REG);

        /*
         * After setting the SW_RESET bit, RTC registers must not be accessed
         * for 3 32kHz clock cycles (roughly 2200 OCP cycles).*/
        
       udelay(100);

        /*
         * Unlock the rtc's registers again as the registers would have been
         * locked due to reset*/
        
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        
         /* Initialize Calender to day 1, 12:00:00 */
        __raw_writel(0x01, base + SECONDS_REG); //SECONDS_REG = 0x01;                    
        __raw_writel(0x30, base + MINUTES_REG); //MINUTES_REG = 0x30;                    
        __raw_writel(0x01, base + HOURS_REG); //HOURS_REG = 0x01;
        __raw_writel(0x08, base + DAYS_REG); //DAYS_REG = 0x08;
        __raw_writel(0x07, base + MONTHS_REG); //MONTHS_REG = 0x07;
        __raw_writel(0x84, base + YEARS_REG); //YEARS_REG  = 0x84;
        __raw_writel(0x01, base + WEEK_REG); //WEEK_REG  = 0x01;
        
        /* Start RTC */
        __raw_writel(0x01, base + RTC_CTRL_REG); //RTC_CTRL_REG = 0x01;
        
        return 0;

    }

    Presently it is failing at RTC Test 3 with following message .

    "Month 6 boundary is not passed"

    Regards,

    Vimal

  • Vimal,

    OK, you have updated the u-boot board file (evm.c) with the ti814x_init(void) function. But how exactly you have integrated the cmd_uu_rtc.c file with the u-boot?

    Could you provide me the exact steps to reproduce this issue (test fail) on my DM814x EVM?

    Regards,
    Pavel

  • Hi Pavel,

    here is the steps i have taken to integrate this file with u-boot.

    1. copied this file into common foldet.

    2. Added following into common/Makefile to compile it.

    COBJS-y += cmd_uu_rtc.o
    COBJS-$(CONFIG_CMD_I2C) += cmd_i2c.o

    3. here is the board file (evm.c)

    /*
     * Copyright (C) 2009, Texas Instruments, Incorporated
     *
     * 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 version 2.
     *
     * This program is distributed "as is" WITHOUT ANY WARRANTY of any
     * kind, whether express or implied; without even the implied warranty
     * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     */
    
    #include <common.h>
    #include <asm/cache.h>
    #include <asm/arch/cpu.h>
    #include <asm/arch/ddr_defs.h>
    #include <asm/arch/hardware.h>
    #include <asm/arch/sys_proto.h>
    #include <asm/arch/clock.h>
    #include <asm/arch/mem.h>
    #include <asm/arch/nand.h>
    #include <linux/mtd/nand.h>
    #include <nand.h>
    #include <net.h>
    #include <miiphy.h>
    #include <netdev.h>
    
    #if 0
    #define __raw_readl(a)		(*(volatile unsigned int *)(a))
    #define __raw_writel(v, a)	(*(volatile unsigned int *)(a) = (v))
    #define __raw_readw(a)		(*(volatile unsigned short *)(a))
    #define __raw_writew(v, a)	(*(volatile unsigned short *)(a) = (v))
    #endif
    
    DECLARE_GLOBAL_DATA_PTR;
    
    static void cmd_macro_config(u32 ddr_phy, u32 inv_clk_out,
    			 u32 ctrl_slave_ratio_cs0, u32 cmd_dll_lock_diff)
    {
    	u32 ddr_phy_base = (DDR_PHY0 == ddr_phy) ?
    			 DDR0_PHY_BASE_ADDR : DDR1_PHY_BASE_ADDR;
    
    	__raw_writel(inv_clk_out,
    		 ddr_phy_base + CMD1_REG_PHY_INVERT_CLKOUT_0);
    	__raw_writel(inv_clk_out,
    		 ddr_phy_base + CMD0_REG_PHY_INVERT_CLKOUT_0);
    	__raw_writel(inv_clk_out,
    		 ddr_phy_base + CMD2_REG_PHY_INVERT_CLKOUT_0);
    
    	__raw_writel(((ctrl_slave_ratio_cs0 << 10) | ctrl_slave_ratio_cs0),
    		ddr_phy_base + CMD0_REG_PHY_CTRL_SLAVE_RATIO_0);
    	__raw_writel(((ctrl_slave_ratio_cs0 << 10) | ctrl_slave_ratio_cs0),
    		ddr_phy_base + CMD1_REG_PHY_CTRL_SLAVE_RATIO_0);
    	__raw_writel(((ctrl_slave_ratio_cs0 << 10) | ctrl_slave_ratio_cs0),
    		 ddr_phy_base + CMD2_REG_PHY_CTRL_SLAVE_RATIO_0);
    
    	__raw_writel(cmd_dll_lock_diff,
    		 ddr_phy_base + CMD0_REG_PHY_DLL_LOCK_DIFF_0);
    	__raw_writel(cmd_dll_lock_diff,
    		 ddr_phy_base + CMD1_REG_PHY_DLL_LOCK_DIFF_0);
    	__raw_writel(cmd_dll_lock_diff,
    		 ddr_phy_base + CMD2_REG_PHY_DLL_LOCK_DIFF_0);
    }
    
    static void data_macro_config(u32 macro_num, u32 phy_num, u32 rd_dqs_cs0,
    		u32 wr_dqs_cs0, u32 fifo_we_cs0, u32 wr_data_cs0)
    {
    	/* 0xA4 is size of each data macro mmr region.
    	 * phy1 is at offset 0x400 from phy0
    	 */
    	u32 base = (macro_num * 0xA4) + (phy_num * 0x400);
    
    	__raw_writel(((rd_dqs_cs0 << 10) | rd_dqs_cs0),
    		(DATA0_REG_PHY0_RD_DQS_SLAVE_RATIO_0 + base));
    	__raw_writel(((wr_dqs_cs0 << 10) | wr_dqs_cs0),
    		(DATA0_REG_PHY0_WR_DQS_SLAVE_RATIO_0 + base));
    	__raw_writel(((PHY_WRLVL_INIT_CS1_DEFINE << 10) |
    		PHY_WRLVL_INIT_CS0_DEFINE),
    		(DATA0_REG_PHY0_WRLVL_INIT_RATIO_0 + base));
    	__raw_writel(((PHY_GATELVL_INIT_CS1_DEFINE << 10) |
    		PHY_GATELVL_INIT_CS0_DEFINE),
    		(DATA0_REG_PHY0_GATELVL_INIT_RATIO_0 + base));
    	__raw_writel(((fifo_we_cs0 << 10) | fifo_we_cs0),
    		(DATA0_REG_PHY0_FIFO_WE_SLAVE_RATIO_0 + base));
    	__raw_writel(((wr_data_cs0 << 10) | wr_data_cs0),
    		(DATA0_REG_PHY0_WR_DATA_SLAVE_RATIO_0 + base));
    	__raw_writel(PHY_DLL_LOCK_DIFF_DEFINE,
    		(DATA0_REG_PHY0_DLL_LOCK_DIFF_0 + base));
    }
    
    int is_ddr3(void)
    {
    	/*
    	 * PG1.0 by default uses DDR2 &  PG2.1 uses DDR3
    	 * To use PG2.1 and DDR2 enable #define CONFIG_TI814X_EVM_DDR2
    	 * in "include/configs/ti8148_evm.h"
    	 */
    	if (PG2_1 == get_cpu_rev())
    		#ifdef CONFIG_TI814X_EVM_DDR2
    			return 0;
    		#else
    			return 1;
    		#endif
    	else
    		return 0;
    }
    
    #ifdef CONFIG_SETUP_PLL
    static void pll_config(u32, u32, u32, u32, u32);
    #if 0
    static void pcie_pll_config(void);
    #endif
    static void audio_pll_config(void);
    static void sata_pll_config(void);
    static void modena_pll_config(void);
    static void l3_pll_config(void);
    static void ddr_pll_config(void);
    static void dsp_pll_config(void);
    static void iss_pll_config(void);
    static void iva_pll_config(void);
    static void usb_pll_config(void);
    #endif
    
    static void unlock_pll_control_mmr(void);
    static void cpsw_pad_config(void);
    static void nor_pad_config_mux(void);
    /*
     * spinning delay to use before udelay works
     */
    static inline void delay(unsigned long loops)
    {
    	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"
    		"bne 1b" : "=r" (loops) : "0"(loops));
    }
    
    /* following added by vimal */
    
    #define TI81XX_RTC_BASE 0x480C0000
    
    #define SECONDS_REG     0x00
    #define MINUTES_REG     0x04
    #define HOURS_REG       0x08
    #define DAYS_REG        0x0C
    #define MONTHS_REG      0x10
    #define YEARS_REG       0x14
    #define WEEK_REG        0x18
    
    #define RTC_CTRL_REG    0x40
    #define RTC_STATUS_REG  0x44
    #define OSC_REG        0x54
    
    #define KICK0_REG    0x6c
    #define KICK1_REG    0x70
    
    #define KICK0_REG_VAL    0x83e70b13
    #define KICK1_REG_VAL    0x95a4f1e0
    #define RESET_VAL    BIT(5)
    
    
    int ti814x_rtc_init(void)
    {
        u32 base;
        
        base = TI81XX_RTC_BASE;    
        
        /* Unlock the rtc's registers*/
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        /* Reset the RTC */
        __raw_writel(RESET_VAL, base + OSC_REG);
    
        /*
         * After setting the SW_RESET bit, RTC registers must not be accessed
         * for 3 32kHz clock cycles (roughly 2200 OCP cycles).*/
        
       udelay(100);
    
        /*
         * Unlock the rtc's registers again as the registers would have been
         * locked due to reset*/
        
        __raw_writel(KICK0_REG_VAL, base + KICK0_REG);
        __raw_writel(KICK1_REG_VAL, base + KICK1_REG);
        
        
         /* Initialize Calender to day 1, 12:00:00 */
        __raw_writel(0x00, base + SECONDS_REG); //SECONDS_REG = 0x01;                    
        __raw_writel(0x00, base + MINUTES_REG); //MINUTES_REG = 0x30;                    
        __raw_writel(0x01, base + HOURS_REG); //HOURS_REG = 0x01;
        __raw_writel(0x01, base + DAYS_REG); //DAYS_REG = 0x08;
        __raw_writel(0x01, base + MONTHS_REG); //MONTHS_REG = 0x07;
        __raw_writel(0x63, base + YEARS_REG); //YEARS_REG  = 0x84;
        __raw_writel(0x01, base + WEEK_REG); //WEEK_REG  = 0x01;
        
        /* Start RTC */
        __raw_writel(0x01, base + RTC_CTRL_REG); //RTC_CTRL_REG = 0x01;
        
        return 0;
    
    }
    /*********** End of Vimal Addition ************/
    
    /*
     * Basic board specific setup
     */
    int board_init(void)
    {
    	u32 regVal;
    
    	/* Do the required pin-muxing before modules are setup */
    	set_muxconf_regs();
    
    	nor_pad_config_mux();
    
    	/* setup RMII_REFCLK to be sourced from audio_pll */
    	__raw_writel(0x4, RMII_REFCLK_SRC);
    
    	if (PG2_1 == get_cpu_rev()) {
    		/*program GMII_SEL register for RGMII mode */
    		__raw_writel(0x30a,GMII_SEL);
    	}
    	/* Get Timer and UART out of reset */
    
    	/* UART softreset */
    	regVal = __raw_readl(UART_SYSCFG);
    	regVal |= 0x2;
    	__raw_writel(regVal, UART_SYSCFG);
    	while( (__raw_readl(UART_SYSSTS) & 0x1) != 0x1);
    
    	/* Disable smart idle */
    	regVal = __raw_readl(UART_SYSCFG);
    	regVal |= (1<<3);
    	__raw_writel(regVal, UART_SYSCFG);
    
    	/* mach type passed to kernel */
    	gd->bd->bi_arch_number = MACH_TYPE_TI8148EVM;
    
    	/* address of boot parameters */
    	gd->bd->bi_boot_params = PHYS_DRAM_1 + 0x100;
    	gpmc_init();
    
    #ifndef CONFIG_NOR
    	/* GPMC will come up with default buswidth configuration,
        * we will override it based on BW pin CONFIG_STATUS register.
        * This is currently required only for NAND/NOR to
        * support 8/16 bit NAND/NOR part. Also we always use chipselect 0
        * for NAND/NOR boot.
        *
        * NOTE: This code is DM8168 EVM specific, hence we are using CS 0.
        * Also, even for other boot modes user is expected to
        * on/off the BW pin on the EVM.
        */
    	gpmc_set_cs_buswidth(0, get_sysboot_bw());
    #endif
    
    	ti814x_rtc_init();  
    	return 0;
    }
    
    /*
     * sets uboots idea of sdram size
     */
    int dram_init(void)
    {
    	/* Fill up board info */
    	gd->bd->bi_dram[0].start = PHYS_DRAM_1;
    	gd->bd->bi_dram[0].size = PHYS_DRAM_1_SIZE;
    
    	gd->bd->bi_dram[1].start = PHYS_DRAM_2;
    	gd->bd->bi_dram[1].size = PHYS_DRAM_2_SIZE;
    
    	return 0;
    }
    
    
    int misc_init_r (void)
    {
    	#ifdef CONFIG_TI814X_MIN_CONFIG
    	printf("The 2nd stage U-Boot will now be auto-loaded\n");
    	printf("Please do not interrupt the countdown till "
    		"TI8148_EVM prompt if 2nd stage is already flashed\n");
    	#endif
    
    	#ifdef CONFIG_TI814X_ASCIIART
    	int i = 0, j = 0;
    	char ti814x[28][54] = {
    "                          .:;rrr;;.                   ",
    "                    ,5#@@@@#####@@@@@@#2,             ",
    "                 ,A@@@hi;;;r5;;;;r;rrSG@@@A,          ",
    "               r@@#i;:;s222hG;rrsrrrrrr;ri#@@r        ",
    "             :@@hr:r;SG3ssrr2r;rrsrsrsrsrr;rh@@:      ",
    "            B@H;;rr;3Hs;rrr;sr;;rrsrsrsrsrsr;;H@B     ",
    "           @@s:rrs;5#;;rrrr;r#@H:;;rrsrsrsrsrr:s@@    ",
    "          @@;;srs&X#9;r;r;;,2@@@rrr:;;rrsrsrsrr;;@@   ",
    "         @@;;rrsrrs@MB#@@@@@###@@@@@@#rsrsrsrsrr;;@@  ",
    "        G@r;rrsrsr;#X;SX25Ss#@@#M@#9H9rrsrsrsrsrs;r@G ",
    "        @9:srsrsrs;2@;:;;:.X@@@@@H::;rrsrsrsrsrsrr:3@ ",
    "       X@;rrsrsrsrr;XAi;;:&@@#@Bs:rrsrsrsrsrsrsrsrr;@X",
    "       @#;rsrsrsrsrr;r2ir@@@###::rrsrsrsrsrsrsrsrsr:@@",
    "       @A:rrsrsrsrr;:2@29@@M@@@;:;rrrrsrsrsrsrsrsrs;H@",
    "       @&;rsrsrsrr;A@@@@@@###@@@s::;:;;rrsrsrsrsrsr;G@",
    "       @#:rrsrsrsr;G@5Hr25@@@#@@@#9XG9s:rrrrsrsrsrs:#@",
    "       M@;rsrsrsrs;r@&#;::S@@@@@@@M@@@@Grr:;rsrsrsr;@#",
    "       :@s;rsrsrsrr:M#Msrr;;&#@@@@@@@@@@H@@5;rsrsr;s@,",
    "        @@:rrsrsrsr;S@rrrsr;:;r3MH@@#@M5,S@@irrsrr:@@ ",
    "         @A:rrsrsrsrrrrrsrsrrr;::;@##@r:;rH@h;srr:H@  ",
    "         ;@9:rrsrsrsrrrsrsrsrsr;,S@Hi@i:;s;MX;rr:h@;  ",
    "          r@B:rrrrsrsrsrsrsrr;;sA@#i,i@h;r;S5;r:H@r   ",
    "           ,@@r;rrrsrsrsrsrr;2BM3r:;r:G@:rrr;;r@@,    ",
    "             B@Mr;rrrrsrsrsr@@S;;;rrr:5M;rr;rM@H      ",
    "              .@@@i;;rrrrsrs2i;rrrrr;r@M:;i@@@.       ",
    "                .A@@#5r;;;r;;;rrr;r:r#AsM@@H.         ",
    "                   ;&@@@@MhXS5i5SX9B@@@@G;            ",
    "                       :ihM#@@@@@##hs,                "};
    
    	for (i = 0; i<28; i++)
    	{
    		for(j = 0; j<54; j++)
    			printf("%c",ti814x[i][j]);
    			printf("\n");
    	}
    	printf("\n");
    	#endif
    	return 0;
    }
    
    #ifdef CONFIG_TI814X_CONFIG_DDR
    static void config_ti814x_ddr(void)
    {
    	int macro, phy_num;
    
    	/*Enable the Power Domain Transition of L3 Fast Domain Peripheral*/
    	__raw_writel(0x2, CM_DEFAULT_FW_CLKCTRL);
    	/*Enable the Power Domain Transition of L3 Fast Domain Peripheral*/
    	__raw_writel(0x2, CM_DEFAULT_L3_FAST_CLKSTCTRL);
    	__raw_writel(0x2, CM_DEFAULT_EMIF_0_CLKCTRL); /*Enable EMIF0 Clock*/
    	__raw_writel(0x2, CM_DEFAULT_EMIF_1_CLKCTRL); /*Enable EMIF1 Clock*/
    	__raw_writel(0x2, CM_DEFAULT_DMM_CLKCTRL);
    
    	/*Poll for L3_FAST_GCLK  & DDR_GCLK  are active*/
    	while ((__raw_readl(CM_DEFAULT_L3_FAST_CLKSTCTRL) & 0x300) != 0x300);
    	/*Poll for Module is functional*/
    	while ((__raw_readl(CM_DEFAULT_EMIF_0_CLKCTRL)) != 0x2);
    	while ((__raw_readl(CM_DEFAULT_EMIF_1_CLKCTRL)) != 0x2);
    	while ((__raw_readl(CM_DEFAULT_DMM_CLKCTRL)) != 0x2);
    
    	if (is_ddr3()) {
    		cmd_macro_config(DDR_PHY0, DDR3_PHY_INVERT_CLKOUT_OFF,
    				DDR3_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
    				PHY_CMD0_DLL_LOCK_DIFF_DEFINE);
    		cmd_macro_config(DDR_PHY1, DDR3_PHY_INVERT_CLKOUT_OFF,
    				DDR3_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
    				PHY_CMD0_DLL_LOCK_DIFF_DEFINE);
    
    		for (phy_num = 0; phy_num <= DDR_PHY1; phy_num++) {
    			for (macro = 0; macro <= DATA_MACRO_3; macro++) {
    				data_macro_config(macro, phy_num,
    					DDR3_PHY_RD_DQS_CS0_DEFINE,
    					DDR3_PHY_WR_DQS_CS0_DEFINE,
    					DDR3_PHY_RD_DQS_GATE_CS0_DEFINE,
    					DDR3_PHY_WR_DATA_CS0_DEFINE);
    			}
    		}
    	} else {
    		cmd_macro_config(DDR_PHY0, PHY_INVERT_CLKOUT_DEFINE,
    				DDR2_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
    				PHY_CMD0_DLL_LOCK_DIFF_DEFINE);
    		cmd_macro_config(DDR_PHY1, PHY_INVERT_CLKOUT_DEFINE,
    				DDR2_PHY_CTRL_SLAVE_RATIO_CS0_DEFINE,
    				PHY_CMD0_DLL_LOCK_DIFF_DEFINE);
    
    		for (phy_num = 0; phy_num <= DDR_PHY1; phy_num++) {
    			for (macro = 0; macro <= DATA_MACRO_3; macro++) {
    				data_macro_config(macro, phy_num,
    					DDR2_PHY_RD_DQS_CS0_DEFINE,
    					DDR2_PHY_WR_DQS_CS0_DEFINE,
    					DDR2_PHY_RD_DQS_GATE_CS0_DEFINE,
    					DDR2_PHY_WR_DATA_CS0_DEFINE);
    			}
    		}
    	}
    
    	/* DDR IO CTRL config */
    	__raw_writel(DDR0_IO_CTRL_DEFINE, DDR0_IO_CTRL);
    	__raw_writel(DDR1_IO_CTRL_DEFINE, DDR1_IO_CTRL);
    
    	__raw_writel(__raw_readl(VTP0_CTRL_REG) | 0x00000040 , VTP0_CTRL_REG);
    	__raw_writel(__raw_readl(VTP1_CTRL_REG) | 0x00000040 , VTP1_CTRL_REG);
    
    	// Write 0 to CLRZ bit
    	__raw_writel(__raw_readl(VTP0_CTRL_REG) & 0xfffffffe , VTP0_CTRL_REG);
    	__raw_writel(__raw_readl(VTP1_CTRL_REG) & 0xfffffffe , VTP1_CTRL_REG);
    
    	// Write 1 to CLRZ bit
    	__raw_writel(__raw_readl(VTP0_CTRL_REG) | 0x00000001 , VTP0_CTRL_REG);
    	__raw_writel(__raw_readl(VTP1_CTRL_REG) | 0x00000001 , VTP1_CTRL_REG);
    
    	// Read VTP control registers & check READY bits
    	while ((__raw_readl(VTP0_CTRL_REG) & 0x00000020) != 0x20);
    	while ((__raw_readl(VTP1_CTRL_REG) & 0x00000020) != 0x20);
    
    	if (PG1_0 == get_cpu_rev()) {
    		/*
    		 * Program the PG1.0 DMM to Access EMIF0 and EMIF1
    		 * Two 256MB sections with 128-byte interleaved (hole in b/w)
    		 */
    		__raw_writel(PG1_0_DMM_LISA_MAP__0, DMM_LISA_MAP__0);
    		__raw_writel(PG1_0_DMM_LISA_MAP__1, DMM_LISA_MAP__1);
    		__raw_writel(PG1_0_DMM_LISA_MAP__2, DMM_LISA_MAP__2);
    		__raw_writel(PG1_0_DMM_LISA_MAP__3, DMM_LISA_MAP__3);
    
    		while (__raw_readl(DMM_LISA_MAP__0) != PG1_0_DMM_LISA_MAP__0);
    		while (__raw_readl(DMM_LISA_MAP__1) != PG1_0_DMM_LISA_MAP__1);
    		while (__raw_readl(DMM_LISA_MAP__2) != PG1_0_DMM_LISA_MAP__2);
    		while (__raw_readl(DMM_LISA_MAP__3) != PG1_0_DMM_LISA_MAP__3);
    	} else {
    		/*
    		 * Program the PG2.1 DMM to Access EMIF0 and EMIF1
    		 * 1G contiguous section with 128-byte interleaving
    		 */
    		__raw_writel(PG2_1_DMM_LISA_MAP__0, DMM_LISA_MAP__0);
    		__raw_writel(PG2_1_DMM_LISA_MAP__1, DMM_LISA_MAP__1);
    		__raw_writel(PG2_1_DMM_LISA_MAP__2, DMM_LISA_MAP__2);
    		__raw_writel(PG2_1_DMM_LISA_MAP__3, DMM_LISA_MAP__3);
    
    		while (__raw_readl(DMM_LISA_MAP__0) != PG2_1_DMM_LISA_MAP__0);
    		while (__raw_readl(DMM_LISA_MAP__1) != PG2_1_DMM_LISA_MAP__1);
    		while (__raw_readl(DMM_LISA_MAP__2) != PG2_1_DMM_LISA_MAP__2);
    		while (__raw_readl(DMM_LISA_MAP__3) != PG2_1_DMM_LISA_MAP__3);
    	}
    	__raw_writel(0x80000000, DMM_PAT_BASE_ADDR);
    
    	if (!is_ddr3()) {
    		/*Program EMIF0 CFG Registers*/
    		__raw_writel(DDR2_EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1);
    		__raw_writel(DDR2_EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM1, EMIF4_0_SDRAM_TIM_1);
    		__raw_writel(DDR2_EMIF_TIM1, EMIF4_0_SDRAM_TIM_1_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM2, EMIF4_0_SDRAM_TIM_2);
    		__raw_writel(DDR2_EMIF_TIM2, EMIF4_0_SDRAM_TIM_2_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM3, EMIF4_0_SDRAM_TIM_3);
    		__raw_writel(DDR2_EMIF_TIM3, EMIF4_0_SDRAM_TIM_3_SHADOW);
    		__raw_writel(DDR2_EMIF_SDRAM_CONFIG, EMIF4_0_SDRAM_CONFIG);
    
    		__raw_writel(DDR_EMIF_REF_CTRL | DDR_EMIF_REF_TRIGGER,
    						 EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    		__raw_writel(DDR2_EMIF_SDRAM_ZQCR, EMIF4_0_SDRAM_ZQCR);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    
    		__raw_writel(DDR2_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR2_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    
    		/*Program EMIF1 CFG Registers*/
    		__raw_writel(DDR2_EMIF_READ_LATENCY, EMIF4_1_DDR_PHY_CTRL_1);
    		__raw_writel(DDR2_EMIF_READ_LATENCY, EMIF4_1_DDR_PHY_CTRL_1_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM1, EMIF4_1_SDRAM_TIM_1);
    		__raw_writel(DDR2_EMIF_TIM1, EMIF4_1_SDRAM_TIM_1_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM2, EMIF4_1_SDRAM_TIM_2);
    		__raw_writel(DDR2_EMIF_TIM2, EMIF4_1_SDRAM_TIM_2_SHADOW);
    		__raw_writel(DDR2_EMIF_TIM3, EMIF4_1_SDRAM_TIM_3);
    		__raw_writel(DDR2_EMIF_TIM3, EMIF4_1_SDRAM_TIM_3_SHADOW);
    		__raw_writel(DDR2_EMIF_SDRAM_CONFIG, EMIF4_1_SDRAM_CONFIG);
    
    		__raw_writel(DDR_EMIF_REF_CTRL | DDR_EMIF_REF_TRIGGER,
    						 EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    		__raw_writel(DDR2_EMIF_SDRAM_ZQCR, EMIF4_1_SDRAM_ZQCR);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    
    		__raw_writel(DDR2_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR2_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    
    	} else {
    		/*Program EMIF0 CFG Registers*/
    		__raw_writel(DDR3_EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1);
    		__raw_writel(DDR3_EMIF_READ_LATENCY, EMIF4_0_DDR_PHY_CTRL_1_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM1, EMIF4_0_SDRAM_TIM_1);
    		__raw_writel(DDR3_EMIF_TIM1, EMIF4_0_SDRAM_TIM_1_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM2, EMIF4_0_SDRAM_TIM_2);
    		__raw_writel(DDR3_EMIF_TIM2, EMIF4_0_SDRAM_TIM_2_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM3, EMIF4_0_SDRAM_TIM_3);
    		__raw_writel(DDR3_EMIF_TIM3, EMIF4_0_SDRAM_TIM_3_SHADOW);
    		__raw_writel(DDR3_EMIF_SDRAM_CONFIG, EMIF4_0_SDRAM_CONFIG);
    
    		__raw_writel(DDR_EMIF_REF_CTRL | DDR_EMIF_REF_TRIGGER,
    						 EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    		__raw_writel(DDR3_EMIF_SDRAM_ZQCR, EMIF4_0_SDRAM_ZQCR);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    
    		__raw_writel(DDR3_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL);
    		__raw_writel(DDR3_EMIF_REF_CTRL, EMIF4_0_SDRAM_REF_CTRL_SHADOW);
    
    		/*Program EMIF1 CFG Registers*/
    		__raw_writel(DDR3_EMIF_READ_LATENCY, EMIF4_1_DDR_PHY_CTRL_1);
    		__raw_writel(DDR3_EMIF_READ_LATENCY, EMIF4_1_DDR_PHY_CTRL_1_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM1, EMIF4_1_SDRAM_TIM_1);
    		__raw_writel(DDR3_EMIF_TIM1, EMIF4_1_SDRAM_TIM_1_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM2, EMIF4_1_SDRAM_TIM_2);
    		__raw_writel(DDR3_EMIF_TIM2, EMIF4_1_SDRAM_TIM_2_SHADOW);
    		__raw_writel(DDR3_EMIF_TIM3, EMIF4_1_SDRAM_TIM_3);
    		__raw_writel(DDR3_EMIF_TIM3, EMIF4_1_SDRAM_TIM_3_SHADOW);
    		__raw_writel(DDR3_EMIF_SDRAM_CONFIG, EMIF4_1_SDRAM_CONFIG);
    
    		__raw_writel(DDR_EMIF_REF_CTRL | DDR_EMIF_REF_TRIGGER,
    						 EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    		__raw_writel(DDR3_EMIF_SDRAM_ZQCR, EMIF4_1_SDRAM_ZQCR);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    
    		__raw_writel(DDR3_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL);
    		__raw_writel(DDR3_EMIF_REF_CTRL, EMIF4_1_SDRAM_REF_CTRL_SHADOW);
    	}
    }
    
    #endif
    
    #ifdef CONFIG_SETUP_PLL
    static void audio_pll_config()
    {
    	pll_config(AUDIO_PLL_BASE,
    			AUDIO_N, AUDIO_M,
    			AUDIO_M2, AUDIO_CLKCTRL);
    }
    
    #if 0
    static void pcie_pll_config()
    {
    	/* Powerdown both reclkp/n single ended receiver */
    	__raw_writel(0x00000002, SERDES_REFCLK_CTRL);
    
    	__raw_writel(0x00000000, PCIE_PLLCFG0);
    
    	/* PCIe(2.5GHz) mode, 100MHz refclk, MDIVINT = 25,
    	 * disable (50,100,125M) clks
    	 */
    	__raw_writel(0x00640000, PCIE_PLLCFG1);
    
    	/* SSC Mantissa and exponent = 0 */
    	__raw_writel(0x00000000, PCIE_PLLCFG2);
    
    	/* TBD */
    	__raw_writel(0x004008E0, PCIE_PLLCFG3);
    
    	/* TBD */
    	__raw_writel(0x0000609C, PCIE_PLLCFG4);
    
    	/* pcie_serdes_cfg_misc */
    	/* TODO: verify the address over here
    	 * (CTRL_BASE + 0x6FC = 0x481406FC ???)
    	 */
    	//__raw_writel(0x00000E7B, 0x48141318);
    	delay(3);
    
    	/* Enable PLL LDO */
    	__raw_writel(0x00000004, PCIE_PLLCFG0);
    	delay(3);
    
    	/* Enable DIG LDO, PLL LD0 */
    	__raw_writel(0x00000014, PCIE_PLLCFG0);
    	delay(3);
    
    	/* Enable DIG LDO, ENBGSC_REF, PLL LDO */
    	__raw_writel(0x00000016, PCIE_PLLCFG0);
    	delay(3);
    	__raw_writel(0x30000016, PCIE_PLLCFG0);
    	delay(3);
    	__raw_writel(0x70000016, PCIE_PLLCFG0);
    	delay(3);
    
    	/* Enable DIG LDO, SELSC, ENBGSC_REF, PLL LDO */
    	__raw_writel(0x70000017, PCIE_PLLCFG0);
    	delay(3);
    
    	/* wait for ADPLL lock */
    	while(__raw_readl(PCIE_PLLSTATUS) != 0x1);
    
    }
    #endif
    
    static void sata_pll_config()
    {
    	__raw_writel(0xC12C003C, SATA_PLLCFG1);
    	__raw_writel(0x004008E0, SATA_PLLCFG3);
    	delay(0xFFFF);
    
    	__raw_writel(0x80000004, SATA_PLLCFG0);
    	delay(0xFFFF);
    
    	/* Enable PLL LDO */
    	__raw_writel(0x80000014, SATA_PLLCFG0);
    	delay(0xFFFF);
    
    	/* Enable DIG LDO, ENBGSC_REF, PLL LDO */
    	__raw_writel(0x80000016, SATA_PLLCFG0);
    	delay(0xFFFF);
    
    	__raw_writel(0xC0000017, SATA_PLLCFG0);
    	delay(0xFFFF);
    
    	/* wait for ADPLL lock */
    	while(((__raw_readl(SATA_PLLSTATUS) & 0x01) == 0x0));
    
    }
    
    static void usb_pll_config()
    {
    	pll_config(USB_PLL_BASE,
    			USB_N, USB_M,
    			USB_M2, USB_CLKCTRL);
    }
    
    static void modena_pll_config()
    {
    	pll_config(MODENA_PLL_BASE,
    			MODENA_N, MODENA_M,
    			MODENA_M2, MODENA_CLKCTRL);
    }
    
    static void l3_pll_config()
    {
    	pll_config(L3_PLL_BASE,
    			L3_N, L3_M,
    			L3_M2, L3_CLKCTRL);
    }
    
    static void ddr_pll_config()
    {
    	pll_config(DDR_PLL_BASE,
    			DDR_N, DDR_M,
    			DDR_M2, DDR_CLKCTRL);
    }
    
    static void dsp_pll_config()
    {
    	pll_config(DSP_PLL_BASE,
    			DSP_N, DSP_M,
    			DSP_M2, DSP_CLKCTRL);
    }
    
    static void iss_pll_config()
    {
    	pll_config(ISS_PLL_BASE,
    			ISS_N, ISS_M,
    			ISS_M2, ISS_CLKCTRL);
    }
    
    static void iva_pll_config()
    {
    	pll_config(IVA_PLL_BASE,
    			IVA_N, IVA_M,
    			IVA_M2, IVA_CLKCTRL);
    }
    
    /*
     * configure individual ADPLLJ
     */
    static void pll_config(u32 base, u32 n, u32 m, u32 m2, u32 clkctrl_val)
    {
    	u32 m2nval, mn2val, read_clkctrl = 0;
    
    	m2nval = (m2 << 16) | n;
    	mn2val = m;
    
    	/* by-pass pll */
    	read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
    	__raw_writel((read_clkctrl | 0x00800000), (base + ADPLLJ_CLKCTRL));
    	while ((__raw_readl(base + ADPLLJ_STATUS) & 0x101) != 0x101);
    	read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
    	__raw_writel((read_clkctrl & 0xfffffffe), (base + ADPLLJ_CLKCTRL));
    
    
    	/*
    	 * ref_clk = 20/(n + 1);
    	 * clkout_dco = ref_clk * m;
    	 * clk_out = clkout_dco/m2;
    	*/
    
    	__raw_writel(m2nval, (base + ADPLLJ_M2NDIV));
    	__raw_writel(mn2val, (base + ADPLLJ_MN2DIV));
    
    	/* Load M2, N2 dividers of ADPLL */
    	__raw_writel(0x1, (base + ADPLLJ_TENABLEDIV));
    	__raw_writel(0x0, (base + ADPLLJ_TENABLEDIV));
    
    	/* Loda M, N dividers of ADPLL */
    	__raw_writel(0x1, (base + ADPLLJ_TENABLE));
    	__raw_writel(0x0, (base + ADPLLJ_TENABLE));
    
    	read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
    
    	if (MODENA_PLL_BASE == base)
    		__raw_writel((read_clkctrl & 0xff7fffff) | clkctrl_val,
    			base + ADPLLJ_CLKCTRL);
    	else
    		__raw_writel((read_clkctrl & 0xff7fe3ff) | clkctrl_val,
    			base + ADPLLJ_CLKCTRL);
    	/* Wait for phase and freq lock */
    	while ((__raw_readl(base + ADPLLJ_STATUS) & 0x600) != 0x600);
    
    }
    #endif
    
    /*
     * Enable the clks & power for perifs (TIMER1, UART0,...)
     */
    void per_clocks_enable(void)
    {
    	u32 temp;
    
    	__raw_writel(0x2, CM_ALWON_L3_SLOW_CLKSTCTRL);
    
    	/* TODO: No module level enable as in ti8148 ??? */
    #if 0
    	/* TIMER 1 */
    	__raw_writel(0x2, CM_ALWON_TIMER_1_CLKCTRL);
    #endif
    	/* Selects OSC0 (20MHz) for DMTIMER1 */
    	temp = __raw_readl(DMTIMER_CLKSRC);
    	temp &= ~(0x7 << 3);
    	temp |= (0x4 << 3);
    	__raw_writel(temp, DMTIMER_CLKSRC);
    
    #if 0
    	while(((__raw_readl(CM_ALWON_L3_SLOW_CLKSTCTRL) & (0x80000<<1)) >> (19+1)) != 1);
    	while(((__raw_readl(CM_ALWON_TIMER_1_CLKCTRL) & 0x30000)>>16) !=0);
    #endif
    	__raw_writel(0x2,(DM_TIMER1_BASE + 0x54));
    	while(__raw_readl(DM_TIMER1_BASE + 0x10) & 1);
    
    	__raw_writel(0x1,(DM_TIMER1_BASE + 0x38));
    
    	/* UARTs */
    	__raw_writel(0x2, CM_ALWON_UART_0_CLKCTRL);
    	while(__raw_readl(CM_ALWON_UART_0_CLKCTRL) != 0x2);
    
    	__raw_writel(0x2, CM_ALWON_UART_1_CLKCTRL);
    	while(__raw_readl(CM_ALWON_UART_1_CLKCTRL) != 0x2);
    
    	__raw_writel(0x2, CM_ALWON_UART_2_CLKCTRL);
    	while(__raw_readl(CM_ALWON_UART_2_CLKCTRL) != 0x2);
    
    	while((__raw_readl(CM_ALWON_L3_SLOW_CLKSTCTRL) & 0x2100) != 0x2100);
    
    	/* SPI */
    	__raw_writel(0x2, CM_ALWON_SPI_CLKCTRL);
    	while(__raw_readl(CM_ALWON_SPI_CLKCTRL) != 0x2);
    
    	/* I2C0 and I2C2 */
    	__raw_writel(0x2, CM_ALWON_I2C_0_CLKCTRL);
    	while(__raw_readl(CM_ALWON_I2C_0_CLKCTRL) != 0x2);
    	/* Ethernet */
    	__raw_writel(0x2, CM_ETHERNET_CLKSTCTRL);
    	__raw_writel(0x2, CM_ALWON_ETHERNET_0_CLKCTRL);
    	while((__raw_readl(CM_ALWON_ETHERNET_0_CLKCTRL) & 0x30000) != 0);
    	__raw_writel(0x2, CM_ALWON_ETHERNET_1_CLKCTRL);
    	/* HSMMC */
    	__raw_writel(0x2, CM_ALWON_HSMMC_CLKCTRL);
    	while(__raw_readl(CM_ALWON_HSMMC_CLKCTRL) != 0x2);
    
    	/*
    	 * McASP2
    	 * select mcasp2 clk from sys_clk_22 (OSC 0)
    	 * so that audio clk (sys_clk_20) can be used for RMII
    	 * ToDo :
    	 * This can be removed once kernel exports set_parent()
    	 */
    	__raw_writel(0x2, CM_ALWON_MCASP2_CLKCTRL);
    	while (__raw_readl(CM_ALWON_MCASP2_CLKCTRL) != 0x2);
    
    	/* WDT */
    	/* For WDT to be functional, it needs to be first stopped by writing
    	 * the pattern 0xAAAA followed by 0x5555 in the WDT start/stop register.
    	 * After that a write-once register in Control module needs to be
    	 * configured to unfreeze the timer.
    	 * Note: It is important to stop the watchdog before unfreezing it
    	*/
    	__raw_writel(0xAAAA, WDT_WSPR);
    	while (__raw_readl(WDT_WWPS) != 0x0);
    	__raw_writel(0x5555, WDT_WSPR);
    	while (__raw_readl(WDT_WWPS) != 0x0);
    
    	/* Unfreeze WDT */
    	__raw_writel(0x13, WDT_UNFREEZE);
    }
    
    /*
     * inits clocks for PRCM as defined in clocks.h
     */
    void prcm_init(u32 in_ddr)
    {
    	/* Enable the control module */
    	__raw_writel(0x2, CM_ALWON_CONTROL_CLKCTRL);
    
    #ifdef CONFIG_SETUP_PLL
    	/* Setup the various plls */
    	audio_pll_config();
    	sata_pll_config();
    #if 0
    	pcie_pll_config();
    #endif
    	modena_pll_config();
    	l3_pll_config();
    	ddr_pll_config();
    	dsp_pll_config();
    	iva_pll_config();
    	iss_pll_config();
    
    	usb_pll_config();
    
    	/*  With clk freqs setup to desired values,
    	 *  enable the required peripherals
    	 */
    	per_clocks_enable();
    #endif
    }
    
    #define PADCTRL_BASE 0x48140000
    
    #define PAD204_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B2c))
    #define PAD205_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B30))
    #define PAD206_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B34))
    #define PAD207_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B38))
    #define PAD208_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B3c))
    #define PAD209_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B40))
    #define PAD210_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B44))
    #define PAD211_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B48))
    #define PAD212_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B4c))
    #define PAD213_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B50))
    #define PAD214_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B54))
    #define PAD215_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B58))
    #define PAD216_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B5c))
    #define PAD217_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B60))
    #define PAD218_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B64))
    #define PAD219_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B68))
    #define PAD220_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B6c))
    #define PAD221_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B70))
    #define PAD222_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B74))
    #define PAD223_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B78))
    #define PAD224_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B7c))
    #define PAD225_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B80))
    #define PAD226_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B84))
    #define PAD227_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B88))
    
    #define PAD232_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0B9C))
    #define PAD233_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BA0))
    #define PAD234_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BA4))
    #define PAD235_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BA8))
    #define PAD236_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BAC))
    #define PAD237_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BB0))
    #define PAD238_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BB4))
    #define PAD239_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BB8))
    #define PAD240_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BBC))
    #define PAD241_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BC0))
    #define PAD242_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BC4))
    #define PAD243_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BC8))
    #define PAD244_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BCC))
    #define PAD245_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BD0))
    #define PAD246_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BD4))
    #define PAD247_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BD8))
    #define PAD248_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BDC))
    #define PAD249_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BE0))
    #define PAD250_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BE4))
    #define PAD251_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BE8))
    #define PAD252_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BEC))
    #define PAD253_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BF0))
    #define PAD254_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BF4))
    #define PAD255_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BF8))
    #define PAD256_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0BFC))
    #define PAD257_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0C00))
    #define PAD258_CNTRL  (*(volatile unsigned int *)(PADCTRL_BASE + 0x0C04))
    
    
    static void cpsw_pad_config()
    {
    	volatile u32 val = 0;
    
    	/*configure pin mux for rmii_refclk,mdio_clk,mdio_d */
    	val = PAD232_CNTRL;
    	PAD232_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    	val = PAD233_CNTRL;
    	PAD233_CNTRL = (volatile unsigned int) (BIT(19) | BIT(17) | BIT(0));
    	val = PAD234_CNTRL;
    	PAD234_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(17) |
    			BIT(0));
    
    	/*For PG1.0 we only support GMII Mode, setup gmii0/gmii1 pins here*/
    	if (PG1_0 == get_cpu_rev()) {
    		/* setup gmii0 pins, pins235-258 in function mode 1 */
    		val = PAD235_CNTRL;
    		PAD235_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) |
    				BIT(0));
    		val = PAD236_CNTRL;
    		PAD236_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) |
    				BIT(0));
    		val = PAD237_CNTRL;
    		PAD237_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) |
    				BIT(0));
    		val = PAD238_CNTRL;
    		PAD238_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) |
    				BIT(0));
    		val = PAD239_CNTRL;
    		PAD239_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) |
    				BIT(0));
    		val = PAD240_CNTRL;
    		PAD240_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD241_CNTRL;
    		PAD241_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD242_CNTRL;
    		PAD242_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD243_CNTRL;
    		PAD243_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD244_CNTRL;
    		PAD244_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD245_CNTRL;
    		PAD245_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD246_CNTRL;
    		PAD246_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD247_CNTRL;
    		PAD247_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD248_CNTRL;
    		PAD248_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD249_CNTRL;
    		PAD249_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD250_CNTRL;
    		PAD250_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD251_CNTRL;
    		PAD251_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD252_CNTRL;
    		PAD252_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD253_CNTRL;
    		PAD253_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD254_CNTRL;
    		PAD254_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD255_CNTRL;
    		PAD255_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD256_CNTRL;
    		PAD256_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD257_CNTRL;
    		PAD257_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD258_CNTRL;
    		PAD258_CNTRL = (volatile unsigned int) (BIT(0));
    
    		/* setup gmii1 pins, pins204-227 in function mode 2 */
    		val = PAD204_CNTRL;
    		PAD204_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(1));
    		val = PAD205_CNTRL;
    		PAD205_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(1));
    		val = PAD206_CNTRL;
    		PAD206_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(1));
    		val = PAD207_CNTRL;
    		PAD207_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(1));
    		val = PAD208_CNTRL;
    		PAD208_CNTRL = (volatile unsigned int) (BIT(19) | BIT(18) | BIT(1));
    		val = PAD209_CNTRL;
    		PAD209_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD210_CNTRL;
    		PAD210_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD211_CNTRL;
    		PAD211_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD212_CNTRL;
    		PAD212_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD213_CNTRL;
    		PAD213_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD214_CNTRL;
    		PAD214_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD215_CNTRL;
    		PAD215_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD216_CNTRL;
    		PAD216_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD217_CNTRL;
    		PAD217_CNTRL = (volatile unsigned int) (BIT(18) | BIT(1));
    		val = PAD218_CNTRL;
    		PAD218_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD219_CNTRL;
    		PAD219_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD220_CNTRL;
    		PAD220_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD221_CNTRL;
    		PAD221_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD222_CNTRL;
    		PAD222_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD223_CNTRL;
    		PAD223_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD224_CNTRL;
    		PAD224_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD225_CNTRL;
    		PAD225_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD226_CNTRL;
    		PAD226_CNTRL = (volatile unsigned int) (BIT(1));
    		val = PAD227_CNTRL;
    		PAD227_CNTRL = (volatile unsigned int) (BIT(1));
    
    	} else {/*setup rgmii0/rgmii1 pins here*/
    		/* In this case we enable rgmii_en bit in GMII_SEL register and
    		 * still program the pins in gmii mode: gmii0 pins in mode 1*/
    		val = PAD235_CNTRL; /*rgmii0_rxc*/
    		PAD235_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD236_CNTRL; /*rgmii0_rxctl*/
    		PAD236_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD237_CNTRL; /*rgmii0_rxd[2]*/
    		PAD237_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD238_CNTRL; /*rgmii0_txctl*/
    		PAD238_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD239_CNTRL; /*rgmii0_txc*/
    		PAD239_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD240_CNTRL; /*rgmii0_txd[0]*/
    		PAD240_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD241_CNTRL; /*rgmii0_rxd[0]*/
    		PAD241_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD242_CNTRL; /*rgmii0_rxd[1]*/
    		PAD242_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD243_CNTRL; /*rgmii1_rxctl*/
    		PAD243_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD244_CNTRL; /*rgmii0_rxd[3]*/
    		PAD244_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD245_CNTRL; /*rgmii0_txd[3]*/
    		PAD245_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD246_CNTRL; /*rgmii0_txd[2]*/
    		PAD246_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD247_CNTRL; /*rgmii0_txd[1]*/
    		PAD247_CNTRL = (volatile unsigned int) BIT(0);
    		val = PAD248_CNTRL; /*rgmii1_rxd[1]*/
    		PAD248_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD249_CNTRL; /*rgmii1_rxc*/
    		PAD249_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD250_CNTRL; /*rgmii1_rxd[3]*/
    		PAD250_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD251_CNTRL; /*rgmii1_txd[1]*/
    		PAD251_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD252_CNTRL; /*rgmii1_txctl*/
    		PAD252_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD253_CNTRL; /*rgmii1_txd[0]*/
    		PAD253_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD254_CNTRL; /*rgmii1_txd[2]*/
    		PAD254_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD255_CNTRL; /*rgmii1_txc*/
    		PAD255_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD256_CNTRL; /*rgmii1_rxd[0]*/
    		PAD256_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    		val = PAD257_CNTRL; /*rgmii1_txd[3]*/
    		PAD257_CNTRL = (volatile unsigned int) (BIT(0));
    		val = PAD258_CNTRL; /*rgmii1_rxd[2]*/
    		PAD258_CNTRL = (volatile unsigned int) (BIT(18) | BIT(0));
    	}
    }
    
    struct nor_pad_config {
    	unsigned int offset;
    	unsigned int value;
    };
    
    static struct nor_pad_config nor_pad_cfg[] = {
    		{GPMC_D0, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D1, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D2, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D3, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D4, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D5, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D6, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D7, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D8, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D9, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D10, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D11, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D12, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D13, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D14, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_D15, MODE(1) | INPUT_EN | PULL_DIS},
    		{GPMC_A1, MODE(2) | PULL_UP_EN},
    		{GPMC_A2, MODE(2) | PULL_UP_EN},
    		{GPMC_A3, MODE(2) | PULL_UP_EN},
    		{GPMC_A4, MODE(2) | PULL_UP_EN},
    		{GPMC_A5, MODE(5) | PULL_UP_EN},
    		{GPMC_A6, MODE(5)},
    		{GPMC_A7, MODE(5)},
    		{GPMC_A8, MODE(5)},
    		{GPMC_A9, MODE(5)},
    		{GPMC_A10, MODE(5) | PULL_UP_EN},
    		{GPMC_A11, MODE(5)},
    		{GPMC_A12, MODE(5)},
    		{GPMC_A13, MODE(2) | PULL_UP_EN},
    		{GPMC_A14, MODE(2) | PULL_UP_EN},
    		{GPMC_A15, MODE(2)},
    		{GPMC_A16, MODE(1)},
    		{GPMC_A17, MODE(1)},
    		{GPMC_A18, MODE(1)},
    		{GPMC_A19, MODE(1)},
    		{GPMC_A20, MODE(1) | PULL_UP_EN},
    		{GPMC_A21, MODE(1)},
    		{GPMC_A22, MODE(1) | PULL_UP_EN},
    		{GPMC_A23, MODE(1)},
    		{GPMC_A24, MODE(2) | PULL_UP_EN},
    		{GPMC_A25, MODE(2)},
    		{GPMC_A27, MODE(8) | PULL_UP_EN},
    		{GPMC_CS0_REG, MODE(1) | PULL_UP_EN},
    		{GPMC_OEN, MODE(1) | PULL_UP_EN},
    		{GPMC_WEN, MODE(1) | PULL_UP_EN},
    		{0},
    };
    
    /*********************************************************************
     *
     * nor_pad_config_mux - configure the pin mux for NOR
     *
     *********************************************************************/
    static void nor_pad_config_mux(void)
    {
    	u8 i = 0;
    
    	while (nor_pad_cfg[i].offset != 0x0) {
    		*(volatile u32 *)(nor_pad_cfg[i].offset) =
    			nor_pad_cfg[i].value;
    		i++;
    	}
    }
    
    /*
     * baord specific muxing of pins
     */
    void set_muxconf_regs(void)
    {
    	u32 i, add, val;
    	u32 pad_conf[] = {
    #include "mux.h"
    	};
    
    	for (i = 0; i<N_PINS; i++)
    	{
    		add = PIN_CTRL_BASE + (i*4);
    		val = __raw_readl(add);
    		val |= pad_conf[i];
    		__raw_writel(val, add);
    	}
    	/* MMC/SD pull-down enable */
    	__raw_writel(0x000C0040, 0x48140928);
    }
    
    void unlock_pll_control_mmr()
    {
    	/* ??? */
    	__raw_writel(0x1EDA4C3D, 0x481C5040);
    	__raw_writel(0x2FF1AC2B, 0x48140060);
    	__raw_writel(0xF757FDC0, 0x48140064);
    	__raw_writel(0xE2BC3A6D, 0x48140068);
    	__raw_writel(0x1EBF131D, 0x4814006c);
    	__raw_writel(0x6F361E05, 0x48140070);
    
    }
    
    /*
     * early system init of muxing and clocks.
     */
    void s_init(u32 in_ddr)
    {
    	/* TODO: Revisit enabling of I/D-cache in 1st stage */
    #if 0
    	icache_enable();
    	dcache_enable();
    #endif
    
    	/*
    	 * Disable Write Allocate on miss to avoid starvation of other masters
    	 * (than A8).
    	 *
    	 * Ref DM814x Erratum: TODO
    	 */
    	l2_disable_wa();
    
    	/* Can be removed as A8 comes up with L2 enabled */
    	l2_cache_enable();
    	unlock_pll_control_mmr();
    	/* Setup the PLLs and the clocks for the peripherals */
    	prcm_init(in_ddr);
    #if defined(CONFIG_TI814X_CONFIG_DDR)
    	if (!in_ddr)
    		config_ti814x_ddr();	/* Do DDR settings */
    #endif
    }
    
    /*
     * Reset the board
     */
    void reset_cpu (ulong addr)
    {
    	addr = __raw_readl(PRM_DEVICE_RSTCTRL);
    	addr &= ~BIT(1);
    	addr |= BIT(1);
    	__raw_writel(addr, PRM_DEVICE_RSTCTRL);
    }
    
    #ifdef CONFIG_DRIVER_TI_CPSW
    
    #define PHY_CONF_REG           22
    #define PHY_CONF_TXCLKEN       (1 << 5)
    
    /* TODO : Check for the board specific PHY */
    static void phy_init(char *name, int addr)
    {
    	unsigned short val;
    	unsigned int   cntr = 0;
    
    	miiphy_reset(name, addr);
    
    	udelay(100000);
    
    	/* Enable PHY to clock out TX_CLK */
    	miiphy_read(name, addr, PHY_CONF_REG, &val);
    	val |= PHY_CONF_TXCLKEN;
    	miiphy_write(name, addr, PHY_CONF_REG, val);
    	miiphy_read(name, addr, PHY_CONF_REG, &val);
    
    	/* Enable Autonegotiation */
    	if (miiphy_read(name, addr, PHY_BMCR, &val) != 0) {
    		printf("failed to read bmcr\n");
    		return;
    	}
    	val |= PHY_BMCR_DPLX | PHY_BMCR_AUTON | PHY_BMCR_100_MBPS;
    	if (miiphy_write(name, addr, PHY_BMCR, val) != 0) {
    		printf("failed to write bmcr\n");
    		return;
    	}
    	miiphy_read(name, addr, PHY_BMCR, &val);
    
    	/* Setup GIG advertisement */
    	miiphy_read(name, addr, PHY_1000BTCR, &val);
    	val |= PHY_1000BTCR_1000FD;
    	val &= ~PHY_1000BTCR_1000HD;
    	miiphy_write(name, addr, PHY_1000BTCR, val);
    	miiphy_read(name, addr, PHY_1000BTCR, &val);
    
    	/* Setup general advertisement */
    	if (miiphy_read(name, addr, PHY_ANAR, &val) != 0) {
    		printf("failed to read anar\n");
    		return;
    	}
    	val |= (PHY_ANLPAR_10 | PHY_ANLPAR_10FD | PHY_ANLPAR_TX |
    		PHY_ANLPAR_TXFD);
    	if (miiphy_write(name, addr, PHY_ANAR, val) != 0) {
    		printf("failed to write anar\n");
    		return;
    	}
    	miiphy_read(name, addr, PHY_ANAR, &val);
    
    	/* Restart auto negotiation*/
    	miiphy_read(name, addr, PHY_BMCR, &val);
    	val |= PHY_BMCR_RST_NEG;
    	miiphy_write(name, addr, PHY_BMCR, val);
    
    	/*check AutoNegotiate complete - it can take upto 3 secs*/
    	do {
    		udelay(40000);
    		cntr++;
    
    		if (!miiphy_read(name, addr, PHY_BMSR, &val)) {
    			if (val & PHY_BMSR_AUTN_COMP)
    				break;
    		}
    	} while (cntr < 250);
    
    	if (!miiphy_read(name, addr, PHY_BMSR, &val)) {
    		if (!(val & PHY_BMSR_AUTN_COMP))
    			printf("Auto negotitation failed\n");
    	}
    }
    
    static void cpsw_control(int enabled)
    {
    	/* nothing for now */
    	/* TODO : VTP was here before */
    }
    
    static struct cpsw_slave_data cpsw_slaves[] = {
    	{
    		.slave_reg_ofs  = 0x50,
    		.sliver_reg_ofs = 0x700,
    		.phy_id         = 1,
    	},
    	{
    		.slave_reg_ofs  = 0x90,
    		.sliver_reg_ofs = 0x740,
    		.phy_id         = 0,
    	},
    };
    
    static struct cpsw_platform_data cpsw_data = {
    	.mdio_base		= TI814X_CPSW_MDIO_BASE,
    	.cpsw_base		= TI814X_CPSW_BASE,
    	.mdio_div		= 0xff,
    	.channels		= 8,
    	.cpdma_reg_ofs		= 0x100,
    	.slaves			= 1,
    	.slave_data		= cpsw_slaves,
    	.ale_reg_ofs		= 0x600,
    	.ale_entries		= 1024,
    	.host_port_reg_ofs	= 0x28,
    	.hw_stats_reg_ofs	= 0x400,
    	.mac_control		= (1 << 5) /* MIIEN      */,
    	.control		= cpsw_control,
    	.phy_init		= phy_init,
    	.host_port_num		= 0,
    };
    
    extern void cpsw_eth_set_mac_addr (const u_int8_t *addr);
    
    int board_eth_init(bd_t *bis)
    {
    	u_int8_t mac_addr[6];
    	u_int32_t mac_hi,mac_lo;
    
    	cpsw_pad_config();
    
    	if (!eth_getenv_enetaddr("ethaddr", mac_addr)) {
    		char mac_addr_env[20];
    
    		printf("<ethaddr> not set. Reading from E-fuse\n");
    		/* try reading mac address from efuse */
    		mac_lo = __raw_readl(MAC_ID0_LO);
    		mac_hi = __raw_readl(MAC_ID0_HI);
    		mac_addr[0] = mac_hi & 0xFF;
    		mac_addr[1] = (mac_hi & 0xFF00) >> 8;
    		mac_addr[2] = (mac_hi & 0xFF0000) >> 16;
    		mac_addr[3] = (mac_hi & 0xFF000000) >> 24;
    		mac_addr[4] = mac_lo & 0xFF;
    		mac_addr[5] = (mac_lo & 0xFF00) >> 8;
    		/* set the ethaddr variable with MACID detected */
    		sprintf(mac_addr_env, "%02x:%02x:%02x:%02x:%02x:%02x",
    			mac_addr[0], mac_addr[1], mac_addr[2],
    			mac_addr[3], mac_addr[4], mac_addr[5]);
    		setenv("ethaddr", mac_addr_env);
    	}
    
    	if(is_valid_ether_addr(mac_addr)) {
    		printf("Detected MACID:%x:%x:%x:%x:%x:%x\n",mac_addr[0],
    			mac_addr[1], mac_addr[2], mac_addr[3],
    			mac_addr[4], mac_addr[5]);
    		cpsw_eth_set_mac_addr(mac_addr);
    	} else {
    		printf("Caution:using static MACID!! Set <ethaddr> variable\n");
    	}
    
    	if (PG1_0 != get_cpu_rev()) {
    		cpsw_slaves[0].phy_id = 0;
    		cpsw_slaves[1].phy_id = 1;
    	}
    
    	return cpsw_register(&cpsw_data);
    }
    #endif
    
    #ifdef CONFIG_NAND_TI81XX
    /******************************************************************************
     * Command to switch between NAND HW and SW ecc
     *****************************************************************************/
    extern void ti81xx_nand_switch_ecc(nand_ecc_modes_t hardware, int32_t mode);
    static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
    {
    	int type = 0;
    	if (argc < 2)
    		goto usage;
    
    	if (strncmp(argv[1], "hw", 2) == 0) {
    		if (argc == 3)
    			type = simple_strtoul(argv[2], NULL, 10);
    		ti81xx_nand_switch_ecc(NAND_ECC_HW, type);
    	}
    	else if (strncmp(argv[1], "sw", 2) == 0)
    		ti81xx_nand_switch_ecc(NAND_ECC_SOFT, 0);
    	else
    		goto usage;
    
    	return 0;
    
    usage:
    	printf ("Usage: nandecc %s\n", cmdtp->usage);
    	return 1;
    }
    
    U_BOOT_CMD(
    	nandecc, 3, 1,	do_switch_ecc,
    	"Switch NAND ECC calculation algorithm b/w hardware and software",
    	"[sw|hw <hw_type>] \n"
    	"   [sw|hw]- Switch b/w hardware(hw) & software(sw) ecc algorithm\n"
    	"   hw_type- 0 for Hamming code\n"
    	"            1 for bch4\n"
    	"            2 for bch8\n"
    	"            3 for bch16\n"
    );
    
    #endif /* CONFIG_NAND_TI81XX */
    
    #ifdef CONFIG_GENERIC_MMC
    int board_mmc_init(bd_t *bis)
    {
            omap_mmc_init(0);
            return 0;
    }
    #endif
    
    

    then in u-boot prompt, you will get UU_RTC command. which u can execute and reproduce the issue.

    Regards,

    Vimal

  • Vimal,

    When I run your RTC test on my side, I have:

    TI8148_EVM#UU_RTC

     RTC TEST 3.........

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     RTC TEST 4.........

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     RTC TEST OK.........

    Even some set_time fail messages, finally the RTC test is reported as "OK". While if I change the evm.c RTC registers like below, the "Month 6 boundary" test is reported as failed!

    evm.c

    /* Initialize Calender to day 1, 12:00:00 */
       /* __raw_writel(0x00, base + SECONDS_REG); //SECONDS_REG = 0x01;                    
        __raw_writel(0x00, base + MINUTES_REG); //MINUTES_REG = 0x30;                    
        __raw_writel(0x01, base + HOURS_REG); //HOURS_REG = 0x01;
        __raw_writel(0x01, base + DAYS_REG); //DAYS_REG = 0x08;
        __raw_writel(0x01, base + MONTHS_REG); //MONTHS_REG = 0x07;
        __raw_writel(0x63, base + YEARS_REG); //YEARS_REG  = 0x84;
        __raw_writel(0x01, base + WEEK_REG); //WEEK_REG  = 0x01; */

        __raw_writel(0x01, base + SECONDS_REG); //SECONDS_REG = 0x01;                    
        __raw_writel(0x30, base + MINUTES_REG); //MINUTES_REG = 0x30;                    
        __raw_writel(0x01, base + HOURS_REG); //HOURS_REG = 0x01;
        __raw_writel(0x08, base + DAYS_REG); //DAYS_REG = 0x08;
        __raw_writel(0x07, base + MONTHS_REG); //MONTHS_REG = 0x07;
        __raw_writel(0x84, base + YEARS_REG); //YEARS_REG  = 0x84;
        __raw_writel(0x01, base + WEEK_REG); //WEEK_REG  = 0x01;

    TI8148_EVM#UU_RTC

     RTC TEST 3.........

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time

     Failed in omap_rtc_set_time
    Month 6 boundary is not passed !


    Best regards,
    Pavel

  • Vimal,

    I also found we have RTC CCS test for the DM816x device, which can be re-use for the DM814x u-boot. I am attaching it, in case you are interested: 1033.rtc.tar.gz

    Also we have some RTC guidelines in ti-ezsdk_dm814x-evm_5_05_02_00/board-support/linux-2.6.37-psp04.04.00.01/Documentation/rtc.txt

    Regards,
    Pavel