phonepad:improve rtc-tps65910 code
authorlw <lw@rock-chips.com>
Mon, 30 Jul 2012 06:59:31 +0000 (14:59 +0800)
committerlw <lw@rock-chips.com>
Mon, 30 Jul 2012 06:59:31 +0000 (14:59 +0800)
drivers/mfd/tps65910-irq.c [changed mode: 0644->0755]
drivers/mfd/tps65910.c
drivers/regulator/tps65910-regulator.c [changed mode: 0644->0755]
drivers/rtc/rtc-tps65910.c
include/linux/mfd/tps65910.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index c9ed5c0..bcec383
@@ -45,7 +45,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data)
        u32 irq_mask;
        u8 reg;
        int i;
-
+       
        tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
        irq_sts = reg;
        tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
@@ -169,17 +169,27 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
 {
        int ret, cur_irq;
        int flags = IRQF_ONESHOT;
+       u8 reg;
 
        if (!irq) {
                dev_warn(tps65910->dev, "No interrupt support, no core IRQ\n");
-               return -EINVAL;
+               return 0;
        }
 
        if (!pdata || !pdata->irq_base) {
                dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n");
-               return -EINVAL;
+               return 0;
        }
 
+       /* Clear unattended interrupts */
+       tps65910->read(tps65910, TPS65910_INT_STS, 1, &reg);
+       tps65910->write(tps65910, TPS65910_INT_STS, 1, &reg);
+       tps65910->read(tps65910, TPS65910_INT_STS2, 1, &reg);
+       tps65910->write(tps65910, TPS65910_INT_STS2, 1, &reg);
+       tps65910->read(tps65910, TPS65910_INT_STS3, 1, &reg);
+       tps65910->write(tps65910, TPS65910_INT_STS3, 1, &reg);
+
+       /* Mask top level interrupts */
        tps65910->irq_mask = 0xFFFFFF;
 
        mutex_init(&tps65910->irq_lock);
index 1f3d30a938ec17b95ec5cf75daeebceb1cc20de9..b000f3ba9b7be09658896485995f8dca7d786e27 100755 (executable)
@@ -44,7 +44,7 @@ static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
        struct i2c_client *i2c = tps65910->i2c_client;
        struct i2c_msg xfer[2];
        int ret;
-       
+       int i;
 
        /* Write register */
        xfer[0].addr = i2c->addr;
@@ -61,7 +61,8 @@ static int tps65910_i2c_read(struct tps65910 *tps65910, u8 reg,
        xfer[1].scl_rate = 200*1000;
 
        ret = i2c_transfer(i2c->adapter, xfer, 2);
-       //printk("%s:reg=0x%x,value=0x%x\n",__func__,reg,*(char *)dest);
+       //for(i=0;i<bytes;i++)
+       //printk("%s:reg=0x%x,value=0x%x\n",__func__,reg+i,*(u8 *)dest++);
        if (ret == 2)
                ret = 0;
        else if (ret >= 0)
@@ -77,15 +78,17 @@ static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
        /* we add 1 byte for device register */
        u8 msg[TPS65910_MAX_REGISTER + 1];
        int ret;
+       int i;
        
        if (bytes > TPS65910_MAX_REGISTER)
                return -EINVAL;
-
-       //printk("%s:reg=0x%x,value=0x%x\n",__func__,reg,*(char *)&src);
        
        msg[0] = reg;
        memcpy(&msg[1], src, bytes);
 
+       //for(i=0;i<bytes;i++)
+       //printk("%s:reg=0x%x,value=0x%x\n",__func__,reg+i,msg[i+1]);
+       
        ret = i2c_master_send(i2c, msg, bytes + 1);
        if (ret < 0)
                return ret;
@@ -95,6 +98,94 @@ static int tps65910_i2c_write(struct tps65910 *tps65910, u8 reg,
        return 0;
 }
 
+static inline int tps65910_read(struct tps65910 *tps65910, u8 reg)
+{
+       u8 val;
+       int err;
+
+       err = tps65910->read(tps65910, reg, 1, &val);
+       if (err < 0)
+               return err;
+
+       return val;
+}
+
+static inline int tps65910_write(struct tps65910 *tps65910, u8 reg, u8 val)
+{
+       return tps65910->write(tps65910, reg, 1, &val);
+}
+
+int tps65910_reg_read(struct tps65910 *tps65910, u8 reg)
+{
+       int data;
+
+       mutex_lock(&tps65910->io_mutex);
+
+       data = tps65910_read(tps65910, reg);
+       if (data < 0)
+               dev_err(tps65910->dev, "Read from reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65910->io_mutex);
+       return data;
+}
+EXPORT_SYMBOL_GPL(tps65910_reg_read);
+
+int tps65910_reg_write(struct tps65910 *tps65910, u8 reg, u8 val)
+{
+       int err;
+
+       mutex_lock(&tps65910->io_mutex);
+
+       err = tps65910_write(tps65910, reg, val);
+       if (err < 0)
+               dev_err(tps65910->dev, "Write for reg 0x%x failed\n", reg);
+
+       mutex_unlock(&tps65910->io_mutex);
+       return err;
+}
+EXPORT_SYMBOL_GPL(tps65910_reg_write);
+
+/**
+ * tps65910_bulk_read: Read multiple tps65910 registers
+ *
+ * @tps65910: Device to read from
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to fill.
+ */
+int tps65910_bulk_read(struct tps65910 *tps65910, u8 reg,
+                    int count, u8 *buf)
+{
+       int ret;
+
+       mutex_lock(&tps65910->io_mutex);
+       
+       ret = tps65910->read(tps65910, reg, count, buf);
+
+       mutex_unlock(&tps65910->io_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tps65910_bulk_read);
+
+int tps65910_bulk_write(struct tps65910 *tps65910, u8 reg,
+                    int count, u8 *buf)
+{
+       int ret;
+
+       mutex_lock(&tps65910->io_mutex);
+       
+       ret = tps65910->write(tps65910, reg, count, buf);
+
+       mutex_unlock(&tps65910->io_mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tps65910_bulk_write);
+
+
+
+
 int tps65910_set_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
 {
        u8 data;
@@ -130,7 +221,7 @@ int tps65910_clear_bits(struct tps65910 *tps65910, u8 reg, u8 mask)
                goto out;
        }
 
-       data &= mask;
+       data &= ~mask;
        err = tps65910_i2c_write(tps65910, reg, 1, &data);
        if (err)
                dev_err(tps65910->dev, "write to reg %x failed\n", reg);
@@ -158,7 +249,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        init_data->irq = pmic_plat_data->irq;
-       init_data->irq_base = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq_base;
 
        tps65910 = kzalloc(sizeof(struct tps65910), GFP_KERNEL);
        if (tps65910 == NULL)
@@ -201,7 +292,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
                        goto err;
                }
        }
-
+       printk("%s:irq=%d,irq_base=%d\n",__func__,init_data->irq,init_data->irq_base);
        return ret;
 
 err:
old mode 100644 (file)
new mode 100755 (executable)
index ca736ad..0739da5
@@ -402,7 +402,7 @@ out:
        return err;
 }
 
-static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
+static int tps65910_pmic_reg_read(struct tps65910_reg *pmic, u8 reg)
 {
        int data;
 
@@ -416,7 +416,7 @@ static int tps65910_reg_read(struct tps65910_reg *pmic, u8 reg)
        return data;
 }
 
-static int tps65910_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val)
+static int tps65910_pmic_reg_write(struct tps65910_reg *pmic, u8 reg, u8 val)
 {
        int err;
 
@@ -507,7 +507,7 @@ static int tps65910_is_enabled(struct regulator_dev *dev)
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read(pmic, reg);
+       value = tps65910_pmic_reg_read(pmic, reg);
        if (value < 0)
                return value;
 
@@ -580,7 +580,7 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read(pmic, reg);
+       value = tps65910_pmic_reg_read(pmic, reg);
        if (value < 0)
                return value;
 
@@ -600,28 +600,28 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               opvsel = tps65910_reg_read(pmic, TPS65910_VDD1_OP);
-               mult = tps65910_reg_read(pmic, TPS65910_VDD1);
+               opvsel = tps65910_pmic_reg_read(pmic, TPS65910_VDD1_OP);
+               mult = tps65910_pmic_reg_read(pmic, TPS65910_VDD1);
                mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read(pmic, TPS65910_VDD1_SR);
+               srvsel = tps65910_pmic_reg_read(pmic, TPS65910_VDD1_SR);
                sr = opvsel & VDD1_OP_CMD_MASK;
                opvsel &= VDD1_OP_SEL_MASK;
                srvsel &= VDD1_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65910_REG_VDD2:
-               opvsel = tps65910_reg_read(pmic, TPS65910_VDD2_OP);
-               mult = tps65910_reg_read(pmic, TPS65910_VDD2);
+               opvsel = tps65910_pmic_reg_read(pmic, TPS65910_VDD2_OP);
+               mult = tps65910_pmic_reg_read(pmic, TPS65910_VDD2);
                mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read(pmic, TPS65910_VDD2_SR);
+               srvsel = tps65910_pmic_reg_read(pmic, TPS65910_VDD2_SR);
                sr = opvsel & VDD2_OP_CMD_MASK;
                opvsel &= VDD2_OP_SEL_MASK;
                srvsel &= VDD2_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65911_REG_VDDCTRL:
-               opvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_OP);
-               srvsel = tps65910_reg_read(pmic, TPS65911_VDDCTRL_SR);
+               opvsel = tps65910_pmic_reg_read(pmic, TPS65911_VDDCTRL_OP);
+               srvsel = tps65910_pmic_reg_read(pmic, TPS65911_VDDCTRL_SR);
                sr = opvsel & VDDCTRL_OP_CMD_MASK;
                opvsel &= VDDCTRL_OP_SEL_MASK;
                srvsel &= VDDCTRL_SR_SEL_MASK;
@@ -661,7 +661,7 @@ static int tps65910_get_voltage(struct regulator_dev *dev)
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read(pmic, reg);
+       value = tps65910_pmic_reg_read(pmic, reg);
        if (value < 0)
                return value;
 
@@ -700,7 +700,7 @@ static int tps65911_get_voltage(struct regulator_dev *dev)
 
        reg = pmic->get_ctrl_reg(id);
 
-       value = tps65910_reg_read(pmic, reg);
+       value = tps65910_pmic_reg_read(pmic, reg);
 
        switch (id) {
        case TPS65911_REG_LDO1:
@@ -759,7 +759,7 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                tps65910_modify_bits(pmic, TPS65910_VDD1,
                                (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
                                                VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
+               tps65910_pmic_reg_write(pmic, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
                dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
@@ -770,11 +770,11 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                tps65910_modify_bits(pmic, TPS65910_VDD2,
                                (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
                                                VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write(pmic, TPS65910_VDD2_OP, vsel);
+               tps65910_pmic_reg_write(pmic, TPS65910_VDD2_OP, vsel);
                break;
        case TPS65911_REG_VDDCTRL:
                vsel = selector + 3;
-               tps65910_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel);
+               tps65910_pmic_reg_write(pmic, TPS65911_VDDCTRL_OP, vsel);
        }
 
        return 0;
@@ -1090,18 +1090,18 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
                                (tps65910_chip_id(mfd) == TPS65911))) {
                int op_reg_add = pmic->get_ctrl_reg(id) + 1;
                int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
-               int opvsel = tps65910_reg_read(pmic, op_reg_add);
-               int srvsel = tps65910_reg_read(pmic, sr_reg_add);
+               int opvsel = tps65910_pmic_reg_read(pmic, op_reg_add);
+               int srvsel = tps65910_pmic_reg_read(pmic, sr_reg_add);
                if (opvsel & VDD1_OP_CMD_MASK) {
                        u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
-                       ret = tps65910_reg_write(pmic, op_reg_add, reg_val);
+                       ret = tps65910_pmic_reg_write(pmic, op_reg_add, reg_val);
                        if (ret < 0) {
                                dev_err(mfd->dev,
                                        "Error in configuring op register\n");
                                return ret;
                        }
                }
-               ret = tps65910_reg_write(pmic, sr_reg_add, 0);
+               ret = tps65910_pmic_reg_write(pmic, sr_reg_add, 0);
                if (ret < 0) {
                        dev_err(mfd->dev, "Error in settting sr register\n");
                        return ret;
index 93290a16ad2285c85b80acd60d52544e9afc3fc7..43e9235c67c06c33cfdeb194b262a68dc9cb4b12 100755 (executable)
@@ -1,35 +1,31 @@
 /*
- * rtc-tps65910.c -- TPS65910 Real Time Clock interface
+ *     Real Time Clock driver for Wolfson Microelectronics tps65910
  *
- * Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
- * Author: Umesh K <umeshk@mistralsolutions.com>
+ *     Copyright (C) 2009 Wolfson Microelectronics PLC.
  *
- * Based on rtc-twl.c
+ *  Author: Mark Brown <broonie@opensource.wolfsonmicro.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.
  *
- * 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.
  */
 
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
 #include <linux/module.h>
-#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
 #include <linux/rtc.h>
+#include <linux/slab.h>
 #include <linux/bcd.h>
-#include <linux/platform_device.h>
 #include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/completion.h>
 #include <linux/mfd/tps65910.h>
-#include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
 
-#if 0
-#define DBG(x...)      printk(KERN_INFO x)
-#else
-#define DBG(x...)
-#endif
 
 /* RTC Definitions */
 /* RTC_CTRL_REG bitfields */
 #define BIT_RTC_PWDN                           0x40
 
 /* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
-#define ALL_TIME_REGS                          6
-
-/*
- * Supports 1 byte read from TPS65910 RTC register.
- */
-static int tps65910_rtc_read_u8(u8 *data, u8 reg)
-{
-       int ret;
-
-       ret = tps65910_i2c_read_u8(TPS65910_I2C_ID0, data, reg);
-
-       if (ret < 0)
-               pr_err("tps65910_rtc: Could not read TPS65910"
-                               "register %X - error %d\n", reg, ret);
-       return ret;
-}
-
-/*
- * Supports 1 byte write to TPS65910 RTC registers.
- */
-static int tps65910_rtc_write_u8(u8 data, u8 reg)
-{
-       int ret;
+#define ALL_TIME_REGS                          7
+#define ALL_ALM_REGS                           6
 
-       ret = tps65910_i2c_write_u8(TPS65910_I2C_ID0, data, reg);
-       if (ret < 0)
-               pr_err("tps65910_rtc: Could not write TPS65910"
-                               "register %X - error %d\n", reg, ret);
-       return ret;
-}
 
-/*
- * Cache the value for timer/alarm interrupts register; this is
- * only changed by callers holding rtc ops lock (or resume).
- */
-static unsigned char rtc_irq_bits;
+#define RTC_SET_TIME_RETRIES   5
+#define RTC_GET_TIME_RETRIES   5
 
-/*
- * Enable 1/second update and/or alarm interrupts.
- */
-static int set_rtc_irq_bit(unsigned char bit)
-{
-       unsigned char val;
-       int ret;
-
-       val = rtc_irq_bits | bit;
-       val |= bit;
-       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret == 0)
-               rtc_irq_bits = val;
 
-       return ret;
-}
+struct tps65910_rtc {
+       struct tps65910 *tps65910;
+       struct rtc_device *rtc;
+       unsigned int alarm_enabled:1;
+};
 
 /*
- * Disable update and/or alarm interrupts.
+ * Read current time and date in RTC
  */
-static int mask_rtc_irq_bit(unsigned char bit)
-{
-       unsigned char val;
-       int ret;
-
-       val = rtc_irq_bits & ~bit;
-       ret = tps65910_rtc_write_u8(val, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret == 0)
-               rtc_irq_bits = val;
-
-       return ret;
-}
-
-static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
-{
-       int ret;
-
-       if (enabled)
-               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-       else
-               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-
-       return ret;
-}
-
-static int tps65910_rtc_update_irq_enable(struct device *dev, unsigned enabled)
+static int tps65910_rtc_readtime(struct device *dev, struct rtc_time *tm)
 {
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
+       struct tps65910 *tps65910 = tps65910_rtc->tps65910;
        int ret;
+       int count = 0;
+       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       u8 rtc_ctl;
 
-       if (enabled)
-               ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-       else
-               ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+       /*Dummy read*/  
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
+       
+       /* Has the RTC been programmed? */
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read RTC control: %d\n", ret);
+               return ret;
+       }
 
-       return ret;
-}
+       rtc_ctl = ret & (~BIT_RTC_CTRL_REG_RTC_V_OPT_M);
 
-#if 1 /* Debugging periodic interrupts */
-/*
- * We will just handle setting the frequency and make use the framework for
- * reading the periodic interupts.
- *
- * @freq: Current periodic IRQ freq:
- * bit 0: every second
- * bit 1: every minute
- * bit 2: every hour
- * bit 3: every day
- */
+       ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
+       if (ret < 0) {
+               dev_err(dev, "Failed to write RTC control: %d\n", ret);
+               return ret;
+       }
 
-static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
-{
-       struct rtc_device *rtc = dev_get_drvdata(dev);
+       
+       /* Read twice to make sure we don't read a corrupt, partially
+        * incremented, value.
+        */
+       do {
+               ret = tps65910_bulk_read(tps65910, TPS65910_SECONDS,
+                                      ALL_TIME_REGS, rtc_data);
+               if (ret != 0)
+                       continue;
+
+               tm->tm_sec = bcd2bin(rtc_data[0]);
+               tm->tm_min = bcd2bin(rtc_data[1]);
+               tm->tm_hour = bcd2bin(rtc_data[2]);
+               tm->tm_mday = bcd2bin(rtc_data[3]);
+               tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
+               tm->tm_year = bcd2bin(rtc_data[5]) + 100;       
+               tm->tm_wday = bcd2bin(rtc_data[6]);
+
+               dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+                       1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+                       tm->tm_hour, tm->tm_min, tm->tm_sec);
+               
+               return ret;
 
-       if (freq < 0 || freq > 3)
-               return -EINVAL;
+       } while (++count < RTC_GET_TIME_RETRIES);
+       dev_err(dev, "Timed out reading current time\n");
 
-       rtc->irq_freq = freq;
-       /* set rtc irq freq to user defined value */
-       set_rtc_irq_bit(freq);
+       return -EIO;
 
-       return 0;
 }
-#endif
 
 /*
- * Gets current TPS65910 RTC time and date parameters.
- *
- * The RTC's time/alarm representation is not what gmtime(3) requires
- * Linux to use:
- *
- *  - Months are 1..12 vs Linux 0-11
- *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ * Set current time and date in RTC
  */
-static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
+       struct tps65910 *tps65910 = tps65910_rtc->tps65910;
        int ret;
-       u8 save_control;
-
-       tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               return ret;
-
-       save_control &= ~BIT_RTC_CTRL_REG_RTC_V_OPT_M;
-
-       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               return ret;
-
-       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_MINUTES);
+       u8 rtc_ctl;     
+       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       
+       rtc_data[0] = bin2bcd(tm->tm_sec);
+       rtc_data[1] = bin2bcd(tm->tm_min);
+       rtc_data[2] = bin2bcd(tm->tm_hour);
+       rtc_data[3] = bin2bcd(tm->tm_mday);
+       rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+       rtc_data[5] = bin2bcd(tm->tm_year - 100);
+       rtc_data[6] = bin2bcd(tm->tm_wday);
+
+       /*Dummy read*/  
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
+       
+       /* Stop RTC while updating the TC registers */
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to read RTC control: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_HOURS);
+       
+       rtc_ctl = ret & (~BIT_RTC_CTRL_REG_STOP_RTC_M);
+
+       ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to write RTC control: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_DAYS);
+       
+       /* update all the time registers in one shot */
+       ret = tps65910_bulk_write(tps65910, TPS65910_SECONDS,
+                                      ALL_TIME_REGS, rtc_data);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to read RTC times: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_MONTHS);
+       
+       /*Dummy read*/  
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
+       
+       /* Start RTC again */
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to read RTC control: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_YEARS);
+       
+       rtc_ctl = ret | BIT_RTC_CTRL_REG_STOP_RTC_M;
+
+       ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to write RTC control: %d\n", ret);
                return ret;
        }
 
-       tm->tm_sec = bcd2bin(rtc_data[0]);
-       tm->tm_min = bcd2bin(rtc_data[1]);
-       tm->tm_hour = bcd2bin(rtc_data[2]);
-       tm->tm_mday = bcd2bin(rtc_data[3]);
-       tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
-       tm->tm_year = bcd2bin(rtc_data[5]) + 100;
-
-       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
-       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
-       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
-       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
-       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
-       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
-       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
-
-       return ret;
+       return 0;
 }
 
-static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm)
+/*
+ * Read alarm time and date in RTC
+ */
+static int tps65910_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-       unsigned char save_control;
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
        int ret;
+       unsigned char alrm_data[ALL_ALM_REGS + 1];
 
-       DBG("%s [%d]tm_wday=%d \n",__FUNCTION__,__LINE__,tm->tm_wday);
-       DBG("%s [%d]tm_sec=%d \n",__FUNCTION__,__LINE__,tm->tm_sec);
-       DBG("%s [%d]tm_min=%d \n",__FUNCTION__,__LINE__,tm->tm_min);
-       DBG("%s [%d]tm_hour=%d \n",__FUNCTION__,__LINE__,tm->tm_hour);
-       DBG("%s [%d]tm_mday=%d \n",__FUNCTION__,__LINE__,tm->tm_mday);
-       DBG("%s [%d]tm_mon=%d \n",__FUNCTION__,__LINE__,tm->tm_mon);
-       DBG("%s [%d]tm_year=%d \n",__FUNCTION__,__LINE__,tm->tm_year);
+       ret = tps65910_bulk_read(tps65910_rtc->tps65910, TPS65910_ALARM_SECONDS,
+                              ALL_ALM_REGS, alrm_data);
+       if (ret != 0) {
+               dev_err(dev, "Failed to read alarm time: %d\n", ret);
+               return ret;
+       }
 
-       rtc_data[1] = bin2bcd(tm->tm_sec);
-       rtc_data[2] = bin2bcd(tm->tm_min);
-       rtc_data[3] = bin2bcd(tm->tm_hour);
-       rtc_data[4] = bin2bcd(tm->tm_mday);
-       rtc_data[5] = bin2bcd(tm->tm_mon + 1);
-       rtc_data[6] = bin2bcd(tm->tm_year - 100);
+       /* some of these fields may be wildcard/"match all" */
+       alrm->time.tm_sec = bcd2bin(alrm_data[0]);
+       alrm->time.tm_min = bcd2bin(alrm_data[1]);
+       alrm->time.tm_hour = bcd2bin(alrm_data[2]);
+       alrm->time.tm_mday = bcd2bin(alrm_data[3]);
+       alrm->time.tm_mon = bcd2bin(alrm_data[4]) - 1;
+       alrm->time.tm_year = bcd2bin(alrm_data[5]) + 100;
+
+       ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read RTC control: %d\n", ret);
+               return ret;
+       }
 
-       /*Dummy read*/
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+       if (ret & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
+               alrm->enabled = 1;
+       else
+               alrm->enabled = 0;
 
-       /* Stop RTC while updating the TC registers */
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               goto out;
+       return 0;
+}
 
-       save_control &= ~BIT_RTC_CTRL_REG_STOP_RTC_M;
+static int tps65910_rtc_stop_alarm(struct tps65910_rtc *tps65910_rtc)
+{
+       tps65910_rtc->alarm_enabled = 0;
 
-       tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
+       return tps65910_clear_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
+                              BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 
-       /* update all the time registers in one shot */
-       ret = tps65910_rtc_write_u8(rtc_data[1], TPS65910_REG_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[2], TPS65910_REG_MINUTES);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[3], TPS65910_REG_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[4], TPS65910_REG_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[5], TPS65910_REG_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(rtc_data[6], TPS65910_REG_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
+}
 
-       /*Dummy read*/
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
+static int tps65910_rtc_start_alarm(struct tps65910_rtc *tps65910_rtc)
+{
+       tps65910_rtc->alarm_enabled = 1;
 
-       ret = tps65910_rtc_read_u8(&save_control, TPS65910_REG_RTC_CTRL);
-       if (ret < 0)
-               goto out;
-       /* Start back RTC */
-       save_control |= BIT_RTC_CTRL_REG_STOP_RTC_M;
-       ret = tps65910_rtc_write_u8(save_control, TPS65910_REG_RTC_CTRL);
+       return tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
+                              BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
 
-out:
-       return ret;
 }
 
-/*
- * Gets current TPS65910 RTC alarm time.
- */
-static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int tps65910_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
-       unsigned char rtc_data[ALL_TIME_REGS + 1];
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
        int ret;
+       unsigned char alrm_data[ALL_TIME_REGS + 1];
 
-       ret = tps65910_rtc_read_u8(&rtc_data[0], TPS65910_REG_ALARM_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[1], TPS65910_REG_ALARM_MINUTES);
+       ret = tps65910_rtc_stop_alarm(tps65910_rtc);
        if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+               dev_err(dev, "Failed to stop alarm: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[2], TPS65910_REG_ALARM_HOURS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[3], TPS65910_REG_ALARM_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_read_u8(&rtc_data[4], TPS65910_REG_ALARM_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
+
+       alrm_data[0] = bin2bcd(alrm->time.tm_sec);
+       alrm_data[1] = bin2bcd(alrm->time.tm_min);
+       alrm_data[2] = bin2bcd(alrm->time.tm_hour);
+       alrm_data[3] = bin2bcd(alrm->time.tm_mday);
+       alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
+       alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
+
+       ret = tps65910_bulk_write(tps65910_rtc->tps65910, TPS65910_ALARM_SECONDS,
+                              ALL_ALM_REGS, alrm_data);
+       if (ret != 0) {
+               dev_err(dev, "Failed to read alarm time: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_read_u8(&rtc_data[5], TPS65910_REG_ALARM_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_read_time error %d\n", ret);
-               return ret;
+
+       if (alrm->enabled) {
+               ret = tps65910_rtc_start_alarm(tps65910_rtc);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to start alarm: %d\n", ret);
+                       return ret;
+               }
        }
 
-       /* some of these fields may be wildcard/"match all" */
-       alm->time.tm_sec = bcd2bin(rtc_data[0]);
-       alm->time.tm_min = bcd2bin(rtc_data[1]);
-       alm->time.tm_hour = bcd2bin(rtc_data[2]);
-       alm->time.tm_mday = bcd2bin(rtc_data[3]);
-       alm->time.tm_mon = bcd2bin(rtc_data[4]) - 1;
-       alm->time.tm_year = bcd2bin(rtc_data[5]) + 100;
+       return 0;
+}
 
-       /* report cached alarm enable state */
-       if (rtc_irq_bits & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M)
-               alm->enabled = 1;
+static int tps65910_rtc_alarm_irq_enable(struct device *dev,
+                                      unsigned int enabled)
+{
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
 
-       return ret;
+       if (enabled)
+               return tps65910_rtc_start_alarm(tps65910_rtc);
+       else
+               return tps65910_rtc_stop_alarm(tps65910_rtc);
 }
 
-static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+static int tps65910_rtc_update_irq_enable(struct device *dev,
+                                      unsigned int enabled)
 {
-       unsigned char alarm_data[ALL_TIME_REGS + 1];
-       int ret;
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
 
-       ret = tps65910_rtc_alarm_irq_enable(dev, 0);
-       if (ret)
-               goto out;
+       if (enabled)
+               return tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
+                              BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+       else
+               return tps65910_clear_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
+                              BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+}
 
-       alarm_data[1] = bin2bcd(alm->time.tm_sec);
-       alarm_data[2] = bin2bcd(alm->time.tm_min);
-       alarm_data[3] = bin2bcd(alm->time.tm_hour);
-       alarm_data[4] = bin2bcd(alm->time.tm_mday);
-       alarm_data[5] = bin2bcd(alm->time.tm_mon + 1);
-       alarm_data[6] = bin2bcd(alm->time.tm_year - 100);
+/*
+ * We will just handle setting the frequency and make use the framework for
+ * reading the periodic interupts.
+ *
+ * @freq: Current periodic IRQ freq:
+ * bit 0: every second
+ * bit 1: every minute
+ * bit 2: every hour
+ * bit 3: every day
+ */
+static int tps65910_rtc_irq_set_freq(struct device *dev, int freq)
+{      
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(dev);
+       int ret;        
+       u8 rtc_ctl;     
+       
+       if (freq < 0 || freq > 3)
+               return -EINVAL;
 
-       /* update all the alarm registers in one shot */
-       ret = tps65910_rtc_write_u8(alarm_data[1], TPS65910_REG_ALARM_SECONDS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[2], TPS65910_REG_ALARM_MINUTES);
+       ret = tps65910_reg_read(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS);
        if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
+               dev_err(dev, "Failed to read RTC interrupt: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_write_u8(alarm_data[3], TPS65910_REG_ALARM_HOURS);
+       
+       rtc_ctl = ret | freq;
+       
+       ret = tps65910_reg_write(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS, rtc_ctl);
        if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
+               dev_err(dev, "Failed to write RTC control: %d\n", ret);
                return ret;
        }
-       ret = tps65910_rtc_write_u8(alarm_data[4], TPS65910_REG_ALARM_DAYS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[5], TPS65910_REG_ALARM_MONTHS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-       ret = tps65910_rtc_write_u8(alarm_data[6], TPS65910_REG_ALARM_YEARS);
-       if (ret < 0) {
-               dev_err(dev, "rtc_write_time error %d\n", ret);
-               return ret;
-       }
-
-       if (alm->enabled)
-               ret = tps65910_rtc_alarm_irq_enable(dev, 1);
-out:
+       
        return ret;
 }
 
 
-struct work_struct rtc_wq;
-unsigned long rtc_events;
-struct rtc_device *global_rtc;
 
-void tps65910_rtc_work(void  *data)
+static irqreturn_t tps65910_alm_irq(int irq, void *data)
 {
-       int res;
-       u8 rd_reg;
-       unsigned long events = 0;
+       struct tps65910_rtc *tps65910_rtc = data;
 
-       DBG("Enter::%s %d\n",__FUNCTION__,__LINE__);
+       rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_AF);
+       
+       return IRQ_HANDLED;
+}
 
-       res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
+static irqreturn_t tps65910_per_irq(int irq, void *data)
+{
+       struct tps65910_rtc *tps65910_rtc = data;
 
-       if (res < 0)
-               goto out;
-       /*
-        * Figure out source of interrupt: ALARM or TIMER in RTC_STATUS_REG.
-        * only one (ALARM or RTC) interrupt source may be enabled
-        * at time, we also could check our results
-        * by reading RTS_INTERRUPTS_REGISTER[IT_TIMER,IT_ALARM]
-        */
-       if (rd_reg & TPS65910_RTC_ALARM_IT) {
-               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_ALARM_IT,
-                               TPS65910_REG_INT_STS);
-               if (res < 0)
-                       goto out;
-
-               /*Dummy read -- mandatory for status register*/
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               mdelay(100);
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-
-               rtc_events |= RTC_IRQF | RTC_AF;
-       } else if (rd_reg & TPS65910_RTC_PERIOD_IT) {
-               res = tps65910_rtc_write_u8(rd_reg | TPS65910_RTC_PERIOD_IT,
-                               TPS65910_REG_INT_STS);
-               if (res < 0)
-                       goto out;
-
-               /*Dummy read -- mandatory for status register*/
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               mdelay(100);
-               res = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
-               rd_reg &= 0xC3;
-               res = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-               rtc_events |= RTC_IRQF | RTC_UF;
-       }
-out:
-       /* Notify RTC core on event */
-       events = rtc_events;
-       rtc_update_irq(global_rtc, 1, events);
+       rtc_update_irq(tps65910_rtc->rtc, 1, RTC_IRQF | RTC_UF);
+
+       //printk("%s:irq=%d\n",__func__,irq);
+       return IRQ_HANDLED;
 }
 
-static struct rtc_class_ops tps65910_rtc_ops = {
-       .read_time      = tps65910_rtc_read_time,
-       .set_time       = tps65910_rtc_set_time,
-       .read_alarm     = tps65910_rtc_read_alarm,
-       .set_alarm      = tps65910_rtc_set_alarm,
+static const struct rtc_class_ops tps65910_rtc_ops = {
+       .read_time = tps65910_rtc_readtime,
+       //.set_mmss = tps65910_rtc_set_mmss,
+       .set_time = tps65910_rtc_set_time,
+       .read_alarm = tps65910_rtc_readalarm,
+       .set_alarm = tps65910_rtc_setalarm,
        .alarm_irq_enable = tps65910_rtc_alarm_irq_enable,
-//     .update_irq_enable = tps65910_rtc_update_irq_enable,
-//     .irq_set_freq   = tps65910_rtc_irq_set_freq,
+       //.update_irq_enable = tps65910_rtc_update_irq_enable,
+       //.irq_set_freq = tps65910_rtc_irq_set_freq,
 };
 
-static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
+#ifdef CONFIG_PM
+/* Turn off the alarm if it should not be a wake source. */
+static int tps65910_rtc_suspend(struct device *dev)
 {
-       struct rtc_device *rtc;
-       int ret = 0, stop_run = 0;
-       u8 rd_reg;
-       struct rtc_time tm_def = {      //      2011.1.1 12:00:00 Saturday
-               .tm_wday = 6,
-               .tm_year = 111,
-               .tm_mon = 0,
-               .tm_mday = 1,
-               .tm_hour = 12,
-               .tm_min = 0,
-               .tm_sec = 0,
-       };
-
-       rtc = rtc_device_register(pdev->name,
-                       &pdev->dev, &tps65910_rtc_ops, THIS_MODULE);
-
-       if (IS_ERR(rtc)) {
-               ret = PTR_ERR(rtc);
-               dev_err(&pdev->dev, "can't register TPS65910 RTC device,\
-                                        err %ld\n", PTR_ERR(rtc));
-               goto out0;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
+       
+       if (tps65910_rtc->alarm_enabled && device_may_wakeup(&pdev->dev))
+               ret = tps65910_rtc_start_alarm(tps65910_rtc);
+       else
+               ret = tps65910_rtc_stop_alarm(tps65910_rtc);
+
+       if (ret != 0)
+               dev_err(&pdev->dev, "Failed to update RTC alarm: %d\n", ret);
+
+       return 0;
+}
+
+/* Enable the alarm if it should be enabled (in case it was disabled to
+ * prevent use as a wake source).
+ */
+static int tps65910_rtc_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
 
+       if (tps65910_rtc->alarm_enabled) {
+               ret = tps65910_rtc_start_alarm(tps65910_rtc);
+               if (ret != 0)
+                       dev_err(&pdev->dev,
+                               "Failed to restart RTC alarm: %d\n", ret);
        }
-       printk(KERN_INFO "TPS65910 RTC device successfully registered\n");
 
-       platform_set_drvdata(pdev, rtc);
-       /* Take rtc out of reset */
-       tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_DEVCTRL);
-       rd_reg &= ~BIT_RTC_PWDN;
-       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_DEVCTRL);
+       return 0;
+}
 
-       /* Dummy read to ensure that the register gets updated.
-        * Please refer tps65910 TRM table:25 for details
-        */
-       stop_run = 0;
-       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_STATUS);
+/* Unconditionally disable the alarm */
+static int tps65910_rtc_freeze(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct tps65910_rtc *tps65910_rtc = dev_get_drvdata(&pdev->dev);
+       int ret;
+       
+       ret = tps65910_rtc_stop_alarm(tps65910_rtc);
+       if (ret != 0)
+               dev_err(&pdev->dev, "Failed to stop RTC alarm: %d\n", ret);
+
+       return 0;
+}
+#else
+#define tps65910_rtc_suspend NULL
+#define tps65910_rtc_resume NULL
+#define tps65910_rtc_freeze NULL
+#endif
+
+struct platform_device *g_pdev;
+static int tps65910_rtc_probe(struct platform_device *pdev)
+{
+       struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
+       struct tps65910_rtc *tps65910_rtc;
+       int per_irq;
+       int alm_irq;
+       int ret = 0;
+       u8 rtc_ctl;
+       
+       struct rtc_time tm;
+       struct rtc_time tm_def = {      //      2012.1.1 12:00:00 Saturday
+                       .tm_wday = 6,
+                       .tm_year = 111,
+                       .tm_mon = 0,
+                       .tm_mday = 1,
+                       .tm_hour = 12,
+                       .tm_min = 0,
+                       .tm_sec = 0,
+               };
+       
+       tps65910_rtc = kzalloc(sizeof(*tps65910_rtc), GFP_KERNEL);
+       if (tps65910_rtc == NULL)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, tps65910_rtc);
+       tps65910_rtc->tps65910 = tps65910;
+       per_irq = tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
+       alm_irq = tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;
+       
+       /* Take rtc out of reset */
+       ret = tps65910_reg_read(tps65910, TPS65910_DEVCTRL);
        if (ret < 0) {
-               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
-               goto out1;
+               dev_err(&pdev->dev, "Failed to read TPS65910_DEVCTRL: %d\n", ret);
+               return ret;
        }
 
-       if (rd_reg & BIT_RTC_STATUS_REG_POWER_UP_M) {
-               dev_warn(&pdev->dev, "Power up reset detected.\n");
-               //      cwz:if rtc power up reset, set default time.
-               printk(KERN_INFO "TPS65910 RTC set to default time\n");
-               tps65910_rtc_set_time(&rtc->dev, &tm_def);
+       if(ret & BIT_RTC_PWDN)
+       {
+               rtc_ctl = ret & (~BIT_RTC_PWDN);
+
+               ret = tps65910_reg_write(tps65910, TPS65910_DEVCTRL, rtc_ctl);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
+                       return ret;
+               }
        }
-       if (!(rd_reg & BIT_RTC_STATUS_REG_RUN_M)) {
-               dev_warn(&pdev->dev, "RTC stop run.\n");
-               stop_run = 1;
+       
+       /*start rtc default*/
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_CTRL);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to read RTC control: %d\n", ret);
+               return ret;
        }
-       if (rd_reg & BIT_RTC_STATUS_REG_ALARM_M)
-               dev_warn(&pdev->dev, "Pending Alarm interrupt detected.\n");
 
-       /* Clear RTC Power up reset and pending alarm interrupts */
-       ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_STATUS);
-       if (ret < 0)
-               goto out1;
+       if(!(ret & BIT_RTC_CTRL_REG_STOP_RTC_M))
+       {
+               rtc_ctl = ret | BIT_RTC_CTRL_REG_STOP_RTC_M;
 
-       ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_INT_STS);
+               ret = tps65910_reg_write(tps65910, TPS65910_RTC_CTRL, rtc_ctl);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "Failed to write RTC control: %d\n", ret);
+                       return ret;
+               }
+       }
+       
+       ret = tps65910_reg_read(tps65910, TPS65910_RTC_STATUS);
        if (ret < 0) {
-               printk(KERN_ERR "TPS65910 RTC STATUS REG READ FAILED\n");
-               goto out1;
+               dev_err(&pdev->dev, "Failed to read RTC status: %d\n", ret);
+               return ret;
+       }
+               
+       /*set init time*/
+       ret = tps65910_rtc_readtime(&pdev->dev, &tm);
+       if (ret)
+       {
+               dev_err(&pdev->dev, "Failed to read RTC time\n");
+               return ret;
+       }
+       
+       ret = rtc_valid_tm(&tm);
+       if (ret) {
+               dev_err(&pdev->dev,"invalid date/time and init time\n");
+               tps65910_rtc_set_time(&pdev->dev, &tm_def); // 2011-01-01 12:00:00
+               dev_info(&pdev->dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+                               1900 + tm_def.tm_year, tm_def.tm_mon + 1, tm_def.tm_mday, tm_def.tm_wday,
+                               tm_def.tm_hour, tm_def.tm_min, tm_def.tm_sec);
        }
 
-       if (rd_reg & 0x40) {
-               printk(KERN_INFO "pending alarm interrupt!!! clearing!!!");
-               tps65910_rtc_write_u8(rd_reg, TPS65910_REG_INT_STS);
+       device_init_wakeup(&pdev->dev, 1);
+
+       tps65910_rtc->rtc = rtc_device_register("tps65910", &pdev->dev,
+                                             &tps65910_rtc_ops, THIS_MODULE);
+       if (IS_ERR(tps65910_rtc->rtc)) {
+               ret = PTR_ERR(tps65910_rtc->rtc);
+               goto err;
        }
 
-       global_rtc = rtc;
-
-       /* Link RTC IRQ handler to TPS65910 Core */
-       //tps65910_add_irq_work(TPS65910_RTC_ALARM_IRQ, tps65910_rtc_work);
-       //tps65910_add_irq_work(TPS65910_RTC_PERIOD_IRQ, tps65910_rtc_work);
-
-       /* Check RTC module status, Enable if it is off */
-       if (stop_run) {
-               dev_info(&pdev->dev, "Enabling TPS65910-RTC.\n");
-               //      cwz:if rtc stop, set default time, then enable rtc
-               printk(KERN_INFO "TPS65910 RTC set to default time\n");
-               tps65910_rtc_set_time(&rtc->dev, &tm_def);
-               ret = tps65910_rtc_read_u8(&rd_reg, TPS65910_REG_RTC_CTRL);
-               if (ret < 0)
-                       goto out1;
-
-               rd_reg |= BIT_RTC_CTRL_REG_STOP_RTC_M;
-               ret = tps65910_rtc_write_u8(rd_reg, TPS65910_REG_RTC_CTRL);
-               if (ret < 0)
-                       goto out1;
+       /*request rtc and alarm irq of tps65910*/
+       ret = request_threaded_irq(per_irq, NULL, tps65910_per_irq,
+                                  IRQF_TRIGGER_RISING, "RTC period",
+                                  tps65910_rtc);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "Failed to request periodic IRQ %d: %d\n",
+                       per_irq, ret);
        }
 
-       /* init cached IRQ enable bits */
-       ret = tps65910_rtc_read_u8(&rtc_irq_bits, TPS65910_REG_RTC_INTERRUPTS);
-       if (ret < 0)
-               goto out1;
+       ret = request_threaded_irq(alm_irq, NULL, tps65910_alm_irq,
+                                  IRQF_TRIGGER_RISING, "RTC alarm",
+                                  tps65910_rtc);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
+                       alm_irq, ret);
+       }
 
-       tps65910_rtc_write_u8(0x3F, TPS65910_REG_INT_MSK);
-       return ret;
+       //for rtc irq test
+       //tps65910_set_bits(tps65910_rtc->tps65910, TPS65910_RTC_INTERRUPTS,
+       //                             BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
+
+       g_pdev = pdev;
+       
+       printk("%s:ok\n",__func__);
+       
+       return 0;
 
-out1:
-       rtc_device_unregister(rtc);
-out0:
+err:
+       kfree(tps65910_rtc);
        return ret;
 }
 
-/*
- * Disable all TPS65910 RTC module interrupts.
- * Sets status flag to free.
- */
 static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
 {
-       /* leave rtc running, but disable irqs */
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
-       int irq = platform_get_irq(pdev, 0);
-
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-
+       struct tps65910_rtc *tps65910_rtc = platform_get_drvdata(pdev);
+       int per_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_PERIOD;
+       int alm_irq = tps65910_rtc->tps65910->irq_base + TPS65910_IRQ_RTC_ALARM;
 
-       free_irq(irq, rtc);
+       free_irq(alm_irq, tps65910_rtc);
+       free_irq(per_irq, tps65910_rtc);
+       rtc_device_unregister(tps65910_rtc->rtc);
+       kfree(tps65910_rtc);
 
-       rtc_device_unregister(rtc);
-       platform_set_drvdata(pdev, NULL);
        return 0;
 }
 
-static void tps65910_rtc_shutdown(struct platform_device *pdev)
-{
-       /* mask timer interrupts, but leave alarm interrupts on to enable
-        * power-on when alarm is triggered
-        */
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-}
+static const struct dev_pm_ops tps65910_rtc_pm_ops = {
+       .suspend = tps65910_rtc_suspend,
+       .resume = tps65910_rtc_resume,
 
-#ifdef CONFIG_PM
+       .freeze = tps65910_rtc_freeze,
+       .thaw = tps65910_rtc_resume,
+       .restore = tps65910_rtc_resume,
 
-static unsigned char irqstat;
+       .poweroff = tps65910_rtc_suspend,
+};
 
-static
-int tps65910_rtc_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       irqstat = rtc_irq_bits;
-       mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-       return 0;
-}
+static struct platform_driver tps65910_rtc_driver = {
+       .probe = tps65910_rtc_probe,
+       .remove = __devexit_p(tps65910_rtc_remove),
+       .driver = {
+               .name = "tps65910-rtc",
+               .pm = &tps65910_rtc_pm_ops,
+       },
+};
 
-static int tps65910_rtc_resume(struct platform_device *pdev)
+static ssize_t rtc_tps65910_test_write(struct file *file, 
+                       const char __user *buf, size_t count, loff_t *offset)
 {
-       set_rtc_irq_bit(irqstat);
-       return 0;
+       char nr_buf[8];
+       int nr = 0, ret;
+       struct platform_device *pdev;   
+       struct rtc_time tm;
+       
+       if(count > 3)
+               return -EFAULT;
+       ret = copy_from_user(nr_buf, buf, count);
+       if(ret < 0)
+               return -EFAULT;
+
+       sscanf(nr_buf, "%d", &nr);
+       if(nr >= 2 || nr < 0)
+       {
+               printk("%s:data is error\n",__func__);
+               return -EFAULT;
+       }
+
+       if(!g_pdev)
+               return -EFAULT;
+       else
+               pdev = g_pdev;
+
+       if(nr == 0)
+       {       
+               tm.tm_wday = 6;
+               tm.tm_year = 111;
+               tm.tm_mon = 0;
+               tm.tm_mday = 1;
+               tm.tm_hour = 12;
+               tm.tm_min = 0;
+               tm.tm_sec = 0;
+       
+               ret = tps65910_rtc_set_time(&pdev->dev, &tm); // 2011-01-01 12:00:00
+               if (ret)
+               {
+                       dev_err(&pdev->dev, "Failed to set RTC time\n");
+                       return -EFAULT;
+               }
+
+       }
+       
+       /*set init time*/
+       ret = tps65910_rtc_readtime(&pdev->dev, &tm);
+       if (ret)
+               dev_err(&pdev->dev, "Failed to read RTC time\n");
+       else
+               dev_info(&pdev->dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+                       1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, tm.tm_wday,
+                       tm.tm_hour, tm.tm_min, tm.tm_sec);
+               
+       if(!ret)
+       printk("%s:ok\n",__func__);
+       else
+       printk("%s:error\n",__func__);
+       
+       return count;
 }
 
-#else
-#define tps65910_rtc_suspend NULL
-#define tps65910_rtc_resume  NULL
-#endif
-
+static const struct file_operations rtc_tps65910_test_fops = {
+       .write = rtc_tps65910_test_write,
+};
 
-static struct platform_driver tps65910rtc_driver = {
-       .probe          = tps65910_rtc_probe,
-       .remove         = __devexit_p(tps65910_rtc_remove),
-       .shutdown       = tps65910_rtc_shutdown,
-       .suspend        = tps65910_rtc_suspend,
-       .resume         = tps65910_rtc_resume,
-       .driver         = {
-               .owner  = THIS_MODULE,
-               .name   = "tps65910_rtc",
-       },
+static struct miscdevice rtc_tps65910_test_misc = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "rtc_tps65910_test",
+       .fops = &rtc_tps65910_test_fops,
 };
 
-//extern int board_wm831x ;
+
 static int __init tps65910_rtc_init(void)
 {
-//     if (board_wm831x == 1)
-//     {
-//             printk("board with wm831 not tps65910,so skip register tps65910\n");
-//             return 0;
-//     }
-
-       return platform_driver_register(&tps65910rtc_driver);
+       misc_register(&rtc_tps65910_test_misc);
+       return platform_driver_register(&tps65910_rtc_driver);
 }
 module_init(tps65910_rtc_init);
 
 static void __exit tps65910_rtc_exit(void)
-{
-       platform_driver_unregister(&tps65910rtc_driver);
+{      
+        misc_deregister(&rtc_tps65910_test_misc);
+       platform_driver_unregister(&tps65910_rtc_driver);
 }
 module_exit(tps65910_rtc_exit);
 
-MODULE_ALIAS("platform:tps65910_rtc");
-MODULE_AUTHOR("cwz  <cwz@rockchips.com");
+MODULE_DESCRIPTION("RTC driver for the tps65910 series PMICs");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tps65910-rtc");
old mode 100644 (file)
new mode 100755 (executable)
index c2276d6..cfc3de0
@@ -957,9 +957,9 @@ struct tps65910 {
        int (*write)(struct tps65910 *tps65910, u8 reg, int size, void *src);
 
        /* Client devices */
-       struct tps65910_pmic *pmic;
-       struct tps65910_rtc *rtc;
-       struct tps65910_power *power;
+       //struct tps65910_pmic *pmic;
+       //struct tps65910_rtc *rtc;
+       //struct tps65910_power *power;
 
        /* GPIO Handling */
        struct gpio_chip gpio;
@@ -1008,6 +1008,13 @@ void tps65910_gpio_init(struct tps65910 *tps65910, int gpio_base);
 int tps65910_irq_init(struct tps65910 *tps65910, int irq,
                struct tps65910_platform_data *pdata);
 int tps65910_irq_exit(struct tps65910 *tps65910);
+int tps65910_reg_read(struct tps65910 *tps65910, u8 reg);
+int tps65910_reg_write(struct tps65910 *tps65910, u8 reg, u8 val);
+int tps65910_bulk_read(struct tps65910 *tps65910, u8 reg,
+                    int count, u8 *buf);
+int tps65910_bulk_write(struct tps65910 *tps65910, u8 reg,
+                    int count, u8 *buf);
+
 int tps65910_i2c_write_u8(u8 slave_addr, u8 value, u8 reg);
 int tps65910_i2c_read_u8(u8 slave_addr, u8 *value, u8 reg);
 int tps65910_device_shutdown(void);