diff options
| -rw-r--r-- | drivers/char/rtc.c | 41 | ||||
| -rw-r--r-- | include/asm-mips/mach-dec/mc146818rtc.h | 2 | ||||
| -rw-r--r-- | include/linux/mc146818rtc.h | 7 |
3 files changed, 41 insertions, 9 deletions
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index cc7bd1a3095b..6ccc364c08df 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -46,13 +46,12 @@ | |||
| 46 | * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init | 46 | * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init |
| 47 | * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer | 47 | * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer |
| 48 | * CONFIG_HPET_EMULATE_RTC | 48 | * CONFIG_HPET_EMULATE_RTC |
| 49 | * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. | ||
| 49 | * 1.12ac Alan Cox: Allow read access to the day of week register | 50 | * 1.12ac Alan Cox: Allow read access to the day of week register |
| 50 | */ | 51 | */ |
| 51 | 52 | ||
| 52 | #define RTC_VERSION "1.12ac" | 53 | #define RTC_VERSION "1.12ac" |
| 53 | 54 | ||
| 54 | #define RTC_IO_EXTENT 0x8 | ||
| 55 | |||
| 56 | /* | 55 | /* |
| 57 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with | 56 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with |
| 58 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) | 57 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) |
| @@ -337,7 +336,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf, | |||
| 337 | if (rtc_has_irq == 0) | 336 | if (rtc_has_irq == 0) |
| 338 | return -EIO; | 337 | return -EIO; |
| 339 | 338 | ||
| 340 | if (count < sizeof(unsigned)) | 339 | /* |
| 340 | * Historically this function used to assume that sizeof(unsigned long) | ||
| 341 | * is the same in userspace and kernelspace. This lead to problems | ||
| 342 | * for configurations with multiple ABIs such a the MIPS o32 and 64 | ||
| 343 | * ABIs supported on the same kernel. So now we support read of both | ||
| 344 | * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the | ||
| 345 | * userspace ABI. | ||
| 346 | */ | ||
| 347 | if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) | ||
| 341 | return -EINVAL; | 348 | return -EINVAL; |
| 342 | 349 | ||
| 343 | add_wait_queue(&rtc_wait, &wait); | 350 | add_wait_queue(&rtc_wait, &wait); |
| @@ -368,10 +375,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf, | |||
| 368 | schedule(); | 375 | schedule(); |
| 369 | } while (1); | 376 | } while (1); |
| 370 | 377 | ||
| 371 | if (count < sizeof(unsigned long)) | 378 | if (count == sizeof(unsigned int)) |
| 372 | retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); | 379 | retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); |
| 373 | else | 380 | else |
| 374 | retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); | 381 | retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); |
| 382 | if (!retval) | ||
| 383 | retval = count; | ||
| 375 | out: | 384 | out: |
| 376 | current->state = TASK_RUNNING; | 385 | current->state = TASK_RUNNING; |
| 377 | remove_wait_queue(&rtc_wait, &wait); | 386 | remove_wait_queue(&rtc_wait, &wait); |
| @@ -923,6 +932,9 @@ static int __init rtc_init(void) | |||
| 923 | struct sparc_isa_device *isa_dev; | 932 | struct sparc_isa_device *isa_dev; |
| 924 | #endif | 933 | #endif |
| 925 | #endif | 934 | #endif |
| 935 | #ifndef __sparc__ | ||
| 936 | void *r; | ||
| 937 | #endif | ||
| 926 | 938 | ||
| 927 | #ifdef __sparc__ | 939 | #ifdef __sparc__ |
| 928 | for_each_ebus(ebus) { | 940 | for_each_ebus(ebus) { |
| @@ -964,8 +976,13 @@ found: | |||
| 964 | } | 976 | } |
| 965 | no_irq: | 977 | no_irq: |
| 966 | #else | 978 | #else |
| 967 | if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) { | 979 | if (RTC_IOMAPPED) |
| 968 | printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0)); | 980 | r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); |
| 981 | else | ||
| 982 | r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); | ||
| 983 | if (!r) { | ||
| 984 | printk(KERN_ERR "rtc: I/O resource %lx is not free.\n", | ||
| 985 | (long)(RTC_PORT(0))); | ||
| 969 | return -EIO; | 986 | return -EIO; |
| 970 | } | 987 | } |
| 971 | 988 | ||
| @@ -979,7 +996,10 @@ no_irq: | |||
| 979 | if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { | 996 | if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { |
| 980 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ | 997 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ |
| 981 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); | 998 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); |
| 982 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | 999 | if (RTC_IOMAPPED) |
| 1000 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 1001 | else | ||
| 1002 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 983 | return -EIO; | 1003 | return -EIO; |
| 984 | } | 1004 | } |
| 985 | hpet_rtc_timer_init(); | 1005 | hpet_rtc_timer_init(); |
| @@ -1079,7 +1099,10 @@ static void __exit rtc_exit (void) | |||
| 1079 | if (rtc_has_irq) | 1099 | if (rtc_has_irq) |
| 1080 | free_irq (rtc_irq, &rtc_port); | 1100 | free_irq (rtc_irq, &rtc_port); |
| 1081 | #else | 1101 | #else |
| 1082 | release_region (RTC_PORT (0), RTC_IO_EXTENT); | 1102 | if (RTC_IOMAPPED) |
| 1103 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 1104 | else | ||
| 1105 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 1083 | #ifdef RTC_IRQ | 1106 | #ifdef RTC_IRQ |
| 1084 | if (rtc_has_irq) | 1107 | if (rtc_has_irq) |
| 1085 | free_irq (RTC_IRQ, NULL); | 1108 | free_irq (RTC_IRQ, NULL); |
diff --git a/include/asm-mips/mach-dec/mc146818rtc.h b/include/asm-mips/mach-dec/mc146818rtc.h index 6d37a5675803..6724e99e43e1 100644 --- a/include/asm-mips/mach-dec/mc146818rtc.h +++ b/include/asm-mips/mach-dec/mc146818rtc.h | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | extern volatile u8 *dec_rtc_base; | 20 | extern volatile u8 *dec_rtc_base; |
| 21 | 21 | ||
| 22 | #define ARCH_RTC_LOCATION | ||
| 23 | |||
| 22 | #define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base) | 24 | #define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base) |
| 23 | #define RTC_IO_EXTENT dec_kn_slot_size | 25 | #define RTC_IO_EXTENT dec_kn_slot_size |
| 24 | #define RTC_IOMAPPED 0 | 26 | #define RTC_IOMAPPED 0 |
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h index bbc93ae217e1..432b2fa24929 100644 --- a/include/linux/mc146818rtc.h +++ b/include/linux/mc146818rtc.h | |||
| @@ -89,4 +89,11 @@ extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ | |||
| 89 | # define RTC_VRT 0x80 /* valid RAM and time */ | 89 | # define RTC_VRT 0x80 /* valid RAM and time */ |
| 90 | /**********************************************************************/ | 90 | /**********************************************************************/ |
| 91 | 91 | ||
| 92 | #ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */ | ||
| 93 | |||
| 94 | #define RTC_IO_EXTENT 0x8 | ||
| 95 | #define RTC_IOMAPPED 1 /* Default to I/O mapping. */ | ||
| 96 | |||
| 97 | #endif /* ARCH_RTC_LOCATION */ | ||
| 98 | |||
| 92 | #endif /* _MC146818RTC_H */ | 99 | #endif /* _MC146818RTC_H */ |
