Blame view
drivers/rtc/rtc-ds1742.c
7.38 KB
5ec3e4b7a [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 [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 [PATCH] RTC: add ... |
13 14 15 16 17 |
*/ #include <linux/bcd.h> #include <linux/init.h> #include <linux/kernel.h> |
5a0e3ad6a include cleanup: ... |
18 |
#include <linux/gfp.h> |
5ec3e4b7a [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 rtc-ds1742: fix r... |
24 |
#define DRV_VERSION "0.4" |
5ec3e4b7a [PATCH] RTC: add ... |
25 |
|
f9231a0ca [PATCH] rtc: ds17... |
26 |
#define RTC_SIZE 8 |
5ec3e4b7a [PATCH] RTC: add ... |
27 |
|
f9231a0ca [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 [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 [PATCH] rtc: ds17... |
54 55 56 57 |
void __iomem *ioaddr_nvram; void __iomem *ioaddr_rtc; size_t size_nvram; size_t size; |
5ec3e4b7a [PATCH] RTC: add ... |
58 |
unsigned long last_jiffies; |
3a7297005 rtc: rtc-ds1742 n... |
59 |
struct bin_attribute nvram_attr; |
5ec3e4b7a [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 [PATCH] rtc: ds17... |
66 |
void __iomem *ioaddr = pdata->ioaddr_rtc; |
5ec3e4b7a [PATCH] RTC: add ... |
67 |
u8 century; |
fe20ba70a drivers/rtc/: use... |
68 |
century = bin2bcd((tm->tm_year + 1900) / 100); |
5ec3e4b7a [PATCH] RTC: add ... |
69 70 |
writeb(RTC_WRITE, ioaddr + RTC_CONTROL); |
fe20ba70a 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 [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 [PATCH] rtc: ds17... |
89 |
void __iomem *ioaddr = pdata->ioaddr_rtc; |
5ec3e4b7a [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 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 [PATCH] RTC: add ... |
113 |
/* year is 1900 + tm->tm_year */ |
fe20ba70a drivers/rtc/: use... |
114 |
tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900; |
5ec3e4b7a [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 [PATCH] constify ... |
123 |
static const struct rtc_class_ops ds1742_rtc_ops = { |
5ec3e4b7a [PATCH] RTC: add ... |
124 125 126 |
.read_time = ds1742_rtc_read_time, .set_time = ds1742_rtc_set_time, }; |
2c3c8bea6 sysfs: add struct... |
127 |
static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj, |
91a690295 sysfs: add parame... |
128 129 |
struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) |
5ec3e4b7a [PATCH] RTC: add ... |
130 |
{ |
50e49bee3 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 [PATCH] RTC: add ... |
133 |
struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
f9231a0ca [PATCH] rtc: ds17... |
134 |
void __iomem *ioaddr = pdata->ioaddr_nvram; |
5ec3e4b7a [PATCH] RTC: add ... |
135 |
ssize_t count; |
f9231a0ca [PATCH] rtc: ds17... |
136 |
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) |
5ec3e4b7a [PATCH] RTC: add ... |
137 138 139 |
*buf++ = readb(ioaddr + pos++); return count; } |
2c3c8bea6 sysfs: add struct... |
140 |
static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj, |
91a690295 sysfs: add parame... |
141 142 |
struct bin_attribute *bin_attr, char *buf, loff_t pos, size_t size) |
5ec3e4b7a [PATCH] RTC: add ... |
143 |
{ |
50e49bee3 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 [PATCH] RTC: add ... |
146 |
struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
f9231a0ca [PATCH] rtc: ds17... |
147 |
void __iomem *ioaddr = pdata->ioaddr_nvram; |
5ec3e4b7a [PATCH] RTC: add ... |
148 |
ssize_t count; |
f9231a0ca [PATCH] rtc: ds17... |
149 |
for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) |
5ec3e4b7a [PATCH] RTC: add ... |
150 151 152 |
writeb(*buf++, ioaddr + pos++); return count; } |
c239122de [PATCH] change __... |
153 |
static int __devinit ds1742_rtc_probe(struct platform_device *pdev) |
5ec3e4b7a [PATCH] RTC: add ... |
154 155 156 157 |
{ struct rtc_device *rtc; struct resource *res; unsigned int cen, sec; |
ac18eb622 rtc-ds1742: fix r... |
158 159 |
struct rtc_plat_data *pdata; void __iomem *ioaddr; |
5ec3e4b7a [PATCH] RTC: add ... |
160 161 162 163 164 |
int ret = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; |
ac18eb622 rtc-ds1742: fix r... |
165 |
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
5ec3e4b7a [PATCH] RTC: add ... |
166 167 |
if (!pdata) return -ENOMEM; |
28f65c11f treewide: Convert... |
168 |
pdata->size = resource_size(res); |
ac18eb622 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 [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 [PATCH] RTC: add ... |
178 |
|
f937331b3 init dynamic bin_... |
179 |
sysfs_bin_attr_init(&pdata->nvram_attr); |
3a7297005 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 [PATCH] RTC: add ... |
185 |
/* turn RTC on if it was not on */ |
f9231a0ca [PATCH] rtc: ds17... |
186 |
ioaddr = pdata->ioaddr_rtc; |
5ec3e4b7a [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 [PATCH] RTC: rtc-... |
195 |
if (!(readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)) |
5ec3e4b7a [PATCH] RTC: add ... |
196 197 |
dev_warn(&pdev->dev, "voltage-low detected. "); |
ac18eb622 rtc-ds1742: fix r... |
198 199 |
pdata->last_jiffies = jiffies; platform_set_drvdata(pdev, pdata); |
5ec3e4b7a [PATCH] RTC: add ... |
200 201 |
rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1742_rtc_ops, THIS_MODULE); |
ac18eb622 rtc-ds1742: fix r... |
202 203 |
if (IS_ERR(rtc)) return PTR_ERR(rtc); |
5ec3e4b7a [PATCH] RTC: add ... |
204 |
pdata->rtc = rtc; |
3a7297005 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 rtc-ds1742: fix r... |
210 |
rtc_device_unregister(rtc); |
3a7297005 rtc: rtc-ds1742 n... |
211 |
} |
5ec3e4b7a [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 rtc: rtc-ds1742 n... |
218 |
sysfs_remove_bin_file(&pdev->dev.kobj, &pdata->nvram_attr); |
5ec3e4b7a [PATCH] RTC: add ... |
219 |
rtc_device_unregister(pdata->rtc); |
5ec3e4b7a [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 rtc: make rtc-ds1... |
227 |
.name = "rtc-ds1742", |
5ec3e4b7a [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 rtc: do not retur... |
239 |
platform_driver_unregister(&ds1742_rtc_driver); |
5ec3e4b7a [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 rtc: fix platform... |
249 |
MODULE_ALIAS("platform:rtc-ds1742"); |