summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c')
-rw-r--r--c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c b/c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c
new file mode 100644
index 0000000000..ae1cdf10d6
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c
@@ -0,0 +1,217 @@
+/*
+ * This file interfaces with the real-time clock found in a
+ * Dallas Semiconductor DS1307/DS1308 serial real-time clock chip.
+ * This RTC have I2C bus interface. BSP have to provide I2C bus primitives
+ * to make this driver working. getRegister and setRegister primitives is
+ * not used here to avoid multiple transactions over I2C bus (each transaction
+ * require significant time and error when date/time information red may
+ * occurs). ulControlPort contains I2C bus number; ulDataPort contains
+ * RTC I2C device address.
+ *
+ * Year 2000 Note:
+ *
+ * This chip only uses a two digit field to store the year. This code
+ * uses the RTEMS Epoch as a pivot year. This lets us map the two digit
+ * year field as follows:
+ *
+ * + two digit years 00-87 are mapped to 2000-2087
+ * + two digit years 88-99 are mapped to 1988-1999
+ *
+ * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ *
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * @(#) $Id$
+ */
+
+#include <rtems.h>
+#include <libchip/rtc.h>
+#include "ds1307.h"
+#include "i2c.h"
+
+/* Convert from/to Binary-Coded Decimal representation */
+#define From_BCD( _x ) ((((_x) >> 4) * 10) + ((_x) & 0x0F))
+#define To_BCD( _x ) ((((_x) / 10) << 4) + ((_x) % 10))
+
+/* ds1307_initialize --
+ * Initialize DS1307 real-time clock chip. If RTC is halted, this
+ * function resume counting.
+ *
+ * PARAMETERS:
+ * minor -- minor RTC device number
+ */
+void
+ds1307_initialize(int minor)
+{
+ i2c_message_status status;
+ int try;
+ rtems_unsigned8 sec;
+ i2c_bus_number bus;
+ i2c_address addr;
+
+ bus = RTC_Table[minor].ulCtrlPort1;
+ addr = RTC_Table[minor].ulDataPort;
+
+ /* Read SECONDS register */
+ try = 0;
+ do {
+ status = i2c_wbrd(bus, addr, 0, &sec, sizeof(sec));
+ try++;
+ } while ((status != I2C_SUCCESSFUL) && (try < 15));
+
+ /* If clock is halted, reset and start the clock */
+ if ((sec & DS1307_SECOND_HALT) != 0)
+ {
+ rtems_unsigned8 start[8];
+ memset(start, 0, sizeof(start));
+ start[0] = DS1307_SECOND;
+ try = 0;
+ do {
+ status = i2c_write(bus, addr, start, 2);
+ } while ((status != I2C_SUCCESSFUL) && (try < 15));
+ }
+}
+
+/* ds1307_get_time --
+ * read current time from DS1307 real-time clock chip and convert it
+ * to the rtems_time_of_day structure.
+ *
+ * PARAMETERS:
+ * minor -- minor RTC device number
+ * time -- place to put return value (date and time)
+ *
+ * RETURNS:
+ * 0, if time obtained successfully
+ * -1, if error occured
+ */
+int
+ds1307_get_time(int minor, rtems_time_of_day *time)
+{
+ i2c_bus_number bus;
+ i2c_address addr;
+ rtems_unsigned8 info[8];
+ rtems_unsigned32 v1, v2;
+ i2c_message_status status;
+ int try;
+
+ if (time == NULL)
+ return -1;
+
+ bus = RTC_Table[minor].ulCtrlPort1;
+ addr = RTC_Table[minor].ulDataPort;
+
+ memset(time, 0, sizeof(rtems_time_of_day));
+ try = 0;
+ do {
+ status = i2c_wbrd(bus, addr, 0, info, sizeof(info));
+ try++;
+ } while ((status != I2C_SUCCESSFUL) && (try < 10));
+
+ if (status != I2C_SUCCESSFUL)
+ {
+ return -1;
+ }
+
+ v1 = info[DS1307_YEAR];
+ v2 = From_BCD(v1);
+ if (v2 < 88)
+ time->year = 2000 + v2;
+ else
+ time->year = 1900 + v2;
+
+ v1 = info[DS1307_MONTH] & ~0xE0;
+ time->month = From_BCD(v1);
+
+ v1 = info[DS1307_DAY] & ~0xC0;
+ time->day = From_BCD(v1);
+
+ v1 = info[DS1307_HOUR];
+ if (v1 & DS1307_HOUR_12)
+ {
+ v2 = v1 & ~0xE0;
+ if (v1 & DS1307_HOUR_PM)
+ {
+ time->hour = From_BCD(v2) + 12;
+ }
+ else
+ {
+ time->hour = From_BCD(v2);
+ }
+ }
+ else
+ {
+ v2 = v1 & ~0xC0;
+ time->hour = From_BCD(v2);
+ }
+
+ v1 = info[DS1307_MINUTE] & ~0x80;
+ time->minute = From_BCD(v1);
+
+ v1 = info[DS1307_SECOND];
+ v2 = v1 & ~0x80;
+ time->second = From_BCD(v2);
+
+ return 0;
+}
+
+/* ds1307_set_time --
+ * set time to the DS1307 real-time clock chip
+ *
+ * PARAMETERS:
+ * minor -- minor RTC device number
+ * time -- new date and time to be written to DS1307
+ *
+ * RETURNS:
+ * 0, if time obtained successfully
+ * -1, if error occured
+ */
+int
+ds1307_set_time(int minor, rtems_time_of_day *time)
+{
+ i2c_bus_number bus;
+ i2c_address addr;
+ rtems_unsigned8 info[8];
+ i2c_message_status status;
+ int try;
+
+ if (time == NULL)
+ return -1;
+
+ bus = RTC_Table[minor].ulCtrlPort1;
+ addr = RTC_Table[minor].ulDataPort;
+
+ if (time->year >= 2088)
+ rtems_fatal_error_occurred(RTEMS_INVALID_NUMBER);
+
+ info[0] = DS1307_SECOND;
+ info[1 + DS1307_YEAR] = To_BCD(time->year % 100);
+ info[1 + DS1307_MONTH] = To_BCD(time->month);
+ info[1 + DS1307_DAY] = To_BCD(time->day);
+ info[1 + DS1307_HOUR] = To_BCD(time->hour);
+ info[1 + DS1307_MINUTE] = To_BCD(time->minute);
+ info[1 + DS1307_SECOND] = To_BCD(time->second);
+ info[1 + DS1307_DAY_OF_WEEK] = 1; /* Do not set day of week */
+
+ try = 0;
+ do {
+ status = i2c_write(bus, addr, info, 8);
+ try++;
+ } while ((status != I2C_SUCCESSFUL) && (try < 10));
+
+ if (status != I2C_SUCCESSFUL)
+ return -1;
+ else
+ return 0;
+}
+
+/* Driver function table */
+
+rtc_fns ds1307_fns = {
+ ds1307_initialize,
+ ds1307_get_time,
+ ds1307_set_time
+};