mkclock.c revision 1.3
11.3Stsutsui/* $NetBSD: mkclock.c,v 1.3 2008/03/28 20:26:13 tsutsui Exp $ */ 21.1Stsutsui 31.1Stsutsui/* 41.1Stsutsui * Copyright (c) 1992, 1993 51.1Stsutsui * The Regents of the University of California. All rights reserved. 61.1Stsutsui * Copyright (c) 1994 Gordon W. Ross 71.1Stsutsui * Copyright (c) 1993 Adam Glass 81.1Stsutsui * Copyright (c) 1996 Paul Kranenburg 91.1Stsutsui * Copyright (c) 1996 101.1Stsutsui * The President and Fellows of Harvard College. All rights reserved. 111.1Stsutsui * 121.1Stsutsui * This software was developed by the Computer Systems Engineering group 131.1Stsutsui * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 141.1Stsutsui * contributed to Berkeley. 151.1Stsutsui * 161.1Stsutsui * All advertising materials mentioning features or use of this software 171.1Stsutsui * must display the following acknowledgement: 181.1Stsutsui * This product includes software developed by Harvard University. 191.1Stsutsui * This product includes software developed by the University of 201.1Stsutsui * California, Lawrence Berkeley Laboratory. 211.1Stsutsui * 221.1Stsutsui * Redistribution and use in source and binary forms, with or without 231.1Stsutsui * modification, are permitted provided that the following conditions 241.1Stsutsui * are met: 251.1Stsutsui * 261.1Stsutsui * 1. Redistributions of source code must retain the above copyright 271.1Stsutsui * notice, this list of conditions and the following disclaimer. 281.1Stsutsui * 2. Redistributions in binary form must reproduce the above copyright 291.1Stsutsui * notice, this list of conditions and the following disclaimer in the 301.1Stsutsui * documentation and/or other materials provided with the distribution. 311.1Stsutsui * 3. All advertising materials mentioning features or use of this software 321.1Stsutsui * must display the following acknowledgement: 331.1Stsutsui * This product includes software developed by the University of 341.1Stsutsui * California, Berkeley and its contributors. 351.1Stsutsui * This product includes software developed by Paul Kranenburg. 361.1Stsutsui * This product includes software developed by Harvard University. 371.1Stsutsui * 4. Neither the name of the University nor the names of its contributors 381.1Stsutsui * may be used to endorse or promote products derived from this software 391.1Stsutsui * without specific prior written permission. 401.1Stsutsui * 411.1Stsutsui * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 421.1Stsutsui * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 431.1Stsutsui * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 441.1Stsutsui * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 451.1Stsutsui * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 461.1Stsutsui * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 471.1Stsutsui * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 481.1Stsutsui * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 491.1Stsutsui * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 501.1Stsutsui * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 511.1Stsutsui * SUCH DAMAGE. 521.1Stsutsui * 531.1Stsutsui * @(#)clock.c 8.1 (Berkeley) 6/11/93 541.1Stsutsui * 551.1Stsutsui */ 561.1Stsutsui 571.1Stsutsui#include <sys/cdefs.h> 581.3Stsutsui__KERNEL_RCSID(0, "$NetBSD: mkclock.c,v 1.3 2008/03/28 20:26:13 tsutsui Exp $"); 591.1Stsutsui 601.1Stsutsui/* 611.1Stsutsui * Clock driver for 'mkclock' - Mostek MK48Txx TOD clock. 621.1Stsutsui */ 631.1Stsutsui 641.1Stsutsui#include <sys/param.h> 651.1Stsutsui#include <sys/kernel.h> 661.1Stsutsui#include <sys/device.h> 671.1Stsutsui#include <sys/proc.h> 681.1Stsutsui#include <sys/resourcevar.h> 691.1Stsutsui#include <sys/malloc.h> 701.1Stsutsui#include <sys/systm.h> 711.1Stsutsui 721.1Stsutsui#include <uvm/uvm_extern.h> 731.1Stsutsui 741.1Stsutsui#include <machine/bus.h> 751.1Stsutsui#include <machine/autoconf.h> 761.1Stsutsui#include <machine/eeprom.h> 771.1Stsutsui#include <machine/cpu.h> 781.1Stsutsui 791.1Stsutsui#include <dev/clock_subr.h> 801.1Stsutsui#include <dev/ic/mk48txxreg.h> 811.1Stsutsui#include <dev/ic/mk48txxvar.h> 821.1Stsutsui 831.1Stsutsui#include <sparc64/dev/iommureg.h> 841.1Stsutsui#include <sparc64/dev/sbusreg.h> 851.1Stsutsui#include <dev/sbus/sbusvar.h> 861.1Stsutsui#include <dev/ebus/ebusreg.h> 871.1Stsutsui#include <dev/ebus/ebusvar.h> 881.1Stsutsui 891.1Stsutsui/* 901.1Stsutsui * clock (eeprom) attaches at the sbus or the ebus (PCI) 911.1Stsutsui */ 921.3Stsutsuistatic int mkclock_sbus_match(device_t, cfdata_t, void *); 931.3Stsutsuistatic void mkclock_sbus_attach(device_t, device_t, void *); 941.1Stsutsui 951.3Stsutsuistatic int mkclock_ebus_match(device_t, cfdata_t, void *); 961.3Stsutsuistatic void mkclock_ebus_attach(device_t, device_t, void *); 971.1Stsutsui 981.1Stsutsuistatic void mkclock_attach(struct mk48txx_softc *, int); 991.1Stsutsui 1001.1Stsutsuistatic int mkclock_wenable(struct todr_chip_handle *, int); 1011.1Stsutsui 1021.1Stsutsui 1031.3StsutsuiCFATTACH_DECL_NEW(mkclock_sbus, sizeof(struct mk48txx_softc), 1041.1Stsutsui mkclock_sbus_match, mkclock_sbus_attach, NULL, NULL); 1051.1Stsutsui 1061.3StsutsuiCFATTACH_DECL_NEW(mkclock_ebus, sizeof(struct mk48txx_softc), 1071.1Stsutsui mkclock_ebus_match, mkclock_ebus_attach, NULL, NULL); 1081.1Stsutsui 1091.1Stsutsui/* 1101.1Stsutsui * The OPENPROM calls the clock the "eeprom", so we have to have our 1111.1Stsutsui * own special match function to call it the "clock". 1121.1Stsutsui */ 1131.1Stsutsuistatic int 1141.3Stsutsuimkclock_sbus_match(device_t parent, cfdata_t cf, void *aux) 1151.1Stsutsui{ 1161.1Stsutsui struct sbus_attach_args *sa = aux; 1171.1Stsutsui 1181.1Stsutsui return (strcmp("eeprom", sa->sa_name) == 0); 1191.1Stsutsui} 1201.1Stsutsui 1211.1Stsutsuistatic int 1221.3Stsutsuimkclock_ebus_match(device_t parent, cfdata_t cf, void *aux) 1231.1Stsutsui{ 1241.1Stsutsui struct ebus_attach_args *ea = aux; 1251.1Stsutsui 1261.1Stsutsui return (strcmp("eeprom", ea->ea_name) == 0); 1271.1Stsutsui} 1281.1Stsutsui 1291.1Stsutsui/* 1301.1Stsutsui * Attach a clock (really `eeprom') to the sbus or ebus. 1311.1Stsutsui * 1321.1Stsutsui * We ignore any existing virtual address as we need to map 1331.1Stsutsui * this read-only and make it read-write only temporarily, 1341.1Stsutsui * whenever we read or write the clock chip. The clock also 1351.1Stsutsui * contains the ID ``PROM'', and I have already had the pleasure 1361.1Stsutsui * of reloading the CPU type, Ethernet address, etc, by hand from 1371.1Stsutsui * the console FORTH interpreter. I intend not to enjoy it again. 1381.1Stsutsui * 1391.1Stsutsui * the MK48T02 is 2K. the MK48T08 is 8K, and the MK48T59 is 1401.1Stsutsui * supposed to be identical to it. 1411.1Stsutsui * 1421.1Stsutsui * This is *UGLY*! We probably have multiple mappings. But I do 1431.1Stsutsui * know that this all fits inside an 8K page, so I'll just map in 1441.1Stsutsui * once. 1451.1Stsutsui * 1461.1Stsutsui * What we really need is some way to record the bus attach args 1471.1Stsutsui * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY 1481.1Stsutsui * or not to write enable/disable the device registers. This is 1491.1Stsutsui * a non-trivial operation. 1501.1Stsutsui */ 1511.1Stsutsui 1521.1Stsutsui/* ARGSUSED */ 1531.1Stsutsuistatic void 1541.3Stsutsuimkclock_sbus_attach(device_t parent, device_t self, void *aux) 1551.1Stsutsui{ 1561.3Stsutsui struct mk48txx_softc *sc = device_private(self); 1571.1Stsutsui struct sbus_attach_args *sa = aux; 1581.1Stsutsui int sz; 1591.1Stsutsui 1601.1Stsutsui sc->sc_bst = sa->sa_bustag; 1611.1Stsutsui 1621.1Stsutsui /* use sa->sa_regs[0].size? */ 1631.1Stsutsui sz = 8192; 1641.1Stsutsui 1651.1Stsutsui if (sbus_bus_map(sc->sc_bst, 1661.1Stsutsui sa->sa_slot, 1671.1Stsutsui (sa->sa_offset & ~(PAGE_SIZE - 1)), 1681.1Stsutsui sz, 1691.1Stsutsui BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 1701.1Stsutsui &sc->sc_bsh) != 0) { 1711.3Stsutsui aprint_error(": can't map register\n"); 1721.1Stsutsui return; 1731.1Stsutsui } 1741.1Stsutsui mkclock_attach(sc, sa->sa_node); 1751.1Stsutsui} 1761.1Stsutsui 1771.1Stsutsui 1781.1Stsutsui/* ARGSUSED */ 1791.1Stsutsuistatic void 1801.1Stsutsuimkclock_ebus_attach(struct device *parent, struct device *self, void *aux) 1811.1Stsutsui{ 1821.1Stsutsui struct mk48txx_softc *sc = (void *)self; 1831.1Stsutsui struct ebus_attach_args *ea = aux; 1841.1Stsutsui int sz; 1851.1Stsutsui 1861.1Stsutsui sc->sc_bst = ea->ea_bustag; 1871.1Stsutsui 1881.1Stsutsui /* hard code to 8K? */ 1891.1Stsutsui sz = ea->ea_reg[0].size; 1901.1Stsutsui 1911.1Stsutsui if (bus_space_map(sc->sc_bst, 1921.1Stsutsui EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 1931.1Stsutsui sz, 1941.1Stsutsui BUS_SPACE_MAP_LINEAR, 1951.1Stsutsui &sc->sc_bsh) != 0) { 1961.3Stsutsui aprint_error(": can't map register\n"); 1971.1Stsutsui return; 1981.1Stsutsui } 1991.1Stsutsui mkclock_attach(sc, ea->ea_node); 2001.1Stsutsui} 2011.1Stsutsui 2021.1Stsutsui 2031.1Stsutsuistatic void 2041.1Stsutsuimkclock_attach(struct mk48txx_softc *sc, int node) 2051.1Stsutsui{ 2061.1Stsutsui 2071.1Stsutsui sc->sc_model = prom_getpropstring(node, "model"); 2081.1Stsutsui 2091.1Stsutsui#ifdef DIAGNOSTIC 2101.1Stsutsui if (sc->sc_model == NULL) 2111.1Stsutsui panic("clockattach: no model property"); 2121.1Stsutsui#endif 2131.1Stsutsui 2141.1Stsutsui /* Our TOD clock year 0 is 1968 */ 2151.1Stsutsui sc->sc_year0 = 1968; 2161.1Stsutsui 2171.1Stsutsui /* Save info for the clock wenable call. */ 2181.1Stsutsui sc->sc_handle.todr_setwen = mkclock_wenable; 2191.1Stsutsui 2201.2Stsutsui mk48txx_attach(sc); 2211.2Stsutsui 2221.3Stsutsui aprint_normal("\n"); 2231.1Stsutsui} 2241.1Stsutsui 2251.1Stsutsui/* 2261.1Stsutsui * Write en/dis-able clock registers. We coordinate so that several 2271.1Stsutsui * writers can run simultaneously. 2281.1Stsutsui */ 2291.1Stsutsuistatic int 2301.1Stsutsuimkclock_wenable(struct todr_chip_handle *handle, int onoff) 2311.1Stsutsui{ 2321.1Stsutsui struct mk48txx_softc *sc; 2331.1Stsutsui vm_prot_t prot; 2341.1Stsutsui vaddr_t va; 2351.1Stsutsui int s, err = 0; 2361.1Stsutsui static int writers; 2371.1Stsutsui 2381.1Stsutsui s = splhigh(); 2391.1Stsutsui if (onoff) 2401.1Stsutsui prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0; 2411.1Stsutsui else 2421.1Stsutsui prot = --writers == 0 ? VM_PROT_READ : 0; 2431.1Stsutsui splx(s); 2441.1Stsutsui if (prot == VM_PROT_NONE) { 2451.1Stsutsui return 0; 2461.1Stsutsui } 2471.1Stsutsui sc = handle->cookie; 2481.1Stsutsui va = (vaddr_t)bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 2491.1Stsutsui if (va == 0UL) { 2501.1Stsutsui printf("clock_wenable: WARNING -- cannot get va\n"); 2511.1Stsutsui return EIO; 2521.1Stsutsui } 2531.1Stsutsui pmap_kprotect(va, prot); 2541.1Stsutsui return (err); 2551.1Stsutsui} 256