[PATCH] libata: implement ata_wait_register()

As waiting for some register bits to change seems to be a common
operation shared by some controllers, implement helper function
ata_wait_register().  This function also takes care of register write
flushing.

Note that the condition is inverted, the wait is over when the masked
value does NOT match @val.  As we're waiting for bits to change, this
test is more powerful and allows the function to be used in more
places.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Tejun Heo 2006-04-11 22:22:29 +09:00 committed by Jeff Garzik
parent 643be977f9
commit c22daff410
2 changed files with 50 additions and 0 deletions

View file

@ -5029,6 +5029,52 @@ int ata_ratelimit(void)
return rc;
}
/**
* ata_wait_register - wait until register value changes
* @reg: IO-mapped register
* @mask: Mask to apply to read register value
* @val: Wait condition
* @interval_msec: polling interval in milliseconds
* @timeout_msec: timeout in milliseconds
*
* Waiting for some bits of register to change is a common
* operation for ATA controllers. This function reads 32bit LE
* IO-mapped register @reg and tests for the following condition.
*
* (*@reg & mask) != val
*
* If the condition is met, it returns; otherwise, the process is
* repeated after @interval_msec until timeout.
*
* LOCKING:
* Kernel thread context (may sleep)
*
* RETURNS:
* The final register value.
*/
u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
unsigned long interval_msec,
unsigned long timeout_msec)
{
unsigned long timeout;
u32 tmp;
tmp = ioread32(reg);
/* Calculate timeout _after_ the first read to make sure
* preceding writes reach the controller before starting to
* eat away the timeout.
*/
timeout = jiffies + (timeout_msec * HZ) / 1000;
while ((tmp & mask) == val && time_before(jiffies, timeout)) {
msleep(interval_msec);
tmp = ioread32(reg);
}
return tmp;
}
/*
* libata is essentially a library of internal helper functions for
* low-level ATA host controller drivers. As such, the API/ABI is
@ -5079,6 +5125,7 @@ EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_pair);
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);

View file

@ -543,6 +543,9 @@ extern unsigned int ata_busy_sleep(struct ata_port *ap,
unsigned long timeout);
extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
void *data, unsigned long delay);
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
unsigned long interval_msec,
unsigned long timeout_msec);
/*
* Default driver ops implementations