counter.c revision 90619
190619Stmm/*- 290619Stmm * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 390619Stmm * All rights reserved. 490619Stmm * 590619Stmm * Redistribution and use in source and binary forms, with or without 690619Stmm * modification, are permitted provided that the following conditions 790619Stmm * are met: 890619Stmm * 1. Redistributions of source code must retain the above copyright 990619Stmm * notice, this list of conditions and the following disclaimer. 1090619Stmm * 2. Redistributions in binary form must reproduce the above copyright 1190619Stmm * notice, this list of conditions and the following disclaimer in the 1290619Stmm * documentation and/or other materials provided with the distribution. 1390619Stmm * 1490619Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1590619Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1690619Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1790619Stmm * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 1890619Stmm * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 1990619Stmm * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2090619Stmm * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 2190619Stmm * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2290619Stmm * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 2390619Stmm * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2490619Stmm * 2590619Stmm * $FreeBSD: head/sys/sparc64/sparc64/counter.c 90619 2002-02-13 16:16:36Z tmm $ 2690619Stmm */ 2790619Stmm 2890619Stmm#include <sys/param.h> 2990619Stmm#include <sys/bus.h> 3090619Stmm#include <sys/malloc.h> 3190619Stmm#include <sys/systm.h> 3290619Stmm#include <sys/time.h> 3390619Stmm#include <sys/timetc.h> 3490619Stmm 3590619Stmm#include <machine/bus.h> 3690619Stmm#include <machine/bus_common.h> 3790619Stmm 3890619Stmm#define COUNTER_MASK ((1 << 29) - 1) 3990619Stmm#define COUNTER_FREQ 1000000 4090619Stmm 4190619Stmm/* Bits in the limit register. */ 4290619Stmm#define CTLR_INTEN (1U << 31) /* Enable timer interrupts */ 4390619Stmm#define CTLR_RELOAD (1U << 30) /* Zero counter on write to limit reg */ 4490619Stmm#define CTLR_PERIODIC (1U << 29) /* Wrap to 0 if limit is reached */ 4590619Stmm 4690619Stmm/* Offsets of the registers for the two counters. */ 4790619Stmm#define CTR_CT0 0x00 4890619Stmm#define CTR_CT1 0x10 4990619Stmm 5090619Stmm/* Register offsets from the base address. */ 5190619Stmm#define CTR_COUNT 0x00 5290619Stmm#define CTR_LIMIT 0x08 5390619Stmm 5490619Stmm 5590619Stmmstatic unsigned counter_get_timecount(struct timecounter *tc); 5690619Stmm 5790619Stmmstruct ct_softc { 5890619Stmm bus_space_tag_t sc_tag; 5990619Stmm bus_space_handle_t sc_handle; 6090619Stmm bus_addr_t sc_offset; 6190619Stmm}; 6290619Stmm 6390619Stmm 6490619Stmm/* 6590619Stmm * This is called from the psycho and sbus drivers. It does not directly attach 6690619Stmm * to the nexus because it shares register space with the bridge in question. 6790619Stmm */ 6890619Stmmvoid 6990619Stmmsparc64_counter_init(bus_space_tag_t tag, bus_space_handle_t handle, 7090619Stmm bus_addr_t offset) 7190619Stmm{ 7290619Stmm struct timecounter *tc; 7390619Stmm struct ct_softc *sc; 7490619Stmm 7590619Stmm printf("initialializing counter-timer\n"); 7690619Stmm /* 7790619Stmm * Turn off interrupts from both counters. Set the limit to the maximum 7890619Stmm * value (although that should not change anything with CTLR_INTEN and 7990619Stmm * CTLR_PERIODIC off). 8090619Stmm */ 8190619Stmm bus_space_write_8(tag, handle, offset + CTR_CT0 + CTR_LIMIT 8290619Stmm , COUNTER_MASK); 8390619Stmm bus_space_write_8(tag, handle, offset + CTR_CT1 + CTR_LIMIT, 8490619Stmm COUNTER_MASK); 8590619Stmm /* Register as a time counter. */ 8690619Stmm tc = malloc(sizeof(*tc), M_DEVBUF, M_WAITOK); 8790619Stmm sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK); 8890619Stmm sc->sc_tag = tag; 8990619Stmm sc->sc_handle = handle; 9090619Stmm sc->sc_offset = offset + CTR_CT0; 9190619Stmm tc->tc_get_timecount = counter_get_timecount; 9290619Stmm tc->tc_poll_pps = NULL; 9390619Stmm tc->tc_counter_mask = COUNTER_MASK; 9490619Stmm tc->tc_frequency = COUNTER_FREQ; 9590619Stmm tc->tc_name = "counter-timer"; 9690619Stmm tc->tc_priv = sc; 9790619Stmm tc_init(tc); 9890619Stmm} 9990619Stmm 10090619Stmmstatic unsigned 10190619Stmmcounter_get_timecount(struct timecounter *tc) 10290619Stmm{ 10390619Stmm struct ct_softc *sc; 10490619Stmm 10590619Stmm sc = tc->tc_priv; 10690619Stmm return (bus_space_read_8(sc->sc_tag, sc->sc_handle, sc->sc_offset) & 10790619Stmm COUNTER_MASK); 10890619Stmm} 10990619Stmm 110