1/* $NetBSD: ixp425_timer.c,v 1.11 2006/04/10 03:36:03 simonb Exp $ */ 2 3/* 4 * Copyright (c) 2003 5 * Ichiro FUKUHARA <ichiro@ichiro.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Ichiro FUKUHARA. 19 * 4. The name of the company nor the name of the author may be used to 20 * endorse or promote products derived from this software without specific 21 * prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h>
| 1/* $NetBSD: ixp425_timer.c,v 1.11 2006/04/10 03:36:03 simonb Exp $ */ 2 3/* 4 * Copyright (c) 2003 5 * Ichiro FUKUHARA <ichiro@ichiro.org>. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Ichiro FUKUHARA. 19 * 4. The name of the company nor the name of the author may be used to 20 * endorse or promote products derived from this software without specific 21 * prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h>
|
97 return (0); 98} 99 100static int 101ixpclk_attach(device_t dev) 102{ 103 struct ixpclk_softc *sc = device_get_softc(dev); 104 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); 105 106 ixpclk_sc = sc; 107 108 sc->sc_dev = dev; 109 sc->sc_iot = sa->sc_iot; 110 sc->sc_baseaddr = IXP425_TIMER_HWBASE; 111 112 if (bus_space_map(sc->sc_iot, sc->sc_baseaddr, 8, 0, 113 &sc->sc_ioh)) 114 panic("%s: Cannot map registers", device_get_name(dev)); 115 116 return (0); 117} 118 119static device_method_t ixpclk_methods[] = { 120 DEVMETHOD(device_probe, ixpclk_probe), 121 DEVMETHOD(device_attach, ixpclk_attach), 122 {0, 0}, 123}; 124 125static driver_t ixpclk_driver = { 126 "ixpclk", 127 ixpclk_methods, 128 sizeof(struct ixpclk_softc), 129}; 130static devclass_t ixpclk_devclass; 131 132DRIVER_MODULE(ixpclk, ixp, ixpclk_driver, ixpclk_devclass, 0, 0); 133static unsigned 134ixp425_timer_get_timecount(struct timecounter *tc) 135{ 136 uint32_t ret; 137 138 ret = GET_TS_VALUE(sc); 139 return (ret); 140} 141 142/* 143 * cpu_initclocks: 144 * 145 * Initialize the clock and get them going. 146 */ 147void 148cpu_initclocks(void) 149{ 150 struct ixpclk_softc* sc = ixpclk_sc; 151 struct resource *irq; 152 device_t dev = sc->sc_dev; 153 u_int oldirqstate; 154 int rid = 0; 155 void *ihl; 156 157 if (hz < 50 || COUNTS_PER_SEC % hz) { 158 printf("Cannot get %d Hz clock; using 100 Hz\n", hz); 159 hz = 100; 160 } 161 tick = 1000000 / hz; /* number of microseconds between interrupts */ 162 163 /* 164 * We only have one timer available; stathz and profhz are 165 * always left as 0 (the upper-layer clock code deals with 166 * this situation). 167 */ 168 if (stathz != 0) 169 printf("Cannot get %d Hz statclock\n", stathz); 170 stathz = 0; 171 172 if (profhz != 0) 173 printf("Cannot get %d Hz profclock\n", profhz); 174 profhz = 0; 175 176 /* Report the clock frequency. */ 177 178 oldirqstate = disable_interrupts(I32_bit); 179 180 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, IXP425_INT_TMR0, 181 IXP425_INT_TMR0, 1, RF_ACTIVE); 182 if (!irq) 183 panic("Unable to setup the clock irq handler.\n"); 184 else 185 bus_setup_intr(dev, irq, INTR_TYPE_CLK, ixpclk_intr, NULL, 186 NULL, &ihl); 187 188 /* Set up the new clock parameters. */ 189 190 /* clear interrupt */ 191 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS, 192 OST_WARM_RESET | OST_WDOG_INT | OST_TS_INT | 193 OST_TIM1_INT | OST_TIM0_INT); 194 195 counts_per_hz = COUNTS_PER_SEC / hz; 196 197 /* reload value & Timer enable */ 198 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_TIM0_RELOAD, 199 (counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN); 200 201 tc_init(&ixp425_timer_timecounter); 202 restore_interrupts(oldirqstate); 203 rid = 0; 204} 205 206 207/* 208 * DELAY: 209 * 210 * Delay for at least N microseconds. 211 */ 212void 213DELAY(int n) 214{ 215 u_int32_t first, last; 216 int usecs; 217 218 if (n == 0) 219 return; 220 221 /* 222 * Clamp the timeout at a maximum value (about 32 seconds with 223 * a 66MHz clock). *Nobody* should be delay()ing for anywhere 224 * near that length of time and if they are, they should be hung 225 * out to dry. 226 */ 227 if (n >= (0x80000000U / COUNTS_PER_USEC)) 228 usecs = (0x80000000U / COUNTS_PER_USEC) - 1; 229 else 230 usecs = n * COUNTS_PER_USEC; 231 232 /* Note: Timestamp timer counts *up*, unlike the other timers */ 233 first = GET_TS_VALUE(); 234 235 while (usecs > 0) { 236 last = GET_TS_VALUE(); 237 usecs -= (int)(last - first); 238 first = last; 239 } 240} 241 242/* 243 * ixpclk_intr: 244 * 245 * Handle the hardclock interrupt. 246 */ 247int 248ixpclk_intr(void *arg) 249{ 250 struct ixpclk_softc* sc = ixpclk_sc; 251 struct trapframe *frame = arg; 252 253 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS, 254 OST_TIM0_INT); 255 256 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 257 return (FILTER_HANDLED); 258} 259 260void 261cpu_startprofclock(void) 262{ 263} 264 265void 266cpu_stopprofclock(void) 267{ 268}
| 97 return (0); 98} 99 100static int 101ixpclk_attach(device_t dev) 102{ 103 struct ixpclk_softc *sc = device_get_softc(dev); 104 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev)); 105 106 ixpclk_sc = sc; 107 108 sc->sc_dev = dev; 109 sc->sc_iot = sa->sc_iot; 110 sc->sc_baseaddr = IXP425_TIMER_HWBASE; 111 112 if (bus_space_map(sc->sc_iot, sc->sc_baseaddr, 8, 0, 113 &sc->sc_ioh)) 114 panic("%s: Cannot map registers", device_get_name(dev)); 115 116 return (0); 117} 118 119static device_method_t ixpclk_methods[] = { 120 DEVMETHOD(device_probe, ixpclk_probe), 121 DEVMETHOD(device_attach, ixpclk_attach), 122 {0, 0}, 123}; 124 125static driver_t ixpclk_driver = { 126 "ixpclk", 127 ixpclk_methods, 128 sizeof(struct ixpclk_softc), 129}; 130static devclass_t ixpclk_devclass; 131 132DRIVER_MODULE(ixpclk, ixp, ixpclk_driver, ixpclk_devclass, 0, 0); 133static unsigned 134ixp425_timer_get_timecount(struct timecounter *tc) 135{ 136 uint32_t ret; 137 138 ret = GET_TS_VALUE(sc); 139 return (ret); 140} 141 142/* 143 * cpu_initclocks: 144 * 145 * Initialize the clock and get them going. 146 */ 147void 148cpu_initclocks(void) 149{ 150 struct ixpclk_softc* sc = ixpclk_sc; 151 struct resource *irq; 152 device_t dev = sc->sc_dev; 153 u_int oldirqstate; 154 int rid = 0; 155 void *ihl; 156 157 if (hz < 50 || COUNTS_PER_SEC % hz) { 158 printf("Cannot get %d Hz clock; using 100 Hz\n", hz); 159 hz = 100; 160 } 161 tick = 1000000 / hz; /* number of microseconds between interrupts */ 162 163 /* 164 * We only have one timer available; stathz and profhz are 165 * always left as 0 (the upper-layer clock code deals with 166 * this situation). 167 */ 168 if (stathz != 0) 169 printf("Cannot get %d Hz statclock\n", stathz); 170 stathz = 0; 171 172 if (profhz != 0) 173 printf("Cannot get %d Hz profclock\n", profhz); 174 profhz = 0; 175 176 /* Report the clock frequency. */ 177 178 oldirqstate = disable_interrupts(I32_bit); 179 180 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, IXP425_INT_TMR0, 181 IXP425_INT_TMR0, 1, RF_ACTIVE); 182 if (!irq) 183 panic("Unable to setup the clock irq handler.\n"); 184 else 185 bus_setup_intr(dev, irq, INTR_TYPE_CLK, ixpclk_intr, NULL, 186 NULL, &ihl); 187 188 /* Set up the new clock parameters. */ 189 190 /* clear interrupt */ 191 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS, 192 OST_WARM_RESET | OST_WDOG_INT | OST_TS_INT | 193 OST_TIM1_INT | OST_TIM0_INT); 194 195 counts_per_hz = COUNTS_PER_SEC / hz; 196 197 /* reload value & Timer enable */ 198 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_TIM0_RELOAD, 199 (counts_per_hz & TIMERRELOAD_MASK) | OST_TIMER_EN); 200 201 tc_init(&ixp425_timer_timecounter); 202 restore_interrupts(oldirqstate); 203 rid = 0; 204} 205 206 207/* 208 * DELAY: 209 * 210 * Delay for at least N microseconds. 211 */ 212void 213DELAY(int n) 214{ 215 u_int32_t first, last; 216 int usecs; 217 218 if (n == 0) 219 return; 220 221 /* 222 * Clamp the timeout at a maximum value (about 32 seconds with 223 * a 66MHz clock). *Nobody* should be delay()ing for anywhere 224 * near that length of time and if they are, they should be hung 225 * out to dry. 226 */ 227 if (n >= (0x80000000U / COUNTS_PER_USEC)) 228 usecs = (0x80000000U / COUNTS_PER_USEC) - 1; 229 else 230 usecs = n * COUNTS_PER_USEC; 231 232 /* Note: Timestamp timer counts *up*, unlike the other timers */ 233 first = GET_TS_VALUE(); 234 235 while (usecs > 0) { 236 last = GET_TS_VALUE(); 237 usecs -= (int)(last - first); 238 first = last; 239 } 240} 241 242/* 243 * ixpclk_intr: 244 * 245 * Handle the hardclock interrupt. 246 */ 247int 248ixpclk_intr(void *arg) 249{ 250 struct ixpclk_softc* sc = ixpclk_sc; 251 struct trapframe *frame = arg; 252 253 bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_OST_STATUS, 254 OST_TIM0_INT); 255 256 hardclock(TRAPF_USERMODE(frame), TRAPF_PC(frame)); 257 return (FILTER_HANDLED); 258} 259 260void 261cpu_startprofclock(void) 262{ 263} 264 265void 266cpu_stopprofclock(void) 267{ 268}
|