diff options
Diffstat (limited to 'drivers/rtc')
| -rw-r--r-- | drivers/rtc/Kconfig | 71 | ||||
| -rw-r--r-- | drivers/rtc/Makefile | 6 | ||||
| -rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 4 | ||||
| -rw-r--r-- | drivers/rtc/rtc-bq4802.c | 230 | ||||
| -rw-r--r-- | drivers/rtc/rtc-cmos.c | 127 | ||||
| -rw-r--r-- | drivers/rtc/rtc-dev.c | 12 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1286.c | 410 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1307.c | 308 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1374.c | 21 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1511.c | 13 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1553.c | 12 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds1672.c | 114 | ||||
| -rw-r--r-- | drivers/rtc/rtc-ds3234.c | 290 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m41t80.c | 43 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m48t35.c | 235 | ||||
| -rw-r--r-- | drivers/rtc/rtc-m48t59.c | 68 | ||||
| -rw-r--r-- | drivers/rtc/rtc-max6900.c | 223 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 58 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pl030.c | 11 | ||||
| -rw-r--r-- | drivers/rtc/rtc-pl031.c | 14 | ||||
| -rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 228 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sh.c | 7 | ||||
| -rw-r--r-- | drivers/rtc/rtc-starfire.c | 120 | ||||
| -rw-r--r-- | drivers/rtc/rtc-stk17ta8.c | 12 | ||||
| -rw-r--r-- | drivers/rtc/rtc-sun4v.c | 153 |
25 files changed, 2276 insertions, 514 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9a9755c92fad..f660ef3e5b29 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -220,22 +220,22 @@ config RTC_DRV_PCF8583 | |||
| 220 | will be called rtc-pcf8583. | 220 | will be called rtc-pcf8583. |
| 221 | 221 | ||
| 222 | config RTC_DRV_M41T80 | 222 | config RTC_DRV_M41T80 |
| 223 | tristate "ST M41T80/81/82/83/84/85/87" | 223 | tristate "ST M41T65/M41T80/81/82/83/84/85/87" |
| 224 | help | 224 | help |
| 225 | If you say Y here you will get support for the | 225 | If you say Y here you will get support for the ST M41T60 |
| 226 | ST M41T80 RTC chips series. Currently following chips are | 226 | and M41T80 RTC chips series. Currently, the following chips are |
| 227 | supported: M41T80, M41T81, M41T82, M41T83, M41ST84, M41ST85 | 227 | supported: M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84, |
| 228 | and M41ST87. | 228 | M41ST85, and M41ST87. |
| 229 | 229 | ||
| 230 | This driver can also be built as a module. If so, the module | 230 | This driver can also be built as a module. If so, the module |
| 231 | will be called rtc-m41t80. | 231 | will be called rtc-m41t80. |
| 232 | 232 | ||
| 233 | config RTC_DRV_M41T80_WDT | 233 | config RTC_DRV_M41T80_WDT |
| 234 | bool "ST M41T80 series RTC watchdog timer" | 234 | bool "ST M41T65/M41T80 series RTC watchdog timer" |
| 235 | depends on RTC_DRV_M41T80 | 235 | depends on RTC_DRV_M41T80 |
| 236 | help | 236 | help |
| 237 | If you say Y here you will get support for the | 237 | If you say Y here you will get support for the |
| 238 | watchdog timer in ST M41T80 RTC chips series. | 238 | watchdog timer in the ST M41T60 and M41T80 RTC chips series. |
| 239 | 239 | ||
| 240 | config RTC_DRV_TWL92330 | 240 | config RTC_DRV_TWL92330 |
| 241 | boolean "TI TWL92330/Menelaus" | 241 | boolean "TI TWL92330/Menelaus" |
| @@ -319,6 +319,15 @@ config RTC_DRV_RS5C348 | |||
| 319 | This driver can also be built as a module. If so, the module | 319 | This driver can also be built as a module. If so, the module |
| 320 | will be called rtc-rs5c348. | 320 | will be called rtc-rs5c348. |
| 321 | 321 | ||
| 322 | config RTC_DRV_DS3234 | ||
| 323 | tristate "Maxim/Dallas DS3234" | ||
| 324 | help | ||
| 325 | If you say yes here you get support for the | ||
| 326 | Maxim/Dallas DS3234 SPI RTC chip. | ||
| 327 | |||
| 328 | This driver can also be built as a module. If so, the module | ||
| 329 | will be called rtc-ds3234. | ||
| 330 | |||
| 322 | endif # SPI_MASTER | 331 | endif # SPI_MASTER |
| 323 | 332 | ||
| 324 | comment "Platform RTC drivers" | 333 | comment "Platform RTC drivers" |
| @@ -329,7 +338,7 @@ comment "Platform RTC drivers" | |||
| 329 | 338 | ||
| 330 | config RTC_DRV_CMOS | 339 | config RTC_DRV_CMOS |
| 331 | tristate "PC-style 'CMOS'" | 340 | tristate "PC-style 'CMOS'" |
| 332 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS | 341 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64 |
| 333 | default y if X86 | 342 | default y if X86 |
| 334 | help | 343 | help |
| 335 | Say "yes" here to get direct support for the real time clock | 344 | Say "yes" here to get direct support for the real time clock |
| @@ -352,6 +361,11 @@ config RTC_DRV_DS1216 | |||
| 352 | help | 361 | help |
| 353 | If you say yes here you get support for the Dallas DS1216 RTC chips. | 362 | If you say yes here you get support for the Dallas DS1216 RTC chips. |
| 354 | 363 | ||
| 364 | config RTC_DRV_DS1286 | ||
| 365 | tristate "Dallas DS1286" | ||
| 366 | help | ||
| 367 | If you say yes here you get support for the Dallas DS1286 RTC chips. | ||
| 368 | |||
| 355 | config RTC_DRV_DS1302 | 369 | config RTC_DRV_DS1302 |
| 356 | tristate "Dallas DS1302" | 370 | tristate "Dallas DS1302" |
| 357 | depends on SH_SECUREEDGE5410 | 371 | depends on SH_SECUREEDGE5410 |
| @@ -405,15 +419,36 @@ config RTC_DRV_M48T86 | |||
| 405 | This driver can also be built as a module. If so, the module | 419 | This driver can also be built as a module. If so, the module |
| 406 | will be called rtc-m48t86. | 420 | will be called rtc-m48t86. |
| 407 | 421 | ||
| 422 | config RTC_DRV_M48T35 | ||
| 423 | tristate "ST M48T35" | ||
| 424 | help | ||
| 425 | If you say Y here you will get support for the | ||
| 426 | ST M48T35 RTC chip. | ||
| 427 | |||
| 428 | This driver can also be built as a module, if so, the module | ||
| 429 | will be called "rtc-m48t35". | ||
| 430 | |||
| 408 | config RTC_DRV_M48T59 | 431 | config RTC_DRV_M48T59 |
| 409 | tristate "ST M48T59" | 432 | tristate "ST M48T59/M48T08/M48T02" |
| 410 | help | 433 | help |
| 411 | If you say Y here you will get support for the | 434 | If you say Y here you will get support for the |
| 412 | ST M48T59 RTC chip. | 435 | ST M48T59 RTC chip and compatible ST M48T08 and M48T02. |
| 436 | |||
| 437 | These chips are usually found in Sun SPARC and UltraSPARC | ||
| 438 | workstations. | ||
| 413 | 439 | ||
| 414 | This driver can also be built as a module, if so, the module | 440 | This driver can also be built as a module, if so, the module |
| 415 | will be called "rtc-m48t59". | 441 | will be called "rtc-m48t59". |
| 416 | 442 | ||
| 443 | config RTC_DRV_BQ4802 | ||
| 444 | tristate "TI BQ4802" | ||
| 445 | help | ||
| 446 | If you say Y here you will get support for the TI | ||
| 447 | BQ4802 RTC chip. | ||
| 448 | |||
| 449 | This driver can also be built as a module. If so, the module | ||
| 450 | will be called rtc-bq4802. | ||
| 451 | |||
| 417 | config RTC_DRV_V3020 | 452 | config RTC_DRV_V3020 |
| 418 | tristate "EM Microelectronic V3020" | 453 | tristate "EM Microelectronic V3020" |
| 419 | help | 454 | help |
| @@ -577,10 +612,24 @@ config RTC_DRV_RS5C313 | |||
| 577 | 612 | ||
| 578 | config RTC_DRV_PPC | 613 | config RTC_DRV_PPC |
| 579 | tristate "PowerPC machine dependent RTC support" | 614 | tristate "PowerPC machine dependent RTC support" |
| 580 | depends on PPC_MERGE | 615 | depends on PPC |
| 581 | help | 616 | help |
| 582 | The PowerPC kernel has machine-specific functions for accessing | 617 | The PowerPC kernel has machine-specific functions for accessing |
| 583 | the RTC. This exposes that functionality through the generic RTC | 618 | the RTC. This exposes that functionality through the generic RTC |
| 584 | class. | 619 | class. |
| 585 | 620 | ||
| 621 | config RTC_DRV_SUN4V | ||
| 622 | bool "SUN4V Hypervisor RTC" | ||
| 623 | depends on SPARC64 | ||
| 624 | help | ||
| 625 | If you say Y here you will get support for the Hypervisor | ||
| 626 | based RTC on SUN4V systems. | ||
| 627 | |||
| 628 | config RTC_DRV_STARFIRE | ||
| 629 | bool "Starfire RTC" | ||
| 630 | depends on SPARC64 | ||
| 631 | help | ||
| 632 | If you say Y here you will get support for the RTC found on | ||
| 633 | Starfire systems. | ||
| 634 | |||
| 586 | endif # RTC_CLASS | 635 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 18622ef84cab..d05928b3ca94 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | |||
| 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
| 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
| 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
| 26 | obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o | ||
| 26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | 27 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o |
| 27 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o | 28 | obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o |
| 28 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 29 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
| @@ -31,13 +32,18 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
| 31 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 32 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
| 32 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 33 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
| 33 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 34 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
| 35 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | ||
| 34 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 36 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
| 35 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 37 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
| 36 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 38 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
| 37 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | 39 | obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o |
| 38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 40 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
| 41 | obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o | ||
| 39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 42 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
| 40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 43 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
| 44 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | ||
| 45 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
| 46 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
| 41 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 47 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
| 42 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 48 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
| 43 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 49 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 4e888cc8be5b..37082616482b 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
| @@ -29,10 +29,10 @@ | |||
| 29 | #include <linux/completion.h> | 29 | #include <linux/completion.h> |
| 30 | 30 | ||
| 31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
| 32 | |||
| 32 | #include <mach/at91_rtc.h> | 33 | #include <mach/at91_rtc.h> |
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | #define AT91_RTC_FREQ 1 | ||
| 36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ | 36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ |
| 37 | 37 | ||
| 38 | static DECLARE_COMPLETION(at91_rtc_updated); | 38 | static DECLARE_COMPLETION(at91_rtc_updated); |
| @@ -228,8 +228,6 @@ static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | |||
| 228 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 228 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
| 229 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 229 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
| 230 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); | 230 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); |
| 231 | seq_printf(seq, "periodic_freq\t: %ld\n", | ||
| 232 | (unsigned long) AT91_RTC_FREQ); | ||
| 233 | 231 | ||
| 234 | return 0; | 232 | return 0; |
| 235 | } | 233 | } |
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c new file mode 100644 index 000000000000..189a018bdf34 --- /dev/null +++ b/drivers/rtc/rtc-bq4802.c | |||
| @@ -0,0 +1,230 @@ | |||
| 1 | /* rtc-bq4802.c: TI BQ4802 RTC driver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/io.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/rtc.h> | ||
| 12 | #include <linux/bcd.h> | ||
| 13 | |||
| 14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | ||
| 16 | MODULE_LICENSE("GPL"); | ||
| 17 | |||
| 18 | struct bq4802 { | ||
| 19 | void __iomem *regs; | ||
| 20 | unsigned long ioport; | ||
| 21 | struct rtc_device *rtc; | ||
| 22 | spinlock_t lock; | ||
| 23 | struct resource *r; | ||
| 24 | u8 (*read)(struct bq4802 *, int); | ||
| 25 | void (*write)(struct bq4802 *, int, u8); | ||
| 26 | }; | ||
| 27 | |||
| 28 | static u8 bq4802_read_io(struct bq4802 *p, int off) | ||
| 29 | { | ||
| 30 | return inb(p->ioport + off); | ||
| 31 | } | ||
| 32 | |||
| 33 | static void bq4802_write_io(struct bq4802 *p, int off, u8 val) | ||
| 34 | { | ||
| 35 | outb(val, p->ioport + off); | ||
| 36 | } | ||
| 37 | |||
| 38 | static u8 bq4802_read_mem(struct bq4802 *p, int off) | ||
| 39 | { | ||
| 40 | return readb(p->regs + off); | ||
| 41 | } | ||
| 42 | |||
| 43 | static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) | ||
| 44 | { | ||
| 45 | writeb(val, p->regs + off); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int bq4802_read_time(struct device *dev, struct rtc_time *tm) | ||
| 49 | { | ||
| 50 | struct platform_device *pdev = to_platform_device(dev); | ||
| 51 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 52 | unsigned long flags; | ||
| 53 | unsigned int century; | ||
| 54 | u8 val; | ||
| 55 | |||
| 56 | spin_lock_irqsave(&p->lock, flags); | ||
| 57 | |||
| 58 | val = p->read(p, 0x0e); | ||
| 59 | p->write(p, 0xe, val | 0x08); | ||
| 60 | |||
| 61 | tm->tm_sec = p->read(p, 0x00); | ||
| 62 | tm->tm_min = p->read(p, 0x02); | ||
| 63 | tm->tm_hour = p->read(p, 0x04); | ||
| 64 | tm->tm_mday = p->read(p, 0x06); | ||
| 65 | tm->tm_mon = p->read(p, 0x09); | ||
| 66 | tm->tm_year = p->read(p, 0x0a); | ||
| 67 | tm->tm_wday = p->read(p, 0x08); | ||
| 68 | century = p->read(p, 0x0f); | ||
| 69 | |||
| 70 | p->write(p, 0x0e, val); | ||
| 71 | |||
| 72 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 73 | |||
| 74 | BCD_TO_BIN(tm->tm_sec); | ||
| 75 | BCD_TO_BIN(tm->tm_min); | ||
| 76 | BCD_TO_BIN(tm->tm_hour); | ||
| 77 | BCD_TO_BIN(tm->tm_mday); | ||
| 78 | BCD_TO_BIN(tm->tm_mon); | ||
| 79 | BCD_TO_BIN(tm->tm_year); | ||
| 80 | BCD_TO_BIN(tm->tm_wday); | ||
| 81 | BCD_TO_BIN(century); | ||
| 82 | |||
| 83 | tm->tm_year += (century * 100); | ||
| 84 | tm->tm_year -= 1900; | ||
| 85 | |||
| 86 | tm->tm_mon--; | ||
| 87 | |||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int bq4802_set_time(struct device *dev, struct rtc_time *tm) | ||
| 92 | { | ||
| 93 | struct platform_device *pdev = to_platform_device(dev); | ||
| 94 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 95 | u8 sec, min, hrs, day, mon, yrs, century, val; | ||
| 96 | unsigned long flags; | ||
| 97 | unsigned int year; | ||
| 98 | |||
| 99 | year = tm->tm_year + 1900; | ||
| 100 | century = year / 100; | ||
| 101 | yrs = year % 100; | ||
| 102 | |||
| 103 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 104 | day = tm->tm_mday; | ||
| 105 | hrs = tm->tm_hour; | ||
| 106 | min = tm->tm_min; | ||
| 107 | sec = tm->tm_sec; | ||
| 108 | |||
| 109 | BIN_TO_BCD(sec); | ||
| 110 | BIN_TO_BCD(min); | ||
| 111 | BIN_TO_BCD(hrs); | ||
| 112 | BIN_TO_BCD(day); | ||
| 113 | BIN_TO_BCD(mon); | ||
| 114 | BIN_TO_BCD(yrs); | ||
| 115 | BIN_TO_BCD(century); | ||
| 116 | |||
| 117 | spin_lock_irqsave(&p->lock, flags); | ||
| 118 | |||
| 119 | val = p->read(p, 0x0e); | ||
| 120 | p->write(p, 0x0e, val | 0x08); | ||
| 121 | |||
| 122 | p->write(p, 0x00, sec); | ||
| 123 | p->write(p, 0x02, min); | ||
| 124 | p->write(p, 0x04, hrs); | ||
| 125 | p->write(p, 0x06, day); | ||
| 126 | p->write(p, 0x09, mon); | ||
| 127 | p->write(p, 0x0a, yrs); | ||
| 128 | p->write(p, 0x0f, century); | ||
| 129 | |||
| 130 | p->write(p, 0x0e, val); | ||
| 131 | |||
| 132 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static const struct rtc_class_ops bq4802_ops = { | ||
| 138 | .read_time = bq4802_read_time, | ||
| 139 | .set_time = bq4802_set_time, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __devinit bq4802_probe(struct platform_device *pdev) | ||
| 143 | { | ||
| 144 | struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 145 | int err = -ENOMEM; | ||
| 146 | |||
| 147 | if (!p) | ||
| 148 | goto out; | ||
| 149 | |||
| 150 | spin_lock_init(&p->lock); | ||
| 151 | |||
| 152 | p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 153 | if (!p->r) { | ||
| 154 | p->r = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
| 155 | err = -EINVAL; | ||
| 156 | if (!p->r) | ||
| 157 | goto out_free; | ||
| 158 | } | ||
| 159 | if (p->r->flags & IORESOURCE_IO) { | ||
| 160 | p->ioport = p->r->start; | ||
| 161 | p->read = bq4802_read_io; | ||
| 162 | p->write = bq4802_write_io; | ||
| 163 | } else if (p->r->flags & IORESOURCE_MEM) { | ||
| 164 | p->regs = ioremap(p->r->start, resource_size(p->r)); | ||
| 165 | p->read = bq4802_read_mem; | ||
| 166 | p->write = bq4802_write_mem; | ||
| 167 | } else { | ||
| 168 | err = -EINVAL; | ||
| 169 | goto out_free; | ||
| 170 | } | ||
| 171 | |||
| 172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | ||
| 173 | &bq4802_ops, THIS_MODULE); | ||
| 174 | if (IS_ERR(p->rtc)) { | ||
| 175 | err = PTR_ERR(p->rtc); | ||
| 176 | goto out_iounmap; | ||
| 177 | } | ||
| 178 | |||
| 179 | platform_set_drvdata(pdev, p); | ||
| 180 | err = 0; | ||
| 181 | out: | ||
| 182 | return err; | ||
| 183 | |||
| 184 | out_iounmap: | ||
| 185 | if (p->r->flags & IORESOURCE_MEM) | ||
| 186 | iounmap(p->regs); | ||
| 187 | out_free: | ||
| 188 | kfree(p); | ||
| 189 | goto out; | ||
| 190 | } | ||
| 191 | |||
| 192 | static int __devexit bq4802_remove(struct platform_device *pdev) | ||
| 193 | { | ||
| 194 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
| 195 | |||
| 196 | rtc_device_unregister(p->rtc); | ||
| 197 | if (p->r->flags & IORESOURCE_MEM) | ||
| 198 | iounmap(p->regs); | ||
| 199 | |||
| 200 | platform_set_drvdata(pdev, NULL); | ||
| 201 | |||
| 202 | kfree(p); | ||
| 203 | |||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* work with hotplug and coldplug */ | ||
| 208 | MODULE_ALIAS("platform:rtc-bq4802"); | ||
| 209 | |||
| 210 | static struct platform_driver bq4802_driver = { | ||
| 211 | .driver = { | ||
| 212 | .name = "rtc-bq4802", | ||
| 213 | .owner = THIS_MODULE, | ||
| 214 | }, | ||
| 215 | .probe = bq4802_probe, | ||
| 216 | .remove = __devexit_p(bq4802_remove), | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int __init bq4802_init(void) | ||
| 220 | { | ||
| 221 | return platform_driver_register(&bq4802_driver); | ||
| 222 | } | ||
| 223 | |||
| 224 | static void __exit bq4802_exit(void) | ||
| 225 | { | ||
| 226 | platform_driver_unregister(&bq4802_driver); | ||
| 227 | } | ||
| 228 | |||
| 229 | module_init(bq4802_init); | ||
| 230 | module_exit(bq4802_exit); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b184367637d0..963ad0b6a4e9 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
| @@ -636,7 +636,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 636 | */ | 636 | */ |
| 637 | #if defined(CONFIG_ATARI) | 637 | #if defined(CONFIG_ATARI) |
| 638 | address_space = 64; | 638 | address_space = 64; |
| 639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | 639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) |
| 640 | address_space = 128; | 640 | address_space = 128; |
| 641 | #else | 641 | #else |
| 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
| @@ -699,7 +699,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
| 699 | /* FIXME teach the alarm code how to handle binary mode; | 699 | /* FIXME teach the alarm code how to handle binary mode; |
| 700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
| 701 | */ | 701 | */ |
| 702 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) { | 702 | if (is_valid_irq(rtc_irq) && |
| 703 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | ||
| 703 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | 704 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); |
| 704 | retval = -ENXIO; | 705 | retval = -ENXIO; |
| 705 | goto cleanup1; | 706 | goto cleanup1; |
| @@ -912,6 +913,92 @@ static inline int cmos_poweroff(struct device *dev) | |||
| 912 | * predate even PNPBIOS should set up platform_bus devices. | 913 | * predate even PNPBIOS should set up platform_bus devices. |
| 913 | */ | 914 | */ |
| 914 | 915 | ||
| 916 | #ifdef CONFIG_ACPI | ||
| 917 | |||
| 918 | #include <linux/acpi.h> | ||
| 919 | |||
| 920 | #ifdef CONFIG_PM | ||
| 921 | static u32 rtc_handler(void *context) | ||
| 922 | { | ||
| 923 | acpi_clear_event(ACPI_EVENT_RTC); | ||
| 924 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
| 925 | return ACPI_INTERRUPT_HANDLED; | ||
| 926 | } | ||
| 927 | |||
| 928 | static inline void rtc_wake_setup(void) | ||
| 929 | { | ||
| 930 | acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL); | ||
| 931 | /* | ||
| 932 | * After the RTC handler is installed, the Fixed_RTC event should | ||
| 933 | * be disabled. Only when the RTC alarm is set will it be enabled. | ||
| 934 | */ | ||
| 935 | acpi_clear_event(ACPI_EVENT_RTC); | ||
| 936 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
| 937 | } | ||
| 938 | |||
| 939 | static void rtc_wake_on(struct device *dev) | ||
| 940 | { | ||
| 941 | acpi_clear_event(ACPI_EVENT_RTC); | ||
| 942 | acpi_enable_event(ACPI_EVENT_RTC, 0); | ||
| 943 | } | ||
| 944 | |||
| 945 | static void rtc_wake_off(struct device *dev) | ||
| 946 | { | ||
| 947 | acpi_disable_event(ACPI_EVENT_RTC, 0); | ||
| 948 | } | ||
| 949 | #else | ||
| 950 | #define rtc_wake_setup() do{}while(0) | ||
| 951 | #define rtc_wake_on NULL | ||
| 952 | #define rtc_wake_off NULL | ||
| 953 | #endif | ||
| 954 | |||
| 955 | /* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find | ||
| 956 | * its device node and pass extra config data. This helps its driver use | ||
| 957 | * capabilities that the now-obsolete mc146818 didn't have, and informs it | ||
| 958 | * that this board's RTC is wakeup-capable (per ACPI spec). | ||
| 959 | */ | ||
| 960 | static struct cmos_rtc_board_info acpi_rtc_info; | ||
| 961 | |||
| 962 | static void __devinit | ||
| 963 | cmos_wake_setup(struct device *dev) | ||
| 964 | { | ||
| 965 | if (acpi_disabled) | ||
| 966 | return; | ||
| 967 | |||
| 968 | rtc_wake_setup(); | ||
| 969 | acpi_rtc_info.wake_on = rtc_wake_on; | ||
| 970 | acpi_rtc_info.wake_off = rtc_wake_off; | ||
| 971 | |||
| 972 | /* workaround bug in some ACPI tables */ | ||
| 973 | if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) { | ||
| 974 | dev_dbg(dev, "bogus FADT month_alarm (%d)\n", | ||
| 975 | acpi_gbl_FADT.month_alarm); | ||
| 976 | acpi_gbl_FADT.month_alarm = 0; | ||
| 977 | } | ||
| 978 | |||
| 979 | acpi_rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm; | ||
| 980 | acpi_rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm; | ||
| 981 | acpi_rtc_info.rtc_century = acpi_gbl_FADT.century; | ||
| 982 | |||
| 983 | /* NOTE: S4_RTC_WAKE is NOT currently useful to Linux */ | ||
| 984 | if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE) | ||
| 985 | dev_info(dev, "RTC can wake from S4\n"); | ||
| 986 | |||
| 987 | dev->platform_data = &acpi_rtc_info; | ||
| 988 | |||
| 989 | /* RTC always wakes from S1/S2/S3, and often S4/STD */ | ||
| 990 | device_init_wakeup(dev, 1); | ||
| 991 | } | ||
| 992 | |||
| 993 | #else | ||
| 994 | |||
| 995 | static void __devinit | ||
| 996 | cmos_wake_setup(struct device *dev) | ||
| 997 | { | ||
| 998 | } | ||
| 999 | |||
| 1000 | #endif | ||
| 1001 | |||
| 915 | #ifdef CONFIG_PNP | 1002 | #ifdef CONFIG_PNP |
| 916 | 1003 | ||
| 917 | #include <linux/pnp.h> | 1004 | #include <linux/pnp.h> |
| @@ -919,6 +1006,8 @@ static inline int cmos_poweroff(struct device *dev) | |||
| 919 | static int __devinit | 1006 | static int __devinit |
| 920 | cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | 1007 | cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) |
| 921 | { | 1008 | { |
| 1009 | cmos_wake_setup(&pnp->dev); | ||
| 1010 | |||
| 922 | if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) | 1011 | if (pnp_port_start(pnp,0) == 0x70 && !pnp_irq_valid(pnp,0)) |
| 923 | /* Some machines contain a PNP entry for the RTC, but | 1012 | /* Some machines contain a PNP entry for the RTC, but |
| 924 | * don't define the IRQ. It should always be safe to | 1013 | * don't define the IRQ. It should always be safe to |
| @@ -996,6 +1085,7 @@ static struct pnp_driver cmos_pnp_driver = { | |||
| 996 | 1085 | ||
| 997 | static int __init cmos_platform_probe(struct platform_device *pdev) | 1086 | static int __init cmos_platform_probe(struct platform_device *pdev) |
| 998 | { | 1087 | { |
| 1088 | cmos_wake_setup(&pdev->dev); | ||
| 999 | return cmos_do_probe(&pdev->dev, | 1089 | return cmos_do_probe(&pdev->dev, |
| 1000 | platform_get_resource(pdev, IORESOURCE_IO, 0), | 1090 | platform_get_resource(pdev, IORESOURCE_IO, 0), |
| 1001 | platform_get_irq(pdev, 0)); | 1091 | platform_get_irq(pdev, 0)); |
| @@ -1030,29 +1120,32 @@ static struct platform_driver cmos_platform_driver = { | |||
| 1030 | 1120 | ||
| 1031 | static int __init cmos_init(void) | 1121 | static int __init cmos_init(void) |
| 1032 | { | 1122 | { |
| 1123 | int retval = 0; | ||
| 1124 | |||
| 1033 | #ifdef CONFIG_PNP | 1125 | #ifdef CONFIG_PNP |
| 1034 | if (pnp_platform_devices) | 1126 | pnp_register_driver(&cmos_pnp_driver); |
| 1035 | return pnp_register_driver(&cmos_pnp_driver); | 1127 | #endif |
| 1036 | else | 1128 | |
| 1037 | return platform_driver_probe(&cmos_platform_driver, | 1129 | if (!cmos_rtc.dev) |
| 1038 | cmos_platform_probe); | 1130 | retval = platform_driver_probe(&cmos_platform_driver, |
| 1039 | #else | 1131 | cmos_platform_probe); |
| 1040 | return platform_driver_probe(&cmos_platform_driver, | 1132 | |
| 1041 | cmos_platform_probe); | 1133 | if (retval == 0) |
| 1042 | #endif /* CONFIG_PNP */ | 1134 | return 0; |
| 1135 | |||
| 1136 | #ifdef CONFIG_PNP | ||
| 1137 | pnp_unregister_driver(&cmos_pnp_driver); | ||
| 1138 | #endif | ||
| 1139 | return retval; | ||
| 1043 | } | 1140 | } |
| 1044 | module_init(cmos_init); | 1141 | module_init(cmos_init); |
| 1045 | 1142 | ||
| 1046 | static void __exit cmos_exit(void) | 1143 | static void __exit cmos_exit(void) |
| 1047 | { | 1144 | { |
| 1048 | #ifdef CONFIG_PNP | 1145 | #ifdef CONFIG_PNP |
| 1049 | if (pnp_platform_devices) | 1146 | pnp_unregister_driver(&cmos_pnp_driver); |
| 1050 | pnp_unregister_driver(&cmos_pnp_driver); | 1147 | #endif |
| 1051 | else | ||
| 1052 | platform_driver_unregister(&cmos_platform_driver); | ||
| 1053 | #else | ||
| 1054 | platform_driver_unregister(&cmos_platform_driver); | 1148 | platform_driver_unregister(&cmos_platform_driver); |
| 1055 | #endif /* CONFIG_PNP */ | ||
| 1056 | } | 1149 | } |
| 1057 | module_exit(cmos_exit); | 1150 | module_exit(cmos_exit); |
| 1058 | 1151 | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 52e2743b04ec..079e9ed907e0 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -432,9 +432,15 @@ static int rtc_dev_release(struct inode *inode, struct file *file) | |||
| 432 | { | 432 | { |
| 433 | struct rtc_device *rtc = file->private_data; | 433 | struct rtc_device *rtc = file->private_data; |
| 434 | 434 | ||
| 435 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | 435 | /* We shut down the repeating IRQs that userspace enabled, |
| 436 | clear_uie(rtc); | 436 | * since nothing is listening to them. |
| 437 | #endif | 437 | * - Update (UIE) ... currently only managed through ioctls |
| 438 | * - Periodic (PIE) ... also used through rtc_*() interface calls | ||
| 439 | * | ||
| 440 | * Leave the alarm alone; it may be set to trigger a system wakeup | ||
| 441 | * later, or be used by kernel code, and is a one-shot event anyway. | ||
| 442 | */ | ||
| 443 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); | ||
| 438 | rtc_irq_set_state(rtc, NULL, 0); | 444 | rtc_irq_set_state(rtc, NULL, 0); |
| 439 | 445 | ||
| 440 | if (rtc->ops->release) | 446 | if (rtc->ops->release) |
diff --git a/drivers/rtc/rtc-ds1286.c b/drivers/rtc/rtc-ds1286.c new file mode 100644 index 000000000000..4fcb16bbff4a --- /dev/null +++ b/drivers/rtc/rtc-ds1286.c | |||
| @@ -0,0 +1,410 @@ | |||
| 1 | /* | ||
| 2 | * DS1286 Real Time Clock interface for Linux | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998, 1999, 2000 Ralf Baechle | ||
| 5 | * Copyright (C) 2008 Thomas Bogendoerfer | ||
| 6 | * | ||
| 7 | * Based on code written by Paul Gortmaker. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/rtc.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/bcd.h> | ||
| 19 | #include <linux/ds1286.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | |||
| 22 | #define DRV_VERSION "1.0" | ||
| 23 | |||
| 24 | struct ds1286_priv { | ||
| 25 | struct rtc_device *rtc; | ||
| 26 | u32 __iomem *rtcregs; | ||
| 27 | size_t size; | ||
| 28 | unsigned long baseaddr; | ||
| 29 | spinlock_t lock; | ||
| 30 | }; | ||
| 31 | |||
| 32 | static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg) | ||
| 33 | { | ||
| 34 | return __raw_readl(&priv->rtcregs[reg]) & 0xff; | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg) | ||
| 38 | { | ||
| 39 | __raw_writel(data, &priv->rtcregs[reg]); | ||
| 40 | } | ||
| 41 | |||
| 42 | #ifdef CONFIG_RTC_INTF_DEV | ||
| 43 | |||
| 44 | static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 45 | { | ||
| 46 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 47 | unsigned long flags; | ||
| 48 | unsigned char val; | ||
| 49 | |||
| 50 | switch (cmd) { | ||
| 51 | case RTC_AIE_OFF: | ||
| 52 | /* Mask alarm int. enab. bit */ | ||
| 53 | spin_lock_irqsave(&priv->lock, flags); | ||
| 54 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
| 55 | val |= RTC_TDM; | ||
| 56 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
| 57 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 58 | break; | ||
| 59 | case RTC_AIE_ON: | ||
| 60 | /* Allow alarm interrupts. */ | ||
| 61 | spin_lock_irqsave(&priv->lock, flags); | ||
| 62 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
| 63 | val &= ~RTC_TDM; | ||
| 64 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
| 65 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 66 | break; | ||
| 67 | case RTC_WIE_OFF: | ||
| 68 | /* Mask watchdog int. enab. bit */ | ||
| 69 | spin_lock_irqsave(&priv->lock, flags); | ||
| 70 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
| 71 | val |= RTC_WAM; | ||
| 72 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
| 73 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 74 | break; | ||
| 75 | case RTC_WIE_ON: | ||
| 76 | /* Allow watchdog interrupts. */ | ||
| 77 | spin_lock_irqsave(&priv->lock, flags); | ||
| 78 | val = ds1286_rtc_read(priv, RTC_CMD); | ||
| 79 | val &= ~RTC_WAM; | ||
| 80 | ds1286_rtc_write(priv, val, RTC_CMD); | ||
| 81 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 82 | break; | ||
| 83 | default: | ||
| 84 | return -ENOIOCTLCMD; | ||
| 85 | } | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | #else | ||
| 90 | #define ds1286_ioctl NULL | ||
| 91 | #endif | ||
| 92 | |||
| 93 | #ifdef CONFIG_PROC_FS | ||
| 94 | |||
| 95 | static int ds1286_proc(struct device *dev, struct seq_file *seq) | ||
| 96 | { | ||
| 97 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 98 | unsigned char month, cmd, amode; | ||
| 99 | const char *s; | ||
| 100 | |||
| 101 | month = ds1286_rtc_read(priv, RTC_MONTH); | ||
| 102 | seq_printf(seq, | ||
| 103 | "oscillator\t: %s\n" | ||
| 104 | "square_wave\t: %s\n", | ||
| 105 | (month & RTC_EOSC) ? "disabled" : "enabled", | ||
| 106 | (month & RTC_ESQW) ? "disabled" : "enabled"); | ||
| 107 | |||
| 108 | amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) | | ||
| 109 | ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) | | ||
| 110 | ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7); | ||
| 111 | switch (amode) { | ||
| 112 | case 7: | ||
| 113 | s = "each minute"; | ||
| 114 | break; | ||
| 115 | case 3: | ||
| 116 | s = "minutes match"; | ||
| 117 | break; | ||
| 118 | case 1: | ||
| 119 | s = "hours and minutes match"; | ||
| 120 | break; | ||
| 121 | case 0: | ||
| 122 | s = "days, hours and minutes match"; | ||
| 123 | break; | ||
| 124 | default: | ||
| 125 | s = "invalid"; | ||
| 126 | break; | ||
| 127 | } | ||
| 128 | seq_printf(seq, "alarm_mode\t: %s\n", s); | ||
| 129 | |||
| 130 | cmd = ds1286_rtc_read(priv, RTC_CMD); | ||
| 131 | seq_printf(seq, | ||
| 132 | "alarm_enable\t: %s\n" | ||
| 133 | "wdog_alarm\t: %s\n" | ||
| 134 | "alarm_mask\t: %s\n" | ||
| 135 | "wdog_alarm_mask\t: %s\n" | ||
| 136 | "interrupt_mode\t: %s\n" | ||
| 137 | "INTB_mode\t: %s_active\n" | ||
| 138 | "interrupt_pins\t: %s\n", | ||
| 139 | (cmd & RTC_TDF) ? "yes" : "no", | ||
| 140 | (cmd & RTC_WAF) ? "yes" : "no", | ||
| 141 | (cmd & RTC_TDM) ? "disabled" : "enabled", | ||
| 142 | (cmd & RTC_WAM) ? "disabled" : "enabled", | ||
| 143 | (cmd & RTC_PU_LVL) ? "pulse" : "level", | ||
| 144 | (cmd & RTC_IBH_LO) ? "low" : "high", | ||
| 145 | (cmd & RTC_IPSW) ? "unswapped" : "swapped"); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | #else | ||
| 150 | #define ds1286_proc NULL | ||
| 151 | #endif | ||
| 152 | |||
| 153 | static int ds1286_read_time(struct device *dev, struct rtc_time *tm) | ||
| 154 | { | ||
| 155 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 156 | unsigned char save_control; | ||
| 157 | unsigned long flags; | ||
| 158 | unsigned long uip_watchdog = jiffies; | ||
| 159 | |||
| 160 | /* | ||
| 161 | * read RTC once any update in progress is done. The update | ||
| 162 | * can take just over 2ms. We wait 10 to 20ms. There is no need to | ||
| 163 | * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. | ||
| 164 | * If you need to know *exactly* when a second has started, enable | ||
| 165 | * periodic update complete interrupts, (via ioctl) and then | ||
| 166 | * immediately read /dev/rtc which will block until you get the IRQ. | ||
| 167 | * Once the read clears, read the RTC time (again via ioctl). Easy. | ||
| 168 | */ | ||
| 169 | |||
| 170 | if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE) | ||
| 171 | while (time_before(jiffies, uip_watchdog + 2*HZ/100)) | ||
| 172 | barrier(); | ||
| 173 | |||
| 174 | /* | ||
| 175 | * Only the values that we read from the RTC are set. We leave | ||
| 176 | * tm_wday, tm_yday and tm_isdst untouched. Even though the | ||
| 177 | * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated | ||
| 178 | * by the RTC when initially set to a non-zero value. | ||
| 179 | */ | ||
| 180 | spin_lock_irqsave(&priv->lock, flags); | ||
| 181 | save_control = ds1286_rtc_read(priv, RTC_CMD); | ||
| 182 | ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD); | ||
| 183 | |||
| 184 | tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS); | ||
| 185 | tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES); | ||
| 186 | tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f; | ||
| 187 | tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE); | ||
| 188 | tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f; | ||
| 189 | tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR); | ||
| 190 | |||
| 191 | ds1286_rtc_write(priv, save_control, RTC_CMD); | ||
| 192 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 193 | |||
| 194 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
| 195 | tm->tm_min = bcd2bin(tm->tm_min); | ||
| 196 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
| 197 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
| 198 | tm->tm_mon = bcd2bin(tm->tm_mon); | ||
| 199 | tm->tm_year = bcd2bin(tm->tm_year); | ||
| 200 | |||
| 201 | /* | ||
| 202 | * Account for differences between how the RTC uses the values | ||
| 203 | * and how they are defined in a struct rtc_time; | ||
| 204 | */ | ||
| 205 | if (tm->tm_year < 45) | ||
| 206 | tm->tm_year += 30; | ||
| 207 | tm->tm_year += 40; | ||
| 208 | if (tm->tm_year < 70) | ||
| 209 | tm->tm_year += 100; | ||
| 210 | |||
| 211 | tm->tm_mon--; | ||
| 212 | |||
| 213 | return rtc_valid_tm(tm); | ||
| 214 | } | ||
| 215 | |||
| 216 | static int ds1286_set_time(struct device *dev, struct rtc_time *tm) | ||
| 217 | { | ||
| 218 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 219 | unsigned char mon, day, hrs, min, sec; | ||
| 220 | unsigned char save_control; | ||
| 221 | unsigned int yrs; | ||
| 222 | unsigned long flags; | ||
| 223 | |||
| 224 | yrs = tm->tm_year + 1900; | ||
| 225 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 226 | day = tm->tm_mday; | ||
| 227 | hrs = tm->tm_hour; | ||
| 228 | min = tm->tm_min; | ||
| 229 | sec = tm->tm_sec; | ||
| 230 | |||
| 231 | if (yrs < 1970) | ||
| 232 | return -EINVAL; | ||
| 233 | |||
| 234 | yrs -= 1940; | ||
| 235 | if (yrs > 255) /* They are unsigned */ | ||
| 236 | return -EINVAL; | ||
| 237 | |||
| 238 | if (yrs >= 100) | ||
| 239 | yrs -= 100; | ||
| 240 | |||
| 241 | sec = bin2bcd(sec); | ||
| 242 | min = bin2bcd(min); | ||
| 243 | hrs = bin2bcd(hrs); | ||
| 244 | day = bin2bcd(day); | ||
| 245 | mon = bin2bcd(mon); | ||
| 246 | yrs = bin2bcd(yrs); | ||
| 247 | |||
| 248 | spin_lock_irqsave(&priv->lock, flags); | ||
| 249 | save_control = ds1286_rtc_read(priv, RTC_CMD); | ||
| 250 | ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD); | ||
| 251 | |||
| 252 | ds1286_rtc_write(priv, yrs, RTC_YEAR); | ||
| 253 | ds1286_rtc_write(priv, mon, RTC_MONTH); | ||
| 254 | ds1286_rtc_write(priv, day, RTC_DATE); | ||
| 255 | ds1286_rtc_write(priv, hrs, RTC_HOURS); | ||
| 256 | ds1286_rtc_write(priv, min, RTC_MINUTES); | ||
| 257 | ds1286_rtc_write(priv, sec, RTC_SECONDS); | ||
| 258 | ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND); | ||
| 259 | |||
| 260 | ds1286_rtc_write(priv, save_control, RTC_CMD); | ||
| 261 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 266 | { | ||
| 267 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 268 | unsigned char cmd; | ||
| 269 | unsigned long flags; | ||
| 270 | |||
| 271 | /* | ||
| 272 | * Only the values that we read from the RTC are set. That | ||
| 273 | * means only tm_wday, tm_hour, tm_min. | ||
| 274 | */ | ||
| 275 | spin_lock_irqsave(&priv->lock, flags); | ||
| 276 | alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f; | ||
| 277 | alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x1f; | ||
| 278 | alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x07; | ||
| 279 | cmd = ds1286_rtc_read(priv, RTC_CMD); | ||
| 280 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 281 | |||
| 282 | alm->time.tm_min = bcd2bin(alm->time.tm_min); | ||
| 283 | alm->time.tm_hour = bcd2bin(alm->time.tm_hour); | ||
| 284 | alm->time.tm_sec = 0; | ||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
| 289 | { | ||
| 290 | struct ds1286_priv *priv = dev_get_drvdata(dev); | ||
| 291 | unsigned char hrs, min, sec; | ||
| 292 | |||
| 293 | hrs = alm->time.tm_hour; | ||
| 294 | min = alm->time.tm_min; | ||
| 295 | sec = alm->time.tm_sec; | ||
| 296 | |||
| 297 | if (hrs >= 24) | ||
| 298 | hrs = 0xff; | ||
| 299 | |||
| 300 | if (min >= 60) | ||
| 301 | min = 0xff; | ||
| 302 | |||
| 303 | if (sec != 0) | ||
| 304 | return -EINVAL; | ||
| 305 | |||
| 306 | min = bin2bcd(min); | ||
| 307 | hrs = bin2bcd(hrs); | ||
| 308 | |||
| 309 | spin_lock(&priv->lock); | ||
| 310 | ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM); | ||
| 311 | ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM); | ||
| 312 | spin_unlock(&priv->lock); | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static const struct rtc_class_ops ds1286_ops = { | ||
| 318 | .ioctl = ds1286_ioctl, | ||
| 319 | .proc = ds1286_proc, | ||
| 320 | .read_time = ds1286_read_time, | ||
| 321 | .set_time = ds1286_set_time, | ||
| 322 | .read_alarm = ds1286_read_alarm, | ||
| 323 | .set_alarm = ds1286_set_alarm, | ||
| 324 | }; | ||
| 325 | |||
| 326 | static int __devinit ds1286_probe(struct platform_device *pdev) | ||
| 327 | { | ||
| 328 | struct rtc_device *rtc; | ||
| 329 | struct resource *res; | ||
| 330 | struct ds1286_priv *priv; | ||
| 331 | int ret = 0; | ||
| 332 | |||
| 333 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 334 | if (!res) | ||
| 335 | return -ENODEV; | ||
| 336 | priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL); | ||
| 337 | if (!priv) | ||
| 338 | return -ENOMEM; | ||
| 339 | |||
| 340 | priv->size = res->end - res->start + 1; | ||
| 341 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | ||
| 342 | ret = -EBUSY; | ||
| 343 | goto out; | ||
| 344 | } | ||
| 345 | priv->baseaddr = res->start; | ||
| 346 | priv->rtcregs = ioremap(priv->baseaddr, priv->size); | ||
| 347 | if (!priv->rtcregs) { | ||
| 348 | ret = -ENOMEM; | ||
| 349 | goto out; | ||
| 350 | } | ||
| 351 | spin_lock_init(&priv->lock); | ||
| 352 | rtc = rtc_device_register("ds1286", &pdev->dev, | ||
| 353 | &ds1286_ops, THIS_MODULE); | ||
| 354 | if (IS_ERR(rtc)) { | ||
| 355 | ret = PTR_ERR(rtc); | ||
| 356 | goto out; | ||
| 357 | } | ||
| 358 | priv->rtc = rtc; | ||
| 359 | platform_set_drvdata(pdev, priv); | ||
| 360 | return 0; | ||
| 361 | |||
| 362 | out: | ||
| 363 | if (priv->rtc) | ||
| 364 | rtc_device_unregister(priv->rtc); | ||
| 365 | if (priv->rtcregs) | ||
| 366 | iounmap(priv->rtcregs); | ||
| 367 | if (priv->baseaddr) | ||
| 368 | release_mem_region(priv->baseaddr, priv->size); | ||
| 369 | kfree(priv); | ||
| 370 | return ret; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int __devexit ds1286_remove(struct platform_device *pdev) | ||
| 374 | { | ||
| 375 | struct ds1286_priv *priv = platform_get_drvdata(pdev); | ||
| 376 | |||
| 377 | rtc_device_unregister(priv->rtc); | ||
| 378 | iounmap(priv->rtcregs); | ||
| 379 | release_mem_region(priv->baseaddr, priv->size); | ||
| 380 | kfree(priv); | ||
| 381 | return 0; | ||
| 382 | } | ||
| 383 | |||
| 384 | static struct platform_driver ds1286_platform_driver = { | ||
| 385 | .driver = { | ||
| 386 | .name = "rtc-ds1286", | ||
| 387 | .owner = THIS_MODULE, | ||
| 388 | }, | ||
| 389 | .probe = ds1286_probe, | ||
| 390 | .remove = __devexit_p(ds1286_remove), | ||
| 391 | }; | ||
| 392 | |||
| 393 | static int __init ds1286_init(void) | ||
| 394 | { | ||
| 395 | return platform_driver_register(&ds1286_platform_driver); | ||
| 396 | } | ||
| 397 | |||
| 398 | static void __exit ds1286_exit(void) | ||
| 399 | { | ||
| 400 | platform_driver_unregister(&ds1286_platform_driver); | ||
| 401 | } | ||
| 402 | |||
| 403 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | ||
| 404 | MODULE_DESCRIPTION("DS1286 RTC driver"); | ||
| 405 | MODULE_LICENSE("GPL"); | ||
| 406 | MODULE_VERSION(DRV_VERSION); | ||
| 407 | MODULE_ALIAS("platform:rtc-ds1286"); | ||
| 408 | |||
| 409 | module_init(ds1286_init); | ||
| 410 | module_exit(ds1286_exit); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bbf97e65202a..4fcf0734a6ef 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
| @@ -23,10 +23,6 @@ | |||
| 23 | * to have set the chip up as a clock (turning on the oscillator and | 23 | * to have set the chip up as a clock (turning on the oscillator and |
| 24 | * setting the date and time), Linux can ignore the non-clock features. | 24 | * setting the date and time), Linux can ignore the non-clock features. |
| 25 | * That's a natural job for a factory or repair bench. | 25 | * That's a natural job for a factory or repair bench. |
| 26 | * | ||
| 27 | * This is currently a simple no-alarms driver. If your board has the | ||
| 28 | * alarm irq wired up on a ds1337 or ds1339, and you want to use that, | ||
| 29 | * then look at the rtc-rs5c372 driver for code to steal... | ||
| 30 | */ | 26 | */ |
| 31 | enum ds_type { | 27 | enum ds_type { |
| 32 | ds_1307, | 28 | ds_1307, |
| @@ -67,6 +63,7 @@ enum ds_type { | |||
| 67 | # define DS1307_BIT_RS0 0x01 | 63 | # define DS1307_BIT_RS0 0x01 |
| 68 | #define DS1337_REG_CONTROL 0x0e | 64 | #define DS1337_REG_CONTROL 0x0e |
| 69 | # define DS1337_BIT_nEOSC 0x80 | 65 | # define DS1337_BIT_nEOSC 0x80 |
| 66 | # define DS1339_BIT_BBSQI 0x20 | ||
| 70 | # define DS1337_BIT_RS2 0x10 | 67 | # define DS1337_BIT_RS2 0x10 |
| 71 | # define DS1337_BIT_RS1 0x08 | 68 | # define DS1337_BIT_RS1 0x08 |
| 72 | # define DS1337_BIT_INTCN 0x04 | 69 | # define DS1337_BIT_INTCN 0x04 |
| @@ -83,19 +80,22 @@ enum ds_type { | |||
| 83 | # define DS1337_BIT_OSF 0x80 | 80 | # define DS1337_BIT_OSF 0x80 |
| 84 | # define DS1337_BIT_A2I 0x02 | 81 | # define DS1337_BIT_A2I 0x02 |
| 85 | # define DS1337_BIT_A1I 0x01 | 82 | # define DS1337_BIT_A1I 0x01 |
| 83 | #define DS1339_REG_ALARM1_SECS 0x07 | ||
| 86 | #define DS1339_REG_TRICKLE 0x10 | 84 | #define DS1339_REG_TRICKLE 0x10 |
| 87 | 85 | ||
| 88 | 86 | ||
| 89 | 87 | ||
| 90 | struct ds1307 { | 88 | struct ds1307 { |
| 91 | u8 reg_addr; | 89 | u8 reg_addr; |
| 92 | bool has_nvram; | 90 | u8 regs[11]; |
| 93 | u8 regs[8]; | ||
| 94 | enum ds_type type; | 91 | enum ds_type type; |
| 92 | unsigned long flags; | ||
| 93 | #define HAS_NVRAM 0 /* bit 0 == sysfs file active */ | ||
| 94 | #define HAS_ALARM 1 /* bit 1 == irq claimed */ | ||
| 95 | struct i2c_msg msg[2]; | 95 | struct i2c_msg msg[2]; |
| 96 | struct i2c_client *client; | 96 | struct i2c_client *client; |
| 97 | struct i2c_client dev; | ||
| 98 | struct rtc_device *rtc; | 97 | struct rtc_device *rtc; |
| 98 | struct work_struct work; | ||
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | struct chip_desc { | 101 | struct chip_desc { |
| @@ -132,12 +132,79 @@ static const struct i2c_device_id ds1307_id[] = { | |||
| 132 | }; | 132 | }; |
| 133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); | 133 | MODULE_DEVICE_TABLE(i2c, ds1307_id); |
| 134 | 134 | ||
| 135 | /*----------------------------------------------------------------------*/ | ||
| 136 | |||
| 137 | /* | ||
| 138 | * The IRQ logic includes a "real" handler running in IRQ context just | ||
| 139 | * long enough to schedule this workqueue entry. We need a task context | ||
| 140 | * to talk to the RTC, since I2C I/O calls require that; and disable the | ||
| 141 | * IRQ until we clear its status on the chip, so that this handler can | ||
| 142 | * work with any type of triggering (not just falling edge). | ||
| 143 | * | ||
| 144 | * The ds1337 and ds1339 both have two alarms, but we only use the first | ||
| 145 | * one (with a "seconds" field). For ds1337 we expect nINTA is our alarm | ||
| 146 | * signal; ds1339 chips have only one alarm signal. | ||
| 147 | */ | ||
| 148 | static void ds1307_work(struct work_struct *work) | ||
| 149 | { | ||
| 150 | struct ds1307 *ds1307; | ||
| 151 | struct i2c_client *client; | ||
| 152 | struct mutex *lock; | ||
| 153 | int stat, control; | ||
| 154 | |||
| 155 | ds1307 = container_of(work, struct ds1307, work); | ||
| 156 | client = ds1307->client; | ||
| 157 | lock = &ds1307->rtc->ops_lock; | ||
| 158 | |||
| 159 | mutex_lock(lock); | ||
| 160 | stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); | ||
| 161 | if (stat < 0) | ||
| 162 | goto out; | ||
| 163 | |||
| 164 | if (stat & DS1337_BIT_A1I) { | ||
| 165 | stat &= ~DS1337_BIT_A1I; | ||
| 166 | i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat); | ||
| 167 | |||
| 168 | control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
| 169 | if (control < 0) | ||
| 170 | goto out; | ||
| 171 | |||
| 172 | control &= ~DS1337_BIT_A1IE; | ||
| 173 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control); | ||
| 174 | |||
| 175 | /* rtc_update_irq() assumes that it is called | ||
| 176 | * from IRQ-disabled context. | ||
| 177 | */ | ||
| 178 | local_irq_disable(); | ||
| 179 | rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); | ||
| 180 | local_irq_enable(); | ||
| 181 | } | ||
| 182 | |||
| 183 | out: | ||
| 184 | if (test_bit(HAS_ALARM, &ds1307->flags)) | ||
| 185 | enable_irq(client->irq); | ||
| 186 | mutex_unlock(lock); | ||
| 187 | } | ||
| 188 | |||
| 189 | static irqreturn_t ds1307_irq(int irq, void *dev_id) | ||
| 190 | { | ||
| 191 | struct i2c_client *client = dev_id; | ||
| 192 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
| 193 | |||
| 194 | disable_irq_nosync(irq); | ||
| 195 | schedule_work(&ds1307->work); | ||
| 196 | return IRQ_HANDLED; | ||
| 197 | } | ||
| 198 | |||
| 199 | /*----------------------------------------------------------------------*/ | ||
| 200 | |||
| 135 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) | 201 | static int ds1307_get_time(struct device *dev, struct rtc_time *t) |
| 136 | { | 202 | { |
| 137 | struct ds1307 *ds1307 = dev_get_drvdata(dev); | 203 | struct ds1307 *ds1307 = dev_get_drvdata(dev); |
| 138 | int tmp; | 204 | int tmp; |
| 139 | 205 | ||
| 140 | /* read the RTC date and time registers all at once */ | 206 | /* read the RTC date and time registers all at once */ |
| 207 | ds1307->reg_addr = 0; | ||
| 141 | ds1307->msg[1].flags = I2C_M_RD; | 208 | ds1307->msg[1].flags = I2C_M_RD; |
| 142 | ds1307->msg[1].len = 7; | 209 | ds1307->msg[1].len = 7; |
| 143 | 210 | ||
| @@ -231,9 +298,186 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
| 231 | return 0; | 298 | return 0; |
| 232 | } | 299 | } |
| 233 | 300 | ||
| 301 | static int ds1307_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
| 302 | { | ||
| 303 | struct i2c_client *client = to_i2c_client(dev); | ||
| 304 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
| 305 | int ret; | ||
| 306 | |||
| 307 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
| 308 | return -EINVAL; | ||
| 309 | |||
| 310 | /* read all ALARM1, ALARM2, and status registers at once */ | ||
| 311 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
| 312 | ds1307->msg[1].flags = I2C_M_RD; | ||
| 313 | ds1307->msg[1].len = 9; | ||
| 314 | |||
| 315 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
| 316 | ds1307->msg, 2); | ||
| 317 | if (ret != 2) { | ||
| 318 | dev_err(dev, "%s error %d\n", "alarm read", ret); | ||
| 319 | return -EIO; | ||
| 320 | } | ||
| 321 | |||
| 322 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
| 323 | "alarm read", | ||
| 324 | ds1307->regs[0], ds1307->regs[1], | ||
| 325 | ds1307->regs[2], ds1307->regs[3], | ||
| 326 | ds1307->regs[4], ds1307->regs[5], | ||
| 327 | ds1307->regs[6], ds1307->regs[7], | ||
| 328 | ds1307->regs[8]); | ||
| 329 | |||
| 330 | /* report alarm time (ALARM1); assume 24 hour and day-of-month modes, | ||
| 331 | * and that all four fields are checked matches | ||
| 332 | */ | ||
| 333 | t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f); | ||
| 334 | t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f); | ||
| 335 | t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f); | ||
| 336 | t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f); | ||
| 337 | t->time.tm_mon = -1; | ||
| 338 | t->time.tm_year = -1; | ||
| 339 | t->time.tm_wday = -1; | ||
| 340 | t->time.tm_yday = -1; | ||
| 341 | t->time.tm_isdst = -1; | ||
| 342 | |||
| 343 | /* ... and status */ | ||
| 344 | t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE); | ||
| 345 | t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I); | ||
| 346 | |||
| 347 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
| 348 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
| 349 | "alarm read", t->time.tm_sec, t->time.tm_min, | ||
| 350 | t->time.tm_hour, t->time.tm_mday, | ||
| 351 | t->enabled, t->pending); | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | static int ds1307_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
| 357 | { | ||
| 358 | struct i2c_client *client = to_i2c_client(dev); | ||
| 359 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
| 360 | unsigned char *buf = ds1307->regs; | ||
| 361 | u8 control, status; | ||
| 362 | int ret; | ||
| 363 | |||
| 364 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
| 365 | return -EINVAL; | ||
| 366 | |||
| 367 | dev_dbg(dev, "%s secs=%d, mins=%d, " | ||
| 368 | "hours=%d, mday=%d, enabled=%d, pending=%d\n", | ||
| 369 | "alarm set", t->time.tm_sec, t->time.tm_min, | ||
| 370 | t->time.tm_hour, t->time.tm_mday, | ||
| 371 | t->enabled, t->pending); | ||
| 372 | |||
| 373 | /* read current status of both alarms and the chip */ | ||
| 374 | ds1307->reg_addr = DS1339_REG_ALARM1_SECS; | ||
| 375 | ds1307->msg[1].flags = I2C_M_RD; | ||
| 376 | ds1307->msg[1].len = 9; | ||
| 377 | |||
| 378 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
| 379 | ds1307->msg, 2); | ||
| 380 | if (ret != 2) { | ||
| 381 | dev_err(dev, "%s error %d\n", "alarm write", ret); | ||
| 382 | return -EIO; | ||
| 383 | } | ||
| 384 | control = ds1307->regs[7]; | ||
| 385 | status = ds1307->regs[8]; | ||
| 386 | |||
| 387 | dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x\n", | ||
| 388 | "alarm set (old status)", | ||
| 389 | ds1307->regs[0], ds1307->regs[1], | ||
| 390 | ds1307->regs[2], ds1307->regs[3], | ||
| 391 | ds1307->regs[4], ds1307->regs[5], | ||
| 392 | ds1307->regs[6], control, status); | ||
| 393 | |||
| 394 | /* set ALARM1, using 24 hour and day-of-month modes */ | ||
| 395 | *buf++ = DS1339_REG_ALARM1_SECS; /* first register addr */ | ||
| 396 | buf[0] = bin2bcd(t->time.tm_sec); | ||
| 397 | buf[1] = bin2bcd(t->time.tm_min); | ||
| 398 | buf[2] = bin2bcd(t->time.tm_hour); | ||
| 399 | buf[3] = bin2bcd(t->time.tm_mday); | ||
| 400 | |||
| 401 | /* set ALARM2 to non-garbage */ | ||
| 402 | buf[4] = 0; | ||
| 403 | buf[5] = 0; | ||
| 404 | buf[6] = 0; | ||
| 405 | |||
| 406 | /* optionally enable ALARM1 */ | ||
| 407 | buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE); | ||
| 408 | if (t->enabled) { | ||
| 409 | dev_dbg(dev, "alarm IRQ armed\n"); | ||
| 410 | buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */ | ||
| 411 | } | ||
| 412 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | ||
| 413 | |||
| 414 | ds1307->msg[1].flags = 0; | ||
| 415 | ds1307->msg[1].len = 10; | ||
| 416 | |||
| 417 | ret = i2c_transfer(to_i2c_adapter(client->dev.parent), | ||
| 418 | &ds1307->msg[1], 1); | ||
| 419 | if (ret != 1) { | ||
| 420 | dev_err(dev, "can't set alarm time\n"); | ||
| 421 | return -EIO; | ||
| 422 | } | ||
| 423 | |||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | |||
| 427 | static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
| 428 | { | ||
| 429 | struct i2c_client *client = to_i2c_client(dev); | ||
| 430 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | ||
| 431 | int ret; | ||
| 432 | |||
| 433 | switch (cmd) { | ||
| 434 | case RTC_AIE_OFF: | ||
| 435 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
| 436 | return -ENOTTY; | ||
| 437 | |||
| 438 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
| 439 | if (ret < 0) | ||
| 440 | return ret; | ||
| 441 | |||
| 442 | ret &= ~DS1337_BIT_A1IE; | ||
| 443 | |||
| 444 | ret = i2c_smbus_write_byte_data(client, | ||
| 445 | DS1337_REG_CONTROL, ret); | ||
| 446 | if (ret < 0) | ||
| 447 | return ret; | ||
| 448 | |||
| 449 | break; | ||
| 450 | |||
| 451 | case RTC_AIE_ON: | ||
| 452 | if (!test_bit(HAS_ALARM, &ds1307->flags)) | ||
| 453 | return -ENOTTY; | ||
| 454 | |||
| 455 | ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); | ||
| 456 | if (ret < 0) | ||
| 457 | return ret; | ||
| 458 | |||
| 459 | ret |= DS1337_BIT_A1IE; | ||
| 460 | |||
| 461 | ret = i2c_smbus_write_byte_data(client, | ||
| 462 | DS1337_REG_CONTROL, ret); | ||
| 463 | if (ret < 0) | ||
| 464 | return ret; | ||
| 465 | |||
| 466 | break; | ||
| 467 | |||
| 468 | default: | ||
| 469 | return -ENOIOCTLCMD; | ||
| 470 | } | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 234 | static const struct rtc_class_ops ds13xx_rtc_ops = { | 475 | static const struct rtc_class_ops ds13xx_rtc_ops = { |
| 235 | .read_time = ds1307_get_time, | 476 | .read_time = ds1307_get_time, |
| 236 | .set_time = ds1307_set_time, | 477 | .set_time = ds1307_set_time, |
| 478 | .read_alarm = ds1307_read_alarm, | ||
| 479 | .set_alarm = ds1307_set_alarm, | ||
| 480 | .ioctl = ds1307_ioctl, | ||
| 237 | }; | 481 | }; |
| 238 | 482 | ||
| 239 | /*----------------------------------------------------------------------*/ | 483 | /*----------------------------------------------------------------------*/ |
| @@ -327,6 +571,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
| 327 | int tmp; | 571 | int tmp; |
| 328 | const struct chip_desc *chip = &chips[id->driver_data]; | 572 | const struct chip_desc *chip = &chips[id->driver_data]; |
| 329 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 573 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
| 574 | int want_irq = false; | ||
| 330 | 575 | ||
| 331 | if (!i2c_check_functionality(adapter, | 576 | if (!i2c_check_functionality(adapter, |
| 332 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 577 | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
| @@ -353,6 +598,12 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
| 353 | switch (ds1307->type) { | 598 | switch (ds1307->type) { |
| 354 | case ds_1337: | 599 | case ds_1337: |
| 355 | case ds_1339: | 600 | case ds_1339: |
| 601 | /* has IRQ? */ | ||
| 602 | if (ds1307->client->irq > 0 && chip->alarm) { | ||
| 603 | INIT_WORK(&ds1307->work, ds1307_work); | ||
| 604 | want_irq = true; | ||
| 605 | } | ||
| 606 | |||
| 356 | ds1307->reg_addr = DS1337_REG_CONTROL; | 607 | ds1307->reg_addr = DS1337_REG_CONTROL; |
| 357 | ds1307->msg[1].len = 2; | 608 | ds1307->msg[1].len = 2; |
| 358 | 609 | ||
| @@ -369,8 +620,20 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
| 369 | 620 | ||
| 370 | /* oscillator off? turn it on, so clock can tick. */ | 621 | /* oscillator off? turn it on, so clock can tick. */ |
| 371 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) | 622 | if (ds1307->regs[0] & DS1337_BIT_nEOSC) |
| 372 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | 623 | ds1307->regs[0] &= ~DS1337_BIT_nEOSC; |
| 373 | ds1307->regs[0] & ~DS1337_BIT_nEOSC); | 624 | |
| 625 | /* Using IRQ? Disable the square wave and both alarms. | ||
| 626 | * For ds1339, be sure alarms can trigger when we're | ||
| 627 | * running on Vbackup (BBSQI); we assume ds1337 will | ||
| 628 | * ignore that bit | ||
| 629 | */ | ||
| 630 | if (want_irq) { | ||
| 631 | ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI; | ||
| 632 | ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); | ||
| 633 | } | ||
| 634 | |||
| 635 | i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, | ||
| 636 | ds1307->regs[0]); | ||
| 374 | 637 | ||
| 375 | /* oscillator fault? clear flag, and warn */ | 638 | /* oscillator fault? clear flag, and warn */ |
| 376 | if (ds1307->regs[1] & DS1337_BIT_OSF) { | 639 | if (ds1307->regs[1] & DS1337_BIT_OSF) { |
| @@ -495,10 +758,22 @@ read_rtc: | |||
| 495 | goto exit_free; | 758 | goto exit_free; |
| 496 | } | 759 | } |
| 497 | 760 | ||
| 761 | if (want_irq) { | ||
| 762 | err = request_irq(client->irq, ds1307_irq, 0, | ||
| 763 | ds1307->rtc->name, client); | ||
| 764 | if (err) { | ||
| 765 | dev_err(&client->dev, | ||
| 766 | "unable to request IRQ!\n"); | ||
| 767 | goto exit_irq; | ||
| 768 | } | ||
| 769 | set_bit(HAS_ALARM, &ds1307->flags); | ||
| 770 | dev_dbg(&client->dev, "got IRQ %d\n", client->irq); | ||
| 771 | } | ||
| 772 | |||
| 498 | if (chip->nvram56) { | 773 | if (chip->nvram56) { |
| 499 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); | 774 | err = sysfs_create_bin_file(&client->dev.kobj, &nvram); |
| 500 | if (err == 0) { | 775 | if (err == 0) { |
| 501 | ds1307->has_nvram = true; | 776 | set_bit(HAS_NVRAM, &ds1307->flags); |
| 502 | dev_info(&client->dev, "56 bytes nvram\n"); | 777 | dev_info(&client->dev, "56 bytes nvram\n"); |
| 503 | } | 778 | } |
| 504 | } | 779 | } |
| @@ -512,7 +787,9 @@ exit_bad: | |||
| 512 | ds1307->regs[2], ds1307->regs[3], | 787 | ds1307->regs[2], ds1307->regs[3], |
| 513 | ds1307->regs[4], ds1307->regs[5], | 788 | ds1307->regs[4], ds1307->regs[5], |
| 514 | ds1307->regs[6]); | 789 | ds1307->regs[6]); |
| 515 | 790 | exit_irq: | |
| 791 | if (ds1307->rtc) | ||
| 792 | rtc_device_unregister(ds1307->rtc); | ||
| 516 | exit_free: | 793 | exit_free: |
| 517 | kfree(ds1307); | 794 | kfree(ds1307); |
| 518 | return err; | 795 | return err; |
| @@ -520,9 +797,14 @@ exit_free: | |||
| 520 | 797 | ||
| 521 | static int __devexit ds1307_remove(struct i2c_client *client) | 798 | static int __devexit ds1307_remove(struct i2c_client *client) |
| 522 | { | 799 | { |
| 523 | struct ds1307 *ds1307 = i2c_get_clientdata(client); | 800 | struct ds1307 *ds1307 = i2c_get_clientdata(client); |
| 801 | |||
| 802 | if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) { | ||
| 803 | free_irq(client->irq, client); | ||
| 804 | cancel_work_sync(&ds1307->work); | ||
| 805 | } | ||
| 524 | 806 | ||
| 525 | if (ds1307->has_nvram) | 807 | if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags)) |
| 526 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); | 808 | sysfs_remove_bin_file(&client->dev.kobj, &nvram); |
| 527 | 809 | ||
| 528 | rtc_device_unregister(ds1307->rtc); | 810 | rtc_device_unregister(ds1307->rtc); |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index a150418fba76..a5b0fc09f0c6 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
| @@ -429,12 +429,33 @@ static int __devexit ds1374_remove(struct i2c_client *client) | |||
| 429 | return 0; | 429 | return 0; |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | #ifdef CONFIG_PM | ||
| 433 | static int ds1374_suspend(struct i2c_client *client, pm_message_t state) | ||
| 434 | { | ||
| 435 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
| 436 | enable_irq_wake(client->irq); | ||
| 437 | return 0; | ||
| 438 | } | ||
| 439 | |||
| 440 | static int ds1374_resume(struct i2c_client *client) | ||
| 441 | { | ||
| 442 | if (client->irq >= 0 && device_may_wakeup(&client->dev)) | ||
| 443 | disable_irq_wake(client->irq); | ||
| 444 | return 0; | ||
| 445 | } | ||
| 446 | #else | ||
| 447 | #define ds1374_suspend NULL | ||
| 448 | #define ds1374_resume NULL | ||
| 449 | #endif | ||
| 450 | |||
| 432 | static struct i2c_driver ds1374_driver = { | 451 | static struct i2c_driver ds1374_driver = { |
| 433 | .driver = { | 452 | .driver = { |
| 434 | .name = "rtc-ds1374", | 453 | .name = "rtc-ds1374", |
| 435 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
| 436 | }, | 455 | }, |
| 437 | .probe = ds1374_probe, | 456 | .probe = ds1374_probe, |
| 457 | .suspend = ds1374_suspend, | ||
| 458 | .resume = ds1374_resume, | ||
| 438 | .remove = __devexit_p(ds1374_remove), | 459 | .remove = __devexit_p(ds1374_remove), |
| 439 | .id_table = ds1374_id, | 460 | .id_table = ds1374_id, |
| 440 | }; | 461 | }; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 0f0d27d1c4ca..86981d34fbb6 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
| @@ -379,18 +379,6 @@ ds1511_interrupt(int irq, void *dev_id) | |||
| 379 | return IRQ_HANDLED; | 379 | return IRQ_HANDLED; |
| 380 | } | 380 | } |
| 381 | 381 | ||
| 382 | static void | ||
| 383 | ds1511_rtc_release(struct device *dev) | ||
| 384 | { | ||
| 385 | struct platform_device *pdev = to_platform_device(dev); | ||
| 386 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 387 | |||
| 388 | if (pdata->irq >= 0) { | ||
| 389 | pdata->irqen = 0; | ||
| 390 | ds1511_rtc_update_alarm(pdata); | ||
| 391 | } | ||
| 392 | } | ||
| 393 | |||
| 394 | static int | 382 | static int |
| 395 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 383 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
| 396 | { | 384 | { |
| @@ -428,7 +416,6 @@ static const struct rtc_class_ops ds1511_rtc_ops = { | |||
| 428 | .set_time = ds1511_rtc_set_time, | 416 | .set_time = ds1511_rtc_set_time, |
| 429 | .read_alarm = ds1511_rtc_read_alarm, | 417 | .read_alarm = ds1511_rtc_read_alarm, |
| 430 | .set_alarm = ds1511_rtc_set_alarm, | 418 | .set_alarm = ds1511_rtc_set_alarm, |
| 431 | .release = ds1511_rtc_release, | ||
| 432 | .ioctl = ds1511_rtc_ioctl, | 419 | .ioctl = ds1511_rtc_ioctl, |
| 433 | }; | 420 | }; |
| 434 | 421 | ||
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index a19f11415540..4ef59285b489 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c | |||
| @@ -207,17 +207,6 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id) | |||
| 207 | return IRQ_HANDLED; | 207 | return IRQ_HANDLED; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static void ds1553_rtc_release(struct device *dev) | ||
| 211 | { | ||
| 212 | struct platform_device *pdev = to_platform_device(dev); | ||
| 213 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 214 | |||
| 215 | if (pdata->irq >= 0) { | ||
| 216 | pdata->irqen = 0; | ||
| 217 | ds1553_rtc_update_alarm(pdata); | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, | 210 | static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, |
| 222 | unsigned long arg) | 211 | unsigned long arg) |
| 223 | { | 212 | { |
| @@ -254,7 +243,6 @@ static const struct rtc_class_ops ds1553_rtc_ops = { | |||
| 254 | .set_time = ds1553_rtc_set_time, | 243 | .set_time = ds1553_rtc_set_time, |
| 255 | .read_alarm = ds1553_rtc_read_alarm, | 244 | .read_alarm = ds1553_rtc_read_alarm, |
| 256 | .set_alarm = ds1553_rtc_set_alarm, | 245 | .set_alarm = ds1553_rtc_set_alarm, |
| 257 | .release = ds1553_rtc_release, | ||
| 258 | .ioctl = ds1553_rtc_ioctl, | 246 | .ioctl = ds1553_rtc_ioctl, |
| 259 | }; | 247 | }; |
| 260 | 248 | ||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 6fa4556f5f5c..341d7a5b45a2 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
| @@ -9,17 +9,10 @@ | |||
| 9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/i2c.h> | 12 | #include <linux/i2c.h> |
| 14 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
| 15 | 14 | ||
| 16 | #define DRV_VERSION "0.3" | 15 | #define DRV_VERSION "0.4" |
| 17 | |||
| 18 | /* Addresses to scan: none. This chip cannot be detected. */ | ||
| 19 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 20 | |||
| 21 | /* Insmod parameters */ | ||
| 22 | I2C_CLIENT_INSMOD; | ||
| 23 | 16 | ||
| 24 | /* Registers */ | 17 | /* Registers */ |
| 25 | 18 | ||
| @@ -29,8 +22,7 @@ I2C_CLIENT_INSMOD; | |||
| 29 | 22 | ||
| 30 | #define DS1672_REG_CONTROL_EOSC 0x80 | 23 | #define DS1672_REG_CONTROL_EOSC 0x80 |
| 31 | 24 | ||
| 32 | /* Prototypes */ | 25 | static struct i2c_driver ds1672_driver; |
| 33 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); | ||
| 34 | 26 | ||
| 35 | /* | 27 | /* |
| 36 | * In the routines that deal directly with the ds1672 hardware, we use | 28 | * In the routines that deal directly with the ds1672 hardware, we use |
| @@ -44,8 +36,8 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 44 | unsigned char buf[4]; | 36 | unsigned char buf[4]; |
| 45 | 37 | ||
| 46 | struct i2c_msg msgs[] = { | 38 | struct i2c_msg msgs[] = { |
| 47 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 39 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
| 48 | { client->addr, I2C_M_RD, 4, buf }, /* read date */ | 40 | {client->addr, I2C_M_RD, 4, buf}, /* read date */ |
| 49 | }; | 41 | }; |
| 50 | 42 | ||
| 51 | /* read date registers */ | 43 | /* read date registers */ |
| @@ -80,7 +72,7 @@ static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | |||
| 80 | buf[2] = (secs & 0x0000FF00) >> 8; | 72 | buf[2] = (secs & 0x0000FF00) >> 8; |
| 81 | buf[3] = (secs & 0x00FF0000) >> 16; | 73 | buf[3] = (secs & 0x00FF0000) >> 16; |
| 82 | buf[4] = (secs & 0xFF000000) >> 24; | 74 | buf[4] = (secs & 0xFF000000) >> 24; |
| 83 | buf[5] = 0; /* set control reg to enable counting */ | 75 | buf[5] = 0; /* set control reg to enable counting */ |
| 84 | 76 | ||
| 85 | xfer = i2c_master_send(client, buf, 6); | 77 | xfer = i2c_master_send(client, buf, 6); |
| 86 | if (xfer != 6) { | 78 | if (xfer != 6) { |
| @@ -127,8 +119,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
| 127 | unsigned char addr = DS1672_REG_CONTROL; | 119 | unsigned char addr = DS1672_REG_CONTROL; |
| 128 | 120 | ||
| 129 | struct i2c_msg msgs[] = { | 121 | struct i2c_msg msgs[] = { |
| 130 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | 122 | {client->addr, 0, 1, &addr}, /* setup read ptr */ |
| 131 | { client->addr, I2C_M_RD, 1, status }, /* read control */ | 123 | {client->addr, I2C_M_RD, 1, status}, /* read control */ |
| 132 | }; | 124 | }; |
| 133 | 125 | ||
| 134 | /* read control register */ | 126 | /* read control register */ |
| @@ -141,7 +133,8 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
| 141 | } | 133 | } |
| 142 | 134 | ||
| 143 | /* following are the sysfs callback functions */ | 135 | /* following are the sysfs callback functions */ |
| 144 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf) | 136 | static ssize_t show_control(struct device *dev, struct device_attribute *attr, |
| 137 | char *buf) | ||
| 145 | { | 138 | { |
| 146 | struct i2c_client *client = to_i2c_client(dev); | 139 | struct i2c_client *client = to_i2c_client(dev); |
| 147 | u8 control; | 140 | u8 control; |
| @@ -152,85 +145,46 @@ static ssize_t show_control(struct device *dev, struct device_attribute *attr, c | |||
| 152 | return err; | 145 | return err; |
| 153 | 146 | ||
| 154 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) | 147 | return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) |
| 155 | ? "disabled" : "enabled"); | 148 | ? "disabled" : "enabled"); |
| 156 | } | 149 | } |
| 150 | |||
| 157 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); | 151 | static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); |
| 158 | 152 | ||
| 159 | static const struct rtc_class_ops ds1672_rtc_ops = { | 153 | static const struct rtc_class_ops ds1672_rtc_ops = { |
| 160 | .read_time = ds1672_rtc_read_time, | 154 | .read_time = ds1672_rtc_read_time, |
| 161 | .set_time = ds1672_rtc_set_time, | 155 | .set_time = ds1672_rtc_set_time, |
| 162 | .set_mmss = ds1672_rtc_set_mmss, | 156 | .set_mmss = ds1672_rtc_set_mmss, |
| 163 | }; | 157 | }; |
| 164 | 158 | ||
| 165 | static int ds1672_attach(struct i2c_adapter *adapter) | 159 | static int ds1672_remove(struct i2c_client *client) |
| 166 | { | 160 | { |
| 167 | return i2c_probe(adapter, &addr_data, ds1672_probe); | ||
| 168 | } | ||
| 169 | |||
| 170 | static int ds1672_detach(struct i2c_client *client) | ||
| 171 | { | ||
| 172 | int err; | ||
| 173 | struct rtc_device *rtc = i2c_get_clientdata(client); | 161 | struct rtc_device *rtc = i2c_get_clientdata(client); |
| 174 | 162 | ||
| 175 | if (rtc) | 163 | if (rtc) |
| 176 | rtc_device_unregister(rtc); | 164 | rtc_device_unregister(rtc); |
| 177 | 165 | ||
| 178 | if ((err = i2c_detach_client(client))) | ||
| 179 | return err; | ||
| 180 | |||
| 181 | kfree(client); | ||
| 182 | |||
| 183 | return 0; | 166 | return 0; |
| 184 | } | 167 | } |
| 185 | 168 | ||
| 186 | static struct i2c_driver ds1672_driver = { | 169 | static int ds1672_probe(struct i2c_client *client, |
| 187 | .driver = { | 170 | const struct i2c_device_id *id) |
| 188 | .name = "ds1672", | ||
| 189 | }, | ||
| 190 | .id = I2C_DRIVERID_DS1672, | ||
| 191 | .attach_adapter = &ds1672_attach, | ||
| 192 | .detach_client = &ds1672_detach, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | ||
| 196 | { | 171 | { |
| 197 | int err = 0; | 172 | int err = 0; |
| 198 | u8 control; | 173 | u8 control; |
| 199 | struct i2c_client *client; | ||
| 200 | struct rtc_device *rtc; | 174 | struct rtc_device *rtc; |
| 201 | 175 | ||
| 202 | dev_dbg(&adapter->dev, "%s\n", __func__); | 176 | dev_dbg(&client->dev, "%s\n", __func__); |
| 203 | 177 | ||
| 204 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | 178 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| 205 | err = -ENODEV; | 179 | return -ENODEV; |
| 206 | goto exit; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
| 210 | err = -ENOMEM; | ||
| 211 | goto exit; | ||
| 212 | } | ||
| 213 | |||
| 214 | /* I2C client */ | ||
| 215 | client->addr = address; | ||
| 216 | client->driver = &ds1672_driver; | ||
| 217 | client->adapter = adapter; | ||
| 218 | |||
| 219 | strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); | ||
| 220 | |||
| 221 | /* Inform the i2c layer */ | ||
| 222 | if ((err = i2c_attach_client(client))) | ||
| 223 | goto exit_kfree; | ||
| 224 | 180 | ||
| 225 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 181 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 226 | 182 | ||
| 227 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, | 183 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, |
| 228 | &ds1672_rtc_ops, THIS_MODULE); | 184 | &ds1672_rtc_ops, THIS_MODULE); |
| 229 | 185 | ||
| 230 | if (IS_ERR(rtc)) { | 186 | if (IS_ERR(rtc)) |
| 231 | err = PTR_ERR(rtc); | 187 | return PTR_ERR(rtc); |
| 232 | goto exit_detach; | ||
| 233 | } | ||
| 234 | 188 | ||
| 235 | i2c_set_clientdata(client, rtc); | 189 | i2c_set_clientdata(client, rtc); |
| 236 | 190 | ||
| @@ -241,7 +195,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
| 241 | 195 | ||
| 242 | if (control & DS1672_REG_CONTROL_EOSC) | 196 | if (control & DS1672_REG_CONTROL_EOSC) |
| 243 | dev_warn(&client->dev, "Oscillator not enabled. " | 197 | dev_warn(&client->dev, "Oscillator not enabled. " |
| 244 | "Set time to enable.\n"); | 198 | "Set time to enable.\n"); |
| 245 | 199 | ||
| 246 | /* Register sysfs hooks */ | 200 | /* Register sysfs hooks */ |
| 247 | err = device_create_file(&client->dev, &dev_attr_control); | 201 | err = device_create_file(&client->dev, &dev_attr_control); |
| @@ -250,19 +204,19 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | |||
| 250 | 204 | ||
| 251 | return 0; | 205 | return 0; |
| 252 | 206 | ||
| 253 | exit_devreg: | 207 | exit_devreg: |
| 254 | rtc_device_unregister(rtc); | 208 | rtc_device_unregister(rtc); |
| 255 | |||
| 256 | exit_detach: | ||
| 257 | i2c_detach_client(client); | ||
| 258 | |||
| 259 | exit_kfree: | ||
| 260 | kfree(client); | ||
| 261 | |||
| 262 | exit: | ||
| 263 | return err; | 209 | return err; |
| 264 | } | 210 | } |
| 265 | 211 | ||
| 212 | static struct i2c_driver ds1672_driver = { | ||
| 213 | .driver = { | ||
| 214 | .name = "rtc-ds1672", | ||
| 215 | }, | ||
| 216 | .probe = &ds1672_probe, | ||
| 217 | .remove = &ds1672_remove, | ||
| 218 | }; | ||
| 219 | |||
| 266 | static int __init ds1672_init(void) | 220 | static int __init ds1672_init(void) |
| 267 | { | 221 | { |
| 268 | return i2c_add_driver(&ds1672_driver); | 222 | return i2c_add_driver(&ds1672_driver); |
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c new file mode 100644 index 000000000000..37d131d03f33 --- /dev/null +++ b/drivers/rtc/rtc-ds3234.c | |||
| @@ -0,0 +1,290 @@ | |||
| 1 | /* drivers/rtc/rtc-ds3234.c | ||
| 2 | * | ||
| 3 | * Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal | ||
| 4 | * and SRAM. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008 MIMOMax Wireless Ltd. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * Changelog: | ||
| 13 | * | ||
| 14 | * 07-May-2008: Dennis Aberilla <denzzzhome@yahoo.com> | ||
| 15 | * - Created based on the max6902 code. Only implements the | ||
| 16 | * date/time keeping functions; no SRAM yet. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/device.h> | ||
| 20 | #include <linux/platform_device.h> | ||
| 21 | #include <linux/rtc.h> | ||
| 22 | #include <linux/spi/spi.h> | ||
| 23 | #include <linux/bcd.h> | ||
| 24 | |||
| 25 | #define DS3234_REG_SECONDS 0x00 | ||
| 26 | #define DS3234_REG_MINUTES 0x01 | ||
| 27 | #define DS3234_REG_HOURS 0x02 | ||
| 28 | #define DS3234_REG_DAY 0x03 | ||
| 29 | #define DS3234_REG_DATE 0x04 | ||
| 30 | #define DS3234_REG_MONTH 0x05 | ||
| 31 | #define DS3234_REG_YEAR 0x06 | ||
| 32 | #define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */ | ||
| 33 | |||
| 34 | #define DS3234_REG_CONTROL 0x0E | ||
| 35 | #define DS3234_REG_CONT_STAT 0x0F | ||
| 36 | |||
| 37 | #undef DS3234_DEBUG | ||
| 38 | |||
| 39 | struct ds3234 { | ||
| 40 | struct rtc_device *rtc; | ||
| 41 | u8 buf[8]; /* Burst read: addr + 7 regs */ | ||
| 42 | u8 tx_buf[2]; | ||
| 43 | u8 rx_buf[2]; | ||
| 44 | }; | ||
| 45 | |||
| 46 | static void ds3234_set_reg(struct device *dev, unsigned char address, | ||
| 47 | unsigned char data) | ||
| 48 | { | ||
| 49 | struct spi_device *spi = to_spi_device(dev); | ||
| 50 | unsigned char buf[2]; | ||
| 51 | |||
| 52 | /* MSB must be '1' to indicate write */ | ||
| 53 | buf[0] = address | 0x80; | ||
| 54 | buf[1] = data; | ||
| 55 | |||
| 56 | spi_write(spi, buf, 2); | ||
| 57 | } | ||
| 58 | |||
| 59 | static int ds3234_get_reg(struct device *dev, unsigned char address, | ||
| 60 | unsigned char *data) | ||
| 61 | { | ||
| 62 | struct spi_device *spi = to_spi_device(dev); | ||
| 63 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
| 64 | struct spi_message message; | ||
| 65 | struct spi_transfer xfer; | ||
| 66 | int status; | ||
| 67 | |||
| 68 | if (!data) | ||
| 69 | return -EINVAL; | ||
| 70 | |||
| 71 | /* Build our spi message */ | ||
| 72 | spi_message_init(&message); | ||
| 73 | memset(&xfer, 0, sizeof(xfer)); | ||
| 74 | |||
| 75 | /* Address + dummy tx byte */ | ||
| 76 | xfer.len = 2; | ||
| 77 | xfer.tx_buf = chip->tx_buf; | ||
| 78 | xfer.rx_buf = chip->rx_buf; | ||
| 79 | |||
| 80 | chip->tx_buf[0] = address; | ||
| 81 | chip->tx_buf[1] = 0xff; | ||
| 82 | |||
| 83 | spi_message_add_tail(&xfer, &message); | ||
| 84 | |||
| 85 | /* do the i/o */ | ||
| 86 | status = spi_sync(spi, &message); | ||
| 87 | if (status == 0) | ||
| 88 | status = message.status; | ||
| 89 | else | ||
| 90 | return status; | ||
| 91 | |||
| 92 | *data = chip->rx_buf[1]; | ||
| 93 | |||
| 94 | return status; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int ds3234_get_datetime(struct device *dev, struct rtc_time *dt) | ||
| 98 | { | ||
| 99 | struct spi_device *spi = to_spi_device(dev); | ||
| 100 | struct ds3234 *chip = dev_get_drvdata(dev); | ||
| 101 | struct spi_message message; | ||
| 102 | struct spi_transfer xfer; | ||
| 103 | int status; | ||
| 104 | |||
| 105 | /* build the message */ | ||
| 106 | spi_message_init(&message); | ||
| 107 | memset(&xfer, 0, sizeof(xfer)); | ||
| 108 | xfer.len = 1 + 7; /* Addr + 7 registers */ | ||
| 109 | xfer.tx_buf = chip->buf; | ||
| 110 | xfer.rx_buf = chip->buf; | ||
| 111 | chip->buf[0] = 0x00; /* Start address */ | ||
| 112 | spi_message_add_tail(&xfer, &message); | ||
| 113 | |||
| 114 | /* do the i/o */ | ||
| 115 | status = spi_sync(spi, &message); | ||
| 116 | if (status == 0) | ||
| 117 | status = message.status; | ||
| 118 | else | ||
| 119 | return status; | ||
| 120 | |||
| 121 | /* Seconds, Minutes, Hours, Day, Date, Month, Year */ | ||
| 122 | dt->tm_sec = bcd2bin(chip->buf[1]); | ||
| 123 | dt->tm_min = bcd2bin(chip->buf[2]); | ||
| 124 | dt->tm_hour = bcd2bin(chip->buf[3] & 0x3f); | ||
| 125 | dt->tm_wday = bcd2bin(chip->buf[4]) - 1; /* 0 = Sun */ | ||
| 126 | dt->tm_mday = bcd2bin(chip->buf[5]); | ||
| 127 | dt->tm_mon = bcd2bin(chip->buf[6] & 0x1f) - 1; /* 0 = Jan */ | ||
| 128 | dt->tm_year = bcd2bin(chip->buf[7] & 0xff) + 100; /* Assume 20YY */ | ||
| 129 | |||
| 130 | #ifdef DS3234_DEBUG | ||
| 131 | dev_dbg(dev, "\n%s : Read RTC values\n", __func__); | ||
| 132 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
| 133 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
| 134 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
| 135 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
| 136 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
| 137 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
| 138 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
| 139 | #endif | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static int ds3234_set_datetime(struct device *dev, struct rtc_time *dt) | ||
| 145 | { | ||
| 146 | #ifdef DS3234_DEBUG | ||
| 147 | dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); | ||
| 148 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); | ||
| 149 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); | ||
| 150 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); | ||
| 151 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); | ||
| 152 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); | ||
| 153 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); | ||
| 154 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); | ||
| 155 | #endif | ||
| 156 | |||
| 157 | ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec)); | ||
| 158 | ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min)); | ||
| 159 | ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f); | ||
| 160 | |||
| 161 | /* 0 = Sun */ | ||
| 162 | ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1)); | ||
| 163 | ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday)); | ||
| 164 | |||
| 165 | /* 0 = Jan */ | ||
| 166 | ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1)); | ||
| 167 | |||
| 168 | /* Assume 20YY although we just want to make sure not to go negative. */ | ||
| 169 | if (dt->tm_year > 100) | ||
| 170 | dt->tm_year -= 100; | ||
| 171 | |||
| 172 | ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year)); | ||
| 173 | |||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | static int ds3234_read_time(struct device *dev, struct rtc_time *tm) | ||
| 178 | { | ||
| 179 | return ds3234_get_datetime(dev, tm); | ||
| 180 | } | ||
| 181 | |||
| 182 | static int ds3234_set_time(struct device *dev, struct rtc_time *tm) | ||
| 183 | { | ||
| 184 | return ds3234_set_datetime(dev, tm); | ||
| 185 | } | ||
| 186 | |||
| 187 | static const struct rtc_class_ops ds3234_rtc_ops = { | ||
| 188 | .read_time = ds3234_read_time, | ||
| 189 | .set_time = ds3234_set_time, | ||
| 190 | }; | ||
| 191 | |||
| 192 | static int ds3234_probe(struct spi_device *spi) | ||
| 193 | { | ||
| 194 | struct rtc_device *rtc; | ||
| 195 | unsigned char tmp; | ||
| 196 | struct ds3234 *chip; | ||
| 197 | int res; | ||
| 198 | |||
| 199 | rtc = rtc_device_register("ds3234", | ||
| 200 | &spi->dev, &ds3234_rtc_ops, THIS_MODULE); | ||
| 201 | if (IS_ERR(rtc)) | ||
| 202 | return PTR_ERR(rtc); | ||
| 203 | |||
| 204 | spi->mode = SPI_MODE_3; | ||
| 205 | spi->bits_per_word = 8; | ||
| 206 | spi_setup(spi); | ||
| 207 | |||
| 208 | chip = kzalloc(sizeof(struct ds3234), GFP_KERNEL); | ||
| 209 | if (!chip) { | ||
| 210 | rtc_device_unregister(rtc); | ||
| 211 | return -ENOMEM; | ||
| 212 | } | ||
| 213 | chip->rtc = rtc; | ||
| 214 | dev_set_drvdata(&spi->dev, chip); | ||
| 215 | |||
| 216 | res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp); | ||
| 217 | if (res) { | ||
| 218 | rtc_device_unregister(rtc); | ||
| 219 | return res; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* Control settings | ||
| 223 | * | ||
| 224 | * CONTROL_REG | ||
| 225 | * BIT 7 6 5 4 3 2 1 0 | ||
| 226 | * EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE | ||
| 227 | * | ||
| 228 | * 0 0 0 1 1 1 0 0 | ||
| 229 | * | ||
| 230 | * CONTROL_STAT_REG | ||
| 231 | * BIT 7 6 5 4 3 2 1 0 | ||
| 232 | * OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F | ||
| 233 | * | ||
| 234 | * 1 0 0 0 1 0 0 0 | ||
| 235 | */ | ||
| 236 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
| 237 | ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c); | ||
| 238 | |||
| 239 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
| 240 | ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88); | ||
| 241 | |||
| 242 | /* Print our settings */ | ||
| 243 | ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp); | ||
| 244 | dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp); | ||
| 245 | |||
| 246 | ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp); | ||
| 247 | dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp); | ||
| 248 | |||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | static int __exit ds3234_remove(struct spi_device *spi) | ||
| 253 | { | ||
| 254 | struct ds3234 *chip = platform_get_drvdata(spi); | ||
| 255 | struct rtc_device *rtc = chip->rtc; | ||
| 256 | |||
| 257 | if (rtc) | ||
| 258 | rtc_device_unregister(rtc); | ||
| 259 | |||
| 260 | kfree(chip); | ||
| 261 | |||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | static struct spi_driver ds3234_driver = { | ||
| 266 | .driver = { | ||
| 267 | .name = "ds3234", | ||
| 268 | .bus = &spi_bus_type, | ||
| 269 | .owner = THIS_MODULE, | ||
| 270 | }, | ||
| 271 | .probe = ds3234_probe, | ||
| 272 | .remove = __devexit_p(ds3234_remove), | ||
| 273 | }; | ||
| 274 | |||
| 275 | static __init int ds3234_init(void) | ||
| 276 | { | ||
| 277 | printk(KERN_INFO "DS3234 SPI RTC Driver\n"); | ||
| 278 | return spi_register_driver(&ds3234_driver); | ||
| 279 | } | ||
| 280 | module_init(ds3234_init); | ||
| 281 | |||
| 282 | static __exit void ds3234_exit(void) | ||
| 283 | { | ||
| 284 | spi_unregister_driver(&ds3234_driver); | ||
| 285 | } | ||
| 286 | module_exit(ds3234_exit); | ||
| 287 | |||
| 288 | MODULE_DESCRIPTION("DS3234 SPI RTC driver"); | ||
| 289 | MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>"); | ||
| 290 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 24bc1689fc74..470fb2d29545 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
| @@ -56,21 +56,27 @@ | |||
| 56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ | 56 | #define M41T80_ALHOUR_HT (1 << 6) /* HT: Halt Update Bit */ |
| 57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ | 57 | #define M41T80_FLAGS_AF (1 << 6) /* AF: Alarm Flag Bit */ |
| 58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ | 58 | #define M41T80_FLAGS_BATT_LOW (1 << 4) /* BL: Battery Low Bit */ |
| 59 | #define M41T80_WATCHDOG_RB2 (1 << 7) /* RB: Watchdog resolution */ | ||
| 60 | #define M41T80_WATCHDOG_RB1 (1 << 1) /* RB: Watchdog resolution */ | ||
| 61 | #define M41T80_WATCHDOG_RB0 (1 << 0) /* RB: Watchdog resolution */ | ||
| 59 | 62 | ||
| 60 | #define M41T80_FEATURE_HT (1 << 0) | 63 | #define M41T80_FEATURE_HT (1 << 0) /* Halt feature */ |
| 61 | #define M41T80_FEATURE_BL (1 << 1) | 64 | #define M41T80_FEATURE_BL (1 << 1) /* Battery low indicator */ |
| 65 | #define M41T80_FEATURE_SQ (1 << 2) /* Squarewave feature */ | ||
| 66 | #define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */ | ||
| 62 | 67 | ||
| 63 | #define DRV_VERSION "0.05" | 68 | #define DRV_VERSION "0.05" |
| 64 | 69 | ||
| 65 | static const struct i2c_device_id m41t80_id[] = { | 70 | static const struct i2c_device_id m41t80_id[] = { |
| 66 | { "m41t80", 0 }, | 71 | { "m41t65", M41T80_FEATURE_HT | M41T80_FEATURE_WD }, |
| 67 | { "m41t81", M41T80_FEATURE_HT }, | 72 | { "m41t80", M41T80_FEATURE_SQ }, |
| 68 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 73 | { "m41t81", M41T80_FEATURE_HT | M41T80_FEATURE_SQ}, |
| 69 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 74 | { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 70 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 75 | { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 71 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 76 | { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 72 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 77 | { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 73 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL }, | 78 | { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, |
| 79 | { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ }, | ||
| 74 | { } | 80 | { } |
| 75 | }; | 81 | }; |
| 76 | MODULE_DEVICE_TABLE(i2c, m41t80_id); | 82 | MODULE_DEVICE_TABLE(i2c, m41t80_id); |
| @@ -386,8 +392,12 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev, | |||
| 386 | struct device_attribute *attr, char *buf) | 392 | struct device_attribute *attr, char *buf) |
| 387 | { | 393 | { |
| 388 | struct i2c_client *client = to_i2c_client(dev); | 394 | struct i2c_client *client = to_i2c_client(dev); |
| 395 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
| 389 | int val; | 396 | int val; |
| 390 | 397 | ||
| 398 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
| 399 | return -EINVAL; | ||
| 400 | |||
| 391 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); | 401 | val = i2c_smbus_read_byte_data(client, M41T80_REG_SQW); |
| 392 | if (val < 0) | 402 | if (val < 0) |
| 393 | return -EIO; | 403 | return -EIO; |
| @@ -408,9 +418,13 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev, | |||
| 408 | const char *buf, size_t count) | 418 | const char *buf, size_t count) |
| 409 | { | 419 | { |
| 410 | struct i2c_client *client = to_i2c_client(dev); | 420 | struct i2c_client *client = to_i2c_client(dev); |
| 421 | struct m41t80_data *clientdata = i2c_get_clientdata(client); | ||
| 411 | int almon, sqw; | 422 | int almon, sqw; |
| 412 | int val = simple_strtoul(buf, NULL, 0); | 423 | int val = simple_strtoul(buf, NULL, 0); |
| 413 | 424 | ||
| 425 | if (!(clientdata->features & M41T80_FEATURE_SQ)) | ||
| 426 | return -EINVAL; | ||
| 427 | |||
| 414 | if (val) { | 428 | if (val) { |
| 415 | if (!is_power_of_2(val)) | 429 | if (!is_power_of_2(val)) |
| 416 | return -EINVAL; | 430 | return -EINVAL; |
| @@ -499,6 +513,8 @@ static void wdt_ping(void) | |||
| 499 | .buf = i2c_data, | 513 | .buf = i2c_data, |
| 500 | }, | 514 | }, |
| 501 | }; | 515 | }; |
| 516 | struct m41t80_data *clientdata = i2c_get_clientdata(save_client); | ||
| 517 | |||
| 502 | i2c_data[0] = 0x09; /* watchdog register */ | 518 | i2c_data[0] = 0x09; /* watchdog register */ |
| 503 | 519 | ||
| 504 | if (wdt_margin > 31) | 520 | if (wdt_margin > 31) |
| @@ -509,6 +525,13 @@ static void wdt_ping(void) | |||
| 509 | */ | 525 | */ |
| 510 | i2c_data[1] = wdt_margin<<2 | 0x82; | 526 | i2c_data[1] = wdt_margin<<2 | 0x82; |
| 511 | 527 | ||
| 528 | /* | ||
| 529 | * M41T65 has three bits for watchdog resolution. Don't set bit 7, as | ||
| 530 | * that would be an invalid resolution. | ||
| 531 | */ | ||
| 532 | if (clientdata->features & M41T80_FEATURE_WD) | ||
| 533 | i2c_data[1] &= ~M41T80_WATCHDOG_RB2; | ||
| 534 | |||
| 512 | i2c_transfer(save_client->adapter, msgs1, 1); | 535 | i2c_transfer(save_client->adapter, msgs1, 1); |
| 513 | } | 536 | } |
| 514 | 537 | ||
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c new file mode 100644 index 000000000000..0b2197559940 --- /dev/null +++ b/drivers/rtc/rtc-m48t35.c | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip | ||
| 3 | * | ||
| 4 | * Copyright (C) 2000 Silicon Graphics, Inc. | ||
| 5 | * Written by Ulf Carlsson (ulfc@engr.sgi.com) | ||
| 6 | * | ||
| 7 | * Copyright (C) 2008 Thomas Bogendoerfer | ||
| 8 | * | ||
| 9 | * Based on code written by Paul Gortmaker. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the | ||
| 13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 14 | * option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/rtc.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/bcd.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | |||
| 23 | #define DRV_VERSION "1.0" | ||
| 24 | |||
| 25 | struct m48t35_rtc { | ||
| 26 | u8 pad[0x7ff8]; /* starts at 0x7ff8 */ | ||
| 27 | u8 control; | ||
| 28 | u8 sec; | ||
| 29 | u8 min; | ||
| 30 | u8 hour; | ||
| 31 | u8 day; | ||
| 32 | u8 date; | ||
| 33 | u8 month; | ||
| 34 | u8 year; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #define M48T35_RTC_SET 0x80 | ||
| 38 | #define M48T35_RTC_READ 0x40 | ||
| 39 | |||
| 40 | struct m48t35_priv { | ||
| 41 | struct rtc_device *rtc; | ||
| 42 | struct m48t35_rtc __iomem *reg; | ||
| 43 | size_t size; | ||
| 44 | unsigned long baseaddr; | ||
| 45 | spinlock_t lock; | ||
| 46 | }; | ||
| 47 | |||
| 48 | static int m48t35_read_time(struct device *dev, struct rtc_time *tm) | ||
| 49 | { | ||
| 50 | struct m48t35_priv *priv = dev_get_drvdata(dev); | ||
| 51 | u8 control; | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Only the values that we read from the RTC are set. We leave | ||
| 55 | * tm_wday, tm_yday and tm_isdst untouched. Even though the | ||
| 56 | * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated | ||
| 57 | * by the RTC when initially set to a non-zero value. | ||
| 58 | */ | ||
| 59 | spin_lock_irq(&priv->lock); | ||
| 60 | control = readb(&priv->reg->control); | ||
| 61 | writeb(control | M48T35_RTC_READ, &priv->reg->control); | ||
| 62 | tm->tm_sec = readb(&priv->reg->sec); | ||
| 63 | tm->tm_min = readb(&priv->reg->min); | ||
| 64 | tm->tm_hour = readb(&priv->reg->hour); | ||
| 65 | tm->tm_mday = readb(&priv->reg->date); | ||
| 66 | tm->tm_mon = readb(&priv->reg->month); | ||
| 67 | tm->tm_year = readb(&priv->reg->year); | ||
| 68 | writeb(control, &priv->reg->control); | ||
| 69 | spin_unlock_irq(&priv->lock); | ||
| 70 | |||
| 71 | tm->tm_sec = bcd2bin(tm->tm_sec); | ||
| 72 | tm->tm_min = bcd2bin(tm->tm_min); | ||
| 73 | tm->tm_hour = bcd2bin(tm->tm_hour); | ||
| 74 | tm->tm_mday = bcd2bin(tm->tm_mday); | ||
| 75 | tm->tm_mon = bcd2bin(tm->tm_mon); | ||
| 76 | tm->tm_year = bcd2bin(tm->tm_year); | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Account for differences between how the RTC uses the values | ||
| 80 | * and how they are defined in a struct rtc_time; | ||
| 81 | */ | ||
| 82 | tm->tm_year += 70; | ||
| 83 | if (tm->tm_year <= 69) | ||
| 84 | tm->tm_year += 100; | ||
| 85 | |||
| 86 | tm->tm_mon--; | ||
| 87 | return rtc_valid_tm(tm); | ||
| 88 | } | ||
| 89 | |||
| 90 | static int m48t35_set_time(struct device *dev, struct rtc_time *tm) | ||
| 91 | { | ||
| 92 | struct m48t35_priv *priv = dev_get_drvdata(dev); | ||
| 93 | unsigned char mon, day, hrs, min, sec; | ||
| 94 | unsigned int yrs; | ||
| 95 | u8 control; | ||
| 96 | |||
| 97 | yrs = tm->tm_year + 1900; | ||
| 98 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
| 99 | day = tm->tm_mday; | ||
| 100 | hrs = tm->tm_hour; | ||
| 101 | min = tm->tm_min; | ||
| 102 | sec = tm->tm_sec; | ||
| 103 | |||
| 104 | if (yrs < 1970) | ||
| 105 | return -EINVAL; | ||
| 106 | |||
| 107 | yrs -= 1970; | ||
| 108 | if (yrs > 255) /* They are unsigned */ | ||
| 109 | return -EINVAL; | ||
| 110 | |||
| 111 | if (yrs > 169) | ||
| 112 | return -EINVAL; | ||
| 113 | |||
| 114 | if (yrs >= 100) | ||
| 115 | yrs -= 100; | ||
| 116 | |||
| 117 | sec = bin2bcd(sec); | ||
| 118 | min = bin2bcd(min); | ||
| 119 | hrs = bin2bcd(hrs); | ||
| 120 | day = bin2bcd(day); | ||
| 121 | mon = bin2bcd(mon); | ||
| 122 | yrs = bin2bcd(yrs); | ||
| 123 | |||
| 124 | spin_lock_irq(&priv->lock); | ||
| 125 | control = readb(&priv->reg->control); | ||
| 126 | writeb(control | M48T35_RTC_SET, &priv->reg->control); | ||
| 127 | writeb(yrs, &priv->reg->year); | ||
| 128 | writeb(mon, &priv->reg->month); | ||
| 129 | writeb(day, &priv->reg->date); | ||
| 130 | writeb(hrs, &priv->reg->hour); | ||
| 131 | writeb(min, &priv->reg->min); | ||
| 132 | writeb(sec, &priv->reg->sec); | ||
| 133 | writeb(control, &priv->reg->control); | ||
| 134 | spin_unlock_irq(&priv->lock); | ||
| 135 | return 0; | ||
| 136 | } | ||
| 137 | |||
| 138 | static const struct rtc_class_ops m48t35_ops = { | ||
| 139 | .read_time = m48t35_read_time, | ||
| 140 | .set_time = m48t35_set_time, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static int __devinit m48t35_probe(struct platform_device *pdev) | ||
| 144 | { | ||
| 145 | struct rtc_device *rtc; | ||
| 146 | struct resource *res; | ||
| 147 | struct m48t35_priv *priv; | ||
| 148 | int ret = 0; | ||
| 149 | |||
| 150 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 151 | if (!res) | ||
| 152 | return -ENODEV; | ||
| 153 | priv = kzalloc(sizeof(struct m48t35_priv), GFP_KERNEL); | ||
| 154 | if (!priv) | ||
| 155 | return -ENOMEM; | ||
| 156 | |||
| 157 | priv->size = res->end - res->start + 1; | ||
| 158 | /* | ||
| 159 | * kludge: remove the #ifndef after ioc3 resource | ||
| 160 | * conflicts are resolved | ||
| 161 | */ | ||
| 162 | #ifndef CONFIG_SGI_IP27 | ||
| 163 | if (!request_mem_region(res->start, priv->size, pdev->name)) { | ||
| 164 | ret = -EBUSY; | ||
| 165 | goto out; | ||
| 166 | } | ||
| 167 | #endif | ||
| 168 | priv->baseaddr = res->start; | ||
| 169 | priv->reg = ioremap(priv->baseaddr, priv->size); | ||
| 170 | if (!priv->reg) { | ||
| 171 | ret = -ENOMEM; | ||
| 172 | goto out; | ||
| 173 | } | ||
| 174 | spin_lock_init(&priv->lock); | ||
| 175 | rtc = rtc_device_register("m48t35", &pdev->dev, | ||
| 176 | &m48t35_ops, THIS_MODULE); | ||
| 177 | if (IS_ERR(rtc)) { | ||
| 178 | ret = PTR_ERR(rtc); | ||
| 179 | goto out; | ||
| 180 | } | ||
| 181 | priv->rtc = rtc; | ||
| 182 | platform_set_drvdata(pdev, priv); | ||
| 183 | return 0; | ||
| 184 | |||
| 185 | out: | ||
| 186 | if (priv->rtc) | ||
| 187 | rtc_device_unregister(priv->rtc); | ||
| 188 | if (priv->reg) | ||
| 189 | iounmap(priv->reg); | ||
| 190 | if (priv->baseaddr) | ||
| 191 | release_mem_region(priv->baseaddr, priv->size); | ||
| 192 | kfree(priv); | ||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int __devexit m48t35_remove(struct platform_device *pdev) | ||
| 197 | { | ||
| 198 | struct m48t35_priv *priv = platform_get_drvdata(pdev); | ||
| 199 | |||
| 200 | rtc_device_unregister(priv->rtc); | ||
| 201 | iounmap(priv->reg); | ||
| 202 | #ifndef CONFIG_SGI_IP27 | ||
| 203 | release_mem_region(priv->baseaddr, priv->size); | ||
| 204 | #endif | ||
| 205 | kfree(priv); | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static struct platform_driver m48t35_platform_driver = { | ||
| 210 | .driver = { | ||
| 211 | .name = "rtc-m48t35", | ||
| 212 | .owner = THIS_MODULE, | ||
| 213 | }, | ||
| 214 | .probe = m48t35_probe, | ||
| 215 | .remove = __devexit_p(m48t35_remove), | ||
| 216 | }; | ||
| 217 | |||
| 218 | static int __init m48t35_init(void) | ||
| 219 | { | ||
| 220 | return platform_driver_register(&m48t35_platform_driver); | ||
| 221 | } | ||
| 222 | |||
| 223 | static void __exit m48t35_exit(void) | ||
| 224 | { | ||
| 225 | platform_driver_unregister(&m48t35_platform_driver); | ||
| 226 | } | ||
| 227 | |||
| 228 | MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>"); | ||
| 229 | MODULE_DESCRIPTION("M48T35 RTC driver"); | ||
| 230 | MODULE_LICENSE("GPL"); | ||
| 231 | MODULE_VERSION(DRV_VERSION); | ||
| 232 | MODULE_ALIAS("platform:rtc-m48t35"); | ||
| 233 | |||
| 234 | module_init(m48t35_init); | ||
| 235 | module_exit(m48t35_exit); | ||
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 013e6c103b9c..ce4eff6a8d51 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
| @@ -24,8 +24,9 @@ | |||
| 24 | #define NO_IRQ (-1) | 24 | #define NO_IRQ (-1) |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | #define M48T59_READ(reg) pdata->read_byte(dev, reg) | 27 | #define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg)) |
| 28 | #define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) | 28 | #define M48T59_WRITE(val, reg) \ |
| 29 | (pdata->write_byte(dev, pdata->offset + reg, val)) | ||
| 29 | 30 | ||
| 30 | #define M48T59_SET_BITS(mask, reg) \ | 31 | #define M48T59_SET_BITS(mask, reg) \ |
| 31 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) | 32 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) |
| @@ -34,7 +35,6 @@ | |||
| 34 | 35 | ||
| 35 | struct m48t59_private { | 36 | struct m48t59_private { |
| 36 | void __iomem *ioaddr; | 37 | void __iomem *ioaddr; |
| 37 | unsigned int size; /* iomem size */ | ||
| 38 | int irq; | 38 | int irq; |
| 39 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
| 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ | 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ |
| @@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
| 82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); | 82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); |
| 83 | 83 | ||
| 84 | val = M48T59_READ(M48T59_WDAY); | 84 | val = M48T59_READ(M48T59_WDAY); |
| 85 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | 85 | if ((pdata->type == M48T59RTC_TYPE_M48T59) && |
| 86 | (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | ||
| 86 | dev_dbg(dev, "Century bit is enabled\n"); | 87 | dev_dbg(dev, "Century bit is enabled\n"); |
| 87 | tm->tm_year += 100; /* one century */ | 88 | tm->tm_year += 100; /* one century */ |
| 88 | } | 89 | } |
| @@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 126 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); | 127 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); |
| 127 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); | 128 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); |
| 128 | 129 | ||
| 129 | if (tm->tm_year/100) | 130 | if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) |
| 130 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); | 131 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); |
| 131 | val |= (BIN2BCD(tm->tm_wday) & 0x07); | 132 | val |= (BIN2BCD(tm->tm_wday) & 0x07); |
| 132 | M48T59_WRITE(val, M48T59_WDAY); | 133 | M48T59_WRITE(val, M48T59_WDAY); |
| @@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = { | |||
| 310 | .proc = m48t59_rtc_proc, | 311 | .proc = m48t59_rtc_proc, |
| 311 | }; | 312 | }; |
| 312 | 313 | ||
| 314 | static const struct rtc_class_ops m48t02_rtc_ops = { | ||
| 315 | .read_time = m48t59_rtc_read_time, | ||
| 316 | .set_time = m48t59_rtc_set_time, | ||
| 317 | }; | ||
| 318 | |||
| 313 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 319 | static ssize_t m48t59_nvram_read(struct kobject *kobj, |
| 314 | struct bin_attribute *bin_attr, | 320 | struct bin_attribute *bin_attr, |
| 315 | char *buf, loff_t pos, size_t size) | 321 | char *buf, loff_t pos, size_t size) |
| @@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
| 321 | ssize_t cnt = 0; | 327 | ssize_t cnt = 0; |
| 322 | unsigned long flags; | 328 | unsigned long flags; |
| 323 | 329 | ||
| 324 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 330 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
| 325 | spin_lock_irqsave(&m48t59->lock, flags); | 331 | spin_lock_irqsave(&m48t59->lock, flags); |
| 326 | *buf++ = M48T59_READ(cnt); | 332 | *buf++ = M48T59_READ(cnt); |
| 327 | spin_unlock_irqrestore(&m48t59->lock, flags); | 333 | spin_unlock_irqrestore(&m48t59->lock, flags); |
| @@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, | |||
| 341 | ssize_t cnt = 0; | 347 | ssize_t cnt = 0; |
| 342 | unsigned long flags; | 348 | unsigned long flags; |
| 343 | 349 | ||
| 344 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 350 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
| 345 | spin_lock_irqsave(&m48t59->lock, flags); | 351 | spin_lock_irqsave(&m48t59->lock, flags); |
| 346 | M48T59_WRITE(*buf++, cnt); | 352 | M48T59_WRITE(*buf++, cnt); |
| 347 | spin_unlock_irqrestore(&m48t59->lock, flags); | 353 | spin_unlock_irqrestore(&m48t59->lock, flags); |
| @@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = { | |||
| 358 | }, | 364 | }, |
| 359 | .read = m48t59_nvram_read, | 365 | .read = m48t59_nvram_read, |
| 360 | .write = m48t59_nvram_write, | 366 | .write = m48t59_nvram_write, |
| 361 | .size = M48T59_NVRAM_SIZE, | ||
| 362 | }; | 367 | }; |
| 363 | 368 | ||
| 364 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | 369 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) |
| @@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 367 | struct m48t59_private *m48t59 = NULL; | 372 | struct m48t59_private *m48t59 = NULL; |
| 368 | struct resource *res; | 373 | struct resource *res; |
| 369 | int ret = -ENOMEM; | 374 | int ret = -ENOMEM; |
| 375 | char *name; | ||
| 376 | const struct rtc_class_ops *ops; | ||
| 370 | 377 | ||
| 371 | /* This chip could be memory-mapped or I/O-mapped */ | 378 | /* This chip could be memory-mapped or I/O-mapped */ |
| 372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 379 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 391 | /* Ensure we only kmalloc platform data once */ | 398 | /* Ensure we only kmalloc platform data once */ |
| 392 | pdev->dev.platform_data = pdata; | 399 | pdev->dev.platform_data = pdata; |
| 393 | } | 400 | } |
| 401 | if (!pdata->type) | ||
| 402 | pdata->type = M48T59RTC_TYPE_M48T59; | ||
| 394 | 403 | ||
| 395 | /* Try to use the generic memory read/write ops */ | 404 | /* Try to use the generic memory read/write ops */ |
| 396 | if (!pdata->write_byte) | 405 | if (!pdata->write_byte) |
| @@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 403 | if (!m48t59) | 412 | if (!m48t59) |
| 404 | return -ENOMEM; | 413 | return -ENOMEM; |
| 405 | 414 | ||
| 406 | m48t59->size = res->end - res->start + 1; | 415 | m48t59->ioaddr = pdata->ioaddr; |
| 407 | m48t59->ioaddr = ioremap(res->start, m48t59->size); | 416 | |
| 408 | if (!m48t59->ioaddr) | 417 | if (!m48t59->ioaddr) { |
| 409 | goto out; | 418 | /* ioaddr not mapped externally */ |
| 419 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | ||
| 420 | if (!m48t59->ioaddr) | ||
| 421 | goto out; | ||
| 422 | } | ||
| 410 | 423 | ||
| 411 | /* Try to get irq number. We also can work in | 424 | /* Try to get irq number. We also can work in |
| 412 | * the mode without IRQ. | 425 | * the mode without IRQ. |
| @@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
| 421 | if (ret) | 434 | if (ret) |
| 422 | goto out; | 435 | goto out; |
| 423 | } | 436 | } |
| 437 | switch (pdata->type) { | ||
| 438 | case M48T59RTC_TYPE_M48T59: | ||
| 439 | name = "m48t59"; | ||
| 440 | ops = &m48t59_rtc_ops; | ||
| 441 | pdata->offset = 0x1ff0; | ||
| 442 | break; | ||
| 443 | case M48T59RTC_TYPE_M48T02: | ||
| 444 | name = "m48t02"; | ||
| 445 | ops = &m48t02_rtc_ops; | ||
| 446 | pdata->offset = 0x7f0; | ||
| 447 | break; | ||
| 448 | case M48T59RTC_TYPE_M48T08: | ||
| 449 | name = "m48t08"; | ||
| 450 | ops = &m48t02_rtc_ops; | ||
| 451 | pdata->offset = 0x1ff0; | ||
| 452 | break; | ||
| 453 | default: | ||
| 454 | dev_err(&pdev->dev, "Unknown RTC type\n"); | ||
| 455 | ret = -ENODEV; | ||
| 456 | goto out; | ||
| 457 | } | ||
| 424 | 458 | ||
| 425 | m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, | 459 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
| 426 | &m48t59_rtc_ops, THIS_MODULE); | ||
| 427 | if (IS_ERR(m48t59->rtc)) { | 460 | if (IS_ERR(m48t59->rtc)) { |
| 428 | ret = PTR_ERR(m48t59->rtc); | 461 | ret = PTR_ERR(m48t59->rtc); |
| 429 | goto out; | 462 | goto out; |
| 430 | } | 463 | } |
| 431 | 464 | ||
| 465 | m48t59_nvram_attr.size = pdata->offset; | ||
| 466 | |||
| 432 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 467 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
| 433 | if (ret) | 468 | if (ret) |
| 434 | goto out; | 469 | goto out; |
| @@ -452,11 +487,12 @@ out: | |||
| 452 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) | 487 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) |
| 453 | { | 488 | { |
| 454 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); | 489 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); |
| 490 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; | ||
| 455 | 491 | ||
| 456 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 492 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
| 457 | if (!IS_ERR(m48t59->rtc)) | 493 | if (!IS_ERR(m48t59->rtc)) |
| 458 | rtc_device_unregister(m48t59->rtc); | 494 | rtc_device_unregister(m48t59->rtc); |
| 459 | if (m48t59->ioaddr) | 495 | if (m48t59->ioaddr && !pdata->ioaddr) |
| 460 | iounmap(m48t59->ioaddr); | 496 | iounmap(m48t59->ioaddr); |
| 461 | if (m48t59->irq != NO_IRQ) | 497 | if (m48t59->irq != NO_IRQ) |
| 462 | free_irq(m48t59->irq, &pdev->dev); | 498 | free_irq(m48t59->irq, &pdev->dev); |
| @@ -491,5 +527,5 @@ module_init(m48t59_rtc_init); | |||
| 491 | module_exit(m48t59_rtc_exit); | 527 | module_exit(m48t59_rtc_exit); |
| 492 | 528 | ||
| 493 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 529 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
| 494 | MODULE_DESCRIPTION("M48T59 RTC driver"); | 530 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
| 495 | MODULE_LICENSE("GPL"); | 531 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-max6900.c b/drivers/rtc/rtc-max6900.c index ded3c0abad83..12c9cd25cad8 100644 --- a/drivers/rtc/rtc-max6900.c +++ b/drivers/rtc/rtc-max6900.c | |||
| @@ -17,19 +17,18 @@ | |||
| 17 | #include <linux/rtc.h> | 17 | #include <linux/rtc.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | 19 | ||
| 20 | #define DRV_NAME "max6900" | 20 | #define DRV_VERSION "0.2" |
| 21 | #define DRV_VERSION "0.1" | ||
| 22 | 21 | ||
| 23 | /* | 22 | /* |
| 24 | * register indices | 23 | * register indices |
| 25 | */ | 24 | */ |
| 26 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ | 25 | #define MAX6900_REG_SC 0 /* seconds 00-59 */ |
| 27 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ | 26 | #define MAX6900_REG_MN 1 /* minutes 00-59 */ |
| 28 | #define MAX6900_REG_HR 2 /* hours 00-23 */ | 27 | #define MAX6900_REG_HR 2 /* hours 00-23 */ |
| 29 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ | 28 | #define MAX6900_REG_DT 3 /* day of month 00-31 */ |
| 30 | #define MAX6900_REG_MO 4 /* month 01-12 */ | 29 | #define MAX6900_REG_MO 4 /* month 01-12 */ |
| 31 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ | 30 | #define MAX6900_REG_DW 5 /* day of week 1-7 */ |
| 32 | #define MAX6900_REG_YR 6 /* year 00-99 */ | 31 | #define MAX6900_REG_YR 6 /* year 00-99 */ |
| 33 | #define MAX6900_REG_CT 7 /* control */ | 32 | #define MAX6900_REG_CT 7 /* control */ |
| 34 | /* register 8 is undocumented */ | 33 | /* register 8 is undocumented */ |
| 35 | #define MAX6900_REG_CENTURY 9 /* century */ | 34 | #define MAX6900_REG_CENTURY 9 /* century */ |
| @@ -39,7 +38,6 @@ | |||
| 39 | 38 | ||
| 40 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ | 39 | #define MAX6900_REG_CT_WP (1 << 7) /* Write Protect */ |
| 41 | 40 | ||
| 42 | |||
| 43 | /* | 41 | /* |
| 44 | * register read/write commands | 42 | * register read/write commands |
| 45 | */ | 43 | */ |
| @@ -52,16 +50,7 @@ | |||
| 52 | 50 | ||
| 53 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ | 51 | #define MAX6900_IDLE_TIME_AFTER_WRITE 3 /* specification says 2.5 mS */ |
| 54 | 52 | ||
| 55 | #define MAX6900_I2C_ADDR 0xa0 | 53 | static struct i2c_driver max6900_driver; |
| 56 | |||
| 57 | static const unsigned short normal_i2c[] = { | ||
| 58 | MAX6900_I2C_ADDR >> 1, | ||
| 59 | I2C_CLIENT_END | ||
| 60 | }; | ||
| 61 | |||
| 62 | I2C_CLIENT_INSMOD; /* defines addr_data */ | ||
| 63 | |||
| 64 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind); | ||
| 65 | 54 | ||
| 66 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | 55 | static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) |
| 67 | { | 56 | { |
| @@ -69,36 +58,35 @@ static int max6900_i2c_read_regs(struct i2c_client *client, u8 *buf) | |||
| 69 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; | 58 | u8 reg_century_read[1] = { MAX6900_REG_CENTURY_READ }; |
| 70 | struct i2c_msg msgs[4] = { | 59 | struct i2c_msg msgs[4] = { |
| 71 | { | 60 | { |
| 72 | .addr = client->addr, | 61 | .addr = client->addr, |
| 73 | .flags = 0, /* write */ | 62 | .flags = 0, /* write */ |
| 74 | .len = sizeof(reg_burst_read), | 63 | .len = sizeof(reg_burst_read), |
| 75 | .buf = reg_burst_read | 64 | .buf = reg_burst_read} |
| 76 | }, | 65 | , |
| 77 | { | 66 | { |
| 78 | .addr = client->addr, | 67 | .addr = client->addr, |
| 79 | .flags = I2C_M_RD, | 68 | .flags = I2C_M_RD, |
| 80 | .len = MAX6900_BURST_LEN, | 69 | .len = MAX6900_BURST_LEN, |
| 81 | .buf = buf | 70 | .buf = buf} |
| 82 | }, | 71 | , |
| 83 | { | 72 | { |
| 84 | .addr = client->addr, | 73 | .addr = client->addr, |
| 85 | .flags = 0, /* write */ | 74 | .flags = 0, /* write */ |
| 86 | .len = sizeof(reg_century_read), | 75 | .len = sizeof(reg_century_read), |
| 87 | .buf = reg_century_read | 76 | .buf = reg_century_read} |
| 88 | }, | 77 | , |
| 89 | { | 78 | { |
| 90 | .addr = client->addr, | 79 | .addr = client->addr, |
| 91 | .flags = I2C_M_RD, | 80 | .flags = I2C_M_RD, |
| 92 | .len = sizeof(buf[MAX6900_REG_CENTURY]), | 81 | .len = sizeof(buf[MAX6900_REG_CENTURY]), |
| 93 | .buf = &buf[MAX6900_REG_CENTURY] | 82 | .buf = &buf[MAX6900_REG_CENTURY] |
| 94 | } | 83 | } |
| 95 | }; | 84 | }; |
| 96 | int rc; | 85 | int rc; |
| 97 | 86 | ||
| 98 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | 87 | rc = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
| 99 | if (rc != ARRAY_SIZE(msgs)) { | 88 | if (rc != ARRAY_SIZE(msgs)) { |
| 100 | dev_err(&client->dev, "%s: register read failed\n", | 89 | dev_err(&client->dev, "%s: register read failed\n", __func__); |
| 101 | __func__); | ||
| 102 | return -EIO; | 90 | return -EIO; |
| 103 | } | 91 | } |
| 104 | return 0; | 92 | return 0; |
| @@ -109,20 +97,18 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
| 109 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; | 97 | u8 i2c_century_buf[1 + 1] = { MAX6900_REG_CENTURY_WRITE }; |
| 110 | struct i2c_msg century_msgs[1] = { | 98 | struct i2c_msg century_msgs[1] = { |
| 111 | { | 99 | { |
| 112 | .addr = client->addr, | 100 | .addr = client->addr, |
| 113 | .flags = 0, /* write */ | 101 | .flags = 0, /* write */ |
| 114 | .len = sizeof(i2c_century_buf), | 102 | .len = sizeof(i2c_century_buf), |
| 115 | .buf = i2c_century_buf | 103 | .buf = i2c_century_buf} |
| 116 | } | ||
| 117 | }; | 104 | }; |
| 118 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; | 105 | u8 i2c_burst_buf[MAX6900_BURST_LEN + 1] = { MAX6900_REG_BURST_WRITE }; |
| 119 | struct i2c_msg burst_msgs[1] = { | 106 | struct i2c_msg burst_msgs[1] = { |
| 120 | { | 107 | { |
| 121 | .addr = client->addr, | 108 | .addr = client->addr, |
| 122 | .flags = 0, /* write */ | 109 | .flags = 0, /* write */ |
| 123 | .len = sizeof(i2c_burst_buf), | 110 | .len = sizeof(i2c_burst_buf), |
| 124 | .buf = i2c_burst_buf | 111 | .buf = i2c_burst_buf} |
| 125 | } | ||
| 126 | }; | 112 | }; |
| 127 | int rc; | 113 | int rc; |
| 128 | 114 | ||
| @@ -133,10 +119,12 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
| 133 | * bit as part of the burst write. | 119 | * bit as part of the burst write. |
| 134 | */ | 120 | */ |
| 135 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; | 121 | i2c_century_buf[1] = buf[MAX6900_REG_CENTURY]; |
| 122 | |||
| 136 | rc = i2c_transfer(client->adapter, century_msgs, | 123 | rc = i2c_transfer(client->adapter, century_msgs, |
| 137 | ARRAY_SIZE(century_msgs)); | 124 | ARRAY_SIZE(century_msgs)); |
| 138 | if (rc != ARRAY_SIZE(century_msgs)) | 125 | if (rc != ARRAY_SIZE(century_msgs)) |
| 139 | goto write_failed; | 126 | goto write_failed; |
| 127 | |||
| 140 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); | 128 | msleep(MAX6900_IDLE_TIME_AFTER_WRITE); |
| 141 | 129 | ||
| 142 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); | 130 | memcpy(&i2c_burst_buf[1], buf, MAX6900_BURST_LEN); |
| @@ -148,45 +136,11 @@ static int max6900_i2c_write_regs(struct i2c_client *client, u8 const *buf) | |||
| 148 | 136 | ||
| 149 | return 0; | 137 | return 0; |
| 150 | 138 | ||
| 151 | write_failed: | 139 | write_failed: |
| 152 | dev_err(&client->dev, "%s: register write failed\n", | 140 | dev_err(&client->dev, "%s: register write failed\n", __func__); |
| 153 | __func__); | ||
| 154 | return -EIO; | 141 | return -EIO; |
| 155 | } | 142 | } |
| 156 | 143 | ||
| 157 | static int max6900_i2c_validate_client(struct i2c_client *client) | ||
| 158 | { | ||
| 159 | u8 regs[MAX6900_REG_LEN]; | ||
| 160 | u8 zero_mask[] = { | ||
| 161 | 0x80, /* seconds */ | ||
| 162 | 0x80, /* minutes */ | ||
| 163 | 0x40, /* hours */ | ||
| 164 | 0xc0, /* day of month */ | ||
| 165 | 0xe0, /* month */ | ||
| 166 | 0xf8, /* day of week */ | ||
| 167 | 0x00, /* year */ | ||
| 168 | 0x7f, /* control */ | ||
| 169 | }; | ||
| 170 | int i; | ||
| 171 | int rc; | ||
| 172 | int reserved; | ||
| 173 | |||
| 174 | reserved = i2c_smbus_read_byte_data(client, MAX6900_REG_RESERVED_READ); | ||
| 175 | if (reserved != 0x07) | ||
| 176 | return -ENODEV; | ||
| 177 | |||
| 178 | rc = max6900_i2c_read_regs(client, regs); | ||
| 179 | if (rc < 0) | ||
| 180 | return rc; | ||
| 181 | |||
| 182 | for (i = 0; i < ARRAY_SIZE(zero_mask); ++i) { | ||
| 183 | if (regs[i] & zero_mask[i]) | ||
| 184 | return -ENODEV; | ||
| 185 | } | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | 144 | static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) |
| 191 | { | 145 | { |
| 192 | int rc; | 146 | int rc; |
| @@ -202,7 +156,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
| 202 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); | 156 | tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]); |
| 203 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; | 157 | tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1; |
| 204 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + | 158 | tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) + |
| 205 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; | 159 | BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900; |
| 206 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); | 160 | tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]); |
| 207 | 161 | ||
| 208 | return 0; | 162 | return 0; |
| @@ -211,7 +165,7 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm) | |||
| 211 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) | 165 | static int max6900_i2c_clear_write_protect(struct i2c_client *client) |
| 212 | { | 166 | { |
| 213 | int rc; | 167 | int rc; |
| 214 | rc = i2c_smbus_write_byte_data (client, MAX6900_REG_CONTROL_WRITE, 0); | 168 | rc = i2c_smbus_write_byte_data(client, MAX6900_REG_CONTROL_WRITE, 0); |
| 215 | if (rc < 0) { | 169 | if (rc < 0) { |
| 216 | dev_err(&client->dev, "%s: control register write failed\n", | 170 | dev_err(&client->dev, "%s: control register write failed\n", |
| 217 | __func__); | 171 | __func__); |
| @@ -220,8 +174,8 @@ static int max6900_i2c_clear_write_protect(struct i2c_client *client) | |||
| 220 | return 0; | 174 | return 0; |
| 221 | } | 175 | } |
| 222 | 176 | ||
| 223 | static int max6900_i2c_set_time(struct i2c_client *client, | 177 | static int |
| 224 | struct rtc_time const *tm) | 178 | max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) |
| 225 | { | 179 | { |
| 226 | u8 regs[MAX6900_REG_LEN]; | 180 | u8 regs[MAX6900_REG_LEN]; |
| 227 | int rc; | 181 | int rc; |
| @@ -258,89 +212,49 @@ static int max6900_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
| 258 | return max6900_i2c_set_time(to_i2c_client(dev), tm); | 212 | return max6900_i2c_set_time(to_i2c_client(dev), tm); |
| 259 | } | 213 | } |
| 260 | 214 | ||
| 261 | static int max6900_attach_adapter(struct i2c_adapter *adapter) | 215 | static int max6900_remove(struct i2c_client *client) |
| 262 | { | ||
| 263 | return i2c_probe(adapter, &addr_data, max6900_probe); | ||
| 264 | } | ||
| 265 | |||
| 266 | static int max6900_detach_client(struct i2c_client *client) | ||
| 267 | { | 216 | { |
| 268 | struct rtc_device *const rtc = i2c_get_clientdata(client); | 217 | struct rtc_device *rtc = i2c_get_clientdata(client); |
| 269 | 218 | ||
| 270 | if (rtc) | 219 | if (rtc) |
| 271 | rtc_device_unregister(rtc); | 220 | rtc_device_unregister(rtc); |
| 272 | 221 | ||
| 273 | return i2c_detach_client(client); | 222 | return 0; |
| 274 | } | 223 | } |
| 275 | 224 | ||
| 276 | static struct i2c_driver max6900_driver = { | ||
| 277 | .driver = { | ||
| 278 | .name = DRV_NAME, | ||
| 279 | }, | ||
| 280 | .id = I2C_DRIVERID_MAX6900, | ||
| 281 | .attach_adapter = max6900_attach_adapter, | ||
| 282 | .detach_client = max6900_detach_client, | ||
| 283 | }; | ||
| 284 | |||
| 285 | static const struct rtc_class_ops max6900_rtc_ops = { | 225 | static const struct rtc_class_ops max6900_rtc_ops = { |
| 286 | .read_time = max6900_rtc_read_time, | 226 | .read_time = max6900_rtc_read_time, |
| 287 | .set_time = max6900_rtc_set_time, | 227 | .set_time = max6900_rtc_set_time, |
| 288 | }; | 228 | }; |
| 289 | 229 | ||
| 290 | static int max6900_probe(struct i2c_adapter *adapter, int addr, int kind) | 230 | static int |
| 231 | max6900_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
| 291 | { | 232 | { |
| 292 | int rc = 0; | 233 | struct rtc_device *rtc; |
| 293 | struct i2c_client *client = NULL; | ||
| 294 | struct rtc_device *rtc = NULL; | ||
| 295 | |||
| 296 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 297 | rc = -ENODEV; | ||
| 298 | goto failout; | ||
| 299 | } | ||
| 300 | |||
| 301 | client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); | ||
| 302 | if (client == NULL) { | ||
| 303 | rc = -ENOMEM; | ||
| 304 | goto failout; | ||
| 305 | } | ||
| 306 | |||
| 307 | client->addr = addr; | ||
| 308 | client->adapter = adapter; | ||
| 309 | client->driver = &max6900_driver; | ||
| 310 | strlcpy(client->name, DRV_NAME, I2C_NAME_SIZE); | ||
| 311 | |||
| 312 | if (kind < 0) { | ||
| 313 | rc = max6900_i2c_validate_client(client); | ||
| 314 | if (rc < 0) | ||
| 315 | goto failout; | ||
| 316 | } | ||
| 317 | 234 | ||
| 318 | rc = i2c_attach_client(client); | 235 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| 319 | if (rc < 0) | 236 | return -ENODEV; |
| 320 | goto failout; | ||
| 321 | 237 | ||
| 322 | dev_info(&client->dev, | 238 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 323 | "chip found, driver version " DRV_VERSION "\n"); | ||
| 324 | 239 | ||
| 325 | rtc = rtc_device_register(max6900_driver.driver.name, | 240 | rtc = rtc_device_register(max6900_driver.driver.name, |
| 326 | &client->dev, | 241 | &client->dev, &max6900_rtc_ops, THIS_MODULE); |
| 327 | &max6900_rtc_ops, THIS_MODULE); | 242 | if (IS_ERR(rtc)) |
| 328 | if (IS_ERR(rtc)) { | 243 | return PTR_ERR(rtc); |
| 329 | rc = PTR_ERR(rtc); | ||
| 330 | goto failout_detach; | ||
| 331 | } | ||
| 332 | 244 | ||
| 333 | i2c_set_clientdata(client, rtc); | 245 | i2c_set_clientdata(client, rtc); |
| 334 | 246 | ||
| 335 | return 0; | 247 | return 0; |
| 336 | |||
| 337 | failout_detach: | ||
| 338 | i2c_detach_client(client); | ||
| 339 | failout: | ||
| 340 | kfree(client); | ||
| 341 | return rc; | ||
| 342 | } | 248 | } |
| 343 | 249 | ||
| 250 | static struct i2c_driver max6900_driver = { | ||
| 251 | .driver = { | ||
| 252 | .name = "rtc-max6900", | ||
| 253 | }, | ||
| 254 | .probe = max6900_probe, | ||
| 255 | .remove = max6900_remove, | ||
| 256 | }; | ||
| 257 | |||
| 344 | static int __init max6900_init(void) | 258 | static int __init max6900_init(void) |
| 345 | { | 259 | { |
| 346 | return i2c_add_driver(&max6900_driver); | 260 | return i2c_add_driver(&max6900_driver); |
| @@ -352,6 +266,7 @@ static void __exit max6900_exit(void) | |||
| 352 | } | 266 | } |
| 353 | 267 | ||
| 354 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); | 268 | MODULE_DESCRIPTION("Maxim MAX6900 RTC driver"); |
| 269 | MODULE_AUTHOR("Dale Farnsworth <dale@farnsworth.org>"); | ||
| 355 | MODULE_LICENSE("GPL"); | 270 | MODULE_LICENSE("GPL"); |
| 356 | MODULE_VERSION(DRV_VERSION); | 271 | MODULE_VERSION(DRV_VERSION); |
| 357 | 272 | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index 748a502a6355..a829f20ad6d6 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
| @@ -179,58 +179,6 @@ struct pcf8563_limit | |||
| 179 | unsigned char max; | 179 | unsigned char max; |
| 180 | }; | 180 | }; |
| 181 | 181 | ||
| 182 | static int pcf8563_validate_client(struct i2c_client *client) | ||
| 183 | { | ||
| 184 | int i; | ||
| 185 | |||
| 186 | static const struct pcf8563_limit pattern[] = { | ||
| 187 | /* register, mask, min, max */ | ||
| 188 | { PCF8563_REG_SC, 0x7F, 0, 59 }, | ||
| 189 | { PCF8563_REG_MN, 0x7F, 0, 59 }, | ||
| 190 | { PCF8563_REG_HR, 0x3F, 0, 23 }, | ||
| 191 | { PCF8563_REG_DM, 0x3F, 0, 31 }, | ||
| 192 | { PCF8563_REG_MO, 0x1F, 0, 12 }, | ||
| 193 | }; | ||
| 194 | |||
| 195 | /* check limits (only registers with bcd values) */ | ||
| 196 | for (i = 0; i < ARRAY_SIZE(pattern); i++) { | ||
| 197 | int xfer; | ||
| 198 | unsigned char value; | ||
| 199 | unsigned char buf = pattern[i].reg; | ||
| 200 | |||
| 201 | struct i2c_msg msgs[] = { | ||
| 202 | { client->addr, 0, 1, &buf }, | ||
| 203 | { client->addr, I2C_M_RD, 1, &buf }, | ||
| 204 | }; | ||
| 205 | |||
| 206 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 207 | |||
| 208 | if (xfer != ARRAY_SIZE(msgs)) { | ||
| 209 | dev_err(&client->dev, | ||
| 210 | "%s: could not read register 0x%02X\n", | ||
| 211 | __func__, pattern[i].reg); | ||
| 212 | |||
| 213 | return -EIO; | ||
| 214 | } | ||
| 215 | |||
| 216 | value = BCD2BIN(buf & pattern[i].mask); | ||
| 217 | |||
| 218 | if (value > pattern[i].max || | ||
| 219 | value < pattern[i].min) { | ||
| 220 | dev_dbg(&client->dev, | ||
| 221 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " | ||
| 222 | "max=%d, value=%d, raw=0x%02X\n", | ||
| 223 | __func__, i, pattern[i].reg, pattern[i].mask, | ||
| 224 | pattern[i].min, pattern[i].max, | ||
| 225 | value, buf); | ||
| 226 | |||
| 227 | return -ENODEV; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | 182 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 235 | { | 183 | { |
| 236 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | 184 | return pcf8563_get_datetime(to_i2c_client(dev), tm); |
| @@ -262,12 +210,6 @@ static int pcf8563_probe(struct i2c_client *client, | |||
| 262 | if (!pcf8563) | 210 | if (!pcf8563) |
| 263 | return -ENOMEM; | 211 | return -ENOMEM; |
| 264 | 212 | ||
| 265 | /* Verify the chip is really an PCF8563 */ | ||
| 266 | if (pcf8563_validate_client(client) < 0) { | ||
| 267 | err = -ENODEV; | ||
| 268 | goto exit_kfree; | ||
| 269 | } | ||
| 270 | |||
| 271 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 213 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 272 | 214 | ||
| 273 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, | 215 | pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, |
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index 8448eeb9d675..826153552157 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c | |||
| @@ -34,15 +34,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id) | |||
| 34 | return IRQ_HANDLED; | 34 | return IRQ_HANDLED; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | static int pl030_open(struct device *dev) | ||
| 38 | { | ||
| 39 | return 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | static void pl030_release(struct device *dev) | ||
| 43 | { | ||
| 44 | } | ||
| 45 | |||
| 46 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 37 | static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
| 47 | { | 38 | { |
| 48 | return -ENOIOCTLCMD; | 39 | return -ENOIOCTLCMD; |
| @@ -104,8 +95,6 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm) | |||
| 104 | } | 95 | } |
| 105 | 96 | ||
| 106 | static const struct rtc_class_ops pl030_ops = { | 97 | static const struct rtc_class_ops pl030_ops = { |
| 107 | .open = pl030_open, | ||
| 108 | .release = pl030_release, | ||
| 109 | .ioctl = pl030_ioctl, | 98 | .ioctl = pl030_ioctl, |
| 110 | .read_time = pl030_read_time, | 99 | .read_time = pl030_read_time, |
| 111 | .set_time = pl030_set_time, | 100 | .set_time = pl030_set_time, |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08b4610ec5a6..333eec689d2f 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
| @@ -45,18 +45,6 @@ static irqreturn_t pl031_interrupt(int irq, void *dev_id) | |||
| 45 | return IRQ_HANDLED; | 45 | return IRQ_HANDLED; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static int pl031_open(struct device *dev) | ||
| 49 | { | ||
| 50 | /* | ||
| 51 | * We request IRQ in pl031_probe, so nothing to do here... | ||
| 52 | */ | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | static void pl031_release(struct device *dev) | ||
| 57 | { | ||
| 58 | } | ||
| 59 | |||
| 60 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 48 | static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
| 61 | { | 49 | { |
| 62 | struct pl031_local *ldata = dev_get_drvdata(dev); | 50 | struct pl031_local *ldata = dev_get_drvdata(dev); |
| @@ -118,8 +106,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
| 118 | } | 106 | } |
| 119 | 107 | ||
| 120 | static const struct rtc_class_ops pl031_ops = { | 108 | static const struct rtc_class_ops pl031_ops = { |
| 121 | .open = pl031_open, | ||
| 122 | .release = pl031_release, | ||
| 123 | .ioctl = pl031_ioctl, | 109 | .ioctl = pl031_ioctl, |
| 124 | .read_time = pl031_read_time, | 110 | .read_time = pl031_read_time, |
| 125 | .set_time = pl031_set_time, | 111 | .set_time = pl031_set_time, |
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 56caf6b2c3e5..8b561958fb1e 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * An I2C driver for Ricoh RS5C372 and RV5C38[67] RTCs | 2 | * An I2C driver for Ricoh RS5C372, R2025S/D and RV5C38[67] RTCs |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> | 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> |
| 5 | * Copyright (C) 2006 Tower Technologies | 5 | * Copyright (C) 2006 Tower Technologies |
| 6 | * Copyright (C) 2008 Paul Mundt | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
| @@ -13,7 +14,7 @@ | |||
| 13 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 14 | #include <linux/bcd.h> | 15 | #include <linux/bcd.h> |
| 15 | 16 | ||
| 16 | #define DRV_VERSION "0.5" | 17 | #define DRV_VERSION "0.6" |
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | /* | 20 | /* |
| @@ -51,7 +52,8 @@ | |||
| 51 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ | 52 | # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ |
| 52 | #define RS5C_REG_CTRL2 15 | 53 | #define RS5C_REG_CTRL2 15 |
| 53 | # define RS5C372_CTRL2_24 (1 << 5) | 54 | # define RS5C372_CTRL2_24 (1 << 5) |
| 54 | # define RS5C_CTRL2_XSTP (1 << 4) | 55 | # define R2025_CTRL2_XST (1 << 5) |
| 56 | # define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */ | ||
| 55 | # define RS5C_CTRL2_CTFG (1 << 2) | 57 | # define RS5C_CTRL2_CTFG (1 << 2) |
| 56 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ | 58 | # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ |
| 57 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ | 59 | # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ |
| @@ -63,6 +65,7 @@ | |||
| 63 | 65 | ||
| 64 | enum rtc_type { | 66 | enum rtc_type { |
| 65 | rtc_undef = 0, | 67 | rtc_undef = 0, |
| 68 | rtc_r2025sd, | ||
| 66 | rtc_rs5c372a, | 69 | rtc_rs5c372a, |
| 67 | rtc_rs5c372b, | 70 | rtc_rs5c372b, |
| 68 | rtc_rv5c386, | 71 | rtc_rv5c386, |
| @@ -70,6 +73,7 @@ enum rtc_type { | |||
| 70 | }; | 73 | }; |
| 71 | 74 | ||
| 72 | static const struct i2c_device_id rs5c372_id[] = { | 75 | static const struct i2c_device_id rs5c372_id[] = { |
| 76 | { "r2025sd", rtc_r2025sd }, | ||
| 73 | { "rs5c372a", rtc_rs5c372a }, | 77 | { "rs5c372a", rtc_rs5c372a }, |
| 74 | { "rs5c372b", rtc_rs5c372b }, | 78 | { "rs5c372b", rtc_rs5c372b }, |
| 75 | { "rv5c386", rtc_rv5c386 }, | 79 | { "rv5c386", rtc_rv5c386 }, |
| @@ -89,6 +93,7 @@ struct rs5c372 { | |||
| 89 | enum rtc_type type; | 93 | enum rtc_type type; |
| 90 | unsigned time24:1; | 94 | unsigned time24:1; |
| 91 | unsigned has_irq:1; | 95 | unsigned has_irq:1; |
| 96 | unsigned smbus:1; | ||
| 92 | char buf[17]; | 97 | char buf[17]; |
| 93 | char *regs; | 98 | char *regs; |
| 94 | }; | 99 | }; |
| @@ -106,10 +111,25 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) | |||
| 106 | * | 111 | * |
| 107 | * The first method doesn't work with the iop3xx adapter driver, on at | 112 | * The first method doesn't work with the iop3xx adapter driver, on at |
| 108 | * least 80219 chips; this works around that bug. | 113 | * least 80219 chips; this works around that bug. |
| 114 | * | ||
| 115 | * The third method on the other hand doesn't work for the SMBus-only | ||
| 116 | * configurations, so we use the the first method there, stripping off | ||
| 117 | * the extra register in the process. | ||
| 109 | */ | 118 | */ |
| 110 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | 119 | if (rs5c->smbus) { |
| 111 | dev_warn(&client->dev, "can't read registers\n"); | 120 | int addr = RS5C_ADDR(RS5C372_REG_SECS); |
| 112 | return -EIO; | 121 | int size = sizeof(rs5c->buf) - 1; |
| 122 | |||
| 123 | if (i2c_smbus_read_i2c_block_data(client, addr, size, | ||
| 124 | rs5c->buf + 1) != size) { | ||
| 125 | dev_warn(&client->dev, "can't read registers\n"); | ||
| 126 | return -EIO; | ||
| 127 | } | ||
| 128 | } else { | ||
| 129 | if ((i2c_transfer(client->adapter, msgs, 1)) != 1) { | ||
| 130 | dev_warn(&client->dev, "can't read registers\n"); | ||
| 131 | return -EIO; | ||
| 132 | } | ||
| 113 | } | 133 | } |
| 114 | 134 | ||
| 115 | dev_dbg(&client->dev, | 135 | dev_dbg(&client->dev, |
| @@ -187,6 +207,7 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 187 | { | 207 | { |
| 188 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 208 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
| 189 | unsigned char buf[8]; | 209 | unsigned char buf[8]; |
| 210 | int addr; | ||
| 190 | 211 | ||
| 191 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " | 212 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " |
| 192 | "mday=%d, mon=%d, year=%d, wday=%d\n", | 213 | "mday=%d, mon=%d, year=%d, wday=%d\n", |
| @@ -194,16 +215,16 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
| 194 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 215 | tm->tm_sec, tm->tm_min, tm->tm_hour, |
| 195 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | 216 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); |
| 196 | 217 | ||
| 197 | buf[0] = RS5C_ADDR(RS5C372_REG_SECS); | 218 | addr = RS5C_ADDR(RS5C372_REG_SECS); |
| 198 | buf[1] = BIN2BCD(tm->tm_sec); | 219 | buf[0] = BIN2BCD(tm->tm_sec); |
| 199 | buf[2] = BIN2BCD(tm->tm_min); | 220 | buf[1] = BIN2BCD(tm->tm_min); |
| 200 | buf[3] = rs5c_hr2reg(rs5c, tm->tm_hour); | 221 | buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour); |
| 201 | buf[4] = BIN2BCD(tm->tm_wday); | 222 | buf[3] = BIN2BCD(tm->tm_wday); |
| 202 | buf[5] = BIN2BCD(tm->tm_mday); | 223 | buf[4] = BIN2BCD(tm->tm_mday); |
| 203 | buf[6] = BIN2BCD(tm->tm_mon + 1); | 224 | buf[5] = BIN2BCD(tm->tm_mon + 1); |
| 204 | buf[7] = BIN2BCD(tm->tm_year - 100); | 225 | buf[6] = BIN2BCD(tm->tm_year - 100); |
| 205 | 226 | ||
| 206 | if ((i2c_master_send(client, buf, 8)) != 8) { | 227 | if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) { |
| 207 | dev_err(&client->dev, "%s: write error\n", __func__); | 228 | dev_err(&client->dev, "%s: write error\n", __func__); |
| 208 | return -EIO; | 229 | return -EIO; |
| 209 | } | 230 | } |
| @@ -266,16 +287,16 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 266 | { | 287 | { |
| 267 | struct i2c_client *client = to_i2c_client(dev); | 288 | struct i2c_client *client = to_i2c_client(dev); |
| 268 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 289 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
| 269 | unsigned char buf[2]; | 290 | unsigned char buf; |
| 270 | int status; | 291 | int status, addr; |
| 271 | 292 | ||
| 272 | buf[1] = rs5c->regs[RS5C_REG_CTRL1]; | 293 | buf = rs5c->regs[RS5C_REG_CTRL1]; |
| 273 | switch (cmd) { | 294 | switch (cmd) { |
| 274 | case RTC_UIE_OFF: | 295 | case RTC_UIE_OFF: |
| 275 | case RTC_UIE_ON: | 296 | case RTC_UIE_ON: |
| 276 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ | 297 | /* some 327a modes use a different IRQ pin for 1Hz irqs */ |
| 277 | if (rs5c->type == rtc_rs5c372a | 298 | if (rs5c->type == rtc_rs5c372a |
| 278 | && (buf[1] & RS5C372A_CTRL1_SL1)) | 299 | && (buf & RS5C372A_CTRL1_SL1)) |
| 279 | return -ENOIOCTLCMD; | 300 | return -ENOIOCTLCMD; |
| 280 | case RTC_AIE_OFF: | 301 | case RTC_AIE_OFF: |
| 281 | case RTC_AIE_ON: | 302 | case RTC_AIE_ON: |
| @@ -293,28 +314,30 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
| 293 | if (status < 0) | 314 | if (status < 0) |
| 294 | return status; | 315 | return status; |
| 295 | 316 | ||
| 296 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 317 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
| 297 | switch (cmd) { | 318 | switch (cmd) { |
| 298 | case RTC_AIE_OFF: /* alarm off */ | 319 | case RTC_AIE_OFF: /* alarm off */ |
| 299 | buf[1] &= ~RS5C_CTRL1_AALE; | 320 | buf &= ~RS5C_CTRL1_AALE; |
| 300 | break; | 321 | break; |
| 301 | case RTC_AIE_ON: /* alarm on */ | 322 | case RTC_AIE_ON: /* alarm on */ |
| 302 | buf[1] |= RS5C_CTRL1_AALE; | 323 | buf |= RS5C_CTRL1_AALE; |
| 303 | break; | 324 | break; |
| 304 | case RTC_UIE_OFF: /* update off */ | 325 | case RTC_UIE_OFF: /* update off */ |
| 305 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 326 | buf &= ~RS5C_CTRL1_CT_MASK; |
| 306 | break; | 327 | break; |
| 307 | case RTC_UIE_ON: /* update on */ | 328 | case RTC_UIE_ON: /* update on */ |
| 308 | buf[1] &= ~RS5C_CTRL1_CT_MASK; | 329 | buf &= ~RS5C_CTRL1_CT_MASK; |
| 309 | buf[1] |= RS5C_CTRL1_CT4; | 330 | buf |= RS5C_CTRL1_CT4; |
| 310 | break; | 331 | break; |
| 311 | } | 332 | } |
| 312 | if ((i2c_master_send(client, buf, 2)) != 2) { | 333 | |
| 334 | if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { | ||
| 313 | printk(KERN_WARNING "%s: can't update alarm\n", | 335 | printk(KERN_WARNING "%s: can't update alarm\n", |
| 314 | rs5c->rtc->name); | 336 | rs5c->rtc->name); |
| 315 | status = -EIO; | 337 | status = -EIO; |
| 316 | } else | 338 | } else |
| 317 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 339 | rs5c->regs[RS5C_REG_CTRL1] = buf; |
| 340 | |||
| 318 | return status; | 341 | return status; |
| 319 | } | 342 | } |
| 320 | 343 | ||
| @@ -364,8 +387,8 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 364 | { | 387 | { |
| 365 | struct i2c_client *client = to_i2c_client(dev); | 388 | struct i2c_client *client = to_i2c_client(dev); |
| 366 | struct rs5c372 *rs5c = i2c_get_clientdata(client); | 389 | struct rs5c372 *rs5c = i2c_get_clientdata(client); |
| 367 | int status; | 390 | int status, addr, i; |
| 368 | unsigned char buf[4]; | 391 | unsigned char buf[3]; |
| 369 | 392 | ||
| 370 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ | 393 | /* only handle up to 24 hours in the future, like RTC_ALM_SET */ |
| 371 | if (t->time.tm_mday != -1 | 394 | if (t->time.tm_mday != -1 |
| @@ -380,33 +403,36 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
| 380 | if (status < 0) | 403 | if (status < 0) |
| 381 | return status; | 404 | return status; |
| 382 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { | 405 | if (rs5c->regs[RS5C_REG_CTRL1] & RS5C_CTRL1_AALE) { |
| 383 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 406 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
| 384 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; | 407 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] & ~RS5C_CTRL1_AALE; |
| 385 | if (i2c_master_send(client, buf, 2) != 2) { | 408 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) { |
| 386 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); | 409 | pr_debug("%s: can't disable alarm\n", rs5c->rtc->name); |
| 387 | return -EIO; | 410 | return -EIO; |
| 388 | } | 411 | } |
| 389 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 412 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
| 390 | } | 413 | } |
| 391 | 414 | ||
| 392 | /* set alarm */ | 415 | /* set alarm */ |
| 393 | buf[0] = RS5C_ADDR(RS5C_REG_ALARM_A_MIN); | 416 | buf[0] = BIN2BCD(t->time.tm_min); |
| 394 | buf[1] = BIN2BCD(t->time.tm_min); | 417 | buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour); |
| 395 | buf[2] = rs5c_hr2reg(rs5c, t->time.tm_hour); | 418 | buf[2] = 0x7f; /* any/all days */ |
| 396 | buf[3] = 0x7f; /* any/all days */ | 419 | |
| 397 | if ((i2c_master_send(client, buf, 4)) != 4) { | 420 | for (i = 0; i < sizeof(buf); i++) { |
| 398 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | 421 | addr = RS5C_ADDR(RS5C_REG_ALARM_A_MIN + i); |
| 399 | return -EIO; | 422 | if (i2c_smbus_write_byte_data(client, addr, buf[i]) < 0) { |
| 423 | pr_debug("%s: can't set alarm time\n", rs5c->rtc->name); | ||
| 424 | return -EIO; | ||
| 425 | } | ||
| 400 | } | 426 | } |
| 401 | 427 | ||
| 402 | /* ... and maybe enable its irq */ | 428 | /* ... and maybe enable its irq */ |
| 403 | if (t->enabled) { | 429 | if (t->enabled) { |
| 404 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | 430 | addr = RS5C_ADDR(RS5C_REG_CTRL1); |
| 405 | buf[1] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; | 431 | buf[0] = rs5c->regs[RS5C_REG_CTRL1] | RS5C_CTRL1_AALE; |
| 406 | if ((i2c_master_send(client, buf, 2)) != 2) | 432 | if (i2c_smbus_write_byte_data(client, addr, buf[0]) < 0) |
| 407 | printk(KERN_WARNING "%s: can't enable alarm\n", | 433 | printk(KERN_WARNING "%s: can't enable alarm\n", |
| 408 | rs5c->rtc->name); | 434 | rs5c->rtc->name); |
| 409 | rs5c->regs[RS5C_REG_CTRL1] = buf[1]; | 435 | rs5c->regs[RS5C_REG_CTRL1] = buf[0]; |
| 410 | } | 436 | } |
| 411 | 437 | ||
| 412 | return 0; | 438 | return 0; |
| @@ -503,18 +529,81 @@ static void rs5c_sysfs_unregister(struct device *dev) | |||
| 503 | 529 | ||
| 504 | static struct i2c_driver rs5c372_driver; | 530 | static struct i2c_driver rs5c372_driver; |
| 505 | 531 | ||
| 532 | static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) | ||
| 533 | { | ||
| 534 | unsigned char buf[2]; | ||
| 535 | int addr, i, ret = 0; | ||
| 536 | |||
| 537 | if (rs5c372->type == rtc_r2025sd) { | ||
| 538 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST)) | ||
| 539 | return ret; | ||
| 540 | rs5c372->regs[RS5C_REG_CTRL2] &= ~R2025_CTRL2_XST; | ||
| 541 | } else { | ||
| 542 | if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) | ||
| 543 | return ret; | ||
| 544 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | ||
| 545 | } | ||
| 546 | |||
| 547 | addr = RS5C_ADDR(RS5C_REG_CTRL1); | ||
| 548 | buf[0] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
| 549 | buf[1] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
| 550 | |||
| 551 | /* use 24hr mode */ | ||
| 552 | switch (rs5c372->type) { | ||
| 553 | case rtc_rs5c372a: | ||
| 554 | case rtc_rs5c372b: | ||
| 555 | buf[1] |= RS5C372_CTRL2_24; | ||
| 556 | rs5c372->time24 = 1; | ||
| 557 | break; | ||
| 558 | case rtc_r2025sd: | ||
| 559 | case rtc_rv5c386: | ||
| 560 | case rtc_rv5c387a: | ||
| 561 | buf[0] |= RV5C387_CTRL1_24; | ||
| 562 | rs5c372->time24 = 1; | ||
| 563 | break; | ||
| 564 | default: | ||
| 565 | /* impossible */ | ||
| 566 | break; | ||
| 567 | } | ||
| 568 | |||
| 569 | for (i = 0; i < sizeof(buf); i++) { | ||
| 570 | addr = RS5C_ADDR(RS5C_REG_CTRL1 + i); | ||
| 571 | ret = i2c_smbus_write_byte_data(rs5c372->client, addr, buf[i]); | ||
| 572 | if (unlikely(ret < 0)) | ||
| 573 | return ret; | ||
| 574 | } | ||
| 575 | |||
| 576 | rs5c372->regs[RS5C_REG_CTRL1] = buf[0]; | ||
| 577 | rs5c372->regs[RS5C_REG_CTRL2] = buf[1]; | ||
| 578 | |||
| 579 | return 0; | ||
| 580 | } | ||
| 581 | |||
| 506 | static int rs5c372_probe(struct i2c_client *client, | 582 | static int rs5c372_probe(struct i2c_client *client, |
| 507 | const struct i2c_device_id *id) | 583 | const struct i2c_device_id *id) |
| 508 | { | 584 | { |
| 509 | int err = 0; | 585 | int err = 0; |
| 586 | int smbus_mode = 0; | ||
| 510 | struct rs5c372 *rs5c372; | 587 | struct rs5c372 *rs5c372; |
| 511 | struct rtc_time tm; | 588 | struct rtc_time tm; |
| 512 | 589 | ||
| 513 | dev_dbg(&client->dev, "%s\n", __func__); | 590 | dev_dbg(&client->dev, "%s\n", __func__); |
| 514 | 591 | ||
| 515 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | 592 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | |
| 516 | err = -ENODEV; | 593 | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { |
| 517 | goto exit; | 594 | /* |
| 595 | * If we don't have any master mode adapter, try breaking | ||
| 596 | * it down in to the barest of capabilities. | ||
| 597 | */ | ||
| 598 | if (i2c_check_functionality(client->adapter, | ||
| 599 | I2C_FUNC_SMBUS_BYTE_DATA | | ||
| 600 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
| 601 | smbus_mode = 1; | ||
| 602 | else { | ||
| 603 | /* Still no good, give up */ | ||
| 604 | err = -ENODEV; | ||
| 605 | goto exit; | ||
| 606 | } | ||
| 518 | } | 607 | } |
| 519 | 608 | ||
| 520 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { | 609 | if (!(rs5c372 = kzalloc(sizeof(struct rs5c372), GFP_KERNEL))) { |
| @@ -528,6 +617,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
| 528 | 617 | ||
| 529 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ | 618 | /* we read registers 0x0f then 0x00-0x0f; skip the first one */ |
| 530 | rs5c372->regs = &rs5c372->buf[1]; | 619 | rs5c372->regs = &rs5c372->buf[1]; |
| 620 | rs5c372->smbus = smbus_mode; | ||
| 531 | 621 | ||
| 532 | err = rs5c_get_regs(rs5c372); | 622 | err = rs5c_get_regs(rs5c372); |
| 533 | if (err < 0) | 623 | if (err < 0) |
| @@ -543,6 +633,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
| 543 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) | 633 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C372_CTRL2_24) |
| 544 | rs5c372->time24 = 1; | 634 | rs5c372->time24 = 1; |
| 545 | break; | 635 | break; |
| 636 | case rtc_r2025sd: | ||
| 546 | case rtc_rv5c386: | 637 | case rtc_rv5c386: |
| 547 | case rtc_rv5c387a: | 638 | case rtc_rv5c387a: |
| 548 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) | 639 | if (rs5c372->regs[RS5C_REG_CTRL1] & RV5C387_CTRL1_24) |
| @@ -558,39 +649,14 @@ static int rs5c372_probe(struct i2c_client *client, | |||
| 558 | 649 | ||
| 559 | /* if the oscillator lost power and no other software (like | 650 | /* if the oscillator lost power and no other software (like |
| 560 | * the bootloader) set it up, do it here. | 651 | * the bootloader) set it up, do it here. |
| 652 | * | ||
| 653 | * The R2025S/D does this a little differently than the other | ||
| 654 | * parts, so we special case that.. | ||
| 561 | */ | 655 | */ |
| 562 | if (rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP) { | 656 | err = rs5c_oscillator_setup(rs5c372); |
| 563 | unsigned char buf[3]; | 657 | if (unlikely(err < 0)) { |
| 564 | 658 | dev_err(&client->dev, "setup error\n"); | |
| 565 | rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; | 659 | goto exit_kfree; |
| 566 | |||
| 567 | buf[0] = RS5C_ADDR(RS5C_REG_CTRL1); | ||
| 568 | buf[1] = rs5c372->regs[RS5C_REG_CTRL1]; | ||
| 569 | buf[2] = rs5c372->regs[RS5C_REG_CTRL2]; | ||
| 570 | |||
| 571 | /* use 24hr mode */ | ||
| 572 | switch (rs5c372->type) { | ||
| 573 | case rtc_rs5c372a: | ||
| 574 | case rtc_rs5c372b: | ||
| 575 | buf[2] |= RS5C372_CTRL2_24; | ||
| 576 | rs5c372->time24 = 1; | ||
| 577 | break; | ||
| 578 | case rtc_rv5c386: | ||
| 579 | case rtc_rv5c387a: | ||
| 580 | buf[1] |= RV5C387_CTRL1_24; | ||
| 581 | rs5c372->time24 = 1; | ||
| 582 | break; | ||
| 583 | default: | ||
| 584 | /* impossible */ | ||
| 585 | break; | ||
| 586 | } | ||
| 587 | |||
| 588 | if ((i2c_master_send(client, buf, 3)) != 3) { | ||
| 589 | dev_err(&client->dev, "setup error\n"); | ||
| 590 | goto exit_kfree; | ||
| 591 | } | ||
| 592 | rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; | ||
| 593 | rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; | ||
| 594 | } | 660 | } |
| 595 | 661 | ||
| 596 | if (rs5c372_get_datetime(client, &tm) < 0) | 662 | if (rs5c372_get_datetime(client, &tm) < 0) |
| @@ -598,6 +664,7 @@ static int rs5c372_probe(struct i2c_client *client, | |||
| 598 | 664 | ||
| 599 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", | 665 | dev_info(&client->dev, "%s found, %s, driver version " DRV_VERSION "\n", |
| 600 | ({ char *s; switch (rs5c372->type) { | 666 | ({ char *s; switch (rs5c372->type) { |
| 667 | case rtc_r2025sd: s = "r2025sd"; break; | ||
| 601 | case rtc_rs5c372a: s = "rs5c372a"; break; | 668 | case rtc_rs5c372a: s = "rs5c372a"; break; |
| 602 | case rtc_rs5c372b: s = "rs5c372b"; break; | 669 | case rtc_rs5c372b: s = "rs5c372b"; break; |
| 603 | case rtc_rv5c386: s = "rv5c386"; break; | 670 | case rtc_rv5c386: s = "rv5c386"; break; |
| @@ -667,7 +734,8 @@ module_exit(rs5c372_exit); | |||
| 667 | 734 | ||
| 668 | MODULE_AUTHOR( | 735 | MODULE_AUTHOR( |
| 669 | "Pavel Mironchik <pmironchik@optifacio.net>, " | 736 | "Pavel Mironchik <pmironchik@optifacio.net>, " |
| 670 | "Alessandro Zummo <a.zummo@towertech.it>"); | 737 | "Alessandro Zummo <a.zummo@towertech.it>, " |
| 738 | "Paul Mundt <lethal@linux-sh.org>"); | ||
| 671 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); | 739 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); |
| 672 | MODULE_LICENSE("GPL"); | 740 | MODULE_LICENSE("GPL"); |
| 673 | MODULE_VERSION(DRV_VERSION); | 741 | MODULE_VERSION(DRV_VERSION); |
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 1f88e9e914ec..fcead4c4cd1f 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c | |||
| @@ -257,12 +257,6 @@ static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) | |||
| 257 | spin_unlock_irq(&rtc->lock); | 257 | spin_unlock_irq(&rtc->lock); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static void sh_rtc_release(struct device *dev) | ||
| 261 | { | ||
| 262 | sh_rtc_setpie(dev, 0); | ||
| 263 | sh_rtc_setaie(dev, 0); | ||
| 264 | } | ||
| 265 | |||
| 266 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) | 260 | static int sh_rtc_proc(struct device *dev, struct seq_file *seq) |
| 267 | { | 261 | { |
| 268 | struct sh_rtc *rtc = dev_get_drvdata(dev); | 262 | struct sh_rtc *rtc = dev_get_drvdata(dev); |
| @@ -559,7 +553,6 @@ static int sh_rtc_irq_set_freq(struct device *dev, int freq) | |||
| 559 | } | 553 | } |
| 560 | 554 | ||
| 561 | static struct rtc_class_ops sh_rtc_ops = { | 555 | static struct rtc_class_ops sh_rtc_ops = { |
| 562 | .release = sh_rtc_release, | ||
| 563 | .ioctl = sh_rtc_ioctl, | 556 | .ioctl = sh_rtc_ioctl, |
| 564 | .read_time = sh_rtc_read_time, | 557 | .read_time = sh_rtc_read_time, |
| 565 | .set_time = sh_rtc_set_time, | 558 | .set_time = sh_rtc_set_time, |
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c new file mode 100644 index 000000000000..7ccb0dd700af --- /dev/null +++ b/drivers/rtc/rtc-starfire.c | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | /* rtc-starfire.c: Starfire platform RTC driver. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/time.h> | ||
| 10 | #include <linux/rtc.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | |||
| 13 | #include <asm/oplib.h> | ||
| 14 | |||
| 15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 16 | MODULE_DESCRIPTION("Starfire RTC driver"); | ||
| 17 | MODULE_LICENSE("GPL"); | ||
| 18 | |||
| 19 | struct starfire_rtc { | ||
| 20 | struct rtc_device *rtc; | ||
| 21 | spinlock_t lock; | ||
| 22 | }; | ||
| 23 | |||
| 24 | static u32 starfire_get_time(void) | ||
| 25 | { | ||
| 26 | static char obp_gettod[32]; | ||
| 27 | static u32 unix_tod; | ||
| 28 | |||
| 29 | sprintf(obp_gettod, "h# %08x unix-gettod", | ||
| 30 | (unsigned int) (long) &unix_tod); | ||
| 31 | prom_feval(obp_gettod); | ||
| 32 | |||
| 33 | return unix_tod; | ||
| 34 | } | ||
| 35 | |||
| 36 | static int starfire_read_time(struct device *dev, struct rtc_time *tm) | ||
| 37 | { | ||
| 38 | struct starfire_rtc *p = dev_get_drvdata(dev); | ||
| 39 | unsigned long flags, secs; | ||
| 40 | |||
| 41 | spin_lock_irqsave(&p->lock, flags); | ||
| 42 | secs = starfire_get_time(); | ||
| 43 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 44 | |||
| 45 | rtc_time_to_tm(secs, tm); | ||
| 46 | |||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static int starfire_set_time(struct device *dev, struct rtc_time *tm) | ||
| 51 | { | ||
| 52 | unsigned long secs; | ||
| 53 | int err; | ||
| 54 | |||
| 55 | err = rtc_tm_to_time(tm, &secs); | ||
| 56 | if (err) | ||
| 57 | return err; | ||
| 58 | |||
| 59 | /* Do nothing, time is set using the service processor | ||
| 60 | * console on this platform. | ||
| 61 | */ | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static const struct rtc_class_ops starfire_rtc_ops = { | ||
| 66 | .read_time = starfire_read_time, | ||
| 67 | .set_time = starfire_set_time, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static int __devinit starfire_rtc_probe(struct platform_device *pdev) | ||
| 71 | { | ||
| 72 | struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 73 | |||
| 74 | if (!p) | ||
| 75 | return -ENOMEM; | ||
| 76 | |||
| 77 | spin_lock_init(&p->lock); | ||
| 78 | |||
| 79 | p->rtc = rtc_device_register("starfire", &pdev->dev, | ||
| 80 | &starfire_rtc_ops, THIS_MODULE); | ||
| 81 | if (IS_ERR(p->rtc)) { | ||
| 82 | int err = PTR_ERR(p->rtc); | ||
| 83 | kfree(p); | ||
| 84 | return err; | ||
| 85 | } | ||
| 86 | platform_set_drvdata(pdev, p); | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int __devexit starfire_rtc_remove(struct platform_device *pdev) | ||
| 91 | { | ||
| 92 | struct starfire_rtc *p = platform_get_drvdata(pdev); | ||
| 93 | |||
| 94 | rtc_device_unregister(p->rtc); | ||
| 95 | kfree(p); | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static struct platform_driver starfire_rtc_driver = { | ||
| 101 | .driver = { | ||
| 102 | .name = "rtc-starfire", | ||
| 103 | .owner = THIS_MODULE, | ||
| 104 | }, | ||
| 105 | .probe = starfire_rtc_probe, | ||
| 106 | .remove = __devexit_p(starfire_rtc_remove), | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int __init starfire_rtc_init(void) | ||
| 110 | { | ||
| 111 | return platform_driver_register(&starfire_rtc_driver); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void __exit starfire_rtc_exit(void) | ||
| 115 | { | ||
| 116 | platform_driver_unregister(&starfire_rtc_driver); | ||
| 117 | } | ||
| 118 | |||
| 119 | module_init(starfire_rtc_init); | ||
| 120 | module_exit(starfire_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index 31d3c8c28588..9a7e920315fa 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
| @@ -215,17 +215,6 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id) | |||
| 215 | return IRQ_HANDLED; | 215 | return IRQ_HANDLED; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | static void stk17ta8_rtc_release(struct device *dev) | ||
| 219 | { | ||
| 220 | struct platform_device *pdev = to_platform_device(dev); | ||
| 221 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
| 222 | |||
| 223 | if (pdata->irq >= 0) { | ||
| 224 | pdata->irqen = 0; | ||
| 225 | stk17ta8_rtc_update_alarm(pdata); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, | 218 | static int stk17ta8_rtc_ioctl(struct device *dev, unsigned int cmd, |
| 230 | unsigned long arg) | 219 | unsigned long arg) |
| 231 | { | 220 | { |
| @@ -254,7 +243,6 @@ static const struct rtc_class_ops stk17ta8_rtc_ops = { | |||
| 254 | .set_time = stk17ta8_rtc_set_time, | 243 | .set_time = stk17ta8_rtc_set_time, |
| 255 | .read_alarm = stk17ta8_rtc_read_alarm, | 244 | .read_alarm = stk17ta8_rtc_read_alarm, |
| 256 | .set_alarm = stk17ta8_rtc_set_alarm, | 245 | .set_alarm = stk17ta8_rtc_set_alarm, |
| 257 | .release = stk17ta8_rtc_release, | ||
| 258 | .ioctl = stk17ta8_rtc_ioctl, | 246 | .ioctl = stk17ta8_rtc_ioctl, |
| 259 | }; | 247 | }; |
| 260 | 248 | ||
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c new file mode 100644 index 000000000000..2012ccbb4a53 --- /dev/null +++ b/drivers/rtc/rtc-sun4v.c | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/kernel.h> | ||
| 7 | #include <linux/module.h> | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/time.h> | ||
| 11 | #include <linux/rtc.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | |||
| 14 | #include <asm/hypervisor.h> | ||
| 15 | |||
| 16 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 17 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | |||
| 20 | struct sun4v_rtc { | ||
| 21 | struct rtc_device *rtc; | ||
| 22 | spinlock_t lock; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static unsigned long hypervisor_get_time(void) | ||
| 26 | { | ||
| 27 | unsigned long ret, time; | ||
| 28 | int retries = 10000; | ||
| 29 | |||
| 30 | retry: | ||
| 31 | ret = sun4v_tod_get(&time); | ||
| 32 | if (ret == HV_EOK) | ||
| 33 | return time; | ||
| 34 | if (ret == HV_EWOULDBLOCK) { | ||
| 35 | if (--retries > 0) { | ||
| 36 | udelay(100); | ||
| 37 | goto retry; | ||
| 38 | } | ||
| 39 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) | ||
| 47 | { | ||
| 48 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
| 49 | unsigned long flags, secs; | ||
| 50 | |||
| 51 | spin_lock_irqsave(&p->lock, flags); | ||
| 52 | secs = hypervisor_get_time(); | ||
| 53 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 54 | |||
| 55 | rtc_time_to_tm(secs, tm); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static int hypervisor_set_time(unsigned long secs) | ||
| 61 | { | ||
| 62 | unsigned long ret; | ||
| 63 | int retries = 10000; | ||
| 64 | |||
| 65 | retry: | ||
| 66 | ret = sun4v_tod_set(secs); | ||
| 67 | if (ret == HV_EOK) | ||
| 68 | return 0; | ||
| 69 | if (ret == HV_EWOULDBLOCK) { | ||
| 70 | if (--retries > 0) { | ||
| 71 | udelay(100); | ||
| 72 | goto retry; | ||
| 73 | } | ||
| 74 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
| 75 | return -EAGAIN; | ||
| 76 | } | ||
| 77 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
| 78 | return -EOPNOTSUPP; | ||
| 79 | } | ||
| 80 | |||
| 81 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) | ||
| 82 | { | ||
| 83 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
| 84 | unsigned long flags, secs; | ||
| 85 | int err; | ||
| 86 | |||
| 87 | err = rtc_tm_to_time(tm, &secs); | ||
| 88 | if (err) | ||
| 89 | return err; | ||
| 90 | |||
| 91 | spin_lock_irqsave(&p->lock, flags); | ||
| 92 | err = hypervisor_set_time(secs); | ||
| 93 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 94 | |||
| 95 | return err; | ||
| 96 | } | ||
| 97 | |||
| 98 | static const struct rtc_class_ops sun4v_rtc_ops = { | ||
| 99 | .read_time = sun4v_read_time, | ||
| 100 | .set_time = sun4v_set_time, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static int __devinit sun4v_rtc_probe(struct platform_device *pdev) | ||
| 104 | { | ||
| 105 | struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
| 106 | |||
| 107 | if (!p) | ||
| 108 | return -ENOMEM; | ||
| 109 | |||
| 110 | spin_lock_init(&p->lock); | ||
| 111 | |||
| 112 | p->rtc = rtc_device_register("sun4v", &pdev->dev, | ||
| 113 | &sun4v_rtc_ops, THIS_MODULE); | ||
| 114 | if (IS_ERR(p->rtc)) { | ||
| 115 | int err = PTR_ERR(p->rtc); | ||
| 116 | kfree(p); | ||
| 117 | return err; | ||
| 118 | } | ||
| 119 | platform_set_drvdata(pdev, p); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int __devexit sun4v_rtc_remove(struct platform_device *pdev) | ||
| 124 | { | ||
| 125 | struct sun4v_rtc *p = platform_get_drvdata(pdev); | ||
| 126 | |||
| 127 | rtc_device_unregister(p->rtc); | ||
| 128 | kfree(p); | ||
| 129 | |||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct platform_driver sun4v_rtc_driver = { | ||
| 134 | .driver = { | ||
| 135 | .name = "rtc-sun4v", | ||
| 136 | .owner = THIS_MODULE, | ||
| 137 | }, | ||
| 138 | .probe = sun4v_rtc_probe, | ||
| 139 | .remove = __devexit_p(sun4v_rtc_remove), | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __init sun4v_rtc_init(void) | ||
| 143 | { | ||
| 144 | return platform_driver_register(&sun4v_rtc_driver); | ||
| 145 | } | ||
| 146 | |||
| 147 | static void __exit sun4v_rtc_exit(void) | ||
| 148 | { | ||
| 149 | platform_driver_unregister(&sun4v_rtc_driver); | ||
| 150 | } | ||
| 151 | |||
| 152 | module_init(sun4v_rtc_init); | ||
| 153 | module_exit(sun4v_rtc_exit); | ||
