Deleted Added
full compact
acpi_timer.c (105281) acpi_timer.c (114277)
1/*-
2 * Copyright (c) 2000, 2001 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

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

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
1/*-
2 * Copyright (c) 2000, 2001 Michael Smith
3 * Copyright (c) 2000 BSDi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

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

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/acpica/acpi_timer.c 105281 2002-10-16 17:27:40Z jhb $
27 * $FreeBSD: head/sys/dev/acpica/acpi_timer.c 114277 2003-04-30 05:27:01Z marcel $
28 */
29#include "opt_acpi.h"
30#include <sys/param.h>
31#include <sys/bus.h>
32#include <sys/kernel.h>
33#include <sys/sysctl.h>
34#if __FreeBSD_version >= 500000
35#include <sys/timetc.h>
36#else
37#include <sys/time.h>
38#endif
39
28 */
29#include "opt_acpi.h"
30#include <sys/param.h>
31#include <sys/bus.h>
32#include <sys/kernel.h>
33#include <sys/sysctl.h>
34#if __FreeBSD_version >= 500000
35#include <sys/timetc.h>
36#else
37#include <sys/time.h>
38#endif
39
40#include <machine/bus_pio.h>
41#include <machine/bus.h>
42#include <machine/resource.h>
43#include <sys/rman.h>
44
45#include "acpi.h"
46
47#include <dev/acpica/acpivar.h>
48#include <pci/pcivar.h>

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

56/*
57 * Hooks for the ACPI CA debugging infrastructure
58 */
59#define _COMPONENT ACPI_SYSTEM
60ACPI_MODULE_NAME("TIMER")
61
62static device_t acpi_timer_dev;
63struct resource *acpi_timer_reg;
40#include <machine/bus.h>
41#include <machine/resource.h>
42#include <sys/rman.h>
43
44#include "acpi.h"
45
46#include <dev/acpica/acpivar.h>
47#include <pci/pcivar.h>

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

55/*
56 * Hooks for the ACPI CA debugging infrastructure
57 */
58#define _COMPONENT ACPI_SYSTEM
59ACPI_MODULE_NAME("TIMER")
60
61static device_t acpi_timer_dev;
62struct resource *acpi_timer_reg;
64#define TIMER_READ bus_space_read_4(rman_get_bustag(acpi_timer_reg), \
65 rman_get_bushandle(acpi_timer_reg), \
66 0)
67
68static u_int acpi_timer_frequency = 14318182/4;
69
70static void acpi_timer_identify(driver_t *driver, device_t parent);
71static int acpi_timer_probe(device_t dev);
72static int acpi_timer_attach(device_t dev);
73static unsigned acpi_timer_get_timecount(struct timecounter *tc);
74static unsigned acpi_timer_get_timecount_safe(struct timecounter *tc);
75static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS);
76static void acpi_timer_test(void);
77
63
64static u_int acpi_timer_frequency = 14318182/4;
65
66static void acpi_timer_identify(driver_t *driver, device_t parent);
67static int acpi_timer_probe(device_t dev);
68static int acpi_timer_attach(device_t dev);
69static unsigned acpi_timer_get_timecount(struct timecounter *tc);
70static unsigned acpi_timer_get_timecount_safe(struct timecounter *tc);
71static int acpi_timer_sysctl_freq(SYSCTL_HANDLER_ARGS);
72static void acpi_timer_test(void);
73
74static u_int32_t read_counter(void);
75static int test_counter(void);
76
78/*
79 * Driver hung off ACPI.
80 */
81static device_method_t acpi_timer_methods[] = {
82 DEVMETHOD(device_identify, acpi_timer_identify),
83 DEVMETHOD(device_probe, acpi_timer_probe),
84 DEVMETHOD(device_attach, acpi_timer_attach),
85

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

101static struct timecounter acpi_timer_timecounter = {
102 acpi_timer_get_timecount_safe,
103 0,
104 0xffffff,
105 0,
106 "ACPI"
107};
108
77/*
78 * Driver hung off ACPI.
79 */
80static device_method_t acpi_timer_methods[] = {
81 DEVMETHOD(device_identify, acpi_timer_identify),
82 DEVMETHOD(device_probe, acpi_timer_probe),
83 DEVMETHOD(device_attach, acpi_timer_attach),
84

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

100static struct timecounter acpi_timer_timecounter = {
101 acpi_timer_get_timecount_safe,
102 0,
103 0xffffff,
104 0,
105 "ACPI"
106};
107
109static int test_counter(void);
110
108
109static u_int32_t
110read_counter()
111{
112 bus_space_handle_t bsh;
113 bus_space_tag_t bst;
114 u_int32_t tv;
115
116 bsh = rman_get_bushandle(acpi_timer_reg);
117 bst = rman_get_bustag(acpi_timer_reg);
118 tv = bus_space_read_4(bst, bsh, 0);
119 bus_space_barrier(bst, bsh, 0, 4, BUS_SPACE_BARRIER_READ);
120 return (tv);
121}
122
111#define N 2000
112static int
113test_counter()
114{
115 int min, max, n, delta;
116 unsigned last, this;
117
118 min = 10000000;
119 max = 0;
123#define N 2000
124static int
125test_counter()
126{
127 int min, max, n, delta;
128 unsigned last, this;
129
130 min = 10000000;
131 max = 0;
120 last = TIMER_READ;
132 last = read_counter();
121 for (n = 0; n < N; n++) {
133 for (n = 0; n < N; n++) {
122 this = TIMER_READ;
134 this = read_counter();
123 delta = (this - last) & 0xffffff;
124 if (delta > max)
125 max = delta;
126 else if (delta < min)
127 min = delta;
128 last = this;
129 }
130 if (max - min > 2)
131 n = 0;
135 delta = (this - last) & 0xffffff;
136 if (delta > max)
137 max = delta;
138 else if (delta < min)
139 min = delta;
140 last = this;
141 }
142 if (max - min > 2)
143 n = 0;
132 else if (min < 0)
144 else if (min < 0 || max == 0)
133 n = 0;
134 else
135 n = 1;
136 if (bootverbose)
137 printf("ACPI timer looks %s min = %d, max = %d, width = %d\n",
138 n ? "GOOD" : "BAD ",
145 n = 0;
146 else
147 n = 1;
148 if (bootverbose)
149 printf("ACPI timer looks %s min = %d, max = %d, width = %d\n",
150 n ? "GOOD" : "BAD ",
139 min, max, max - min + 1);
151 min, max, max - min);
140 return (n);
141}
142
143/*
144 * Locate the ACPI timer using the FADT, set up and allocate the I/O resources
145 * we will be using.
146 */
147static void
148acpi_timer_identify(driver_t *driver, device_t parent)
149{
150 device_t dev;
151 char desc[40];
152 return (n);
153}
154
155/*
156 * Locate the ACPI timer using the FADT, set up and allocate the I/O resources
157 * we will be using.
158 */
159static void
160acpi_timer_identify(driver_t *driver, device_t parent)
161{
162 device_t dev;
163 char desc[40];
152 int rid, i, j;
164 u_long rlen, rstart;
165 int i, j, rid, rtype;
153
154 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
155
156 if (acpi_disabled("timer"))
157 return_VOID;
158
159 if (AcpiGbl_FADT == NULL)
160 return_VOID;
161
162 if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) {
163 device_printf(parent, "could not add acpi_timer0\n");
164 return_VOID;
165 }
166 acpi_timer_dev = dev;
166
167 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
168
169 if (acpi_disabled("timer"))
170 return_VOID;
171
172 if (AcpiGbl_FADT == NULL)
173 return_VOID;
174
175 if ((dev = BUS_ADD_CHILD(parent, 0, "acpi_timer", 0)) == NULL) {
176 device_printf(parent, "could not add acpi_timer0\n");
177 return_VOID;
178 }
179 acpi_timer_dev = dev;
180
167 rid = 0;
181 rid = 0;
168 bus_set_resource(dev, SYS_RES_IOPORT, rid, AcpiGbl_FADT->V1_PmTmrBlk, sizeof(u_int32_t));
169 if ((acpi_timer_reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE)) == NULL) {
170 device_printf(dev, "couldn't allocate I/O resource (port 0x%x)\n", AcpiGbl_FADT->V1_PmTmrBlk);
182 rlen = AcpiGbl_FADT->PmTmLen;
183 rtype = (AcpiGbl_FADT->XPmTmrBlk.AddressSpaceId)
184 ? SYS_RES_IOPORT : SYS_RES_MEMORY;
185 rstart = AcpiGbl_FADT->XPmTmrBlk.Address;
186 bus_set_resource(dev, rtype, rid, rstart, rlen);
187 acpi_timer_reg = bus_alloc_resource(dev, rtype, &rid, 0, ~0, 1, RF_ACTIVE);
188 if (acpi_timer_reg == NULL) {
189 device_printf(dev, "couldn't allocate I/O resource (%s 0x%lx)\n",
190 (rtype == SYS_RES_IOPORT) ? "port" : "mem", rstart);
171 return_VOID;
172 }
173 if (testenv("debug.acpi.timer_test"))
174 acpi_timer_test();
175
176 acpi_timer_timecounter.tc_frequency = acpi_timer_frequency;
177 j = 0;
178 for(i = 0; i < 10; i++)
179 j += test_counter();
180 if (j == 10) {
181 acpi_timer_timecounter.tc_name = "ACPI-fast";
182 acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount;
183 } else {
184 acpi_timer_timecounter.tc_name = "ACPI-safe";
185 acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount_safe;
186 }
187 tc_init(&acpi_timer_timecounter);
188
191 return_VOID;
192 }
193 if (testenv("debug.acpi.timer_test"))
194 acpi_timer_test();
195
196 acpi_timer_timecounter.tc_frequency = acpi_timer_frequency;
197 j = 0;
198 for(i = 0; i < 10; i++)
199 j += test_counter();
200 if (j == 10) {
201 acpi_timer_timecounter.tc_name = "ACPI-fast";
202 acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount;
203 } else {
204 acpi_timer_timecounter.tc_name = "ACPI-safe";
205 acpi_timer_timecounter.tc_get_timecount = acpi_timer_get_timecount_safe;
206 }
207 tc_init(&acpi_timer_timecounter);
208
189 sprintf(desc, "%d-bit timer at 3.579545MHz", AcpiGbl_FADT->TmrValExt ? 32 : 24);
209 sprintf(desc, "%d-bit timer at 3.579545MHz", (AcpiGbl_FADT->TmrValExt)
210 ? 32 : 24);
190 device_set_desc_copy(dev, desc);
191
192 return_VOID;
193}
194
195static int
196acpi_timer_probe(device_t dev)
197{

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

207}
208
209/*
210 * Fetch current time value from reliable hardware.
211 */
212static unsigned
213acpi_timer_get_timecount(struct timecounter *tc)
214{
211 device_set_desc_copy(dev, desc);
212
213 return_VOID;
214}
215
216static int
217acpi_timer_probe(device_t dev)
218{

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

228}
229
230/*
231 * Fetch current time value from reliable hardware.
232 */
233static unsigned
234acpi_timer_get_timecount(struct timecounter *tc)
235{
215 return(TIMER_READ);
236 return (read_counter());
216}
217
218/*
219 * Fetch current time value from hardware that may not correctly
220 * latch the counter.
221 */
222static unsigned
223acpi_timer_get_timecount_safe(struct timecounter *tc)
224{
225 unsigned u1, u2, u3;
226
237}
238
239/*
240 * Fetch current time value from hardware that may not correctly
241 * latch the counter.
242 */
243static unsigned
244acpi_timer_get_timecount_safe(struct timecounter *tc)
245{
246 unsigned u1, u2, u3;
247
227 u2 = TIMER_READ;
228 u3 = TIMER_READ;
248 u2 = read_counter();
249 u3 = read_counter();
229 do {
230 u1 = u2;
231 u2 = u3;
250 do {
251 u1 = u2;
252 u2 = u3;
232 u3 = TIMER_READ;
253 u3 = read_counter();
233 } while (u1 > u2 || u2 > u3 || (u3 - u1) > 15);
234 return (u2);
235}
236
237/*
238 * Timecounter freqency adjustment interface.
239 */
240static int

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

261 * Test harness for verifying ACPI timer behaviour.
262 * Boot with debug.acpi.timer_test set to invoke this.
263 */
264static void
265acpi_timer_test(void)
266{
267 u_int32_t u1, u2, u3;
268
254 } while (u1 > u2 || u2 > u3 || (u3 - u1) > 15);
255 return (u2);
256}
257
258/*
259 * Timecounter freqency adjustment interface.
260 */
261static int

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

282 * Test harness for verifying ACPI timer behaviour.
283 * Boot with debug.acpi.timer_test set to invoke this.
284 */
285static void
286acpi_timer_test(void)
287{
288 u_int32_t u1, u2, u3;
289
269 u1 = TIMER_READ;
270 u2 = TIMER_READ;
271 u3 = TIMER_READ;
290 u1 = read_counter();
291 u2 = read_counter();
292 u3 = read_counter();
272
273 device_printf(acpi_timer_dev, "timer test in progress, reboot to quit.\n");
274 for (;;) {
275 /*
276 * The failure case is where u3 > u1, but u2 does not fall between the two,
277 * ie. it contains garbage.
278 */
279 if (u3 > u1) {
280 if ((u2 < u1) || (u2 > u3))
281 device_printf(acpi_timer_dev, "timer is not monotonic: 0x%08x,0x%08x,0x%08x\n",
282 u1, u2, u3);
283 }
284 u1 = u2;
285 u2 = u3;
293
294 device_printf(acpi_timer_dev, "timer test in progress, reboot to quit.\n");
295 for (;;) {
296 /*
297 * The failure case is where u3 > u1, but u2 does not fall between the two,
298 * ie. it contains garbage.
299 */
300 if (u3 > u1) {
301 if ((u2 < u1) || (u2 > u3))
302 device_printf(acpi_timer_dev, "timer is not monotonic: 0x%08x,0x%08x,0x%08x\n",
303 u1, u2, u3);
304 }
305 u1 = u2;
306 u2 = u3;
286 u3 = TIMER_READ;
307 u3 = read_counter();
287 }
288}
289
290/*
291 * Chipset workaround driver hung off PCI.
292 *
293 * Some ACPI timers are known or believed to suffer from implementation
294 * problems which can lead to erroneous values being read from the timer.

--- 74 unchanged lines hidden ---
308 }
309}
310
311/*
312 * Chipset workaround driver hung off PCI.
313 *
314 * Some ACPI timers are known or believed to suffer from implementation
315 * problems which can lead to erroneous values being read from the timer.

--- 74 unchanged lines hidden ---