Author: jchandra
Date: Wed Aug 25 13:37:55 2010
New Revision: 211814
URL: http://svn.freebsd.org/changeset/base/211814

Log:
  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.

Modified:
  head/sys/mips/rmi/pic.h
  head/sys/mips/rmi/xlr_machdep.c

Modified: head/sys/mips/rmi/pic.h
==============================================================================
--- head/sys/mips/rmi/pic.h     Wed Aug 25 12:35:36 2010        (r211813)
+++ head/sys/mips/rmi/pic.h     Wed Aug 25 13:37:55 2010        (r211814)
@@ -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
        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_ */

Modified: head/sys/mips/rmi/xlr_machdep.c
==============================================================================
--- head/sys/mips/rmi/xlr_machdep.c     Wed Aug 25 12:35:36 2010        
(r211813)
+++ head/sys/mips/rmi/xlr_machdep.c     Wed Aug 25 13:37:55 2010        
(r211814)
@@ -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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to