xref: /openbsd-src/sys/arch/armv7/omap/dmtimer.c (revision 0ed1bf01ac7e45759b65902d0ab711deb359316d)
1*0ed1bf01Scheloha /*	$OpenBSD: dmtimer.c,v 1.22 2023/09/17 14:50:51 cheloha Exp $	*/
28eda2d14Spatrick /*
38eda2d14Spatrick  * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
48eda2d14Spatrick  * Copyright (c) 2013 Raphael Graf <r@undefined.ch>
58eda2d14Spatrick  *
68eda2d14Spatrick  * Permission to use, copy, modify, and distribute this software for any
78eda2d14Spatrick  * purpose with or without fee is hereby granted, provided that the above
88eda2d14Spatrick  * copyright notice and this permission notice appear in all copies.
98eda2d14Spatrick  *
108eda2d14Spatrick  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
118eda2d14Spatrick  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
128eda2d14Spatrick  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
138eda2d14Spatrick  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
148eda2d14Spatrick  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
158eda2d14Spatrick  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
168eda2d14Spatrick  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
178eda2d14Spatrick  */
188eda2d14Spatrick 
198eda2d14Spatrick /*
2097db43afSjsg  *	WARNING - this timer initialization has not been checked
218eda2d14Spatrick  *	to see if it will do _ANYTHING_ sane if the omap enters
228eda2d14Spatrick  *	low power mode.
238eda2d14Spatrick  */
248eda2d14Spatrick 
258eda2d14Spatrick #include <sys/param.h>
268eda2d14Spatrick #include <sys/systm.h>
278eda2d14Spatrick #include <sys/kernel.h>
289451db9bScheloha #include <sys/clockintr.h>
298eda2d14Spatrick #include <sys/evcount.h>
308eda2d14Spatrick #include <sys/device.h>
319451db9bScheloha #include <sys/stdint.h>
328eda2d14Spatrick #include <sys/timetc.h>
338eda2d14Spatrick #include <machine/bus.h>
348d957e1aSsyl #include <armv7/armv7/armv7var.h>
358eda2d14Spatrick #include <armv7/omap/prcmvar.h>
368eda2d14Spatrick 
378eda2d14Spatrick #include <machine/intr.h>
388eda2d14Spatrick 
398eda2d14Spatrick /* registers */
408eda2d14Spatrick #define	DM_TIDR		0x000
418eda2d14Spatrick #define		DM_TIDR_MAJOR		0x00000700
428eda2d14Spatrick #define		DM_TIDR_MINOR		0x0000003f
438eda2d14Spatrick #define	DM_TIOCP_CFG	0x010
448eda2d14Spatrick #define 	DM_TIOCP_CFG_IDLEMODE	(3<<2)
458eda2d14Spatrick #define 	DM_TIOCP_CFG_EMUFREE	(1<<1)
468eda2d14Spatrick #define 	DM_TIOCP_CFG_SOFTRESET	(1<<0)
478eda2d14Spatrick #define	DM_TISR		0x028
488eda2d14Spatrick #define		DM_TISR_TCAR		(1<<2)
498eda2d14Spatrick #define		DM_TISR_OVF		(1<<1)
508eda2d14Spatrick #define		DM_TISR_MAT		(1<<0)
518eda2d14Spatrick #define DM_TIER		0x2c
528eda2d14Spatrick #define		DM_TIER_TCAR_EN		(1<<2)
538eda2d14Spatrick #define		DM_TIER_OVF_EN		(1<<1)
548eda2d14Spatrick #define		DM_TIER_MAT_EN		(1<<0)
558eda2d14Spatrick #define DM_TIECR	0x30
568eda2d14Spatrick #define		DM_TIECR_TCAR_EN	(1<<2)
578eda2d14Spatrick #define		DM_TIECR_OVF_EN		(1<<1)
588eda2d14Spatrick #define		DM_TIECR_MAT_EN		(1<<0)
598eda2d14Spatrick #define	DM_TWER		0x034
608eda2d14Spatrick #define		DM_TWER_TCAR_EN		(1<<2)
618eda2d14Spatrick #define		DM_TWER_OVF_EN		(1<<1)
628eda2d14Spatrick #define		DM_TWER_MAT_EN		(1<<0)
638eda2d14Spatrick #define	DM_TCLR		0x038
648eda2d14Spatrick #define		DM_TCLR_GPO		(1<<14)
658eda2d14Spatrick #define		DM_TCLR_CAPT		(1<<13)
668eda2d14Spatrick #define		DM_TCLR_PT		(1<<12)
678eda2d14Spatrick #define		DM_TCLR_TRG		(3<<10)
688eda2d14Spatrick #define		DM_TCLR_TRG_O		(1<<10)
698eda2d14Spatrick #define		DM_TCLR_TRG_OM		(2<<10)
708eda2d14Spatrick #define		DM_TCLR_TCM		(3<<8)
718eda2d14Spatrick #define		DM_TCLR_TCM_RISE	(1<<8)
728eda2d14Spatrick #define		DM_TCLR_TCM_FALL	(2<<8)
738eda2d14Spatrick #define		DM_TCLR_TCM_BOTH	(3<<8)
748eda2d14Spatrick #define		DM_TCLR_SCPWM		(1<<7)
758eda2d14Spatrick #define		DM_TCLR_CE		(1<<6)
768eda2d14Spatrick #define		DM_TCLR_PRE		(1<<5)
778eda2d14Spatrick #define		DM_TCLR_PTV		(7<<2)
788eda2d14Spatrick #define		DM_TCLR_AR		(1<<1)
798eda2d14Spatrick #define		DM_TCLR_ST		(1<<0)
808eda2d14Spatrick #define	DM_TCRR		0x03c
818eda2d14Spatrick #define	DM_TLDR		0x040
828eda2d14Spatrick #define	DM_TTGR		0x044
838eda2d14Spatrick #define	DM_TWPS		0x048
848eda2d14Spatrick #define		DM_TWPS_TMAR		(1<<4)
858eda2d14Spatrick #define		DM_TWPS_TTGR		(1<<3)
868eda2d14Spatrick #define		DM_TWPS_TLDR		(1<<2)
878eda2d14Spatrick #define		DM_TWPS_TCLR		(1<<0)
888eda2d14Spatrick #define		DM_TWPS_TCRR		(1<<1)
898eda2d14Spatrick #define		DM_TWPS_ALL		0x1f
908eda2d14Spatrick #define	DM_TMAR		0x04c
918eda2d14Spatrick #define	DM_TCAR		0x050
928eda2d14Spatrick #define	DM_TSICR	0x054
938eda2d14Spatrick #define		DM_TSICR_POSTED		(1<<2)
948eda2d14Spatrick #define		DM_TSICR_SFT		(1<<1)
958eda2d14Spatrick #define	DM_TCAR2	0x058
968eda2d14Spatrick 
978eda2d14Spatrick #define TIMER_FREQUENCY			32768	/* 32kHz is used, selectable */
988eda2d14Spatrick #define MAX_TIMERS			2
998eda2d14Spatrick 
1008eda2d14Spatrick void dmtimer_attach(struct device *parent, struct device *self, void *args);
1018eda2d14Spatrick int dmtimer_intr(void *frame);
1029451db9bScheloha void dmtimer_reset_tisr(void);
1038eda2d14Spatrick void dmtimer_wait(int reg);
1048eda2d14Spatrick void dmtimer_cpu_initclocks(void);
10511d1f9b2Scheloha void dmtimer_cpu_startclock(void);
1068eda2d14Spatrick void dmtimer_delay(u_int);
1078eda2d14Spatrick void dmtimer_setstatclockrate(int newhz);
1088eda2d14Spatrick 
1098eda2d14Spatrick u_int dmtimer_get_timecount(struct timecounter *);
1108eda2d14Spatrick 
1118eda2d14Spatrick static struct timecounter dmtimer_timecounter = {
1128611d3cdScheloha 	.tc_get_timecount = dmtimer_get_timecount,
1138611d3cdScheloha 	.tc_counter_mask = 0xffffffff,
1148611d3cdScheloha 	.tc_frequency = 0,
1158611d3cdScheloha 	.tc_name = "dmtimer",
1168611d3cdScheloha 	.tc_quality = 0,
1178611d3cdScheloha 	.tc_priv = NULL,
1188eda2d14Spatrick };
1198eda2d14Spatrick 
1209451db9bScheloha void dmtimer_rearm(void *, uint64_t);
1219451db9bScheloha void dmtimer_trigger(void *);
1229451db9bScheloha 
1239451db9bScheloha struct intrclock dmtimer_intrclock = {
1249451db9bScheloha 	.ic_rearm = dmtimer_rearm,
1259451db9bScheloha 	.ic_trigger = dmtimer_trigger
1269451db9bScheloha };
1279451db9bScheloha 
1288eda2d14Spatrick bus_space_handle_t dmtimer_ioh0;
1298eda2d14Spatrick int dmtimer_irq = 0;
1308eda2d14Spatrick 
1318eda2d14Spatrick struct dmtimer_softc {
1328eda2d14Spatrick 	struct device		sc_dev;
1338eda2d14Spatrick 	bus_space_tag_t		sc_iot;
1348eda2d14Spatrick 	bus_space_handle_t	sc_ioh[MAX_TIMERS];
1358eda2d14Spatrick 	u_int32_t		sc_irq;
1368eda2d14Spatrick 	u_int32_t		sc_ticks_per_second;
1379451db9bScheloha 	u_int64_t		sc_nsec_cycle_ratio;
1389451db9bScheloha 	u_int64_t		sc_nsec_max;
1398eda2d14Spatrick };
1408eda2d14Spatrick 
1419fdf0c62Smpi const struct cfattach	dmtimer_ca = {
1428eda2d14Spatrick 	sizeof (struct dmtimer_softc), NULL, dmtimer_attach
1438eda2d14Spatrick };
1448eda2d14Spatrick 
1458eda2d14Spatrick struct cfdriver dmtimer_cd = {
1468eda2d14Spatrick 	NULL, "dmtimer", DV_DULL
1478eda2d14Spatrick };
1488eda2d14Spatrick 
1498eda2d14Spatrick void
dmtimer_attach(struct device * parent,struct device * self,void * args)1508eda2d14Spatrick dmtimer_attach(struct device *parent, struct device *self, void *args)
1518eda2d14Spatrick {
1528eda2d14Spatrick 	struct dmtimer_softc	*sc = (struct dmtimer_softc *)self;
1538d957e1aSsyl 	struct armv7_attach_args *aa = args;
1548eda2d14Spatrick 	bus_space_handle_t	ioh;
1558eda2d14Spatrick 	u_int32_t		rev, cfg;
1568eda2d14Spatrick 
1578d957e1aSsyl 	sc->sc_iot = aa->aa_iot;
1588eda2d14Spatrick 
1598d957e1aSsyl 	if (bus_space_map(sc->sc_iot, aa->aa_dev->mem[0].addr,
1608d957e1aSsyl 	    aa->aa_dev->mem[0].size, 0, &ioh))
1614123b6a7Sderaadt 		panic("%s: bus_space_map failed!", __func__);
1628eda2d14Spatrick 
1638eda2d14Spatrick 
1648eda2d14Spatrick 	prcm_setclock(1, PRCM_CLK_SPEED_32);
1658eda2d14Spatrick 	prcm_setclock(2, PRCM_CLK_SPEED_32);
1668eda2d14Spatrick 	prcm_enablemodule(PRCM_TIMER2);
1678eda2d14Spatrick 	prcm_enablemodule(PRCM_TIMER3);
1688eda2d14Spatrick 
1698eda2d14Spatrick 	/* reset */
1708eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
1718eda2d14Spatrick 	    DM_TIOCP_CFG_SOFTRESET);
1728eda2d14Spatrick 	while (bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG)
1738eda2d14Spatrick 	    & DM_TIOCP_CFG_SOFTRESET)
1748eda2d14Spatrick 		;
1758eda2d14Spatrick 
1768eda2d14Spatrick 	if (self->dv_unit == 0) {
1778eda2d14Spatrick 		dmtimer_ioh0 = ioh;
1788d957e1aSsyl 		dmtimer_irq = aa->aa_dev->irq[0];
1798eda2d14Spatrick 		/* enable write posted mode */
1808eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, ioh, DM_TSICR, DM_TSICR_POSTED);
1818eda2d14Spatrick 		/* stop timer */
1828eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, ioh, DM_TCLR, 0);
1838eda2d14Spatrick 	} else if (self->dv_unit == 1) {
1848eda2d14Spatrick 		/* start timer because it is used in delay */
1858eda2d14Spatrick 		/* interrupts and posted mode are disabled */
1868eda2d14Spatrick 		sc->sc_irq = dmtimer_irq;
1878eda2d14Spatrick 		sc->sc_ioh[0] = dmtimer_ioh0;
1888eda2d14Spatrick 		sc->sc_ioh[1] = ioh;
1898eda2d14Spatrick 
1908eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, ioh, DM_TCRR, 0);
1918eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, ioh, DM_TLDR, 0);
1928eda2d14Spatrick 		bus_space_write_4(sc->sc_iot, ioh, DM_TCLR,
1938eda2d14Spatrick 		    DM_TCLR_AR | DM_TCLR_ST);
1948eda2d14Spatrick 
1958eda2d14Spatrick 		dmtimer_timecounter.tc_frequency = TIMER_FREQUENCY;
1968eda2d14Spatrick 		dmtimer_timecounter.tc_priv = sc;
1978eda2d14Spatrick 		tc_init(&dmtimer_timecounter);
1988eda2d14Spatrick 		arm_clock_register(dmtimer_cpu_initclocks, dmtimer_delay,
19911d1f9b2Scheloha 		    dmtimer_setstatclockrate, dmtimer_cpu_startclock);
2008eda2d14Spatrick 	}
2018eda2d14Spatrick 	else
202ddb53a58Smiod 		panic("attaching too many dmtimers at 0x%lx",
2038d957e1aSsyl 		    aa->aa_dev->mem[0].addr);
2048eda2d14Spatrick 
2058eda2d14Spatrick 	/* set IDLEMODE to smart-idle */
2068eda2d14Spatrick 	cfg = bus_space_read_4(sc->sc_iot, ioh, DM_TIOCP_CFG);
2078eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, ioh, DM_TIOCP_CFG,
2088eda2d14Spatrick 	    (cfg & ~DM_TIOCP_CFG_IDLEMODE) | 0x02);
2098eda2d14Spatrick 
2108eda2d14Spatrick 	rev = bus_space_read_4(sc->sc_iot, ioh, DM_TIDR);
2118eda2d14Spatrick 	printf(" rev %d.%d\n", (rev & DM_TIDR_MAJOR) >> 8, rev & DM_TIDR_MINOR);
2128eda2d14Spatrick }
2138eda2d14Spatrick 
2148eda2d14Spatrick int
dmtimer_intr(void * frame)2158eda2d14Spatrick dmtimer_intr(void *frame)
2168eda2d14Spatrick {
2179451db9bScheloha 	dmtimer_reset_tisr();		/* clear pending interrupts */
2189451db9bScheloha 	clockintr_dispatch(frame);
2198eda2d14Spatrick 	return 1;
2208eda2d14Spatrick }
2218eda2d14Spatrick 
2228eda2d14Spatrick /*
2238eda2d14Spatrick  * would be interesting to play with trigger mode while having one timer
2242252d02cSkettenis  * in 32kHz mode, and the other timer running in sysclk mode and use
2258eda2d14Spatrick  * the high resolution speeds (matters more for delay than tick timer
2268eda2d14Spatrick  */
2278eda2d14Spatrick 
2288eda2d14Spatrick void
dmtimer_cpu_initclocks(void)22937e35e27Sjsg dmtimer_cpu_initclocks(void)
2308eda2d14Spatrick {
2318eda2d14Spatrick 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
2328eda2d14Spatrick 
2334533a266Scheloha 	stathz = hz;
2344533a266Scheloha 	profhz = stathz * 10;
235b3ef18bdScheloha 	statclock_is_randomized = 1;
2368eda2d14Spatrick 
2378eda2d14Spatrick 	sc->sc_ticks_per_second = TIMER_FREQUENCY; /* 32768 */
2389451db9bScheloha 	sc->sc_nsec_cycle_ratio =
2399451db9bScheloha 	    sc->sc_ticks_per_second * (1ULL << 32) / 1000000000;
2409451db9bScheloha 	sc->sc_nsec_max = UINT64_MAX / sc->sc_nsec_cycle_ratio;
2419451db9bScheloha 	dmtimer_intrclock.ic_cookie = sc;
2428eda2d14Spatrick 
2438eda2d14Spatrick 	/* establish interrupts */
2448eda2d14Spatrick 	arm_intr_establish(sc->sc_irq, IPL_CLOCK, dmtimer_intr,
2458eda2d14Spatrick 	    NULL, "tick");
2468eda2d14Spatrick 
2478eda2d14Spatrick 	/* setup timer 0 */
2488eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TLDR, 0);
2498eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TIER, DM_TIER_OVF_EN);
2508eda2d14Spatrick 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TWER, DM_TWER_OVF_EN);
25111d1f9b2Scheloha }
2529451db9bScheloha 
25311d1f9b2Scheloha void
dmtimer_cpu_startclock(void)25411d1f9b2Scheloha dmtimer_cpu_startclock(void)
25511d1f9b2Scheloha {
2569451db9bScheloha 	/* start the clock interrupt cycle */
2579451db9bScheloha 	clockintr_cpu_init(&dmtimer_intrclock);
2589451db9bScheloha 	clockintr_trigger();
2598eda2d14Spatrick }
2608eda2d14Spatrick 
2618eda2d14Spatrick void
dmtimer_wait(int reg)2628eda2d14Spatrick dmtimer_wait(int reg)
2638eda2d14Spatrick {
2648eda2d14Spatrick 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
2658eda2d14Spatrick 	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TWPS) & reg)
2668eda2d14Spatrick 		;
2678eda2d14Spatrick }
2688eda2d14Spatrick 
2699451db9bScheloha /*
2709451db9bScheloha  * Clear all interrupt status bits.
2719451db9bScheloha  */
2729451db9bScheloha void
dmtimer_reset_tisr(void)2739451db9bScheloha dmtimer_reset_tisr(void)
2749451db9bScheloha {
2759451db9bScheloha 	struct dmtimer_softc *sc = dmtimer_cd.cd_devs[1];
2769451db9bScheloha 	u_int32_t tisr;
2779451db9bScheloha 
2789451db9bScheloha 	tisr = bus_space_read_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR);
2799451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TISR, tisr);
2809451db9bScheloha }
2819451db9bScheloha 
2828eda2d14Spatrick void
dmtimer_delay(u_int usecs)2838eda2d14Spatrick dmtimer_delay(u_int usecs)
2848eda2d14Spatrick {
2858eda2d14Spatrick 	struct dmtimer_softc	*sc = dmtimer_cd.cd_devs[1];
2868eda2d14Spatrick 	u_int32_t		clock, oclock, delta, delaycnt;
2878eda2d14Spatrick 	volatile int		j;
2888eda2d14Spatrick 	int			csec, usec;
2898eda2d14Spatrick 
2908eda2d14Spatrick 	if (usecs > (0x80000000 / (TIMER_FREQUENCY))) {
2918eda2d14Spatrick 		csec = usecs / 10000;
2928eda2d14Spatrick 		usec = usecs % 10000;
2938eda2d14Spatrick 
2948eda2d14Spatrick 		delaycnt = (TIMER_FREQUENCY / 100) * csec +
2958eda2d14Spatrick 		    (TIMER_FREQUENCY / 100) * usec / 10000;
2968eda2d14Spatrick 	} else {
2978eda2d14Spatrick 		delaycnt = TIMER_FREQUENCY * usecs / 1000000;
2988eda2d14Spatrick 	}
2998eda2d14Spatrick 	if (delaycnt <= 1)
3008eda2d14Spatrick 		for (j = 100; j > 0; j--)
3018eda2d14Spatrick 			;
3028eda2d14Spatrick 
3038eda2d14Spatrick 	if (sc->sc_ioh[1] == 0) {
3048eda2d14Spatrick 		/* BAH */
3058eda2d14Spatrick 		for (; usecs > 0; usecs--)
3068eda2d14Spatrick 			for (j = 100; j > 0; j--)
3078eda2d14Spatrick 				;
3088eda2d14Spatrick 		return;
3098eda2d14Spatrick 	}
3108eda2d14Spatrick 	oclock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
3118eda2d14Spatrick 	while (1) {
3128eda2d14Spatrick 		for (j = 100; j > 0; j--)
3138eda2d14Spatrick 			;
3148eda2d14Spatrick 		clock = bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
3158eda2d14Spatrick 		delta = clock - oclock;
3168eda2d14Spatrick 		if (delta > delaycnt)
3178eda2d14Spatrick 			break;
3188eda2d14Spatrick 	}
3198eda2d14Spatrick 
3208eda2d14Spatrick }
3218eda2d14Spatrick 
3228eda2d14Spatrick void
dmtimer_setstatclockrate(int newhz)3238eda2d14Spatrick dmtimer_setstatclockrate(int newhz)
3248eda2d14Spatrick {
3258eda2d14Spatrick }
3268eda2d14Spatrick 
3278eda2d14Spatrick 
3288eda2d14Spatrick u_int
dmtimer_get_timecount(struct timecounter * tc)3298eda2d14Spatrick dmtimer_get_timecount(struct timecounter *tc)
3308eda2d14Spatrick {
3318eda2d14Spatrick 	struct dmtimer_softc *sc = dmtimer_timecounter.tc_priv;
3328eda2d14Spatrick 
3338eda2d14Spatrick 	return bus_space_read_4(sc->sc_iot, sc->sc_ioh[1], DM_TCRR);
3348eda2d14Spatrick }
3359451db9bScheloha 
3369451db9bScheloha void
dmtimer_rearm(void * cookie,uint64_t nsecs)3379451db9bScheloha dmtimer_rearm(void *cookie, uint64_t nsecs)
3389451db9bScheloha {
3399451db9bScheloha 	struct dmtimer_softc *sc = cookie;
3409451db9bScheloha 	uint32_t cycles;
3419451db9bScheloha 
3429451db9bScheloha 	if (nsecs > sc->sc_nsec_max)
3439451db9bScheloha 		nsecs = sc->sc_nsec_max;
3449451db9bScheloha 	cycles = (nsecs * sc->sc_nsec_cycle_ratio) >> 32;
3459451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR,
3469451db9bScheloha 	    UINT32_MAX - cycles);
3479451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, DM_TCLR_ST);
3489451db9bScheloha 	dmtimer_wait(DM_TWPS_ALL);
3499451db9bScheloha }
3509451db9bScheloha 
3519451db9bScheloha void
dmtimer_trigger(void * cookie)3529451db9bScheloha dmtimer_trigger(void *cookie)
3539451db9bScheloha {
3549451db9bScheloha 	struct dmtimer_softc *sc = cookie;
3559451db9bScheloha 
3569451db9bScheloha 	/* stop timer */
3579451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, 0);
3589451db9bScheloha 
3599451db9bScheloha 	dmtimer_reset_tisr();	/* clear pending interrupts */
3609451db9bScheloha 
3619451db9bScheloha 	/* set shortest possible timeout */
3629451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCRR, UINT32_MAX);
3639451db9bScheloha 	dmtimer_wait(DM_TWPS_ALL);
3649451db9bScheloha 
3659451db9bScheloha 	/* start timer */
3669451db9bScheloha 	bus_space_write_4(sc->sc_iot, sc->sc_ioh[0], DM_TCLR, DM_TCLR_ST);
3679451db9bScheloha 	dmtimer_wait(DM_TWPS_ALL);
3689451db9bScheloha }
369