Provide timecounter based on XLR PIC timer.
- Use timer 7 in XLR PIC as a 32 counter - provide pic_init_timer(), pic_set_timer(), pic_timer_count32() and pic_timer_count() PIC timer operations. - register this timer as platform_timecounter on rmi platform.
This commit is contained in:
parent
c2f84fc39a
commit
867a12afe1
sys/mips/rmi
@ -100,6 +100,8 @@
|
||||
#define PIC_TIMER_MAXVAL_1(i) (PIC_TIMER_MAXVAL_1_BASE + (i))
|
||||
#define PIC_TIMER_COUNT_0(i) (PIC_TIMER_COUNT_0_BASE + (i))
|
||||
#define PIC_TIMER_COUNT_1(i) (PIC_TIMER_COUNT_0_BASE + (i))
|
||||
#define PIC_TIMER_HZ 66000000U
|
||||
|
||||
|
||||
/*
|
||||
* We use a simple mapping form PIC interrupts to CPU IRQs.
|
||||
@ -241,4 +243,54 @@ void pic_setup_intr(int picintr, int irq, uint32_t cpumask)
|
||||
mtx_unlock_spin(&xlr_pic_lock);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
pic_init_timer(int timer)
|
||||
{
|
||||
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
|
||||
uint32_t val;
|
||||
|
||||
mtx_lock_spin(&xlr_pic_lock);
|
||||
val = xlr_read_reg(mmio, PIC_CTRL);
|
||||
val |= (1 << (8 + timer));
|
||||
xlr_write_reg(mmio, PIC_CTRL, val);
|
||||
mtx_unlock_spin(&xlr_pic_lock);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
pic_set_timer(int timer, uint64_t maxval)
|
||||
{
|
||||
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
|
||||
|
||||
xlr_write_reg(mmio, PIC_TIMER_MAXVAL_0(timer),
|
||||
(maxval & 0xffffffff));
|
||||
xlr_write_reg(mmio, PIC_TIMER_MAXVAL_1(timer),
|
||||
(maxval >> 32) & 0xffffffff);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
pic_timer_count32(int timer)
|
||||
{
|
||||
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
|
||||
|
||||
return (xlr_read_reg(mmio, PIC_TIMER_COUNT_0(timer)));
|
||||
}
|
||||
|
||||
/*
|
||||
* The timer can wrap 32 bits between the two reads, so we
|
||||
* need additional logic to detect that.
|
||||
*/
|
||||
static __inline uint64_t
|
||||
pic_timer_count(int timer)
|
||||
{
|
||||
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
|
||||
uint32_t tu1, tu2, tl;
|
||||
|
||||
tu1 = xlr_read_reg(mmio, PIC_TIMER_COUNT_1(timer));
|
||||
tl = xlr_read_reg(mmio, PIC_TIMER_COUNT_0(timer));
|
||||
tu2 = xlr_read_reg(mmio, PIC_TIMER_COUNT_1(timer));
|
||||
if (tu2 != tu1)
|
||||
tl = xlr_read_reg(mmio, PIC_TIMER_COUNT_0(timer));
|
||||
return (((uint64_t)tu2 << 32) | tl);
|
||||
}
|
||||
|
||||
#endif /* _RMI_PIC_H_ */
|
||||
|
@ -278,14 +278,31 @@ mips_init(void)
|
||||
mutex_init();
|
||||
}
|
||||
|
||||
u_int
|
||||
platform_get_timecount(struct timecounter *tc __unused)
|
||||
{
|
||||
|
||||
return (0xffffffffU - pic_timer_count32(PIC_CLOCK_TIMER));
|
||||
}
|
||||
|
||||
static void
|
||||
xlr_pic_init(void)
|
||||
{
|
||||
struct timecounter pic_timecounter = {
|
||||
platform_get_timecount, /* get_timecount */
|
||||
0, /* no poll_pps */
|
||||
~0U, /* counter_mask */
|
||||
PIC_TIMER_HZ, /* frequency */
|
||||
"XLRPIC", /* name */
|
||||
2000, /* quality (adjusted in code) */
|
||||
};
|
||||
xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
|
||||
int i, level, irq;
|
||||
|
||||
mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
|
||||
xlr_write_reg(mmio, PIC_CTRL, 0);
|
||||
|
||||
/* Initialize all IRT entries */
|
||||
for (i = 0; i < PIC_NUM_IRTS; i++) {
|
||||
irq = PIC_INTR_TO_IRQ(i);
|
||||
level = PIC_IRQ_IS_EDGE_TRIGGERED(irq);
|
||||
@ -300,6 +317,11 @@ xlr_pic_init(void)
|
||||
xlr_write_reg(mmio, PIC_IRT_1(i), (level << 30) | (1 << 6) |
|
||||
irq);
|
||||
}
|
||||
|
||||
/* Setup timer 7 of PIC as a timestamp, no interrupts */
|
||||
pic_init_timer(PIC_CLOCK_TIMER);
|
||||
pic_set_timer(PIC_CLOCK_TIMER, ~UINT64_C(0));
|
||||
platform_timecounter = &pic_timecounter;
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user