diff options
author | Torsten Ertbjerg Rasmussen <tr@newtec.dk> | 2006-12-06 23:39:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 11:39:43 -0500 |
commit | f9231a0ca1afd05543d9f83539d6ecd5c018e8cf (patch) | |
tree | 4305db0c914b3789296b05774c48aec76c0b3d21 /drivers/rtc | |
parent | 3908fd2ed920af818aa596672da68ba26173ff27 (diff) |
[PATCH] rtc: ds1743 support
The real time clocks ds1742 and ds1743 differs only in the size of the
nvram. This patch changes the existing ds1742 driver to support also
ds1743. The main change is that the nvram size is determined from the
resource attached to the device.
The patch have benefitted from suggestions from Atsushi Nemeto, who is the
author of the ds1742 driver.
Signed-off-by: Torsten Rasmussen Rasmussen <tr@newtec.dk>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Acked-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1742.c | 67 |
2 files changed, 41 insertions, 30 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4d32bad79f1b..2a63ab2b47f4 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -154,11 +154,11 @@ config RTC_DRV_DS1672 | |||
154 | will be called rtc-ds1672. | 154 | will be called rtc-ds1672. |
155 | 155 | ||
156 | config RTC_DRV_DS1742 | 156 | config RTC_DRV_DS1742 |
157 | tristate "Dallas DS1742" | 157 | tristate "Dallas DS1742/1743" |
158 | depends on RTC_CLASS | 158 | depends on RTC_CLASS |
159 | help | 159 | help |
160 | If you say yes here you get support for the | 160 | If you say yes here you get support for the |
161 | Dallas DS1742 timekeeping chip. | 161 | Dallas DS1742/1743 timekeeping chip. |
162 | 162 | ||
163 | This driver can also be built as a module. If so, the module | 163 | This driver can also be built as a module. If so, the module |
164 | will be called rtc-ds1742. | 164 | will be called rtc-ds1742. |
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 | } |