summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorrhsieh <rhsieh@nvidia.com>2010-06-28 10:25:03 -0400
committerAntti Hatala <ahatala@nvidia.com>2010-06-29 04:10:01 -0700
commit7ddeb18acc426474d4f5447eb45ca7f29671aa55 (patch)
tree432313599f9b69ad9f5ada9a7c56e5f021265649 /drivers
parentd563271ec962dcb8ef677c45ff63e6c016cdb25a (diff)
tegra: [RTC Alarm Clock] Implement TI pmu tps6586x by PMIC (pwr_int) pin
Integrate PMU RTC alarm function from K29 to K32. Bug 701881 Change-Id: Iee137be5a2e9a369611037da4c39b9f443ce8979 Reviewed-on: http://git-master/r/3265 Reviewed-by: Ching Kuang (Roger) Hsieh <rhsieh@nvidia.com> Tested-by: Ching Kuang (Roger) Hsieh <rhsieh@nvidia.com> Reviewed-by: Wilson Chen <wichen@nvidia.com> Reviewed-by: Antti Hatala <ahatala@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/rtc-tegra-odm.c111
1 files changed, 106 insertions, 5 deletions
diff --git a/drivers/rtc/rtc-tegra-odm.c b/drivers/rtc/rtc-tegra-odm.c
index 1c0e7c74be03..f87a5be674d3 100644
--- a/drivers/rtc/rtc-tegra-odm.c
+++ b/drivers/rtc/rtc-tegra-odm.c
@@ -21,8 +21,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#define NV_DEBUG 0
-
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -31,9 +29,10 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/platform_device.h>
-
#include "nvodm_pmu.h"
+#define PMU_IOCTL_ENABLE 1
+
/* Create a custom rtc structrue and move this to that structure */
static NvOdmPmuDeviceHandle hPmu = NULL;
@@ -72,9 +71,109 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
return 0;
}
+#if (PMU_IOCTL_ENABLE)
+static int tegra_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ struct rtc_wkalrm wkalrm;
+ NvU32 count = 0;
+
+ switch (cmd) {
+ case RTC_ALM_READ:
+ if(NvOdmPmuReadAlarm(hPmu, &count))
+ {
+ wkalrm.time.tm_hour = count / 3600;
+ wkalrm.time.tm_min = (count - (wkalrm.time.tm_hour * 3600)) / 60;
+ wkalrm.time.tm_sec = (count - (wkalrm.time.tm_min * 60) - (wkalrm.time.tm_hour * 3600) );
+ if (copy_to_user(argp, &count, sizeof(count)))
+ return -EFAULT;
+ }
+ else
+ {
+ pr_debug("NvOdmPmuReadRtc failed\n");
+ return -EINVAL;
+ }
+ break;
+
+ case RTC_ALM_SET:
+ if (copy_from_user(&wkalrm, argp, sizeof(wkalrm)))
+ return -EFAULT;
+ count = wkalrm.time.tm_hour * 3600 + wkalrm.time.tm_min * 60 + wkalrm.time.tm_sec;
+ if(!NvOdmPmuWriteAlarm(hPmu, count))
+ {
+ pr_debug("NvOdmPmuWriteRtc failed\n");
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+
+ struct rtc_time *time = &wkalrm->time;
+
+ NvU32 alarm_sec = 0;
+ if(!NvOdmPmuReadAlarm(hPmu, &alarm_sec))
+ return -EINVAL;
+
+ rtc_time_to_tm(alarm_sec, time);
+
+ return 0;
+}
+
+static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtc_time *time = &wkalrm->time;
+ NvU32 now;
+ NvU32 alarm_sec;
+ struct rtc_time now_time;
+
+ pr_debug("wkalrm->enabled = %d\n", wkalrm->enabled);
+ if (wkalrm->enabled == 0)
+ return 0;
+
+ if (!NvOdmPmuReadRtc(hPmu, &now)) {
+ pr_debug("NvOdmPmuReadRtc failed\n");
+ return -1;
+ }
+
+ rtc_time_to_tm(now, &now_time);
+ pr_debug( "read now_time %02d:%02d:%02d %02d/%02d/%04d\n",
+ now_time.tm_hour, now_time.tm_min, now_time.tm_sec,
+ now_time.tm_mon + 1, now_time.tm_mday, now_time.tm_year + 1900);
+
+ pr_debug("write alarm_time %02d:%02d:%02d %02d/%02d/%04d\n",
+ time->tm_hour, time->tm_min, time->tm_sec,
+ time->tm_mon+1, time->tm_mday, time->tm_yday+1900);
+
+ alarm_sec = (NvU32)mktime(now_time.tm_year + 1900, time->tm_mon+1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ if (alarm_sec < now)
+ alarm_sec = (NvU32)mktime(now_time.tm_year + 1901, time->tm_mon+1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+
+ pr_debug("alarm_sec = %u\n", alarm_sec);
+
+ if(!NvOdmPmuWriteAlarm(hPmu, alarm_sec-now))
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
static struct rtc_class_ops tegra_rtc_ops = {
.read_time = tegra_rtc_read_time,
.set_time = tegra_rtc_set_time,
+#if (PMU_IOCTL_ENABLE)
+ .ioctl = tegra_rtc_ioctl,
+ .read_alarm = tegra_rtc_read_alarm,
+ .set_alarm = tegra_rtc_set_alarm,
+#endif
};
static int __init tegra_rtc_probe(struct platform_device *pdev)
@@ -93,8 +192,10 @@ static int __init tegra_rtc_probe(struct platform_device *pdev)
* and then clobbering it if the value is bogus */
if (NvOdmPmuReadRtc(hPmu, &initial) && ((time_t)initial < 0))
- NvOdmPmuWriteRtc(hPmu, 0);
-
+ {
+ if(!NvOdmPmuWriteRtc(hPmu, 0))
+ return -EINVAL;
+ }
rtc = rtc_device_register(pdev->name, &pdev->dev,