11.14Sthorpej/* $NetBSD: mkclock.c,v 1.14 2025/09/07 21:45:15 thorpej 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.14Sthorpej__KERNEL_RCSID(0, "$NetBSD: mkclock.c,v 1.14 2025/09/07 21:45:15 thorpej 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/systm.h> 701.1Stsutsui 711.1Stsutsui#include <uvm/uvm_extern.h> 721.1Stsutsui 731.8Sdyoung#include <sys/bus.h> 741.1Stsutsui#include <machine/autoconf.h> 751.1Stsutsui#include <machine/eeprom.h> 761.1Stsutsui#include <machine/cpu.h> 771.1Stsutsui 781.1Stsutsui#include <dev/clock_subr.h> 791.1Stsutsui#include <dev/ic/mk48txxreg.h> 801.1Stsutsui#include <dev/ic/mk48txxvar.h> 811.1Stsutsui 821.1Stsutsui#include <dev/sbus/sbusvar.h> 831.1Stsutsui#include <dev/ebus/ebusreg.h> 841.1Stsutsui#include <dev/ebus/ebusvar.h> 851.1Stsutsui 861.9Smrg#include <sparc64/dev/fhcvar.h> 871.9Smrg 881.1Stsutsui/* 891.1Stsutsui * clock (eeprom) attaches at the sbus or the ebus (PCI) 901.1Stsutsui */ 911.3Stsutsuistatic int mkclock_sbus_match(device_t, cfdata_t, void *); 921.3Stsutsuistatic void mkclock_sbus_attach(device_t, device_t, void *); 931.1Stsutsui 941.3Stsutsuistatic int mkclock_ebus_match(device_t, cfdata_t, void *); 951.3Stsutsuistatic void mkclock_ebus_attach(device_t, device_t, void *); 961.1Stsutsui 971.9Smrgstatic int mkclock_fhc_match(device_t, cfdata_t, void *); 981.9Smrgstatic void mkclock_fhc_attach(device_t, device_t, void *); 991.9Smrg 1001.1Stsutsuistatic void mkclock_attach(struct mk48txx_softc *, int); 1011.1Stsutsui 1021.1Stsutsuistatic int mkclock_wenable(struct todr_chip_handle *, int); 1031.1Stsutsui 1041.1Stsutsui 1051.3StsutsuiCFATTACH_DECL_NEW(mkclock_sbus, sizeof(struct mk48txx_softc), 1061.1Stsutsui mkclock_sbus_match, mkclock_sbus_attach, NULL, NULL); 1071.1Stsutsui 1081.3StsutsuiCFATTACH_DECL_NEW(mkclock_ebus, sizeof(struct mk48txx_softc), 1091.1Stsutsui mkclock_ebus_match, mkclock_ebus_attach, NULL, NULL); 1101.1Stsutsui 1111.9SmrgCFATTACH_DECL_NEW(mkclock_fhc, sizeof(struct mk48txx_softc), 1121.9Smrg mkclock_fhc_match, mkclock_fhc_attach, NULL, NULL); 1131.9Smrg 1141.1Stsutsui/* 1151.1Stsutsui * The OPENPROM calls the clock the "eeprom", so we have to have our 1161.1Stsutsui * own special match function to call it the "clock". 1171.1Stsutsui */ 1181.1Stsutsuistatic int 1191.3Stsutsuimkclock_sbus_match(device_t parent, cfdata_t cf, void *aux) 1201.1Stsutsui{ 1211.1Stsutsui struct sbus_attach_args *sa = aux; 1221.1Stsutsui 1231.1Stsutsui return (strcmp("eeprom", sa->sa_name) == 0); 1241.1Stsutsui} 1251.1Stsutsui 1261.1Stsutsuistatic int 1271.3Stsutsuimkclock_ebus_match(device_t parent, cfdata_t cf, void *aux) 1281.1Stsutsui{ 1291.1Stsutsui struct ebus_attach_args *ea = aux; 1301.1Stsutsui 1311.1Stsutsui return (strcmp("eeprom", ea->ea_name) == 0); 1321.1Stsutsui} 1331.1Stsutsui 1341.9Smrgstatic int 1351.9Smrgmkclock_fhc_match(device_t parent, cfdata_t cf, void *aux) 1361.9Smrg{ 1371.9Smrg struct fhc_attach_args *fa = aux; 1381.9Smrg 1391.9Smrg return (strcmp("eeprom", fa->fa_name) == 0); 1401.9Smrg} 1411.9Smrg 1421.1Stsutsui/* 1431.1Stsutsui * Attach a clock (really `eeprom') to the sbus or ebus. 1441.1Stsutsui * 1451.1Stsutsui * We ignore any existing virtual address as we need to map 1461.1Stsutsui * this read-only and make it read-write only temporarily, 1471.1Stsutsui * whenever we read or write the clock chip. The clock also 1481.1Stsutsui * contains the ID ``PROM'', and I have already had the pleasure 1491.1Stsutsui * of reloading the CPU type, Ethernet address, etc, by hand from 1501.1Stsutsui * the console FORTH interpreter. I intend not to enjoy it again. 1511.1Stsutsui * 1521.1Stsutsui * the MK48T02 is 2K. the MK48T08 is 8K, and the MK48T59 is 1531.1Stsutsui * supposed to be identical to it. 1541.1Stsutsui * 1551.1Stsutsui * This is *UGLY*! We probably have multiple mappings. But I do 1561.1Stsutsui * know that this all fits inside an 8K page, so I'll just map in 1571.1Stsutsui * once. 1581.1Stsutsui * 1591.1Stsutsui * What we really need is some way to record the bus attach args 1601.1Stsutsui * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY 1611.1Stsutsui * or not to write enable/disable the device registers. This is 1621.1Stsutsui * a non-trivial operation. 1631.1Stsutsui */ 1641.1Stsutsui 1651.1Stsutsui/* ARGSUSED */ 1661.1Stsutsuistatic void 1671.3Stsutsuimkclock_sbus_attach(device_t parent, device_t self, void *aux) 1681.1Stsutsui{ 1691.3Stsutsui struct mk48txx_softc *sc = device_private(self); 1701.1Stsutsui struct sbus_attach_args *sa = aux; 1711.1Stsutsui int sz; 1721.1Stsutsui 1731.5Stsutsui sc->sc_dev = self; 1741.1Stsutsui sc->sc_bst = sa->sa_bustag; 1751.1Stsutsui 1761.1Stsutsui /* use sa->sa_regs[0].size? */ 1771.1Stsutsui sz = 8192; 1781.1Stsutsui 1791.1Stsutsui if (sbus_bus_map(sc->sc_bst, 1801.1Stsutsui sa->sa_slot, 1811.6Snakayama trunc_page(sa->sa_offset), 1821.1Stsutsui sz, 1831.1Stsutsui BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 1841.1Stsutsui &sc->sc_bsh) != 0) { 1851.3Stsutsui aprint_error(": can't map register\n"); 1861.1Stsutsui return; 1871.1Stsutsui } 1881.1Stsutsui mkclock_attach(sc, sa->sa_node); 1891.1Stsutsui} 1901.1Stsutsui 1911.1Stsutsui 1921.1Stsutsui/* ARGSUSED */ 1931.1Stsutsuistatic void 1941.12Schsmkclock_ebus_attach(device_t parent, device_t self, void *aux) 1951.1Stsutsui{ 1961.4Stsutsui struct mk48txx_softc *sc = device_private(self); 1971.1Stsutsui struct ebus_attach_args *ea = aux; 1981.1Stsutsui int sz; 1991.1Stsutsui 2001.5Stsutsui sc->sc_dev = self; 2011.1Stsutsui sc->sc_bst = ea->ea_bustag; 2021.1Stsutsui 2031.1Stsutsui /* hard code to 8K? */ 2041.1Stsutsui sz = ea->ea_reg[0].size; 2051.1Stsutsui 2061.11Sjdc /* Use the PROM address if there. */ 2071.11Sjdc if (ea->ea_nvaddr) 2081.11Sjdc sparc_promaddr_to_handle(sc->sc_bst, ea->ea_vaddr[0], 2091.11Sjdc &sc->sc_bsh); 2101.11Sjdc else if (bus_space_map(sc->sc_bst, 2111.1Stsutsui EBUS_ADDR_FROM_REG(&ea->ea_reg[0]), 2121.1Stsutsui sz, 2131.1Stsutsui BUS_SPACE_MAP_LINEAR, 2141.1Stsutsui &sc->sc_bsh) != 0) { 2151.3Stsutsui aprint_error(": can't map register\n"); 2161.1Stsutsui return; 2171.1Stsutsui } 2181.1Stsutsui mkclock_attach(sc, ea->ea_node); 2191.1Stsutsui} 2201.1Stsutsui 2211.9Smrg/* ARGSUSED */ 2221.9Smrgstatic void 2231.12Schsmkclock_fhc_attach(device_t parent, device_t self, void *aux) 2241.9Smrg{ 2251.9Smrg struct mk48txx_softc *sc = device_private(self); 2261.9Smrg struct fhc_attach_args *fa = aux; 2271.9Smrg 2281.9Smrg sc->sc_dev = self; 2291.9Smrg sc->sc_bst = fa->fa_bustag; 2301.9Smrg 2311.9Smrg if (fhc_bus_map(sc->sc_bst, 2321.9Smrg fa->fa_reg[0].fbr_slot, 2331.9Smrg (fa->fa_reg[0].fbr_offset & ~NBPG), 2341.9Smrg fa->fa_reg[0].fbr_size, 2351.9Smrg BUS_SPACE_MAP_LINEAR, 2361.9Smrg &sc->sc_bsh) != 0) { 2371.9Smrg aprint_error(": can't map register\n"); 2381.9Smrg return; 2391.9Smrg } 2401.9Smrg mkclock_attach(sc, fa->fa_node); 2411.9Smrg} 2421.9Smrg 2431.1Stsutsui 2441.1Stsutsuistatic void 2451.1Stsutsuimkclock_attach(struct mk48txx_softc *sc, int node) 2461.1Stsutsui{ 2471.1Stsutsui 2481.1Stsutsui sc->sc_model = prom_getpropstring(node, "model"); 2491.1Stsutsui 2501.1Stsutsui#ifdef DIAGNOSTIC 2511.1Stsutsui if (sc->sc_model == NULL) 2521.1Stsutsui panic("clockattach: no model property"); 2531.1Stsutsui#endif 2541.1Stsutsui 2551.1Stsutsui /* Our TOD clock year 0 is 1968 */ 2561.1Stsutsui sc->sc_year0 = 1968; 2571.1Stsutsui 2581.1Stsutsui /* Save info for the clock wenable call. */ 2591.1Stsutsui sc->sc_handle.todr_setwen = mkclock_wenable; 2601.1Stsutsui 2611.2Stsutsui mk48txx_attach(sc); 2621.2Stsutsui 2631.3Stsutsui aprint_normal("\n"); 2641.1Stsutsui} 2651.1Stsutsui 2661.1Stsutsui/* 2671.1Stsutsui * Write en/dis-able clock registers. We coordinate so that several 2681.1Stsutsui * writers can run simultaneously. 2691.1Stsutsui */ 2701.1Stsutsuistatic int 2711.1Stsutsuimkclock_wenable(struct todr_chip_handle *handle, int onoff) 2721.1Stsutsui{ 2731.14Sthorpej struct mk48txx_softc *sc = device_private(handle->todr_dev); 2741.1Stsutsui vm_prot_t prot; 2751.1Stsutsui vaddr_t va; 2761.1Stsutsui int s, err = 0; 2771.1Stsutsui static int writers; 2781.1Stsutsui 2791.10Smrg /* XXXSMP */ 2801.1Stsutsui s = splhigh(); 2811.1Stsutsui if (onoff) 2821.1Stsutsui prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0; 2831.1Stsutsui else 2841.1Stsutsui prot = --writers == 0 ? VM_PROT_READ : 0; 2851.1Stsutsui splx(s); 2861.1Stsutsui if (prot == VM_PROT_NONE) { 2871.1Stsutsui return 0; 2881.1Stsutsui } 2891.1Stsutsui va = (vaddr_t)bus_space_vaddr(sc->sc_bst, sc->sc_bsh); 2901.1Stsutsui if (va == 0UL) { 2911.1Stsutsui printf("clock_wenable: WARNING -- cannot get va\n"); 2921.1Stsutsui return EIO; 2931.1Stsutsui } 2941.1Stsutsui pmap_kprotect(va, prot); 2951.1Stsutsui return (err); 2961.1Stsutsui} 297