Commit 38e0e8c0 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Linus Torvalds

[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: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: default avatarMartin Michlmayr <tbm@cyrius.com>
Cc: Paul Gortmaker <penguin@muskoka.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 06c67bef
...@@ -46,13 +46,12 @@ ...@@ -46,13 +46,12 @@
* 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init * 1.11a Daniele Bellucci: Audit create_proc_read_entry in rtc_init
* 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer * 1.12 Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
* CONFIG_HPET_EMULATE_RTC * CONFIG_HPET_EMULATE_RTC
* 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly.
* 1.12ac Alan Cox: Allow read access to the day of week register * 1.12ac Alan Cox: Allow read access to the day of week register
*/ */
#define RTC_VERSION "1.12ac" #define RTC_VERSION "1.12ac"
#define RTC_IO_EXTENT 0x8
/* /*
* Note that *all* calls to CMOS_READ and CMOS_WRITE are done with * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
* interrupts disabled. Due to the index-port/data-port (0x70/0x71) * 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,7 +336,15 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
if (rtc_has_irq == 0) if (rtc_has_irq == 0)
return -EIO; return -EIO;
if (count < sizeof(unsigned)) /*
* Historically this function used to assume that sizeof(unsigned long)
* is the same in userspace and kernelspace. This lead to problems
* for configurations with multiple ABIs such a the MIPS o32 and 64
* ABIs supported on the same kernel. So now we support read of both
* 4 and 8 bytes and assume that's the sizeof(unsigned long) in the
* userspace ABI.
*/
if (count != sizeof(unsigned int) && count != sizeof(unsigned long))
return -EINVAL; return -EINVAL;
add_wait_queue(&rtc_wait, &wait); add_wait_queue(&rtc_wait, &wait);
...@@ -368,10 +375,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf, ...@@ -368,10 +375,12 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
schedule(); schedule();
} while (1); } while (1);
if (count < sizeof(unsigned long)) if (count == sizeof(unsigned int))
retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int); retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
else else
retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long); retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long);
if (!retval)
retval = count;
out: out:
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
remove_wait_queue(&rtc_wait, &wait); remove_wait_queue(&rtc_wait, &wait);
...@@ -923,6 +932,9 @@ static int __init rtc_init(void) ...@@ -923,6 +932,9 @@ static int __init rtc_init(void)
struct sparc_isa_device *isa_dev; struct sparc_isa_device *isa_dev;
#endif #endif
#endif #endif
#ifndef __sparc__
void *r;
#endif
#ifdef __sparc__ #ifdef __sparc__
for_each_ebus(ebus) { for_each_ebus(ebus) {
...@@ -964,8 +976,13 @@ found: ...@@ -964,8 +976,13 @@ found:
} }
no_irq: no_irq:
#else #else
if (!request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc")) { if (RTC_IOMAPPED)
printk(KERN_ERR "rtc: I/O port %d is not free.\n", RTC_PORT (0)); r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
else
r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
if (!r) {
printk(KERN_ERR "rtc: I/O resource %lx is not free.\n",
(long)(RTC_PORT(0)));
return -EIO; return -EIO;
} }
...@@ -979,7 +996,10 @@ no_irq: ...@@ -979,7 +996,10 @@ no_irq:
if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) { if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */ /* Yeah right, seeing as irq 8 doesn't even hit the bus. */
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
if (RTC_IOMAPPED)
release_region(RTC_PORT(0), RTC_IO_EXTENT); release_region(RTC_PORT(0), RTC_IO_EXTENT);
else
release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
return -EIO; return -EIO;
} }
hpet_rtc_timer_init(); hpet_rtc_timer_init();
...@@ -1079,7 +1099,10 @@ static void __exit rtc_exit (void) ...@@ -1079,7 +1099,10 @@ static void __exit rtc_exit (void)
if (rtc_has_irq) if (rtc_has_irq)
free_irq (rtc_irq, &rtc_port); free_irq (rtc_irq, &rtc_port);
#else #else
release_region (RTC_PORT (0), RTC_IO_EXTENT); if (RTC_IOMAPPED)
release_region(RTC_PORT(0), RTC_IO_EXTENT);
else
release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
#ifdef RTC_IRQ #ifdef RTC_IRQ
if (rtc_has_irq) if (rtc_has_irq)
free_irq (RTC_IRQ, NULL); free_irq (RTC_IRQ, NULL);
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
extern volatile u8 *dec_rtc_base; extern volatile u8 *dec_rtc_base;
#define ARCH_RTC_LOCATION
#define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base) #define RTC_PORT(x) CPHYSADDR((long)dec_rtc_base)
#define RTC_IO_EXTENT dec_kn_slot_size #define RTC_IO_EXTENT dec_kn_slot_size
#define RTC_IOMAPPED 0 #define RTC_IOMAPPED 0
......
...@@ -89,4 +89,11 @@ extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ ...@@ -89,4 +89,11 @@ extern spinlock_t rtc_lock; /* serialize CMOS RAM access */
# define RTC_VRT 0x80 /* valid RAM and time */ # define RTC_VRT 0x80 /* valid RAM and time */
/**********************************************************************/ /**********************************************************************/
#ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */
#define RTC_IO_EXTENT 0x8
#define RTC_IOMAPPED 1 /* Default to I/O mapping. */
#endif /* ARCH_RTC_LOCATION */
#endif /* _MC146818RTC_H */ #endif /* _MC146818RTC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment