8b8454d50b4c093209eb63dce739b139a3fa563f
[dragonfly.git] / sys / platform / pc32 / acpica5 / acpi_pstate_machdep.c
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Sepherosa Ziehau <sepherosa@gmail.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
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
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/globaldata.h>
38
39 #include <machine/md_var.h>
40 #include <machine/cpufunc.h>
41 #include <machine/cpufreq.h>
42 #include <machine/cputypes.h>
43 #include <machine/specialreg.h>
44
45 #include "acpi.h"
46 #include "acpi_cpu_pstate.h"
47
48 #define AMD_APMI_HWPSTATE               0x80
49
50 #define AMD_MSR_PSTATE_CSR_MASK         0x7ULL
51 #define AMD1X_MSR_PSTATE_CTL            0xc0010062
52 #define AMD1X_MSR_PSTATE_ST             0xc0010063
53
54 #define AMD_MSR_PSTATE_EN               0x8000000000000000ULL
55
56 #define AMD10_MSR_PSTATE_START          0xc0010064
57 #define AMD10_MSR_PSTATE_COUNT          5
58
59 #define AMD0F_PST_CTL_FID(cval)         (((cval) >> 0)  & 0x3f)
60 #define AMD0F_PST_CTL_VID(cval)         (((cval) >> 6)  & 0x1f)
61 #define AMD0F_PST_CTL_VST(cval)         (((cval) >> 11) & 0x7f)
62 #define AMD0F_PST_CTL_MVS(cval)         (((cval) >> 18) & 0x3)
63 #define AMD0F_PST_CTL_PLLTIME(cval)     (((cval) >> 20) & 0x7f)
64 #define AMD0F_PST_CTL_RVO(cval)         (((cval) >> 28) & 0x3)
65 #define AMD0F_PST_CTL_IRT(cval)         (((cval) >> 30) & 0x3)
66
67 #define AMD0F_PST_ST_FID(sval)          (((sval) >> 0) & 0x3f)
68 #define AMD0F_PST_ST_VID(sval)          (((sval) >> 6) & 0x3f)
69
70 #define INTEL_MSR_MISC_ENABLE           0x1a0
71 #define INTEL_MSR_MISC_EST_EN           0x10000ULL
72
73 #define INTEL_MSR_PERF_STATUS           0x198
74 #define INTEL_MSR_PERF_CTL              0x199
75 #define INTEL_MSR_PERF_MASK             0xffffULL
76
77 static const struct acpi_pst_md *
78                 acpi_pst_amd_probe(void);
79 static int      acpi_pst_amd_check_csr(const struct acpi_pst_res *,
80                     const struct acpi_pst_res *);
81 static int      acpi_pst_amd1x_check_pstates(const struct acpi_pstate *, int,
82                     uint32_t, uint32_t);
83 static int      acpi_pst_amd10_check_pstates(const struct acpi_pstate *, int);
84 static int      acpi_pst_amd0f_check_pstates(const struct acpi_pstate *, int);
85 static int      acpi_pst_amd_init(const struct acpi_pst_res *,
86                     const struct acpi_pst_res *);
87 static int      acpi_pst_amd1x_set_pstate(const struct acpi_pst_res *,
88                     const struct acpi_pst_res *, const struct acpi_pstate *);
89 static int      acpi_pst_amd0f_set_pstate(const struct acpi_pst_res *,
90                     const struct acpi_pst_res *, const struct acpi_pstate *);
91 static const struct acpi_pstate *
92                 acpi_pst_amd1x_get_pstate(const struct acpi_pst_res *,
93                     const struct acpi_pstate *, int);
94 static const struct acpi_pstate *
95                 acpi_pst_amd0f_get_pstate(const struct acpi_pst_res *,
96                     const struct acpi_pstate *, int);
97
98 static const struct acpi_pst_md *
99                 acpi_pst_intel_probe(void);
100 static int      acpi_pst_intel_check_csr(const struct acpi_pst_res *,
101                     const struct acpi_pst_res *);
102 static int      acpi_pst_intel_check_pstates(const struct acpi_pstate *, int);
103 static int      acpi_pst_intel_init(const struct acpi_pst_res *,
104                     const struct acpi_pst_res *);
105 static int      acpi_pst_intel_set_pstate(const struct acpi_pst_res *,
106                     const struct acpi_pst_res *, const struct acpi_pstate *);
107 static const struct acpi_pstate *
108                 acpi_pst_intel_get_pstate(const struct acpi_pst_res *,
109                     const struct acpi_pstate *, int);
110
111 static int      acpi_pst_md_gas_asz(const ACPI_GENERIC_ADDRESS *);
112 static int      acpi_pst_md_gas_verify(const ACPI_GENERIC_ADDRESS *);
113 static uint32_t acpi_pst_md_res_read(const struct acpi_pst_res *);
114 static void     acpi_pst_md_res_write(const struct acpi_pst_res *, uint32_t);
115
116 static const struct acpi_pst_md acpi_pst_amd10 = {
117         .pmd_check_csr          = acpi_pst_amd_check_csr,
118         .pmd_check_pstates      = acpi_pst_amd10_check_pstates,
119         .pmd_init               = acpi_pst_amd_init,
120         .pmd_set_pstate         = acpi_pst_amd1x_set_pstate,
121         .pmd_get_pstate         = acpi_pst_amd1x_get_pstate
122 };
123
124 static const struct acpi_pst_md acpi_pst_amd0f = {
125         .pmd_check_csr          = acpi_pst_amd_check_csr,
126         .pmd_check_pstates      = acpi_pst_amd0f_check_pstates,
127         .pmd_init               = acpi_pst_amd_init,
128         .pmd_set_pstate         = acpi_pst_amd0f_set_pstate,
129         .pmd_get_pstate         = acpi_pst_amd0f_get_pstate
130 };
131
132 static const struct acpi_pst_md acpi_pst_intel = {
133         .pmd_check_csr          = acpi_pst_intel_check_csr,
134         .pmd_check_pstates      = acpi_pst_intel_check_pstates,
135         .pmd_init               = acpi_pst_intel_init,
136         .pmd_set_pstate         = acpi_pst_intel_set_pstate,
137         .pmd_get_pstate         = acpi_pst_intel_get_pstate
138 };
139
140 const struct acpi_pst_md *
141 acpi_pst_md_probe(void)
142 {
143         if (cpu_vendor_id == CPU_VENDOR_AMD)
144                 return acpi_pst_amd_probe();
145         else if (cpu_vendor_id == CPU_VENDOR_INTEL)
146                 return acpi_pst_intel_probe();
147         return NULL;
148 }
149
150 static const struct acpi_pst_md *
151 acpi_pst_amd_probe(void)
152 {
153         uint32_t regs[4], ext_family;
154
155         if ((cpu_id & 0x00000f00) != 0x00000f00)
156                 return NULL;
157
158         /* Check whether APMI exists */
159         do_cpuid(0x80000000, regs);
160         if (regs[0] < 0x80000007)
161                 return NULL;
162
163         /* Fetch APMI */
164         do_cpuid(0x80000007, regs);
165
166         ext_family = cpu_id & 0x0ff00000;
167         switch (ext_family) {
168         case 0x00000000:        /* Family 0fh */
169                 if ((regs[3] & 0x06) == 0x06)
170                         return &acpi_pst_amd0f;
171                 break;
172
173         case 0x00100000:        /* Family 10h */
174                 if (regs[3] & 0x80)
175                         return &acpi_pst_amd10;
176                 break;
177
178         default:
179                 break;
180         }
181         return NULL;
182 }
183
184 static int
185 acpi_pst_amd_check_csr(const struct acpi_pst_res *ctrl,
186                        const struct acpi_pst_res *status)
187 {
188         if (ctrl->pr_gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) {
189                 kprintf("cpu%d: Invalid P-State control register\n", mycpuid);
190                 return EINVAL;
191         }
192         if (status->pr_gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) {
193                 kprintf("cpu%d: Invalid P-State status register\n", mycpuid);
194                 return EINVAL;
195         }
196         return 0;
197 }
198
199 static int
200 acpi_pst_amd1x_check_pstates(const struct acpi_pstate *pstates, int npstates,
201                              uint32_t msr_start, uint32_t msr_end)
202 {
203         int i;
204
205         /*
206          * Make sure that related MSR P-State registers are enabled.
207          *
208          * NOTE:
209          * We don't check status register value here;
210          * it will not be used.
211          */
212         for (i = 0; i < npstates; ++i) {
213                 uint64_t pstate;
214                 uint32_t msr;
215
216                 msr = msr_start +
217                       (pstates[i].st_cval & AMD_MSR_PSTATE_CSR_MASK);
218                 if (msr >= msr_end) {
219                         kprintf("cpu%d: MSR P-State register %#08x "
220                                 "does not exist\n", mycpuid, msr);
221                         return EINVAL;
222                 }
223
224                 pstate = rdmsr(msr);
225                 if ((pstate & AMD_MSR_PSTATE_EN) == 0) {
226                         kprintf("cpu%d: MSR P-State register %#08x "
227                                 "is not enabled\n", mycpuid, msr);
228                         return EINVAL;
229                 }
230         }
231         return 0;
232 }
233
234 static int
235 acpi_pst_amd10_check_pstates(const struct acpi_pstate *pstates, int npstates)
236 {
237         /* Only P0-P4 are supported */
238         if (npstates > AMD10_MSR_PSTATE_COUNT) {
239                 kprintf("cpu%d: only P0-P4 is allowed\n", mycpuid);
240                 return EINVAL;
241         }
242
243         return acpi_pst_amd1x_check_pstates(pstates, npstates,
244                         AMD10_MSR_PSTATE_START,
245                         AMD10_MSR_PSTATE_START + AMD10_MSR_PSTATE_COUNT);
246 }
247
248 static int
249 acpi_pst_amd1x_set_pstate(const struct acpi_pst_res *ctrl __unused,
250                           const struct acpi_pst_res *status __unused,
251                           const struct acpi_pstate *pstate)
252 {
253         uint64_t cval;
254
255         cval = pstate->st_cval & AMD_MSR_PSTATE_CSR_MASK;
256         wrmsr(AMD1X_MSR_PSTATE_CTL, cval);
257
258         /*
259          * Don't check AMD1X_MSR_PSTATE_ST here, since it is
260          * affected by various P-State limits.
261          *
262          * For details:
263          * AMD Family 10h Processor BKDG Rev 3.20 (#31116)
264          * 2.4.2.4 P-state Transition Behavior
265          */
266
267         return 0;
268 }
269
270 static const struct acpi_pstate *
271 acpi_pst_amd1x_get_pstate(const struct acpi_pst_res *status __unused,
272                           const struct acpi_pstate *pstates, int npstates)
273 {
274         uint64_t sval;
275         int i;
276
277         sval = rdmsr(AMD1X_MSR_PSTATE_ST) & AMD_MSR_PSTATE_CSR_MASK;
278         for (i = 0; i < npstates; ++i) {
279                 if ((pstates[i].st_sval & AMD_MSR_PSTATE_CSR_MASK) == sval)
280                         return &pstates[i];
281         }
282         return NULL;
283 }
284
285 static int
286 acpi_pst_amd0f_check_pstates(const struct acpi_pstate *pstates, int npstates)
287 {
288         struct amd0f_fidvid fv_max, fv_min;
289         int i;
290
291         amd0f_fidvid_limit(&fv_min, &fv_max);
292
293         for (i = 0; i < npstates; ++i) {
294                 const struct acpi_pstate *p = &pstates[i];
295                 uint32_t fid, vid, mvs, rvo;
296                 int mvs_mv, rvo_mv;
297
298                 fid = AMD0F_PST_CTL_FID(p->st_cval);
299                 vid = AMD0F_PST_CTL_VID(p->st_cval);
300
301                 if (fid > fv_max.fid || fid < fv_min.fid) {
302                         kprintf("cpu%d: Invalid FID %#x [%#x, %#x]\n",
303                                 mycpuid, fid, fv_min.fid, fv_max.fid);
304                         return EINVAL;
305                 }
306                 if (vid < fv_max.vid || vid > fv_min.vid) {
307                         kprintf("cpu%d: Invalid VID %#x [%#x, %#x]\n",
308                                 mycpuid, vid, fv_max.vid, fv_min.fid);
309                         return EINVAL;
310                 }
311
312                 mvs = AMD0F_PST_CTL_MVS(p->st_cval);
313                 rvo = AMD0F_PST_CTL_RVO(p->st_cval);
314
315                 /* Only 0 is allowed, i.e. 25mV stepping */
316                 if (mvs != 0) {
317                         kprintf("cpu%d: Invalid MVS %#x\n", mycpuid, mvs);
318                         return EINVAL;
319                 }
320
321                 /* -> mV */
322                 mvs_mv = 25 * (1 << mvs);
323                 rvo_mv = 25 * rvo;
324                 if (rvo_mv % mvs_mv != 0) {
325                         kprintf("cpu%d: Invalid MVS/RVO (%#x/%#x)\n",
326                                 mycpuid, mvs, rvo);
327                         return EINVAL;
328                 }
329         }
330         return 0;
331 }
332
333 static int
334 acpi_pst_amd0f_set_pstate(const struct acpi_pst_res *ctrl __unused,
335                           const struct acpi_pst_res *status __unused,
336                           const struct acpi_pstate *pstate)
337 {
338         struct amd0f_fidvid fv;
339         struct amd0f_xsit xsit;
340
341         fv.fid = AMD0F_PST_CTL_FID(pstate->st_cval);
342         fv.vid = AMD0F_PST_CTL_VID(pstate->st_cval);
343
344         xsit.rvo = AMD0F_PST_CTL_RVO(pstate->st_cval);
345         xsit.mvs = AMD0F_PST_CTL_MVS(pstate->st_cval);
346         xsit.vst = AMD0F_PST_CTL_VST(pstate->st_cval);
347         xsit.pll_time = AMD0F_PST_CTL_PLLTIME(pstate->st_cval);
348         xsit.irt = AMD0F_PST_CTL_IRT(pstate->st_cval);
349
350         return amd0f_set_fidvid(&fv, &xsit);
351 }
352
353 static const struct acpi_pstate *
354 acpi_pst_amd0f_get_pstate(const struct acpi_pst_res *status __unused,
355                           const struct acpi_pstate *pstates, int npstates)
356 {
357         struct amd0f_fidvid fv;
358         int error, i;
359
360         error = amd0f_get_fidvid(&fv);
361         if (error)
362                 return NULL;
363
364         for (i = 0; i < npstates; ++i) {
365                 const struct acpi_pstate *p = &pstates[i];
366
367                 if (fv.fid == AMD0F_PST_ST_FID(p->st_sval) &&
368                     fv.vid == AMD0F_PST_ST_VID(p->st_sval))
369                         return p;
370         }
371         return NULL;
372 }
373
374 static int
375 acpi_pst_amd_init(const struct acpi_pst_res *ctrl __unused,
376                   const struct acpi_pst_res *status __unused)
377 {
378         return 0;
379 }
380
381 static const struct acpi_pst_md *
382 acpi_pst_intel_probe(void)
383 {
384         uint32_t family;
385
386         if ((cpu_feature2 & CPUID2_EST) == 0)
387                 return NULL;
388
389         family = cpu_id & 0xf00;
390         if (family != 0xf00 && family != 0x600)
391                 return NULL;
392         return &acpi_pst_intel;
393 }
394
395 static int
396 acpi_pst_intel_check_csr(const struct acpi_pst_res *ctrl,
397                          const struct acpi_pst_res *status)
398 {
399         int error;
400
401         if (ctrl->pr_gas.SpaceId != status->pr_gas.SpaceId) {
402                 kprintf("cpu%d: P-State control(%d)/status(%d) registers have "
403                         "different SpaceId", mycpuid,
404                         ctrl->pr_gas.SpaceId, status->pr_gas.SpaceId);
405                 return EINVAL;
406         }
407
408         switch (ctrl->pr_gas.SpaceId) {
409         case ACPI_ADR_SPACE_FIXED_HARDWARE:
410                 if (ctrl->pr_res != NULL || status->pr_res != NULL) {
411                         /* XXX should panic() */
412                         kprintf("cpu%d: Allocated resource for fixed hardware "
413                                 "registers\n", mycpuid);
414                         return EINVAL;
415                 }
416                 break;
417
418         case ACPI_ADR_SPACE_SYSTEM_IO:
419                 if (ctrl->pr_res == NULL) {
420                         kprintf("cpu%d: ioport allocation failed for control "
421                                 "register\n", mycpuid);
422                         return ENXIO;
423                 }
424                 error = acpi_pst_md_gas_verify(&ctrl->pr_gas);
425                 if (error) {
426                         kprintf("cpu%d: Invalid control register GAS\n",
427                                 mycpuid);
428                         return error;
429                 }
430
431                 if (status->pr_res == NULL) {
432                         kprintf("cpu%d: ioport allocation failed for status "
433                                 "register\n", mycpuid);
434                         return ENXIO;
435                 }
436                 error = acpi_pst_md_gas_verify(&status->pr_gas);
437                 if (error) {
438                         kprintf("cpu%d: Invalid status register GAS\n",
439                                 mycpuid);
440                         return error;
441                 }
442                 break;
443
444         default:
445                 kprintf("cpu%d: Invalid P-State control/status register "
446                         "SpaceId %d\n", mycpuid, ctrl->pr_gas.SpaceId);
447                 return EOPNOTSUPP;
448         }
449         return 0;
450 }
451
452 static int
453 acpi_pst_intel_check_pstates(const struct acpi_pstate *pstates __unused,
454                              int npstates __unused)
455 {
456         return 0;
457 }
458
459 static int
460 acpi_pst_intel_init(const struct acpi_pst_res *ctrl __unused,
461                     const struct acpi_pst_res *status __unused)
462 {
463         uint32_t family, model;
464         uint64_t misc_enable;
465
466         family = cpu_id & 0xf00;
467         if (family == 0xf00) {
468                 /* EST enable bit is reserved in INTEL_MSR_MISC_ENABLE */
469                 return 0;
470         }
471         KKASSERT(family == 0x600);
472
473         model = ((cpu_id & 0xf0000) >> 12) | ((cpu_id & 0xf0) >> 4);
474         if (model < 0xd) {
475                 /* EST enable bit is reserved in INTEL_MSR_MISC_ENABLE */
476                 return 0;
477         }
478
479         misc_enable = rdmsr(INTEL_MSR_MISC_ENABLE);
480         if ((misc_enable & INTEL_MSR_MISC_EST_EN) == 0) {
481                 misc_enable |= INTEL_MSR_MISC_EST_EN;
482                 wrmsr(INTEL_MSR_MISC_ENABLE, misc_enable);
483
484                 misc_enable = rdmsr(INTEL_MSR_MISC_ENABLE);
485                 if ((misc_enable & INTEL_MSR_MISC_EST_EN) == 0) {
486                         kprintf("cpu%d: Can't enable EST\n", mycpuid);
487                         return EIO;
488                 }
489         }
490         return 0;
491 }
492
493 static int
494 acpi_pst_intel_set_pstate(const struct acpi_pst_res *ctrl,
495                           const struct acpi_pst_res *status __unused,
496                           const struct acpi_pstate *pstate)
497 {
498         if (ctrl->pr_res != NULL) {
499                 acpi_pst_md_res_write(ctrl, pstate->st_cval);
500         } else {
501                 uint64_t ctl;
502
503                 ctl = rdmsr(INTEL_MSR_PERF_CTL);
504                 ctl &= ~INTEL_MSR_PERF_MASK;
505                 ctl |= (pstate->st_cval & INTEL_MSR_PERF_MASK);
506                 wrmsr(INTEL_MSR_PERF_CTL, ctl);
507         }
508         return 0;
509 }
510
511 static const struct acpi_pstate *
512 acpi_pst_intel_get_pstate(const struct acpi_pst_res *status,
513                           const struct acpi_pstate *pstates, int npstates)
514 {
515         int i;
516
517         if (status->pr_res != NULL) {
518                 uint32_t st;
519
520                 st = acpi_pst_md_res_read(status);
521                 for (i = 0; i < npstates; ++i) {
522                         if (pstates[i].st_sval == st)
523                                 return &pstates[i];
524                 }
525         } else {
526                 uint64_t sval;
527
528                 sval = rdmsr(INTEL_MSR_PERF_STATUS) & INTEL_MSR_PERF_MASK;
529                 for (i = 0; i < npstates; ++i) {
530                         if ((pstates[i].st_sval & INTEL_MSR_PERF_MASK) == sval)
531                                 return &pstates[i];
532                 }
533         }
534         return NULL;
535 }
536
537 static int
538 acpi_pst_md_gas_asz(const ACPI_GENERIC_ADDRESS *gas)
539 {
540         int asz;
541
542         if (gas->AccessWidth != 0)
543                 asz = gas->AccessWidth;
544         else
545                 asz = gas->BitWidth / NBBY;
546         switch (asz) {
547         case 1:
548         case 2:
549         case 4:
550                 break;
551         default:
552                 asz = 0;
553                 break;
554         }
555         return asz;
556 }
557
558 static int
559 acpi_pst_md_gas_verify(const ACPI_GENERIC_ADDRESS *gas)
560 {
561         int reg, end, asz;
562
563         if (gas->BitOffset % NBBY != 0)
564                 return EINVAL;
565
566         end = gas->BitWidth / NBBY;
567         reg = gas->BitOffset / NBBY;
568
569         if (reg >= end)
570                 return EINVAL;
571
572         asz = acpi_pst_md_gas_asz(gas);
573         if (asz == 0)
574                 return EINVAL;
575
576         if (reg + asz > end)
577                 return EINVAL;
578         return 0;
579 }
580
581 static uint32_t
582 acpi_pst_md_res_read(const struct acpi_pst_res *res)
583 {
584         int asz, reg;
585
586         KKASSERT(res->pr_res != NULL);
587         asz = acpi_pst_md_gas_asz(&res->pr_gas);
588         reg = res->pr_gas.BitOffset / NBBY;
589
590         switch (asz) {
591         case 1:
592                 return bus_space_read_1(res->pr_bt, res->pr_bh, reg);
593         case 2:
594                 return bus_space_read_2(res->pr_bt, res->pr_bh, reg);
595         case 4:
596                 return bus_space_read_4(res->pr_bt, res->pr_bh, reg);
597         }
598         panic("unsupported access width %d\n", asz);
599
600         /* NEVER REACHED */
601         return 0;
602 }
603
604 static void
605 acpi_pst_md_res_write(const struct acpi_pst_res *res, uint32_t val)
606 {
607         int asz, reg;
608
609         KKASSERT(res->pr_res != NULL);
610         asz = acpi_pst_md_gas_asz(&res->pr_gas);
611         reg = res->pr_gas.BitOffset / NBBY;
612
613         switch (asz) {
614         case 1:
615                 bus_space_write_1(res->pr_bt, res->pr_bh, reg, val);
616                 break;
617         case 2:
618                 bus_space_write_2(res->pr_bt, res->pr_bh, reg, val);
619                 break;
620         case 4:
621                 bus_space_write_4(res->pr_bt, res->pr_bh, reg, val);
622                 break;
623         default:
624                 panic("unsupported access width %d\n", asz);
625         }
626 }