summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halfire/ppc/fpds1385.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halfire/ppc/fpds1385.c')
-rw-r--r--private/ntos/nthals/halfire/ppc/fpds1385.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/private/ntos/nthals/halfire/ppc/fpds1385.c b/private/ntos/nthals/halfire/ppc/fpds1385.c
new file mode 100644
index 000000000..06cac0749
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpds1385.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpds1385.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/05/20 22:35:57 $
+ * $Locker: $
+ *
+ * fpds1385.c: set of routines to init, and maintain the DS1385
+ *
+ */
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpreg.h"
+#include "fpio.h" // pick up the io space register access macros
+#include "fpds1385.h" // defines specific to the dallas 1385
+
+#define DS1385_BAILOUT_COUNT 10
+
+UCHAR OriginalA; // storage location for rtc data in control reg a
+UCHAR OriginalB; // storage location for rtc data in control reg b
+BOOLEAN RtcBinaryMode = FALSE;
+ // Flag to indicate if RTC is programmed in BINHEX or
+ // BCD format
+
+BOOLEAN RtcFailure = FALSE;
+ // Flag to indicate if the RTC was read correctly
+BOOLEAN NvramFailure = FALSE;
+ // Flag to indicate if the NVRAM was read correctly
+ULONG TotalDs1385Failures = 0;
+ // Keep track of failures to read the DS1385
+/*
+ * HalpInitFireRTC:
+ *
+ * Make sure the dallas 1385 chip is correctly setup. This means that
+ * all the configuration bits are in place. If the chip is not correctly
+ * setup, save the time off, fix the bits, recalculate the time if needed,
+ * and restore the time. Particularly, if the "DataMode" or "24/12 hour"
+ * bits are changed the time will need to be recalculated.
+ */
+BOOLEAN
+HalpInitFirePowerRTC( VOID )
+{
+ TIME_FIELDS TimeFields;
+ UCHAR tval;
+ BOOLEAN Status = FALSE;
+ UCHAR ds1385Data;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitFirePowerRTC: begin \n"););
+ if ( !(HalQueryRealTimeClock( &TimeFields )) ) {
+ HalDisplayString("Not sure RTC is initted \n");
+ }
+
+ //
+ // Make sure the time is valid before worrying about any of the bits.
+ //
+ ds1385Data = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+ if ( ds1385Data & RTC_VRT ) {
+
+ //
+ // Verify that the DataMode is BCD
+ // the time style is 24 hour,
+ // that Daylight Savings is NOT enabled,
+ // that the square wave output is enabled.
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+ OriginalB = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register b is %x \n",
+ OriginalB););
+
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ RTC_24_HR |
+ //
+ // for consistency with firmware, setup the RTC
+ // to maintain the time in BCD format rather
+ // than binary
+ //
+ // RTC_BIN_MODE |
+ RTC_SQWE|
+ RTC_UIE |
+ RTC_PIE);
+
+ RtcBinaryMode = FALSE;
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
+ OriginalA = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register a is %x\n",
+ OriginalA););
+
+ //
+ // Ensure the Oscillator is running and updating, not either
+ // stopped or counting but not updating.
+ //
+ if ((tval & ( RTC_DV1 | RTC_DV2 | RTC_DV0 )) != RTC_DV1 ) {
+ tval = RTC_DV1;
+ }
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERA, (UCHAR)(tval | RTC_4096_HZ));
+
+ //
+ // Clear the interrupt flag bits
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERC);
+
+ //
+ // Finally, restore the time: HalSetRealTimeClock will take
+ // care of any BCD=BIN conversion necessary.
+ //
+ if ( HalSetRealTimeClock ( &TimeFields)) {
+ Status=TRUE;
+ }
+
+ } else {
+
+ HalDisplayString("RTC Time is invalid: battery is dead?\n");
+ }
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: end \n"););
+ return(Status);
+}
+
+
+//
+// write a byte to the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteReg(UCHAR reg, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rIndexRTC = reg;
+ FireSyncRegister();
+ rDataRTC = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read it three times
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+//
+// read a byte from the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadReg(UCHAR reg)
+{
+ KIRQL OldIrql;
+ UCHAR result = 0xff;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+
+//
+// write a byte to the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteNVRAM(USHORT addr, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ rNvramData = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read the register three times
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+
+//
+// read a byte from the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadNVRAM(USHORT addr)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ UCHAR result = 0xff;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+