|
@@ -1,7 +1,7 @@
|
|
/*
|
|
/*
|
|
* Driver for NEC VR4100 series Real Time Clock unit.
|
|
* Driver for NEC VR4100 series Real Time Clock unit.
|
|
*
|
|
*
|
|
- * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
|
|
|
|
|
|
+ * Copyright (C) 2003-2008 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* 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
|
|
* it under the terms of the GNU General Public License as published by
|
|
@@ -34,7 +34,7 @@
|
|
|
|
|
|
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
|
|
MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
|
|
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
|
|
MODULE_DESCRIPTION("NEC VR4100 series RTC driver");
|
|
-MODULE_LICENSE("GPL");
|
|
|
|
|
|
+MODULE_LICENSE("GPL v2");
|
|
|
|
|
|
/* RTC 1 registers */
|
|
/* RTC 1 registers */
|
|
#define ETIMELREG 0x00
|
|
#define ETIMELREG 0x00
|
|
@@ -82,7 +82,6 @@ static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */
|
|
|
|
|
|
static DEFINE_SPINLOCK(rtc_lock);
|
|
static DEFINE_SPINLOCK(rtc_lock);
|
|
static char rtc_name[] = "RTC";
|
|
static char rtc_name[] = "RTC";
|
|
-static unsigned long periodic_frequency;
|
|
|
|
static unsigned long periodic_count;
|
|
static unsigned long periodic_count;
|
|
static unsigned int alarm_enabled;
|
|
static unsigned int alarm_enabled;
|
|
static int aie_irq = -1;
|
|
static int aie_irq = -1;
|
|
@@ -207,10 +206,37 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|
|
|
|
|
+static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
|
|
{
|
|
{
|
|
unsigned long count;
|
|
unsigned long count;
|
|
|
|
|
|
|
|
+ count = RTC_FREQUENCY;
|
|
|
|
+ do_div(count, freq);
|
|
|
|
+
|
|
|
|
+ periodic_count = count;
|
|
|
|
+
|
|
|
|
+ spin_lock_irq(&rtc_lock);
|
|
|
|
+
|
|
|
|
+ rtc1_write(RTCL1LREG, count);
|
|
|
|
+ rtc1_write(RTCL1HREG, count >> 16);
|
|
|
|
+
|
|
|
|
+ spin_unlock_irq(&rtc_lock);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
|
|
|
|
+{
|
|
|
|
+ if (enabled)
|
|
|
|
+ enable_irq(pie_irq);
|
|
|
|
+ else
|
|
|
|
+ disable_irq(pie_irq);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
|
|
|
+{
|
|
switch (cmd) {
|
|
switch (cmd) {
|
|
case RTC_AIE_ON:
|
|
case RTC_AIE_ON:
|
|
spin_lock_irq(&rtc_lock);
|
|
spin_lock_irq(&rtc_lock);
|
|
@@ -230,33 +256,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
|
|
alarm_enabled = 0;
|
|
alarm_enabled = 0;
|
|
}
|
|
}
|
|
|
|
|
|
- spin_unlock_irq(&rtc_lock);
|
|
|
|
- break;
|
|
|
|
- case RTC_PIE_ON:
|
|
|
|
- enable_irq(pie_irq);
|
|
|
|
- break;
|
|
|
|
- case RTC_PIE_OFF:
|
|
|
|
- disable_irq(pie_irq);
|
|
|
|
- break;
|
|
|
|
- case RTC_IRQP_READ:
|
|
|
|
- return put_user(periodic_frequency, (unsigned long __user *)arg);
|
|
|
|
- break;
|
|
|
|
- case RTC_IRQP_SET:
|
|
|
|
- if (arg > MAX_PERIODIC_RATE)
|
|
|
|
- return -EINVAL;
|
|
|
|
-
|
|
|
|
- periodic_frequency = arg;
|
|
|
|
-
|
|
|
|
- count = RTC_FREQUENCY;
|
|
|
|
- do_div(count, arg);
|
|
|
|
-
|
|
|
|
- periodic_count = count;
|
|
|
|
-
|
|
|
|
- spin_lock_irq(&rtc_lock);
|
|
|
|
-
|
|
|
|
- rtc1_write(RTCL1LREG, count);
|
|
|
|
- rtc1_write(RTCL1HREG, count >> 16);
|
|
|
|
-
|
|
|
|
spin_unlock_irq(&rtc_lock);
|
|
spin_unlock_irq(&rtc_lock);
|
|
break;
|
|
break;
|
|
case RTC_EPOCH_READ:
|
|
case RTC_EPOCH_READ:
|
|
@@ -309,6 +308,8 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
|
|
.set_time = vr41xx_rtc_set_time,
|
|
.set_time = vr41xx_rtc_set_time,
|
|
.read_alarm = vr41xx_rtc_read_alarm,
|
|
.read_alarm = vr41xx_rtc_read_alarm,
|
|
.set_alarm = vr41xx_rtc_set_alarm,
|
|
.set_alarm = vr41xx_rtc_set_alarm,
|
|
|
|
+ .irq_set_freq = vr41xx_rtc_irq_set_freq,
|
|
|
|
+ .irq_set_state = vr41xx_rtc_irq_set_state,
|
|
};
|
|
};
|
|
|
|
|
|
static int __devinit rtc_probe(struct platform_device *pdev)
|
|
static int __devinit rtc_probe(struct platform_device *pdev)
|
|
@@ -346,6 +347,8 @@ static int __devinit rtc_probe(struct platform_device *pdev)
|
|
goto err_iounmap_all;
|
|
goto err_iounmap_all;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ rtc->max_user_freq = MAX_PERIODIC_RATE;
|
|
|
|
+
|
|
spin_lock_irq(&rtc_lock);
|
|
spin_lock_irq(&rtc_lock);
|
|
|
|
|
|
rtc1_write(ECMPLREG, 0);
|
|
rtc1_write(ECMPLREG, 0);
|