9
0
Fork 0

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 <antonynpavlov@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Antony Pavlov 2014-07-30 00:10:18 +04:00 committed by Sascha Hauer
parent 6d3fc76b77
commit ed98f1522d
8 changed files with 209 additions and 0 deletions

View File

@ -28,5 +28,6 @@ source "drivers/bus/Kconfig"
source "drivers/regulator/Kconfig"
source "drivers/reset/Kconfig"
source "drivers/pci/Kconfig"
source "drivers/rtc/Kconfig"
endmenu

View File

@ -27,3 +27,4 @@ obj-y += bus/
obj-$(CONFIG_REGULATOR) += regulator/
obj-$(CONFIG_RESET_CONTROLLER) += reset/
obj-$(CONFIG_PCI) += pci/
obj-y += rtc/

15
drivers/rtc/Kconfig Normal file
View File

@ -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.

6
drivers/rtc/Makefile Normal file
View File

@ -0,0 +1,6 @@
#
# Makefile for RTC class/drivers.
#
obj-$(CONFIG_RTC_LIB) += rtc-lib.o
obj-$(CONFIG_RTC_CLASS) += class.o

70
drivers/rtc/class.c Normal file
View File

@ -0,0 +1,70 @@
/*
* RTC barebox subsystem, base class
*
* Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
*
* 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 <linux/err.h>
#include <rtc.h>
#include <linux/rtc.h>
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);

68
drivers/rtc/rtc-lib.c Normal file
View File

@ -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 <a.zummo@towertech.it>
*
* 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 <rtc.h>
#include <linux/rtc.h>
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);

46
include/linux/rtc.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Generic RTC interface.
* This version contains the part of the user interface to the Real Time Clock
* service. It is used with both the legacy mc146818 and also EFI
* Struct rtc_time and first 12 ioctl by Paul Gortmaker, 1996 - separated out
* from <linux/mc146818rtc.h> to this file for 2.4 kernels.
*
* Copyright (C) 1999 Hewlett-Packard Co.
* Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
*/
#ifndef _LINUX_RTC_H_
#define _LINUX_RTC_H_
#include <common.h>
#include <linux/types.h>
extern int rtc_month_days(unsigned int month, unsigned int year);
extern int rtc_valid_tm(struct rtc_time *tm);
extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
struct rtc_class_ops;
struct rtc_device {
struct device_d *dev;
struct device_d class_dev;
struct list_head list;
const struct rtc_class_ops *ops;
};
struct rtc_class_ops {
int (*read_time)(struct rtc_device *, struct rtc_time *);
int (*set_time)(struct rtc_device *, struct rtc_time *);
};
extern int rtc_register(struct rtc_device *rtcdev);
extern int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm);
extern int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm);
static inline bool is_leap_year(unsigned int year)
{
return (!(year % 4) && (year % 100)) || !(year % 400);
}
#endif /* _LINUX_RTC_H_ */

View File

@ -53,4 +53,6 @@ void to_tm (int, struct rtc_time *);
unsigned long mktime (unsigned int, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int);
extern struct rtc_device *rtc_lookup(const char *name);
#endif /* _RTC_H_ */