]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'rtc/rtc-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Mon, 2 Nov 2015 03:22:13 +0000 (14:22 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Mon, 2 Nov 2015 03:22:13 +0000 (14:22 +1100)
21 files changed:
Documentation/devicetree/bindings/rtc/dallas,ds1390.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/pcf8563.txt [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/rtc-ab8500.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-da9063.c
drivers/rtc/rtc-davinci.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1343.c
drivers/rtc/rtc-ds1390.c
drivers/rtc/rtc-isl12057.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-opal.c
drivers/rtc/rtc-pcf2127.c
drivers/rtc/rtc-pcf85063.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pl031.c
drivers/rtc/rtc-rx8025.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-stmp3xxx.c
tools/testing/selftests/timers/rtctest.c

diff --git a/Documentation/devicetree/bindings/rtc/dallas,ds1390.txt b/Documentation/devicetree/bindings/rtc/dallas,ds1390.txt
new file mode 100644 (file)
index 0000000..8e76f26
--- /dev/null
@@ -0,0 +1,18 @@
+* Dallas DS1390                SPI Serial Real-Time Clock
+
+Required properties:
+- compatible: Should contain "dallas,ds1390".
+- reg: SPI address for chip
+
+Optional properties:
+- trickle-resistor-ohms : Selected resistor for trickle charger
+       Values usable for ds1390 are 250, 2000, 4000
+       Should be given if trickle charger should be enabled
+- trickle-diode-disable : Do not use internal trickle charger diode
+       Should be given if internal trickle charger diode should be disabled
+Example:
+       ds1390: rtc@68 {
+               compatible = "dallas,ds1390";
+               trickle-resistor-ohms = <250>;
+               reg = <0>;
+       };
diff --git a/Documentation/devicetree/bindings/rtc/pcf8563.txt b/Documentation/devicetree/bindings/rtc/pcf8563.txt
new file mode 100644 (file)
index 0000000..72f6d2c
--- /dev/null
@@ -0,0 +1,25 @@
+* Philips PCF8563/Epson RTC8564 Real Time Clock
+
+Philips PCF8563/Epson RTC8564 Real Time Clock
+
+Required properties:
+see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+
+Optional property:
+- #clock-cells: Should be 0.
+- clock-output-names:
+  overwrite the default clock name "pcf8563-clkout"
+
+Example:
+
+pcf8563: pcf8563@51 {
+       compatible = "nxp,pcf8563";
+       reg = <0x51>;
+       #clock-cells = <0>;
+};
+
+device {
+...
+       clocks = <&pcf8563>;
+...
+};
index 9d4290617cee5ab2969999ddb098db46b30f8e9d..57c2dbc4f438a9c18b32df68bece3fa467c374e6 100644 (file)
@@ -666,8 +666,8 @@ config RTC_DRV_DS1390
          If you say yes here you get support for the
          Dallas/Maxim DS1390/93/94 chips.
 
-         This driver only supports the RTC feature, and not other chip
-         features such as alarms and trickle charging.
+         This driver supports the RTC feature and trickle charging but not
+         other chip features such as alarms.
 
          This driver can also be built as a module. If so, the module
          will be called rtc-ds1390.
index 51407c4c7bd2be69ccb287575880ada7870bbcd0..24a0af650a1bcf6b0c514a3cd186fb5e079ef278 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/pm_wakeirq.h>
 
 #define AB8500_RTC_SOFF_STAT_REG       0x00
 #define AB8500_RTC_CC_CONF_REG         0x01
@@ -493,11 +494,12 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
        }
 
        err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-                       rtc_alarm_handler, IRQF_NO_SUSPEND | IRQF_ONESHOT,
+                       rtc_alarm_handler, IRQF_ONESHOT,
                        "ab8500-rtc", rtc);
        if (err < 0)
                return err;
 
+       dev_pm_set_wake_irq(&pdev->dev, irq);
        platform_set_drvdata(pdev, rtc);
 
        err = ab8500_sysfs_rtc_register(&pdev->dev);
@@ -513,6 +515,8 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
 
 static int ab8500_rtc_remove(struct platform_device *pdev)
 {
+       dev_pm_clear_wake_irq(&pdev->dev);
+       device_init_wakeup(&pdev->dev, false);
        ab8500_sysfs_rtc_unregister(&pdev->dev);
 
        return 0;
index cb62e214b52a0066f0a0402c7d89d8b0de74b4fb..b60fd477778f7fed1e8c1a510d80646f47d8373f 100644 (file)
@@ -495,6 +495,8 @@ static int at91_rtc_suspend(struct device *dev)
        /* this IRQ is shared with DBGU and other hardware which isn't
         * necessarily doing PM like we are...
         */
+       at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM);
+
        at91_rtc_imr = at91_rtc_read_imr()
                        & (AT91_RTC_ALARM|AT91_RTC_SECEV);
        if (at91_rtc_imr) {
index 00a8f7f4f87cbc58426f11bb8cf83dfcf38ab90e..284b587da65c5fb20f6e96b8c843e52c0b420415 100644 (file)
@@ -1,15 +1,15 @@
 /* rtc-da9063.c - Real time clock device driver for DA9063
- * Copyright (C) 2013-14  Dialog Semiconductor Ltd.
+ * Copyright (C) 2013-2015  Dialog Semiconductor Ltd.
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library 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 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 library is distributed in the hope that it will be useful,
+ * 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
- * Library General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #include <linux/delay.h>
@@ -516,5 +516,5 @@ module_platform_driver(da9063_rtc_driver);
 
 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
 MODULE_DESCRIPTION("Real time clock device driver for Dialog DA9063");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DA9063_DRVNAME_RTC);
index c84f46168a52afa92772d91429d97929c79334da..c5432bf64e1c317324f009353ca7961e97e8fb63 100644 (file)
@@ -546,7 +546,6 @@ static int __exit davinci_rtc_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver davinci_rtc_driver = {
-       .probe          = davinci_rtc_probe,
        .remove         = __exit_p(davinci_rtc_remove),
        .driver         = {
                .name = "rtc_davinci",
index a705e6490808f277e21102bf208a5e77c1d35bb1..188006c55ce0708771709199b183aff93c16c3b1 100644 (file)
@@ -718,9 +718,9 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        regs[3] = bin2bcd(t->time.tm_sec);
        regs[4] = bin2bcd(t->time.tm_min);
        regs[5] = bin2bcd(t->time.tm_hour);
-       regs[6] = bin2bcd(t->time.tm_wday) + 1;
+       regs[6] = bin2bcd(t->time.tm_wday + 1);
        regs[7] = bin2bcd(t->time.tm_mday);
-       regs[8] = bin2bcd(t->time.tm_mon) + 1;
+       regs[8] = bin2bcd(t->time.tm_mon + 1);
 
        /* Clear the alarm 0 interrupt flag. */
        regs[6] &= ~MCP794XX_BIT_ALMX_IF;
index 07371a9e37936b7290febc3a0ec08a3c30e37da2..3d389bd8a289590561d45a0dc3a82697fd659bf4 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/rtc.h>
 #include <linux/bcd.h>
 #include <linux/pm.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 
 #define DS1343_DRV_VERSION     "01.00"
@@ -663,15 +664,15 @@ static int ds1343_probe(struct spi_device *spi)
 
        if (priv->irq >= 0) {
                res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
-                                               ds1343_thread,
-                                               IRQF_NO_SUSPEND | IRQF_ONESHOT,
+                                               ds1343_thread, IRQF_ONESHOT,
                                                "ds1343", priv);
                if (res) {
                        priv->irq = -1;
                        dev_err(&spi->dev,
                                "unable to request irq for rtc ds1343\n");
                } else {
-                       device_set_wakeup_capable(&spi->dev, 1);
+                       device_init_wakeup(&spi->dev, true);
+                       dev_pm_set_wake_irq(&spi->dev, spi->irq);
                }
        }
 
@@ -692,6 +693,8 @@ static int ds1343_remove(struct spi_device *spi)
                priv->irqen &= ~RTC_AF;
                mutex_unlock(&priv->mutex);
 
+               dev_pm_clear_wake_irq(&spi->dev);
+               device_init_wakeup(&spi->dev, false);
                devm_free_irq(&spi->dev, spi->irq, priv);
        }
 
index 4c229c97ef9749ea844685d7923f4cf7fc7f3596..aa0d2c6f1edc235d00d2da56be0d55b9d88ed44a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/spi/spi.h>
 #include <linux/bcd.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #define DS1390_REG_100THS              0x00
 #define DS1390_REG_SECONDS             0x01
 #define DS1390_REG_STATUS              0x0E
 #define DS1390_REG_TRICKLE             0x0F
 
+#define DS1390_TRICKLE_CHARGER_ENABLE  0xA0
+#define DS1390_TRICKLE_CHARGER_250_OHM 0x01
+#define DS1390_TRICKLE_CHARGER_2K_OHM  0x02
+#define DS1390_TRICKLE_CHARGER_4K_OHM  0x03
+#define DS1390_TRICKLE_CHARGER_NO_DIODE        0x04
+#define DS1390_TRICKLE_CHARGER_DIODE   0x08
+
 struct ds1390 {
        struct rtc_device *rtc;
        u8 txrx_buf[9]; /* cmd + 8 registers */
 };
 
+static void ds1390_set_reg(struct device *dev, unsigned char address,
+                          unsigned char data)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       unsigned char buf[2];
+
+       /* MSB must be '1' to write */
+       buf[0] = address | 0x80;
+       buf[1] = data;
+
+       spi_write(spi, buf, 2);
+}
+
 static int ds1390_get_reg(struct device *dev, unsigned char address,
                                unsigned char *data)
 {
@@ -62,11 +83,50 @@ static int ds1390_get_reg(struct device *dev, unsigned char address,
        if (status != 0)
                return status;
 
-       *data = chip->txrx_buf[1];
+       *data = chip->txrx_buf[0];
 
        return 0;
 }
 
+static void ds1390_trickle_of_init(struct spi_device *spi)
+{
+       u32 ohms = 0;
+       u8 value;
+
+       if (of_property_read_u32(spi->dev.of_node, "trickle-resistor-ohms",
+                                &ohms))
+               goto out;
+
+       /* Enable charger */
+       value = DS1390_TRICKLE_CHARGER_ENABLE;
+       if (of_property_read_bool(spi->dev.of_node, "trickle-diode-disable"))
+               value |= DS1390_TRICKLE_CHARGER_NO_DIODE;
+       else
+               value |= DS1390_TRICKLE_CHARGER_DIODE;
+
+       /* Resistor select */
+       switch (ohms) {
+       case 250:
+               value |= DS1390_TRICKLE_CHARGER_250_OHM;
+               break;
+       case 2000:
+               value |= DS1390_TRICKLE_CHARGER_2K_OHM;
+               break;
+       case 4000:
+               value |= DS1390_TRICKLE_CHARGER_4K_OHM;
+               break;
+       default:
+               dev_warn(&spi->dev,
+                        "Unsupported ohm value %02ux in dt\n", ohms);
+               return;
+       }
+
+       ds1390_set_reg(&spi->dev, DS1390_REG_TRICKLE, value);
+
+out:
+       return;
+}
+
 static int ds1390_read_time(struct device *dev, struct rtc_time *dt)
 {
        struct spi_device *spi = to_spi_device(dev);
@@ -143,6 +203,9 @@ static int ds1390_probe(struct spi_device *spi)
                return res;
        }
 
+       if (spi->dev.of_node)
+               ds1390_trickle_of_init(spi);
+
        chip->rtc = devm_rtc_device_register(&spi->dev, "ds1390",
                                        &ds1390_rtc_ops, THIS_MODULE);
        if (IS_ERR(chip->rtc)) {
index a0462e5430c79c2378fef402b4a5270e18cdefa9..54328d4ac0d31061a4afd76d5651279ef526449b 100644 (file)
@@ -466,9 +466,8 @@ static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap)
  * is for instance the case on ReadyNAS 102, 104 and 2120. On those
  * devices with no IRQ driectly connected to the SoC, the RTC chip
  * can be forced as a wakeup source by stating that explicitly in
- * the device's .dts file using the "isil,irq2-can-wakeup-machine"
- * boolean property. This will guarantee 'wakealarm' sysfs entry is
- * available on the device.
+ * the device's .dts file using the "wakeup-source" boolean property.
+ * This will guarantee 'wakealarm' sysfs entry is available on the device.
  *
  * The function below returns 1, i.e. the capability of the chip to
  * wakeup the device, based on IRQ availability or if the boolean
@@ -479,8 +478,9 @@ static bool isl12057_can_wakeup_machine(struct device *dev)
 {
        struct isl12057_rtc_data *data = dev_get_drvdata(dev);
 
-       return (data->irq || of_property_read_bool(dev->of_node,
-                                             "isil,irq2-can-wakeup-machine"));
+       return data->irq || of_property_read_bool(dev->of_node, "wakeup-source")
+               || of_property_read_bool(dev->of_node, /* legacy */
+                                        "isil,irq2-can-wakeup-machine");
 }
 #else
 static bool isl12057_can_wakeup_machine(struct device *dev)
index aa3b8f1b34d932a90256b13e99b0a6d53ec5c5cc..b57a304ff62c65ff4877d7c27c81b37a5a872bcb 100644 (file)
@@ -638,7 +638,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
        if (client->irq > 0) {
                rc = devm_request_threaded_irq(&client->dev, client->irq, NULL,
                                               isl1208_rtc_interrupt,
-                                              IRQF_SHARED,
+                                              IRQF_SHARED | IRQF_ONESHOT,
                                               isl1208_driver.driver.name,
                                               client);
                if (!rc) {
index 6fbf9e617151d1d2376816e725c2c55e8b7e61eb..df39ce02a99d33f9b5c606b187ab374567290dae 100644 (file)
@@ -152,10 +152,10 @@ exit:
 /* Set Timed Power-On */
 static int opal_set_tpo_time(struct device *dev, struct rtc_wkalrm *alarm)
 {
-       u64 h_m_s_ms = 0, token;
+       u64 h_m_s_ms = 0;
        struct opal_msg msg;
        u32 y_m_d = 0;
-       int rc;
+       int token, rc;
 
        tm_to_opal(&alarm->time, &y_m_d, &h_m_s_ms);
 
@@ -199,8 +199,9 @@ static int opal_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
 
-       if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
-                                                NULL)) {
+       if (pdev->dev.of_node &&
+           (of_property_read_bool(pdev->dev.of_node, "wakeup-source") ||
+            of_property_read_bool(pdev->dev.of_node, "has-tpo")/* legacy */)) {
                device_set_wakeup_capable(&pdev->dev, true);
                opal_rtc_ops.read_alarm = opal_get_tpo_time;
                opal_rtc_ops.set_alarm = opal_set_tpo_time;
index 4b11d31f71740b4de9897ec46be1ec0b4cb39835..629bfdf8c74540ac81a0c538f4b79e301bec8638 100644 (file)
 #include <linux/module.h>
 #include <linux/of.h>
 
-#define DRV_VERSION "0.0.1"
-
 #define PCF2127_REG_CTRL1       (0x00)  /* Control Register 1 */
 #define PCF2127_REG_CTRL2       (0x01)  /* Control Register 2 */
+
 #define PCF2127_REG_CTRL3       (0x02)  /* Control Register 3 */
+#define PCF2127_REG_CTRL3_BLF          BIT(2)
+
 #define PCF2127_REG_SC          (0x03)  /* datetime */
 #define PCF2127_REG_MN          (0x04)
 #define PCF2127_REG_HR          (0x05)
@@ -39,8 +40,6 @@ static struct i2c_driver pcf2127_driver;
 
 struct pcf2127 {
        struct rtc_device *rtc;
-       int voltage_low; /* indicates if a low_voltage was detected */
-       int oscillator_failed; /* OSF was detected and date is unreliable */
 };
 
 /*
@@ -49,7 +48,6 @@ struct pcf2127 {
  */
 static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-       struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
        unsigned char buf[10] = { PCF2127_REG_CTRL1 };
 
        /* read registers */
@@ -59,18 +57,15 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
                return -EIO;
        }
 
-       if (buf[PCF2127_REG_CTRL3] & 0x04) {
-               pcf2127->voltage_low = 1;
+       if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
                dev_info(&client->dev,
                        "low voltage detected, check/replace RTC battery.\n");
-       }
 
        if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
                /*
                 * no need clear the flag here,
                 * it will be cleared once the new date is saved
                 */
-               pcf2127->oscillator_failed = 1;
                dev_warn(&client->dev,
                         "oscillator stop detected, date/time is not reliable\n");
                return -EINVAL;
@@ -107,7 +102,6 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 
 static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
-       struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
        unsigned char buf[8];
        int i = 0, err;
 
@@ -141,9 +135,6 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                return -EIO;
        }
 
-       /* clear OSF flag in client data */
-       pcf2127->oscillator_failed = 0;
-
        return 0;
 }
 
@@ -151,17 +142,28 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int pcf2127_rtc_ioctl(struct device *dev,
                                unsigned int cmd, unsigned long arg)
 {
-       struct pcf2127 *pcf2127 = i2c_get_clientdata(to_i2c_client(dev));
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned char buf = PCF2127_REG_CTRL3;
+       int touser;
+       int ret;
 
        switch (cmd) {
        case RTC_VL_READ:
-               if (pcf2127->voltage_low)
-                       dev_info(dev, "low voltage detected, check/replace battery\n");
-               if (pcf2127->oscillator_failed)
-                       dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
+               ret = i2c_master_send(client, &buf, 1);
+               if (!ret)
+                       ret = -EIO;
+               if (ret < 0)
+                       return ret;
+
+               ret = i2c_master_recv(client, &buf, 1);
+               if (!ret)
+                       ret = -EIO;
+               if (ret < 0)
+                       return ret;
 
-               if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
-                                       sizeof(int)))
+               touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
+
+               if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
                        return -EFAULT;
                return 0;
        default:
@@ -203,8 +205,6 @@ static int pcf2127_probe(struct i2c_client *client,
        if (!pcf2127)
                return -ENOMEM;
 
-       dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
-
        i2c_set_clientdata(client, pcf2127);
 
        pcf2127->rtc = devm_rtc_device_register(&client->dev,
@@ -241,5 +241,4 @@ module_i2c_driver(pcf2127_driver);
 
 MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
 MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
index b6d73dd881f248bce67976754fb5f932477d5686..63334cbeca41d8233b55e674e120ec4bd895a45a 100644 (file)
@@ -80,13 +80,7 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
                (tm->tm_year >= 100) : (tm->tm_year < 100);
 
-       /* the clock can give out invalid datetime, but we cannot return
-        * -EINVAL otherwise hwclock will refuse to set the time on bootup.
-        */
-       if (rtc_valid_tm(tm) < 0)
-               dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
-       return 0;
+       return rtc_valid_tm(tm);
 }
 
 static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
index e569243db57efb4f5aca9f4634047a6bae3072b5..c8f95b8e463add9070f6bf6b014dcaf7e34560a7 100644 (file)
@@ -14,6 +14,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk-provider.h>
 #include <linux/i2c.h>
 #include <linux/bcd.h>
 #include <linux/rtc.h>
 
 #define PCF8563_REG_AMN                0x09 /* alarm */
 
-#define PCF8563_REG_CLKO       0x0D /* clock out */
+#define PCF8563_REG_CLKO               0x0D /* clock out */
+#define PCF8563_REG_CLKO_FE            0x80 /* clock out enabled */
+#define PCF8563_REG_CLKO_F_MASK                0x03 /* frequenc mask */
+#define PCF8563_REG_CLKO_F_32768HZ     0x00
+#define PCF8563_REG_CLKO_F_1024HZ      0x01
+#define PCF8563_REG_CLKO_F_32HZ                0x02
+#define PCF8563_REG_CLKO_F_1HZ         0x03
+
 #define PCF8563_REG_TMRC       0x0E /* timer control */
 #define PCF8563_TMRC_ENABLE    BIT(7)
 #define PCF8563_TMRC_4096      0
@@ -76,6 +84,9 @@ struct pcf8563 {
        int voltage_low; /* incicates if a low_voltage was detected */
 
        struct i2c_client *client;
+#ifdef CONFIG_COMMON_CLK
+       struct clk_hw           clkout_hw;
+#endif
 };
 
 static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
@@ -390,6 +401,158 @@ static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
        return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
 }
 
+#ifdef CONFIG_COMMON_CLK
+/*
+ * Handling of the clkout
+ */
+
+#define clkout_hw_to_pcf8563(_hw) container_of(_hw, struct pcf8563, clkout_hw)
+
+static int clkout_rates[] = {
+       32768,
+       1024,
+       32,
+       1,
+};
+
+static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
+                                               unsigned long parent_rate)
+{
+       struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+       struct i2c_client *client = pcf8563->client;
+       unsigned char buf;
+       int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+       if (ret < 0)
+               return 0;
+
+       buf &= PCF8563_REG_CLKO_F_MASK;
+       return clkout_rates[ret];
+}
+
+static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long *prate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+               if (clkout_rates[i] <= rate)
+                       return clkout_rates[i];
+
+       return 0;
+}
+
+static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long parent_rate)
+{
+       struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+       struct i2c_client *client = pcf8563->client;
+       unsigned char buf;
+       int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+       int i;
+
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
+               if (clkout_rates[i] == rate) {
+                       buf &= ~PCF8563_REG_CLKO_F_MASK;
+                       buf |= i;
+                       ret = pcf8563_write_block_data(client,
+                                                      PCF8563_REG_CLKO, 1,
+                                                      &buf);
+                       return ret;
+               }
+
+       return -EINVAL;
+}
+
+static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
+{
+       struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+       struct i2c_client *client = pcf8563->client;
+       unsigned char buf;
+       int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+       if (ret < 0)
+               return ret;
+
+       if (enable)
+               buf |= PCF8563_REG_CLKO_FE;
+       else
+               buf &= ~PCF8563_REG_CLKO_FE;
+
+       ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+       return ret;
+}
+
+static int pcf8563_clkout_prepare(struct clk_hw *hw)
+{
+       return pcf8563_clkout_control(hw, 1);
+}
+
+static void pcf8563_clkout_unprepare(struct clk_hw *hw)
+{
+       pcf8563_clkout_control(hw, 0);
+}
+
+static int pcf8563_clkout_is_prepared(struct clk_hw *hw)
+{
+       struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
+       struct i2c_client *client = pcf8563->client;
+       unsigned char buf;
+       int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+
+       if (ret < 0)
+               return ret;
+
+       return !!(buf & PCF8563_REG_CLKO_FE);
+}
+
+static const struct clk_ops pcf8563_clkout_ops = {
+       .prepare = pcf8563_clkout_prepare,
+       .unprepare = pcf8563_clkout_unprepare,
+       .is_prepared = pcf8563_clkout_is_prepared,
+       .recalc_rate = pcf8563_clkout_recalc_rate,
+       .round_rate = pcf8563_clkout_round_rate,
+       .set_rate = pcf8563_clkout_set_rate,
+};
+
+static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
+{
+       struct i2c_client *client = pcf8563->client;
+       struct device_node *node = client->dev.of_node;
+       struct clk *clk;
+       struct clk_init_data init;
+       int ret;
+       unsigned char buf;
+
+       /* disable the clkout output */
+       buf = 0;
+       ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+       if (ret < 0)
+               return ERR_PTR(ret);
+
+       init.name = "pcf8563-clkout";
+       init.ops = &pcf8563_clkout_ops;
+       init.flags = CLK_IS_ROOT;
+       init.parent_names = NULL;
+       init.num_parents = 0;
+       pcf8563->clkout_hw.init = &init;
+
+       /* optional override of the clockname */
+       of_property_read_string(node, "clock-output-names", &init.name);
+
+       /* register the clock */
+       clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
+
+       if (!IS_ERR(clk))
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+       return clk;
+}
+#endif
+
 static const struct rtc_class_ops pcf8563_rtc_ops = {
        .ioctl          = pcf8563_rtc_ioctl,
        .read_time      = pcf8563_rtc_read_time,
@@ -459,6 +622,11 @@ static int pcf8563_probe(struct i2c_client *client,
 
        }
 
+#ifdef CONFIG_COMMON_CLK
+       /* register clk in common clk framework */
+       pcf8563_clkout_register_clk(pcf8563);
+#endif
+
        /* the pcf8563 alarm only supports a minute accuracy */
        pcf8563->rtc->uie_unsupported = 1;
 
index 41dcb7ddb906040ce18722e3c93e076f05c0e4b4..e1687e19c59f4ad57e6dd78d5f7e8702fa411d27 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/bcd.h>
 #include <linux/delay.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 
 /*
@@ -305,6 +306,8 @@ static int pl031_remove(struct amba_device *adev)
 {
        struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
 
+       dev_pm_clear_wake_irq(&adev->dev);
+       device_init_wakeup(&adev->dev, false);
        free_irq(adev->irq[0], ldata);
        rtc_device_unregister(ldata->rtc);
        iounmap(ldata->base);
@@ -370,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
                }
        }
 
-       device_init_wakeup(&adev->dev, 1);
+       device_init_wakeup(&adev->dev, true);
        ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
                                        THIS_MODULE);
        if (IS_ERR(ldata->rtc)) {
@@ -383,7 +386,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
                ret = -EIO;
                goto out_no_irq;
        }
-
+       dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
        return 0;
 
 out_no_irq:
@@ -408,7 +411,6 @@ static struct pl031_vendor_data arm_pl031 = {
                .set_alarm = pl031_set_alarm,
                .alarm_irq_enable = pl031_alarm_irq_enable,
        },
-       .irqflags = IRQF_NO_SUSPEND,
 };
 
 /* The First ST derivative */
@@ -422,7 +424,6 @@ static struct pl031_vendor_data stv1_pl031 = {
        },
        .clockwatch = true,
        .st_weekday = true,
-       .irqflags = IRQF_NO_SUSPEND,
 };
 
 /* And the second ST derivative */
@@ -439,8 +440,10 @@ static struct pl031_vendor_data stv2_pl031 = {
        /*
         * This variant shares the IRQ with another block and must not
         * suspend that IRQ line.
+        * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
+        * remove IRQF_COND_SUSPEND
         */
-       .irqflags = IRQF_SHARED | IRQF_NO_SUSPEND,
+       .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
 };
 
 static struct amba_id pl031_ids[] = {
index 24c3d69ce1b97887485a2d668716a439c0a7625a..bd911bafb809a2ede1c46c3f2e2877ac7507fc50 100644 (file)
@@ -65,6 +65,7 @@
 
 static const struct i2c_device_id rx8025_id[] = {
        { "rx8025", 0 },
+       { "rv8803", 1 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, rx8025_id);
@@ -518,9 +519,8 @@ static int rx8025_probe(struct i2c_client *client,
        }
 
        rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
-       if (!rx8025) {
+       if (!rx8025)
                return -ENOMEM;
-       }
 
        rx8025->client = client;
        i2c_set_clientdata(client, rx8025);
index 7cc8f73a3fe8f65174c43922529a8523177ded27..ffb860d18701753bfaea2308fea9deb2a6ed6a9d 100644 (file)
@@ -302,6 +302,7 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
        struct s3c_rtc *info = dev_get_drvdata(dev);
        struct rtc_time *tm = &alrm->time;
        unsigned int alrm_en;
+       int year = tm->tm_year - 100;
 
        dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
                 alrm->enabled,
@@ -328,6 +329,21 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
                writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
        }
 
+       if (year < 100 && year >= 0) {
+               alrm_en |= S3C2410_RTCALM_YEAREN;
+               writeb(bin2bcd(year), info->base + S3C2410_ALMYEAR);
+       }
+
+       if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
+               alrm_en |= S3C2410_RTCALM_MONEN;
+               writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);
+       }
+
+       if (tm->tm_mday <= 31 && tm->tm_mday >= 1) {
+               alrm_en |= S3C2410_RTCALM_DAYEN;
+               writeb(bin2bcd(tm->tm_mday), info->base + S3C2410_ALMDATE);
+       }
+
        dev_dbg(dev, "setting S3C2410_RTCALM to %08x\n", alrm_en);
 
        writeb(alrm_en, info->base + S3C2410_RTCALM);
index eb09eddf39b8a089441965f641eb27af01bde83a..ca54d039da3154b10b7b1a0c1356f8a2d28901ab 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/stmp3xxx_rtc_wdt.h>
 
 #define STMP3XXX_RTC_CTRL                      0x0
-#define STMP3XXX_RTC_CTRL_SET                  0x4
-#define STMP3XXX_RTC_CTRL_CLR                  0x8
 #define STMP3XXX_RTC_CTRL_ALARM_IRQ_EN         0x00000001
 #define STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN       0x00000002
 #define STMP3XXX_RTC_CTRL_ALARM_IRQ            0x00000004
@@ -52,8 +50,6 @@
 #define STMP3XXX_RTC_WATCHDOG                  0x50
 
 #define STMP3XXX_RTC_PERSISTENT0               0x60
-#define STMP3XXX_RTC_PERSISTENT0_SET           0x64
-#define STMP3XXX_RTC_PERSISTENT0_CLR           0x68
 #define STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE           (1 << 0)
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN         (1 << 1)
 #define STMP3XXX_RTC_PERSISTENT0_ALARM_EN              (1 << 2)
@@ -179,7 +175,7 @@ static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id)
 
        if (status & STMP3XXX_RTC_CTRL_ALARM_IRQ) {
                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ,
-                               rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+                       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
                rtc_update_irq(rtc_data->rtc, 1, RTC_AF | RTC_IRQF);
                return IRQ_HANDLED;
        }
@@ -194,15 +190,17 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
        if (enabled) {
                writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                                STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
-                               rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+                       rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+                               STMP_OFFSET_REG_SET);
                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-                               rtc_data->io + STMP3XXX_RTC_CTRL_SET);
+                       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_SET);
        } else {
                writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                                STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN,
-                               rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+                       rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+                               STMP_OFFSET_REG_CLR);
                writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-                               rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+                       rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
        }
        return 0;
 }
@@ -245,7 +243,7 @@ static int stmp3xxx_rtc_remove(struct platform_device *pdev)
                return 0;
 
        writel(STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-                       rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+               rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 
        return 0;
 }
@@ -334,16 +332,17 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
                        STMP3XXX_RTC_PERSISTENT0_CLOCKSOURCE;
        }
 
-       writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0_SET);
+       writel(pers0_set, rtc_data->io + STMP3XXX_RTC_PERSISTENT0 +
+                       STMP_OFFSET_REG_SET);
 
        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE | pers0_clr,
-                       rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+               rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
 
        writel(STMP3XXX_RTC_CTRL_ONEMSEC_IRQ_EN |
                        STMP3XXX_RTC_CTRL_ALARM_IRQ_EN,
-                       rtc_data->io + STMP3XXX_RTC_CTRL_CLR);
+               rtc_data->io + STMP3XXX_RTC_CTRL + STMP_OFFSET_REG_CLR);
 
        rtc_data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
                                &stmp3xxx_rtc_ops, THIS_MODULE);
@@ -376,7 +375,7 @@ static int stmp3xxx_rtc_resume(struct device *dev)
        writel(STMP3XXX_RTC_PERSISTENT0_ALARM_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE_EN |
                        STMP3XXX_RTC_PERSISTENT0_ALARM_WAKE,
-                       rtc_data->io + STMP3XXX_RTC_PERSISTENT0_CLR);
+               rtc_data->io + STMP3XXX_RTC_PERSISTENT0 + STMP_OFFSET_REG_CLR);
        return 0;
 }
 #endif
index d80ae852334d1560522f0b74034479bf7efe00d1..624bce51b27d26fad9a88528a71439125a20d183 100644 (file)
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
        /* Turn on update interrupts (one per second) */
        retval = ioctl(fd, RTC_UIE_ON, 0);
        if (retval == -1) {
-               if (errno == ENOTTY) {
+               if (errno == EINVAL) {
                        fprintf(stderr,
                                "\n...Update IRQs not supported.\n");
                        goto test_READ;