Blame view

drivers/rtc/rtc-ds1742.c 7.38 KB
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
1
2
3
4
5
6
7
8
  /*
   * An rtc driver for the Dallas DS1742
   *
   * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
9
10
11
12
   *
   * Copyright (C) 2006 Torsten Ertbjerg Rasmussen <tr@newtec.dk>
   *  - nvram size determined from resource
   *  - this ds1742 driver now supports ds1743.
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
13
14
15
16
17
   */
  
  #include <linux/bcd.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
18
  #include <linux/gfp.h>
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
19
20
21
22
23
  #include <linux/delay.h>
  #include <linux/jiffies.h>
  #include <linux/rtc.h>
  #include <linux/platform_device.h>
  #include <linux/io.h>
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
24
  #define DRV_VERSION "0.4"
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
25

f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
26
  #define RTC_SIZE		8
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
27

f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
28
29
30
31
32
33
34
35
36
  #define RTC_CONTROL		0
  #define RTC_CENTURY		0
  #define RTC_SECONDS		1
  #define RTC_MINUTES		2
  #define RTC_HOURS		3
  #define RTC_DAY			4
  #define RTC_DATE		5
  #define RTC_MONTH		6
  #define RTC_YEAR		7
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  
  #define RTC_CENTURY_MASK	0x3f
  #define RTC_SECONDS_MASK	0x7f
  #define RTC_DAY_MASK		0x07
  
  /* Bits in the Control/Century register */
  #define RTC_WRITE		0x80
  #define RTC_READ		0x40
  
  /* Bits in the Seconds register */
  #define RTC_STOP		0x80
  
  /* Bits in the Day register */
  #define RTC_BATT_FLAG		0x80
  
  struct rtc_plat_data {
  	struct rtc_device *rtc;
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
54
55
56
57
  	void __iomem *ioaddr_nvram;
  	void __iomem *ioaddr_rtc;
  	size_t size_nvram;
  	size_t size;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
58
  	unsigned long last_jiffies;
3a7297005   Torsten Ertbjerg Rasmussen   rtc: rtc-ds1742 n...
59
  	struct bin_attribute nvram_attr;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
60
61
62
63
64
65
  };
  
  static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
  {
  	struct platform_device *pdev = to_platform_device(dev);
  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
66
  	void __iomem *ioaddr = pdata->ioaddr_rtc;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
67
  	u8 century;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
68
  	century = bin2bcd((tm->tm_year + 1900) / 100);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
69
70
  
  	writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
71
72
73
74
75
76
77
  	writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
  	writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
  	writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
  	writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
  	writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
  	writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
  	writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
78
79
80
81
82
83
84
85
86
87
88
  
  	/* RTC_CENTURY and RTC_CONTROL share same register */
  	writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
  	writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
  	return 0;
  }
  
  static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
  {
  	struct platform_device *pdev = to_platform_device(dev);
  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
89
  	void __iomem *ioaddr = pdata->ioaddr_rtc;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  	unsigned int year, month, day, hour, minute, second, week;
  	unsigned int century;
  
  	/* give enough time to update RTC in case of continuous read */
  	if (pdata->last_jiffies == jiffies)
  		msleep(1);
  	pdata->last_jiffies = jiffies;
  	writeb(RTC_READ, ioaddr + RTC_CONTROL);
  	second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
  	minute = readb(ioaddr + RTC_MINUTES);
  	hour = readb(ioaddr + RTC_HOURS);
  	day = readb(ioaddr + RTC_DATE);
  	week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
  	month = readb(ioaddr + RTC_MONTH);
  	year = readb(ioaddr + RTC_YEAR);
  	century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
  	writeb(0, ioaddr + RTC_CONTROL);
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
107
108
109
110
111
112
  	tm->tm_sec = bcd2bin(second);
  	tm->tm_min = bcd2bin(minute);
  	tm->tm_hour = bcd2bin(hour);
  	tm->tm_mday = bcd2bin(day);
  	tm->tm_wday = bcd2bin(week);
  	tm->tm_mon = bcd2bin(month) - 1;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
113
  	/* year is 1900 + tm->tm_year */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
114
  	tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
115
116
117
118
119
120
121
122
  
  	if (rtc_valid_tm(tm) < 0) {
  		dev_err(dev, "retrieved date/time is not valid.
  ");
  		rtc_time_to_tm(0, tm);
  	}
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
123
  static const struct rtc_class_ops ds1742_rtc_ops = {
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
124
125
126
  	.read_time	= ds1742_rtc_read_time,
  	.set_time	= ds1742_rtc_set_time,
  };
2c3c8bea6   Chris Wright   sysfs: add struct...
127
  static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj,
91a690295   Zhang Rui   sysfs: add parame...
128
129
  				 struct bin_attribute *bin_attr,
  				 char *buf, loff_t pos, size_t size)
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
130
  {
50e49bee3   Atsushi Nemoto   rtc: do not use c...
131
132
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct platform_device *pdev = to_platform_device(dev);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
133
  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
134
  	void __iomem *ioaddr = pdata->ioaddr_nvram;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
135
  	ssize_t count;
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
136
  	for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
137
138
139
  		*buf++ = readb(ioaddr + pos++);
  	return count;
  }
2c3c8bea6   Chris Wright   sysfs: add struct...
140
  static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
91a690295   Zhang Rui   sysfs: add parame...
141
142
  				  struct bin_attribute *bin_attr,
  				  char *buf, loff_t pos, size_t size)
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
143
  {
50e49bee3   Atsushi Nemoto   rtc: do not use c...
144
145
  	struct device *dev = container_of(kobj, struct device, kobj);
  	struct platform_device *pdev = to_platform_device(dev);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
146
  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
147
  	void __iomem *ioaddr = pdata->ioaddr_nvram;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
148
  	ssize_t count;
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
149
  	for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
150
151
152
  		writeb(*buf++, ioaddr + pos++);
  	return count;
  }
c239122de   Prarit Bhargava   [PATCH] change __...
153
  static int __devinit ds1742_rtc_probe(struct platform_device *pdev)
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
154
155
156
157
  {
  	struct rtc_device *rtc;
  	struct resource *res;
  	unsigned int cen, sec;
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
158
159
  	struct rtc_plat_data *pdata;
  	void __iomem *ioaddr;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
160
161
162
163
164
  	int ret = 0;
  
  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!res)
  		return -ENODEV;
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
165
  	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
166
167
  	if (!pdata)
  		return -ENOMEM;
28f65c11f   Joe Perches   treewide: Convert...
168
  	pdata->size = resource_size(res);
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
169
170
171
172
173
174
  	if (!devm_request_mem_region(&pdev->dev, res->start, pdata->size,
  		pdev->name))
  		return -EBUSY;
  	ioaddr = devm_ioremap(&pdev->dev, res->start, pdata->size);
  	if (!ioaddr)
  		return -ENOMEM;
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
175
176
177
  	pdata->ioaddr_nvram = ioaddr;
  	pdata->size_nvram = pdata->size - RTC_SIZE;
  	pdata->ioaddr_rtc = ioaddr + pdata->size_nvram;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
178

f937331b3   Wolfram Sang   init dynamic bin_...
179
  	sysfs_bin_attr_init(&pdata->nvram_attr);
3a7297005   Torsten Ertbjerg Rasmussen   rtc: rtc-ds1742 n...
180
181
182
183
184
  	pdata->nvram_attr.attr.name = "nvram";
  	pdata->nvram_attr.attr.mode = S_IRUGO | S_IWUSR;
  	pdata->nvram_attr.read = ds1742_nvram_read;
  	pdata->nvram_attr.write = ds1742_nvram_write;
  	pdata->nvram_attr.size = pdata->size_nvram;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
185
  	/* turn RTC on if it was not on */
f9231a0ca   Torsten Ertbjerg Rasmussen   [PATCH] rtc: ds17...
186
  	ioaddr = pdata->ioaddr_rtc;
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
187
188
189
190
191
192
193
194
  	sec = readb(ioaddr + RTC_SECONDS);
  	if (sec & RTC_STOP) {
  		sec &= RTC_SECONDS_MASK;
  		cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
  		writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
  		writeb(sec, ioaddr + RTC_SECONDS);
  		writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
  	}
391b1fe67   Atsushi Nemoto   [PATCH] RTC: rtc-...
195
  	if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG))
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
196
197
  		dev_warn(&pdev->dev, "voltage-low detected.
  ");
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
198
199
  	pdata->last_jiffies = jiffies;
  	platform_set_drvdata(pdev, pdata);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
200
201
  	rtc = rtc_device_register(pdev->name, &pdev->dev,
  				  &ds1742_rtc_ops, THIS_MODULE);
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
202
203
  	if (IS_ERR(rtc))
  		return PTR_ERR(rtc);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
204
  	pdata->rtc = rtc;
3a7297005   Torsten Ertbjerg Rasmussen   rtc: rtc-ds1742 n...
205
206
207
208
209
  
  	ret = sysfs_create_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
  	if (ret) {
  		dev_err(&pdev->dev, "creating nvram file in sysfs failed
  ");
ac18eb622   Atsushi Nemoto   rtc-ds1742: fix r...
210
  		rtc_device_unregister(rtc);
3a7297005   Torsten Ertbjerg Rasmussen   rtc: rtc-ds1742 n...
211
  	}
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
212
213
214
215
216
217
  	return ret;
  }
  
  static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
  {
  	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
3a7297005   Torsten Ertbjerg Rasmussen   rtc: rtc-ds1742 n...
218
  	sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
219
  	rtc_device_unregister(pdata->rtc);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
220
221
222
223
224
225
226
  	return 0;
  }
  
  static struct platform_driver ds1742_rtc_driver = {
  	.probe		= ds1742_rtc_probe,
  	.remove		= __devexit_p(ds1742_rtc_remove),
  	.driver		= {
a95e23a27   Atsushi Nemoto   rtc: make rtc-ds1...
227
  		.name	= "rtc-ds1742",
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
228
229
230
231
232
233
234
235
236
237
238
  		.owner	= THIS_MODULE,
  	},
  };
  
  static __init int ds1742_init(void)
  {
  	return platform_driver_register(&ds1742_rtc_driver);
  }
  
  static __exit void ds1742_exit(void)
  {
ef154ec69   Atsushi Nemoto   rtc: do not retur...
239
  	platform_driver_unregister(&ds1742_rtc_driver);
5ec3e4b7a   Atsushi Nemoto   [PATCH] RTC: add ...
240
241
242
243
244
245
246
247
248
  }
  
  module_init(ds1742_init);
  module_exit(ds1742_exit);
  
  MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
  MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);
ad28a07bc   Kay Sievers   rtc: fix platform...
249
  MODULE_ALIAS("platform:rtc-ds1742");