Skip to content

Commit

Permalink
rtc: fall back to requesting only the ports we actually use
Browse files Browse the repository at this point in the history
Firmware like PNPBIOS or ACPI can report the address space consumed by the
RTC.  The actual space consumed may be less than the size (RTC_IO_EXTENT)
assumed by the RTC driver.

The PNP core doesn't request resources yet, but I'd like to make it do so.
If/when it does, the RTC_IO_EXTENT request may fail, which prevents the RTC
driver from loading.

Since we only use the RTC index and data registers at RTC_PORT(0) and
RTC_PORT(1), we can fall back to requesting just enough space for those.

If the PNP core requests resources, this results in typical I/O port usage
like this:

    0070-0073 : 00:06		<-- PNP device 00:06 responds to 70-73
      0070-0071 : rtc		<-- RTC driver uses only 70-71

instead of the current:

    0070-0077 : rtc		<-- RTC_IO_EXTENT == 8

Signed-off-by: Bjorn Helgaas <[email protected]>
Cc: Alessandro Zummo <[email protected]>
Cc: David Brownell <[email protected]>
Cc: Ralf Baechle <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Bjorn Helgaas authored and Linus Torvalds committed Nov 15, 2007
1 parent 4c06be1 commit 9626f1f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
36 changes: 30 additions & 6 deletions drivers/char/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,12 +918,29 @@ static const struct file_operations rtc_proc_fops = {
};
#endif

static resource_size_t rtc_size;

static struct resource * __init rtc_request_region(resource_size_t size)
{
struct resource *r;

if (RTC_IOMAPPED)
r = request_region(RTC_PORT(0), size, "rtc");
else
r = request_mem_region(RTC_PORT(0), size, "rtc");

if (r)
rtc_size = size;

return r;
}

static void rtc_release_region(void)
{
if (RTC_IOMAPPED)
release_region(RTC_PORT(0), RTC_IO_EXTENT);
release_region(RTC_PORT(0), rtc_size);
else
release_mem_region(RTC_PORT(0), RTC_IO_EXTENT);
release_mem_region(RTC_PORT(0), rtc_size);
}

static int __init rtc_init(void)
Expand Down Expand Up @@ -976,10 +993,17 @@ static int __init rtc_init(void)
}
no_irq:
#else
if (RTC_IOMAPPED)
r = request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
else
r = request_mem_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
r = rtc_request_region(RTC_IO_EXTENT);

/*
* If we've already requested a smaller range (for example, because
* PNPBIOS or ACPI told us how the device is configured), the request
* above might fail because it's too big.
*
* If so, request just the range we actually use.
*/
if (!r)
r = rtc_request_region(RTC_IO_EXTENT_USED);
if (!r) {
#ifdef RTC_IRQ
rtc_has_irq = 0;
Expand Down
3 changes: 3 additions & 0 deletions include/linux/mc146818rtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,11 @@ struct cmos_rtc_board_info {
#ifndef ARCH_RTC_LOCATION /* Override by <asm/mc146818rtc.h>? */

#define RTC_IO_EXTENT 0x8
#define RTC_IO_EXTENT_USED 0x2
#define RTC_IOMAPPED 1 /* Default to I/O mapping. */

#else
#define RTC_IO_EXTENT_USED RTC_IO_EXTENT
#endif /* ARCH_RTC_LOCATION */

#endif /* _MC146818RTC_H */

0 comments on commit 9626f1f

Please sign in to comment.