#ifdef CONFIG_X86_PM_TIMER
/* detect the location of the ACPI PM Timer */
- if (fadt->header.revision >= FADT2_REVISION_ID) {
+ if (fadt->header.revision >= FADT2_REVISION_ID &&
+ fadt->xpm_timer_block.space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
/* FADT rev. 2 */
- if (fadt->xpm_timer_block.space_id ==
- ACPI_ADR_SPACE_SYSTEM_IO) {
+ if (fadt->xpm_timer_block.access_width != 0 &&
+ ACPI_ACCESS_BIT_WIDTH(fadt->xpm_timer_block.access_width) != 32)
+ printk(KERN_WARNING PREFIX "PM-Timer has invalid access width(%u)\n",
+ fadt->xpm_timer_block.access_width);
+ else if (fadt->xpm_timer_block.bit_offset != 0)
+ printk(KERN_WARNING PREFIX "PM-Timer has invalid bit offset(%u)\n",
+ fadt->xpm_timer_block.bit_offset);
+ else {
pmtmr_ioport = fadt->xpm_timer_block.address;
pmtmr_width = fadt->xpm_timer_block.bit_width;
}
*/
if (!pmtmr_ioport) {
pmtmr_ioport = fadt->pm_timer_block;
- pmtmr_width = fadt->pm_timer_length == 4 ? 24 : 0;
+ pmtmr_width = fadt->pm_timer_length == 4 ? 32 : 0;
}
+ if (pmtmr_width < 32 && (fadt->flags & ACPI_FADT_32BIT_TIMER))
+ printk(KERN_WARNING PREFIX "PM-Timer is too short\n");
+ if (pmtmr_width > 24 && !(fadt->flags & ACPI_FADT_32BIT_TIMER))
+ pmtmr_width = 24;
if (pmtmr_ioport)
printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x (%u bits)\n",
pmtmr_ioport, pmtmr_width);
static s64 __init init_pmtimer(struct platform_timesource *pts)
{
u64 start;
- u32 count, target, mask = 0xffffff;
+ u32 count, target, mask;
- if ( !pmtmr_ioport || !pmtmr_width )
+ if ( !pmtmr_ioport || (pmtmr_width != 24 && pmtmr_width != 32) )
return 0;
- if ( pmtmr_width == 32 )
- {
- pts->counter_bits = 32;
- mask = 0xffffffff;
- }
+ pts->counter_bits = pmtmr_width;
+ mask = 0xffffffff >> (32 - pmtmr_width);
count = inl(pmtmr_ioport) & mask;
start = rdtsc_ordered();
.name = "ACPI PM Timer",
.frequency = ACPI_PM_FREQUENCY,
.read_counter = read_pmtimer_count,
- .counter_bits = 24,
.init = init_pmtimer
};
#define ACPI_COMPARE_NAME(a,b) (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE))
#endif
+/*
+ * Algorithm to obtain access bit or byte width.
+ * Can be used with access_width of struct acpi_generic_address and access_size of
+ * struct acpi_resource_generic_register.
+ */
+#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2))
+#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) - 1))
+
/*
* Macros for moving data around to/from buffers that are possibly unaligned.
* If the hardware supports the transfer of unaligned data, just do the store.