From: Felipe Balbi <felipe.ba...@nokia.com>

remove the old syfs interface and move to rtc class
device registration.

Signed-off-by: Felipe Balbi <felipe.ba...@nokia.com>
---
 drivers/cbus/Kconfig    |    2 +-
 drivers/cbus/retu-rtc.c |  382 ++++++++++++++++-------------------------------
 2 files changed, 130 insertions(+), 254 deletions(-)

diff --git a/drivers/cbus/Kconfig b/drivers/cbus/Kconfig
index c344a99..c6b39fb 100644
--- a/drivers/cbus/Kconfig
+++ b/drivers/cbus/Kconfig
@@ -65,7 +65,7 @@ config CBUS_RETU_POWERBUTTON
          If you want support for the Retu power button, you should say Y here.
 
 config CBUS_RETU_RTC
-       depends on CBUS_RETU && SYSFS
+       depends on CBUS_RETU && RTC_CLASS
        tristate "Support for Retu pseudo-RTC"
        ---help---
          Say Y here if you want support for the device that alleges to be an
diff --git a/drivers/cbus/retu-rtc.c b/drivers/cbus/retu-rtc.c
index 1fe2b51..b0a0f3d 100644
--- a/drivers/cbus/retu-rtc.c
+++ b/drivers/cbus/retu-rtc.c
@@ -40,6 +40,7 @@
 #include <linux/completion.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
+#include <linux/rtc.h>
 #include <linux/workqueue.h>
 
 #include "cbus.h"
@@ -51,6 +52,7 @@ struct retu_rtc {
        struct completion       sync;
        struct work_struct      work;
        struct device           *dev;
+       struct rtc_device       *rtc;
 
        u16                     alarm_expired;
        u16                     reset_occurred;
@@ -68,92 +70,6 @@ static void retu_rtc_barrier(struct retu_rtc *rtc)
        retu_disable_irq(RETU_INT_RTCS);
 }
 
-static ssize_t retu_rtc_time_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       u16                     dsr, hmr, dsr2;
-
-       mutex_lock(&rtc->mutex);
-
-       do {
-               u16 dummy;
-
-               /*
-                * Not being in_interrupt() for a retu rtc IRQ, we need to
-                * read twice for consistency..
-                */
-               dummy   = retu_read_reg(RETU_REG_RTCDSR);
-               dsr     = retu_read_reg(RETU_REG_RTCDSR);
-
-               dummy   = retu_read_reg(RETU_REG_RTCHMR);
-               hmr     = retu_read_reg(RETU_REG_RTCHMR);
-
-               dummy   = retu_read_reg(RETU_REG_RTCDSR);
-               dsr2    = retu_read_reg(RETU_REG_RTCDSR);
-       } while ((dsr != dsr2));
-
-       mutex_unlock(&rtc->mutex);
-
-       /*
-        * Format a 32-bit date-string for userspace
-        *
-        * days | hours | minutes | seconds
-        *
-        * 8 bits for each.
-        *
-        * This mostly sucks because days and seconds are tracked in RTCDSR
-        * while hours and minutes are tracked in RTCHMR. And yes, there
-        * really are no words that can describe an 8 bit day register (or
-        * rather, none that will be reprinted here).
-        */
-       return sprintf(buf, "0x%08x\n", (((dsr >> 8) & 0xff) << 24) |
-                       (((hmr >> 8) & 0x1f) << 16) |
-                       ((hmr & 0x3f) << 8) | (dsr & 0x3f));
-}
-
-static ssize_t retu_rtc_time_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-
-       mutex_lock(&rtc->mutex);
-       /*
-        * Writing anything to the day counter forces it to 0
-        * The seconds counter would be cleared by resetting the minutes
-        * counter, however this won't happen, since we are using the
-        * hh:mm counters as a set of free running counters and the
-        * day counter as a multiple overflow holder.
-        */
-
-       /* Reset day counter, but keep Temperature Shutdown state */
-       retu_write_reg(RETU_REG_RTCDSR,
-                      retu_read_reg(RETU_REG_RTCDSR) & (1 << 6));
-
-       mutex_unlock(&rtc->mutex);
-
-       return count;
-}
-static DEVICE_ATTR(time, S_IRUGO | S_IWUSR, retu_rtc_time_show,
-                  retu_rtc_time_store);
-
-static ssize_t retu_rtc_reset_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-
-       /*
-        * Returns the status of the rtc
-        *
-        * 0: no reset has occurred or the status has been cleared
-        * 1: a reset has occurred
-        *
-        * RTC needs to be reset only when both main battery
-        * _AND_ backup battery are discharged
-        */
-       return sprintf(buf, "%u\n", rtc->reset_occurred);
-}
-
 static void retu_rtc_do_reset(struct retu_rtc *rtc)
 {
        u16 ccr1;
@@ -174,167 +90,6 @@ static void retu_rtc_do_reset(struct retu_rtc *rtc)
        rtc->reset_occurred = 1;
 }
 
-static ssize_t retu_rtc_reset_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       unsigned                choice;
-
-       if (sscanf(buf, "%u", &choice) != 1)
-               return count;
-       mutex_lock(&rtc->mutex);
-       if (choice == 0)
-               rtc->reset_occurred = 0;
-       else if (choice == 1)
-               retu_rtc_do_reset(rtc);
-       mutex_unlock(&rtc->mutex);
-       return count;
-}
-static DEVICE_ATTR(reset, S_IRUGO | S_IWUSR, retu_rtc_reset_show,
-                  retu_rtc_reset_store);
-
-static ssize_t retu_rtc_alarm_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       ssize_t                 retval;
-       u16                     chmar;
-
-       mutex_lock(&rtc->mutex);
-       /*
-        * Format a 16-bit date-string for userspace
-        *
-        * hours | minutes
-        * 8 bits for each.
-        */
-       chmar = retu_read_reg(RETU_REG_RTCHMAR);
-       /* No shifting needed, only masking unrelated bits */
-       retval = sprintf(buf, "0x%04x\n", chmar & 0x1f3f);
-       mutex_unlock(&rtc->mutex);
-
-       return retval;
-}
-
-static ssize_t retu_rtc_alarm_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-
-       unsigned                minutes;
-       unsigned                hours;
-       unsigned                alrm;
-
-       u16                     chmar;
-
-       mutex_lock(&rtc->mutex);
-
-       if (sscanf(buf, "%x", &alrm) != 1)
-               return count;
-       hours = (alrm >> 8) & 0x001f;
-       minutes = (alrm >> 0) & 0x003f;
-       if ((hours < 24 && minutes < 60) || (hours == 24 && minutes == 60)) {
-               /*
-                * OK, the time format for the alarm is valid (including the
-                * disabling values)
-                */
-               /* Keeps the RTC watchdog status */
-               chmar = retu_read_reg(RETU_REG_RTCHMAR) & 0x6000;
-               chmar |= alrm & 0x1f3f; /* Stores the requested alarm */
-               retu_rtc_barrier(rtc);
-               retu_write_reg(RETU_REG_RTCHMAR, chmar);
-               /* If the alarm is being disabled */
-               if (hours == 24 && minutes == 60) {
-                       /* disable the interrupt */
-                       retu_disable_irq(RETU_INT_RTCA);
-                       rtc->alarm_expired = 0;
-               } else
-                       /* enable the interrupt */
-                       retu_enable_irq(RETU_INT_RTCA);
-       }
-       mutex_unlock(&rtc->mutex);
-
-       return count;
-}
-static DEVICE_ATTR(alarm, S_IRUGO | S_IWUSR, retu_rtc_alarm_show,
-                  retu_rtc_alarm_store);
-
-static ssize_t retu_rtc_alarm_expired_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       ssize_t                 retval;
-
-       retval = sprintf(buf, "%u\n", rtc->alarm_expired);
-
-       return retval;
-}
-
-static ssize_t retu_rtc_alarm_expired_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-
-       rtc->alarm_expired = 0;
-
-       return count;
-}
-static DEVICE_ATTR(alarm_expired, S_IRUGO | S_IWUSR,
-               retu_rtc_alarm_expired_show, retu_rtc_alarm_expired_store);
-
-
-static ssize_t retu_rtc_cal_show(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       u16                     rtccalr1;
-
-       mutex_lock(&rtc->mutex);
-       rtccalr1 = retu_read_reg(RETU_REG_RTCCALR);
-       mutex_unlock(&rtc->mutex);
-
-       /*
-        * Shows the status of the Calibration Register.
-        *
-        * Default, after power loss: 0x0000
-        * Default, for R&D: 0x00C0
-        * Default, for factory: 0x00??
-        *
-        */
-       return sprintf(buf, "0x%04x\n", rtccalr1 & 0x00ff);
-}
-
-static ssize_t retu_rtc_cal_store(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct retu_rtc         *rtc = dev_get_drvdata(dev);
-       unsigned                calibration_value;
-
-       if (sscanf(buf, "%x", &calibration_value) != 1)
-               return count;
-
-       mutex_lock(&rtc->mutex);
-       retu_rtc_barrier(rtc);
-       retu_write_reg(RETU_REG_RTCCALR, calibration_value & 0x00ff);
-       mutex_unlock(&rtc->mutex);
-
-       return count;
-}
-static DEVICE_ATTR(cal, S_IRUGO | S_IWUSR, retu_rtc_cal_show,
-                  retu_rtc_cal_store);
-
-static struct attribute *retu_rtc_attrs[] = {
-       &dev_attr_cal.attr,
-       &dev_attr_alarm_expired.attr,
-       &dev_attr_alarm.attr,
-       &dev_attr_reset.attr,
-       &dev_attr_time.attr,
-       NULL,
-};
-
-static const struct attribute_group retu_rtc_group = {
-       .attrs = retu_rtc_attrs,
-};
-
 static void retu_rtca_disable(struct retu_rtc *rtc)
 {
        retu_disable_irq(RETU_INT_RTCA);
@@ -348,8 +103,6 @@ static void retu_rtca_expired(struct work_struct *work)
        struct retu_rtc         *rtc = work_to_rtc(work);
 
        retu_rtca_disable(rtc);
-
-       sysfs_notify(&rtc->dev->kobj, NULL, "alarm_expired");
 }
 
 /*
@@ -397,6 +150,127 @@ static int retu_rtc_init_irq(struct retu_rtc *rtc)
        return 0;
 }
 
+static int retu_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct retu_rtc         *rtc = dev_get_drvdata(dev);
+       u16                     chmar;
+
+       mutex_lock(&rtc->mutex);
+
+       chmar = ((alm->time.tm_hour & 0x1f) << 8) | (alm->time.tm_min & 0x3f);
+       retu_write_reg(RETU_REG_RTCHMAR, chmar);
+
+       mutex_unlock(&rtc->mutex);
+
+       return 0;
+}
+
+static int retu_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+       struct retu_rtc         *rtc = dev_get_drvdata(dev);
+       u16                     chmar;
+
+       mutex_lock(&rtc->mutex);
+
+       chmar = retu_read_reg(RETU_REG_RTCHMAR);
+
+       alm->time.tm_hour       = (chmar >> 8) & 0x1f;
+       alm->time.tm_min        = chmar & 0x3f;
+       alm->enabled            = !!rtc->alarm_expired;
+
+       mutex_unlock(&rtc->mutex);
+
+       return 0;
+}
+
+static int retu_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct retu_rtc         *rtc = dev_get_drvdata(dev);
+       u16                     dsr;
+       u16                     hmr;
+
+       dsr = ((tm->tm_mday & 0xff) << 8) | (tm->tm_hour & 0xff);
+       hmr = ((tm->tm_min & 0xff) << 8) | (tm->tm_sec & 0xff);
+
+       mutex_lock(&rtc->mutex);
+
+       retu_write_reg(RETU_REG_RTCDSR, dsr);
+       retu_write_reg(RETU_REG_RTCHMR, hmr);
+
+       mutex_unlock(&rtc->mutex);
+
+       return 0;
+}
+
+static int retu_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct retu_rtc         *rtc = dev_get_drvdata(dev);
+       u16                     dsr;
+       u16                     hmr;
+
+       /*
+        * DSR holds days and hours
+        * HMR hols minutes and seconds
+        *
+        * both are 16 bit registers with 8-bit for each field.
+        */
+
+       mutex_lock(&rtc->mutex);
+
+       dsr     = retu_read_reg(RETU_REG_RTCDSR);
+       hmr     = retu_read_reg(RETU_REG_RTCHMR);
+
+       tm->tm_sec      = hmr & 0xff;
+       tm->tm_min      = hmr >> 8;
+       tm->tm_hour     = dsr & 0xff;
+       tm->tm_mday     = dsr >> 8;
+
+       mutex_unlock(&rtc->mutex);
+
+       return 0;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+
+static int retu_rtc_ioctl(struct device *dev, unsigned int cmd,
+               unsigned long arg)
+{
+       struct retu_rtc         *rtc = dev_get_drvdata(dev);
+
+       mutex_lock(&rtc->mutex);
+
+       switch (cmd) {
+       case RTC_AIE_OFF:
+               retu_disable_irq(RETU_INT_RTCA);
+               break;
+       case RTC_AIE_ON:
+               retu_enable_irq(RETU_INT_RTCA);
+               break;
+       case RTC_UIE_OFF:
+               retu_disable_irq(RETU_INT_RTCS);
+               break;
+       case RTC_UIE_ON:
+               retu_enable_irq(RETU_INT_RTCS);
+               break;
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       mutex_unlock(&rtc->mutex);
+
+       return 0;
+}
+#else
+#define retu_rtc_ioctl NULL
+#endif
+
+static struct rtc_class_ops retu_rtc_ops = {
+       .ioctl                  = retu_rtc_ioctl,
+       .read_time              = retu_rtc_read_time,
+       .set_time               = retu_rtc_set_time,
+       .read_alarm             = retu_rtc_read_alarm,
+       .set_alarm              = retu_rtc_set_alarm,
+};
 
 static int __devinit retu_rtc_probe(struct platform_device *pdev)
 {
@@ -437,9 +311,11 @@ static int __devinit retu_rtc_probe(struct platform_device 
*pdev)
        else
                retu_rtc_do_reset(rtc);
 
-       r = sysfs_create_group(&pdev->dev.kobj, &retu_rtc_group);
-       if (r) {
-               dev_err(&pdev->dev, "couldn't create sysfs interface\n");
+
+       rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, &
+                       retu_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc)) {
+               dev_err(&pdev->dev, "can't register RTC device\n");
                goto err2;
        }
 
@@ -466,7 +342,7 @@ static int __devexit retu_rtc_remove(struct platform_device 
*pdev)
        retu_disable_irq(RETU_INT_RTCA);
        retu_free_irq(RETU_INT_RTCS);
        retu_free_irq(RETU_INT_RTCA);
-       sysfs_remove_group(&pdev->dev.kobj, &retu_rtc_group);
+       rtc_device_unregister(rtc->rtc);
        kfree(rtc);
 
        return 0;
-- 
1.7.0.rc0.33.g7c3932

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to