Deleted Added
full compact
at91_pit.c (210040) at91_pit.c (213496)
1/*-
1/*-
2 * Copyright (c) 2010 Yohanes Nugroho. All rights reserved.
2 * Copyright (c) 2009 Gallon Sylvestre. All rights reserved.
3 * Copyright (c) 2010 Greg Ansley. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the

--- 8 unchanged lines hidden (view full) ---

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
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
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the

--- 8 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 213496 2010-10-06 22:25:21Z cognet $");
27
28#include <sys/param.h>
29
30#include <sys/param.h>
29#include <sys/systm.h>
31#include <sys/bus.h>
30#include <sys/kernel.h>
31#include <sys/module.h>
32#include <sys/kernel.h>
33#include <sys/module.h>
32#include <sys/time.h>
33#include <sys/bus.h>
34#include <sys/resource.h>
34#include <sys/resource.h>
35#include <sys/systm.h>
36#include <sys/rman.h>
37#include <sys/time.h>
35#include <sys/timetc.h>
36#include <sys/watchdog.h>
37
38#include <machine/bus.h>
39#include <machine/cpu.h>
40#include <machine/cpufunc.h>
38#include <sys/timetc.h>
39#include <sys/watchdog.h>
40
41#include <machine/bus.h>
42#include <machine/cpu.h>
43#include <machine/cpufunc.h>
41#include <machine/resource.h>
42#include <machine/frame.h>
43#include <machine/intr.h>
44#include <machine/frame.h>
45#include <machine/intr.h>
46#include <machine/resource.h>
44
45#include <arm/at91/at91var.h>
46#include <arm/at91/at91_pitreg.h>
47
48#include <arm/at91/at91var.h>
49#include <arm/at91/at91_pitreg.h>
47#include <arm/at91/at91_pmcvar.h>
48#include <arm/at91/at91sam9g20reg.h>
49
50
50__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pit.c 210040 2010-07-14 00:48:53Z cognet $");
51static struct pit_softc {
52 struct resource *mem_res; /* Memory resource */
53 void *intrhand; /* Interrupt handle */
54 device_t sc_dev;
55} *sc;
51
56
52static struct at91pit_softc {
53 bus_space_tag_t sc_st;
54 bus_space_handle_t sc_sh;
55 device_t sc_dev;
56} *pit_softc;
57static uint32_t timecount = 0;
57
58
58#define RD4(off) \
59 bus_space_read_4(pit_softc->sc_st, pit_softc->sc_sh, (off))
60#define WR4(off, val) \
61 bus_space_write_4(pit_softc->sc_st, pit_softc->sc_sh, (off), (val))
59static inline uint32_t
60RD4(struct pit_softc *sc, bus_size_t off)
61{
62 return (bus_read_4(sc->mem_res, off));
63}
62
64
65static inline void
66WR4(struct pit_softc *sc, bus_size_t off, uint32_t val)
67{
68 bus_write_4(sc->mem_res, off, val);
69}
70
63static unsigned at91pit_get_timecount(struct timecounter *tc);
71static unsigned at91pit_get_timecount(struct timecounter *tc);
64static int clock_intr(void *arg);
72static int pit_intr(void *arg);
65
73
74#ifndef PIT_PRESCALE
75#define PIT_PRESCALE (16)
76#endif
77
66static struct timecounter at91pit_timecounter = {
67 at91pit_get_timecount, /* get_timecount */
68 NULL, /* no poll_pps */
78static struct timecounter at91pit_timecounter = {
79 at91pit_get_timecount, /* get_timecount */
80 NULL, /* no poll_pps */
69 0xffffffffu, /* counter mask */
70 0, /* frequency */
71 "AT91SAM9261 timer", /* name */
81 0xffffffff, /* counter mask */
82 0 / PIT_PRESCALE, /* frequency */
83 "AT91SAM9 timer", /* name */
72 1000 /* quality */
73};
74
84 1000 /* quality */
85};
86
75
76uint32_t
77at91_pit_base(void);
78
79uint32_t
80at91_pit_size(void);
81
82static int
83at91pit_probe(device_t dev)
84{
87static int
88at91pit_probe(device_t dev)
89{
85 device_set_desc(dev, "PIT");
86 return (0);
87}
88
90
89uint32_t
90at91_pit_base(void)
91{
92 return (AT91SAM9G20_PIT_BASE);
91 if (at91_is_sam9()) {
92 device_set_desc(dev, "AT91SAM9 PIT");
93 return (0);
94 }
95 return (ENXIO);
93}
94
96}
97
95uint32_t
96at91_pit_size(void)
97{
98 return (AT91SAM9G20_PIT_SIZE);
99}
100
101static int pit_rate;
102static int pit_cycle;
103static int pit_counter;
104
105static int
106at91pit_attach(device_t dev)
107{
98static int
99at91pit_attach(device_t dev)
100{
108 struct at91_softc *sc = device_get_softc(device_get_parent(dev));
109 struct resource *irq;
110 int rid = 0;
111 void *ih;
101 void *ih;
102 int rid, err = 0;
103 struct at91_softc *at91_sc;
104 struct resource *irq;
112
105
113 pit_softc = device_get_softc(dev);
114 pit_softc->sc_st = sc->sc_st;
115 pit_softc->sc_dev = dev;
116 if (bus_space_subregion(sc->sc_st, sc->sc_sh, at91_pit_base(),
117 at91_pit_size(), &pit_softc->sc_sh) != 0)
118 panic("couldn't subregion pit registers");
106 at91_sc = device_get_softc(device_get_parent(dev));
107 sc = device_get_softc(dev);
108 sc->sc_dev = dev;
119
109
110 rid = 0;
111 sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
112 RF_ACTIVE);
113
114 if (sc->mem_res == NULL)
115 panic("couldn't allocate register resources");
116
117 rid = 0;
120 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1,
121 RF_ACTIVE | RF_SHAREABLE);
118 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 1, 1, 1,
119 RF_ACTIVE | RF_SHAREABLE);
122 if (!irq)
123 panic("Unable to allocate IRQ for the system timer");
124 else
125 bus_setup_intr(dev, irq, INTR_TYPE_CLK,
126 clock_intr, NULL, NULL, &ih);
127
120 if (!irq) {
121 device_printf(dev, "could not allocate interrupt resources.\n");
122 err = ENOMEM;
123 goto out;
124 }
128
125
129 device_printf(dev, "AT91SAM9x pit registered\n");
130 return (0);
126 /* Activate the interrupt. */
127 err = bus_setup_intr(dev, irq, INTR_TYPE_CLK, pit_intr,
128 NULL, NULL, &ih);
129
130 at91pit_timecounter.tc_frequency = at91_master_clock / PIT_PRESCALE;
131 tc_init(&at91pit_timecounter);
132
133 //Enable the PIT here.
134 WR4(sc, PIT_MR,
135 PIT_PIV(at91_master_clock / PIT_PRESCALE / hz) |
136 PIT_EN | PIT_IEN);
137out:
138 return (err);
131}
132
133static device_method_t at91pit_methods[] = {
134 DEVMETHOD(device_probe, at91pit_probe),
135 DEVMETHOD(device_attach, at91pit_attach),
136 {0,0},
137};
138
139static driver_t at91pit_driver = {
140 "at91_pit",
141 at91pit_methods,
139}
140
141static device_method_t at91pit_methods[] = {
142 DEVMETHOD(device_probe, at91pit_probe),
143 DEVMETHOD(device_attach, at91pit_attach),
144 {0,0},
145};
146
147static driver_t at91pit_driver = {
148 "at91_pit",
149 at91pit_methods,
142 sizeof(struct at91pit_softc),
150 sizeof(struct pit_softc),
143};
144
145static devclass_t at91pit_devclass;
146
147DRIVER_MODULE(at91_pit, atmelarm, at91pit_driver, at91pit_devclass, 0, 0);
148
149static int
151};
152
153static devclass_t at91pit_devclass;
154
155DRIVER_MODULE(at91_pit, atmelarm, at91pit_driver, at91pit_devclass, 0, 0);
156
157static int
150clock_intr(void *arg)
158pit_intr(void *arg)
151{
159{
152
153 struct trapframe *fp = arg;
160 struct trapframe *fp = arg;
161 uint32_t icnt;
154
162
155 if (RD4(PIT_SR) & PIT_PITS_DONE) {
156 uint32_t pivr = RD4(PIT_PIVR);
157 if (PIT_CNT(pivr)>1) {
158 printf("cnt = %d\n", PIT_CNT(pivr));
159 }
160 pit_counter += pit_cycle;
163 if (RD4(sc, PIT_SR) & PIT_PITS_DONE) {
164 icnt = RD4(sc, PIT_PIVR) >> 20;
165
166 /* Just add in the overflows we just read */
167 timecount += PIT_PIV(RD4(sc, PIT_MR)) * icnt;
168
161 hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
162 return (FILTER_HANDLED);
163 }
164 return (FILTER_STRAY);
165}
166
169 hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp));
170 return (FILTER_HANDLED);
171 }
172 return (FILTER_STRAY);
173}
174
167static unsigned
175static unsigned
168at91pit_get_timecount(struct timecounter *tc)
169{
176at91pit_get_timecount(struct timecounter *tc)
177{
170 return pit_counter;
178 uint32_t piir, icnt;
179
180 piir = RD4(sc, PIT_PIIR); /* Current count | over flows */
181 icnt = piir >> 20; /* Overflows */
182 return (timecount + PIT_PIV(piir) + PIT_PIV(RD4(sc, PIT_MR)) * icnt);
171}
172
183}
184
173/*todo: review this*/
174void
185void
175DELAY(int n)
186DELAY(int us)
176{
187{
177 u_int32_t start, end, cur;
188 int32_t cnt, last, piv;
189 uint64_t pit_freq;
190 const uint64_t mhz = 1E6;
178
191
179 start = RD4(PIT_PIIR);
180 n = (n * 1000) / (at91_master_clock / 12);
181 if (n <= 0)
182 n = 1;
183 end = (start + n);
184 cur = start;
185 if (start > end) {
186 while (cur >= start || cur < end)
187 cur = RD4(PIT_PIIR);
188 } else {
189 while (cur < end)
190 cur = RD4(PIT_PIIR);
192 last = PIT_PIV(RD4(sc, PIT_PIIR));
193
194 /* Max delay ~= 260s. @ 133Mhz */
195 pit_freq = at91_master_clock / PIT_PRESCALE;
196 cnt = ((pit_freq * us) + (mhz -1)) / mhz;
197 cnt = (cnt <= 0) ? 1 : cnt;
198
199 while (cnt > 0) {
200 piv = PIT_PIV(RD4(sc, PIT_PIIR));
201 cnt -= piv - last ;
202 if (piv < last)
203 cnt -= PIT_PIV(~0u) - last;
204 last = piv;
191 }
192}
193
194/*
205 }
206}
207
208/*
195 * The 3 next functions must be implement with the futur PLL code.
209 * The 3 next functions must be implement with the future PLL code.
196 */
197void
198cpu_startprofclock(void)
199{
200}
201
202void
203cpu_stopprofclock(void)
204{
205}
206
210 */
211void
212cpu_startprofclock(void)
213{
214}
215
216void
217cpu_stopprofclock(void)
218{
219}
220
207#define HZ 100
208
209void
210cpu_initclocks(void)
211{
221void
222cpu_initclocks(void)
223{
212 struct at91_pmc_clock *master;
213
214 master = at91_pmc_clock_ref("mck");
215 pit_rate = master->hz / 16;
216 pit_cycle = (pit_rate + HZ/2) / HZ;
217 at91pit_timecounter.tc_frequency = pit_rate;
218 WR4(PIT_MR, 0);
219
220 while (PIT_PIV(RD4(PIT_PIVR)) != 0);
221
222 WR4(PIT_MR, (pit_cycle - 1) | PIT_IEN | PIT_EN);
223 tc_init(&at91pit_timecounter);
224}
224}
225
226void
227cpu_reset(void)
228{
229 *(volatile int *)(AT91SAM9G20_BASE + AT91SAM9G20_RSTC_BASE +
230 RSTC_CR) = RSTC_PROCRST | RSTC_PERRST | RSTC_KEY;
231 while (1)
232 continue;
233}