mkclock.c revision 1.9
11.9Smrg/* $NetBSD: mkclock.c,v 1.9 2011/07/29 08:37:36 mrg 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.9Smrg__KERNEL_RCSID(0, "$NetBSD: mkclock.c,v 1.9 2011/07/29 08:37:36 mrg 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.8Sdyoung#include <sys/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 <dev/sbus/sbusvar.h> 841.1Stsutsui#include <dev/ebus/ebusreg.h> 851.1Stsutsui#include <dev/ebus/ebusvar.h> 861.1Stsutsui 871.9Smrg#include <sparc64/dev/fhcvar.h> 881.9Smrg 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.9Smrgstatic int mkclock_fhc_match(device_t, cfdata_t, void *); 991.9Smrgstatic void mkclock_fhc_attach(device_t, device_t, void *); 1001.9Smrg 1011.1Stsutsuistatic void mkclock_attach(struct mk48txx_softc *, int); 1021.1Stsutsui 1031.1Stsutsuistatic int mkclock_wenable(struct todr_chip_handle *, int); 1041.1Stsutsui 1051.1Stsutsui 1061.3StsutsuiCFATTACH_DECL_NEW(mkclock_sbus, sizeof(struct mk48txx_softc), 1071.1Stsutsui mkclock_sbus_match, mkclock_sbus_attach, NULL, NULL); 1081.1Stsutsui 1091.3StsutsuiCFATTACH_DECL_NEW(mkclock_ebus, sizeof(struct mk48txx_softc), 1101.1Stsutsui mkclock_ebus_match, mkclock_ebus_attach, NULL, NULL); 1111.1Stsutsui 1121.9SmrgCFATTACH_DECL_NEW(mkclock_fhc, sizeof(struct mk48txx_softc), 1131.9Smrg mkclock_fhc_match, mkclock_fhc_attach, NULL, NULL); 1141.9Smrg 1151.1Stsutsui/* 1161.1Stsutsui * The OPENPROM calls the clock the "eeprom", so we have to have our 1171.1Stsutsui * own special match function to call it the "clock". 1181.1Stsutsui */ 1191.1Stsutsuistatic int 1201.3Stsutsuimkclock_sbus_match(device_t parent, cfdata_t cf, void *aux) 1211.1Stsutsui{ 1221.1Stsutsui struct sbus_attach_args *sa = aux; 1231.1Stsutsui 1241.1Stsutsui return (strcmp("eeprom", sa->sa_name) == 0); 1251.1Stsutsui} 1261.1Stsutsui 1271.1Stsutsuistatic int 1281.3Stsutsuimkclock_ebus_match(device_t parent, cfdata_t cf, void *aux) 1291.1Stsutsui{ 1301.1Stsutsui struct ebus_attach_args *ea = aux; 1311.1Stsutsui 1321.1Stsutsui return (strcmp("eeprom", ea->ea_name) == 0); 1331.1Stsutsui} 1341.1Stsutsui 1351.9Smrgstatic int 1361.9Smrgmkclock_fhc_match(device_t parent, cfdata_t cf, void *aux) 1371.9Smrg{ 1381.9Smrg struct fhc_attach_args *fa = aux; 1391.9Smrg 1401.9Smrg return (strcmp("eeprom", fa->fa_name) == 0); 1411.9Smrg} 1421.9Smrg 1431.1Stsutsui/* 1441.1Stsutsui * Attach a clock (really `eeprom') to the sbus or ebus. 1451.1Stsutsui * 1461.1Stsutsui * We ignore any existing virtual address as we need to map 1471.1Stsutsui * this read-only and make it read-write only temporarily, 1481.1Stsutsui * whenever we read or write the clock chip. The clock also 1491.1Stsutsui * contains the ID ``PROM'', and I have already had the pleasure 1501.1Stsutsui * of reloading the CPU type, Ethernet address, etc, by hand from 1511.1Stsutsui * the console FORTH interpreter. I intend not to enjoy it again. 1521.1Stsutsui * 1531.1Stsutsui * the MK48T02 is 2K. the MK48T08 is 8K, and the MK48T59 is 1541.1Stsutsui * supposed to be identical to it. 1551.1Stsutsui * 1561.1Stsutsui * This is *UGLY*! We probably have multiple mappings. But I do 1571.1Stsutsui * know that this all fits inside an 8K page, so I'll just map in 1581.1Stsutsui * once. 1591.1Stsutsui * 1601.1Stsutsui * What we really need is some way to record the bus attach args 1611.1Stsutsui * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY 1621.1Stsutsui * or not to write enable/disable the device registers. This is 1631.1Stsutsui * a non-trivial operation. 1641.1Stsutsui */ 1651.1Stsutsui 1661.1Stsutsui/* ARGSUSED */ 1671.1Stsutsuistatic void 1681.3Stsutsuimkclock_sbus_attach(device_t parent, device_t self, void *aux) 1691.1Stsutsui{ 1701.3Stsutsui struct mk48txx_softc *sc = device_private(self); 1711.1Stsutsui struct sbus_attach_args *sa = aux; 1721.1Stsutsui int sz; 1731.1Stsutsui 1741.5Stsutsui sc->sc_dev = self; 1751.1Stsutsui sc->sc_bst = sa->sa_bustag; 1761.1Stsutsui 1771.1Stsutsui /* use sa->sa_regs[0].size? */ 1781.1Stsutsui sz = 8192; 1791.1Stsutsui 1801.1Stsutsui if (sbus_bus_map(sc->sc_bst, 1811.1Stsutsui sa->sa_slot, 1821.6Snakayama trunc_page(sa->sa_offset), 1831.1Stsutsui sz, 1841.1Stsutsui BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 1851.1Stsutsui &sc->sc_bsh) != 0) { 1861.3Stsutsui aprint_error(": can't map register\n"); 1871.1Stsutsui return; 1881.1Stsutsui } 1891.1Stsutsui mkclock_attach(sc, sa->sa_node); 1901.1Stsutsui} 1911.1Stsutsui 1921.1Stsutsui 1931.1Stsutsui/* ARGSUSED */ 1941.1Stsutsuistatic void 1951.1Stsutsuimkclock_ebus_attach(struct device *parent, struct device *self, void *aux) 1961.1Stsutsui{ 1971.4Stsutsui struct mk48txx_softc *sc = device_private(self); 1981.1Stsutsui struct ebus_attach_args *ea = aux; 1991.1Stsutsui int sz; 2001.1Stsutsui 2011.5Stsutsui sc->sc_dev = self; 2021.1Stsutsui sc->sc_bst = ea->ea_bustag; 2031.1Stsutsui 2041.1Stsutsui /* hard code to 8K? */ 2051.1Stsutsui sz = ea->ea_reg[0].size; 2061.1Stsutsui 2071.1Stsutsui if (bus_space_map(sc->sc_bst, 2081.1Stsutsui EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 2091.1Stsutsui sz, 2101.1Stsutsui BUS_SPACE_MAP_LINEAR, 2111.1Stsutsui &sc->sc_bsh) != 0) { 2121.3Stsutsui aprint_error(": can't map register\n"); 2131.1Stsutsui return; 2141.1Stsutsui } 2151.1Stsutsui mkclock_attach(sc, ea->ea_node); 2161.1Stsutsui} 2171.1Stsutsui 2181.9Smrg/* ARGSUSED */ 2191.9Smrgstatic void 2201.9Smrgmkclock_fhc_attach(struct device *parent, struct device *self, void *aux) 2211.9Smrg{ 2221.9Smrg struct mk48txx_softc *sc = device_private(self); 2231.9Smrg struct fhc_attach_args *fa = aux; 2241.9Smrg 2251.9Smrg sc->sc_dev = self; 2261.9Smrg sc->sc_bst = fa->fa_bustag; 2271.9Smrg 2281.9Smrg if (fhc_bus_map(sc->sc_bst, 2291.9Smrg fa->fa_reg[0].fbr_slot, 2301.9Smrg (fa->fa_reg[0].fbr_offset & ~NBPG), 2311.9Smrg fa->fa_reg[0].fbr_size, 2321.9Smrg BUS_SPACE_MAP_LINEAR, 2331.9Smrg &sc->sc_bsh) != 0) { 2341.9Smrg aprint_error(": can't map register\n"); 2351.9Smrg return; 2361.9Smrg } 2371.9Smrg mkclock_attach(sc, fa->fa_node); 2381.9Smrg} 2391.9Smrg 2401.1Stsutsui 2411.1Stsutsuistatic void 2421.1Stsutsuimkclock_attach(struct mk48txx_softc *sc, int node) 2431.1Stsutsui{ 2441.1Stsutsui 2451.1Stsutsui sc->sc_model = prom_getpropstring(node, "model"); 2461.1Stsutsui 2471.1Stsutsui#ifdef DIAGNOSTIC 2481.1Stsutsui if (sc->sc_model == NULL) 2491.1Stsutsui panic("clockattach: no model property"); 2501.1Stsutsui#endif 2511.1Stsutsui 2521.1Stsutsui /* Our TOD clock year 0 is 1968 */ 2531.1Stsutsui sc->sc_year0 = 1968; 2541.1Stsutsui 2551.1Stsutsui /* Save info for the clock wenable call. */ 2561.1Stsutsui sc->sc_handle.todr_setwen = mkclock_wenable; 2571.1Stsutsui 2581.2Stsutsui mk48txx_attach(sc); 2591.2Stsutsui 2601.3Stsutsui aprint_normal("\n"); 2611.1Stsutsui} 2621.1Stsutsui 2631.1Stsutsui/* 2641.1Stsutsui * Write en/dis-able clock registers. We coordinate so that several 2651.1Stsutsui * writers can run simultaneously. 2661.1Stsutsui */ 2671.1Stsutsuistatic int 2681.1Stsutsuimkclock_wenable(struct todr_chip_handle *handle, int onoff) 2691.1Stsutsui{ 2701.1Stsutsui struct mk48txx_softc *sc; 2711.1Stsutsui vm_prot_t prot; 2721.1Stsutsui vaddr_t va; 2731.1Stsutsui int s, err = 0; 2741.1Stsutsui static int writers; 2751.1Stsutsui 2761.1Stsutsui s = splhigh(); 2771.1Stsutsui if (onoff) 2781.1Stsutsui prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0; 2791.1Stsutsui else 2801.1Stsutsui prot = --writers == 0 ? VM_PROT_READ : 0; 2811.1Stsutsui splx(s); 2821.1Stsutsui if (prot == VM_PROT_NONE) { 2831.1Stsutsui return 0; 2841.1Stsutsui } 2851.1Stsutsui sc = handle->cookie; 2861.1Stsutsui va = (vaddr_t)bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 2871.1Stsutsui if (va == 0UL) { 2881.1Stsutsui printf("clock_wenable: WARNING -- cannot get va\n"); 2891.1Stsutsui return EIO; 2901.1Stsutsui } 2911.1Stsutsui pmap_kprotect(va, prot); 2921.1Stsutsui return (err); 2931.1Stsutsui} 294