diff options
Diffstat (limited to 'drivers/rtc/rtc-ds1742.c')
-rw-r--r-- | drivers/rtc/rtc-ds1742.c | 67 |
1 files changed, 39 insertions, 28 deletions
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c index 6273a3d240a2..17633bfa8480 100644 --- a/drivers/rtc/rtc-ds1742.c +++ b/drivers/rtc/rtc-ds1742.c | |||
@@ -6,6 +6,10 @@ | |||
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | * | ||
10 | * Copyright (C) 2006 Torsten Ertbjerg Rasmussen <tr@newtec.dk> | ||
11 | * - nvram size determined from resource | ||
12 | * - this ds1742 driver now supports ds1743. | ||
9 | */ | 13 | */ |
10 | 14 | ||
11 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
@@ -17,20 +21,19 @@ | |||
17 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
18 | #include <linux/io.h> | 22 | #include <linux/io.h> |
19 | 23 | ||
20 | #define DRV_VERSION "0.2" | 24 | #define DRV_VERSION "0.3" |
21 | 25 | ||
22 | #define RTC_REG_SIZE 0x800 | 26 | #define RTC_SIZE 8 |
23 | #define RTC_OFFSET 0x7f8 | ||
24 | 27 | ||
25 | #define RTC_CONTROL (RTC_OFFSET + 0) | 28 | #define RTC_CONTROL 0 |
26 | #define RTC_CENTURY (RTC_OFFSET + 0) | 29 | #define RTC_CENTURY 0 |
27 | #define RTC_SECONDS (RTC_OFFSET + 1) | 30 | #define RTC_SECONDS 1 |
28 | #define RTC_MINUTES (RTC_OFFSET + 2) | 31 | #define RTC_MINUTES 2 |
29 | #define RTC_HOURS (RTC_OFFSET + 3) | 32 | #define RTC_HOURS 3 |
30 | #define RTC_DAY (RTC_OFFSET + 4) | 33 | #define RTC_DAY 4 |
31 | #define RTC_DATE (RTC_OFFSET + 5) | 34 | #define RTC_DATE 5 |
32 | #define RTC_MONTH (RTC_OFFSET + 6) | 35 | #define RTC_MONTH 6 |
33 | #define RTC_YEAR (RTC_OFFSET + 7) | 36 | #define RTC_YEAR 7 |
34 | 37 | ||
35 | #define RTC_CENTURY_MASK 0x3f | 38 | #define RTC_CENTURY_MASK 0x3f |
36 | #define RTC_SECONDS_MASK 0x7f | 39 | #define RTC_SECONDS_MASK 0x7f |
@@ -48,7 +51,10 @@ | |||
48 | 51 | ||
49 | struct rtc_plat_data { | 52 | struct rtc_plat_data { |
50 | struct rtc_device *rtc; | 53 | struct rtc_device *rtc; |
51 | void __iomem *ioaddr; | 54 | void __iomem *ioaddr_nvram; |
55 | void __iomem *ioaddr_rtc; | ||
56 | size_t size_nvram; | ||
57 | size_t size; | ||
52 | unsigned long baseaddr; | 58 | unsigned long baseaddr; |
53 | unsigned long last_jiffies; | 59 | unsigned long last_jiffies; |
54 | }; | 60 | }; |
@@ -57,7 +63,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
57 | { | 63 | { |
58 | struct platform_device *pdev = to_platform_device(dev); | 64 | struct platform_device *pdev = to_platform_device(dev); |
59 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 65 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
60 | void __iomem *ioaddr = pdata->ioaddr; | 66 | void __iomem *ioaddr = pdata->ioaddr_rtc; |
61 | u8 century; | 67 | u8 century; |
62 | 68 | ||
63 | century = BIN2BCD((tm->tm_year + 1900) / 100); | 69 | century = BIN2BCD((tm->tm_year + 1900) / 100); |
@@ -82,7 +88,7 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
82 | { | 88 | { |
83 | struct platform_device *pdev = to_platform_device(dev); | 89 | struct platform_device *pdev = to_platform_device(dev); |
84 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 90 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
85 | void __iomem *ioaddr = pdata->ioaddr; | 91 | void __iomem *ioaddr = pdata->ioaddr_rtc; |
86 | unsigned int year, month, day, hour, minute, second, week; | 92 | unsigned int year, month, day, hour, minute, second, week; |
87 | unsigned int century; | 93 | unsigned int century; |
88 | 94 | ||
@@ -127,10 +133,10 @@ static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, | |||
127 | struct platform_device *pdev = | 133 | struct platform_device *pdev = |
128 | to_platform_device(container_of(kobj, struct device, kobj)); | 134 | to_platform_device(container_of(kobj, struct device, kobj)); |
129 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 135 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
130 | void __iomem *ioaddr = pdata->ioaddr; | 136 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
131 | ssize_t count; | 137 | ssize_t count; |
132 | 138 | ||
133 | for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) | 139 | for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) |
134 | *buf++ = readb(ioaddr + pos++); | 140 | *buf++ = readb(ioaddr + pos++); |
135 | return count; | 141 | return count; |
136 | } | 142 | } |
@@ -141,10 +147,10 @@ static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, | |||
141 | struct platform_device *pdev = | 147 | struct platform_device *pdev = |
142 | to_platform_device(container_of(kobj, struct device, kobj)); | 148 | to_platform_device(container_of(kobj, struct device, kobj)); |
143 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 149 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
144 | void __iomem *ioaddr = pdata->ioaddr; | 150 | void __iomem *ioaddr = pdata->ioaddr_nvram; |
145 | ssize_t count; | 151 | ssize_t count; |
146 | 152 | ||
147 | for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) | 153 | for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--) |
148 | writeb(*buf++, ioaddr + pos++); | 154 | writeb(*buf++, ioaddr + pos++); |
149 | return count; | 155 | return count; |
150 | } | 156 | } |
@@ -155,7 +161,6 @@ static struct bin_attribute ds1742_nvram_attr = { | |||
155 | .mode = S_IRUGO | S_IWUGO, | 161 | .mode = S_IRUGO | S_IWUGO, |
156 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
157 | }, | 163 | }, |
158 | .size = RTC_OFFSET, | ||
159 | .read = ds1742_nvram_read, | 164 | .read = ds1742_nvram_read, |
160 | .write = ds1742_nvram_write, | 165 | .write = ds1742_nvram_write, |
161 | }; | 166 | }; |
@@ -175,19 +180,23 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) | |||
175 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | 180 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); |
176 | if (!pdata) | 181 | if (!pdata) |
177 | return -ENOMEM; | 182 | return -ENOMEM; |
178 | if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { | 183 | pdata->size = res->end - res->start + 1; |
184 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | ||
179 | ret = -EBUSY; | 185 | ret = -EBUSY; |
180 | goto out; | 186 | goto out; |
181 | } | 187 | } |
182 | pdata->baseaddr = res->start; | 188 | pdata->baseaddr = res->start; |
183 | ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); | 189 | ioaddr = ioremap(pdata->baseaddr, pdata->size); |
184 | if (!ioaddr) { | 190 | if (!ioaddr) { |
185 | ret = -ENOMEM; | 191 | ret = -ENOMEM; |
186 | goto out; | 192 | goto out; |
187 | } | 193 | } |
188 | pdata->ioaddr = ioaddr; | 194 | pdata->ioaddr_nvram = ioaddr; |
195 | pdata->size_nvram = pdata->size - RTC_SIZE; | ||
196 | pdata->ioaddr_rtc = ioaddr + pdata->size_nvram; | ||
189 | 197 | ||
190 | /* turn RTC on if it was not on */ | 198 | /* turn RTC on if it was not on */ |
199 | ioaddr = pdata->ioaddr_rtc; | ||
191 | sec = readb(ioaddr + RTC_SECONDS); | 200 | sec = readb(ioaddr + RTC_SECONDS); |
192 | if (sec & RTC_STOP) { | 201 | if (sec & RTC_STOP) { |
193 | sec &= RTC_SECONDS_MASK; | 202 | sec &= RTC_SECONDS_MASK; |
@@ -208,6 +217,8 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) | |||
208 | pdata->rtc = rtc; | 217 | pdata->rtc = rtc; |
209 | pdata->last_jiffies = jiffies; | 218 | pdata->last_jiffies = jiffies; |
210 | platform_set_drvdata(pdev, pdata); | 219 | platform_set_drvdata(pdev, pdata); |
220 | ds1742_nvram_attr.size = max(ds1742_nvram_attr.size, | ||
221 | pdata->size_nvram); | ||
211 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); | 222 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); |
212 | if (ret) | 223 | if (ret) |
213 | goto out; | 224 | goto out; |
@@ -215,10 +226,10 @@ static int __init ds1742_rtc_probe(struct platform_device *pdev) | |||
215 | out: | 226 | out: |
216 | if (pdata->rtc) | 227 | if (pdata->rtc) |
217 | rtc_device_unregister(pdata->rtc); | 228 | rtc_device_unregister(pdata->rtc); |
218 | if (ioaddr) | 229 | if (pdata->ioaddr_nvram) |
219 | iounmap(ioaddr); | 230 | iounmap(pdata->ioaddr_nvram); |
220 | if (pdata->baseaddr) | 231 | if (pdata->baseaddr) |
221 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | 232 | release_mem_region(pdata->baseaddr, pdata->size); |
222 | kfree(pdata); | 233 | kfree(pdata); |
223 | return ret; | 234 | return ret; |
224 | } | 235 | } |
@@ -229,8 +240,8 @@ static int __devexit ds1742_rtc_remove(struct platform_device *pdev) | |||
229 | 240 | ||
230 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); | 241 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); |
231 | rtc_device_unregister(pdata->rtc); | 242 | rtc_device_unregister(pdata->rtc); |
232 | iounmap(pdata->ioaddr); | 243 | iounmap(pdata->ioaddr_nvram); |
233 | release_mem_region(pdata->baseaddr, RTC_REG_SIZE); | 244 | release_mem_region(pdata->baseaddr, pdata->size); |
234 | kfree(pdata); | 245 | kfree(pdata); |
235 | return 0; | 246 | return 0; |
236 | } | 247 | } |