Skip to content

Commit c3bc26d

Browse files
Lv Zhengrafaeljw
authored andcommitted
ACPICA: ACPI 2.0, Hardware: Add access_width/bit_offset support in acpi_hw_read()
ACPICA commit 96ece052d4d073aae4f935f0ff0746646aea1174 ACPICA commit 3d8583a054e410f2ea4d73b48986facad9cfc0d4 This patch adds access_width/bit_offset support in acpi_hw_read(). This also enables GAS definition where bit_width is not a power of two. Lv Zheng. Link: acpica/acpica@96ece052 Link: acpica/acpica@3d8583a0 Link: https://bugs.acpica.org/show_bug.cgi?id=1240 Signed-off-by: Lv Zheng <[email protected]> Signed-off-by: Bob Moore <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 9222aa8 commit c3bc26d

File tree

1 file changed

+62
-13
lines changed

1 file changed

+62
-13
lines changed

drivers/acpi/acpica/hwregs.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,17 +195,19 @@ acpi_hw_validate_register(struct acpi_generic_address *reg,
195195
* 64-bit values is not needed.
196196
*
197197
* LIMITATIONS: <These limitations also apply to acpi_hw_write>
198-
* bit_width must be exactly 8, 16, or 32.
199198
* space_ID must be system_memory or system_IO.
200-
* bit_offset and access_width are currently ignored, as there has
201-
* not been a need to implement these.
202199
*
203200
******************************************************************************/
204201

205202
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
206203
{
207204
u64 address;
205+
u8 access_width;
206+
u32 bit_width;
207+
u8 bit_offset;
208208
u64 value64;
209+
u32 value32;
210+
u8 index;
209211
acpi_status status;
210212

211213
ACPI_FUNCTION_NAME(hw_read);
@@ -217,28 +219,75 @@ acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
217219
return (status);
218220
}
219221

220-
/* Initialize entire 32-bit return value to zero */
221-
222+
/*
223+
* Initialize entire 32-bit return value to zero, convert access_width
224+
* into number of bits based
225+
*/
222226
*value = 0;
227+
access_width = acpi_hw_get_access_bit_width(reg, 32);
228+
bit_width = reg->bit_offset + reg->bit_width;
229+
bit_offset = reg->bit_offset;
223230

224231
/*
225232
* Two address spaces supported: Memory or IO. PCI_Config is
226233
* not supported here because the GAS structure is insufficient
227234
*/
228-
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
229-
status = acpi_os_read_memory((acpi_physical_address)
230-
address, &value64, reg->bit_width);
235+
index = 0;
236+
while (bit_width) {
237+
if (bit_offset >= access_width) {
238+
value32 = 0;
239+
bit_offset -= access_width;
240+
} else {
241+
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
242+
status =
243+
acpi_os_read_memory((acpi_physical_address)
244+
address +
245+
index *
246+
ACPI_DIV_8
247+
(access_width),
248+
&value64, access_width);
249+
value32 = (u32)value64;
250+
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
251+
252+
status = acpi_hw_read_port((acpi_io_address)
253+
address +
254+
index *
255+
ACPI_DIV_8
256+
(access_width),
257+
&value32,
258+
access_width);
259+
}
231260

232-
*value = (u32)value64;
233-
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
261+
/*
262+
* Use offset style bit masks because:
263+
* bit_offset < access_width/bit_width < access_width, and
264+
* access_width is ensured to be less than 32-bits by
265+
* acpi_hw_validate_register().
266+
*/
267+
if (bit_offset) {
268+
value32 &= ACPI_MASK_BITS_BELOW(bit_offset);
269+
bit_offset = 0;
270+
}
271+
if (bit_width < access_width) {
272+
value32 &= ACPI_MASK_BITS_ABOVE(bit_width);
273+
}
274+
}
275+
276+
/*
277+
* Use offset style bit writes because "Index * AccessWidth" is
278+
* ensured to be less than 32-bits by acpi_hw_validate_register().
279+
*/
280+
ACPI_SET_BITS(value, index * access_width,
281+
ACPI_MASK_BITS_ABOVE_32(access_width), value32);
234282

235-
status = acpi_hw_read_port((acpi_io_address)
236-
address, value, reg->bit_width);
283+
bit_width -=
284+
bit_width > access_width ? access_width : bit_width;
285+
index++;
237286
}
238287

239288
ACPI_DEBUG_PRINT((ACPI_DB_IO,
240289
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
241-
*value, reg->bit_width, ACPI_FORMAT_UINT64(address),
290+
*value, access_width, ACPI_FORMAT_UINT64(address),
242291
acpi_ut_get_region_name(reg->space_id)));
243292

244293
return (status);

0 commit comments

Comments
 (0)