summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-12 22:30:10 +0000
committerian <ian@FreeBSD.org>2014-05-12 22:30:10 +0000
commit6c09b7134e113ccb1708681c3edf9d50ee568af9 (patch)
treea4c92aee36a8db341e076a8bfcdcd6ceb47eb071
parent20d3a754301a0885106987322e7a70a51290df83 (diff)
downloadFreeBSD-src-6c09b7134e113ccb1708681c3edf9d50ee568af9.zip
FreeBSD-src-6c09b7134e113ccb1708681c3edf9d50ee568af9.tar.gz
MFC r259744, cleanups to move global vars into softc, use named values, etc.
-rw-r--r--sys/arm/ti/am335x/am335x_dmtimer.c235
1 files changed, 128 insertions, 107 deletions
diff --git a/sys/arm/ti/am335x/am335x_dmtimer.c b/sys/arm/ti/am335x/am335x_dmtimer.c
index b6c6fd0..aef0435 100644
--- a/sys/arm/ti/am335x/am335x_dmtimer.c
+++ b/sys/arm/ti/am335x/am335x_dmtimer.c
@@ -99,13 +99,16 @@ struct am335x_dmtimer_softc {
struct resource * tmr_mem_res[AM335X_NUM_TIMERS];
struct resource * tmr_irq_res[AM335X_NUM_TIMERS];
uint32_t sysclk_freq;
- struct am335x_dmtimer {
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
- struct eventtimer et;
- } t[AM335X_NUM_TIMERS];
+ uint32_t tc_num; /* Which timer number is tc. */
+ uint32_t et_num; /* Which timer number is et. */
+ struct resource * tc_memres; /* Resources for tc timer. */
+ struct resource * et_memres; /* Resources for et timer. */
+ struct timecounter tc;
+ struct eventtimer et;
};
+static struct am335x_dmtimer_softc *am335x_dmtimer_sc;
+
static struct resource_spec am335x_dmtimer_mem_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_MEMORY, 1, RF_ACTIVE },
@@ -129,51 +132,58 @@ static struct resource_spec am335x_dmtimer_irq_spec[] = {
{ -1, 0, 0 }
};
-static struct am335x_dmtimer *am335x_dmtimer_tc_tmr = NULL;
+static inline uint32_t
+am335x_dmtimer_tc_read_4(struct am335x_dmtimer_softc *sc, uint32_t reg)
+{
-/* Read/Write macros for Timer used as timecounter */
-#define am335x_dmtimer_tc_read_4(reg) \
- bus_space_read_4(am335x_dmtimer_tc_tmr->bst, \
- am335x_dmtimer_tc_tmr->bsh, reg)
+ return (bus_read_4(sc->tc_memres, reg));
+}
-#define am335x_dmtimer_tc_write_4(reg, val) \
- bus_space_write_4(am335x_dmtimer_tc_tmr->bst, \
- am335x_dmtimer_tc_tmr->bsh, reg, val)
+static inline void
+am335x_dmtimer_tc_write_4(struct am335x_dmtimer_softc *sc, uint32_t reg,
+ uint32_t val)
+{
-/* Read/Write macros for Timer used as eventtimer */
-#define am335x_dmtimer_et_read_4(reg) \
- bus_space_read_4(tmr->bst, tmr->bsh, reg)
+ bus_write_4(sc->tc_memres, reg, val);
+}
-#define am335x_dmtimer_et_write_4(reg, val) \
- bus_space_write_4(tmr->bst, tmr->bsh, reg, val)
+static inline uint32_t
+am335x_dmtimer_et_read_4(struct am335x_dmtimer_softc *sc, uint32_t reg)
+{
-static unsigned am335x_dmtimer_tc_get_timecount(struct timecounter *);
+ return (bus_read_4(sc->et_memres, reg));
+}
-static struct timecounter am335x_dmtimer_tc = {
- .tc_name = "AM335x Timecounter",
- .tc_get_timecount = am335x_dmtimer_tc_get_timecount,
- .tc_poll_pps = NULL,
- .tc_counter_mask = ~0u,
- .tc_frequency = 0,
- .tc_quality = 1000,
-};
+static inline void
+am335x_dmtimer_et_write_4(struct am335x_dmtimer_softc *sc, uint32_t reg,
+ uint32_t val)
+{
+
+ bus_write_4(sc->et_memres, reg, val);
+}
static unsigned
am335x_dmtimer_tc_get_timecount(struct timecounter *tc)
{
- return am335x_dmtimer_tc_read_4(DMT_TCRR);
+ struct am335x_dmtimer_softc *sc;
+
+ sc = tc->tc_priv;
+
+ return (am335x_dmtimer_tc_read_4(sc, DMT_TCRR));
}
static int
am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
- struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv;
- uint32_t load, count;
- uint32_t tclr = 0;
+ struct am335x_dmtimer_softc *sc;
+ uint32_t count, load, tclr;
+
+ sc = et->et_priv;
+ tclr = 0;
if (period != 0) {
load = ((uint32_t)et->et_frequency * period) >> 32;
- tclr |= 2; /* autoreload bit */
+ tclr |= DMT_TCLR_AUTOLOAD;
panic("periodic timer not implemented\n");
} else {
load = 0;
@@ -185,23 +195,24 @@ am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
count = load;
/* Reset Timer */
- am335x_dmtimer_et_write_4(DMT_TSICR, 2);
+ am335x_dmtimer_et_write_4(sc, DMT_TSICR, DMT_TSICR_RESET);
/* Wait for reset to complete */
- while (am335x_dmtimer_et_read_4(DMT_TIOCP_CFG) & 1);
+ while (am335x_dmtimer_et_read_4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
+ continue;
/* set load value */
- am335x_dmtimer_et_write_4(DMT_TLDR, 0xFFFFFFFE - load);
+ am335x_dmtimer_et_write_4(sc, DMT_TLDR, 0xFFFFFFFE - load);
/* set counter value */
- am335x_dmtimer_et_write_4(DMT_TCRR, 0xFFFFFFFE - count);
+ am335x_dmtimer_et_write_4(sc, DMT_TCRR, 0xFFFFFFFE - count);
/* enable overflow interrupt */
- am335x_dmtimer_et_write_4(DMT_IRQENABLE_SET, 2);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQENABLE_SET, DMT_IRQ_OVF);
/* start timer(ST) */
- tclr |= 1;
- am335x_dmtimer_et_write_4(DMT_TCLR, tclr);
+ tclr |= DMT_TCLR_START;
+ am335x_dmtimer_et_write_4(sc, DMT_TCLR, tclr);
return (0);
}
@@ -209,13 +220,15 @@ am335x_dmtimer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
static int
am335x_dmtimer_stop(struct eventtimer *et)
{
- struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)et->et_priv;
+ struct am335x_dmtimer_softc *sc;
+
+ sc = et->et_priv;
/* Disable all interrupts */
- am335x_dmtimer_et_write_4(DMT_IRQENABLE_CLR, 7);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQENABLE_CLR, DMT_IRQ_MASK);
/* Stop Timer */
- am335x_dmtimer_et_write_4(DMT_TCLR, 0);
+ am335x_dmtimer_et_write_4(sc, DMT_TCLR, 0);
return (0);
}
@@ -223,12 +236,13 @@ am335x_dmtimer_stop(struct eventtimer *et)
static int
am335x_dmtimer_intr(void *arg)
{
- struct am335x_dmtimer *tmr = (struct am335x_dmtimer *)arg;
+ struct am335x_dmtimer_softc *sc;
+ sc = arg;
/* Ack interrupt */
- am335x_dmtimer_et_write_4(DMT_IRQSTATUS, 7);
- if (tmr->et.et_active)
- tmr->et.et_event_cb(&tmr->et, tmr->et.et_arg);
+ am335x_dmtimer_et_write_4(sc, DMT_IRQSTATUS, DMT_IRQ_OVF);
+ if (sc->et.et_active)
+ sc->et.et_event_cb(&sc->et, sc->et.et_arg);
return (FILTER_HANDLED);
}
@@ -236,8 +250,6 @@ am335x_dmtimer_intr(void *arg)
static int
am335x_dmtimer_probe(device_t dev)
{
- struct am335x_dmtimer_softc *sc;
- sc = (struct am335x_dmtimer_softc *)device_get_softc(dev);
if (ofw_bus_is_compatible(dev, "ti,am335x-dmtimer")) {
device_set_desc(dev, "AM335x DMTimer");
@@ -250,22 +262,29 @@ am335x_dmtimer_probe(device_t dev)
static int
am335x_dmtimer_attach(device_t dev)
{
- struct am335x_dmtimer_softc *sc = device_get_softc(dev);
+ struct am335x_dmtimer_softc *sc;
void *ihl;
int err;
- int i;
- if (am335x_dmtimer_tc_tmr != NULL)
+ /*
+ * Note that if this routine returns an error status rather than running
+ * to completion it makes no attempt to clean up allocated resources;
+ * the system is essentially dead anyway without functional timers.
+ */
+
+ sc = device_get_softc(dev);
+
+ if (am335x_dmtimer_sc != NULL)
return (EINVAL);
- /* Get the base clock frequency */
+ /* Get the base clock frequency. */
err = ti_prcm_clk_get_source_freq(SYS_CLK, &sc->sysclk_freq);
if (err) {
device_printf(dev, "Error: could not get sysclk frequency\n");
return (ENXIO);
}
- /* Request the memory resources */
+ /* Request the memory resources. */
err = bus_alloc_resources(dev, am335x_dmtimer_mem_spec,
sc->tmr_mem_res);
if (err) {
@@ -273,7 +292,7 @@ am335x_dmtimer_attach(device_t dev)
return (ENXIO);
}
- /* Request the IRQ resources */
+ /* Request the IRQ resources. */
err = bus_alloc_resources(dev, am335x_dmtimer_irq_spec,
sc->tmr_irq_res);
if (err) {
@@ -281,65 +300,64 @@ am335x_dmtimer_attach(device_t dev)
return (ENXIO);
}
- for(i=0;i<AM335X_NUM_TIMERS;i++) {
- sc->t[i].bst = rman_get_bustag(sc->tmr_mem_res[i]);
- sc->t[i].bsh = rman_get_bushandle(sc->tmr_mem_res[i]);
- }
+ /* Configure DMTimer3 as eventtimer and DMTimer4 as timecounter. */
+ sc->et_num = 3;
+ sc->tc_num = 2;
+ sc->et_memres = sc->tmr_mem_res[sc->et_num];
+ sc->tc_memres = sc->tmr_mem_res[sc->tc_num];
- /* Configure DMTimer2 and DMTimer3 source and enable them */
- err = ti_prcm_clk_set_source(DMTIMER2_CLK, SYSCLK_CLK);
- err |= ti_prcm_clk_enable(DMTIMER2_CLK);
- err |= ti_prcm_clk_set_source(DMTIMER3_CLK, SYSCLK_CLK);
- err |= ti_prcm_clk_enable(DMTIMER3_CLK);
+ err = ti_prcm_clk_set_source(DMTIMER0_CLK + sc->et_num, SYSCLK_CLK);
+ err |= ti_prcm_clk_enable(DMTIMER0_CLK + sc->et_num);
+ err |= ti_prcm_clk_set_source(DMTIMER0_CLK + sc->tc_num, SYSCLK_CLK);
+ err |= ti_prcm_clk_enable(DMTIMER0_CLK + sc->tc_num);
if (err) {
device_printf(dev, "Error: could not setup timer clock\n");
return (ENXIO);
}
- /* Take DMTimer2 for TC */
- am335x_dmtimer_tc_tmr = &sc->t[2];
-
- /* Reset Timer */
- am335x_dmtimer_tc_write_4(DMT_TSICR, 2);
-
- /* Wait for reset to complete */
- while (am335x_dmtimer_tc_read_4(DMT_TIOCP_CFG) & 1);
-
- /* set load value */
- am335x_dmtimer_tc_write_4(DMT_TLDR, 0);
-
- /* set counter value */
- am335x_dmtimer_tc_write_4(DMT_TCRR, 0);
-
- /* Set Timer autoreload(AR) and start timer(ST) */
- am335x_dmtimer_tc_write_4(DMT_TCLR, 3);
-
- am335x_dmtimer_tc.tc_frequency = sc->sysclk_freq;
- tc_init(&am335x_dmtimer_tc);
-
- /* Register DMTimer3 as ET */
-
- /* Setup and enable the timer */
- if (bus_setup_intr(dev, sc->tmr_irq_res[3], INTR_TYPE_CLK,
- am335x_dmtimer_intr, NULL, &sc->t[3], &ihl) != 0) {
+ /* Set up timecounter; register tc. */
+ am335x_dmtimer_tc_write_4(sc, DMT_TSICR, DMT_TSICR_RESET);
+ while (am335x_dmtimer_tc_read_4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
+ continue;
+
+ am335x_dmtimer_tc_write_4(sc, DMT_TLDR, 0);
+ am335x_dmtimer_tc_write_4(sc, DMT_TCRR, 0);
+ am335x_dmtimer_tc_write_4(sc, DMT_TCLR,
+ DMT_TCLR_START | DMT_TCLR_AUTOLOAD);
+
+ sc->tc.tc_name = "AM335x Timecounter";
+ sc->tc.tc_get_timecount = am335x_dmtimer_tc_get_timecount;
+ sc->tc.tc_poll_pps = NULL;
+ sc->tc.tc_counter_mask = ~0u;
+ sc->tc.tc_frequency = sc->sysclk_freq;
+ sc->tc.tc_quality = 1000;
+ sc->tc.tc_priv = sc;
+ tc_init(&sc->tc);
+
+ /* Setup eventtimer; register et. */
+ if (bus_setup_intr(dev, sc->tmr_irq_res[sc->et_num], INTR_TYPE_CLK,
+ am335x_dmtimer_intr, NULL, sc, &ihl) != 0) {
bus_release_resources(dev, am335x_dmtimer_irq_spec,
sc->tmr_irq_res);
device_printf(dev, "Unable to setup the clock irq handler.\n");
return (ENXIO);
}
- sc->t[3].et.et_name = "AM335x Eventtimer0";
- sc->t[3].et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT;
- sc->t[3].et.et_quality = 1000;
- sc->t[3].et.et_frequency = sc->sysclk_freq;
- sc->t[3].et.et_min_period =
- (0x00000002LLU << 32) / sc->t[3].et.et_frequency;
- sc->t[3].et.et_max_period =
- (0xfffffffeLLU << 32) / sc->t[3].et.et_frequency;
- sc->t[3].et.et_start = am335x_dmtimer_start;
- sc->t[3].et.et_stop = am335x_dmtimer_stop;
- sc->t[3].et.et_priv = &sc->t[3];
- et_register(&sc->t[3].et);
+ sc->et.et_name = "AM335x Eventtimer";
+ sc->et.et_flags = ET_FLAGS_ONESHOT;
+ sc->et.et_quality = 1000;
+ sc->et.et_frequency = sc->sysclk_freq;
+ sc->et.et_min_period =
+ ((0x00000005LLU << 32) / sc->et.et_frequency);
+ sc->et.et_max_period =
+ (0xfffffffeLLU << 32) / sc->et.et_frequency;
+ sc->et.et_start = am335x_dmtimer_start;
+ sc->et.et_stop = am335x_dmtimer_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+
+ /* Store a pointer to the softc for use in DELAY(). */
+ am335x_dmtimer_sc = sc;
return (0);
}
@@ -370,10 +388,13 @@ cpu_initclocks(void)
void
DELAY(int usec)
{
- int32_t counts;
+ struct am335x_dmtimer_softc *sc;
+ int32_t counts;
uint32_t first, last;
- if (am335x_dmtimer_tc_tmr == NULL) {
+ sc = am335x_dmtimer_sc;
+
+ if (sc == NULL) {
for (; usec > 0; usec--)
for (counts = 200; counts > 0; counts--)
/* Prevent gcc from optimizing out the loop */
@@ -382,13 +403,13 @@ DELAY(int usec)
}
/* Get the number of times to count */
- counts = usec * (am335x_dmtimer_tc.tc_frequency / 1000000) + 1;
+ counts = (usec + 1) * (sc->sysclk_freq / 1000000);
- first = am335x_dmtimer_tc_read_4(DMT_TCRR);
+ first = am335x_dmtimer_tc_read_4(sc, DMT_TCRR);
while (counts > 0) {
- last = am335x_dmtimer_tc_read_4(DMT_TCRR);
- if (last>first) {
+ last = am335x_dmtimer_tc_read_4(sc, DMT_TCRR);
+ if (last > first) {
counts -= (int32_t)(last - first);
} else {
counts -= (int32_t)((0xFFFFFFFF - first) + last);
OpenPOWER on IntegriCloud