1 1.9 rin /* $NetBSD: imxclock.c,v 1.9 2020/05/29 12:30:38 rin Exp $ */ 2 1.3 bsh /* 3 1.3 bsh * Copyright (c) 2009, 2010 Genetec corp. All rights reserved. 4 1.3 bsh * Written by Hashimoto Kenichi for Genetec corp. 5 1.3 bsh * 6 1.3 bsh * Redistribution and use in source and binary forms, with or without 7 1.3 bsh * modification, are permitted provided that the following conditions 8 1.3 bsh * are met: 9 1.3 bsh * 1. Redistributions of source code must retain the above copyright 10 1.3 bsh * notice, this list of conditions and the following disclaimer. 11 1.3 bsh * 2. Redistributions in binary form must reproduce the above copyright 12 1.3 bsh * notice, this list of conditions and the following disclaimer in the 13 1.3 bsh * documentation and/or other materials provided with the distribution. 14 1.3 bsh * 15 1.3 bsh * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND 16 1.3 bsh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 1.3 bsh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 1.3 bsh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP. 19 1.3 bsh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 1.3 bsh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 1.3 bsh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 1.3 bsh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 1.3 bsh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 1.3 bsh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 1.3 bsh * POSSIBILITY OF SUCH DAMAGE. 26 1.3 bsh */ 27 1.3 bsh 28 1.3 bsh /* 29 1.3 bsh * common part for i.MX31 and i.MX51 30 1.3 bsh */ 31 1.3 bsh 32 1.7 hkenken #include <sys/cdefs.h> 33 1.9 rin __KERNEL_RCSID(0, "$NetBSD: imxclock.c,v 1.9 2020/05/29 12:30:38 rin Exp $"); 34 1.7 hkenken 35 1.7 hkenken #include "opt_imx.h" 36 1.7 hkenken 37 1.3 bsh #include <sys/param.h> 38 1.3 bsh #include <sys/systm.h> 39 1.3 bsh #include <sys/kernel.h> 40 1.3 bsh #include <sys/evcnt.h> 41 1.3 bsh #include <sys/atomic.h> 42 1.3 bsh #include <sys/time.h> 43 1.3 bsh #include <sys/timetc.h> 44 1.3 bsh 45 1.2 matt #include <sys/types.h> 46 1.3 bsh #include <sys/device.h> 47 1.3 bsh 48 1.3 bsh #include <machine/intr.h> 49 1.4 dyoung #include <sys/bus.h> 50 1.3 bsh 51 1.3 bsh #include <arm/cpu.h> 52 1.3 bsh #include <arm/armreg.h> 53 1.3 bsh #include <arm/cpufunc.h> 54 1.3 bsh 55 1.3 bsh #include <arm/imx/imxclockvar.h> 56 1.3 bsh #include <arm/imx/imxepitreg.h> 57 1.3 bsh 58 1.3 bsh static u_int imx_epit_get_timecount(struct timecounter *); 59 1.3 bsh static int imxclock_intr(void *); 60 1.3 bsh 61 1.3 bsh static struct timecounter imx_epit_timecounter = { 62 1.9 rin .tc_get_timecount = imx_epit_get_timecount, 63 1.9 rin .tc_counter_mask = 0xffffffff, 64 1.9 rin .tc_name = "epit", 65 1.9 rin .tc_quality = 100, 66 1.3 bsh }; 67 1.3 bsh 68 1.3 bsh static volatile uint32_t imxclock_base; 69 1.7 hkenken struct imxclock_softc *imxclock = NULL; 70 1.2 matt 71 1.2 matt void 72 1.2 matt cpu_initclocks(void) 73 1.2 matt { 74 1.3 bsh uint32_t reg; 75 1.5 bsh u_int freq; 76 1.3 bsh 77 1.7 hkenken if (epit1_sc != NULL) 78 1.7 hkenken imxclock = epit1_sc; 79 1.7 hkenken else if (epit2_sc != NULL) 80 1.7 hkenken imxclock = epit2_sc; 81 1.7 hkenken else 82 1.3 bsh panic("%s: driver has not been initialized!", __FUNCTION__); 83 1.3 bsh 84 1.7 hkenken freq = imxclock_get_timerfreq(imxclock); 85 1.3 bsh imx_epit_timecounter.tc_frequency = freq; 86 1.3 bsh tc_init(&imx_epit_timecounter); 87 1.3 bsh 88 1.7 hkenken aprint_verbose_dev(imxclock->sc_dev, 89 1.7 hkenken "timer clock frequency %d\n", freq); 90 1.5 bsh 91 1.7 hkenken imxclock->sc_reload_value = freq / hz - 1; 92 1.3 bsh 93 1.7 hkenken /* stop timers */ 94 1.7 hkenken bus_space_write_4(imxclock->sc_iot, imxclock->sc_ioh, EPIT_EPITCR, 0); 95 1.3 bsh 96 1.3 bsh aprint_normal("clock: hz=%d stathz = %d\n", hz, stathz); 97 1.3 bsh 98 1.7 hkenken bus_space_write_4(imxclock->sc_iot, imxclock->sc_ioh, EPIT_EPITLR, 99 1.7 hkenken imxclock->sc_reload_value); 100 1.7 hkenken bus_space_write_4(imxclock->sc_iot, imxclock->sc_ioh, EPIT_EPITCMPR, 0); 101 1.3 bsh 102 1.7 hkenken reg = EPITCR_ENMOD | EPITCR_IOVW | EPITCR_RLD | imxclock->sc_clksrc; 103 1.7 hkenken bus_space_write_4(imxclock->sc_iot, imxclock->sc_ioh, 104 1.5 bsh EPIT_EPITCR, reg); 105 1.5 bsh reg |= EPITCR_EN | EPITCR_OCIEN | EPITCR_WAITEN | EPITCR_DOZEN | 106 1.5 bsh EPITCR_STOPEN; 107 1.7 hkenken bus_space_write_4(imxclock->sc_iot, imxclock->sc_ioh, 108 1.5 bsh EPIT_EPITCR, reg); 109 1.3 bsh 110 1.8 hkenken imxclock->sc_ih = intr_establish(imxclock->sc_intr, IPL_CLOCK, 111 1.6 matt IST_LEVEL, imxclock_intr, NULL); 112 1.2 matt } 113 1.2 matt 114 1.2 matt void 115 1.2 matt setstatclockrate(int schz) 116 1.2 matt { 117 1.2 matt } 118 1.3 bsh 119 1.3 bsh static int 120 1.3 bsh imxclock_intr(void *arg) 121 1.3 bsh { 122 1.7 hkenken struct imxclock_softc *sc = imxclock; 123 1.3 bsh 124 1.3 bsh bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPIT_EPITSR, 1); 125 1.3 bsh atomic_add_32(&imxclock_base, sc->sc_reload_value); 126 1.3 bsh 127 1.3 bsh hardclock((struct clockframe *)arg); 128 1.3 bsh 129 1.3 bsh return 1; 130 1.3 bsh } 131 1.3 bsh 132 1.3 bsh u_int 133 1.3 bsh imx_epit_get_timecount(struct timecounter *tc) 134 1.3 bsh { 135 1.3 bsh uint32_t counter; 136 1.3 bsh uint32_t base; 137 1.3 bsh u_int oldirqstate; 138 1.3 bsh 139 1.3 bsh oldirqstate = disable_interrupts(I32_bit); 140 1.7 hkenken counter = bus_space_read_4(imxclock->sc_iot, imxclock->sc_ioh, EPIT_EPITCNT); 141 1.3 bsh base = imxclock_base; 142 1.3 bsh restore_interrupts(oldirqstate); 143 1.3 bsh 144 1.3 bsh return base - counter; 145 1.3 bsh } 146