diff options
Diffstat (limited to 'drivers/char/rtc.c')
| -rw-r--r-- | drivers/char/rtc.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index ec6b65ec69ea..0c66b802736a 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -918,6 +918,31 @@ static const struct file_operations rtc_proc_fops = { | |||
| 918 | }; | 918 | }; |
| 919 | #endif | 919 | #endif |
| 920 | 920 | ||
| 921 | static resource_size_t rtc_size; | ||
| 922 | |||
| 923 | static struct resource * __init rtc_request_region(resource_size_t size) | ||
| 924 | { | ||
| 925 | struct resource *r; | ||
| 926 | |||
| 927 | if (RTC_IOMAPPED) | ||
| 928 | r = request_region(RTC_PORT(0), size, "rtc"); | ||
| 929 | else | ||
| 930 | r = request_mem_region(RTC_PORT(0), size, "rtc"); | ||
| 931 | |||
| 932 | if (r) | ||
| 933 | rtc_size = size; | ||
| 934 | |||
| 935 | return r; | ||
| 936 | } | ||
| 937 | |||
| 938 | static void rtc_release_region(void) | ||
| 939 | { | ||
| 940 | if (RTC_IOMAPPED) | ||
| 941 | release_region(RTC_PORT(0), rtc_size); | ||
| 942 | else | ||
| 943 | release_mem_region(RTC_PORT(0), rtc_size); | ||
| 944 | } | ||
| 945 | |||
| 921 | static int __init rtc_init(void) | 946 | static int __init rtc_init(void) |
| 922 | { | 947 | { |
| 923 | #ifdef CONFIG_PROC_FS | 948 | #ifdef CONFIG_PROC_FS |
| @@ -968,10 +993,17 @@ found: | |||
| 968 | } | 993 | } |
| 969 | no_irq: | 994 | no_irq: |
| 970 | #else | 995 | #else |
| 971 | if (RTC_IOMAPPED) | 996 | r = rtc_request_region(RTC_IO_EXTENT); |
| 972 | r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); | 997 | |
| 973 | else | 998 | /* |
| 974 | r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc"); | 999 | * If we've already requested a smaller range (for example, because |
| 1000 | * PNPBIOS or ACPI told us how the device is configured), the request | ||
| 1001 | * above might fail because it's too big. | ||
| 1002 | * | ||
| 1003 | * If so, request just the range we actually use. | ||
| 1004 | */ | ||
| 1005 | if (!r) | ||
| 1006 | r = rtc_request_region(RTC_IO_EXTENT_USED); | ||
| 975 | if (!r) { | 1007 | if (!r) { |
| 976 | #ifdef RTC_IRQ | 1008 | #ifdef RTC_IRQ |
| 977 | rtc_has_irq = 0; | 1009 | rtc_has_irq = 0; |
| @@ -992,10 +1024,7 @@ no_irq: | |||
| 992 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ | 1024 | /* Yeah right, seeing as irq 8 doesn't even hit the bus. */ |
| 993 | rtc_has_irq = 0; | 1025 | rtc_has_irq = 0; |
| 994 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); | 1026 | printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ); |
| 995 | if (RTC_IOMAPPED) | 1027 | rtc_release_region(); |
| 996 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 997 | else | ||
| 998 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 999 | return -EIO; | 1028 | return -EIO; |
| 1000 | } | 1029 | } |
| 1001 | hpet_rtc_timer_init(); | 1030 | hpet_rtc_timer_init(); |
| @@ -1009,7 +1038,7 @@ no_irq: | |||
| 1009 | free_irq(RTC_IRQ, NULL); | 1038 | free_irq(RTC_IRQ, NULL); |
| 1010 | rtc_has_irq = 0; | 1039 | rtc_has_irq = 0; |
| 1011 | #endif | 1040 | #endif |
| 1012 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | 1041 | rtc_release_region(); |
| 1013 | return -ENODEV; | 1042 | return -ENODEV; |
| 1014 | } | 1043 | } |
| 1015 | 1044 | ||
| @@ -1091,10 +1120,7 @@ static void __exit rtc_exit (void) | |||
| 1091 | if (rtc_has_irq) | 1120 | if (rtc_has_irq) |
| 1092 | free_irq (rtc_irq, &rtc_port); | 1121 | free_irq (rtc_irq, &rtc_port); |
| 1093 | #else | 1122 | #else |
| 1094 | if (RTC_IOMAPPED) | 1123 | rtc_release_region(); |
| 1095 | release_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 1096 | else | ||
| 1097 | release_mem_region(RTC_PORT(0), RTC_IO_EXTENT); | ||
| 1098 | #ifdef RTC_IRQ | 1124 | #ifdef RTC_IRQ |
| 1099 | if (rtc_has_irq) | 1125 | if (rtc_has_irq) |
| 1100 | free_irq (RTC_IRQ, NULL); | 1126 | free_irq (RTC_IRQ, NULL); |
