diff options
| author | 2013-09-04 14:38:24 +0000 | |
|---|---|---|
| committer | 2013-09-04 14:38:24 +0000 | |
| commit | 8eda2d14dce8aa0e7fb004c223d2283029a448b3 (patch) | |
| tree | ff1ec5619e69ff29fba97c49ba91f60a39272972 /sys/arch/beagle/dev/gptimer.c | |
| parent | time_t and random fixes from NSD upstream, ok deraadt@ (diff) | |
| download | wireguard-openbsd-8eda2d14dce8aa0e7fb004c223d2283029a448b3.tar.xz wireguard-openbsd-8eda2d14dce8aa0e7fb004c223d2283029a448b3.zip | |
In the future, we shouldn't have one port port ARM SoC, that's just
ridiculous. This is the first step for a common and generic ARM port
for ARMv7 SoCs.
Diffstat (limited to 'sys/arch/beagle/dev/gptimer.c')
| -rw-r--r-- | sys/arch/beagle/dev/gptimer.c | 441 |
1 files changed, 0 insertions, 441 deletions
diff --git a/sys/arch/beagle/dev/gptimer.c b/sys/arch/beagle/dev/gptimer.c deleted file mode 100644 index 714bfb00ba1..00000000000 --- a/sys/arch/beagle/dev/gptimer.c +++ /dev/null @@ -1,441 +0,0 @@ -/* $OpenBSD: gptimer.c,v 1.13 2013/05/09 13:40:38 patrick Exp $ */ -/* - * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * WARNING - this timer initializion has not been checked - * to see if it will do _ANYTHING_ sane if the omap enters - * low power mode. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/time.h> -#include <sys/evcount.h> -#include <sys/device.h> -#include <sys/timetc.h> -#include <dev/clock_subr.h> -#include <machine/bus.h> -#include <beagle/dev/omapvar.h> -#include <beagle/dev/prcmvar.h> - -#include <machine/intr.h> -#include <arm/cpufunc.h> - -/* registers */ -#define GP_TIDR 0x000 -#define GP_TIDR_REV 0xff -#define GP_TIOCP_CFG 0x010 -#define GP_TIOCP_CFG_CLKA 0x000000300 -#define GP_TIOCP_CFG_EMUFREE 0x000000020 -#define GP_TIOCP_CFG_IDLEMODE 0x000000018 -#define GP_TIOCP_CFG_ENAPWAKEUP 0x000000004 -#define GP_TIOCP_CFG_SOFTRESET 0x000000002 -#define GP_TIOCP_CFG_AUTOIDLE 0x000000001 -#define GP_TISTAT 0x014 -#define GP_TISTAT_RESETDONE 0x000000001 -#define GP_TISR 0x018 -#define GP_TISTAT_TCAR 0x00000004 -#define GP_TISTAT_OVF 0x00000002 -#define GP_TISTAT_MATCH 0x00000001 -#define GP_TIER 0x1c -#define GP_TIER_TCAR_EN 0x4 -#define GP_TIER_OVF_EN 0x2 -#define GP_TIER_MAT_EN 0x1 -#define GP_TWER 0x020 -#define GP_TWER_TCAR_EN 0x00000004 -#define GP_TWER_OVF_EN 0x00000002 -#define GP_TWER_MAT_EN 0x00000001 -#define GP_TCLR 0x024 -#define GP_TCLR_GPO (1<<14) -#define GP_TCLR_CAPT (1<<13) -#define GP_TCLR_PT (1<<12) -#define GP_TCLR_TRG (3<<10) -#define GP_TCLR_TRG_O (1<<10) -#define GP_TCLR_TRG_OM (2<<10) -#define GP_TCLR_TCM (3<<8) -#define GP_TCLR_TCM_RISE (1<<8) -#define GP_TCLR_TCM_FALL (2<<8) -#define GP_TCLR_TCM_BOTH (3<<8) -#define GP_TCLR_SCPWM (1<<7) -#define GP_TCLR_CE (1<<6) -#define GP_TCLR_PRE (1<<5) -#define GP_TCLR_PTV (7<<2) -#define GP_TCLR_AR (1<<1) -#define GP_TCLR_ST (1<<0) -#define GP_TCRR 0x028 /* counter */ -#define GP_TLDR 0x02c /* reload */ -#define GP_TTGR 0x030 -#define GP_TWPS 0x034 -#define GP_TWPS_TCLR 0x01 -#define GP_TWPS_TCRR 0x02 -#define GP_TWPS_TLDR 0x04 -#define GP_TWPS_TTGR 0x08 -#define GP_TWPS_TMAR 0x10 -#define GP_TWPS_ALL 0x1f -#define GP_TMAR 0x038 -#define GP_TCAR 0x03C -#define GP_TSICR 0x040 -#define GP_TSICR_POSTED 0x00000002 -#define GP_TSICR_SFT 0x00000001 -#define GP_TCAR2 0x044 - -#define TIMER_FREQUENCY 32768 /* 32kHz is used, selectable */ - -static struct evcount clk_count; -static struct evcount stat_count; -#define GPT1_IRQ 38 -#define GPTIMER0_IRQ 38 - -//static int clk_irq = GPT1_IRQ; /* XXX 37 */ - -void gptimer_attach(struct device *parent, struct device *self, void *args); -int gptimer_intr(void *frame); -void gptimer_wait(int reg); -void gptimer_cpu_initclocks(void); -void gptimer_delay(u_int); -void gptimer_setstatclockrate(int newhz); - -bus_space_tag_t gptimer_iot; -bus_space_handle_t gptimer_ioh0, gptimer_ioh1; -int gptimer_irq = 0; - -u_int gptimer_get_timecount(struct timecounter *); - -static struct timecounter gptimer_timecounter = { - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL -}; - -volatile u_int32_t nexttickevent; -volatile u_int32_t nextstatevent; -u_int32_t ticks_per_second; -u_int32_t ticks_per_intr; -u_int32_t ticks_err_cnt; -u_int32_t ticks_err_sum; -u_int32_t statvar, statmin; - -struct cfattach gptimer_ca = { - sizeof (struct device), NULL, gptimer_attach -}; - -struct cfdriver gptimer_cd = { - NULL, "gptimer", DV_DULL -}; - -void -gptimer_attach(struct device *parent, struct device *self, void *args) -{ - struct omap_attach_args *oa = args; - bus_space_handle_t ioh; - u_int32_t rev; - - gptimer_iot = oa->oa_iot; - if (bus_space_map(gptimer_iot, oa->oa_dev->mem[0].addr, - oa->oa_dev->mem[0].size, 0, &ioh)) - panic("gptimer_attach: bus_space_map failed!"); - - rev = bus_space_read_4(gptimer_iot, ioh, GP_TIDR); - - printf(" rev %d.%d\n", rev >> 4 & 0xf, rev & 0xf); - if (self->dv_unit == 0) { - gptimer_ioh0 = ioh; - gptimer_irq = oa->oa_dev->irq[0]; - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, 0); - } else if (self->dv_unit == 1) { - /* start timer because it is used in delay */ - gptimer_ioh1 = ioh; - bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCRR, 0); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TLDR, 0); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh1, GP_TCLR, - GP_TCLR_AR | GP_TCLR_ST); - gptimer_wait(GP_TWPS_ALL); - - gptimer_timecounter.tc_frequency = TIMER_FREQUENCY; - tc_init(&gptimer_timecounter); - } - else - panic("attaching too many gptimers at 0x%x", - oa->oa_dev->mem[0].addr); - - arm_clock_register(gptimer_cpu_initclocks, gptimer_delay, - gptimer_setstatclockrate, NULL); -} - -/* - * See comment in arm/xscale/i80321_clock.c - * - * counter is count up, but with autoreload timers it is not possible - * to detect how many interrupts passed while interrupts were blocked. - * also it is not possible to atomically add to the register - * get get it to precisely fire at a non-fixed interval. - * - * To work around this two timers are used, GPT1 is used as a reference - * clock without reload , however we just ignore the interrupt it - * would (may?) generate. - * - * Internally this keeps track of when the next timer should fire - * and based on that time and the current value of the reference - * clock a number is written into the timer count register to schedule - * the next event. - */ - -int -gptimer_intr(void *frame) -{ - u_int32_t now, r; - u_int32_t nextevent, duration; - - /* clear interrupt */ - now = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); - - while ((int32_t) (nexttickevent - now) < 0) { - nexttickevent += ticks_per_intr; - ticks_err_sum += ticks_err_cnt; -#if 0 - if (ticks_err_sum > hz) { - u_int32_t match_error; - match_error = ticks_err_sum / hz - ticks_err_sum -= (match_error * hz); - } -#else - /* looping a few times is faster than divide */ - while (ticks_err_sum > hz) { - nexttickevent += 1; - ticks_err_sum -= hz; - } -#endif - clk_count.ec_count++; - hardclock(frame); - } - while ((int32_t) (nextstatevent - now) < 0) { - do { - r = random() & (statvar -1); - } while (r == 0); /* random == 0 not allowed */ - nextstatevent += statmin + r; - /* XXX - correct nextstatevent? */ - stat_count.ec_count++; - statclock(frame); - } - if ((now - nexttickevent) < (now - nextstatevent)) - nextevent = nexttickevent; - else - nextevent = nextstatevent; - -/* XXX */ - duration = nextevent - - bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); -#if 0 - printf("duration 0x%x %x %x\n", nextevent - - bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR), - bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TCRR), - bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR)); -#endif - - - if (duration <= 0) - duration = 1; /* trigger immediately. */ - - if (duration > ticks_per_intr) { - /* - * If interrupts are blocked too long, like during - * the root prompt or ddb, the timer can roll over, - * this will allow the system to continue to run - * even if time is lost. - */ - duration = ticks_per_intr; - nexttickevent = now; - nextstatevent = now; - } - - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR, - bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR)); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -duration); - - return 1; -} - -/* - * would be interesting to play with trigger mode while having one timer - * in 32KHz mode, and the other timer running in sysclk mode and use - * the high resolution speeds (matters more for delay than tick timer - */ - -void -gptimer_cpu_initclocks() -{ -// u_int32_t now; - stathz = 128; - profhz = 1024; - - ticks_per_second = TIMER_FREQUENCY; - - setstatclockrate(stathz); - - ticks_per_intr = ticks_per_second / hz; - ticks_err_cnt = ticks_per_second % hz; - ticks_err_sum = 0;; - - prcm_setclock(1, PRCM_CLK_SPEED_32); - prcm_setclock(2, PRCM_CLK_SPEED_32); - /* establish interrupts */ - arm_intr_establish(gptimer_irq, IPL_CLOCK, gptimer_intr, - NULL, "tick"); - - /* setup timer 0 (hardware timer 2) */ - /* reset? - XXX */ - - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TLDR, 0); - - nexttickevent = nextstatevent = bus_space_read_4(gptimer_iot, - gptimer_ioh1, GP_TCRR) + ticks_per_intr; - - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TIER, GP_TIER_OVF_EN); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TWER, GP_TWER_OVF_EN); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCLR, - GP_TCLR_AR | GP_TCLR_ST); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TISR, - bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TISR)); - gptimer_wait(GP_TWPS_ALL); - bus_space_write_4(gptimer_iot, gptimer_ioh0, GP_TCRR, -ticks_per_intr); - gptimer_wait(GP_TWPS_ALL); -} - -void -gptimer_wait(int reg) -{ - while (bus_space_read_4(gptimer_iot, gptimer_ioh0, GP_TWPS) & reg) - ; -} - -#if 0 -void -microtime(struct timeval *tvp) -{ - int s; - int deltacnt; - u_int32_t counter, expected; - s = splhigh(); - - if (1) { /* not inited */ - tvp->tv_sec = 0; - tvp->tv_usec = 0; - return; - } - s = splhigh(); - counter = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); - expected = nexttickevent; - - *tvp = time; - splx(s); - - deltacnt = counter - expected + ticks_per_intr; - -#if 1 - /* low frequency timer algorithm */ - tvp->tv_usec += deltacnt * 1000000ULL / TIMER_FREQUENCY; -#else - /* high frequency timer algorithm - XXX */ - tvp->tv_usec += deltacnt / (TIMER_FREQUENCY / 1000000ULL); -#endif - - while (tvp->tv_usec >= 1000000) { - tvp->tv_sec++; - tvp->tv_usec -= 1000000; - } - -} -#endif - -void -gptimer_delay(u_int usecs) -{ - u_int32_t clock, oclock, delta, delaycnt; - volatile int j; - int csec, usec; - - if (usecs > (0x80000000 / (TIMER_FREQUENCY))) { - csec = usecs / 10000; - usec = usecs % 10000; - - delaycnt = (TIMER_FREQUENCY / 100) * csec + - (TIMER_FREQUENCY / 100) * usec / 10000; - } else { - delaycnt = TIMER_FREQUENCY * usecs / 1000000; - } - if (delaycnt <= 1) - for (j = 100; j > 0; j--) - ; - - if (gptimer_ioh1 == 0) { - /* BAH */ - for (; usecs > 0; usecs--) - for (j = 100; j > 0; j--) - ; - return; - } - oclock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); - while (1) { - for (j = 100; j > 0; j--) - ; - clock = bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); - delta = clock - oclock; - if (delta > delaycnt) - break; - } - -} - -void -gptimer_setstatclockrate(int newhz) -{ - int minint, statint; - int s; - - s = splclock(); - - statint = ticks_per_second / newhz; - /* calculate largest 2^n which is smaller that just over half statint */ - statvar = 0x40000000; /* really big power of two */ - minint = statint / 2 + 100; - while (statvar > minint) - statvar >>= 1; - - statmin = statint - (statvar >> 1); - - splx(s); - - /* - * XXX this allows the next stat timer to occur then it switches - * to the new frequency. Rather than switching instantly. - */ -} - - -u_int -gptimer_get_timecount(struct timecounter *tc) -{ - return bus_space_read_4(gptimer_iot, gptimer_ioh1, GP_TCRR); -} |
