Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c86edc0 authored by Alessandro Zummo's avatar Alessandro Zummo Committed by Linus Torvalds
Browse files

[PATCH] RTC subsystem: class



Add the basic RTC subsystem infrastructure to the kernel.

rtc/class.c - registration facilities for RTC drivers
rtc/interface.c - kernel/rtc interface functions
rtc/hctosys.c - snippet of code that copies hw clock to sw clock
		at bootup, if configured to do so.

Signed-off-by: default avatarAlessandro Zummo <a.zummo@towertech.it>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4079c39a
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -3741,10 +3741,11 @@ D: Mylex DAC960 PCI RAID driver
D: Miscellaneous kernel fixes

N: Alessandro Zummo
E: azummo@ita.flashnet.it
W: http://freepage.logicom.it/azummo/
E: a.zummo@towertech.it
D: CMI8330 support is sb_card.c
D: ISAPnP fixes in sb_card.c
D: ZyXEL omni.net lcd plus driver
D: RTC subsystem
S: Italy

N: Marc Zyngier
+6 −0
Original line number Diff line number Diff line
@@ -2233,6 +2233,12 @@ M: p_gortmaker@yahoo.com
L:	linux-kernel@vger.kernel.org
S:	Maintained

REAL TIME CLOCK (RTC) SUBSYSTEM
P:	Alessandro Zummo
M:	a.zummo@towertech.it
L:	linux-kernel@vger.kernel.org
S:	Maintained

REISERFS FILE SYSTEM
P:	Hans Reiser
M:	reiserfs-dev@namesys.com
+42 −2
Original line number Diff line number Diff line
#
\#
# RTC class/drivers configuration
#

menu "Real Time Clock"

config RTC_LIB
	tristate

config RTC_CLASS
	tristate "RTC class"
	depends on EXPERIMENTAL
	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 of more of the interfaces below.

	  This driver can also be built as a module. If so, the module
	  will be called rtc-class.

config RTC_HCTOSYS
	bool "Set system time from RTC on startup"
	depends on RTC_CLASS = y
	default y
	help
	  If you say yes here, the system time will be set using
	  the value read from the specified RTC device. This is useful
	  in order to avoid unnecessary fschk runs.

config RTC_HCTOSYS_DEVICE
	string "The RTC to read the time from"
	depends on RTC_HCTOSYS = y
	default "rtc0"
	help
	  The RTC device that will be used as the source for
	  the system time, usually rtc0.

comment "RTC interfaces"
	depends on RTC_CLASS

comment "RTC drivers"
	depends on RTC_CLASS

endmenu
+4 −1
Original line number Diff line number Diff line
@@ -3,3 +3,6 @@
#

obj-$(CONFIG_RTC_LIB)		+= rtc-lib.o
obj-$(CONFIG_RTC_HCTOSYS)	+= hctosys.o
obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o
rtc-core-y			:= class.o interface.o

drivers/rtc/class.c

0 → 100644
+145 −0
Original line number Diff line number Diff line
/*
 * RTC subsystem, base class
 *
 * Copyright (C) 2005 Tower Technologies
 * Author: Alessandro Zummo <a.zummo@towertech.it>
 *
 * class skeleton from drivers/hwmon/hwmon.c
 *
 * 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 <linux/module.h>
#include <linux/rtc.h>
#include <linux/kdev_t.h>
#include <linux/idr.h>

static DEFINE_IDR(rtc_idr);
static DEFINE_MUTEX(idr_lock);
struct class *rtc_class;

static void rtc_device_release(struct class_device *class_dev)
{
	struct rtc_device *rtc = to_rtc_device(class_dev);
	mutex_lock(&idr_lock);
	idr_remove(&rtc_idr, rtc->id);
	mutex_unlock(&idr_lock);
	kfree(rtc);
}

/**
 * rtc_device_register - register w/ RTC class
 * @dev: the device to register
 *
 * rtc_device_unregister() must be called when the class device is no
 * longer needed.
 *
 * Returns the pointer to the new struct class device.
 */
struct rtc_device *rtc_device_register(const char *name, struct device *dev,
					struct rtc_class_ops *ops,
					struct module *owner)
{
	struct rtc_device *rtc;
	int id, err;

	if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
		err = -ENOMEM;
		goto exit;
	}


	mutex_lock(&idr_lock);
	err = idr_get_new(&rtc_idr, NULL, &id);
	mutex_unlock(&idr_lock);

	if (err < 0)
		goto exit;

	id = id & MAX_ID_MASK;

	rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL);
	if (rtc == NULL) {
		err = -ENOMEM;
		goto exit_idr;
	}

	rtc->id = id;
	rtc->ops = ops;
	rtc->owner = owner;
	rtc->class_dev.dev = dev;
	rtc->class_dev.class = rtc_class;
	rtc->class_dev.release = rtc_device_release;

	mutex_init(&rtc->ops_lock);
	spin_lock_init(&rtc->irq_lock);
	spin_lock_init(&rtc->irq_task_lock);

	strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
	snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id);

	err = class_device_register(&rtc->class_dev);
	if (err)
		goto exit_kfree;

	dev_info(dev, "rtc core: registered %s as %s\n",
			rtc->name, rtc->class_dev.class_id);

	return rtc;

exit_kfree:
	kfree(rtc);

exit_idr:
	idr_remove(&rtc_idr, id);

exit:
	return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(rtc_device_register);


/**
 * rtc_device_unregister - removes the previously registered RTC class device
 *
 * @rtc: the RTC class device to destroy
 */
void rtc_device_unregister(struct rtc_device *rtc)
{
	mutex_lock(&rtc->ops_lock);
	rtc->ops = NULL;
	mutex_unlock(&rtc->ops_lock);
	class_device_unregister(&rtc->class_dev);
}
EXPORT_SYMBOL_GPL(rtc_device_unregister);

int rtc_interface_register(struct class_interface *intf)
{
	intf->class = rtc_class;
	return class_interface_register(intf);
}
EXPORT_SYMBOL_GPL(rtc_interface_register);

static int __init rtc_init(void)
{
	rtc_class = class_create(THIS_MODULE, "rtc");
	if (IS_ERR(rtc_class)) {
		printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
		return PTR_ERR(rtc_class);
	}
	return 0;
}

static void __exit rtc_exit(void)
{
	class_destroy(rtc_class);
}

module_init(rtc_init);
module_exit(rtc_exit);

MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>");
MODULE_DESCRIPTION("RTC class support");
MODULE_LICENSE("GPL");
Loading