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 26178840Smarius#include <sys/cdefs.h> 27178840Smarius__FBSDID("$FreeBSD$"); 28178840Smarius 2990619Stmm#include <sys/param.h> 3090619Stmm#include <sys/bus.h> 3190619Stmm#include <sys/malloc.h> 3290619Stmm#include <sys/systm.h> 3390619Stmm#include <sys/time.h> 3490619Stmm#include <sys/timetc.h> 3590619Stmm 3690619Stmm#include <machine/bus.h> 3790619Stmm#include <machine/bus_common.h> 3890619Stmm 3990619Stmm#define COUNTER_MASK ((1 << 29) - 1) 4090619Stmm#define COUNTER_FREQ 1000000 41135971Skensmith#define COUNTER_QUALITY 100 4290619Stmm 4390619Stmm/* Bits in the limit register. */ 4490619Stmm#define CTLR_INTEN (1U << 31) /* Enable timer interrupts */ 4590619Stmm#define CTLR_RELOAD (1U << 30) /* Zero counter on write to limit reg */ 4690619Stmm#define CTLR_PERIODIC (1U << 29) /* Wrap to 0 if limit is reached */ 4790619Stmm 4890619Stmm/* Offsets of the registers for the two counters. */ 4990619Stmm#define CTR_CT0 0x00 5090619Stmm#define CTR_CT1 0x10 5190619Stmm 5290619Stmm/* Register offsets from the base address. */ 5390619Stmm#define CTR_COUNT 0x00 5490619Stmm#define CTR_LIMIT 0x08 5590619Stmm 5690619Stmm 57178840Smariusstatic timecounter_get_t counter_get_timecount; 5890619Stmm 5990619Stmmstruct ct_softc { 6090619Stmm bus_space_tag_t sc_tag; 6190619Stmm bus_space_handle_t sc_handle; 6290619Stmm bus_addr_t sc_offset; 6390619Stmm}; 6490619Stmm 6590619Stmm 6690619Stmm/* 67178840Smarius * This is called from the psycho and sbus drivers. It does not directly 68178840Smarius * attach to the nexus because it shares register space with the bridge in 69178840Smarius * question. 7090619Stmm */ 7190619Stmmvoid 72178840Smariussparc64_counter_init(const char *name, bus_space_tag_t tag, 73178840Smarius bus_space_handle_t handle, bus_addr_t offset) 7490619Stmm{ 7590619Stmm struct timecounter *tc; 7690619Stmm struct ct_softc *sc; 7790619Stmm 78129083Smux printf("initializing counter-timer\n"); 7990619Stmm /* 80178840Smarius * Turn off interrupts from both counters. Set the limit to the 81178840Smarius * maximum value (although that should not change anything with 82178840Smarius * CTLR_INTEN and CTLR_PERIODIC off). 8390619Stmm */ 84129083Smux bus_space_write_8(tag, handle, offset + CTR_CT0 + CTR_LIMIT, 85129083Smux COUNTER_MASK); 8690619Stmm bus_space_write_8(tag, handle, offset + CTR_CT1 + CTR_LIMIT, 8790619Stmm COUNTER_MASK); 8890619Stmm /* Register as a time counter. */ 89223961Smarius tc = malloc(sizeof(*tc), M_DEVBUF, M_WAITOK | M_ZERO); 90111119Simp sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK); 9190619Stmm sc->sc_tag = tag; 9290619Stmm sc->sc_handle = handle; 9390619Stmm sc->sc_offset = offset + CTR_CT0; 9490619Stmm tc->tc_get_timecount = counter_get_timecount; 9590619Stmm tc->tc_counter_mask = COUNTER_MASK; 9690619Stmm tc->tc_frequency = COUNTER_FREQ; 97178840Smarius tc->tc_name = strdup(name, M_DEVBUF); 9890619Stmm tc->tc_priv = sc; 99135971Skensmith tc->tc_quality = COUNTER_QUALITY; 10090619Stmm tc_init(tc); 10190619Stmm} 10290619Stmm 103129083Smuxstatic unsigned int 10490619Stmmcounter_get_timecount(struct timecounter *tc) 10590619Stmm{ 10690619Stmm struct ct_softc *sc; 10790619Stmm 10890619Stmm sc = tc->tc_priv; 109223961Smarius return (bus_space_read_8(sc->sc_tag, sc->sc_handle, sc->sc_offset)); 11090619Stmm} 111