aboutsummaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig9
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-cmos.c24
-rw-r--r--drivers/rtc/rtc-ds1511.c17
-rw-r--r--drivers/rtc/rtc-ds1553.c13
-rw-r--r--drivers/rtc/rtc-ds1742.c26
-rw-r--r--drivers/rtc/rtc-ep93xx.c14
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c22
-rw-r--r--drivers/rtc/rtc-imxdi.c16
-rw-r--r--drivers/rtc/rtc-lpc32xx.c24
-rw-r--r--drivers/rtc/rtc-max77686.c4
-rw-r--r--drivers/rtc/rtc-moxart.c330
-rw-r--r--drivers/rtc/rtc-mv.c17
-rw-r--r--drivers/rtc/rtc-mxc.c14
-rw-r--r--drivers/rtc/rtc-nuc900.c2
-rw-r--r--drivers/rtc/rtc-omap.c60
-rw-r--r--drivers/rtc/rtc-palmas.c35
-rw-r--r--drivers/rtc/rtc-pcf2127.c6
-rw-r--r--drivers/rtc/rtc-sirfsoc.c13
-rw-r--r--drivers/rtc/rtc-stk17ta8.c15
-rw-r--r--drivers/rtc/rtc-tx4939.c14
21 files changed, 503 insertions, 173 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 9e3498bf302b..9654aa3c05cb 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1249,6 +1249,15 @@ config RTC_DRV_SIRFSOC
Say "yes" here to support the real time clock on SiRF SOC chips.
This driver can also be built as a module called rtc-sirfsoc.
+config RTC_DRV_MOXART
+ tristate "MOXA ART RTC"
+ help
+ If you say yes here you get support for the MOXA ART
+ RTC module.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-moxart
+
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index d3b4488f48f2..2dff3d2009b5 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -130,3 +130,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
+obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index be06d7150de5..24e733c98f8b 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -1018,23 +1018,6 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
cmos_do_remove(&pnp->dev);
}
-#ifdef CONFIG_PM
-
-static int cmos_pnp_suspend(struct pnp_dev *pnp, pm_message_t mesg)
-{
- return cmos_suspend(&pnp->dev);
-}
-
-static int cmos_pnp_resume(struct pnp_dev *pnp)
-{
- return cmos_resume(&pnp->dev);
-}
-
-#else
-#define cmos_pnp_suspend NULL
-#define cmos_pnp_resume NULL
-#endif
-
static void cmos_pnp_shutdown(struct pnp_dev *pnp)
{
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
@@ -1060,8 +1043,11 @@ static struct pnp_driver cmos_pnp_driver = {
/* flag ensures resume() gets called, and stops syslog spam */
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
- .suspend = cmos_pnp_suspend,
- .resume = cmos_pnp_resume,
+#ifdef CONFIG_PM_SLEEP
+ .driver = {
+ .pm = &cmos_pm_ops,
+ },
+#endif
};
#endif /* CONFIG_PNP */
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 308a8fefe76f..bc7b4fcf603c 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -89,7 +89,6 @@ enum ds1511reg {
struct rtc_plat_data {
struct rtc_device *rtc;
void __iomem *ioaddr; /* virtual base address */
- int size; /* amount of memory mapped */
int irq;
unsigned int irqen;
int alrm_sec;
@@ -479,20 +478,14 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
struct rtc_plat_data *pdata;
int ret = 0;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
- pdev->name))
- return -EBUSY;
- ds1511_base = devm_ioremap(&pdev->dev, res->start, pdata->size);
- if (!ds1511_base)
- return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ds1511_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ds1511_base))
+ return PTR_ERR(ds1511_base);
pdata->ioaddr = ds1511_base;
pdata->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 8c6c952e90b1..fd31571941f5 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -285,19 +285,14 @@ static int ds1553_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
- pdev->name))
- return -EBUSY;
- ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
- if (!ioaddr)
- return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ioaddr))
+ return PTR_ERR(ioaddr);
pdata->ioaddr = ioaddr;
pdata->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index eccdc62ae1c0..17b73fdc3b6e 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -52,11 +52,9 @@
#define RTC_BATT_FLAG 0x80
struct rtc_plat_data {
- struct rtc_device *rtc;
void __iomem *ioaddr_nvram;
void __iomem *ioaddr_rtc;
size_t size_nvram;
- size_t size;
unsigned long last_jiffies;
struct bin_attribute nvram_attr;
};
@@ -117,11 +115,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* year is 1900 + tm->tm_year */
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
- if (rtc_valid_tm(tm) < 0) {
- dev_err(dev, "retrieved date/time is not valid.\n");
- rtc_time_to_tm(0, tm);
- }
- return 0;
+ return rtc_valid_tm(tm);
}
static const struct rtc_class_ops ds1742_rtc_ops = {
@@ -168,22 +162,17 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
- pdev->name))
- return -EBUSY;
- ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size);
- if (!ioaddr)
- return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ioaddr))
+ return PTR_ERR(ioaddr);
pdata->ioaddr_nvram = ioaddr;
- pdata->size_nvram = pdata->size - RTC_SIZE;
+ pdata->size_nvram = resource_size(res) - RTC_SIZE;
pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
sysfs_bin_attr_init(&pdata->nvram_attr);
@@ -212,7 +201,6 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
&ds1742_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
- pdata->rtc = rtc;
ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 549b3c3792d2..580e7b56bde8 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -138,17 +138,9 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENXIO;
-
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name))
- return -EBUSY;
-
- ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!ep93xx_rtc->mmio_base)
- return -ENXIO;
+ ep93xx_rtc->mmio_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ep93xx_rtc->mmio_base))
+ return PTR_ERR(ep93xx_rtc->mmio_base);
pdev->dev.platform_data = ep93xx_rtc;
platform_set_drvdata(pdev, ep93xx_rtc);
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index 7273b0139e5c..4e2a81854f51 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -23,10 +23,6 @@
#include <linux/iio/iio.h>
#include <linux/rtc.h>
-/* Format: HID-SENSOR-usage_id_in_hex */
-/* Usage ID from spec for Time: 0x2000A0 */
-#define DRIVER_NAME "HID-SENSOR-2000a0" /* must be lowercase */
-
enum hid_time_channel {
CHANNEL_SCAN_INDEX_YEAR,
CHANNEL_SCAN_INDEX_MONTH,
@@ -283,9 +279,11 @@ static int hid_time_probe(struct platform_device *pdev)
"hid-sensor-time", &hid_time_rtc_ops,
THIS_MODULE);
- if (IS_ERR(time_state->rtc)) {
+ if (IS_ERR_OR_NULL(time_state->rtc)) {
+ ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
+ time_state->rtc = NULL;
+ sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
dev_err(&pdev->dev, "rtc device register failed!\n");
- return PTR_ERR(time_state->rtc);
}
return ret;
@@ -300,9 +298,19 @@ static int hid_time_remove(struct platform_device *pdev)
return 0;
}
+static struct platform_device_id hid_time_ids[] = {
+ {
+ /* Format: HID-SENSOR-usage_id_in_hex_lowercase */
+ .name = "HID-SENSOR-2000a0",
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, hid_time_ids);
+
static struct platform_driver hid_time_platform_driver = {
+ .id_table = hid_time_ids,
.driver = {
- .name = DRIVER_NAME,
+ .name = KBUILD_MODNAME,
.owner = THIS_MODULE,
},
.probe = hid_time_probe,
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index d3a8c8e255de..abd7f9091f34 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -375,24 +375,16 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
struct imxdi_dev *imxdi;
int rc;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
imxdi = devm_kzalloc(&pdev->dev, sizeof(*imxdi), GFP_KERNEL);
if (!imxdi)
return -ENOMEM;
imxdi->pdev = pdev;
- if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
- pdev->name))
- return -EBUSY;
-
- imxdi->ioaddr = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (imxdi->ioaddr == NULL)
- return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(imxdi->ioaddr))
+ return PTR_ERR(imxdi->ioaddr);
spin_lock_init(&imxdi->irq_lock);
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index 8276ae94a2a9..bfdbcb82d069 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -201,16 +201,9 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct lpc32xx_rtc *rtc;
- resource_size_t size;
int rtcirq;
u32 tmp;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Can't get memory resource\n");
- return -ENOENT;
- }
-
rtcirq = platform_get_irq(pdev, 0);
if (rtcirq < 0 || rtcirq >= NR_IRQS) {
dev_warn(&pdev->dev, "Can't get interrupt resource\n");
@@ -224,19 +217,10 @@ static int lpc32xx_rtc_probe(struct platform_device *pdev)
}
rtc->irq = rtcirq;
- size = resource_size(res);
-
- if (!devm_request_mem_region(&pdev->dev, res->start, size,
- pdev->name)) {
- dev_err(&pdev->dev, "RTC registers are not free\n");
- return -EBUSY;
- }
-
- rtc->rtc_base = devm_ioremap(&pdev->dev, res->start, size);
- if (!rtc->rtc_base) {
- dev_err(&pdev->dev, "Can't map memory\n");
- return -ENOMEM;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->rtc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rtc->rtc_base))
+ return PTR_ERR(rtc->rtc_base);
spin_lock_init(&rtc->lock);
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 9915cb96014b..9efe118a28ba 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -240,9 +240,9 @@ static int max77686_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
alrm->pending = 0;
- ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS1, &val);
+ ret = regmap_read(info->max77686->regmap, MAX77686_REG_STATUS2, &val);
if (ret < 0) {
- dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
+ dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}
diff --git a/drivers/rtc/rtc-moxart.c b/drivers/rtc/rtc-moxart.c
new file mode 100644
index 000000000000..c29dee0946e6
--- /dev/null
+++ b/drivers/rtc/rtc-moxart.c
@@ -0,0 +1,330 @@
+/*
+ * MOXA ART RTC driver.
+ *
+ * Copyright (C) 2013 Jonas Jensen
+ *
+ * Jonas Jensen <jonas.jensen@gmail.com>
+ *
+ * Based on code from
+ * Moxa Technology Co., Ltd. <www.moxa.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#define GPIO_RTC_RESERVED 0x0C
+#define GPIO_RTC_DATA_SET 0x10
+#define GPIO_RTC_DATA_CLEAR 0x14
+#define GPIO_RTC_PIN_PULL_ENABLE 0x18
+#define GPIO_RTC_PIN_PULL_TYPE 0x1C
+#define GPIO_RTC_INT_ENABLE 0x20
+#define GPIO_RTC_INT_RAW_STATE 0x24
+#define GPIO_RTC_INT_MASKED_STATE 0x28
+#define GPIO_RTC_INT_MASK 0x2C
+#define GPIO_RTC_INT_CLEAR 0x30
+#define GPIO_RTC_INT_TRIGGER 0x34
+#define GPIO_RTC_INT_BOTH 0x38
+#define GPIO_RTC_INT_RISE_NEG 0x3C
+#define GPIO_RTC_BOUNCE_ENABLE 0x40
+#define GPIO_RTC_BOUNCE_PRE_SCALE 0x44
+#define GPIO_RTC_PROTECT_W 0x8E
+#define GPIO_RTC_PROTECT_R 0x8F
+#define GPIO_RTC_YEAR_W 0x8C
+#define GPIO_RTC_YEAR_R 0x8D
+#define GPIO_RTC_DAY_W 0x8A
+#define GPIO_RTC_DAY_R 0x8B
+#define GPIO_RTC_MONTH_W 0x88
+#define GPIO_RTC_MONTH_R 0x89
+#define GPIO_RTC_DATE_W 0x86
+#define GPIO_RTC_DATE_R 0x87
+#define GPIO_RTC_HOURS_W 0x84
+#define GPIO_RTC_HOURS_R 0x85
+#define GPIO_RTC_MINUTES_W 0x82
+#define GPIO_RTC_MINUTES_R 0x83
+#define GPIO_RTC_SECONDS_W 0x80
+#define GPIO_RTC_SECONDS_R 0x81
+#define GPIO_RTC_DELAY_TIME 8
+
+struct moxart_rtc {
+ struct rtc_device *rtc;
+ spinlock_t rtc_lock;
+ int gpio_data, gpio_sclk, gpio_reset;
+};
+
+static int day_of_year[12] = { 0, 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334 };
+
+static void moxart_rtc_write_byte(struct device *dev, u8 data)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < 8; i++, data >>= 1) {
+ gpio_set_value(moxart_rtc->gpio_sclk, 0);
+ gpio_set_value(moxart_rtc->gpio_data, ((data & 1) == 1));
+ udelay(GPIO_RTC_DELAY_TIME);
+ gpio_set_value(moxart_rtc->gpio_sclk, 1);
+ udelay(GPIO_RTC_DELAY_TIME);
+ }
+}
+
+static u8 moxart_rtc_read_byte(struct device *dev)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+ int i;
+ u8 data = 0;
+
+ for (i = 0; i < 8; i++) {
+ gpio_set_value(moxart_rtc->gpio_sclk, 0);
+ udelay(GPIO_RTC_DELAY_TIME);
+ gpio_set_value(moxart_rtc->gpio_sclk, 1);
+ udelay(GPIO_RTC_DELAY_TIME);
+ if (gpio_get_value(moxart_rtc->gpio_data))
+ data |= (1 << i);
+ udelay(GPIO_RTC_DELAY_TIME);
+ }
+ return data;
+}
+
+static u8 moxart_rtc_read_register(struct device *dev, u8 cmd)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+ u8 data;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_direction_output(moxart_rtc->gpio_data, 0);
+ gpio_set_value(moxart_rtc->gpio_reset, 1);
+ udelay(GPIO_RTC_DELAY_TIME);
+ moxart_rtc_write_byte(dev, cmd);
+ gpio_direction_input(moxart_rtc->gpio_data);
+ udelay(GPIO_RTC_DELAY_TIME);
+ data = moxart_rtc_read_byte(dev);
+ gpio_set_value(moxart_rtc->gpio_sclk, 0);
+ gpio_set_value(moxart_rtc->gpio_reset, 0);
+ udelay(GPIO_RTC_DELAY_TIME);
+
+ local_irq_restore(flags);
+
+ return data;
+}
+
+static void moxart_rtc_write_register(struct device *dev, u8 cmd, u8 data)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_direction_output(moxart_rtc->gpio_data, 0);
+ gpio_set_value(moxart_rtc->gpio_reset, 1);
+ udelay(GPIO_RTC_DELAY_TIME);
+ moxart_rtc_write_byte(dev, cmd);
+ moxart_rtc_write_byte(dev, data);
+ gpio_set_value(moxart_rtc->gpio_sclk, 0);
+ gpio_set_value(moxart_rtc->gpio_reset, 0);
+ udelay(GPIO_RTC_DELAY_TIME);
+
+ local_irq_restore(flags);
+}
+
+static int moxart_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+
+ spin_lock_irq(&moxart_rtc->rtc_lock);
+
+ moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0);
+ moxart_rtc_write_register(dev, GPIO_RTC_YEAR_W,
+ (((tm->tm_year - 100) / 10) << 4) |
+ ((tm->tm_year - 100) % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_MONTH_W,
+ (((tm->tm_mon + 1) / 10) << 4) |
+ ((tm->tm_mon + 1) % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_DATE_W,
+ ((tm->tm_mday / 10) << 4) |
+ (tm->tm_mday % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_HOURS_W,
+ ((tm->tm_hour / 10) << 4) |
+ (tm->tm_hour % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_MINUTES_W,
+ ((tm->tm_min / 10) << 4) |
+ (tm->tm_min % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_SECONDS_W,
+ ((tm->tm_sec / 10) << 4) |
+ (tm->tm_sec % 10));
+
+ moxart_rtc_write_register(dev, GPIO_RTC_PROTECT_W, 0x80);
+
+ spin_unlock_irq(&moxart_rtc->rtc_lock);
+
+ dev_dbg(dev, "%s: success tm_year=%d tm_mon=%d\n"
+ "tm_mday=%d tm_hour=%d tm_min=%d tm_sec=%d\n",
+ __func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return 0;
+}
+
+static int moxart_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct moxart_rtc *moxart_rtc = dev_get_drvdata(dev);
+ unsigned char v;
+
+ spin_lock_irq(&moxart_rtc->rtc_lock);
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_SECONDS_R);
+ tm->tm_sec = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_MINUTES_R);
+ tm->tm_min = (((v & 0x70) >> 4) * 10) + (v & 0x0F);
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_HOURS_R);
+ if (v & 0x80) { /* 12-hour mode */
+ tm->tm_hour = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
+ if (v & 0x20) { /* PM mode */
+ tm->tm_hour += 12;
+ if (tm->tm_hour >= 24)
+ tm->tm_hour = 0;
+ }
+ } else { /* 24-hour mode */
+ tm->tm_hour = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
+ }
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_DATE_R);
+ tm->tm_mday = (((v & 0x30) >> 4) * 10) + (v & 0x0F);
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_MONTH_R);
+ tm->tm_mon = (((v & 0x10) >> 4) * 10) + (v & 0x0F);
+ tm->tm_mon--;
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_YEAR_R);
+ tm->tm_year = (((v & 0xF0) >> 4) * 10) + (v & 0x0F);
+ tm->tm_year += 100;
+ if (tm->tm_year <= 69)
+ tm->tm_year += 100;
+
+ v = moxart_rtc_read_register(dev, GPIO_RTC_DAY_R);
+ tm->tm_wday = (v & 0x0f) - 1;
+ tm->tm_yday = day_of_year[tm->tm_mon];
+ tm->tm_yday += (tm->tm_mday - 1);
+ if (tm->tm_mon >= 2) {
+ if (!(tm->tm_year % 4) && (tm->tm_year % 100))
+ tm->tm_yday++;
+ }
+
+ tm->tm_isdst = 0;
+
+ spin_unlock_irq(&moxart_rtc->rtc_lock);
+
+ return 0;
+}
+
+static const struct rtc_class_ops moxart_rtc_ops = {
+ .read_time = moxart_rtc_read_time,
+ .set_time = moxart_rtc_set_time,
+};
+
+static int moxart_rtc_probe(struct platform_device *pdev)
+{
+ struct moxart_rtc *moxart_rtc;
+ int ret = 0;
+
+ moxart_rtc = devm_kzalloc(&pdev->dev, sizeof(*moxart_rtc), GFP_KERNEL);
+ if (!moxart_rtc) {
+ dev_err(&pdev->dev, "devm_kzalloc failed\n");
+ return -ENOMEM;
+ }
+
+ moxart_rtc->gpio_data = of_get_named_gpio(pdev->dev.of_node,
+ "gpio-rtc-data", 0);
+ if (!gpio_is_valid(moxart_rtc->gpio_data)) {
+ dev_err(&pdev->dev, "invalid gpio (data): %d\n",
+ moxart_rtc->gpio_data);
+ return moxart_rtc->gpio_data;
+ }
+
+ moxart_rtc->gpio_sclk = of_get_named_gpio(pdev->dev.of_node,
+ "gpio-rtc-sclk", 0);
+ if (!gpio_is_valid(moxart_rtc->gpio_sclk)) {
+ dev_err(&pdev->dev, "invalid gpio (sclk): %d\n",
+ moxart_rtc->gpio_sclk);
+ return moxart_rtc->gpio_sclk;
+ }
+
+ moxart_rtc->gpio_reset = of_get_named_gpio(pdev->dev.of_node,
+ "gpio-rtc-reset", 0);
+ if (!gpio_is_valid(moxart_rtc->gpio_reset)) {
+ dev_err(&pdev->dev, "invalid gpio (reset): %d\n",
+ moxart_rtc->gpio_reset);
+ return moxart_rtc->gpio_reset;
+ }
+
+ spin_lock_init(&moxart_rtc->rtc_lock);
+ platform_set_drvdata(pdev, moxart_rtc);
+
+ ret = devm_gpio_request(&pdev->dev, moxart_rtc->gpio_data, "rtc_data");
+ if (ret) {
+ dev_err(&pdev->dev, "can't get rtc_data gpio\n");
+ return ret;
+ }
+
+ ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_sclk,
+ GPIOF_DIR_OUT, "rtc_sclk");
+ if (ret) {
+ dev_err(&pdev->dev, "can't get rtc_sclk gpio\n");
+ return ret;
+ }
+
+ ret = devm_gpio_request_one(&pdev->dev, moxart_rtc->gpio_reset,
+ GPIOF_DIR_OUT, "rtc_reset");
+ if (ret) {
+ dev_err(&pdev->dev, "can't get rtc_reset gpio\n");
+ return ret;
+ }
+
+ moxart_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+ &moxart_rtc_ops,
+ THIS_MODULE);
+ if (IS_ERR(moxart_rtc->rtc)) {
+ dev_err(&pdev->dev, "devm_rtc_device_register failed\n");
+ return PTR_ERR(moxart_rtc->rtc);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id moxart_rtc_match[] = {
+ { .compatible = "moxa,moxart-rtc" },
+ { },
+};
+
+static struct platform_driver moxart_rtc_driver = {
+ .probe = moxart_rtc_probe,
+ .driver = {
+ .name = "moxart-rtc",
+ .owner = THIS_MODULE,
+ .of_match_table = moxart_rtc_match,
+ },
+};
+module_platform_driver(moxart_rtc_driver);
+
+MODULE_DESCRIPTION("MOXART RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonas Jensen <jonas.jensen@gmail.com>");
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index baab802f2153..d536c5962c99 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -221,26 +221,17 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
{
struct resource *res;
struct rtc_plat_data *pdata;
- resource_size_t size;
u32 rtc_time;
int ret = 0;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, res->start, size,
- pdev->name))
- return -EBUSY;
-
- pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, size);
- if (!pdata->ioaddr)
- return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pdata->ioaddr))
+ return PTR_ERR(pdata->ioaddr);
pdata->clk = devm_clk_get(&pdev->dev, NULL);
/* Not all SoCs require a clock.*/
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index ab87bacb8f88..50c572645546 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -377,22 +377,16 @@ static int mxc_rtc_probe(struct platform_device *pdev)
unsigned long rate;
int ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata->devtype = pdev->id_entry->driver_data;
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name))
- return -EBUSY;
-
- pdata->ioaddr = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pdata->ioaddr))
+ return PTR_ERR(pdata->ioaddr);
pdata->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(pdata->clk)) {
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
index 22861c5e0c59..248653c74b80 100644
--- a/drivers/rtc/rtc-nuc900.c
+++ b/drivers/rtc/rtc-nuc900.c
@@ -99,7 +99,7 @@ static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc)
if (!timeout)
return ERR_PTR(-EPERM);
- return 0;
+ return NULL;
}
static int nuc900_rtc_bcd2bin(unsigned int timereg,
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index c6ffbaec32a4..c7d97ee59327 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -70,6 +70,8 @@
#define OMAP_RTC_KICK0_REG 0x6c
#define OMAP_RTC_KICK1_REG 0x70
+#define OMAP_RTC_IRQWAKEEN 0x7c
+
/* OMAP_RTC_CTRL_REG bit fields: */
#define OMAP_RTC_CTRL_SPLIT (1<<7)
#define OMAP_RTC_CTRL_DISABLE (1<<6)
@@ -94,12 +96,21 @@
#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
+/* OMAP_RTC_IRQWAKEEN bit fields: */
+#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1)
+
/* OMAP_RTC_KICKER values */
#define KICK0_VALUE 0x83e70b13
#define KICK1_VALUE 0x95a4f1e0
#define OMAP_RTC_HAS_KICKER 0x1
+/*
+ * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
+ * generation for event Alarm.
+ */
+#define OMAP_RTC_HAS_IRQWAKEEN 0x2
+
static void __iomem *rtc_base;
#define rtc_read(addr) readb(rtc_base + (addr))
@@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;
-#define OMAP_RTC_DATA_DA830_IDX 1
+#define OMAP_RTC_DATA_AM3352_IDX 1
+#define OMAP_RTC_DATA_DA830_IDX 2
static struct platform_device_id omap_rtc_devtype[] = {
{
.name = DRIVER_NAME,
- }, {
+ },
+ [OMAP_RTC_DATA_AM3352_IDX] = {
+ .name = "am3352-rtc",
+ .driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
+ },
+ [OMAP_RTC_DATA_DA830_IDX] = {
.name = "da830-rtc",
.driver_data = OMAP_RTC_HAS_KICKER,
},
@@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
{ .compatible = "ti,da830-rtc",
.data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
},
+ { .compatible = "ti,am3352-rtc",
+ .data = &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
+ },
{},
};
MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@@ -464,16 +484,28 @@ static u8 irqstat;
static int omap_rtc_suspend(struct device *dev)
{
+ u8 irqwake_stat;
+ struct platform_device *pdev = to_platform_device(dev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(pdev);
+
irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
/* FIXME the RTC alarm is not currently acting as a wakeup event
- * source, and in fact this enable() call is just saving a flag
- * that's never used...
+ * source on some platforms, and in fact this enable() call is just
+ * saving a flag that's never used...
*/
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
enable_irq_wake(omap_rtc_alarm);
- else
+
+ if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
+ irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
+ irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
+ rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
+ }
+ } else {
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
+ }
/* Disable the clock/module */
pm_runtime_put_sync(dev);
@@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)
static int omap_rtc_resume(struct device *dev)
{
+ u8 irqwake_stat;
+ struct platform_device *pdev = to_platform_device(dev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(pdev);
+
/* Enable the clock/module so that we can access the registers */
pm_runtime_get_sync(dev);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
disable_irq_wake(omap_rtc_alarm);
- else
+
+ if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
+ irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
+ irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
+ rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
+ }
+ } else {
rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
+ }
return 0;
}
#endif
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index a1fecc8d97fc..fffb7d3449d7 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -238,6 +238,15 @@ static int palmas_rtc_probe(struct platform_device *pdev)
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
struct palmas_rtc *palmas_rtc = NULL;
int ret;
+ bool enable_bb_charging = false;
+ bool high_bb_charging;
+
+ if (pdev->dev.of_node) {
+ enable_bb_charging = of_property_read_bool(pdev->dev.of_node,
+ "ti,backup-battery-chargeable");
+ high_bb_charging = of_property_read_bool(pdev->dev.of_node,
+ "ti,backup-battery-charge-high-current");
+ }
palmas_rtc = devm_kzalloc(&pdev->dev, sizeof(struct palmas_rtc),
GFP_KERNEL);
@@ -254,6 +263,32 @@ static int palmas_rtc_probe(struct platform_device *pdev)
palmas_rtc->dev = &pdev->dev;
platform_set_drvdata(pdev, palmas_rtc);
+ if (enable_bb_charging) {
+ unsigned reg = PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG;
+
+ if (high_bb_charging)
+ reg = 0;
+
+ ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
+ PALMAS_BACKUP_BATTERY_CTRL,
+ PALMAS_BACKUP_BATTERY_CTRL_BBS_BBC_LOW_ICHRG, reg);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "BACKUP_BATTERY_CTRL update failed, %d\n", ret);
+ return ret;
+ }
+
+ ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
+ PALMAS_BACKUP_BATTERY_CTRL,
+ PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN,
+ PALMAS_BACKUP_BATTERY_CTRL_BB_CHG_EN);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "BACKUP_BATTERY_CTRL update failed, %d\n", ret);
+ return ret;
+ }
+ }
+
/* Start RTC */
ret = palmas_update_bits(palmas, PALMAS_RTC_BASE, PALMAS_RTC_CTRL_REG,
PALMAS_RTC_CTRL_REG_STOP_RTC,
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 205b9f7da1b8..1ee514a3972c 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -203,11 +203,6 @@ static int pcf2127_probe(struct i2c_client *client,
return 0;
}
-static int pcf2127_remove(struct i2c_client *client)
-{
- return 0;
-}
-
static const struct i2c_device_id pcf2127_id[] = {
{ "pcf2127", 0 },
{ }
@@ -229,7 +224,6 @@ static struct i2c_driver pcf2127_driver = {
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_probe,
- .remove = pcf2127_remove,
.id_table = pcf2127_id,
};
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c
index aa7ed4b5f7f0..63460cf80f1b 100644
--- a/drivers/rtc/rtc-sirfsoc.c
+++ b/drivers/rtc/rtc-sirfsoc.c
@@ -44,6 +44,7 @@ struct sirfsoc_rtc_drv {
struct rtc_device *rtc;
u32 rtc_base;
u32 irq;
+ unsigned irq_wake;
/* Overflow for every 8 years extra time */
u32 overflow_rtc;
#ifdef CONFIG_PM
@@ -355,8 +356,8 @@ static int sirfsoc_rtc_suspend(struct device *dev)
rtcdrv->saved_counter =
sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
- if (device_may_wakeup(&pdev->dev))
- enable_irq_wake(rtcdrv->irq);
+ if (device_may_wakeup(&pdev->dev) && !enable_irq_wake(rtcdrv->irq))
+ rtcdrv->irq_wake = 1;
return 0;
}
@@ -423,8 +424,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
sirfsoc_rtc_thaw(dev);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);
+ rtcdrv->irq_wake = 0;
+ }
return 0;
}
@@ -434,8 +437,10 @@ static int sirfsoc_rtc_restore(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
struct sirfsoc_rtc_drv *rtcdrv = platform_get_drvdata(pdev);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(&pdev->dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);
+ rtcdrv->irq_wake = 0;
+ }
return 0;
}
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index af5e97e3f272..a176ba614683 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -294,19 +294,14 @@ static int stk17ta8_rtc_probe(struct platform_device *pdev)
void __iomem *ioaddr;
int ret = 0;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- if (!devm_request_mem_region(&pdev->dev, res->start, RTC_REG_SIZE,
- pdev->name))
- return -EBUSY;
- ioaddr = devm_ioremap(&pdev->dev, res->start, RTC_REG_SIZE);
- if (!ioaddr)
- return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ioaddr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ioaddr))
+ return PTR_ERR(ioaddr);
pdata->ioaddr = ioaddr;
pdata->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index f9a0677e4e3b..4f87234e0dee 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -244,9 +244,6 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
struct resource *res;
int irq, ret;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return -ENODEV;
@@ -255,13 +252,10 @@ static int __init tx4939_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, pdata);
- if (!devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), pdev->name))
- return -EBUSY;
- pdata->rtcreg = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!pdata->rtcreg)
- return -EBUSY;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pdata->rtcreg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(pdata->rtcreg))
+ return PTR_ERR(pdata->rtcreg);
spin_lock_init(&pdata->lock);
tx4939_rtc_cmd(pdata->rtcreg, TX4939_RTCCTL_COMMAND_NOP);