171 lines
4.8 KiB
C
171 lines
4.8 KiB
C
#ident "IP12diags/time/rt_clock.c: $Revision: 1.16 $"
|
|
|
|
#include "sys/types.h"
|
|
#include "sys/cpu.h"
|
|
#include "sys/sbd.h"
|
|
#include "sys/i8254clock.h"
|
|
#include "sys/dp8573clk.h"
|
|
#include <libsk.h>
|
|
#include "uif.h"
|
|
|
|
#define CLOCK_COUNTER 10
|
|
#define POWER_FAIL_DELAY_ENABLE (0x02)
|
|
#define POWER_FAIL_INT_ENABLE (0x80)
|
|
#define TIMESAVE_COUNTER 5
|
|
#define COUNTER2_VAL 1000 /* counter2 output = 1 kHz */
|
|
#define COUNTER1_VAL 2000 /* counter1 output = 2 sec */
|
|
#define CAUSE_COUNTER1 CAUSE_IP6
|
|
|
|
/*
|
|
tests the accuracy of the DP8573/DP8572 real time clock by comparing the
|
|
elapsed time generated by the clock with the time generated by the
|
|
i8254 counter/timer on INT2
|
|
*/
|
|
int
|
|
rt_clock ()
|
|
{
|
|
int counter;
|
|
static char *counter_name[CLOCK_COUNTER] = {
|
|
"Ten milliseconds",
|
|
"Second",
|
|
"Minute",
|
|
"Hour",
|
|
"Day of month",
|
|
"Month",
|
|
"Year",
|
|
0, /* don't care */
|
|
0, /* don't care */
|
|
"Day of week"
|
|
};
|
|
unsigned int current_time[CLOCK_COUNTER];
|
|
static unsigned char expected_time[CLOCK_COUNTER] = {
|
|
0x50,
|
|
0x01,
|
|
0x00,
|
|
0x00,
|
|
0x01,
|
|
0x01,
|
|
0x00,
|
|
0x01, /* don't care */
|
|
0x00, /* don't care */
|
|
0x01
|
|
};
|
|
static unsigned char initial_time[CLOCK_COUNTER] = {
|
|
0x50,
|
|
0x59,
|
|
0x59,
|
|
0x23,
|
|
0x31,
|
|
0x12,
|
|
0x99,
|
|
0x66, /* don't care */
|
|
0x03, /* don't care */
|
|
0x07
|
|
};
|
|
int passed = TRUE;
|
|
volatile struct dp8573_clk *rt_clock =
|
|
(struct dp8573_clk *) PHYS_TO_K1(RT_CLOCK_ADDR);
|
|
volatile struct pt_clock *pt = (struct pt_clock *)PT_CLOCK_ADDR;
|
|
|
|
msg_printf (VRB, "Time of day clock test\n");
|
|
|
|
rt_clock->ck_status |= RTC_RS;
|
|
rt_clock->ck_rtime1 = 0x0; /* stop the clock */
|
|
rt_clock->ck_outmode1 = 0x0;
|
|
rt_clock->ck_int0ctl1 = 0x0;
|
|
rt_clock->ck_int1ctl1 = POWER_FAIL_INT_ENABLE;
|
|
|
|
/* save current time
|
|
*/
|
|
for (counter = 0; counter < CLOCK_COUNTER; counter++)
|
|
current_time[counter] = rt_clock->ck_counter[counter];
|
|
|
|
/* enable timesave function
|
|
*/
|
|
rt_clock->ck_status &= ~RTC_RS;
|
|
rt_clock->ck_pflag0 = 0x0;
|
|
rt_clock->ck_tsavctl0 = RTC_TIMSAVON | POWER_FAIL_DELAY_ENABLE;
|
|
|
|
/* set up clock counters and clear timesave ram
|
|
*/
|
|
for (counter = 0; counter < CLOCK_COUNTER; counter++)
|
|
rt_clock->ck_counter[counter] = initial_time[counter];
|
|
|
|
for (counter = 0; counter < TIMESAVE_COUNTER; counter++)
|
|
rt_clock->ck_timsav[counter] = 0x0;
|
|
|
|
/* start counter/timer ticking
|
|
*/
|
|
*(volatile char *)TIMER_ACK_ADDR = ACK_TIMER0 | ACK_TIMER1; wbflush();
|
|
pt->pt_control = PTCW_SC(2)|PTCW_16B|PTCW_MODE(MODE_RG); wbflush();
|
|
pt->pt_counter2 = COUNTER2_VAL & 0xff; wbflush();
|
|
pt->pt_counter2 = (COUNTER2_VAL >> 8) & 0xff; wbflush();
|
|
pt->pt_control = PTCW_SC(1)|PTCW_16B|PTCW_MODE(MODE_RG); wbflush();
|
|
pt->pt_counter1 = COUNTER1_VAL & 0xff; wbflush();
|
|
pt->pt_counter1 = (COUNTER1_VAL >> 8) & 0xff; wbflush();
|
|
|
|
rt_clock->ck_status |= RTC_RS;
|
|
rt_clock->ck_rtime1 |= RTC_RUN; /* start the clock */
|
|
|
|
/* wait for counter/timer to expire
|
|
*/
|
|
*(volatile char *)TIMER_ACK_ADDR = ACK_TIMER0 | ACK_TIMER1; wbflush();
|
|
while (1)
|
|
if (get_cause() & CAUSE_COUNTER1)
|
|
break;
|
|
|
|
rt_clock->ck_status &= ~RTC_RS;
|
|
rt_clock->ck_tsavctl0 &= ~RTC_TIMSAVON; /* latch time in timesave ram */
|
|
|
|
rt_clock->ck_status |= RTC_RS;
|
|
rt_clock->ck_rtime1 &= ~RTC_RUN; /* stop the clock */
|
|
|
|
/* clean up counter/timer regs
|
|
*/
|
|
pt->pt_control = PTCW_SC(0)|PTCW_16B|PTCW_MODE(MODE_STS); wbflush();
|
|
pt->pt_control = PTCW_SC(1)|PTCW_16B|PTCW_MODE(MODE_STS); wbflush();
|
|
*(volatile char *)TIMER_ACK_ADDR = ACK_TIMER0 | ACK_TIMER1;
|
|
|
|
/* verify clock counters, all counters must match exactly
|
|
*/
|
|
for (counter = 0; counter < CLOCK_COUNTER; counter++)
|
|
if (counter_name[counter])
|
|
if ((rt_clock->ck_counter[counter] & 0xff) !=
|
|
expected_time[counter]) {
|
|
passed = FALSE;
|
|
msg_printf (ERR,
|
|
"%s clock counter, Expected: 0x%02x, Actual: 0x%02x\n",
|
|
counter_name[counter], expected_time[counter],
|
|
rt_clock->ck_counter[counter] & 0xff);
|
|
} /* if */
|
|
|
|
/* verify time save counters, all counters must match exactly
|
|
*/
|
|
for (counter = 0; counter < TIMESAVE_COUNTER; counter++)
|
|
if ((rt_clock->ck_timsav[counter] & 0xff) !=
|
|
expected_time[counter + 1]) {
|
|
passed = FALSE;
|
|
msg_printf (ERR,
|
|
"%s time save counter, Expected: 0x%02x, Actual: 0x%02x\n",
|
|
counter_name[counter + 1], expected_time[counter + 1],
|
|
rt_clock->ck_timsav[counter] & 0xff);
|
|
} /* if */
|
|
|
|
/* restart the clock. the time will be ~3 seconds behind
|
|
*/
|
|
for (counter = 0; counter < CLOCK_COUNTER; counter++)
|
|
rt_clock->ck_counter[counter] = current_time[counter];
|
|
|
|
rt_clock->ck_status |= RTC_RS;
|
|
rt_clock->ck_rtime1 |= RTC_RUN; /* start the clock */
|
|
|
|
if (!passed)
|
|
sum_error ("time of day clock");
|
|
else
|
|
okydoky ();
|
|
|
|
return (passed);
|
|
} /* rt_clock */
|
|
|
|
|