1 /* 2 * (C) Copyright 2007 3 * Sascha Hauer, Pengutronix 4 * 5 * (C) Copyright 2008-2009 Freescale Semiconductor, Inc. 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 #include <common.h> 27 #include <asm/io.h> 28 #include <asm/arch/imx-regs.h> 29 30 /* General purpose timers bitfields */ 31 #define GPTCR_SWR (1<<15) /* Software reset */ 32 #define GPTCR_FRR (1<<9) /* Freerun / restart */ 33 #define GPTCR_CLKSOURCE_32 (0x100<<6) /* Clock source */ 34 #define GPTCR_CLKSOURCE_IPG (0x001<<6) /* Clock source */ 35 #define GPTCR_TEN (1) /* Timer enable */ 36 #define GPTPR_VAL (66) 37 38 int timer_init(void) 39 { 40 int i; 41 struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; 42 43 /* setup GP Timer 1 */ 44 writel(GPTCR_SWR, &gpt->ctrl); 45 for (i = 0; i < 100; i++) 46 writel(0, &gpt->ctrl); /* We have no udelay by now */ 47 48 writel(GPTPR_VAL, &gpt->pre); 49 /* Freerun Mode, PERCLK1 input */ 50 writel(readl(&gpt->ctrl) | 51 GPTCR_CLKSOURCE_IPG | GPTCR_TEN, 52 &gpt->ctrl); 53 54 return 0; 55 } 56 57 void reset_timer_masked(void) 58 { 59 struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; 60 61 writel(0, &gpt->ctrl); 62 /* Freerun Mode, PERCLK1 input */ 63 writel(GPTCR_CLKSOURCE_IPG | GPTCR_TEN, 64 &gpt->ctrl); 65 } 66 67 inline ulong get_timer_masked(void) 68 { 69 70 struct gpt_regs *gpt = (struct gpt_regs *)GPT1_BASE_ADDR; 71 ulong val = readl(&gpt->counter); 72 73 return val; 74 } 75 76 ulong get_timer(ulong base) 77 { 78 ulong tmp; 79 80 tmp = get_timer_masked(); 81 82 if (tmp <= (base * 1000)) { 83 /* Overflow */ 84 tmp += (0xffffffff - base); 85 } 86 87 return (tmp / 1000) - base; 88 } 89 90 /* 91 * delay x useconds AND preserve advance timstamp value 92 * GPTCNT is now supposed to tick 1 by 1 us. 93 */ 94 void __udelay(unsigned long usec) 95 { 96 ulong tmp; 97 98 tmp = get_timer_masked(); /* get current timestamp */ 99 100 /* if setting this forward will roll time stamp */ 101 if ((usec + tmp + 1) < tmp) { 102 /* reset "advancing" timestamp to 0, set lastinc value */ 103 reset_timer_masked(); 104 } else { 105 /* else, set advancing stamp wake up time */ 106 tmp += usec; 107 } 108 109 while (get_timer_masked() < tmp) /* loop till event */ 110 /*NOP*/; 111 } 112