diff options
Diffstat (limited to 'c/src/lib/libbsp/m68k/mcf5206elite/tod')
-rw-r--r-- | c/src/lib/libbsp/m68k/mcf5206elite/tod/.cvsignore | 2 | ||||
-rw-r--r-- | c/src/lib/libbsp/m68k/mcf5206elite/tod/ds1307.c | 217 | ||||
-rw-r--r-- | c/src/lib/libbsp/m68k/mcf5206elite/tod/todcfg.c | 84 |
3 files changed, 303 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/mcf5206elite/tod/.cvsignore b/c/src/lib/libbsp/m68k/mcf5206elite/tod/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5206elite/tod/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in 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 +}; diff --git a/c/src/lib/libbsp/m68k/mcf5206elite/tod/todcfg.c b/c/src/lib/libbsp/m68k/mcf5206elite/tod/todcfg.c new file mode 100644 index 0000000000..ec063877f0 --- /dev/null +++ b/c/src/lib/libbsp/m68k/mcf5206elite/tod/todcfg.c @@ -0,0 +1,84 @@ +/* + * This file contains the RTC driver table for Motorola MCF5206eLITE + * ColdFire evaluation board. + * + * 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 <bsp.h> +#include <libchip/rtc.h> +#include <ds1307.h> + +/* Forward function declaration */ +boolean mcf5206elite_ds1307_probe(int minor); + +extern rtc_fns ds1307_fns; + +/* The following table configures the RTC drivers used in this BSP */ +rtc_tbl RTC_Table[] = { + { + "/dev/rtc", /* sDeviceName */ + RTC_CUSTOM, /* deviceType */ + &ds1307_fns, /* pDeviceFns */ + mcf5206elite_ds1307_probe, /* deviceProbe */ + NULL, /* pDeviceParams */ + 0x00, /* ulCtrlPort1, for DS1307-I2C bus number */ + DS1307_I2C_ADDRESS, /* ulDataPort, for DS1307-I2C device addr */ + NULL, /* getRegister - not applicable to DS1307 */ + NULL /* setRegister - not applicable to DS1307 */ + } +}; + +/* Some information used by the RTC driver */ + +#define NUM_RTCS (sizeof(RTC_Table)/sizeof(rtc_tbl)) + +unsigned long RTC_Count = NUM_RTCS; + +rtems_device_minor_number RTC_Minor; + +/* mcf5206elite_ds1307_probe -- + * RTC presence probe function. Return TRUE, if device is present. + * Device presence checked by probe access to RTC device over I2C bus. + * + * PARAMETERS: + * minor - minor RTC device number + * + * RETURNS: + * TRUE, if RTC device is present + */ +boolean +mcf5206elite_ds1307_probe(int minor) +{ + int try = 0; + i2c_message_status status; + rtc_tbl *rtc; + i2c_bus_number bus; + i2c_address addr; + + if (minor >= NUM_RTCS) + return FALSE; + + rtc = RTC_Table + minor; + + bus = rtc->ulCtrlPort1; + addr = rtc->ulDataPort; + do { + status = i2c_wrbyte(bus, addr, 0); + if (status == I2C_NO_DEVICE) + return FALSE; + try++; + } while ((try < 15) && (status != I2C_SUCCESSFUL)); + if (status == I2C_SUCCESSFUL) + return TRUE; + else + return FALSE; +} |