Help reading of code programming the PIT by introducing constants for
control word, read back and latch commands, as well as status.
Requested-by: Jason Andryuk <jason.andryuk@amd.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v3: New.
--- a/xen/arch/x86/apic.c
+++ b/xen/arch/x86/apic.c
@@ -983,7 +983,7 @@ static unsigned int __init get_8254_time
/*spin_lock_irqsave(&i8253_lock, flags);*/
- outb_p(0x00, PIT_MODE);
+ outb_p(PIT_LTCH_CH(0), PIT_MODE);
count = inb_p(PIT_CH0);
count |= inb_p(PIT_CH0) << 8;
--- a/xen/arch/x86/include/asm/time.h
+++ b/xen/arch/x86/include/asm/time.h
@@ -58,4 +58,38 @@ struct time_scale;
void set_time_scale(struct time_scale *ts, u64 ticks_per_sec);
u64 scale_delta(u64 delta, const struct time_scale *scale);
+/* Programmable Interval Timer (8254) */
+
+/* Timer Control Word */
+#define PIT_TCW_CH(n) ((n) << 6)
+/* Lower bits also Timer Status. */
+#define PIT_RW_MSB (1 << 5)
+#define PIT_RW_LSB (1 << 4)
+#define PIT_RW_LSB_MSB (PIT_RW_LSB | PIT_RW_MSB)
+#define PIT_MODE_EOC (0 << 1)
+#define PIT_MODE_ONESHOT (1 << 1)
+#define PIT_MODE_RATE_GEN (2 << 1)
+#define PIT_MODE_SQUARE_WAVE (3 << 1)
+#define PIT_MODE_SW_STROBE (4 << 1)
+#define PIT_MODE_HW_STROBE (5 << 1)
+#define PIT_BINARY (0 << 0)
+#define PIT_BCD (1 << 0)
+
+/* Read Back Command */
+#define PIT_RDB PIT_TCW_CH(3)
+#define PIT_RDB_NO_COUNT (1 << 5)
+#define PIT_RDB_NO_STATUS (1 << 4)
+#define PIT_RDB_CH2 (1 << 3)
+#define PIT_RDB_CH1 (1 << 2)
+#define PIT_RDB_CH0 (1 << 1)
+#define PIT_RDB_RSVD (1 << 0)
+
+/* Counter Latch Command */
+#define PIT_LTCH_CH(n) PIT_TCW_CH(n)
+
+/* Timer Status */
+#define PIT_STATUS_OUT_PIN (1 << 7)
+#define PIT_STATUS_NULL_COUNT (1 << 6)
+/* Lower bits match Timer Control Word. */
+
#endif /* __X86_TIME_H__ */
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -222,7 +222,7 @@ static void cf_check timer_interrupt(int
spin_lock_irq(&pit_lock);
- outb(0x80, PIT_MODE);
+ outb(PIT_LTCH_CH(2), PIT_MODE);
count = inb(PIT_CH2);
count |= inb(PIT_CH2) << 8;
@@ -245,7 +245,8 @@ static void preinit_pit(void)
{
/* Set PIT channel 0 to HZ Hz. */
#define LATCH (((CLOCK_TICK_RATE)+(HZ/2))/HZ)
- outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb_p(PIT_TCW_CH(0) | PIT_RW_LSB_MSB | PIT_MODE_RATE_GEN | PIT_BINARY,
+ PIT_MODE);
outb_p(LATCH & 0xff, PIT_CH0); /* LSB */
outb(LATCH >> 8, PIT_CH0); /* MSB */
#undef LATCH
@@ -356,7 +357,7 @@ static u64 cf_check read_pit_count(void)
spin_lock_irqsave(&pit_lock, flags);
- outb(0x80, PIT_MODE);
+ outb(PIT_LTCH_CH(2), PIT_MODE);
count16 = inb(PIT_CH2);
count16 |= inb(PIT_CH2) << 8;
@@ -383,7 +384,8 @@ static s64 __init cf_check init_pit(stru
*/
#define CALIBRATE_LATCH CALIBRATE_VALUE(CLOCK_TICK_RATE)
BUILD_BUG_ON(CALIBRATE_LATCH >> 16);
- outb(0xb0, PIT_MODE); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(PIT_TCW_CH(2) | PIT_RW_LSB_MSB | PIT_MODE_EOC | PIT_BINARY,
+ PIT_MODE);
outb(CALIBRATE_LATCH & 0xff, PIT_CH2); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, PIT_CH2); /* MSB of count */
#undef CALIBRATE_LATCH
@@ -408,7 +410,8 @@ static s64 __init cf_check init_pit(stru
static void cf_check resume_pit(struct platform_timesource *pts)
{
/* Set CTC channel 2 to mode 0 again; initial value does not matter. */
- outb(0xb0, PIT_MODE); /* binary, mode 0, LSB/MSB, Ch 2 */
+ outb(PIT_TCW_CH(2) | PIT_RW_LSB_MSB | PIT_MODE_EOC | PIT_BINARY,
+ PIT_MODE);
outb(0, PIT_CH2); /* LSB of count */
outb(0, PIT_CH2); /* MSB of count */
}
@@ -2456,7 +2459,8 @@ static int _disable_pit_irq(bool init)
}
/* Disable PIT CH0 timer interrupt. */
- outb_p(0x30, PIT_MODE);
+ outb_p(PIT_TCW_CH(0) | PIT_RW_LSB_MSB | PIT_MODE_EOC | PIT_BINARY,
+ PIT_MODE);
outb_p(0, PIT_CH0);
outb_p(0, PIT_CH0);
@@ -2562,17 +2566,18 @@ int hwdom_pit_access(struct ioreq *ioreq
case PIT_MODE:
if ( ioreq->dir == IOREQ_READ )
return 0; /* urk! */
- switch ( ioreq->data & 0xc0 )
+ switch ( ioreq->data & PIT_TCW_CH(3) )
{
- case 0xc0: /* Read Back */
- if ( ioreq->data & 0x08 ) /* Select Channel 2? */
- outb(ioreq->data & 0xf8, PIT_MODE);
- if ( !(ioreq->data & 0x06) ) /* Select Channel 0/1? */
+ case PIT_RDB: /* Read Back */
+ if ( ioreq->data & PIT_RDB_CH2 )
+ outb(ioreq->data & ~(PIT_RDB_CH1 | PIT_RDB_CH0 | PIT_RDB_RSVD),
+ PIT_MODE);
+ if ( !(ioreq->data & (PIT_RDB_CH0 | PIT_RDB_CH1)) )
return 1; /* no - we're done */
/* Filter Channel 2 and reserved bit 0. */
- ioreq->data &= ~0x09;
+ ioreq->data &= ~(PIT_RDB_CH2 | PIT_RDB_RSVD);
return 0; /* emulate ch0/1 readback */
- case 0x80: /* Select Counter 2 */
+ case PIT_TCW_CH(2):
outb(ioreq->data, PIT_MODE);
return 1;
}
On 2024-05-22 08:59, Jan Beulich wrote: > Help reading of code programming the PIT by introducing constants for > control word, read back and latch commands, as well as status. > > Requested-by: Jason Andryuk <jason.andryuk@amd.com> > Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Jason Andryuk <jason.andryuk@amd.com> Thanks for making the switch. Regards, Jason
© 2016 - 2024 Red Hat, Inc.