diff options
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/Kconfig | 2 | ||||
-rw-r--r-- | drivers/rtc/class.c | 32 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 27 | ||||
-rw-r--r-- | drivers/rtc/rtc-mc13xxx.c | 6 |
4 files changed, 40 insertions, 27 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5a538fc1cc85..53eb4e55b289 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -8,7 +8,7 @@ config RTC_LIB | |||
8 | menuconfig RTC_CLASS | 8 | menuconfig RTC_CLASS |
9 | bool "Real Time Clock" | 9 | bool "Real Time Clock" |
10 | default n | 10 | default n |
11 | depends on !S390 | 11 | depends on !S390 && !UML |
12 | select RTC_LIB | 12 | select RTC_LIB |
13 | help | 13 | help |
14 | Generic RTC class support. If you say yes here, you will | 14 | Generic RTC class support. If you say yes here, you will |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 01a7df5317c1..e8326f26fa2f 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -21,16 +21,13 @@ | |||
21 | #include "rtc-core.h" | 21 | #include "rtc-core.h" |
22 | 22 | ||
23 | 23 | ||
24 | static DEFINE_IDR(rtc_idr); | 24 | static DEFINE_IDA(rtc_ida); |
25 | static DEFINE_MUTEX(idr_lock); | ||
26 | struct class *rtc_class; | 25 | struct class *rtc_class; |
27 | 26 | ||
28 | static void rtc_device_release(struct device *dev) | 27 | static void rtc_device_release(struct device *dev) |
29 | { | 28 | { |
30 | struct rtc_device *rtc = to_rtc_device(dev); | 29 | struct rtc_device *rtc = to_rtc_device(dev); |
31 | mutex_lock(&idr_lock); | 30 | ida_simple_remove(&rtc_ida, rtc->id); |
32 | idr_remove(&rtc_idr, rtc->id); | ||
33 | mutex_unlock(&idr_lock); | ||
34 | kfree(rtc); | 31 | kfree(rtc); |
35 | } | 32 | } |
36 | 33 | ||
@@ -146,25 +143,16 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
146 | struct rtc_wkalrm alrm; | 143 | struct rtc_wkalrm alrm; |
147 | int id, err; | 144 | int id, err; |
148 | 145 | ||
149 | if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { | 146 | id = ida_simple_get(&rtc_ida, 0, 0, GFP_KERNEL); |
150 | err = -ENOMEM; | 147 | if (id < 0) { |
148 | err = id; | ||
151 | goto exit; | 149 | goto exit; |
152 | } | 150 | } |
153 | 151 | ||
154 | |||
155 | mutex_lock(&idr_lock); | ||
156 | err = idr_get_new(&rtc_idr, NULL, &id); | ||
157 | mutex_unlock(&idr_lock); | ||
158 | |||
159 | if (err < 0) | ||
160 | goto exit; | ||
161 | |||
162 | id = id & MAX_ID_MASK; | ||
163 | |||
164 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); | 152 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); |
165 | if (rtc == NULL) { | 153 | if (rtc == NULL) { |
166 | err = -ENOMEM; | 154 | err = -ENOMEM; |
167 | goto exit_idr; | 155 | goto exit_ida; |
168 | } | 156 | } |
169 | 157 | ||
170 | rtc->id = id; | 158 | rtc->id = id; |
@@ -222,10 +210,8 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev, | |||
222 | exit_kfree: | 210 | exit_kfree: |
223 | kfree(rtc); | 211 | kfree(rtc); |
224 | 212 | ||
225 | exit_idr: | 213 | exit_ida: |
226 | mutex_lock(&idr_lock); | 214 | ida_simple_remove(&rtc_ida, id); |
227 | idr_remove(&rtc_idr, id); | ||
228 | mutex_unlock(&idr_lock); | ||
229 | 215 | ||
230 | exit: | 216 | exit: |
231 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", | 217 | dev_err(dev, "rtc core: unable to register %s, err = %d\n", |
@@ -276,7 +262,7 @@ static void __exit rtc_exit(void) | |||
276 | { | 262 | { |
277 | rtc_dev_exit(); | 263 | rtc_dev_exit(); |
278 | class_destroy(rtc_class); | 264 | class_destroy(rtc_class); |
279 | idr_destroy(&rtc_idr); | 265 | ida_destroy(&rtc_ida); |
280 | } | 266 | } |
281 | 267 | ||
282 | subsys_initcall(rtc_init); | 268 | subsys_initcall(rtc_init); |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index b2005b44e4f7..62b0763b7b9a 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -34,6 +34,7 @@ enum ds_type { | |||
34 | ds_1388, | 34 | ds_1388, |
35 | ds_3231, | 35 | ds_3231, |
36 | m41t00, | 36 | m41t00, |
37 | mcp7941x, | ||
37 | rx_8025, | 38 | rx_8025, |
38 | // rs5c372 too? different address... | 39 | // rs5c372 too? different address... |
39 | }; | 40 | }; |
@@ -43,6 +44,7 @@ enum ds_type { | |||
43 | #define DS1307_REG_SECS 0x00 /* 00-59 */ | 44 | #define DS1307_REG_SECS 0x00 /* 00-59 */ |
44 | # define DS1307_BIT_CH 0x80 | 45 | # define DS1307_BIT_CH 0x80 |
45 | # define DS1340_BIT_nEOSC 0x80 | 46 | # define DS1340_BIT_nEOSC 0x80 |
47 | # define MCP7941X_BIT_ST 0x80 | ||
46 | #define DS1307_REG_MIN 0x01 /* 00-59 */ | 48 | #define DS1307_REG_MIN 0x01 /* 00-59 */ |
47 | #define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ | 49 | #define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ |
48 | # define DS1307_BIT_12HR 0x40 /* in REG_HOUR */ | 50 | # define DS1307_BIT_12HR 0x40 /* in REG_HOUR */ |
@@ -50,6 +52,7 @@ enum ds_type { | |||
50 | # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ | 52 | # define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ |
51 | # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ | 53 | # define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ |
52 | #define DS1307_REG_WDAY 0x03 /* 01-07 */ | 54 | #define DS1307_REG_WDAY 0x03 /* 01-07 */ |
55 | # define MCP7941X_BIT_VBATEN 0x08 | ||
53 | #define DS1307_REG_MDAY 0x04 /* 01-31 */ | 56 | #define DS1307_REG_MDAY 0x04 /* 01-31 */ |
54 | #define DS1307_REG_MONTH 0x05 /* 01-12 */ | 57 | #define DS1307_REG_MONTH 0x05 /* 01-12 */ |
55 | # define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ | 58 | # define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ |
@@ -137,6 +140,8 @@ static const struct chip_desc chips[] = { | |||
137 | }, | 140 | }, |
138 | [m41t00] = { | 141 | [m41t00] = { |
139 | }, | 142 | }, |
143 | [mcp7941x] = { | ||
144 | }, | ||
140 | [rx_8025] = { | 145 | [rx_8025] = { |
141 | }, }; | 146 | }, }; |
142 | 147 | ||
@@ -149,6 +154,7 @@ static const struct i2c_device_id ds1307_id[] = { | |||
149 | { "ds1340", ds_1340 }, | 154 | { "ds1340", ds_1340 }, |
150 | { "ds3231", ds_3231 }, | 155 | { "ds3231", ds_3231 }, |
151 | { "m41t00", m41t00 }, | 156 | { "m41t00", m41t00 }, |
157 | { "mcp7941x", mcp7941x }, | ||
152 | { "pt7c4338", ds_1307 }, | 158 | { "pt7c4338", ds_1307 }, |
153 | { "rx8025", rx_8025 }, | 159 | { "rx8025", rx_8025 }, |
154 | { } | 160 | { } |
@@ -365,6 +371,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
365 | buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN | 371 | buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN |
366 | | DS1340_BIT_CENTURY; | 372 | | DS1340_BIT_CENTURY; |
367 | break; | 373 | break; |
374 | case mcp7941x: | ||
375 | buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST; | ||
376 | buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN; | ||
377 | break; | ||
368 | default: | 378 | default: |
369 | break; | 379 | break; |
370 | } | 380 | } |
@@ -809,6 +819,23 @@ read_rtc: | |||
809 | dev_warn(&client->dev, "SET TIME!\n"); | 819 | dev_warn(&client->dev, "SET TIME!\n"); |
810 | } | 820 | } |
811 | break; | 821 | break; |
822 | case mcp7941x: | ||
823 | /* make sure that the backup battery is enabled */ | ||
824 | if (!(ds1307->regs[DS1307_REG_WDAY] & MCP7941X_BIT_VBATEN)) { | ||
825 | i2c_smbus_write_byte_data(client, DS1307_REG_WDAY, | ||
826 | ds1307->regs[DS1307_REG_WDAY] | ||
827 | | MCP7941X_BIT_VBATEN); | ||
828 | } | ||
829 | |||
830 | /* clock halted? turn it on, so clock can tick. */ | ||
831 | if (!(tmp & MCP7941X_BIT_ST)) { | ||
832 | i2c_smbus_write_byte_data(client, DS1307_REG_SECS, | ||
833 | MCP7941X_BIT_ST); | ||
834 | dev_warn(&client->dev, "SET TIME!\n"); | ||
835 | goto read_rtc; | ||
836 | } | ||
837 | |||
838 | break; | ||
812 | case rx_8025: | 839 | case rx_8025: |
813 | case ds_1337: | 840 | case ds_1337: |
814 | case ds_1339: | 841 | case ds_1339: |
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index a1a278bc340d..9d0c3b478d55 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c | |||
@@ -309,7 +309,7 @@ static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev) | |||
309 | return IRQ_HANDLED; | 309 | return IRQ_HANDLED; |
310 | } | 310 | } |
311 | 311 | ||
312 | static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev) | 312 | static int __init mc13xxx_rtc_probe(struct platform_device *pdev) |
313 | { | 313 | { |
314 | int ret; | 314 | int ret; |
315 | struct mc13xxx_rtc *priv; | 315 | struct mc13xxx_rtc *priv; |
@@ -378,7 +378,7 @@ err_reset_irq_request: | |||
378 | return ret; | 378 | return ret; |
379 | } | 379 | } |
380 | 380 | ||
381 | static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev) | 381 | static int __exit mc13xxx_rtc_remove(struct platform_device *pdev) |
382 | { | 382 | { |
383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); | 383 | struct mc13xxx_rtc *priv = platform_get_drvdata(pdev); |
384 | 384 | ||
@@ -410,7 +410,7 @@ const struct platform_device_id mc13xxx_rtc_idtable[] = { | |||
410 | 410 | ||
411 | static struct platform_driver mc13xxx_rtc_driver = { | 411 | static struct platform_driver mc13xxx_rtc_driver = { |
412 | .id_table = mc13xxx_rtc_idtable, | 412 | .id_table = mc13xxx_rtc_idtable, |
413 | .remove = __devexit_p(mc13xxx_rtc_remove), | 413 | .remove = __exit_p(mc13xxx_rtc_remove), |
414 | .driver = { | 414 | .driver = { |
415 | .name = DRIVER_NAME, | 415 | .name = DRIVER_NAME, |
416 | .owner = THIS_MODULE, | 416 | .owner = THIS_MODULE, |