socsvn commit: r271977 - soc2014/astarasikov/head/sys/arm/goldfish
astarasikov at FreeBSD.org
astarasikov at FreeBSD.org
Wed Aug 6 01:36:49 UTC 2014
Author: astarasikov
Date: Wed Aug 6 01:36:48 2014
New Revision: 271977
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=271977
Log:
[goldfish]: working timer (finally, fixes random & init)
Modified:
soc2014/astarasikov/head/sys/arm/goldfish/goldfish_timer.c
Modified: soc2014/astarasikov/head/sys/arm/goldfish/goldfish_timer.c
==============================================================================
--- soc2014/astarasikov/head/sys/arm/goldfish/goldfish_timer.c Wed Aug 6 01:36:05 2014 (r271976)
+++ soc2014/astarasikov/head/sys/arm/goldfish/goldfish_timer.c Wed Aug 6 01:36:48 2014 (r271977)
@@ -59,12 +59,7 @@
GOLDFISH_TIMER_CLEAR_ALARM = 0x14,
};
-#define CLOCK_TICK_RATE ((50 * 1000 * 1000) / 16)
-
-#define DEFAULT_FREQUENCY 1000000
-
-#define DEFAULT_DIVISOR 16
-#define DEFAULT_CONTROL_DIV TIMER_CONTROL_DIV16
+#define CLOCK_TICK_RATE (1000 * 1000 * 1000)
struct goldfish_timer_softc {
struct resource* mem_res;
@@ -78,6 +73,9 @@
struct eventtimer et;
};
+static int goldfish_timer_initialized;
+static struct goldfish_timer_softc *goldfish_timer_sc;
+
#define goldfish_timer_tc_read_4(reg) \
bus_space_read_4(sc->bst, sc->bsh, reg)
@@ -98,7 +96,7 @@
static unsigned
goldfish_timer_tc_get_timecount(struct timecounter *tc)
{
- return (unsigned)goldfish_timer_read_counter64(tc);
+ return (unsigned)(goldfish_timer_read_counter64(tc));
}
static int
@@ -109,15 +107,15 @@
if (first != 0) {
sc->et_enabled = 1;
-
count = ((uint64_t)et->et_frequency * first);
-
goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_HIGH, count >> 32);
goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_LOW, count & 0xffffffff);
- printf("setting timer to %llu\n", count);
-
return (0);
}
+ else {
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_HIGH, 0);
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_LOW, 0);
+ }
if (period != 0) {
panic("period");
@@ -141,7 +139,7 @@
goldfish_timer_intr(void *arg)
{
struct goldfish_timer_softc *sc = arg;
- //goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_INTERRUPT, 1);
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_INTERRUPT, 1);
if (sc->et_enabled && sc->et.et_active)
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
@@ -166,26 +164,29 @@
{
struct goldfish_timer_softc *sc = device_get_softc(dev);
int mem_rid = 0, irq_rid = 0;
-
+
/* TODO: get frequency from FDT */
- sc->sysclk_freq = CLOCK_TICK_RATE * 16;
+ sc->sysclk_freq = CLOCK_TICK_RATE;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, RF_ACTIVE);
- if (sc->mem_res == NULL)
+ if (sc->mem_res == NULL) {
goto fail;
+ }
sc->bst = rman_get_bustag(sc->mem_res);
sc->bsh = rman_get_bushandle(sc->mem_res);
/* Request the IRQ resources */
sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid, RF_ACTIVE);
- if (sc->irq_res == NULL)
+ if (sc->irq_res == NULL) {
goto fail;
+ }
/* Setup and enable the timer */
if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_CLK,
- goldfish_timer_intr, NULL, sc,
- &sc->intr_hl) != 0)
+ goldfish_timer_intr, NULL, sc, &sc->intr_hl) != 0)
+ {
goto fail;
+ }
/*
* Timer 1, timecounter
@@ -198,25 +199,33 @@
sc->tc.tc_quality = 200;
sc->tc.tc_priv = sc;
- goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_ALARM, 1);
- goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_INTERRUPT, 1);
-
- tc_init(&sc->tc);
-
/*
* Timer 2, event timer
*/
sc->et_enabled = 0;
sc->et.et_name = "Goldfish Event Timer";
- sc->et.et_flags = /*ET_FLAGS_PERIODIC |*/ ET_FLAGS_ONESHOT;
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
sc->et.et_frequency = CLOCK_TICK_RATE;
sc->et.et_quality = 200;
- sc->et.et_min_period = (0x00000001LLU << 32) / sc->et.et_frequency;
- sc->et.et_max_period = (0xffffffffLLU << 32) / sc->et.et_frequency;
+ sc->et.et_min_period = (0x00000002LLU << 32) / sc->et.et_frequency;
+ sc->et.et_max_period = (0xfffffffeLLU << 32) / sc->et.et_frequency;
sc->et.et_start = goldfish_timer_start;
sc->et.et_stop = goldfish_timer_stop;
sc->et.et_priv = sc;
+
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_ALARM, 1);
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_CLEAR_INTERRUPT, 1);
+
et_register(&sc->et);
+ tc_init(&sc->tc);
+
+ /* keep a global reference to sc to avoid lookup during DELAY */
+ goldfish_timer_sc = sc;
+ goldfish_timer_initialized = 1;
+
+ /* trigger an interrupt */
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_HIGH, 0);
+ goldfish_timer_tc_write_4(GOLDFISH_TIMER_ALARM_LOW, 0);
return (0);
@@ -233,7 +242,7 @@
static device_method_t goldfish_timer_methods[] = {
DEVMETHOD(device_probe, goldfish_timer_probe),
DEVMETHOD(device_attach, goldfish_timer_attach),
- { 0, 0 }
+ DEVMETHOD_END,
};
static driver_t goldfish_timer_driver = {
@@ -251,12 +260,9 @@
{
uint64_t counts;
uint64_t now, end;
- device_t timer_dev;
- struct goldfish_timer_softc *sc;
-
- timer_dev = devclass_get_device(goldfish_timer_devclass, 0);
- if (timer_dev == NULL) {
+ /* Let us uncomment this as soon as rootfs mounts and init starts */
+ if (!goldfish_timer_initialized || !goldfish_timer_sc) {
/*
* Timer is not initialized yet
*/
@@ -267,20 +273,19 @@
return;
}
- sc = device_get_softc(timer_dev);
-
/* Get the number of times to count */
- counts = usec * ((sc->tc.tc_frequency / 1000000) + 1);
+ counts = usec * ((goldfish_timer_sc->tc.tc_frequency / 1000000) + 1);
- now = goldfish_timer_read_counter64(&sc->tc);
+ now = goldfish_timer_read_counter64(&goldfish_timer_sc->tc);
end = now + counts;
while (now < end) {
- now = goldfish_timer_read_counter64(&sc->tc);
+ now = goldfish_timer_read_counter64(&goldfish_timer_sc->tc);
}
}
void
cpu_initclocks(void)
{
+ cpu_initclocks_bsp();
}
More information about the svn-soc-all
mailing list