/* $NetBSD: clock_ebus.c,v 1.8 2014/02/24 14:26:11 martin Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code was written by Alessandro Forin and Neil Pittman
* at Microsoft Research and contributed to The NetBSD Foundation
* by Microsoft Corporation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: clock_ebus.c,v 1.8 2014/02/24 14:26:11 martin Exp $");
/*
* Compute reload according to whatever value passed in,
* Warn if fractional
*/
if (hz > 1) {
uint32_t r = reload / hz;
if ((r * hz) != reload)
printf("%s: %d Hz clock will cause roundoffs"
" with 10MHz xtal (%d)\n",
device_xname(sc->sc_dev), hz, reload - (r * hz));
reload = r;
}
/*
* 32bit processor, guard against interrupts in the middle of
* reading this 64bit entity
*/
/* BUGBUG Should read it "twice" to guard against rollover too. */
s = splhigh();
free = tc->FreeRunning;
splx(s);
/*
* Big fight with the compiler here, it gets very confused by 64bits.
*/
#if 1
/*
* This is in C:
*/
{
uint64_t freeS, freeU;
freeS = free / 10000000UL;
freeU = free % 10000000UL;
tv->tv_sec = freeS;
tv->tv_usec = freeU / 10;
#if 0
printf("egt: s x%" PRIx64 " u x%lx (fs %" PRId64
" fu %" PRId64 " f %" PRId64 ")\n",
tv->tv_sec, tv->tv_usec, freeS, freeU, free);
#endif
}
#else
/*
* And this is in assembly :-)
*/
{
u_quad_t r;
u_quad_t d = __qdivrem(free,(u_quad_t)10000000,&r);
uint32_t su, uu;
su = (uint32_t)d;
uu = (uint32_t)r;
uu = uu / 10; /* in usecs */
tv->tv_sec = su;
tv->tv_usec = uu;
#if 0
printf("egt: s x%" PRIx64 " u x%lx (fs %" PRId64
" fu %" PRId64 " f %" PRId64 ")\n",
tv->tv_sec, tv->tv_usec, d, r, free);
#endif
}
#endif
return 0;
}
/*
* Reset the TODR based on the time value.
*/
static int
eclock_settime(struct todr_chip_handle *todr, struct timeval *tv)
{
struct eclock_softc *sc = todr->cookie;
struct _Tc *tc = sc->sc_dp;
uint64_t free, su;
uint32_t uu;
int s;
/* Careful with what we do here, else the compilerbugs hit hard */
s = splhigh();