1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <acpi/acpi.h>
46#include "accommon.h"
47#include "acevents.h"
48
49#define _COMPONENT ACPI_HARDWARE
50ACPI_MODULE_NAME("hwregs")
51
52#if (!ACPI_REDUCED_HARDWARE)
53
54static u8
55acpi_hw_get_access_bit_width(u64 address,
56 struct acpi_generic_address *reg,
57 u8 max_bit_width);
58
59static acpi_status
60acpi_hw_read_multiple(u32 *value,
61 struct acpi_generic_address *register_a,
62 struct acpi_generic_address *register_b);
63
64static acpi_status
65acpi_hw_write_multiple(u32 value,
66 struct acpi_generic_address *register_a,
67 struct acpi_generic_address *register_b);
68
69#endif
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85static u8
86acpi_hw_get_access_bit_width(u64 address,
87 struct acpi_generic_address *reg, u8 max_bit_width)
88{
89 u8 access_bit_width;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 if (!reg->bit_offset && reg->bit_width &&
106 ACPI_IS_POWER_OF_TWO(reg->bit_width) &&
107 ACPI_IS_ALIGNED(reg->bit_width, 8)) {
108 access_bit_width = reg->bit_width;
109 } else if (reg->access_width) {
110 access_bit_width = ACPI_ACCESS_BIT_WIDTH(reg->access_width);
111 } else {
112 access_bit_width =
113 ACPI_ROUND_UP_POWER_OF_TWO_8(reg->bit_offset +
114 reg->bit_width);
115 if (access_bit_width <= 8) {
116 access_bit_width = 8;
117 } else {
118 while (!ACPI_IS_ALIGNED(address, access_bit_width >> 3)) {
119 access_bit_width >>= 1;
120 }
121 }
122 }
123
124
125
126 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
127 max_bit_width = 32;
128 }
129
130
131
132
133
134
135 if (access_bit_width < max_bit_width) {
136 return (access_bit_width);
137 }
138 return (max_bit_width);
139}
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157acpi_status
158acpi_hw_validate_register(struct acpi_generic_address *reg,
159 u8 max_bit_width, u64 *address)
160{
161 u8 bit_width;
162 u8 access_width;
163
164
165
166 if (!reg) {
167 return (AE_BAD_PARAMETER);
168 }
169
170
171
172
173
174
175 ACPI_MOVE_64_TO_64(address, ®->address);
176 if (!(*address)) {
177 return (AE_BAD_ADDRESS);
178 }
179
180
181
182 if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
183 (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
184 ACPI_ERROR((AE_INFO,
185 "Unsupported address space: 0x%X", reg->space_id));
186 return (AE_SUPPORT);
187 }
188
189
190
191 if (reg->access_width > 4) {
192 ACPI_ERROR((AE_INFO,
193 "Unsupported register access width: 0x%X",
194 reg->access_width));
195 return (AE_SUPPORT);
196 }
197
198
199
200 access_width =
201 acpi_hw_get_access_bit_width(*address, reg, max_bit_width);
202 bit_width =
203 ACPI_ROUND_UP(reg->bit_offset + reg->bit_width, access_width);
204 if (max_bit_width < bit_width) {
205 ACPI_WARNING((AE_INFO,
206 "Requested bit width 0x%X is smaller than register bit width 0x%X",
207 max_bit_width, bit_width));
208 return (AE_SUPPORT);
209 }
210
211 return (AE_OK);
212}
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231acpi_status acpi_hw_read(u64 *value, struct acpi_generic_address *reg)
232{
233 u64 address;
234 u8 access_width;
235 u32 bit_width;
236 u8 bit_offset;
237 u64 value64;
238 u32 value32;
239 u8 index;
240 acpi_status status;
241
242 ACPI_FUNCTION_NAME(hw_read);
243
244
245
246 status = acpi_hw_validate_register(reg, 64, &address);
247 if (ACPI_FAILURE(status)) {
248 return (status);
249 }
250
251
252
253
254
255 *value = 0;
256 access_width = acpi_hw_get_access_bit_width(address, reg, 64);
257 bit_width = reg->bit_offset + reg->bit_width;
258 bit_offset = reg->bit_offset;
259
260
261
262
263
264 index = 0;
265 while (bit_width) {
266 if (bit_offset >= access_width) {
267 value64 = 0;
268 bit_offset -= access_width;
269 } else {
270 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
271 status =
272 acpi_os_read_memory((acpi_physical_address)
273 address +
274 index *
275 ACPI_DIV_8
276 (access_width),
277 &value64, access_width);
278 } else {
279
280 status = acpi_hw_read_port((acpi_io_address)
281 address +
282 index *
283 ACPI_DIV_8
284 (access_width),
285 &value32,
286 access_width);
287 value64 = (u64)value32;
288 }
289 }
290
291
292
293
294
295 ACPI_SET_BITS(value, index * access_width,
296 ACPI_MASK_BITS_ABOVE_64(access_width), value64);
297
298 bit_width -=
299 bit_width > access_width ? access_width : bit_width;
300 index++;
301 }
302
303 ACPI_DEBUG_PRINT((ACPI_DB_IO,
304 "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
305 ACPI_FORMAT_UINT64(*value), access_width,
306 ACPI_FORMAT_UINT64(address),
307 acpi_ut_get_region_name(reg->space_id)));
308
309 return (status);
310}
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326acpi_status acpi_hw_write(u64 value, struct acpi_generic_address *reg)
327{
328 u64 address;
329 u8 access_width;
330 u32 bit_width;
331 u8 bit_offset;
332 u64 value64;
333 u8 index;
334 acpi_status status;
335
336 ACPI_FUNCTION_NAME(hw_write);
337
338
339
340 status = acpi_hw_validate_register(reg, 64, &address);
341 if (ACPI_FAILURE(status)) {
342 return (status);
343 }
344
345
346
347 access_width = acpi_hw_get_access_bit_width(address, reg, 64);
348 bit_width = reg->bit_offset + reg->bit_width;
349 bit_offset = reg->bit_offset;
350
351
352
353
354
355 index = 0;
356 while (bit_width) {
357
358
359
360
361 value64 = ACPI_GET_BITS(&value, index * access_width,
362 ACPI_MASK_BITS_ABOVE_64(access_width));
363
364 if (bit_offset >= access_width) {
365 bit_offset -= access_width;
366 } else {
367 if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
368 status =
369 acpi_os_write_memory((acpi_physical_address)
370 address +
371 index *
372 ACPI_DIV_8
373 (access_width),
374 value64, access_width);
375 } else {
376
377 status = acpi_hw_write_port((acpi_io_address)
378 address +
379 index *
380 ACPI_DIV_8
381 (access_width),
382 (u32)value64,
383 access_width);
384 }
385 }
386
387
388
389
390
391 bit_width -=
392 bit_width > access_width ? access_width : bit_width;
393 index++;
394 }
395
396 ACPI_DEBUG_PRINT((ACPI_DB_IO,
397 "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
398 ACPI_FORMAT_UINT64(value), access_width,
399 ACPI_FORMAT_UINT64(address),
400 acpi_ut_get_region_name(reg->space_id)));
401
402 return (status);
403}
404
405#if (!ACPI_REDUCED_HARDWARE)
406
407
408
409
410
411
412
413
414
415
416
417
418acpi_status acpi_hw_clear_acpi_status(void)
419{
420 acpi_status status;
421 acpi_cpu_flags lock_flags = 0;
422
423 ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
424
425 ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n",
426 ACPI_BITMASK_ALL_FIXED_STATUS,
427 ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address)));
428
429 lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
430
431
432
433 status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS,
434 ACPI_BITMASK_ALL_FIXED_STATUS);
435
436 acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
437
438 if (ACPI_FAILURE(status)) {
439 goto exit;
440 }
441
442
443
444 status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL);
445
446exit:
447 return_ACPI_STATUS(status);
448}
449
450
451
452
453
454
455
456
457
458
459
460
461
462struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
463{
464 ACPI_FUNCTION_ENTRY();
465
466 if (register_id > ACPI_BITREG_MAX) {
467 ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: 0x%X",
468 register_id));
469 return (NULL);
470 }
471
472 return (&acpi_gbl_bit_register_info[register_id]);
473}
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
493{
494 acpi_status status;
495
496 ACPI_FUNCTION_TRACE(hw_write_pm1_control);
497
498 status =
499 acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
500 if (ACPI_FAILURE(status)) {
501 return_ACPI_STATUS(status);
502 }
503
504 if (acpi_gbl_FADT.xpm1b_control_block.address) {
505 status =
506 acpi_hw_write(pm1b_control,
507 &acpi_gbl_FADT.xpm1b_control_block);
508 }
509 return_ACPI_STATUS(status);
510}
511
512
513
514
515
516
517
518
519
520
521
522
523
524acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value)
525{
526 u32 value = 0;
527 u64 value64;
528 acpi_status status;
529
530 ACPI_FUNCTION_TRACE(hw_register_read);
531
532 switch (register_id) {
533 case ACPI_REGISTER_PM1_STATUS:
534
535 status = acpi_hw_read_multiple(&value,
536 &acpi_gbl_xpm1a_status,
537 &acpi_gbl_xpm1b_status);
538 break;
539
540 case ACPI_REGISTER_PM1_ENABLE:
541
542 status = acpi_hw_read_multiple(&value,
543 &acpi_gbl_xpm1a_enable,
544 &acpi_gbl_xpm1b_enable);
545 break;
546
547 case ACPI_REGISTER_PM1_CONTROL:
548
549 status = acpi_hw_read_multiple(&value,
550 &acpi_gbl_FADT.
551 xpm1a_control_block,
552 &acpi_gbl_FADT.
553 xpm1b_control_block);
554
555
556
557
558
559
560 value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS;
561 break;
562
563 case ACPI_REGISTER_PM2_CONTROL:
564
565 status =
566 acpi_hw_read(&value64, &acpi_gbl_FADT.xpm2_control_block);
567 value = (u32)value64;
568 break;
569
570 case ACPI_REGISTER_PM_TIMER:
571
572 status = acpi_hw_read(&value64, &acpi_gbl_FADT.xpm_timer_block);
573 value = (u32)value64;
574 break;
575
576 case ACPI_REGISTER_SMI_COMMAND_BLOCK:
577
578 status =
579 acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8);
580 break;
581
582 default:
583
584 ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
585 status = AE_BAD_PARAMETER;
586 break;
587 }
588
589 if (ACPI_SUCCESS(status)) {
590 *return_value = (u32)value;
591 }
592
593 return_ACPI_STATUS(status);
594}
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622acpi_status acpi_hw_register_write(u32 register_id, u32 value)
623{
624 acpi_status status;
625 u32 read_value;
626 u64 read_value64;
627
628 ACPI_FUNCTION_TRACE(hw_register_write);
629
630 switch (register_id) {
631 case ACPI_REGISTER_PM1_STATUS:
632
633
634
635
636
637
638
639
640
641
642 value &= ~ACPI_PM1_STATUS_PRESERVED_BITS;
643
644 status = acpi_hw_write_multiple(value,
645 &acpi_gbl_xpm1a_status,
646 &acpi_gbl_xpm1b_status);
647 break;
648
649 case ACPI_REGISTER_PM1_ENABLE:
650
651 status = acpi_hw_write_multiple(value,
652 &acpi_gbl_xpm1a_enable,
653 &acpi_gbl_xpm1b_enable);
654 break;
655
656 case ACPI_REGISTER_PM1_CONTROL:
657
658
659
660
661 status = acpi_hw_read_multiple(&read_value,
662 &acpi_gbl_FADT.
663 xpm1a_control_block,
664 &acpi_gbl_FADT.
665 xpm1b_control_block);
666 if (ACPI_FAILURE(status)) {
667 goto exit;
668 }
669
670
671
672 ACPI_INSERT_BITS(value, ACPI_PM1_CONTROL_PRESERVED_BITS,
673 read_value);
674
675
676
677 status = acpi_hw_write_multiple(value,
678 &acpi_gbl_FADT.
679 xpm1a_control_block,
680 &acpi_gbl_FADT.
681 xpm1b_control_block);
682 break;
683
684 case ACPI_REGISTER_PM2_CONTROL:
685
686
687
688
689 status =
690 acpi_hw_read(&read_value64,
691 &acpi_gbl_FADT.xpm2_control_block);
692 if (ACPI_FAILURE(status)) {
693 goto exit;
694 }
695 read_value = (u32)read_value64;
696
697
698
699 ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
700 read_value);
701
702 status =
703 acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
704 break;
705
706 case ACPI_REGISTER_PM_TIMER:
707
708 status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
709 break;
710
711 case ACPI_REGISTER_SMI_COMMAND_BLOCK:
712
713
714
715 status =
716 acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8);
717 break;
718
719 default:
720
721 ACPI_ERROR((AE_INFO, "Unknown Register ID: 0x%X", register_id));
722 status = AE_BAD_PARAMETER;
723 break;
724 }
725
726exit:
727 return_ACPI_STATUS(status);
728}
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744static acpi_status
745acpi_hw_read_multiple(u32 *value,
746 struct acpi_generic_address *register_a,
747 struct acpi_generic_address *register_b)
748{
749 u32 value_a = 0;
750 u32 value_b = 0;
751 u64 value64;
752 acpi_status status;
753
754
755
756 status = acpi_hw_read(&value64, register_a);
757 if (ACPI_FAILURE(status)) {
758 return (status);
759 }
760 value_a = (u32)value64;
761
762
763
764 if (register_b->address) {
765 status = acpi_hw_read(&value64, register_b);
766 if (ACPI_FAILURE(status)) {
767 return (status);
768 }
769 value_b = (u32)value64;
770 }
771
772
773
774
775
776
777
778
779
780
781
782 *value = (value_a | value_b);
783 return (AE_OK);
784}
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800static acpi_status
801acpi_hw_write_multiple(u32 value,
802 struct acpi_generic_address *register_a,
803 struct acpi_generic_address *register_b)
804{
805 acpi_status status;
806
807
808
809 status = acpi_hw_write(value, register_a);
810 if (ACPI_FAILURE(status)) {
811 return (status);
812 }
813
814
815
816
817
818
819
820
821
822
823
824
825
826 if (register_b->address) {
827 status = acpi_hw_write(value, register_b);
828 }
829
830 return (status);
831}
832
833#endif
834