55 * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
66 * Copyright (c) 2023, Linaro Limited
77 */
8+ #include <linux/efi.h>
89#include <linux/of.h>
910#include <linux/module.h>
1011#include <linux/nvmem-consumer.h>
1617#include <linux/regmap.h>
1718#include <linux/slab.h>
1819#include <linux/spinlock.h>
19-
2020#include <linux/unaligned.h>
2121
22+ #include <asm/byteorder.h>
23+
2224/* RTC_CTRL register bit fields */
2325#define PM8xxx_RTC_ENABLE BIT(7)
2426#define PM8xxx_RTC_ALARM_CLEAR BIT(0)
@@ -46,28 +48,123 @@ struct pm8xxx_rtc_regs {
4648 unsigned int alarm_en ;
4749};
4850
51+ struct qcom_uefi_rtc_info {
52+ __le32 offset_gps ;
53+ u8 reserved [8 ];
54+ } __packed ;
55+
4956/**
5057 * struct pm8xxx_rtc - RTC driver internal structure
5158 * @rtc: RTC device
5259 * @regmap: regmap used to access registers
5360 * @allow_set_time: whether the time can be set
61+ * @use_uefi: use UEFI variable as fallback for offset
5462 * @alarm_irq: alarm irq number
5563 * @regs: register description
5664 * @dev: device structure
65+ * @rtc_info: qcom uefi rtc-info structure
5766 * @nvmem_cell: nvmem cell for offset
5867 * @offset: offset from epoch in seconds
5968 */
6069struct pm8xxx_rtc {
6170 struct rtc_device * rtc ;
6271 struct regmap * regmap ;
6372 bool allow_set_time ;
73+ bool use_uefi ;
6474 int alarm_irq ;
6575 const struct pm8xxx_rtc_regs * regs ;
6676 struct device * dev ;
77+ struct qcom_uefi_rtc_info rtc_info ;
6778 struct nvmem_cell * nvmem_cell ;
6879 u32 offset ;
6980};
7081
82+ #ifdef CONFIG_EFI
83+
84+ MODULE_IMPORT_NS ("EFIVAR" );
85+
86+ #define QCOM_UEFI_NAME L"RTCInfo"
87+ #define QCOM_UEFI_GUID EFI_GUID(0x882f8c2b, 0x9646, 0x435f, \
88+ 0x8d, 0xe5, 0xf2, 0x08, 0xff, 0x80, 0xc1, 0xbd)
89+ #define QCOM_UEFI_ATTRS (EFI_VARIABLE_NON_VOLATILE | \
90+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
91+ EFI_VARIABLE_RUNTIME_ACCESS)
92+
93+ static int pm8xxx_rtc_read_uefi_offset (struct pm8xxx_rtc * rtc_dd )
94+ {
95+ struct qcom_uefi_rtc_info * rtc_info = & rtc_dd -> rtc_info ;
96+ unsigned long size = sizeof (* rtc_info );
97+ struct device * dev = rtc_dd -> dev ;
98+ efi_status_t status ;
99+ u32 offset_gps ;
100+ int rc ;
101+
102+ rc = efivar_lock ();
103+ if (rc )
104+ return rc ;
105+
106+ status = efivar_get_variable (QCOM_UEFI_NAME , & QCOM_UEFI_GUID , NULL ,
107+ & size , rtc_info );
108+ efivar_unlock ();
109+
110+ if (status != EFI_SUCCESS ) {
111+ dev_dbg (dev , "failed to read UEFI offset: %lu\n" , status );
112+ return efi_status_to_err (status );
113+ }
114+
115+ if (size != sizeof (* rtc_info )) {
116+ dev_dbg (dev , "unexpected UEFI structure size %lu\n" , size );
117+ return - EINVAL ;
118+ }
119+
120+ dev_dbg (dev , "uefi_rtc_info = %*ph\n" , (int )size , rtc_info );
121+
122+ /* Convert from GPS to Unix time offset */
123+ offset_gps = le32_to_cpu (rtc_info -> offset_gps );
124+ rtc_dd -> offset = offset_gps + (u32 )RTC_TIMESTAMP_EPOCH_GPS ;
125+
126+ return 0 ;
127+ }
128+
129+ static int pm8xxx_rtc_write_uefi_offset (struct pm8xxx_rtc * rtc_dd , u32 offset )
130+ {
131+ struct qcom_uefi_rtc_info * rtc_info = & rtc_dd -> rtc_info ;
132+ unsigned long size = sizeof (* rtc_info );
133+ struct device * dev = rtc_dd -> dev ;
134+ efi_status_t status ;
135+ u32 offset_gps ;
136+
137+ /* Convert from Unix to GPS time offset */
138+ offset_gps = offset - (u32 )RTC_TIMESTAMP_EPOCH_GPS ;
139+
140+ rtc_info -> offset_gps = cpu_to_le32 (offset_gps );
141+
142+ dev_dbg (dev , "efi_rtc_info = %*ph\n" , (int )size , rtc_info );
143+
144+ status = efivar_set_variable (QCOM_UEFI_NAME , & QCOM_UEFI_GUID ,
145+ QCOM_UEFI_ATTRS , size , rtc_info );
146+ if (status != EFI_SUCCESS ) {
147+ dev_dbg (dev , "failed to write UEFI offset: %lx\n" , status );
148+ return efi_status_to_err (status );
149+ }
150+
151+ return 0 ;
152+ }
153+
154+ #else /* CONFIG_EFI */
155+
156+ static int pm8xxx_rtc_read_uefi_offset (struct pm8xxx_rtc * rtc_dd )
157+ {
158+ return - ENODEV ;
159+ }
160+
161+ static int pm8xxx_rtc_write_uefi_offset (struct pm8xxx_rtc * rtc_dd , u32 offset )
162+ {
163+ return - ENODEV ;
164+ }
165+
166+ #endif /* CONFIG_EFI */
167+
71168static int pm8xxx_rtc_read_nvmem_offset (struct pm8xxx_rtc * rtc_dd )
72169{
73170 size_t len ;
@@ -110,14 +207,6 @@ static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset)
110207 return 0 ;
111208}
112209
113- static int pm8xxx_rtc_read_offset (struct pm8xxx_rtc * rtc_dd )
114- {
115- if (!rtc_dd -> nvmem_cell )
116- return 0 ;
117-
118- return pm8xxx_rtc_read_nvmem_offset (rtc_dd );
119- }
120-
121210static int pm8xxx_rtc_read_raw (struct pm8xxx_rtc * rtc_dd , u32 * secs )
122211{
123212 const struct pm8xxx_rtc_regs * regs = rtc_dd -> regs ;
@@ -155,7 +244,7 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs)
155244 u32 offset ;
156245 int rc ;
157246
158- if (!rtc_dd -> nvmem_cell )
247+ if (!rtc_dd -> nvmem_cell && ! rtc_dd -> use_uefi )
159248 return - ENODEV ;
160249
161250 rc = pm8xxx_rtc_read_raw (rtc_dd , & raw_secs );
@@ -167,7 +256,11 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs)
167256 if (offset == rtc_dd -> offset )
168257 return 0 ;
169258
170- rc = pm8xxx_rtc_write_nvmem_offset (rtc_dd , offset );
259+ if (rtc_dd -> nvmem_cell )
260+ rc = pm8xxx_rtc_write_nvmem_offset (rtc_dd , offset );
261+ else
262+ rc = pm8xxx_rtc_write_uefi_offset (rtc_dd , offset );
263+
171264 if (rc )
172265 return rc ;
173266
@@ -455,6 +548,30 @@ static const struct of_device_id pm8xxx_id_table[] = {
455548};
456549MODULE_DEVICE_TABLE (of , pm8xxx_id_table );
457550
551+ static int pm8xxx_rtc_probe_offset (struct pm8xxx_rtc * rtc_dd )
552+ {
553+ int rc ;
554+
555+ rtc_dd -> nvmem_cell = devm_nvmem_cell_get (rtc_dd -> dev , "offset" );
556+ if (IS_ERR (rtc_dd -> nvmem_cell )) {
557+ rc = PTR_ERR (rtc_dd -> nvmem_cell );
558+ if (rc != - ENOENT )
559+ return rc ;
560+ rtc_dd -> nvmem_cell = NULL ;
561+ } else {
562+ return pm8xxx_rtc_read_nvmem_offset (rtc_dd );
563+ }
564+
565+ /* Use UEFI storage as fallback if available */
566+ if (efivar_is_available ()) {
567+ rc = pm8xxx_rtc_read_uefi_offset (rtc_dd );
568+ if (rc == 0 )
569+ rtc_dd -> use_uefi = true;
570+ }
571+
572+ return 0 ;
573+ }
574+
458575static int pm8xxx_rtc_probe (struct platform_device * pdev )
459576{
460577 const struct of_device_id * match ;
@@ -469,6 +586,9 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
469586 if (rtc_dd == NULL )
470587 return - ENOMEM ;
471588
589+ rtc_dd -> regs = match -> data ;
590+ rtc_dd -> dev = & pdev -> dev ;
591+
472592 rtc_dd -> regmap = dev_get_regmap (pdev -> dev .parent , NULL );
473593 if (!rtc_dd -> regmap )
474594 return - ENXIO ;
@@ -479,20 +599,8 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
479599
480600 rtc_dd -> allow_set_time = of_property_read_bool (pdev -> dev .of_node ,
481601 "allow-set-time" );
482-
483- rtc_dd -> nvmem_cell = devm_nvmem_cell_get (& pdev -> dev , "offset" );
484- if (IS_ERR (rtc_dd -> nvmem_cell )) {
485- rc = PTR_ERR (rtc_dd -> nvmem_cell );
486- if (rc != - ENOENT )
487- return rc ;
488- rtc_dd -> nvmem_cell = NULL ;
489- }
490-
491- rtc_dd -> regs = match -> data ;
492- rtc_dd -> dev = & pdev -> dev ;
493-
494602 if (!rtc_dd -> allow_set_time ) {
495- rc = pm8xxx_rtc_read_offset (rtc_dd );
603+ rc = pm8xxx_rtc_probe_offset (rtc_dd );
496604 if (rc )
497605 return rc ;
498606 }
0 commit comments