1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright 2015 IBM Corp.
4 #include <linux/module.h>
6 #include <linux/platform_device.h>
11 struct rtc_device
*rtc_dev
;
19 #define RTC_UNLOCK BIT(1)
20 #define RTC_ENABLE BIT(0)
22 static int aspeed_rtc_read_time(struct device
*dev
, struct rtc_time
*tm
)
24 struct aspeed_rtc
*rtc
= dev_get_drvdata(dev
);
25 unsigned int cent
, year
;
28 if (!(readl(rtc
->base
+ RTC_CTRL
) & RTC_ENABLE
)) {
29 dev_dbg(dev
, "%s failing as rtc disabled\n", __func__
);
34 reg2
= readl(rtc
->base
+ RTC_YEAR
);
35 reg1
= readl(rtc
->base
+ RTC_TIME
);
36 } while (reg2
!= readl(rtc
->base
+ RTC_YEAR
));
38 tm
->tm_mday
= (reg1
>> 24) & 0x1f;
39 tm
->tm_hour
= (reg1
>> 16) & 0x1f;
40 tm
->tm_min
= (reg1
>> 8) & 0x3f;
41 tm
->tm_sec
= (reg1
>> 0) & 0x3f;
43 cent
= (reg2
>> 16) & 0x1f;
44 year
= (reg2
>> 8) & 0x7f;
45 tm
->tm_mon
= ((reg2
>> 0) & 0x0f) - 1;
46 tm
->tm_year
= year
+ (cent
* 100) - 1900;
48 dev_dbg(dev
, "%s %ptR", __func__
, tm
);
53 static int aspeed_rtc_set_time(struct device
*dev
, struct rtc_time
*tm
)
55 struct aspeed_rtc
*rtc
= dev_get_drvdata(dev
);
59 cent
= (tm
->tm_year
+ 1900) / 100;
60 year
= tm
->tm_year
% 100;
62 reg1
= (tm
->tm_mday
<< 24) | (tm
->tm_hour
<< 16) | (tm
->tm_min
<< 8) |
65 reg2
= ((cent
& 0x1f) << 16) | ((year
& 0x7f) << 8) |
66 ((tm
->tm_mon
+ 1) & 0xf);
68 ctrl
= readl(rtc
->base
+ RTC_CTRL
);
69 writel(ctrl
| RTC_UNLOCK
, rtc
->base
+ RTC_CTRL
);
71 writel(reg1
, rtc
->base
+ RTC_TIME
);
72 writel(reg2
, rtc
->base
+ RTC_YEAR
);
74 /* Re-lock and ensure enable is set now that a time is programmed */
75 writel(ctrl
| RTC_ENABLE
, rtc
->base
+ RTC_CTRL
);
80 static const struct rtc_class_ops aspeed_rtc_ops
= {
81 .read_time
= aspeed_rtc_read_time
,
82 .set_time
= aspeed_rtc_set_time
,
85 static int aspeed_rtc_probe(struct platform_device
*pdev
)
87 struct aspeed_rtc
*rtc
;
89 rtc
= devm_kzalloc(&pdev
->dev
, sizeof(*rtc
), GFP_KERNEL
);
93 rtc
->base
= devm_platform_ioremap_resource(pdev
, 0);
94 if (IS_ERR(rtc
->base
))
95 return PTR_ERR(rtc
->base
);
97 rtc
->rtc_dev
= devm_rtc_allocate_device(&pdev
->dev
);
98 if (IS_ERR(rtc
->rtc_dev
))
99 return PTR_ERR(rtc
->rtc_dev
);
101 platform_set_drvdata(pdev
, rtc
);
103 rtc
->rtc_dev
->ops
= &aspeed_rtc_ops
;
104 rtc
->rtc_dev
->range_min
= RTC_TIMESTAMP_BEGIN_1900
;
105 rtc
->rtc_dev
->range_max
= 38814989399LL; /* 3199-12-31 23:59:59 */
107 return devm_rtc_register_device(rtc
->rtc_dev
);
110 static const struct of_device_id aspeed_rtc_match
[] = {
111 { .compatible
= "aspeed,ast2400-rtc", },
112 { .compatible
= "aspeed,ast2500-rtc", },
113 { .compatible
= "aspeed,ast2600-rtc", },
116 MODULE_DEVICE_TABLE(of
, aspeed_rtc_match
);
118 static struct platform_driver aspeed_rtc_driver
= {
120 .name
= "aspeed-rtc",
121 .of_match_table
= of_match_ptr(aspeed_rtc_match
),
125 module_platform_driver_probe(aspeed_rtc_driver
, aspeed_rtc_probe
);
127 MODULE_DESCRIPTION("ASPEED RTC driver");
128 MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>");
129 MODULE_LICENSE("GPL");