16c08d5dcSPrafulla Wadaskar /* 26c08d5dcSPrafulla Wadaskar * (C) Copyright 2010 36c08d5dcSPrafulla Wadaskar * Marvell Semiconductor <www.marvell.com> 46c08d5dcSPrafulla Wadaskar * Written-by: Prafulla Wadaskar <prafulla@marvell.com> 56c08d5dcSPrafulla Wadaskar * Contributor: Mahavir Jain <mjain@marvell.com> 66c08d5dcSPrafulla Wadaskar * 76c08d5dcSPrafulla Wadaskar * See file CREDITS for list of people who contributed to this 86c08d5dcSPrafulla Wadaskar * project. 96c08d5dcSPrafulla Wadaskar * 106c08d5dcSPrafulla Wadaskar * This program is free software; you can redistribute it and/or 116c08d5dcSPrafulla Wadaskar * modify it under the terms of the GNU General Public License as 126c08d5dcSPrafulla Wadaskar * published by the Free Software Foundation; either version 2 of 136c08d5dcSPrafulla Wadaskar * the License, or (at your option) any later version. 146c08d5dcSPrafulla Wadaskar * 156c08d5dcSPrafulla Wadaskar * This program is distributed in the hope that it will be useful, 166c08d5dcSPrafulla Wadaskar * but WITHOUT ANY WARRANTY; without even the implied warranty of 176c08d5dcSPrafulla Wadaskar * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 186c08d5dcSPrafulla Wadaskar * GNU General Public License for more details. 196c08d5dcSPrafulla Wadaskar * 206c08d5dcSPrafulla Wadaskar * You should have received a copy of the GNU General Public License 216c08d5dcSPrafulla Wadaskar * along with this program; if not, write to the Free Software 226c08d5dcSPrafulla Wadaskar * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 236c08d5dcSPrafulla Wadaskar * MA 02110-1301 USA 246c08d5dcSPrafulla Wadaskar */ 256c08d5dcSPrafulla Wadaskar 266c08d5dcSPrafulla Wadaskar #include <common.h> 27ab1b9552SLei Wen #include <asm/arch/cpu.h> 286c08d5dcSPrafulla Wadaskar #include <asm/arch/armada100.h> 296c08d5dcSPrafulla Wadaskar 306c08d5dcSPrafulla Wadaskar /* 316c08d5dcSPrafulla Wadaskar * Timer registers 326c08d5dcSPrafulla Wadaskar * Refer Section A.6 in Datasheet 336c08d5dcSPrafulla Wadaskar */ 346c08d5dcSPrafulla Wadaskar struct armd1tmr_registers { 356c08d5dcSPrafulla Wadaskar u32 clk_ctrl; /* Timer clk control reg */ 366c08d5dcSPrafulla Wadaskar u32 match[9]; /* Timer match registers */ 376c08d5dcSPrafulla Wadaskar u32 count[3]; /* Timer count registers */ 386c08d5dcSPrafulla Wadaskar u32 status[3]; 396c08d5dcSPrafulla Wadaskar u32 ie[3]; 406c08d5dcSPrafulla Wadaskar u32 preload[3]; /* Timer preload value */ 416c08d5dcSPrafulla Wadaskar u32 preload_ctrl[3]; 426c08d5dcSPrafulla Wadaskar u32 wdt_match_en; 436c08d5dcSPrafulla Wadaskar u32 wdt_match_r; 446c08d5dcSPrafulla Wadaskar u32 wdt_val; 456c08d5dcSPrafulla Wadaskar u32 wdt_sts; 466c08d5dcSPrafulla Wadaskar u32 icr[3]; 476c08d5dcSPrafulla Wadaskar u32 wdt_icr; 486c08d5dcSPrafulla Wadaskar u32 cer; /* Timer count enable reg */ 496c08d5dcSPrafulla Wadaskar u32 cmr; 506c08d5dcSPrafulla Wadaskar u32 ilr[3]; 516c08d5dcSPrafulla Wadaskar u32 wcr; 526c08d5dcSPrafulla Wadaskar u32 wfar; 536c08d5dcSPrafulla Wadaskar u32 wsar; 546c08d5dcSPrafulla Wadaskar u32 cvwr; 556c08d5dcSPrafulla Wadaskar }; 566c08d5dcSPrafulla Wadaskar 576c08d5dcSPrafulla Wadaskar #define TIMER 0 /* Use TIMER 0 */ 586c08d5dcSPrafulla Wadaskar /* Each timer has 3 match registers */ 596c08d5dcSPrafulla Wadaskar #define MATCH_CMP(x) ((3 * TIMER) + x) 606c08d5dcSPrafulla Wadaskar #define TIMER_LOAD_VAL 0xffffffff 616c08d5dcSPrafulla Wadaskar #define COUNT_RD_REQ 0x1 626c08d5dcSPrafulla Wadaskar 636c08d5dcSPrafulla Wadaskar DECLARE_GLOBAL_DATA_PTR; 64*8ff43b03SSimon Glass /* Using gd->arch.tbu from timestamp and gd->tbl for lastdec */ 656c08d5dcSPrafulla Wadaskar 666c08d5dcSPrafulla Wadaskar /* For preventing risk of instability in reading counter value, 676c08d5dcSPrafulla Wadaskar * first set read request to register cvwr and then read same 686c08d5dcSPrafulla Wadaskar * register after it captures counter value. 696c08d5dcSPrafulla Wadaskar */ 706c08d5dcSPrafulla Wadaskar ulong read_timer(void) 716c08d5dcSPrafulla Wadaskar { 726c08d5dcSPrafulla Wadaskar struct armd1tmr_registers *armd1timers = 736c08d5dcSPrafulla Wadaskar (struct armd1tmr_registers *) ARMD1_TIMER_BASE; 746c08d5dcSPrafulla Wadaskar volatile int loop=100; 756c08d5dcSPrafulla Wadaskar 766c08d5dcSPrafulla Wadaskar writel(COUNT_RD_REQ, &armd1timers->cvwr); 776c08d5dcSPrafulla Wadaskar while (loop--); 786c08d5dcSPrafulla Wadaskar return(readl(&armd1timers->cvwr)); 796c08d5dcSPrafulla Wadaskar } 806c08d5dcSPrafulla Wadaskar 816c08d5dcSPrafulla Wadaskar ulong get_timer_masked(void) 826c08d5dcSPrafulla Wadaskar { 836c08d5dcSPrafulla Wadaskar ulong now = read_timer(); 846c08d5dcSPrafulla Wadaskar 856c08d5dcSPrafulla Wadaskar if (now >= gd->tbl) { 866c08d5dcSPrafulla Wadaskar /* normal mode */ 87*8ff43b03SSimon Glass gd->arch.tbu += now - gd->tbl; 886c08d5dcSPrafulla Wadaskar } else { 896c08d5dcSPrafulla Wadaskar /* we have an overflow ... */ 90*8ff43b03SSimon Glass gd->arch.tbu += now + TIMER_LOAD_VAL - gd->tbl; 916c08d5dcSPrafulla Wadaskar } 926c08d5dcSPrafulla Wadaskar gd->tbl = now; 936c08d5dcSPrafulla Wadaskar 94*8ff43b03SSimon Glass return gd->arch.tbu; 956c08d5dcSPrafulla Wadaskar } 966c08d5dcSPrafulla Wadaskar 976c08d5dcSPrafulla Wadaskar ulong get_timer(ulong base) 986c08d5dcSPrafulla Wadaskar { 996c08d5dcSPrafulla Wadaskar return ((get_timer_masked() / (CONFIG_SYS_HZ_CLOCK / 1000)) - 1006c08d5dcSPrafulla Wadaskar base); 1016c08d5dcSPrafulla Wadaskar } 1026c08d5dcSPrafulla Wadaskar 1036c08d5dcSPrafulla Wadaskar void __udelay(unsigned long usec) 1046c08d5dcSPrafulla Wadaskar { 1056c08d5dcSPrafulla Wadaskar ulong delayticks; 1066c08d5dcSPrafulla Wadaskar ulong endtime; 1076c08d5dcSPrafulla Wadaskar 1086c08d5dcSPrafulla Wadaskar delayticks = (usec * (CONFIG_SYS_HZ_CLOCK / 1000000)); 1096c08d5dcSPrafulla Wadaskar endtime = get_timer_masked() + delayticks; 1106c08d5dcSPrafulla Wadaskar 1116c08d5dcSPrafulla Wadaskar while (get_timer_masked() < endtime); 1126c08d5dcSPrafulla Wadaskar } 1136c08d5dcSPrafulla Wadaskar 1146c08d5dcSPrafulla Wadaskar /* 1156c08d5dcSPrafulla Wadaskar * init the Timer 1166c08d5dcSPrafulla Wadaskar */ 1176c08d5dcSPrafulla Wadaskar int timer_init(void) 1186c08d5dcSPrafulla Wadaskar { 1196c08d5dcSPrafulla Wadaskar struct armd1apb1_registers *apb1clkres = 1206c08d5dcSPrafulla Wadaskar (struct armd1apb1_registers *) ARMD1_APBC1_BASE; 1216c08d5dcSPrafulla Wadaskar struct armd1tmr_registers *armd1timers = 1226c08d5dcSPrafulla Wadaskar (struct armd1tmr_registers *) ARMD1_TIMER_BASE; 1236c08d5dcSPrafulla Wadaskar 1246c08d5dcSPrafulla Wadaskar /* Enable Timer clock at 3.25 MHZ */ 1256c08d5dcSPrafulla Wadaskar writel(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3), &apb1clkres->timers); 1266c08d5dcSPrafulla Wadaskar 1276c08d5dcSPrafulla Wadaskar /* load value into timer */ 1286c08d5dcSPrafulla Wadaskar writel(0x0, &armd1timers->clk_ctrl); 1296c08d5dcSPrafulla Wadaskar /* Use Timer 0 Match Resiger 0 */ 1306c08d5dcSPrafulla Wadaskar writel(TIMER_LOAD_VAL, &armd1timers->match[MATCH_CMP(0)]); 1316c08d5dcSPrafulla Wadaskar /* Preload value is 0 */ 1326c08d5dcSPrafulla Wadaskar writel(0x0, &armd1timers->preload[TIMER]); 1336c08d5dcSPrafulla Wadaskar /* Enable match comparator 0 for Timer 0 */ 1346c08d5dcSPrafulla Wadaskar writel(0x1, &armd1timers->preload_ctrl[TIMER]); 1356c08d5dcSPrafulla Wadaskar 1366c08d5dcSPrafulla Wadaskar /* Enable timer 0 */ 1376c08d5dcSPrafulla Wadaskar writel(0x1, &armd1timers->cer); 138*8ff43b03SSimon Glass /* init the gd->arch.tbu and gd->tbl value */ 13917659d7dSGraeme Russ gd->tbl = read_timer(); 140*8ff43b03SSimon Glass gd->arch.tbu = 0; 1416c08d5dcSPrafulla Wadaskar 1426c08d5dcSPrafulla Wadaskar return 0; 1436c08d5dcSPrafulla Wadaskar } 1446c08d5dcSPrafulla Wadaskar 1456c08d5dcSPrafulla Wadaskar #define MPMU_APRR_WDTR (1<<4) 1466c08d5dcSPrafulla Wadaskar #define TMR_WFAR 0xbaba /* WDT Register First key */ 1476c08d5dcSPrafulla Wadaskar #define TMP_WSAR 0xeb10 /* WDT Register Second key */ 1486c08d5dcSPrafulla Wadaskar 1496c08d5dcSPrafulla Wadaskar /* 1506c08d5dcSPrafulla Wadaskar * This function uses internal Watchdog Timer 1516c08d5dcSPrafulla Wadaskar * based reset mechanism. 1526c08d5dcSPrafulla Wadaskar * Steps to write watchdog registers (protected access) 1536c08d5dcSPrafulla Wadaskar * 1. Write key value to TMR_WFAR reg. 1546c08d5dcSPrafulla Wadaskar * 2. Write key value to TMP_WSAR reg. 1556c08d5dcSPrafulla Wadaskar * 3. Perform write operation. 1566c08d5dcSPrafulla Wadaskar */ 1576c08d5dcSPrafulla Wadaskar void reset_cpu (unsigned long ignored) 1586c08d5dcSPrafulla Wadaskar { 1596c08d5dcSPrafulla Wadaskar struct armd1mpmu_registers *mpmu = 1606c08d5dcSPrafulla Wadaskar (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; 1616c08d5dcSPrafulla Wadaskar struct armd1tmr_registers *armd1timers = 1626c08d5dcSPrafulla Wadaskar (struct armd1tmr_registers *) ARMD1_TIMER_BASE; 1636c08d5dcSPrafulla Wadaskar u32 val; 1646c08d5dcSPrafulla Wadaskar 1656c08d5dcSPrafulla Wadaskar /* negate hardware reset to the WDT after system reset */ 1666c08d5dcSPrafulla Wadaskar val = readl(&mpmu->aprr); 1676c08d5dcSPrafulla Wadaskar val = val | MPMU_APRR_WDTR; 1686c08d5dcSPrafulla Wadaskar writel(val, &mpmu->aprr); 1696c08d5dcSPrafulla Wadaskar 1706c08d5dcSPrafulla Wadaskar /* reset/enable WDT clock */ 1716c08d5dcSPrafulla Wadaskar writel(APBC_APBCLK | APBC_FNCLK | APBC_RST, &mpmu->wdtpcr); 1726c08d5dcSPrafulla Wadaskar readl(&mpmu->wdtpcr); 1736c08d5dcSPrafulla Wadaskar writel(APBC_APBCLK | APBC_FNCLK, &mpmu->wdtpcr); 1746c08d5dcSPrafulla Wadaskar readl(&mpmu->wdtpcr); 1756c08d5dcSPrafulla Wadaskar 1766c08d5dcSPrafulla Wadaskar /* clear previous WDT status */ 1776c08d5dcSPrafulla Wadaskar writel(TMR_WFAR, &armd1timers->wfar); 1786c08d5dcSPrafulla Wadaskar writel(TMP_WSAR, &armd1timers->wsar); 1796c08d5dcSPrafulla Wadaskar writel(0, &armd1timers->wdt_sts); 1806c08d5dcSPrafulla Wadaskar 1816c08d5dcSPrafulla Wadaskar /* set match counter */ 1826c08d5dcSPrafulla Wadaskar writel(TMR_WFAR, &armd1timers->wfar); 1836c08d5dcSPrafulla Wadaskar writel(TMP_WSAR, &armd1timers->wsar); 1846c08d5dcSPrafulla Wadaskar writel(0xf, &armd1timers->wdt_match_r); 1856c08d5dcSPrafulla Wadaskar 1866c08d5dcSPrafulla Wadaskar /* enable WDT reset */ 1876c08d5dcSPrafulla Wadaskar writel(TMR_WFAR, &armd1timers->wfar); 1886c08d5dcSPrafulla Wadaskar writel(TMP_WSAR, &armd1timers->wsar); 1896c08d5dcSPrafulla Wadaskar writel(0x3, &armd1timers->wdt_match_en); 1906c08d5dcSPrafulla Wadaskar 1916c08d5dcSPrafulla Wadaskar while(1); 1926c08d5dcSPrafulla Wadaskar } 19396f5c4b2SPrafulla Wadaskar 19496f5c4b2SPrafulla Wadaskar /* 19596f5c4b2SPrafulla Wadaskar * This function is derived from PowerPC code (read timebase as long long). 19696f5c4b2SPrafulla Wadaskar * On ARM it just returns the timer value. 19796f5c4b2SPrafulla Wadaskar */ 19896f5c4b2SPrafulla Wadaskar unsigned long long get_ticks(void) 19996f5c4b2SPrafulla Wadaskar { 20096f5c4b2SPrafulla Wadaskar return get_timer(0); 20196f5c4b2SPrafulla Wadaskar } 20296f5c4b2SPrafulla Wadaskar 20396f5c4b2SPrafulla Wadaskar /* 20496f5c4b2SPrafulla Wadaskar * This function is derived from PowerPC code (timebase clock frequency). 20596f5c4b2SPrafulla Wadaskar * On ARM it returns the number of timer ticks per second. 20696f5c4b2SPrafulla Wadaskar */ 20796f5c4b2SPrafulla Wadaskar ulong get_tbclk (void) 20896f5c4b2SPrafulla Wadaskar { 20996f5c4b2SPrafulla Wadaskar return (ulong)CONFIG_SYS_HZ; 21096f5c4b2SPrafulla Wadaskar } 211