#include <linux/module.h>
 #include <linux/i2c.h>
-#include <linux/slab.h>
 #include <linux/bcd.h>
-#include <linux/bitops.h>
 #include <linux/regmap.h>
 #include <linux/rtc.h>
-#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/samsung/core.h>
 #include <linux/mfd/samsung/irq.h>
 #include <linux/mfd/samsung/rtc.h>
+#include <linux/mfd/samsung/s2mps14.h>
 
 /*
  * Maximum number of retries for checking changes in UDR field
        .rtc_udr_mask           = S5M_RTC_UDR_MASK,
 };
 
+/*
+ * Register map for S2MPS14.
+ * It may be also suitable for S2MPS11 but this was not tested.
+ */
+static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
+       .regs_count             = 7,
+       .time                   = S2MPS_RTC_SEC,
+       .ctrl                   = S2MPS_RTC_CTRL,
+       .alarm0                 = S2MPS_ALARM0_SEC,
+       .alarm1                 = S2MPS_ALARM1_SEC,
+       .smpl_wtsr              = S2MPS_WTSR_SMPL_CNTL,
+       .rtc_udr_update         = S2MPS_RTC_UDR_CON,
+       .rtc_udr_mask           = S2MPS_RTC_WUDR_MASK,
+};
+
 struct s5m_rtc_info {
        struct device *dev;
        struct i2c_client *i2c;
                ret = regmap_read(info->regmap, S5M_RTC_STATUS, &val);
                val &= S5M_ALARM0_STATUS;
                break;
+       case S2MPS14X:
+               ret = regmap_read(info->s5m87xx->regmap_pmic, S2MPS14_REG_ST2,
+                               &val);
+               val &= S2MPS_ALARM0_STATUS;
+               break;
        default:
                return -EINVAL;
        }
                return ret;
        }
 
-       data |= S5M_RTC_TIME_EN_MASK;
        data |= info->regs->rtc_udr_mask;
+       if (info->device_type == S5M8763X || info->device_type == S5M8767X)
+               data |= S5M_RTC_TIME_EN_MASK;
 
        ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
        if (ret < 0) {
                return ret;
        }
 
-       data &= ~S5M_RTC_TIME_EN_MASK;
        data |= info->regs->rtc_udr_mask;
+       switch (info->device_type) {
+       case S5M8763X:
+       case S5M8767X:
+               data &= ~S5M_RTC_TIME_EN_MASK;
+               break;
+       case S2MPS14X:
+               data |= S2MPS_RTC_RUDR_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        ret = regmap_write(info->regmap, info->regs->rtc_udr_update, data);
        if (ret < 0) {
        u8 data[info->regs->regs_count];
        int ret;
 
+       if (info->device_type == S2MPS14X) {
+               ret = regmap_update_bits(info->regmap,
+                               info->regs->rtc_udr_update,
+                               S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
+               if (ret) {
+                       dev_err(dev,
+                               "Failed to prepare registers for time reading: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
        ret = regmap_bulk_read(info->regmap, info->regs->time, data,
                        info->regs->regs_count);
        if (ret < 0)
                break;
 
        case S5M8767X:
+       case S2MPS14X:
                s5m8767_data_to_tm(data, tm, info->rtc_24hr_mode);
                break;
 
                s5m8763_tm_to_data(tm, data);
                break;
        case S5M8767X:
+       case S2MPS14X:
                ret = s5m8767_tm_to_data(tm, data);
                break;
        default:
                break;
 
        case S5M8767X:
+       case S2MPS14X:
                s5m8767_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
                alrm->enabled = 0;
                for (i = 0; i < info->regs->regs_count; i++) {
                break;
 
        case S5M8767X:
+       case S2MPS14X:
                for (i = 0; i < info->regs->regs_count; i++)
                        data[i] &= ~ALARM_ENABLE_MASK;
 
                break;
 
        case S5M8767X:
+       case S2MPS14X:
                data[RTC_SEC] |= ALARM_ENABLE_MASK;
                data[RTC_MIN] |= ALARM_ENABLE_MASK;
                data[RTC_HOUR] |= ALARM_ENABLE_MASK;
                break;
 
        case S5M8767X:
+       case S2MPS14X:
                s5m8767_tm_to_data(&alrm->time, data);
                break;
 
        u8 data[2];
        int ret;
 
-       /* UDR update time. Default of 7.32 ms is too long. */
-       ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON,
-                       S5M_RTC_UDR_T_MASK, S5M_RTC_UDR_T_450_US);
-       if (ret < 0)
-               dev_err(info->dev, "%s: fail to change UDR time: %d\n",
-                               __func__, ret);
+       switch (info->device_type) {
+       case S5M8763X:
+       case S5M8767X:
+               /* UDR update time. Default of 7.32 ms is too long. */
+               ret = regmap_update_bits(info->regmap, S5M_RTC_UDR_CON,
+                               S5M_RTC_UDR_T_MASK, S5M_RTC_UDR_T_450_US);
+               if (ret < 0)
+                       dev_err(info->dev, "%s: fail to change UDR time: %d\n",
+                                       __func__, ret);
 
-       /* Set RTC control register : Binary mode, 24hour mode */
-       data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
-       data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+               /* Set RTC control register : Binary mode, 24hour mode */
+               data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+               data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+
+               ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
+               break;
+
+       case S2MPS14X:
+               data[0] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
+               ret = regmap_write(info->regmap, info->regs->ctrl, data[0]);
+               break;
+
+       default:
+               return -EINVAL;
+       }
 
        info->rtc_24hr_mode = 1;
-       ret = regmap_raw_write(info->regmap, S5M_ALARM0_CONF, data, 2);
        if (ret < 0) {
                dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
                        __func__, ret);
        switch (pdata->device_type) {
        case S2MPS14X:
                regmap_cfg = &s2mps14_rtc_regmap_config;
+               info->regs = &s2mps_rtc_regs;
                break;
        case S5M8763X:
                regmap_cfg = &s5m_rtc_regmap_config;
        info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
        switch (pdata->device_type) {
+       case S2MPS14X:
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
+                               S2MPS14_IRQ_RTCA0);
+               break;
+
        case S5M8763X:
                info->irq = regmap_irq_get_virq(s5m87xx->irq_data,
                                S5M8763_IRQ_ALARM0);
 static SIMPLE_DEV_PM_OPS(s5m_rtc_pm_ops, s5m_rtc_suspend, s5m_rtc_resume);
 
 static const struct platform_device_id s5m_rtc_id[] = {
-       { "s5m-rtc", 0 },
+       { "s5m-rtc",            S5M8767X },
+       { "s2mps14-rtc",        S2MPS14X },
 };
 
 static struct platform_driver s5m_rtc_driver = {
 
 /* Module information */
 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
-MODULE_DESCRIPTION("Samsung S5M RTC driver");
+MODULE_DESCRIPTION("Samsung S5M/S2MPS14 RTC driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:s5m-rtc");