Merge tag 'rtc-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Aug 2018 23:30:27 +0000 (16:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Aug 2018 23:30:27 +0000 (16:30 -0700)
Pull RTC updates from Alexandre Belloni:
 "It is now possible to add custom sysfs attributes while avoiding a
  possible race condition. Unused code has been removed resulting in a
  nice reduction of the code base. And more drivers have been switched
  to SPDX by their maintainers.

 Summary:

  Subsystem:
   - new helpers to add custom sysfs attributes
   - struct rtc_task removal along with rtc_irq_[un]register()
   - rtc_irq_set_state and rtc_irq_set_freq are not exported anymore

  Drivers:
   - armada38x: reset after rtc power loss
   - ds1307: now supports m41t11
   - isl1208: now supports isl1219 and tamper detection
   - pcf2127: internal SRAM support"

* tag 'rtc-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (34 commits)
  rtc: ds1307: simplify hwmon config
  rtc: s5m: Add SPDX license identifier
  rtc: maxim: Add SPDX license identifiers
  rtc: isl1219: add device tree documentation
  rtc: isl1208: set ev-evienb bit from device tree
  rtc: isl1208: Add "evdet" interrupt source for isl1219
  rtc: isl1208: add support for isl1219 with tamper detection
  rtc: sysfs: facilitate attribute add to rtc device
  rtc: remove struct rtc_task
  char: rtc: remove task handling
  rtc: pcf85063: preserve control register value between stop and start
  rtc: sh: remove unused variable rtc_dev
  rtc: unexport rtc_irq_set_*
  rtc: simplify rtc_irq_set_state/rtc_irq_set_freq
  rtc: remove irq_task and irq_task_lock
  rtc: remove rtc_irq_register/rtc_irq_unregister
  rtc: sh: remove dead code
  rtc: sa1100: don't set PIE frequency
  rtc: ds1307: support m41t11 variant
  rtc: ds1307: fix data pointer to m41t0
  ...

28 files changed:
Documentation/devicetree/bindings/rtc/isil,isl1219.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-ds1307.txt
drivers/char/rtc.c
drivers/rtc/Kconfig
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-armada38x.c
drivers/rtc/rtc-bq4802.c
drivers/rtc/rtc-core.h
drivers/rtc/rtc-dev.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1685.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-max77686.c
drivers/rtc/rtc-max8997.c
drivers/rtc/rtc-max8998.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf2127.c
drivers/rtc/rtc-pcf85063.c
drivers/rtc/rtc-s5m.c
drivers/rtc/rtc-sa1100.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-stmp3xxx.c
drivers/rtc/rtc-sysfs.c
drivers/rtc/rtc-test.c
include/linux/rtc.h

diff --git a/Documentation/devicetree/bindings/rtc/isil,isl1219.txt b/Documentation/devicetree/bindings/rtc/isil,isl1219.txt
new file mode 100644 (file)
index 0000000..c3efd48
--- /dev/null
@@ -0,0 +1,29 @@
+Intersil ISL1219 I2C RTC/Alarm chip with event in
+
+ISL1219 has additional pins EVIN and #EVDET for tamper detection.
+
+Required properties supported by the device:
+
+ - "compatible": must be "isil,isl1219"
+ - "reg": I2C bus address of the device
+
+Optional properties:
+
+ - "interrupt-names": list which may contains "irq" and "evdet"
+ - "interrupts": list of interrupts for "irq" and "evdet"
+ - "isil,ev-evienb": if present EV.EVIENB bit is set to the specified
+                     value for proper operation.
+
+
+Example isl1219 node with #IRQ pin connected to SoC gpio1 pin12
+ and #EVDET pin connected to SoC gpio2 pin 24:
+
+       isl1219: rtc@68 {
+               compatible = "isil,isl1219";
+               reg = <0x68>;
+               interrupt-names = "irq", "evdet";
+               interrupts-extended = <&gpio1 12 IRQ_TYPE_EDGE_FALLING>,
+                       <&gpio2 24 IRQ_TYPE_EDGE_FALLING>;
+               isil,ev-evienb = <1>;
+       };
+
index 226cc93df87530119d46be14bc3d485f643b4f63..eebfbe04207a0e02f8e4d517f4dfb4ce0678a1e0 100644 (file)
@@ -13,6 +13,7 @@ Required properties:
        "maxim,ds3231",
        "st,m41t0",
        "st,m41t00",
+       "st,m41t11",
        "microchip,mcp7940x",
        "microchip,mcp7941x",
        "pericom,pt7c4338",
index 94fedeeec0356b7a9f818b72369cca1bd312379e..4948c8bda6b1fb7d5dc1dd734f52ebc11307aa99 100644 (file)
@@ -193,14 +193,6 @@ static unsigned long rtc_freq;             /* Current periodic IRQ rate    */
 static unsigned long rtc_irq_data;     /* our output to the world      */
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
-#ifdef RTC_IRQ
-/*
- * rtc_task_lock nests inside rtc_lock.
- */
-static DEFINE_SPINLOCK(rtc_task_lock);
-static rtc_task_t *rtc_callback;
-#endif
-
 /*
  *     If this driver ever becomes modularised, it will be really nice
  *     to make the epoch retain its value across module reload...
@@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
 
        spin_unlock(&rtc_lock);
 
-       /* Now do the rest of the actions */
-       spin_lock(&rtc_task_lock);
-       if (rtc_callback)
-               rtc_callback->func(rtc_callback->private_data);
-       spin_unlock(&rtc_task_lock);
        wake_up_interruptible(&rtc_wait);
 
        kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
index a2ba5db36145c90ec8c842e28d362e6deb34659b..7d7be60a2413f060fe3f6e86b7ab51a9407f0c8f 100644 (file)
@@ -244,15 +244,6 @@ config RTC_DRV_DS1307
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1307.
 
-config RTC_DRV_DS1307_HWMON
-       bool "HWMON support for rtc-ds1307"
-       depends on RTC_DRV_DS1307 && HWMON
-       depends on !(RTC_DRV_DS1307=y && HWMON=m)
-       default y
-       help
-         Say Y here if you want to expose temperature sensor data on
-         rtc-ds1307 (only DS3231)
-
 config RTC_DRV_DS1307_CENTURY
        bool "Century bit support for rtc-ds1307"
        depends on RTC_DRV_DS1307
@@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS
 
          Unless you are debugging this driver, choose N.
 
-config RTC_DS1685_SYSFS_REGS
-       bool "SysFS access to RTC register bits"
-       depends on RTC_DRV_DS1685_FAMILY && SYSFS
-       help
-         Enable this to provide access to the RTC control register bits
-         in /sys.  Some of the bits are read-write, others are read-only.
-
-         Keep in mind that reading Control C's bits automatically clears
-         all pending IRQ flags - this can cause lost interrupts.
-
-         If you know that you need access to these bits, choose Y, Else N.
-
 config RTC_DRV_DS1742
        tristate "Maxim/Dallas DS1742/1743"
        depends on HAS_IOMEM
index d37588f080556d16af315862b99370ef4a948ea5..0fca4d74c76b34a645d3b65382a46f16c9bf9501 100644 (file)
@@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev)
                return 0;
        }
 
-       getnstimeofday64(&old_system);
+       ktime_get_real_ts64(&old_system);
        old_rtc.tv_sec = rtc_tm_to_time64(&tm);
 
 
@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
                return 0;
 
        /* snapshot the current rtc and system time at resume */
-       getnstimeofday64(&new_system);
+       ktime_get_real_ts64(&new_system);
        err = rtc_read_time(rtc, &tm);
        if (err < 0) {
                pr_debug("%s:  fail to read rtc time\n", dev_name(&rtc->dev));
@@ -172,7 +172,6 @@ static struct rtc_device *rtc_allocate_device(void)
 
        mutex_init(&rtc->ops_lock);
        spin_lock_init(&rtc->irq_lock);
-       spin_lock_init(&rtc->irq_task_lock);
        init_waitqueue_head(&rtc->irq_queue);
 
        /* Init timerqueue */
index bac1eeb3d31204d9e99a93e1e682972b5f7177bb..3d577e259e91b94f6e1b5abbce60bf3746308803 100644 (file)
@@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode)
        rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
        spin_unlock_irqrestore(&rtc->irq_lock, flags);
 
-       /* call the task func */
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task)
-               rtc->irq_task->func(rtc->irq_task->private_data);
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-
        wake_up_interruptible(&rtc->irq_queue);
        kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
 }
@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc)
 }
 EXPORT_SYMBOL_GPL(rtc_class_close);
 
-int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task)
-{
-       int retval = -EBUSY;
-
-       if (task == NULL || task->func == NULL)
-               return -EINVAL;
-
-       /* Cannot register while the char dev is in use */
-       if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags))
-               return -EBUSY;
-
-       spin_lock_irq(&rtc->irq_task_lock);
-       if (rtc->irq_task == NULL) {
-               rtc->irq_task = task;
-               retval = 0;
-       }
-       spin_unlock_irq(&rtc->irq_task_lock);
-
-       clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
-
-       return retval;
-}
-EXPORT_SYMBOL_GPL(rtc_irq_register);
-
-void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task)
-{
-       spin_lock_irq(&rtc->irq_task_lock);
-       if (rtc->irq_task == task)
-               rtc->irq_task = NULL;
-       spin_unlock_irq(&rtc->irq_task_lock);
-}
-EXPORT_SYMBOL_GPL(rtc_irq_unregister);
-
 static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
 {
        /*
@@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
  * Context: any
  *
  * Note that rtc_irq_set_freq() should previously have been used to
- * specify the desired frequency of periodic IRQ task->func() callbacks.
+ * specify the desired frequency of periodic IRQ.
  */
-int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled)
+int rtc_irq_set_state(struct rtc_device *rtc, int enabled)
 {
        int err = 0;
-       unsigned long flags;
 
-retry:
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task != NULL && task == NULL)
-               err = -EBUSY;
-       else if (rtc->irq_task != task)
-               err = -EACCES;
-       else {
-               if (rtc_update_hrtimer(rtc, enabled) < 0) {
-                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-                       cpu_relax();
-                       goto retry;
-               }
-               rtc->pie_enabled = enabled;
-       }
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+       while (rtc_update_hrtimer(rtc, enabled) < 0)
+               cpu_relax();
+
+       rtc->pie_enabled = enabled;
 
        trace_rtc_irq_set_state(enabled, err);
        return err;
 }
-EXPORT_SYMBOL_GPL(rtc_irq_set_state);
 
 /**
  * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
  * @rtc: the rtc device
  * @task: currently registered with rtc_irq_register()
- * @freq: positive frequency with which task->func() will be called
+ * @freq: positive frequency
  * Context: any
  *
  * Note that rtc_irq_set_state() is used to enable or disable the
  * periodic IRQs.
  */
-int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq)
+int rtc_irq_set_freq(struct rtc_device *rtc, int freq)
 {
        int err = 0;
-       unsigned long flags;
 
        if (freq <= 0 || freq > RTC_MAX_FREQ)
                return -EINVAL;
-retry:
-       spin_lock_irqsave(&rtc->irq_task_lock, flags);
-       if (rtc->irq_task != NULL && task == NULL)
-               err = -EBUSY;
-       else if (rtc->irq_task != task)
-               err = -EACCES;
-       else {
-               rtc->irq_freq = freq;
-               if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) {
-                       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
-                       cpu_relax();
-                       goto retry;
-               }
-       }
-       spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
+
+       rtc->irq_freq = freq;
+       while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0)
+               cpu_relax();
 
        trace_rtc_irq_set_freq(freq, err);
        return err;
 }
-EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
 
 /**
  * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
@@ -979,8 +914,8 @@ again:
                timerqueue_del(&rtc->timerqueue, &timer->node);
                trace_rtc_timer_dequeue(timer);
                timer->enabled = 0;
-               if (timer->task.func)
-                       timer->task.func(timer->task.private_data);
+               if (timer->func)
+                       timer->func(timer->private_data);
 
                trace_rtc_timer_fired(timer);
                /* Re-add/fwd periodic timers */
@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
 {
        timerqueue_init(&timer->node);
        timer->enabled = 0;
-       timer->task.func = f;
-       timer->task.private_data = data;
+       timer->func = f;
+       timer->private_data = data;
 }
 
 /* rtc_timer_start - Sets an rtc_timer to fire in the future
index 1e4978c96ffd273c617e9c8d89f49a9b2a0838ec..bde53c8ccee2cbbcac52120dde4cc217e9c10f93 100644 (file)
@@ -30,6 +30,8 @@
 #define RTC_IRQ_FREQ_1HZ           BIT(2)
 #define RTC_CCR                    0x18
 #define RTC_CCR_MODE               BIT(15)
+#define RTC_CONF_TEST      0x1C
+#define RTC_NOMINAL_TIMING         BIT(13)
 
 #define RTC_TIME           0xC
 #define RTC_ALARM1         0x10
@@ -75,6 +77,7 @@ struct armada38x_rtc {
        void __iomem        *regs_soc;
        spinlock_t          lock;
        int                 irq;
+       bool                initialized;
        struct value_to_freq *val_to_freq;
        struct armada38x_rtc_data *data;
 };
@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
        return 0;
 }
 
+static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
+{
+       u32 reg;
+
+       reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST);
+       /* If bits [7:0] are non-zero, assume RTC was uninitialized */
+       if (reg & 0xff) {
+               rtc_delayed_write(0, rtc, RTC_CONF_TEST);
+               msleep(500); /* Oscillator startup time */
+               rtc_delayed_write(0, rtc, RTC_TIME);
+               rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc,
+                                 RTC_STATUS);
+               rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR);
+       }
+       rtc->initialized = true;
+}
+
 static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct armada38x_rtc *rtc = dev_get_drvdata(dev);
@@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
        if (ret)
                goto out;
 
+       if (!rtc->initialized)
+               armada38x_rtc_reset(rtc);
+
        spin_lock_irqsave(&rtc->lock, flags);
        rtc_delayed_write(time, rtc, RTC_TIME);
        spin_unlock_irqrestore(&rtc->lock, flags);
index d768f6747961cc206c3c1d14e8e3caaec2e971d9..113493b5214952b2740a9c1f270525572bc07545 100644 (file)
@@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev)
        } else if (p->r->flags & IORESOURCE_MEM) {
                p->regs = devm_ioremap(&pdev->dev, p->r->start,
                                        resource_size(p->r));
+               if (!p->regs){
+                       err = -ENOMEM;
+                       goto out;
+               }
                p->read = bq4802_read_mem;
                p->write = bq4802_write_mem;
        } else {
index 0abf98983e13f6353e75e7d732d78a361b189dd7..ccc17a2e293d178985a496fa87e696cac5491fe9 100644 (file)
@@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
 
 #ifdef CONFIG_RTC_INTF_SYSFS
 const struct attribute_group **rtc_get_dev_attribute_groups(void);
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp);
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps);
 #else
 static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
 {
        return NULL;
 }
+
+static inline
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+       return 0;
+}
+
+static inline
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+       return 0;
+}
 #endif
index efa221e8bc22da4b60f788b48768f59ef5fff220..43d962a9c2105a2f8f4aa84c35583a37cffe5e26 100644 (file)
@@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file,
                return rtc_set_time(rtc, &tm);
 
        case RTC_PIE_ON:
-               err = rtc_irq_set_state(rtc, NULL, 1);
+               err = rtc_irq_set_state(rtc, 1);
                break;
 
        case RTC_PIE_OFF:
-               err = rtc_irq_set_state(rtc, NULL, 0);
+               err = rtc_irq_set_state(rtc, 0);
                break;
 
        case RTC_AIE_ON:
@@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file,
                return rtc_update_irq_enable(rtc, 0);
 
        case RTC_IRQP_SET:
-               err = rtc_irq_set_freq(rtc, NULL, arg);
+               err = rtc_irq_set_freq(rtc, arg);
                break;
 
        case RTC_IRQP_READ:
@@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
        /* Keep ioctl until all drivers are converted */
        rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
        rtc_update_irq_enable(rtc, 0);
-       rtc_irq_set_state(rtc, NULL, 0);
+       rtc_irq_set_state(rtc, 0);
 
        clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
        return 0;
index e9ec4160d7f6bff6aeeebd70c2d88c4689b53597..4b2b4627daebfb89b77121d499110d7f553a7394 100644 (file)
@@ -44,6 +44,7 @@ enum ds_type {
        ds_3231,
        m41t0,
        m41t00,
+       m41t11,
        mcp794xx,
        rx_8025,
        rx_8130,
@@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = {
                .irq_handler = rx8130_irq,
                .rtc_ops = &rx8130_rtc_ops,
        },
+       [m41t11] = {
+               /* this is battery backed SRAM */
+               .nvram_offset   = 8,
+               .nvram_size     = 56,
+       },
        [mcp794xx] = {
                .alarm          = 1,
                /* this is battery backed SRAM */
@@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = {
        { "ds3231", ds_3231 },
        { "m41t0", m41t0 },
        { "m41t00", m41t00 },
+       { "m41t11", m41t11 },
        { "mcp7940x", mcp794xx },
        { "mcp7941x", mcp794xx },
        { "pt7c4338", ds_1307 },
@@ -299,12 +306,16 @@ static const struct of_device_id ds1307_of_match[] = {
        },
        {
                .compatible = "st,m41t0",
-               .data = (void *)m41t00
+               .data = (void *)m41t0
        },
        {
                .compatible = "st,m41t00",
                .data = (void *)m41t00
        },
+       {
+               .compatible = "st,m41t11",
+               .data = (void *)m41t11
+       },
        {
                .compatible = "microchip,mcp7940x",
                .data = (void *)mcp794xx
@@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
        { .id = "DS3231", .driver_data = ds_3231 },
        { .id = "M41T0", .driver_data = m41t0 },
        { .id = "M41T00", .driver_data = m41t00 },
+       { .id = "M41T11", .driver_data = m41t11 },
        { .id = "MCP7940X", .driver_data = mcp794xx },
        { .id = "MCP7941X", .driver_data = mcp794xx },
        { .id = "PT7C4338", .driver_data = ds_1307 },
@@ -1030,7 +1042,7 @@ static u8 ds1307_trickle_init(struct ds1307 *ds1307,
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_RTC_DRV_DS1307_HWMON
+#if IS_REACHABLE(CONFIG_HWMON)
 
 /*
  * Temperature sensor support for ds3231 devices.
@@ -1576,6 +1588,7 @@ read_rtc:
        case ds_1307:
        case m41t0:
        case m41t00:
+       case m41t11:
                /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH) {
                        regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
@@ -1641,6 +1654,7 @@ read_rtc:
        case ds_1340:
        case m41t0:
        case m41t00:
+       case m41t11:
                /*
                 * NOTE: ignores century bits; fix before deploying
                 * systems that will run through year 2100.
index 5c0db6c8134cb23362896dbb618af72cfa74eebc..6f39f683a98c6385f208473459b705bfe91e1f74 100644 (file)
@@ -1188,552 +1188,6 @@ ds1685_rtc_sysfs_misc_grp = {
        .attrs = ds1685_rtc_sysfs_misc_attrs,
 };
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_ctrl_regs {
-       const char *name;
-       const u8 reg;
-       const u8 bit;
-};
-
-/*
- * Ctrl register bit lookup table.
- */
-static const struct ds1685_rtc_ctrl_regs
-ds1685_ctrl_regs_table[] = {
-       { "uip",  RTC_CTRL_A,      RTC_CTRL_A_UIP   },
-       { "dv2",  RTC_CTRL_A,      RTC_CTRL_A_DV2   },
-       { "dv1",  RTC_CTRL_A,      RTC_CTRL_A_DV1   },
-       { "dv0",  RTC_CTRL_A,      RTC_CTRL_A_DV0   },
-       { "rs3",  RTC_CTRL_A,      RTC_CTRL_A_RS3   },
-       { "rs2",  RTC_CTRL_A,      RTC_CTRL_A_RS2   },
-       { "rs1",  RTC_CTRL_A,      RTC_CTRL_A_RS1   },
-       { "rs0",  RTC_CTRL_A,      RTC_CTRL_A_RS0   },
-       { "set",  RTC_CTRL_B,      RTC_CTRL_B_SET   },
-       { "pie",  RTC_CTRL_B,      RTC_CTRL_B_PIE   },
-       { "aie",  RTC_CTRL_B,      RTC_CTRL_B_AIE   },
-       { "uie",  RTC_CTRL_B,      RTC_CTRL_B_UIE   },
-       { "sqwe", RTC_CTRL_B,      RTC_CTRL_B_SQWE  },
-       { "dm",   RTC_CTRL_B,      RTC_CTRL_B_DM    },
-       { "2412", RTC_CTRL_B,      RTC_CTRL_B_2412  },
-       { "dse",  RTC_CTRL_B,      RTC_CTRL_B_DSE   },
-       { "irqf", RTC_CTRL_C,      RTC_CTRL_C_IRQF  },
-       { "pf",   RTC_CTRL_C,      RTC_CTRL_C_PF    },
-       { "af",   RTC_CTRL_C,      RTC_CTRL_C_AF    },
-       { "uf",   RTC_CTRL_C,      RTC_CTRL_C_UF    },
-       { "vrt",  RTC_CTRL_D,      RTC_CTRL_D_VRT   },
-       { "vrt2", RTC_EXT_CTRL_4A, RTC_CTRL_4A_VRT2 },
-       { "incr", RTC_EXT_CTRL_4A, RTC_CTRL_4A_INCR },
-       { "pab",  RTC_EXT_CTRL_4A, RTC_CTRL_4A_PAB  },
-       { "rf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_RF   },
-       { "wf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_WF   },
-       { "kf",   RTC_EXT_CTRL_4A, RTC_CTRL_4A_KF   },
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-       { "bme",  RTC_EXT_CTRL_4A, RTC_CTRL_4A_BME  },
-#endif
-       { "abe",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_ABE  },
-       { "e32k", RTC_EXT_CTRL_4B, RTC_CTRL_4B_E32K },
-       { "cs",   RTC_EXT_CTRL_4B, RTC_CTRL_4B_CS   },
-       { "rce",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_RCE  },
-       { "prs",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_PRS  },
-       { "rie",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_RIE  },
-       { "wie",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_WIE  },
-       { "kse",  RTC_EXT_CTRL_4B, RTC_CTRL_4B_KSE  },
-       { NULL,   0,               0                },
-};
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_lookup - ctrl register bit lookup function.
- * @name: ctrl register bit to look up in ds1685_ctrl_regs_table.
- */
-static const struct ds1685_rtc_ctrl_regs*
-ds1685_rtc_sysfs_ctrl_regs_lookup(const char *name)
-{
-       const struct ds1685_rtc_ctrl_regs *p = ds1685_ctrl_regs_table;
-
-       for (; p->name != NULL; ++p)
-               if (strcmp(p->name, name) == 0)
-                       return p;
-
-       return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_show - reads a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 tmp;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_ctrl_regs *reg_info =
-               ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
-       /* Make sure we actually matched something. */
-       if (!reg_info)
-               return -EINVAL;
-
-       /* No spinlock during a read -- mutex is already held. */
-       ds1685_rtc_switch_to_bank1(rtc);
-       tmp = rtc->read(rtc, reg_info->reg) & reg_info->bit;
-       ds1685_rtc_switch_to_bank0(rtc);
-
-       return sprintf(buf, "%d\n", (tmp ? 1 : 0));
-}
-
-/**
- * ds1685_rtc_sysfs_ctrl_regs_store - writes a ctrl register bit via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       u8 reg = 0, bit = 0, tmp;
-       unsigned long flags;
-       long int val = 0;
-       const struct ds1685_rtc_ctrl_regs *reg_info =
-               ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
-
-       /* We only accept numbers. */
-       if (kstrtol(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       /* bits are binary, 0 or 1 only. */
-       if ((val != 0) && (val != 1))
-               return -ERANGE;
-
-       /* Make sure we actually matched something. */
-       if (!reg_info)
-               return -EINVAL;
-
-       reg = reg_info->reg;
-       bit = reg_info->bit;
-
-       /* Safe to spinlock during a write. */
-       ds1685_rtc_begin_ctrl_access(rtc, &flags);
-       tmp = rtc->read(rtc, reg);
-       rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
-       ds1685_rtc_end_ctrl_access(rtc, flags);
-
-       return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RO - device_attribute for read-only register bit.
- * @bit: bit to read.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RO(bit)                              \
-       static DEVICE_ATTR(bit, S_IRUGO,                                \
-       ds1685_rtc_sysfs_ctrl_regs_show, NULL)
-
-/**
- * DS1685_RTC_SYSFS_CTRL_REG_RW - device_attribute for read-write register bit.
- * @bit: bit to read or write.
- */
-#define DS1685_RTC_SYSFS_CTRL_REG_RW(bit)                              \
-       static DEVICE_ATTR(bit, S_IRUGO | S_IWUSR,                      \
-       ds1685_rtc_sysfs_ctrl_regs_show,                                \
-       ds1685_rtc_sysfs_ctrl_regs_store)
-
-/*
- * Control Register A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(uip);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(dv1);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dv0);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs3);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs2);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs1);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rs0);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrla_attrs[] = {
-       &dev_attr_uip.attr,
-       &dev_attr_dv2.attr,
-       &dev_attr_dv1.attr,
-       &dev_attr_dv0.attr,
-       &dev_attr_rs3.attr,
-       &dev_attr_rs2.attr,
-       &dev_attr_rs1.attr,
-       &dev_attr_rs0.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrla_grp = {
-       .name = "ctrla",
-       .attrs = ds1685_rtc_sysfs_ctrla_attrs,
-};
-
-
-/*
- * Control Register B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(set);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(aie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(uie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(sqwe);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dm);
-DS1685_RTC_SYSFS_CTRL_REG_RO(2412);
-DS1685_RTC_SYSFS_CTRL_REG_RO(dse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlb_attrs[] = {
-       &dev_attr_set.attr,
-       &dev_attr_pie.attr,
-       &dev_attr_aie.attr,
-       &dev_attr_uie.attr,
-       &dev_attr_sqwe.attr,
-       &dev_attr_dm.attr,
-       &dev_attr_2412.attr,
-       &dev_attr_dse.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlb_grp = {
-       .name = "ctrlb",
-       .attrs = ds1685_rtc_sysfs_ctrlb_attrs,
-};
-
-/*
- * Control Register C bits.
- *
- * Reading Control C clears these bits!  Reading them individually can
- * possibly cause an interrupt to be missed.  Use the /proc interface
- * to see all the bits in this register simultaneously.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(irqf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(pf);
-DS1685_RTC_SYSFS_CTRL_REG_RO(af);
-DS1685_RTC_SYSFS_CTRL_REG_RO(uf);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrlc_attrs[] = {
-       &dev_attr_irqf.attr,
-       &dev_attr_pf.attr,
-       &dev_attr_af.attr,
-       &dev_attr_uf.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrlc_grp = {
-       .name = "ctrlc",
-       .attrs = ds1685_rtc_sysfs_ctrlc_attrs,
-};
-
-/*
- * Control Register D bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrld_attrs[] = {
-       &dev_attr_vrt.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrld_grp = {
-       .name = "ctrld",
-       .attrs = ds1685_rtc_sysfs_ctrld_attrs,
-};
-
-/*
- * Control Register 4A bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RO(vrt2);
-DS1685_RTC_SYSFS_CTRL_REG_RO(incr);
-DS1685_RTC_SYSFS_CTRL_REG_RW(pab);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wf);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kf);
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-DS1685_RTC_SYSFS_CTRL_REG_RO(bme);
-#endif
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4a_attrs[] = {
-       &dev_attr_vrt2.attr,
-       &dev_attr_incr.attr,
-       &dev_attr_pab.attr,
-       &dev_attr_rf.attr,
-       &dev_attr_wf.attr,
-       &dev_attr_kf.attr,
-#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689)
-       &dev_attr_bme.attr,
-#endif
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4a_grp = {
-       .name = "ctrl4a",
-       .attrs = ds1685_rtc_sysfs_ctrl4a_attrs,
-};
-
-/*
- * Control Register 4B bits.
- */
-DS1685_RTC_SYSFS_CTRL_REG_RW(abe);
-DS1685_RTC_SYSFS_CTRL_REG_RW(e32k);
-DS1685_RTC_SYSFS_CTRL_REG_RO(cs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rce);
-DS1685_RTC_SYSFS_CTRL_REG_RW(prs);
-DS1685_RTC_SYSFS_CTRL_REG_RW(rie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(wie);
-DS1685_RTC_SYSFS_CTRL_REG_RW(kse);
-
-static struct attribute*
-ds1685_rtc_sysfs_ctrl4b_attrs[] = {
-       &dev_attr_abe.attr,
-       &dev_attr_e32k.attr,
-       &dev_attr_cs.attr,
-       &dev_attr_rce.attr,
-       &dev_attr_prs.attr,
-       &dev_attr_rie.attr,
-       &dev_attr_wie.attr,
-       &dev_attr_kse.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_ctrl4b_grp = {
-       .name = "ctrl4b",
-       .attrs = ds1685_rtc_sysfs_ctrl4b_attrs,
-};
-
-
-/**
- * struct ds1685_rtc_ctrl_regs.
- * @name: char pointer for the bit name.
- * @reg: control register the bit is in.
- * @bit: the bit's offset in the register.
- */
-struct ds1685_rtc_time_regs {
-       const char *name;
-       const u8 reg;
-       const u8 mask;
-       const u8 min;
-       const u8 max;
-};
-
-/*
- * Time/Date register lookup tables.
- */
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bcd_table[] = {
-       { "seconds",       RTC_SECS,       RTC_SECS_BCD_MASK,   0, 59 },
-       { "minutes",       RTC_MINS,       RTC_MINS_BCD_MASK,   0, 59 },
-       { "hours",         RTC_HRS,        RTC_HRS_24_BCD_MASK, 0, 23 },
-       { "wday",          RTC_WDAY,       RTC_WDAY_MASK,       1,  7 },
-       { "mday",          RTC_MDAY,       RTC_MDAY_BCD_MASK,   1, 31 },
-       { "month",         RTC_MONTH,      RTC_MONTH_BCD_MASK,  1, 12 },
-       { "year",          RTC_YEAR,       RTC_YEAR_BCD_MASK,   0, 99 },
-       { "century",       RTC_CENTURY,    RTC_CENTURY_MASK,    0, 99 },
-       { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BCD_MASK,   0, 59 },
-       { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BCD_MASK,   0, 59 },
-       { "alarm_hours",   RTC_HRS_ALARM,  RTC_HRS_24_BCD_MASK, 0, 23 },
-       { "alarm_mday",    RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 1, 31 },
-       { NULL,            0,              0,                   0,  0 },
-};
-
-static const struct ds1685_rtc_time_regs
-ds1685_time_regs_bin_table[] = {
-       { "seconds",       RTC_SECS,       RTC_SECS_BIN_MASK,   0x00, 0x3b },
-       { "minutes",       RTC_MINS,       RTC_MINS_BIN_MASK,   0x00, 0x3b },
-       { "hours",         RTC_HRS,        RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
-       { "wday",          RTC_WDAY,       RTC_WDAY_MASK,       0x01, 0x07 },
-       { "mday",          RTC_MDAY,       RTC_MDAY_BIN_MASK,   0x01, 0x1f },
-       { "month",         RTC_MONTH,      RTC_MONTH_BIN_MASK,  0x01, 0x0c },
-       { "year",          RTC_YEAR,       RTC_YEAR_BIN_MASK,   0x00, 0x63 },
-       { "century",       RTC_CENTURY,    RTC_CENTURY_MASK,    0x00, 0x63 },
-       { "alarm_seconds", RTC_SECS_ALARM, RTC_SECS_BIN_MASK,   0x00, 0x3b },
-       { "alarm_minutes", RTC_MINS_ALARM, RTC_MINS_BIN_MASK,   0x00, 0x3b },
-       { "alarm_hours",   RTC_HRS_ALARM,  RTC_HRS_24_BIN_MASK, 0x00, 0x17 },
-       { "alarm_mday",    RTC_MDAY_ALARM, RTC_MDAY_ALARM_MASK, 0x01, 0x1f },
-       { NULL,            0,              0,                   0x00, 0x00 },
-};
-
-/**
- * ds1685_rtc_sysfs_time_regs_bcd_lookup - time/date reg bit lookup function.
- * @name: register bit to look up in ds1685_time_regs_bcd_table.
- */
-static const struct ds1685_rtc_time_regs*
-ds1685_rtc_sysfs_time_regs_lookup(const char *name, bool bcd_mode)
-{
-       const struct ds1685_rtc_time_regs *p;
-
-       if (bcd_mode)
-               p = ds1685_time_regs_bcd_table;
-       else
-               p = ds1685_time_regs_bin_table;
-
-       for (; p->name != NULL; ++p)
-               if (strcmp(p->name, name) == 0)
-                       return p;
-
-       return NULL;
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_show - reads a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 tmp;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_time_regs *bcd_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
-       const struct ds1685_rtc_time_regs *bin_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
-       /* Make sure we actually matched something. */
-       if (!bcd_reg_info || !bin_reg_info)
-               return -EINVAL;
-
-       /* bcd_reg_info->reg == bin_reg_info->reg. */
-       ds1685_rtc_begin_data_access(rtc);
-       tmp = rtc->read(rtc, bcd_reg_info->reg);
-       ds1685_rtc_end_data_access(rtc);
-
-       tmp = ds1685_rtc_bcd2bin(rtc, tmp, bcd_reg_info->mask,
-                                bin_reg_info->mask);
-
-       return sprintf(buf, "%d\n", tmp);
-}
-
-/**
- * ds1685_rtc_sysfs_time_regs_store - writes a time/date register via sysfs.
- * @dev: pointer to device structure.
- * @attr: pointer to device_attribute structure.
- * @buf: pointer to char array to hold the output.
- * @count: number of bytes written.
- */
-static ssize_t
-ds1685_rtc_sysfs_time_regs_store(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       long int val = 0;
-       struct ds1685_priv *rtc = dev_get_drvdata(dev);
-       const struct ds1685_rtc_time_regs *bcd_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, true);
-       const struct ds1685_rtc_time_regs *bin_reg_info =
-               ds1685_rtc_sysfs_time_regs_lookup(attr->attr.name, false);
-
-       /* We only accept numbers. */
-       if (kstrtol(buf, 10, &val) < 0)
-               return -EINVAL;
-
-       /* Make sure we actually matched something. */
-       if (!bcd_reg_info || !bin_reg_info)
-               return -EINVAL;
-
-       /* Check for a valid range. */
-       if (rtc->bcd_mode) {
-               if ((val < bcd_reg_info->min) || (val > bcd_reg_info->max))
-                       return -ERANGE;
-       } else {
-               if ((val < bin_reg_info->min) || (val > bin_reg_info->max))
-                       return -ERANGE;
-       }
-
-       val = ds1685_rtc_bin2bcd(rtc, val, bin_reg_info->mask,
-                                bcd_reg_info->mask);
-
-       /* bcd_reg_info->reg == bin_reg_info->reg. */
-       ds1685_rtc_begin_data_access(rtc);
-       rtc->write(rtc, bcd_reg_info->reg, val);
-       ds1685_rtc_end_data_access(rtc);
-
-       return count;
-}
-
-/**
- * DS1685_RTC_SYSFS_REG_RW - device_attribute for a read-write time register.
- * @reg: time/date register to read or write.
- */
-#define DS1685_RTC_SYSFS_TIME_REG_RW(reg)                              \
-       static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,                      \
-       ds1685_rtc_sysfs_time_regs_show,                                \
-       ds1685_rtc_sysfs_time_regs_store)
-
-/*
- * Time/Date Register bits.
- */
-DS1685_RTC_SYSFS_TIME_REG_RW(seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(wday);
-DS1685_RTC_SYSFS_TIME_REG_RW(mday);
-DS1685_RTC_SYSFS_TIME_REG_RW(month);
-DS1685_RTC_SYSFS_TIME_REG_RW(year);
-DS1685_RTC_SYSFS_TIME_REG_RW(century);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_seconds);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_minutes);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_hours);
-DS1685_RTC_SYSFS_TIME_REG_RW(alarm_mday);
-
-static struct attribute*
-ds1685_rtc_sysfs_time_attrs[] = {
-       &dev_attr_seconds.attr,
-       &dev_attr_minutes.attr,
-       &dev_attr_hours.attr,
-       &dev_attr_wday.attr,
-       &dev_attr_mday.attr,
-       &dev_attr_month.attr,
-       &dev_attr_year.attr,
-       &dev_attr_century.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_time_grp = {
-       .name = "datetime",
-       .attrs = ds1685_rtc_sysfs_time_attrs,
-};
-
-static struct attribute*
-ds1685_rtc_sysfs_alarm_attrs[] = {
-       &dev_attr_alarm_seconds.attr,
-       &dev_attr_alarm_minutes.attr,
-       &dev_attr_alarm_hours.attr,
-       &dev_attr_alarm_mday.attr,
-       NULL,
-};
-
-static const struct attribute_group
-ds1685_rtc_sysfs_alarm_grp = {
-       .name = "alarm",
-       .attrs = ds1685_rtc_sysfs_alarm_attrs,
-};
-#endif /* CONFIG_RTC_DS1685_SYSFS_REGS */
-
-
 /**
  * ds1685_rtc_sysfs_register - register sysfs files.
  * @dev: pointer to device structure.
@@ -1752,39 +1206,6 @@ ds1685_rtc_sysfs_register(struct device *dev)
        if (ret)
                return ret;
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
-       if (ret)
-               return ret;
-
-       ret = sysfs_create_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
-       if (ret)
-               return ret;
-#endif
        return 0;
 }
 
@@ -1798,17 +1219,6 @@ ds1685_rtc_sysfs_unregister(struct device *dev)
        sysfs_remove_bin_file(&dev->kobj, &ds1685_rtc_sysfs_nvram_attr);
        sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_misc_grp);
 
-#ifdef CONFIG_RTC_DS1685_SYSFS_REGS
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrla_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlb_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrlc_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrld_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4a_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_ctrl4b_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_time_grp);
-       sysfs_remove_group(&dev->kobj, &ds1685_rtc_sysfs_alarm_grp);
-#endif
-
        return 0;
 }
 #endif /* CONFIG_SYSFS */
index 1a2c38cc01785c573c5bfeccbf332290020296a9..ea18a8f4bce063a91587d4424c8d615788af5dfd 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
+#include "rtc-core.h"
+#include <linux/of_irq.h>
 
 /* Register map */
 /* rtc section */
 #define ISL1208_REG_SR_ARST    (1<<7)  /* auto reset */
 #define ISL1208_REG_SR_XTOSCB  (1<<6)  /* crystal oscillator */
 #define ISL1208_REG_SR_WRTC    (1<<4)  /* write rtc */
+#define ISL1208_REG_SR_EVT     (1<<3)  /* event */
 #define ISL1208_REG_SR_ALM     (1<<2)  /* alarm */
 #define ISL1208_REG_SR_BAT     (1<<1)  /* battery */
 #define ISL1208_REG_SR_RTCF    (1<<0)  /* rtc fail */
 #define ISL1208_REG_INT 0x08
 #define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
 #define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
-#define ISL1208_REG_09  0x09   /* reserved */
+#define ISL1219_REG_EV  0x09
+#define ISL1219_REG_EV_EVEN    (1<<4)   /* event detection enable */
+#define ISL1219_REG_EV_EVIENB  (1<<7)   /* event in pull-up disable */
 #define ISL1208_REG_ATR 0x0a
 #define ISL1208_REG_DTR 0x0b
 
 #define ISL1208_REG_USR2 0x13
 #define ISL1208_USR_SECTION_LEN 2
 
+/* event section */
+#define ISL1219_REG_SCT 0x14
+#define ISL1219_REG_MNT 0x15
+#define ISL1219_REG_HRT 0x16
+#define ISL1219_REG_DTT 0x17
+#define ISL1219_REG_MOT 0x18
+#define ISL1219_REG_YRT 0x19
+#define ISL1219_EVT_SECTION_LEN 6
+
 static struct i2c_driver isl1208_driver;
 
+/* ISL1208 various variants */
+enum {
+       TYPE_ISL1208 = 0,
+       TYPE_ISL1218,
+       TYPE_ISL1219,
+};
+
 /* block read */
 static int
 isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
@@ -80,8 +101,8 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
        };
        int ret;
 
-       BUG_ON(reg > ISL1208_REG_USR2);
-       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+       WARN_ON(reg > ISL1219_REG_YRT);
+       WARN_ON(reg + len > ISL1219_REG_YRT + 1);
 
        ret = i2c_transfer(client->adapter, msgs, 2);
        if (ret > 0)
@@ -104,8 +125,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
        };
        int ret;
 
-       BUG_ON(reg > ISL1208_REG_USR2);
-       BUG_ON(reg + len > ISL1208_REG_USR2 + 1);
+       WARN_ON(reg > ISL1219_REG_YRT);
+       WARN_ON(reg + len > ISL1219_REG_YRT + 1);
 
        i2c_buf[0] = reg;
        memcpy(&i2c_buf[1], &buf[0], len);
@@ -493,6 +514,73 @@ isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
        return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
 }
 
+static ssize_t timestamp0_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       int sr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       sr &= ~ISL1208_REG_SR_EVT;
+
+       sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+       if (sr < 0)
+               dev_err(dev, "%s: writing SR failed\n",
+                       __func__);
+
+       return count;
+};
+
+static ssize_t timestamp0_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = dev_get_drvdata(dev);
+       u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, };
+       struct rtc_time tm;
+       int sr;
+
+       sr = isl1208_i2c_get_sr(client);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading SR failed\n", __func__);
+               return sr;
+       }
+
+       if (!(sr & ISL1208_REG_SR_EVT))
+               return 0;
+
+       sr = isl1208_i2c_read_regs(client, ISL1219_REG_SCT, regs,
+                                  ISL1219_EVT_SECTION_LEN);
+       if (sr < 0) {
+               dev_err(dev, "%s: reading event section failed\n",
+                       __func__);
+               return 0;
+       }
+
+       /* MSB of each alarm register is an enable bit */
+       tm.tm_sec = bcd2bin(regs[ISL1219_REG_SCT - ISL1219_REG_SCT] & 0x7f);
+       tm.tm_min = bcd2bin(regs[ISL1219_REG_MNT - ISL1219_REG_SCT] & 0x7f);
+       tm.tm_hour = bcd2bin(regs[ISL1219_REG_HRT - ISL1219_REG_SCT] & 0x3f);
+       tm.tm_mday = bcd2bin(regs[ISL1219_REG_DTT - ISL1219_REG_SCT] & 0x3f);
+       tm.tm_mon =
+               bcd2bin(regs[ISL1219_REG_MOT - ISL1219_REG_SCT] & 0x1f) - 1;
+       tm.tm_year = bcd2bin(regs[ISL1219_REG_YRT - ISL1219_REG_SCT]) + 100;
+
+       sr = rtc_valid_tm(&tm);
+       if (sr)
+               return sr;
+
+       return sprintf(buf, "%llu\n",
+                               (unsigned long long)rtc_tm_to_time64(&tm));
+};
+
+static DEVICE_ATTR_RW(timestamp0);
+
 static irqreturn_t
 isl1208_rtc_interrupt(int irq, void *data)
 {
@@ -538,6 +626,13 @@ isl1208_rtc_interrupt(int irq, void *data)
                        return err;
        }
 
+       if (sr & ISL1208_REG_SR_EVT) {
+               sysfs_notify(&rtc->dev.kobj, NULL,
+                            dev_attr_timestamp0.attr.name);
+               dev_warn(&client->dev, "event detected");
+               handled = 1;
+       }
+
        return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -623,11 +718,39 @@ static const struct attribute_group isl1208_rtc_sysfs_files = {
        .attrs  = isl1208_rtc_attrs,
 };
 
+static struct attribute *isl1219_rtc_attrs[] = {
+       &dev_attr_timestamp0.attr,
+       NULL
+};
+
+static const struct attribute_group isl1219_rtc_sysfs_files = {
+       .attrs  = isl1219_rtc_attrs,
+};
+
+static int isl1208_setup_irq(struct i2c_client *client, int irq)
+{
+       int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
+                                       isl1208_rtc_interrupt,
+                                       IRQF_SHARED | IRQF_ONESHOT,
+                                       isl1208_driver.driver.name,
+                                       client);
+       if (!rc) {
+               device_init_wakeup(&client->dev, 1);
+               enable_irq_wake(irq);
+       } else {
+               dev_err(&client->dev,
+                       "Unable to request irq %d, no alarm support\n",
+                       irq);
+       }
+       return rc;
+}
+
 static int
 isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
        int rc = 0;
        struct rtc_device *rtc;
+       int evdet_irq = -1;
 
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
                return -ENODEV;
@@ -642,6 +765,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
        rtc->ops = &isl1208_rtc_ops;
 
        i2c_set_clientdata(client, rtc);
+       dev_set_drvdata(&rtc->dev, client);
 
        rc = isl1208_i2c_get_sr(client);
        if (rc < 0) {
@@ -653,26 +777,46 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
                dev_warn(&client->dev, "rtc power failure detected, "
                         "please set clock.\n");
 
+       if (id->driver_data == TYPE_ISL1219) {
+               struct device_node *np = client->dev.of_node;
+               u32 evienb;
+
+               rc = i2c_smbus_read_byte_data(client, ISL1219_REG_EV);
+               if (rc < 0) {
+                       dev_err(&client->dev, "failed to read EV reg\n");
+                       return rc;
+               }
+               rc |= ISL1219_REG_EV_EVEN;
+               if (!of_property_read_u32(np, "isil,ev-evienb", &evienb)) {
+                       if (evienb)
+                               rc |= ISL1219_REG_EV_EVIENB;
+                       else
+                               rc &= ~ISL1219_REG_EV_EVIENB;
+               }
+               rc = i2c_smbus_write_byte_data(client, ISL1219_REG_EV, rc);
+               if (rc < 0) {
+                       dev_err(&client->dev, "could not enable tamper detection\n");
+                       return rc;
+               }
+               rc = rtc_add_group(rtc, &isl1219_rtc_sysfs_files);
+               if (rc)
+                       return rc;
+               evdet_irq = of_irq_get_byname(np, "evdet");
+       }
+
        rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
        if (rc)
                return rc;
 
-       if (client->irq > 0) {
-               rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-                                              isl1208_rtc_interrupt,
-                                              IRQF_SHARED | IRQF_ONESHOT,
-                                              isl1208_driver.driver.name,
-                                              client);
-               if (!rc) {
-                       device_init_wakeup(&client->dev, 1);
-                       enable_irq_wake(client->irq);
-               } else {
-                       dev_err(&client->dev,
-                               "Unable to request irq %d, no alarm support\n",
-                               client->irq);
-                       client->irq = 0;
-               }
-       }
+       if (client->irq > 0)
+               rc = isl1208_setup_irq(client, client->irq);
+       if (rc)
+               return rc;
+
+       if (evdet_irq > 0 && evdet_irq != client->irq)
+               rc = isl1208_setup_irq(client, evdet_irq);
+       if (rc)
+               return rc;
 
        return rtc_register_device(rtc);
 }
@@ -686,8 +830,9 @@ isl1208_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id isl1208_id[] = {
-       { "isl1208", 0 },
-       { "isl1218", 0 },
+       { "isl1208", TYPE_ISL1208 },
+       { "isl1218", TYPE_ISL1218 },
+       { "isl1219", TYPE_ISL1219 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, isl1208_id);
@@ -695,6 +840,7 @@ MODULE_DEVICE_TABLE(i2c, isl1208_id);
 static const struct of_device_id isl1208_of_match[] = {
        { .compatible = "isil,isl1208" },
        { .compatible = "isil,isl1218" },
+       { .compatible = "isil,isl1219" },
        { }
 };
 MODULE_DEVICE_TABLE(of, isl1208_of_match);
index 1053a406b3aaa9cc5ffb3c2b5dad221102b82b66..ac9ca104288946dfcc5b06c12e122e004bf4dea3 100644 (file)
@@ -373,7 +373,6 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
        struct m48t59_private *m48t59 = NULL;
        struct resource *res;
        int ret = -ENOMEM;
-       char *name;
        const struct rtc_class_ops *ops;
        struct nvmem_config nvmem_cfg = {
                .name = "m48t59-",
@@ -448,17 +447,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
        }
        switch (pdata->type) {
        case M48T59RTC_TYPE_M48T59:
-               name = "m48t59";
                ops = &m48t59_rtc_ops;
                pdata->offset = 0x1ff0;
                break;
        case M48T59RTC_TYPE_M48T02:
-               name = "m48t02";
                ops = &m48t02_rtc_ops;
                pdata->offset = 0x7f0;
                break;
        case M48T59RTC_TYPE_M48T08:
-               name = "m48t08";
                ops = &m48t02_rtc_ops;
                pdata->offset = 0x1ff0;
                break;
index cefde273fae6e36494f3e79a7625424ea52422aa..8a60900d6b8b53af51d348355c065590bc6518a1 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX77686 and MAX77802
- *
- * Copyright (C) 2012 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8997.c
- *
- *  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 the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX77686 and MAX77802
+//
+// Copyright (C) 2012 Samsung Electronics Co.Ltd
+//
+//  based on rtc-max8997.c
 
 #include <linux/i2c.h>
 #include <linux/slab.h>
index e8cee123e8aae3b1c08774d6d01796dd34ef71be..08c661a332ec0e73b47e08522feb39ad1f8ff5ae 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8997
- *
- * Copyright (C) 2013 Samsung Electronics Co.Ltd
- *
- *  based on rtc-max8998.c
- *
- *  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 the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8997
+//
+// Copyright (C) 2013 Samsung Electronics Co.Ltd
+//
+//  based on rtc-max8998.c
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index d8c0f9b3f87d5e330c943a575eaca6b16b7345f7..c873b4509b3cfe9fa6a17ee826d67d586b7530a2 100644 (file)
@@ -1,16 +1,10 @@
-/*
- * RTC driver for Maxim MAX8998
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Minkyu Kang <mk7.kang@samsung.com>
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- *  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 the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// RTC driver for Maxim MAX8998
+//
+// Copyright (C) 2010 Samsung Electronics Co.Ltd
+// Author: Minkyu Kang <mk7.kang@samsung.com>
+// Author: Joonyoung Shim <jy0922.shim@samsung.com>
 
 #include <linux/module.h>
 #include <linux/i2c.h>
index 39086398833e0f8ea95d272f91e4f09fec7cf68f..323ff55cc16564833d75ed4b0fa682642ad4fc0f 100644 (file)
@@ -449,6 +449,7 @@ static void omap_rtc_power_off(void)
 
        if (tm2bcd(&tm) < 0) {
                dev_err(&rtc->rtc->dev, "power off failed\n");
+               rtc->type->lock(rtc);
                return;
        }
 
@@ -582,9 +583,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
        u32 val;
        u16 arg = 0;
 
-       rtc->type->unlock(rtc);
        val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
-       rtc->type->lock(rtc);
 
        switch (param) {
        case PIN_CONFIG_INPUT_ENABLE:
@@ -614,9 +613,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
        u32 param_val;
        int i;
 
-       rtc->type->unlock(rtc);
        val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
-       rtc->type->lock(rtc);
 
        /* active low by default */
        val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
@@ -861,13 +858,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
                        goto err;
        }
 
-       if (rtc->is_pmic_controller) {
-               if (!pm_power_off) {
-                       omap_rtc_power_off_rtc = rtc;
-                       pm_power_off = omap_rtc_power_off;
-               }
-       }
-
        /* Support ext_wakeup pinconf */
        rtc_pinctrl_desc.name = dev_name(&pdev->dev);
 
@@ -880,12 +870,21 @@ static int omap_rtc_probe(struct platform_device *pdev)
 
        ret = rtc_register_device(rtc->rtc);
        if (ret)
-               goto err;
+               goto err_deregister_pinctrl;
 
        rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
 
+       if (rtc->is_pmic_controller) {
+               if (!pm_power_off) {
+                       omap_rtc_power_off_rtc = rtc;
+                       pm_power_off = omap_rtc_power_off;
+               }
+       }
+
        return 0;
 
+err_deregister_pinctrl:
+       pinctrl_unregister(rtc->pctldev);
 err:
        clk_disable_unprepare(rtc->clk);
        device_init_wakeup(&pdev->dev, false);
index e83be1852c2fb276b25f1ff112e2be240e5aae0c..9f99a0966550b5e77672e83cc707eda26b22ede5 100644 (file)
 #define PCF2127_REG_MO          (0x08)
 #define PCF2127_REG_YR          (0x09)
 
+/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
+#define PCF2127_REG_RAM_addr_MSB       0x1a
+#define PCF2127_REG_RAM_wrt_cmd        0x1c
+#define PCF2127_REG_RAM_rd_cmd         0x1d
+
 #define PCF2127_OSF             BIT(7)  /* Oscillator Fail flag */
 
 struct pcf2127 {
@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
        .set_time       = pcf2127_rtc_set_time,
 };
 
+static int pcf2127_nvmem_read(void *priv, unsigned int offset,
+                             void *val, size_t bytes)
+{
+       struct pcf2127 *pcf2127 = priv;
+       int ret;
+       unsigned char offsetbuf[] = { offset >> 8, offset };
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+                               offsetbuf, 2);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
+                              val, bytes);
+
+       return ret ?: bytes;
+}
+
+static int pcf2127_nvmem_write(void *priv, unsigned int offset,
+                              void *val, size_t bytes)
+{
+       struct pcf2127 *pcf2127 = priv;
+       int ret;
+       unsigned char offsetbuf[] = { offset >> 8, offset };
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
+                               offsetbuf, 2);
+       if (ret)
+               return ret;
+
+       ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
+                               val, bytes);
+
+       return ret ?: bytes;
+}
+
 static int pcf2127_probe(struct device *dev, struct regmap *regmap,
-                       const char *name)
+                       const char *name, bool has_nvmem)
 {
        struct pcf2127 *pcf2127;
+       int ret = 0;
 
        dev_dbg(dev, "%s\n", __func__);
 
@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
 
        pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
                                                THIS_MODULE);
+       if (IS_ERR(pcf2127->rtc))
+               return PTR_ERR(pcf2127->rtc);
+
+       if (has_nvmem) {
+               struct nvmem_config nvmem_cfg = {
+                       .priv = pcf2127,
+                       .reg_read = pcf2127_nvmem_read,
+                       .reg_write = pcf2127_nvmem_write,
+                       .size = 512,
+               };
+
+               ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
+       }
 
-       return PTR_ERR_OR_ZERO(pcf2127->rtc);
+       return ret;
 }
 
 #ifdef CONFIG_OF
@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
        }
 
        return pcf2127_probe(&client->dev, regmap,
-                               pcf2127_i2c_driver.driver.name);
+                            pcf2127_i2c_driver.driver.name, id->driver_data);
 }
 
 static const struct i2c_device_id pcf2127_i2c_id[] = {
-       { "pcf2127", 0 },
+       { "pcf2127", 1 },
        { "pcf2129", 0 },
        { }
 };
@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
                return PTR_ERR(regmap);
        }
 
-       return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
+       return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
+                            spi_get_device_id(spi)->driver_data);
 }
 
 static const struct spi_device_id pcf2127_spi_id[] = {
-       { "pcf2127", 0 },
+       { "pcf2127", 1 },
        { "pcf2129", 0 },
        { }
 };
index 49bcbb3d4a696160798a3bbaa36a2be8e8e81db2..283c2335b01b69b54a636680ec88d88852b11aa6 100644 (file)
@@ -43,37 +43,38 @@ static struct i2c_driver pcf85063_driver;
 
 static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
 {
-       s32 ret;
+       int rc;
+       u8 reg;
 
-       ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
-       if (ret < 0) {
+       rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to stop the clock\n");
                return -EIO;
        }
 
        /* stop the clock */
-       ret |= PCF85063_REG_CTRL1_STOP;
+       reg = rc | PCF85063_REG_CTRL1_STOP;
 
-       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret);
-       if (ret < 0) {
+       rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to stop the clock\n");
                return -EIO;
        }
 
-       *ctrl1 = ret;
+       *ctrl1 = reg;
 
        return 0;
 }
 
 static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
 {
-       s32 ret;
+       int rc;
 
        /* start the clock */
        ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
 
-       ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
-       if (ret < 0) {
+       rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
+       if (rc < 0) {
                dev_err(&client->dev, "Failing to start the clock\n");
                return -EIO;
        }
index 8428455432ca77c89790256cab801ab055c3fdd0..6495f84f74288cfda5e2a26274dbdedb152531b2 100644 (file)
@@ -1,19 +1,9 @@
-/*
- * Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
- *     http://www.samsung.com
- *
- *  Copyright (C) 2013 Google, Inc
- *
- *  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
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
+//     http://www.samsung.com
+//
+//  Copyright (C) 2013 Google, Inc
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
index ed71d11136276d1259e976bb0814909726d1f75a..304d905cb23fd20240cdb8b4953310cb5d1a1609 100644 (file)
@@ -224,7 +224,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
        info->rtc = rtc;
 
        rtc->max_user_freq = RTC_FREQ;
-       rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
        /* Fix for a nasty initialization problem the in SA11xx RTSR register.
         * See also the comments in sa1100_rtc_interrupt().
index 776b70a14e036e45808a86442577adb2d00645a7..51ba414798a83f0a2dfd1b6610fbf5dbaf4375d4 100644 (file)
@@ -143,8 +143,6 @@ static int __sh_rtc_alarm(struct sh_rtc *rtc)
 
 static int __sh_rtc_periodic(struct sh_rtc *rtc)
 {
-       struct rtc_device *rtc_dev = rtc->rtc_dev;
-       struct rtc_task *irq_task;
        unsigned int tmp, pending;
 
        tmp = readb(rtc->regbase + RCR2);
@@ -161,14 +159,7 @@ static int __sh_rtc_periodic(struct sh_rtc *rtc)
        else {
                if (rtc->periodic_freq & PF_HP)
                        rtc->periodic_freq |= PF_COUNT;
-               if (rtc->periodic_freq & PF_KOU) {
-                       spin_lock(&rtc_dev->irq_task_lock);
-                       irq_task = rtc_dev->irq_task;
-                       if (irq_task)
-                               irq_task->func(irq_task->private_data);
-                       spin_unlock(&rtc_dev->irq_task_lock);
-               } else
-                       rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
+               rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
        }
 
        return pending;
@@ -224,81 +215,6 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
        return IRQ_RETVAL(ret);
 }
 
-static int sh_rtc_irq_set_state(struct device *dev, int enable)
-{
-       struct sh_rtc *rtc = dev_get_drvdata(dev);
-       unsigned int tmp;
-
-       spin_lock_irq(&rtc->lock);
-
-       tmp = readb(rtc->regbase + RCR2);
-
-       if (enable) {
-               rtc->periodic_freq |= PF_KOU;
-               tmp &= ~RCR2_PEF;       /* Clear PES bit */
-               tmp |= (rtc->periodic_freq & ~PF_HP);   /* Set PES2-0 */
-       } else {
-               rtc->periodic_freq &= ~PF_KOU;
-               tmp &= ~(RCR2_PESMASK | RCR2_PEF);
-       }
-
-       writeb(tmp, rtc->regbase + RCR2);
-
-       spin_unlock_irq(&rtc->lock);
-
-       return 0;
-}
-
-static int sh_rtc_irq_set_freq(struct device *dev, int freq)
-{
-       struct sh_rtc *rtc = dev_get_drvdata(dev);
-       int tmp, ret = 0;
-
-       spin_lock_irq(&rtc->lock);
-       tmp = rtc->periodic_freq & PF_MASK;
-
-       switch (freq) {
-       case 0:
-               rtc->periodic_freq = 0x00;
-               break;
-       case 1:
-               rtc->periodic_freq = 0x60;
-               break;
-       case 2:
-               rtc->periodic_freq = 0x50;
-               break;
-       case 4:
-               rtc->periodic_freq = 0x40;
-               break;
-       case 8:
-               rtc->periodic_freq = 0x30 | PF_HP;
-               break;
-       case 16:
-               rtc->periodic_freq = 0x30;
-               break;
-       case 32:
-               rtc->periodic_freq = 0x20 | PF_HP;
-               break;
-       case 64:
-               rtc->periodic_freq = 0x20;
-               break;
-       case 128:
-               rtc->periodic_freq = 0x10 | PF_HP;
-               break;
-       case 256:
-               rtc->periodic_freq = 0x10;
-               break;
-       default:
-               ret = -ENOTSUPP;
-       }
-
-       if (ret == 0)
-               rtc->periodic_freq |= tmp;
-
-       spin_unlock_irq(&rtc->lock);
-       return ret;
-}
-
 static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
 {
        struct sh_rtc *rtc = dev_get_drvdata(dev);
@@ -675,8 +591,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rtc);
 
        /* everything disabled by default */
-       sh_rtc_irq_set_freq(&pdev->dev, 0);
-       sh_rtc_irq_set_state(&pdev->dev, 0);
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
@@ -708,8 +622,6 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
 {
        struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
-       sh_rtc_irq_set_state(&pdev->dev, 0);
-
        sh_rtc_setaie(&pdev->dev, 0);
        sh_rtc_setcie(&pdev->dev, 0);
 
index 8a75cc3af6e706f23b0b33767e960fae0d2d4fae..b2483a749ac45fa58c4f9a7dd507ca19775222ca 100644 (file)
@@ -40,49 +40,83 @@ struct snvs_rtc_data {
        struct clk *clk;
 };
 
+/* Read 64 bit timer register, which could be in inconsistent state */
+static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
+{
+       u32 msb, lsb;
+
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
+       return (u64)msb << 32 | lsb;
+}
+
+/* Read the secure real time counter, taking care to deal with the cases of the
+ * counter updating while being read.
+ */
 static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
 {
        u64 read1, read2;
-       u32 val;
+       unsigned int timeout = 100;
 
+       /* As expected, the registers might update between the read of the LSB
+        * reg and the MSB reg.  It's also possible that one register might be
+        * in partially modified state as well.
+        */
+       read1 = rtc_read_lpsrt(data);
        do {
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-               read1 = val;
-               read1 <<= 32;
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-               read1 |= val;
-
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
-               read2 = val;
-               read2 <<= 32;
-               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
-               read2 |= val;
-       } while (read1 != read2);
+               read2 = read1;
+               read1 = rtc_read_lpsrt(data);
+       } while (read1 != read2 && --timeout);
+       if (!timeout)
+               dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
 
        /* Convert 47-bit counter to 32-bit raw second count */
        return (u32) (read1 >> CNTR_TO_SECS_SH);
 }
 
-static void rtc_write_sync_lp(struct snvs_rtc_data *data)
+/* Just read the lsb from the counter, dealing with inconsistent state */
+static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
+{
+       u32 count1, count2;
+       unsigned int timeout = 100;
+
+       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+       do {
+               count2 = count1;
+               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+       } while (count1 != count2 && --timeout);
+       if (!timeout) {
+               dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+               return -ETIMEDOUT;
+       }
+
+       *lsb = count1;
+       return 0;
+}
+
+static int rtc_write_sync_lp(struct snvs_rtc_data *data)
 {
-       u32 count1, count2, count3;
-       int i;
-
-       /* Wait for 3 CKIL cycles */
-       for (i = 0; i < 3; i++) {
-               do {
-                       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-                       regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-               } while (count1 != count2);
-
-               /* Now wait until counter value changes */
-               do {
-                       do {
-                               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
-                               regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
-                       } while (count2 != count3);
-               } while (count3 == count1);
+       u32 count1, count2;
+       u32 elapsed;
+       unsigned int timeout = 1000;
+       int ret;
+
+       ret = rtc_read_lp_counter_lsb(data, &count1);
+       if (ret)
+               return ret;
+
+       /* Wait for 3 CKIL cycles, about 61.0-91.5 ┬Ás */
+       do {
+               ret = rtc_read_lp_counter_lsb(data, &count2);
+               if (ret)
+                       return ret;
+               elapsed = count2 - count1; /* wrap around _is_ handled! */
+       } while (elapsed < 3 && --timeout);
+       if (!timeout) {
+               dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
+               return -ETIMEDOUT;
        }
+       return 0;
 }
 
 static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
@@ -166,9 +200,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
                           (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
                           enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
 
-       rtc_write_sync_lp(data);
-
-       return 0;
+       return rtc_write_sync_lp(data);
 }
 
 static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -176,11 +208,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct snvs_rtc_data *data = dev_get_drvdata(dev);
        struct rtc_time *alrm_tm = &alrm->time;
        unsigned long time;
+       int ret;
 
        rtc_tm_to_time(alrm_tm, &time);
 
        regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
-       rtc_write_sync_lp(data);
+       ret = rtc_write_sync_lp(data);
+       if (ret)
+               return ret;
        regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
 
        /* Clear alarm interrupt status bit */
index d578e40d5a506308a76307a5050fd61552fc9420..b76318fd5bb004b4fa492de45df151e9b46b9a35 100644 (file)
@@ -288,10 +288,22 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, rtc_data);
 
-       err = stmp_reset_block(rtc_data->io);
-       if (err) {
-               dev_err(&pdev->dev, "stmp_reset_block failed: %d\n", err);
-               return err;
+       /*
+        * Resetting the rtc stops the watchdog timer that is potentially
+        * running. So (assuming it is running on purpose) don't reset if the
+        * watchdog is enabled.
+        */
+       if (readl(rtc_data->io + STMP3XXX_RTC_CTRL) &
+           STMP3XXX_RTC_CTRL_WATCHDOGEN) {
+               dev_info(&pdev->dev,
+                        "Watchdog is running, skip resetting rtc\n");
+       } else {
+               err = stmp_reset_block(rtc_data->io);
+               if (err) {
+                       dev_err(&pdev->dev, "stmp_reset_block failed: %d\n",
+                               err);
+                       return err;
+               }
        }
 
        /*
index 454da38c60122d3a91ffb3fef3369b7de3f6e203..f1ff30ade5343b07ff54d05bcd82fddbc3bea0d6 100644 (file)
@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
 {
        return rtc_attr_groups;
 }
+
+int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
+{
+       size_t old_cnt = 0, add_cnt = 0, new_cnt;
+       const struct attribute_group **groups, **old;
+
+       if (rtc->registered)
+               return -EINVAL;
+       if (!grps)
+               return -EINVAL;
+
+       groups = rtc->dev.groups;
+       if (groups)
+               for (; *groups; groups++)
+                       old_cnt++;
+
+       for (groups = grps; *groups; groups++)
+               add_cnt++;
+
+       new_cnt = old_cnt + add_cnt + 1;
+       groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
+       if (IS_ERR_OR_NULL(groups))
+               return PTR_ERR(groups);
+       memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
+       memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
+       groups[old_cnt + add_cnt] = NULL;
+
+       old = rtc->dev.groups;
+       rtc->dev.groups = groups;
+       if (old && old != rtc_attr_groups)
+               devm_kfree(&rtc->dev, old);
+
+       return 0;
+}
+EXPORT_SYMBOL(rtc_add_groups);
+
+int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
+{
+       const struct attribute_group *groups[] = { grp, NULL };
+
+       return rtc_add_groups(rtc, groups);
+}
+EXPORT_SYMBOL(rtc_add_group);
index 8469256edc2af906fa8991b7fd910348f3761f7b..ade6a82709bee792c912dcc6f81c26f6f8b56d5b 100644 (file)
@@ -22,7 +22,7 @@ struct rtc_test_data {
        bool alarm_en;
 };
 
-struct platform_device *pdev[MAX_RTC_TEST];
+static struct platform_device *pdev[MAX_RTC_TEST];
 
 static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
index 6268208760e9587acac1114a4ce071e4bbacb160..6aedc30003e731576ae87857666b2abe5b510187 100644 (file)
@@ -87,16 +87,11 @@ struct rtc_class_ops {
        int (*set_offset)(struct device *, long offset);
 };
 
-typedef struct rtc_task {
-       void (*func)(void *private_data);
-       void *private_data;
-} rtc_task_t;
-
-
 struct rtc_timer {
-       struct rtc_task task;
        struct timerqueue_node node;
        ktime_t period;
+       void (*func)(void *private_data);
+       void *private_data;
        int enabled;
 };
 
@@ -121,8 +116,6 @@ struct rtc_device {
        wait_queue_head_t irq_queue;
        struct fasync_struct *async_queue;
 
-       struct rtc_task *irq_task;
-       spinlock_t irq_task_lock;
        int irq_freq;
        int max_user_freq;
 
@@ -204,14 +197,8 @@ extern void rtc_update_irq(struct rtc_device *rtc,
 extern struct rtc_device *rtc_class_open(const char *name);
 extern void rtc_class_close(struct rtc_device *rtc);
 
-extern int rtc_irq_register(struct rtc_device *rtc,
-                               struct rtc_task *task);
-extern void rtc_irq_unregister(struct rtc_device *rtc,
-                               struct rtc_task *task);
-extern int rtc_irq_set_state(struct rtc_device *rtc,
-                               struct rtc_task *task, int enabled);
-extern int rtc_irq_set_freq(struct rtc_device *rtc,
-                               struct rtc_task *task, int freq);
+extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled);
+extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq);
 extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
 extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
 extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,