at91_pit.c (237115) | at91_pit.c (237130) |
---|---|
1/*- 2 * Copyright (c) 2009 Gallon Sylvestre. All rights reserved. 3 * Copyright (c) 2010 Greg Ansley. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2009 Gallon Sylvestre. All rights reserved. 3 * Copyright (c) 2010 Greg Ansley. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 11 unchanged lines hidden (view full) --- 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> |
28__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pit.c 237115 2012-06-15 06:38:55Z imp $"); | 28__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pit.c 237130 2012-06-15 08:37:50Z imp $"); |
29 30#include <sys/param.h> 31#include <sys/bus.h> 32#include <sys/kernel.h> 33#include <sys/module.h> 34#include <sys/resource.h> 35#include <sys/systm.h> 36#include <sys/rman.h> --- 6 unchanged lines hidden (view full) --- 43#include <machine/cpufunc.h> 44#include <machine/frame.h> 45#include <machine/intr.h> 46#include <machine/resource.h> 47 48#include <arm/at91/at91var.h> 49#include <arm/at91/at91_pitreg.h> 50 | 29 30#include <sys/param.h> 31#include <sys/bus.h> 32#include <sys/kernel.h> 33#include <sys/module.h> 34#include <sys/resource.h> 35#include <sys/systm.h> 36#include <sys/rman.h> --- 6 unchanged lines hidden (view full) --- 43#include <machine/cpufunc.h> 44#include <machine/frame.h> 45#include <machine/intr.h> 46#include <machine/resource.h> 47 48#include <arm/at91/at91var.h> 49#include <arm/at91/at91_pitreg.h> 50 |
51#ifndef PIT_PRESCALE 52#define PIT_PRESCALE (16) 53#endif 54 |
|
51static struct pit_softc { 52 struct resource *mem_res; /* Memory resource */ 53 void *intrhand; /* Interrupt handle */ 54 device_t sc_dev; 55} *sc; 56 57static uint32_t timecount = 0; | 55static struct pit_softc { 56 struct resource *mem_res; /* Memory resource */ 57 void *intrhand; /* Interrupt handle */ 58 device_t sc_dev; 59} *sc; 60 61static uint32_t timecount = 0; |
62static unsigned at91pit_get_timecount(struct timecounter *tc); 63static int pit_intr(void *arg); |
|
58 59static inline uint32_t 60RD4(struct pit_softc *sc, bus_size_t off) 61{ 62 63 return (bus_read_4(sc->mem_res, off)); 64} 65 66static inline void 67WR4(struct pit_softc *sc, bus_size_t off, uint32_t val) 68{ 69 70 bus_write_4(sc->mem_res, off, val); 71} 72 | 64 65static inline uint32_t 66RD4(struct pit_softc *sc, bus_size_t off) 67{ 68 69 return (bus_read_4(sc->mem_res, off)); 70} 71 72static inline void 73WR4(struct pit_softc *sc, bus_size_t off, uint32_t val) 74{ 75 76 bus_write_4(sc->mem_res, off, val); 77} 78 |
73static unsigned at91pit_get_timecount(struct timecounter *tc); 74static int pit_intr(void *arg); | 79static void 80at91pit_delay(int us) 81{ 82 int32_t cnt, last, piv; 83 uint64_t pit_freq; 84 const uint64_t mhz = 1E6; |
75 | 85 |
76#ifndef PIT_PRESCALE 77#define PIT_PRESCALE (16) 78#endif | 86 last = PIT_PIV(RD4(sc, PIT_PIIR)); |
79 | 87 |
88 /* Max delay ~= 260s. @ 133Mhz */ 89 pit_freq = at91_master_clock / PIT_PRESCALE; 90 cnt = ((pit_freq * us) + (mhz -1)) / mhz; 91 cnt = (cnt <= 0) ? 1 : cnt; 92 93 while (cnt > 0) { 94 piv = PIT_PIV(RD4(sc, PIT_PIIR)); 95 cnt -= piv - last ; 96 if (piv < last) 97 cnt -= PIT_PIV(~0u) - last; 98 last = piv; 99 } 100} 101 |
|
80static struct timecounter at91pit_timecounter = { 81 at91pit_get_timecount, /* get_timecount */ 82 NULL, /* no poll_pps */ 83 0xffffffff, /* counter mask */ 84 0 / PIT_PRESCALE, /* frequency */ 85 "AT91SAM9 timer", /* name */ 86 1000 /* quality */ 87}; 88 89static int 90at91pit_probe(device_t dev) 91{ 92 | 102static struct timecounter at91pit_timecounter = { 103 at91pit_get_timecount, /* get_timecount */ 104 NULL, /* no poll_pps */ 105 0xffffffff, /* counter mask */ 106 0 / PIT_PRESCALE, /* frequency */ 107 "AT91SAM9 timer", /* name */ 108 1000 /* quality */ 109}; 110 111static int 112at91pit_probe(device_t dev) 113{ 114 |
93 if (at91_is_sam9() || at91_is_sam9xe()) { 94 device_set_desc(dev, "AT91SAM9 PIT"); 95 return (0); 96 } 97 return (ENXIO); | 115 device_set_desc(dev, "AT91SAM9 PIT"); 116 return (0); |
98} 99 100static int 101at91pit_attach(device_t dev) 102{ 103 void *ih; 104 int rid, err = 0; 105 struct at91_softc *at91_sc; --- 24 unchanged lines hidden (view full) --- 130 &ih); 131 132 at91pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE; 133 tc_init(&at91pit_timecounter); 134 135 /* Enable the PIT here. */ 136 WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) | 137 PIT_EN | PIT_IEN); | 117} 118 119static int 120at91pit_attach(device_t dev) 121{ 122 void *ih; 123 int rid, err = 0; 124 struct at91_softc *at91_sc; --- 24 unchanged lines hidden (view full) --- 149 &ih); 150 151 at91pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE; 152 tc_init(&at91pit_timecounter); 153 154 /* Enable the PIT here. */ 155 WR4(sc, PIT_MR, PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) | 156 PIT_EN | PIT_IEN); |
157 soc_data.delay = at91pit_delay; |
|
138out: 139 return (err); 140} 141 142static device_method_t at91pit_methods[] = { 143 DEVMETHOD(device_probe, at91pit_probe), 144 DEVMETHOD(device_attach, at91pit_attach), 145 DEVMETHOD_END --- 32 unchanged lines hidden (view full) --- 178at91pit_get_timecount(struct timecounter *tc) 179{ 180 uint32_t piir, icnt; 181 182 piir = RD4(sc, PIT_PIIR); /* Current count | over flows */ 183 icnt = piir >> 20; /* Overflows */ 184 return (timecount + PIT_PIV(piir) + PIT_PIV(RD4(sc, PIT_MR)) * icnt); 185} | 158out: 159 return (err); 160} 161 162static device_method_t at91pit_methods[] = { 163 DEVMETHOD(device_probe, at91pit_probe), 164 DEVMETHOD(device_attach, at91pit_attach), 165 DEVMETHOD_END --- 32 unchanged lines hidden (view full) --- 198at91pit_get_timecount(struct timecounter *tc) 199{ 200 uint32_t piir, icnt; 201 202 piir = RD4(sc, PIT_PIIR); /* Current count | over flows */ 203 icnt = piir >> 20; /* Overflows */ 204 return (timecount + PIT_PIV(piir) + PIT_PIV(RD4(sc, PIT_MR)) * icnt); 205} |
186 187void 188DELAY(int us) 189{ 190 int32_t cnt, last, piv; 191 uint64_t pit_freq; 192 const uint64_t mhz = 1E6; 193 194 last = PIT_PIV(RD4(sc, PIT_PIIR)); 195 196 /* Max delay ~= 260s. @ 133Mhz */ 197 pit_freq = at91_master_clock / PIT_PRESCALE; 198 cnt = ((pit_freq * us) + (mhz -1)) / mhz; 199 cnt = (cnt <= 0) ? 1 : cnt; 200 201 while (cnt > 0) { 202 piv = PIT_PIV(RD4(sc, PIT_PIIR)); 203 cnt -= piv - last ; 204 if (piv < last) 205 cnt -= PIT_PIV(~0u) - last; 206 last = piv; 207 } 208} | |