From ed98f1522d2157a0266095b00ab1481da6085337 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Wed, 30 Jul 2014 00:10:18 +0400 Subject: Add a simple rtc framework This patch adds a simple rtc framework for reading and setting board's RTC time. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- drivers/rtc/Kconfig | 15 +++++++++++ drivers/rtc/Makefile | 6 +++++ drivers/rtc/class.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/rtc/rtc-lib.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 drivers/rtc/Kconfig create mode 100644 drivers/rtc/Makefile create mode 100644 drivers/rtc/class.c create mode 100644 drivers/rtc/rtc-lib.c (limited to 'drivers/rtc') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig new file mode 100644 index 0000000000..540150373d --- /dev/null +++ b/drivers/rtc/Kconfig @@ -0,0 +1,15 @@ +# +# RTC class/drivers configuration +# + +config RTC_LIB + bool + +menuconfig RTC_CLASS + bool "Real Time Clock" + default n + select RTC_LIB + help + Generic RTC class support. If you say yes here, you will + be allowed to plug one or more RTCs to your system. You will + probably want to enable one or more of the interfaces below. diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile new file mode 100644 index 0000000000..7d1b5bc8c8 --- /dev/null +++ b/drivers/rtc/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for RTC class/drivers. +# + +obj-$(CONFIG_RTC_LIB) += rtc-lib.o +obj-$(CONFIG_RTC_CLASS) += class.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c new file mode 100644 index 0000000000..356707be2f --- /dev/null +++ b/drivers/rtc/class.c @@ -0,0 +1,70 @@ +/* + * RTC barebox subsystem, base class + * + * Copyright (C) 2014 Antony Pavlov + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +LIST_HEAD(rtc_list); +EXPORT_SYMBOL(rtc_list); + +struct rtc_device *rtc_lookup(const char *name) +{ + struct rtc_device *r; + + if (!name) + return ERR_PTR(-ENODEV); + + list_for_each_entry(r, &rtc_list, list) { + if (!strcmp(dev_name(&r->class_dev), name)) + return r; + } + + return ERR_PTR(-ENODEV); +} +EXPORT_SYMBOL(rtc_lookup); + +int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) +{ + return rtc->ops->read_time(rtc, tm); +} +EXPORT_SYMBOL(rtc_read_time); + +int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) +{ + return rtc->ops->set_time(rtc, tm); +} +EXPORT_SYMBOL(rtc_set_time); + +int rtc_register(struct rtc_device *rtcdev) +{ + struct device_d *dev = &rtcdev->class_dev; + + if (!rtcdev->ops) + return -EINVAL; + + dev->id = DEVICE_ID_DYNAMIC; + strcpy(dev->name, "rtc"); + if (rtcdev->dev) + dev->parent = rtcdev->dev; + platform_device_register(dev); + + list_add_tail(&rtcdev->list, &rtc_list); + + return 0; +} +EXPORT_SYMBOL(rtc_register); diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c new file mode 100644 index 0000000000..0d6acde3e0 --- /dev/null +++ b/drivers/rtc/rtc-lib.c @@ -0,0 +1,68 @@ +/* + * rtc and date/time utility functions + * + * This code was ported from linux-3.15 kernel by Antony Pavlov. + * + * Copyright (C) 2005-06 Tower Technologies + * Author: Alessandro Zummo + * + * based on arch/arm/common/rtctime.c and other bits + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +static const unsigned char rtc_days_in_month[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +static const unsigned short rtc_ydays[2][13] = { + /* Normal years */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } +}; + +#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) + +/* + * The number of days in the month. + */ +int rtc_month_days(unsigned int month, unsigned int year) +{ + return rtc_days_in_month[month] + (is_leap_year(year) && month == 1); +} +EXPORT_SYMBOL(rtc_month_days); + +/* + * Does the rtc_time represent a valid date/time? + */ +int rtc_valid_tm(struct rtc_time *tm) +{ + if (tm->tm_year < 70 + || ((unsigned)tm->tm_mon) >= 12 + || tm->tm_mday < 1 + || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) + || ((unsigned)tm->tm_hour) >= 24 + || ((unsigned)tm->tm_min) >= 60 + || ((unsigned)tm->tm_sec) >= 60) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(rtc_valid_tm); + +/* + * Convert Gregorian date to seconds since 01-01-1970 00:00:00. + */ +int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) +{ + *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + return 0; +} +EXPORT_SYMBOL(rtc_tm_to_time); -- cgit v1.2.3