diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:55:15 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:44 +0200 |
commit | 4fb1b79a804ca8de866be0ef718e54e1f62fa3ec (patch) | |
tree | 11b85c98244db22c927e7f1323ed222c43a589b0 /bsps/m68k/mcf5206elite | |
parent | bsps: Move legacy network drivers to bsps (diff) | |
download | rtems-4fb1b79a804ca8de866be0ef718e54e1f62fa3ec.tar.bz2 |
bsps: Move RTC drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/m68k/mcf5206elite')
-rw-r--r-- | bsps/m68k/mcf5206elite/rtc/ds1307.c | 206 | ||||
-rw-r--r-- | bsps/m68k/mcf5206elite/rtc/todcfg.c | 80 |
2 files changed, 286 insertions, 0 deletions
diff --git a/bsps/m68k/mcf5206elite/rtc/ds1307.c b/bsps/m68k/mcf5206elite/rtc/ds1307.c new file mode 100644 index 0000000000..ab7fc7daac --- /dev/null +++ b/bsps/m68k/mcf5206elite/rtc/ds1307.c @@ -0,0 +1,206 @@ +/* + * 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.rtems.org/license/LICENSE. + */ + +#include <rtems.h> +#include <libchip/rtc.h> +#include <string.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 + */ +static void ds1307_initialize(int minor) +{ + i2c_message_status status; + int try; + uint8_t 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) { + uint8_t 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 + */ +static int ds1307_get_time(int minor, rtems_time_of_day *time) +{ + i2c_bus_number bus; + i2c_address addr; + uint8_t info[8]; + uint32_t 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 + */ +static int ds1307_set_time(int minor, const rtems_time_of_day *time) +{ + i2c_bus_number bus; + i2c_address addr; + uint8_t 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/bsps/m68k/mcf5206elite/rtc/todcfg.c b/bsps/m68k/mcf5206elite/rtc/todcfg.c new file mode 100644 index 0000000000..aacb8575bd --- /dev/null +++ b/bsps/m68k/mcf5206elite/rtc/todcfg.c @@ -0,0 +1,80 @@ +/* + * 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.rtems.org/license/LICENSE. + */ + +#include <i2c.h> +#include <libchip/rtc.h> +#include <ds1307.h> + +/* Forward function declaration */ +bool 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)) + +size_t RTC_Count = NUM_RTCS; + +/* 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 + */ +bool +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; +} |