summaryrefslogtreecommitdiff
path: root/cvmx-tim.c
diff options
context:
space:
mode:
Diffstat (limited to 'cvmx-tim.c')
-rw-r--r--cvmx-tim.c116
1 files changed, 81 insertions, 35 deletions
diff --git a/cvmx-tim.c b/cvmx-tim.c
index 1c88b64a0b9d3..5d2d3e1ad2cdb 100644
--- a/cvmx-tim.c
+++ b/cvmx-tim.c
@@ -1,5 +1,5 @@
/***********************license start***************
- * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
+ * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
@@ -15,7 +15,7 @@
* disclaimer in the documentation and/or other materials provided
* with the distribution.
- * * Neither the name of Cavium Networks nor the names of
+ * * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
@@ -26,7 +26,7 @@
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
- * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
+ * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
@@ -48,7 +48,7 @@
*
* Support library for the hardware work queue timers.
*
- * <hr>$Revision: 49448 $<hr>
+ * <hr>$Revision: 70030 $<hr>
*/
#include "executive-config.h"
#include "cvmx-config.h"
@@ -82,8 +82,6 @@ CVMX_SHARED cvmx_tim_t cvmx_tim;
*/
int cvmx_tim_setup(uint64_t tick, uint64_t max_ticks)
{
- cvmx_tim_mem_ring0_t config_ring0;
- cvmx_tim_mem_ring1_t config_ring1;
uint64_t timer_id;
int error = -1;
uint64_t tim_clock_hz = cvmx_clock_get_rate(CVMX_CLOCK_TIM);
@@ -92,12 +90,20 @@ int cvmx_tim_setup(uint64_t tick, uint64_t max_ticks)
uint64_t tick_ns = 1000 * tick;
int i;
uint32_t temp;
+ int timer_thr = 1024;
/* for the simulator */
if (tim_clock_hz == 0)
- tim_clock_hz = 333000000;
+ tim_clock_hz = 800000000;
- hw_tick_ns = 1024 * 1000000000ull / tim_clock_hz;
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ {
+ cvmx_tim_fr_rn_tt_t fr_tt;
+ fr_tt.u64 = cvmx_read_csr(CVMX_TIM_FR_RN_TT);
+ timer_thr = fr_tt.s.fr_rn_tt;
+ }
+
+ hw_tick_ns = timer_thr * 1000000000ull / tim_clock_hz;
/*
* Double the minimal allowed tick to 2 * HW tick. tick between
* (hw_tick_ns, 2*hw_tick_ns) will set config_ring1.s.interval
@@ -113,19 +119,24 @@ int cvmx_tim_setup(uint64_t tick, uint64_t max_ticks)
/* Reinitialize out timer state */
memset(&cvmx_tim, 0, sizeof(cvmx_tim));
-
- if ((tick_ns < (hw_tick_ns_allowed)) || (tick_ns > 4194304 * hw_tick_ns))
- {
- cvmx_dprintf("ERROR: cvmx_tim_setup: Requested tick %lu(ns) is smaller than"
- " the minimal ticks allowed by hardware %lu(ns)\n",
- tick_ns, hw_tick_ns_allowed);
- return error;
- }
+ if (tick_ns < hw_tick_ns_allowed)
+ {
+ cvmx_dprintf("ERROR: cvmx_tim_setup: Requested tick %lu(ns) is smaller than"
+ " the minimal ticks allowed by hardware %lu(ns)\n",
+ tick_ns, hw_tick_ns_allowed);
+ return error;
+ }
+ else if (tick_ns > 4194304 * hw_tick_ns)
+ {
+ cvmx_dprintf("ERROR: cvmx_tim_setup: Requested tick %lu(ns) is greater than"
+ " the max ticks %lu(ns)\n", tick_ns, hw_tick_ns);
+ return error;
+ }
for (i=2; i<20; i++)
{
- if (tick_ns < (hw_tick_ns << i))
- break;
+ if (tick_ns < (hw_tick_ns << i))
+ break;
}
cvmx_tim.max_ticks = (uint32_t)max_ticks;
@@ -165,22 +176,57 @@ int cvmx_tim_setup(uint64_t tick, uint64_t max_ticks)
/* Loop through all timers */
for (timer_id = 0; timer_id<CVMX_TIM_NUM_TIMERS; timer_id++)
{
+ int interval = ((1 << (cvmx_tim.bucket_shift - 10)) - 1);
cvmx_tim_bucket_entry_t *bucket = cvmx_tim.bucket + timer_id * cvmx_tim.num_buckets;
- /* Tell the hardware where about the bucket array */
- config_ring0.u64 = 0;
- config_ring0.s.first_bucket = cvmx_ptr_to_phys(bucket) >> 5;
- config_ring0.s.num_buckets = cvmx_tim.num_buckets - 1;
- config_ring0.s.ring = timer_id;
- cvmx_write_csr(CVMX_TIM_MEM_RING0, config_ring0.u64);
-
- /* Tell the hardware the size of each chunk block in pointers */
- config_ring1.u64 = 0;
- config_ring1.s.enable = 1;
- config_ring1.s.pool = CVMX_FPA_TIMER_POOL;
- config_ring1.s.words_per_chunk = CVMX_FPA_TIMER_POOL_SIZE / 8;
- config_ring1.s.interval = (1 << (cvmx_tim.bucket_shift - 10)) - 1;
- config_ring1.s.ring = timer_id;
- cvmx_write_csr(CVMX_TIM_MEM_RING1, config_ring1.u64);
+ if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+ {
+ cvmx_tim_ringx_ctl0_t ring_ctl0;
+ cvmx_tim_ringx_ctl1_t ring_ctl1;
+ cvmx_tim_ringx_ctl2_t ring_ctl2;
+ cvmx_tim_reg_flags_t reg_flags;
+
+ /* Tell the hardware where about the bucket array */
+ ring_ctl2.u64 = 0;
+ ring_ctl2.s.csize = CVMX_FPA_TIMER_POOL_SIZE / 8;
+ ring_ctl2.s.base = cvmx_ptr_to_phys(bucket) >> 5;
+ cvmx_write_csr(CVMX_TIM_RINGX_CTL2(timer_id), ring_ctl2.u64);
+
+ reg_flags.u64 = cvmx_read_csr(CVMX_TIM_REG_FLAGS);
+ ring_ctl1.u64 = 0;
+ ring_ctl1.s.cpool = ((reg_flags.s.ena_dfb == 0) ? CVMX_FPA_TIMER_POOL : 0);
+ ring_ctl1.s.bsize = cvmx_tim.num_buckets - 1;
+ cvmx_write_csr(CVMX_TIM_RINGX_CTL1(timer_id), ring_ctl1.u64);
+
+ ring_ctl0.u64 = 0;
+ ring_ctl0.s.timercount = interval + timer_id * interval / CVMX_TIM_NUM_TIMERS;
+ cvmx_write_csr(CVMX_TIM_RINGX_CTL0(timer_id), ring_ctl0.u64);
+
+ ring_ctl0.u64 = cvmx_read_csr(CVMX_TIM_RINGX_CTL0(timer_id));
+ ring_ctl0.s.ena = 1;
+ ring_ctl0.s.interval = interval;
+ cvmx_write_csr(CVMX_TIM_RINGX_CTL0(timer_id), ring_ctl0.u64);
+ ring_ctl0.u64 = cvmx_read_csr(CVMX_TIM_RINGX_CTL0(timer_id));
+ }
+ else
+ {
+ cvmx_tim_mem_ring0_t config_ring0;
+ cvmx_tim_mem_ring1_t config_ring1;
+ /* Tell the hardware where about the bucket array */
+ config_ring0.u64 = 0;
+ config_ring0.s.first_bucket = cvmx_ptr_to_phys(bucket) >> 5;
+ config_ring0.s.num_buckets = cvmx_tim.num_buckets - 1;
+ config_ring0.s.ring = timer_id;
+ cvmx_write_csr(CVMX_TIM_MEM_RING0, config_ring0.u64);
+
+ /* Tell the hardware the size of each chunk block in pointers */
+ config_ring1.u64 = 0;
+ config_ring1.s.enable = 1;
+ config_ring1.s.pool = CVMX_FPA_TIMER_POOL;
+ config_ring1.s.words_per_chunk = CVMX_FPA_TIMER_POOL_SIZE / 8;
+ config_ring1.s.interval = interval;
+ config_ring1.s.ring = timer_id;
+ cvmx_write_csr(CVMX_TIM_MEM_RING1, config_ring1.u64);
+ }
}
return 0;
@@ -194,7 +240,7 @@ void cvmx_tim_start(void)
{
cvmx_tim_control_t control;
- control.u64 = 0;
+ control.u64 = cvmx_read_csr(CVMX_TIM_REG_FLAGS);
control.s.enable_dwb = 1;
control.s.enable_timers = 1;
@@ -210,7 +256,7 @@ void cvmx_tim_start(void)
void cvmx_tim_stop(void)
{
cvmx_tim_control_t control;
- control.u64 = 0;
+ control.u64 = cvmx_read_csr(CVMX_TIM_REG_FLAGS);
control.s.enable_dwb = 0;
control.s.enable_timers = 0;
cvmx_write_csr(CVMX_TIM_REG_FLAGS, control.u64);