Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 115911
b: refs/heads/master
c: c8fc40c
h: refs/heads/master
i:
  115909: c6d5374
  115907: a28e1d7
  115903: 38a8d5f
v: v3
  • Loading branch information
David Brownell authored and Linus Torvalds committed Oct 20, 2008
1 parent 68de8e2 commit 94e571d
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1f3ccaed13944b9cfa9af7f6c70bfb292e42a347
refs/heads/master: c8fc40cd345bfd88d8a98e7916909b9143502999
70 changes: 63 additions & 7 deletions trunk/drivers/rtc/rtc-cmos.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,43 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)

/*----------------------------------------------------------------*/

#ifdef RTC_PORT

/* Most newer x86 systems have two register banks, the first used
* for RTC and NVRAM and the second only for NVRAM. Caller must
* own rtc_lock ... and we won't worry about access during NMI.
*/
#define can_bank2 true

static inline unsigned char cmos_read_bank2(unsigned char addr)
{
outb(addr, RTC_PORT(2));
return inb(RTC_PORT(3));
}

static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
{
outb(addr, RTC_PORT(2));
outb(val, RTC_PORT(2));
}

#else

#define can_bank2 false

static inline unsigned char cmos_read_bank2(unsigned char addr)
{
return 0;
}

static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
{
}

#endif

/*----------------------------------------------------------------*/

static int cmos_read_time(struct device *dev, struct rtc_time *t)
{
/* REVISIT: if the clock has a "century" register, use
Expand Down Expand Up @@ -491,12 +528,21 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr,

if (unlikely(off >= attr->size))
return 0;
if (unlikely(off < 0))
return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;

off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++)
*buf++ = CMOS_READ(off);
for (retval = 0; count; count--, off++, retval++) {
if (off < 128)
*buf++ = CMOS_READ(off);
else if (can_bank2)
*buf++ = cmos_read_bank2(off);
else
break;
}
spin_unlock_irq(&rtc_lock);

return retval;
Expand All @@ -512,6 +558,8 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
if (unlikely(off >= attr->size))
return -EFBIG;
if (unlikely(off < 0))
return -EINVAL;
if ((off + count) > attr->size)
count = attr->size - off;

Expand All @@ -520,15 +568,20 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
* here. If userspace is smart enough to know what fields of
* NVRAM to update, updating checksums is also part of its job.
*/
off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) {
for (retval = 0; count; count--, off++, retval++) {
/* don't trash RTC registers */
if (off == cmos->day_alrm
|| off == cmos->mon_alrm
|| off == cmos->century)
buf++;
else
else if (off < 128)
CMOS_WRITE(*buf++, off);
else if (can_bank2)
cmos_write_bank2(*buf++, off);
else
break;
}
spin_unlock_irq(&rtc_lock);

Expand Down Expand Up @@ -631,8 +684,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)

/* Heuristic to deduce NVRAM size ... do what the legacy NVRAM
* driver did, but don't reject unknown configs. Old hardware
* won't address 128 bytes, and for now we ignore the way newer
* chips can address 256 bytes (using two more i/o ports).
* won't address 128 bytes. Newer chips have multiple banks,
* though they may not be listed in one I/O resource.
*/
#if defined(CONFIG_ATARI)
address_space = 64;
Expand All @@ -642,6 +695,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
#warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
address_space = 128;
#endif
if (can_bank2 && ports->end > (ports->start + 1))
address_space = 256;

/* For ACPI systems extension info comes from the FADT. On others,
* board specific setup provides it as appropriate. Systems where
Expand Down Expand Up @@ -740,7 +795,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup2;
}

pr_info("%s: alarms up to one %s%s%s\n",
pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n",
cmos_rtc.rtc->dev.bus_id,
is_valid_irq(rtc_irq)
? (cmos_rtc.mon_alrm
Expand All @@ -749,6 +804,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
? "month" : "day"))
: "no",
cmos_rtc.century ? ", y3k" : "",
nvram.size,
is_hpet_enabled() ? ", hpet irqs" : "");

return 0;
Expand Down

0 comments on commit 94e571d

Please sign in to comment.