diff options
author | rhsieh <rhsieh@nvidia.com> | 2010-06-28 10:25:03 -0400 |
---|---|---|
committer | Antti Hatala <ahatala@nvidia.com> | 2010-06-29 04:10:01 -0700 |
commit | 7ddeb18acc426474d4f5447eb45ca7f29671aa55 (patch) | |
tree | 432313599f9b69ad9f5ada9a7c56e5f021265649 /drivers/rtc | |
parent | d563271ec962dcb8ef677c45ff63e6c016cdb25a (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/rtc')
-rw-r--r-- | drivers/rtc/rtc-tegra-odm.c | 111 |
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, |