patch-2.2.8 linux/arch/ppc/kernel/prep_time.c
Next file: linux/arch/ppc/kernel/process.c
Previous file: linux/arch/ppc/kernel/prep_setup.c
Back to the patch index
Back to the overall index
- Lines: 361
- Date:
Thu Apr 29 12:39:01 1999
- Orig file:
v2.2.7/linux/arch/ppc/kernel/prep_time.c
- Orig date:
Tue Mar 23 14:35:46 1999
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
@@ -22,7 +22,9 @@
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/processor.h>
-#include <asm/nvram.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/mk48t59.h>
#include "time.h"
@@ -41,133 +43,44 @@
* is setup at boot time to use the correct addresses.
* -- Cort
*/
-/*
- * translate from mc146818 to m48t18 addresses
- */
-unsigned int clock_transl[] __prepdata = { MOTO_RTC_SECONDS,0 /* alarm */,
- MOTO_RTC_MINUTES,0 /* alarm */,
- MOTO_RTC_HOURS,0 /* alarm */, /* 4,5 */
- MOTO_RTC_DAY_OF_WEEK,
- MOTO_RTC_DAY_OF_MONTH,
- MOTO_RTC_MONTH,
- MOTO_RTC_YEAR, /* 9 */
- MOTO_RTC_CONTROLA, MOTO_RTC_CONTROLB /* 10,11 */
-};
-
-/*
- * The following struture is used to access the MK48T18
- */
-typedef volatile struct _MK48T18 {
- unsigned char ucNvRAM[0x3ff8]; /* NvRAM locations */
- unsigned char ucControl;
- unsigned char ucSecond; /* 0-59 */
- unsigned char ucMinute; /* 0-59 */
- unsigned char ucHour; /* 0-23 */
- unsigned char ucDay; /* 1-7 */
- unsigned char ucDate; /* 1-31 */
- unsigned char ucMonth; /* 1-12 */
- unsigned char ucYear; /* 0-99 */
-} MK48T18, *PMK48T18;
-
-/*
- * The control register contains a 5 bit calibration value plus sign
- * and read/write enable bits
- */
-#define MK48T18_CTRL_CAL_MASK 0x1f
-#define MK48T18_CTRL_CAL_SIGN 0x20
-#define MK48T18_CTRL_READ 0x40
-#define MK48T18_CTRL_WRITE 0x80
-/*
- * The STOP bit is the most significant bit of the seconds location
- */
-#define MK48T18_SEC_MASK 0x7f
-#define MK48T18_SEC_STOP 0x80
-/*
- * The day location also contains the frequency test bit which should
- * be zero for normal operation
- */
-#define MK48T18_DAY_MASK 0x07
-#define MK48T18_DAY_FT 0x40
-
-__prep
-int prep_cmos_clock_read(int addr)
-{
- if ( _prep_type == _PREP_IBM )
- return CMOS_READ(addr);
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- return (inb(NVRAM_DATA));
- }
- else if ( _prep_type == _PREP_Radstone )
- return CMOS_READ(addr);
-
- printk("Unknown machine in prep_cmos_clock_read()!\n");
- return -1;
-}
-
-__prep
-void prep_cmos_clock_write(unsigned long val, int addr)
-{
- if ( _prep_type == _PREP_IBM )
- {
- CMOS_WRITE(val,addr);
- return;
- }
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- outb(val,NVRAM_DATA);
- return;
- }
- else if ( _prep_type == _PREP_Radstone )
- {
- CMOS_WRITE(val,addr);
- return;
- }
-
- printk("Unknown machine in prep_cmos_clock_write()!\n");
-}
/*
* Set the hardware clock. -- Cort
*/
__prep
-int prep_set_rtc_time(unsigned long nowtime)
+int mc146818_set_rtc_time(unsigned long nowtime)
{
unsigned char save_control, save_freq_select;
struct rtc_time tm;
to_tm(nowtime, &tm);
- save_control = prep_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- prep_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = prep_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ /* tell the clock it's being set */
+ save_control = CMOS_READ(RTC_CONTROL);
- prep_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ /* stop and reset prescaler */
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
BIN_TO_BCD(tm.tm_sec);
BIN_TO_BCD(tm.tm_min);
BIN_TO_BCD(tm.tm_hour);
BIN_TO_BCD(tm.tm_mon);
- BIN_TO_BCD(tm.tm_wday);
BIN_TO_BCD(tm.tm_mday);
BIN_TO_BCD(tm.tm_year);
}
- prep_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- prep_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- prep_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- prep_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- prep_cmos_clock_write(tm.tm_wday+1,RTC_DAY_OF_WEEK);
- prep_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- prep_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
+ CMOS_WRITE(tm.tm_sec, RTC_SECONDS);
+ CMOS_WRITE(tm.tm_min, RTC_MINUTES);
+ CMOS_WRITE(tm.tm_hour, RTC_HOURS);
+ CMOS_WRITE(tm.tm_mon, RTC_MONTH);
+ CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
+ CMOS_WRITE(tm.tm_year, RTC_YEAR);
+
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
* battery and quartz) will not reset the oscillator and will not
@@ -175,52 +88,14 @@
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
*/
- prep_cmos_clock_write(save_control, RTC_CONTROL);
- prep_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
- /*
- * Radstone Technology PPC1a boards use an MK48T18 device
- * as the "master" RTC but also have a DS1287 equivalent incorporated
- * into the PCI-ISA bridge device. The DS1287 is initialised by the boot
- * firmware to reflect the value held in the MK48T18 and thus the
- * time may be read from this device both here and in the rtc driver.
- * Whenever we set the time, however, if it is to be preserved across
- * boots we must also update the "master" RTC.
- */
- if((_prep_type==_PREP_Radstone) && (ucSystemType==RS_SYS_TYPE_PPC1a))
- {
- PMK48T18 pMk48t18=(PMK48T18)(_ISA_MEM_BASE+0x00800000);
-
- /*
- * Set the write enable bit
- */
- pMk48t18->ucControl|=MK48T18_CTRL_WRITE;
- eieio();
- /*
- * Update the clock
- */
- pMk48t18->ucSecond=tm.tm_sec;
- pMk48t18->ucMinute=tm.tm_min;
- pMk48t18->ucHour=tm.tm_hour;
- pMk48t18->ucMonth=tm.tm_mon;
- pMk48t18->ucDay=tm.tm_wday+1;
- pMk48t18->ucDate=tm.tm_mday;
- pMk48t18->ucYear=tm.tm_year;
-
- eieio();
- /*
- * Clear the write enable bit
- */
- pMk48t18->ucControl&=~MK48T18_CTRL_WRITE;
- }
-
- if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
- time_state = TIME_OK;
return 0;
}
__prep
-unsigned long prep_get_rtc_time(void)
+unsigned long mc146818_get_rtc_time(void)
{
unsigned int year, mon, day, hour, min, sec;
int i;
@@ -232,29 +107,123 @@
*/
/* read RTC exactly on falling edge of update flag */
for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
break;
for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP))
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
break;
do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = prep_cmos_clock_read(RTC_SECONDS);
- min = prep_cmos_clock_read(RTC_MINUTES);
- hour = prep_cmos_clock_read(RTC_HOURS);
- day = prep_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = prep_cmos_clock_read(RTC_MONTH);
- year = prep_cmos_clock_read(RTC_YEAR);
- } while (sec != prep_cmos_clock_read(RTC_SECONDS));
- if (!(prep_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
if ((year += 1900) < 1970)
year += 100;
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+__prep
+int mk48t59_set_rtc_time(unsigned long nowtime)
+{
+ unsigned char save_control;
+ struct rtc_time tm;
+
+
+ to_tm(nowtime, &tm);
+
+ /* tell the clock it's being written */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_WRITE));
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec);
+ ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min);
+ ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour);
+ ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon);
+ ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
+ ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year);
+
+ /* Turn off the write bit. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ return 0;
+}
+
+__prep
+unsigned long mk48t59_get_rtc_time(void)
+{
+ unsigned char save_control;
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ /* Make sure the time is not stopped. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control & (~MK48T59_RTC_CB_STOP)));
+
+ /* Now make sure the read bit is off so the value will change. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ save_control &= ~MK48T59_RTC_CA_READ;
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ /* Read the seconds value to see when it changes. */
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+
+ /* Wait until the seconds value changes, then read the value. */
+ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+ break;
+ }
+ }
+
+ /* Set the register to read the value. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_READ));
+
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
+ hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
+ day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
+ mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
+ year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
+
+ /* Let the time values change again. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+
+ year = year + 1900;
+ if (year < 1970) {
+ year += 100;
+ }
+
return mktime(year, mon, day, hour, min, sec);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)