AHCI: Fix AHCI driver for ARM.

On ARM, we must ensure proper interdevice write ordering.
The AHCI interrupt status register must be updated in HW before
registers in interrupt controller.
Unfortunately, only way how we can do it is readback.

Discussed with:	mav
Approved by:	kib (mentor)
Differential Revision: https://reviews.freebsd.org/D4240
This commit is contained in:
Michal Meloun 2015-11-29 11:28:04 +00:00
parent 7c259020fb
commit d3214e8d6d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=291444
2 changed files with 17 additions and 0 deletions

View File

@ -483,6 +483,7 @@ ahci_intr(void *data)
/* AHCI declares level triggered IS. */
if (!(ctlr->quirks & AHCI_Q_EDGEIS))
ATA_OUTL(ctlr->r_mem, AHCI_IS, is);
ATA_RBL(ctlr->r_mem, AHCI_IS);
}
/*
@ -501,6 +502,7 @@ ahci_intr_one(void *data)
ctlr->interrupt[unit].function(arg);
/* AHCI declares level triggered IS. */
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
ATA_RBL(ctlr->r_mem, AHCI_IS);
}
static void
@ -516,6 +518,7 @@ ahci_intr_one_edge(void *data)
ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
if ((arg = ctlr->interrupt[unit].argument))
ctlr->interrupt[unit].function(arg);
ATA_RBL(ctlr->r_mem, AHCI_IS);
}
struct resource *

View File

@ -562,6 +562,20 @@ enum ahci_err_type {
#define ATA_OUTSL_STRM(res, offset, addr, count) \
bus_write_multi_stream_4((res), (offset), (addr), (count))
/*
* On some platforms, we must ensure proper interdevice write ordering.
* The AHCI interrupt status register must be updated in HW before
* registers in interrupt controller.
* Unfortunately, only way how we can do it is readback.
*
* Currently, only ARM is known to have this issue.
*/
#if defined(__arm__)
#define ATA_RBL(res, offset) \
bus_read_4((res), (offset))
#else
#define ATA_RBL(res, offset)
#endif
#define AHCI_Q_NOFORCE 0x00000001
#define AHCI_Q_NOPMP 0x00000002