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