Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] char/rtc: Handle memory-mapped chips properly

Handle memory-mapped chips properly, needed for example on DECstations.
This support was in Linux 2.4 but for some reason got lost in 2.6. This
patch is taken directly from the linux-mips repository.

[akpm@osdl.org: cleanup]
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Martin Michlmayr <tbm@cyrius.com>
Cc: Paul Gortmaker <penguin@muskoka.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Maciej W. Rozycki and committed by
Linus Torvalds
38e0e8c0 06c67bef

+41 -9
+32 -9
drivers/char/rtc.c
··· 46 46 * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init 47 47 * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer 48 48 * CONFIG_HPET_EMULATE_RTC 49 + * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. 49 50 * 1.12ac Alan Cox: Allow read access to the day of week register 50 51 */ 51 52 52 53 #define RTC_VERSION "1.12ac" 53 - 54 - #define RTC_IO_EXTENT 0x8 55 54 56 55 /* 57 56 * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with ··· 336 337 if (rtc_has_irq == 0) 337 338 return -EIO; 338 339 339 - if (count < sizeof(unsigned)) 340 + /* 341 + * Historically this function used to assume that sizeof(unsigned long) 342 + * is the same in userspace and kernelspace. This lead to problems 343 + * for configurations with multiple ABIs such a the MIPS o32 and 64 344 + * ABIs supported on the same kernel. So now we support read of both 345 + * 4 and 8 bytes and assume that's the sizeof(unsigned long) in the 346 + * userspace ABI. 347 + */ 348 + if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) 340 349 return -EINVAL; 341 350 342 351 add_wait_queue(&rtc_wait, &wait); ··· 375 368 schedule(); 376 369 } while (1); 377 370 378 - if (count < sizeof(unsigned long)) 379 - retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); 371 + if (count == sizeof(unsigned int)) 372 + retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); 380 373 else 381 374 retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); 375 + if (!retval) 376 + retval = count; 382 377 out: 383 378 current->state = TASK_RUNNING; 384 379 remove_wait_queue(&rtc_wait, &wait); ··· 932 923 struct sparc_isa_device *isa_dev; 933 924 #endif 934 925 #endif 926 + #ifndef __sparc__ 927 + void *r; 928 + #endif 935 929 936 930 #ifdef __sparc__ 937 931 for_each_ebus(ebus) { ··· 976 964 } 977 965 no_irq: 978 966 #else 979 - if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) { 980 - printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0)); 967 + if (RTC_IOMAPPED) 968 + r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); 969 + else 970 + r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); 971 + if (!r) { 972 + printk(KERN_ERR "rtc: I/O resource %lx is not free.\n", 973 + (long)(RTC_PORT(0))); 981 974 return -EIO; 982 975 } 983 976 ··· 996 979 if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { 997 980 /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ 998 981 printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); 999 - release_region(RTC_PORT(0), RTC_IO_EXTENT); 982 + if (RTC_IOMAPPED) 983 + release_region(RTC_PORT(0), RTC_IO_EXTENT); 984 + else 985 + release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); 1000 986 return -EIO; 1001 987 } 1002 988 hpet_rtc_timer_init(); ··· 1099 1079 if (rtc_has_irq) 1100 1080 free_irq (rtc_irq, &rtc_port); 1101 1081 #else 1102 - release_region (RTC_PORT (0), RTC_IO_EXTENT); 1082 + if (RTC_IOMAPPED) 1083 + release_region(RTC_PORT(0), RTC_IO_EXTENT); 1084 + else 1085 + release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); 1103 1086 #ifdef RTC_IRQ 1104 1087 if (rtc_has_irq) 1105 1088 free_irq (RTC_IRQ, NULL);
+2
include/asm-mips/mach-dec/mc146818rtc.h
··· 19 19 20 20 extern volatile u8 *dec_rtc_base; 21 21 22 + #define ARCH_RTC_LOCATION 23 + 22 24 #define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base) 23 25 #define RTC_IO_EXTENT dec_kn_slot_size 24 26 #define RTC_IOMAPPED 0
+7
include/linux/mc146818rtc.h
··· 89 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 99 #endif /* _MC146818RTC_H */