xref: /openbmc/linux/drivers/rtc/rtc-max8907.c (revision 04596d4b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * RTC driver for Maxim MAX8907
4  *
5  * Copyright (c) 2011-2012, NVIDIA Corporation.
6  *
7  * Based on drivers/rtc/rtc-max8925.c,
8  * Copyright (C) 2009-2010 Marvell International Ltd.
9  */
10 
11 #include <linux/bcd.h>
12 #include <linux/mfd/max8907.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/regmap.h>
16 #include <linux/rtc.h>
17 #include <linux/slab.h>
18 
19 enum {
20 	RTC_SEC = 0,
21 	RTC_MIN,
22 	RTC_HOUR,
23 	RTC_WEEKDAY,
24 	RTC_DATE,
25 	RTC_MONTH,
26 	RTC_YEAR1,
27 	RTC_YEAR2,
28 };
29 
30 #define TIME_NUM			8
31 #define ALARM_1SEC			(1 << 7)
32 #define HOUR_12				(1 << 7)
33 #define HOUR_AM_PM			(1 << 5)
34 #define ALARM0_IRQ			(1 << 3)
35 #define ALARM1_IRQ			(1 << 2)
36 #define ALARM0_STATUS			(1 << 2)
37 #define ALARM1_STATUS			(1 << 1)
38 
39 struct max8907_rtc {
40 	struct max8907		*max8907;
41 	struct regmap		*regmap;
42 	struct rtc_device	*rtc_dev;
43 	int			irq;
44 };
45 
max8907_irq_handler(int irq,void * data)46 static irqreturn_t max8907_irq_handler(int irq, void *data)
47 {
48 	struct max8907_rtc *rtc = data;
49 
50 	regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0);
51 
52 	rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
53 
54 	return IRQ_HANDLED;
55 }
56 
regs_to_tm(u8 * regs,struct rtc_time * tm)57 static void regs_to_tm(u8 *regs, struct rtc_time *tm)
58 {
59 	tm->tm_year = bcd2bin(regs[RTC_YEAR2]) * 100 +
60 		bcd2bin(regs[RTC_YEAR1]) - 1900;
61 	tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1;
62 	tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f);
63 	tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07);
64 	if (regs[RTC_HOUR] & HOUR_12) {
65 		tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f);
66 		if (tm->tm_hour == 12)
67 			tm->tm_hour = 0;
68 		if (regs[RTC_HOUR] & HOUR_AM_PM)
69 			tm->tm_hour += 12;
70 	} else {
71 		tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x03f);
72 	}
73 	tm->tm_min = bcd2bin(regs[RTC_MIN] & 0x7f);
74 	tm->tm_sec = bcd2bin(regs[RTC_SEC] & 0x7f);
75 }
76 
tm_to_regs(struct rtc_time * tm,u8 * regs)77 static void tm_to_regs(struct rtc_time *tm, u8 *regs)
78 {
79 	u8 high, low;
80 
81 	high = (tm->tm_year + 1900) / 100;
82 	low = tm->tm_year % 100;
83 	regs[RTC_YEAR2] = bin2bcd(high);
84 	regs[RTC_YEAR1] = bin2bcd(low);
85 	regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
86 	regs[RTC_DATE] = bin2bcd(tm->tm_mday);
87 	regs[RTC_WEEKDAY] = tm->tm_wday;
88 	regs[RTC_HOUR] = bin2bcd(tm->tm_hour);
89 	regs[RTC_MIN] = bin2bcd(tm->tm_min);
90 	regs[RTC_SEC] = bin2bcd(tm->tm_sec);
91 }
92 
max8907_rtc_read_time(struct device * dev,struct rtc_time * tm)93 static int max8907_rtc_read_time(struct device *dev, struct rtc_time *tm)
94 {
95 	struct max8907_rtc *rtc = dev_get_drvdata(dev);
96 	u8 regs[TIME_NUM];
97 	int ret;
98 
99 	ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_RTC_SEC, regs,
100 			       TIME_NUM);
101 	if (ret < 0)
102 		return ret;
103 
104 	regs_to_tm(regs, tm);
105 
106 	return 0;
107 }
108 
max8907_rtc_set_time(struct device * dev,struct rtc_time * tm)109 static int max8907_rtc_set_time(struct device *dev, struct rtc_time *tm)
110 {
111 	struct max8907_rtc *rtc = dev_get_drvdata(dev);
112 	u8 regs[TIME_NUM];
113 
114 	tm_to_regs(tm, regs);
115 
116 	return regmap_bulk_write(rtc->regmap, MAX8907_REG_RTC_SEC, regs,
117 				 TIME_NUM);
118 }
119 
max8907_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)120 static int max8907_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
121 {
122 	struct max8907_rtc *rtc = dev_get_drvdata(dev);
123 	u8 regs[TIME_NUM];
124 	unsigned int val;
125 	int ret;
126 
127 	ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs,
128 			       TIME_NUM);
129 	if (ret < 0)
130 		return ret;
131 
132 	regs_to_tm(regs, &alrm->time);
133 
134 	ret = regmap_read(rtc->regmap, MAX8907_REG_ALARM0_CNTL, &val);
135 	if (ret < 0)
136 		return ret;
137 
138 	alrm->enabled = !!(val & 0x7f);
139 
140 	return 0;
141 }
142 
max8907_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)143 static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
144 {
145 	struct max8907_rtc *rtc = dev_get_drvdata(dev);
146 	u8 regs[TIME_NUM];
147 	int ret;
148 
149 	tm_to_regs(&alrm->time, regs);
150 
151 	/* Disable alarm while we update the target time */
152 	ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0);
153 	if (ret < 0)
154 		return ret;
155 
156 	ret = regmap_bulk_write(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs,
157 				TIME_NUM);
158 	if (ret < 0)
159 		return ret;
160 
161 	if (alrm->enabled)
162 		ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x77);
163 
164 	return ret;
165 }
166 
167 static const struct rtc_class_ops max8907_rtc_ops = {
168 	.read_time	= max8907_rtc_read_time,
169 	.set_time	= max8907_rtc_set_time,
170 	.read_alarm	= max8907_rtc_read_alarm,
171 	.set_alarm	= max8907_rtc_set_alarm,
172 };
173 
max8907_rtc_probe(struct platform_device * pdev)174 static int max8907_rtc_probe(struct platform_device *pdev)
175 {
176 	struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
177 	struct max8907_rtc *rtc;
178 	int ret;
179 
180 	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
181 	if (!rtc)
182 		return -ENOMEM;
183 	platform_set_drvdata(pdev, rtc);
184 
185 	rtc->max8907 = max8907;
186 	rtc->regmap = max8907->regmap_rtc;
187 
188 	rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "max8907-rtc",
189 					&max8907_rtc_ops, THIS_MODULE);
190 	if (IS_ERR(rtc->rtc_dev)) {
191 		ret = PTR_ERR(rtc->rtc_dev);
192 		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
193 		return ret;
194 	}
195 
196 	rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc,
197 				       MAX8907_IRQ_RTC_ALARM0);
198 	if (rtc->irq < 0)
199 		return rtc->irq;
200 
201 	ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
202 				max8907_irq_handler,
203 				IRQF_ONESHOT, "max8907-alarm0", rtc);
204 	if (ret < 0)
205 		dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n",
206 			rtc->irq, ret);
207 
208 	return ret;
209 }
210 
211 static struct platform_driver max8907_rtc_driver = {
212 	.driver = {
213 		.name = "max8907-rtc",
214 	},
215 	.probe = max8907_rtc_probe,
216 };
217 module_platform_driver(max8907_rtc_driver);
218 
219 MODULE_DESCRIPTION("Maxim MAX8907 RTC driver");
220 MODULE_LICENSE("GPL v2");
221