2525#include <linux/module.h>
2626#include <linux/platform_device.h>
2727#include <linux/pm_runtime.h>
28+ #include <linux/rtc.h>
2829#include <linux/suspend.h>
2930
3031MODULE_DESCRIPTION ("ACPI Time and Alarm (TAD) Device Driver" );
@@ -51,6 +52,7 @@ MODULE_AUTHOR("Rafael J. Wysocki");
5152
5253/* ACPI TAD RTC */
5354#define ACPI_TAD_TZ_UNSPEC 2047
55+ #define ACPI_TAD_TIME_ISDST 3
5456
5557struct acpi_tad_driver_data {
5658 u32 capabilities ;
@@ -164,6 +166,8 @@ static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
164166 return 0 ;
165167}
166168
169+ /* sysfs interface */
170+
167171static char * acpi_tad_rt_next_field (char * s , int * val )
168172{
169173 char * p ;
@@ -579,6 +583,71 @@ static const struct attribute_group acpi_tad_attr_group = {
579583 .is_visible = acpi_tad_attr_is_visible ,
580584};
581585
586+ #ifdef CONFIG_RTC_CLASS
587+ /* RTC class device interface */
588+
589+ static int acpi_tad_rtc_set_time (struct device * dev , struct rtc_time * tm )
590+ {
591+ struct acpi_tad_rt rt ;
592+
593+ rt .year = tm -> tm_year + 1900 ;
594+ rt .month = tm -> tm_mon + 1 ;
595+ rt .day = tm -> tm_mday ;
596+ rt .hour = tm -> tm_hour ;
597+ rt .minute = tm -> tm_min ;
598+ rt .second = tm -> tm_sec ;
599+ rt .tz = ACPI_TAD_TZ_UNSPEC ;
600+ rt .daylight = ACPI_TAD_TIME_ISDST * !!tm -> tm_isdst ;
601+
602+ return acpi_tad_set_real_time (dev , & rt );
603+ }
604+
605+ static int acpi_tad_rtc_read_time (struct device * dev , struct rtc_time * tm )
606+ {
607+ struct acpi_tad_rt rt ;
608+ int ret ;
609+
610+ ret = acpi_tad_get_real_time (dev , & rt );
611+ if (ret )
612+ return ret ;
613+
614+ tm -> tm_year = rt .year - 1900 ;
615+ tm -> tm_mon = rt .month - 1 ;
616+ tm -> tm_mday = rt .day ;
617+ tm -> tm_hour = rt .hour ;
618+ tm -> tm_min = rt .minute ;
619+ tm -> tm_sec = rt .second ;
620+ tm -> tm_isdst = rt .daylight == ACPI_TAD_TIME_ISDST ;
621+
622+ return 0 ;
623+ }
624+
625+ static const struct rtc_class_ops acpi_tad_rtc_ops = {
626+ .read_time = acpi_tad_rtc_read_time ,
627+ .set_time = acpi_tad_rtc_set_time ,
628+ };
629+
630+ static void acpi_tad_register_rtc (struct device * dev )
631+ {
632+ struct rtc_device * rtc ;
633+
634+ rtc = devm_rtc_allocate_device (dev );
635+ if (IS_ERR (rtc ))
636+ return ;
637+
638+ rtc -> range_min = mktime64 (1900 , 1 , 1 , 0 , 0 , 0 );
639+ rtc -> range_max = mktime64 (9999 , 12 , 31 , 23 , 59 , 59 );
640+
641+ rtc -> ops = & acpi_tad_rtc_ops ;
642+
643+ devm_rtc_register_device (rtc );
644+ }
645+ #else /* !CONFIG_RTC_CLASS */
646+ static inline void acpi_tad_register_rtc (struct device * dev ) {}
647+ #endif /* !CONFIG_RTC_CLASS */
648+
649+ /* Platform driver interface */
650+
582651static int acpi_tad_disable_timer (struct device * dev , u32 timer_id )
583652{
584653 return acpi_tad_wake_set (dev , "_STV" , timer_id , ACPI_TAD_WAKE_DISABLED );
@@ -660,10 +729,15 @@ static int acpi_tad_probe(struct platform_device *pdev)
660729 pm_runtime_suspend (dev );
661730
662731 ret = sysfs_create_group (& dev -> kobj , & acpi_tad_attr_group );
663- if (ret )
732+ if (ret ) {
664733 acpi_tad_remove (pdev );
734+ return ret ;
735+ }
665736
666- return ret ;
737+ if (caps & ACPI_TAD_RT )
738+ acpi_tad_register_rtc (dev );
739+
740+ return 0 ;
667741}
668742
669743static const struct acpi_device_id acpi_tad_ids [] = {
0 commit comments