1a95579cdSAlessandro Zummo /* 2a95579cdSAlessandro Zummo * An RTC test device/driver 3a95579cdSAlessandro Zummo * Copyright (C) 2005 Tower Technologies 4a95579cdSAlessandro Zummo * Author: Alessandro Zummo <a.zummo@towertech.it> 5a95579cdSAlessandro Zummo * 6a95579cdSAlessandro Zummo * This program is free software; you can redistribute it and/or modify 7a95579cdSAlessandro Zummo * it under the terms of the GNU General Public License version 2 as 8a95579cdSAlessandro Zummo * published by the Free Software Foundation. 9a95579cdSAlessandro Zummo */ 10a95579cdSAlessandro Zummo 11a95579cdSAlessandro Zummo #include <linux/module.h> 12a95579cdSAlessandro Zummo #include <linux/err.h> 13a95579cdSAlessandro Zummo #include <linux/rtc.h> 14a95579cdSAlessandro Zummo #include <linux/platform_device.h> 15a95579cdSAlessandro Zummo 16a95579cdSAlessandro Zummo static struct platform_device *test0 = NULL, *test1 = NULL; 17a95579cdSAlessandro Zummo 18a95579cdSAlessandro Zummo static int test_rtc_read_alarm(struct device *dev, 19a95579cdSAlessandro Zummo struct rtc_wkalrm *alrm) 20a95579cdSAlessandro Zummo { 21a95579cdSAlessandro Zummo return 0; 22a95579cdSAlessandro Zummo } 23a95579cdSAlessandro Zummo 24a95579cdSAlessandro Zummo static int test_rtc_set_alarm(struct device *dev, 25a95579cdSAlessandro Zummo struct rtc_wkalrm *alrm) 26a95579cdSAlessandro Zummo { 27a95579cdSAlessandro Zummo return 0; 28a95579cdSAlessandro Zummo } 29a95579cdSAlessandro Zummo 30a95579cdSAlessandro Zummo static int test_rtc_read_time(struct device *dev, 31a95579cdSAlessandro Zummo struct rtc_time *tm) 32a95579cdSAlessandro Zummo { 33a95579cdSAlessandro Zummo rtc_time_to_tm(get_seconds(), tm); 34a95579cdSAlessandro Zummo return 0; 35a95579cdSAlessandro Zummo } 36a95579cdSAlessandro Zummo 37a95579cdSAlessandro Zummo static int test_rtc_set_time(struct device *dev, 38a95579cdSAlessandro Zummo struct rtc_time *tm) 39a95579cdSAlessandro Zummo { 40a95579cdSAlessandro Zummo return 0; 41a95579cdSAlessandro Zummo } 42a95579cdSAlessandro Zummo 43a95579cdSAlessandro Zummo static int test_rtc_set_mmss(struct device *dev, unsigned long secs) 44a95579cdSAlessandro Zummo { 45a95579cdSAlessandro Zummo return 0; 46a95579cdSAlessandro Zummo } 47a95579cdSAlessandro Zummo 48a95579cdSAlessandro Zummo static int test_rtc_proc(struct device *dev, struct seq_file *seq) 49a95579cdSAlessandro Zummo { 50a95579cdSAlessandro Zummo struct platform_device *plat_dev = to_platform_device(dev); 51a95579cdSAlessandro Zummo 52a95579cdSAlessandro Zummo seq_printf(seq, "24hr\t\t: yes\n"); 53a95579cdSAlessandro Zummo seq_printf(seq, "test\t\t: yes\n"); 54a95579cdSAlessandro Zummo seq_printf(seq, "id\t\t: %d\n", plat_dev->id); 55a95579cdSAlessandro Zummo 56a95579cdSAlessandro Zummo return 0; 57a95579cdSAlessandro Zummo } 58a95579cdSAlessandro Zummo 59a95579cdSAlessandro Zummo static int test_rtc_ioctl(struct device *dev, unsigned int cmd, 60a95579cdSAlessandro Zummo unsigned long arg) 61a95579cdSAlessandro Zummo { 62a95579cdSAlessandro Zummo /* We do support interrupts, they're generated 63a95579cdSAlessandro Zummo * using the sysfs interface. 64a95579cdSAlessandro Zummo */ 65a95579cdSAlessandro Zummo switch (cmd) { 66a95579cdSAlessandro Zummo case RTC_PIE_ON: 67a95579cdSAlessandro Zummo case RTC_PIE_OFF: 68a95579cdSAlessandro Zummo case RTC_UIE_ON: 69a95579cdSAlessandro Zummo case RTC_UIE_OFF: 70a95579cdSAlessandro Zummo case RTC_AIE_ON: 71a95579cdSAlessandro Zummo case RTC_AIE_OFF: 72a95579cdSAlessandro Zummo return 0; 73a95579cdSAlessandro Zummo 74a95579cdSAlessandro Zummo default: 75a95579cdSAlessandro Zummo return -EINVAL; 76a95579cdSAlessandro Zummo } 77a95579cdSAlessandro Zummo } 78a95579cdSAlessandro Zummo 79a95579cdSAlessandro Zummo static struct rtc_class_ops test_rtc_ops = { 80a95579cdSAlessandro Zummo .proc = test_rtc_proc, 81a95579cdSAlessandro Zummo .read_time = test_rtc_read_time, 82a95579cdSAlessandro Zummo .set_time = test_rtc_set_time, 83a95579cdSAlessandro Zummo .read_alarm = test_rtc_read_alarm, 84a95579cdSAlessandro Zummo .set_alarm = test_rtc_set_alarm, 85a95579cdSAlessandro Zummo .set_mmss = test_rtc_set_mmss, 86a95579cdSAlessandro Zummo .ioctl = test_rtc_ioctl, 87a95579cdSAlessandro Zummo }; 88a95579cdSAlessandro Zummo 89a95579cdSAlessandro Zummo static ssize_t test_irq_show(struct device *dev, 90a95579cdSAlessandro Zummo struct device_attribute *attr, char *buf) 91a95579cdSAlessandro Zummo { 92a95579cdSAlessandro Zummo return sprintf(buf, "%d\n", 42); 93a95579cdSAlessandro Zummo } 94a95579cdSAlessandro Zummo static ssize_t test_irq_store(struct device *dev, 95a95579cdSAlessandro Zummo struct device_attribute *attr, 96a95579cdSAlessandro Zummo const char *buf, size_t count) 97a95579cdSAlessandro Zummo { 98a95579cdSAlessandro Zummo int retval; 99a95579cdSAlessandro Zummo struct platform_device *plat_dev = to_platform_device(dev); 100a95579cdSAlessandro Zummo struct rtc_device *rtc = platform_get_drvdata(plat_dev); 101a95579cdSAlessandro Zummo 102a95579cdSAlessandro Zummo retval = count; 103a95579cdSAlessandro Zummo if (strncmp(buf, "tick", 4) == 0) 104a95579cdSAlessandro Zummo rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); 105a95579cdSAlessandro Zummo else if (strncmp(buf, "alarm", 5) == 0) 106a95579cdSAlessandro Zummo rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); 107a95579cdSAlessandro Zummo else if (strncmp(buf, "update", 6) == 0) 108a95579cdSAlessandro Zummo rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); 109a95579cdSAlessandro Zummo else 110a95579cdSAlessandro Zummo retval = -EINVAL; 111a95579cdSAlessandro Zummo 112a95579cdSAlessandro Zummo return retval; 113a95579cdSAlessandro Zummo } 114a95579cdSAlessandro Zummo static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); 115a95579cdSAlessandro Zummo 116a95579cdSAlessandro Zummo static int test_probe(struct platform_device *plat_dev) 117a95579cdSAlessandro Zummo { 118a95579cdSAlessandro Zummo int err; 119a95579cdSAlessandro Zummo struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, 120a95579cdSAlessandro Zummo &test_rtc_ops, THIS_MODULE); 121a95579cdSAlessandro Zummo if (IS_ERR(rtc)) { 122a95579cdSAlessandro Zummo err = PTR_ERR(rtc); 123a95579cdSAlessandro Zummo dev_err(&plat_dev->dev, 124a95579cdSAlessandro Zummo "unable to register the class device\n"); 125a95579cdSAlessandro Zummo return err; 126a95579cdSAlessandro Zummo } 127a95579cdSAlessandro Zummo device_create_file(&plat_dev->dev, &dev_attr_irq); 128a95579cdSAlessandro Zummo 129a95579cdSAlessandro Zummo platform_set_drvdata(plat_dev, rtc); 130a95579cdSAlessandro Zummo 131a95579cdSAlessandro Zummo return 0; 132a95579cdSAlessandro Zummo } 133a95579cdSAlessandro Zummo 134a95579cdSAlessandro Zummo static int __devexit test_remove(struct platform_device *plat_dev) 135a95579cdSAlessandro Zummo { 136a95579cdSAlessandro Zummo struct rtc_device *rtc = platform_get_drvdata(plat_dev); 137a95579cdSAlessandro Zummo 138a95579cdSAlessandro Zummo rtc_device_unregister(rtc); 139a95579cdSAlessandro Zummo device_remove_file(&plat_dev->dev, &dev_attr_irq); 140a95579cdSAlessandro Zummo 141a95579cdSAlessandro Zummo return 0; 142a95579cdSAlessandro Zummo } 143a95579cdSAlessandro Zummo 144a95579cdSAlessandro Zummo static struct platform_driver test_drv = { 145a95579cdSAlessandro Zummo .probe = test_probe, 146a95579cdSAlessandro Zummo .remove = __devexit_p(test_remove), 147a95579cdSAlessandro Zummo .driver = { 148a95579cdSAlessandro Zummo .name = "rtc-test", 149a95579cdSAlessandro Zummo .owner = THIS_MODULE, 150a95579cdSAlessandro Zummo }, 151a95579cdSAlessandro Zummo }; 152a95579cdSAlessandro Zummo 153a95579cdSAlessandro Zummo static int __init test_init(void) 154a95579cdSAlessandro Zummo { 155a95579cdSAlessandro Zummo int err; 156a95579cdSAlessandro Zummo 157a95579cdSAlessandro Zummo if ((err = platform_driver_register(&test_drv))) 158a95579cdSAlessandro Zummo return err; 159a95579cdSAlessandro Zummo 160a95579cdSAlessandro Zummo if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { 161a95579cdSAlessandro Zummo err = -ENOMEM; 162a95579cdSAlessandro Zummo goto exit_driver_unregister; 163a95579cdSAlessandro Zummo } 164a95579cdSAlessandro Zummo 165a95579cdSAlessandro Zummo if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { 166a95579cdSAlessandro Zummo err = -ENOMEM; 167a95579cdSAlessandro Zummo goto exit_free_test0; 168a95579cdSAlessandro Zummo } 169a95579cdSAlessandro Zummo 170a95579cdSAlessandro Zummo if ((err = platform_device_add(test0))) 171a95579cdSAlessandro Zummo goto exit_free_test1; 172a95579cdSAlessandro Zummo 173a95579cdSAlessandro Zummo if ((err = platform_device_add(test1))) 174a95579cdSAlessandro Zummo goto exit_device_unregister; 175a95579cdSAlessandro Zummo 176a95579cdSAlessandro Zummo return 0; 177a95579cdSAlessandro Zummo 178a95579cdSAlessandro Zummo exit_device_unregister: 179a95579cdSAlessandro Zummo platform_device_unregister(test0); 180a95579cdSAlessandro Zummo 181a95579cdSAlessandro Zummo exit_free_test1: 182a95579cdSAlessandro Zummo platform_device_put(test1); 183a95579cdSAlessandro Zummo 184a95579cdSAlessandro Zummo exit_free_test0: 185a95579cdSAlessandro Zummo platform_device_put(test0); 186a95579cdSAlessandro Zummo 187a95579cdSAlessandro Zummo exit_driver_unregister: 188a95579cdSAlessandro Zummo platform_driver_unregister(&test_drv); 189a95579cdSAlessandro Zummo return err; 190a95579cdSAlessandro Zummo } 191a95579cdSAlessandro Zummo 192a95579cdSAlessandro Zummo static void __exit test_exit(void) 193a95579cdSAlessandro Zummo { 194a95579cdSAlessandro Zummo platform_device_unregister(test0); 195a95579cdSAlessandro Zummo platform_device_unregister(test1); 196a95579cdSAlessandro Zummo platform_driver_unregister(&test_drv); 197a95579cdSAlessandro Zummo } 198a95579cdSAlessandro Zummo 199a95579cdSAlessandro Zummo MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); 200a95579cdSAlessandro Zummo MODULE_DESCRIPTION("RTC test driver/device"); 201a95579cdSAlessandro Zummo MODULE_LICENSE("GPL"); 202a95579cdSAlessandro Zummo 203a95579cdSAlessandro Zummo module_init(test_init); 204a95579cdSAlessandro Zummo module_exit(test_exit); 205