summaryrefslogtreecommitdiffstats
path: root/sys/dev/mvs
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-06-12 11:08:51 +0000
committermav <mav@FreeBSD.org>2012-06-12 11:08:51 +0000
commit2836cfaf805f7b751e904f8f53aaf421aafdb66f (patch)
treeb5e94464d9d82884c3aa4443c18aa559bbf565e6 /sys/dev/mvs
parent813f2809c580633e12abec8bd0f7599ee0865661 (diff)
downloadFreeBSD-src-2836cfaf805f7b751e904f8f53aaf421aafdb66f.zip
FreeBSD-src-2836cfaf805f7b751e904f8f53aaf421aafdb66f.tar.gz
- Limit r214102 workaround to only x86. On arm it causes more problems
then solves because of cache coherency issues. This fixes periodic error messages on console and command timeouts. - Patch SATA PHY configuration for 65nm SoCs to improve SNR same as Linux does. MFC after: 2 weeks
Diffstat (limited to 'sys/dev/mvs')
-rw-r--r--sys/dev/mvs/mvs.c41
-rw-r--r--sys/dev/mvs/mvs.h5
-rw-r--r--sys/dev/mvs/mvs_soc.c2
3 files changed, 47 insertions, 1 deletions
diff --git a/sys/dev/mvs/mvs.c b/sys/dev/mvs/mvs.c
index 507c13f..21c9f97 100644
--- a/sys/dev/mvs/mvs.c
+++ b/sys/dev/mvs/mvs.c
@@ -1048,14 +1048,19 @@ mvs_crbq_intr(device_t dev)
* Handle only successfull completions here.
* Errors will be handled by main intr handler.
*/
+#if defined(__i386__) || defined(__amd64__)
if (crpb->id == 0xffff && crpb->rspflg == 0xffff) {
device_printf(dev, "Unfilled CRPB "
"%d (%d->%d) tag %d flags %04x rs %08x\n",
cin_idx, fin_idx, in_idx, slot, flags, ch->rslots);
- } else if (ch->numtslots != 0 ||
+ } else
+#endif
+ if (ch->numtslots != 0 ||
(flags & EDMA_IE_EDEVERR) == 0) {
+#if defined(__i386__) || defined(__amd64__)
crpb->id = 0xffff;
crpb->rspflg = 0xffff;
+#endif
if (ch->slot[slot].state >= MVS_SLOT_RUNNING) {
ccb = ch->slot[slot].ccb;
ccb->ataio.res.status =
@@ -1999,6 +2004,39 @@ mvs_reset_to(void *arg)
}
static void
+mvs_errata(device_t dev)
+{
+ struct mvs_channel *ch = device_get_softc(dev);
+ uint32_t val;
+
+ if (ch->quirks & MVS_Q_SOC65) {
+ val = ATA_INL(ch->r_mem, SATA_PHYM3);
+ val &= ~(0x3 << 27); /* SELMUPF = 1 */
+ val |= (0x1 << 27);
+ val &= ~(0x3 << 29); /* SELMUPI = 1 */
+ val |= (0x1 << 29);
+ ATA_OUTL(ch->r_mem, SATA_PHYM3, val);
+
+ val = ATA_INL(ch->r_mem, SATA_PHYM4);
+ val &= ~0x1; /* SATU_OD8 = 0 */
+ val |= (0x1 << 16); /* reserved bit 16 = 1 */
+ ATA_OUTL(ch->r_mem, SATA_PHYM4, val);
+
+ val = ATA_INL(ch->r_mem, SATA_PHYM9_GEN2);
+ val &= ~0xf; /* TXAMP[3:0] = 8 */
+ val |= 0x8;
+ val &= ~(0x1 << 14); /* TXAMP[4] = 0 */
+ ATA_OUTL(ch->r_mem, SATA_PHYM9_GEN2, val);
+
+ val = ATA_INL(ch->r_mem, SATA_PHYM9_GEN1);
+ val &= ~0xf; /* TXAMP[3:0] = 8 */
+ val |= 0x8;
+ val &= ~(0x1 << 14); /* TXAMP[4] = 0 */
+ ATA_OUTL(ch->r_mem, SATA_PHYM9_GEN1, val);
+ }
+}
+
+static void
mvs_reset(device_t dev)
{
struct mvs_channel *ch = device_get_softc(dev);
@@ -2044,6 +2082,7 @@ mvs_reset(device_t dev)
ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EATARST);
DELAY(25);
ATA_OUTL(ch->r_mem, EDMA_CMD, 0);
+ mvs_errata(dev);
/* Reset and reconnect PHY, */
if (!mvs_sata_phy_reset(dev)) {
if (bootverbose)
diff --git a/sys/dev/mvs/mvs.h b/sys/dev/mvs/mvs.h
index f4e4a61..4938fb4 100644
--- a/sys/dev/mvs/mvs.h
+++ b/sys/dev/mvs/mvs.h
@@ -382,6 +382,10 @@
#define SATA_FISDW5 0x384 /* FIS DW5 */
#define SATA_FISDW6 0x388 /* FIS DW6 */
+#define SATA_PHYM9_GEN2 0x398
+#define SATA_PHYM9_GEN1 0x39c
+#define SATA_PHYCFG_OFS 0x3a0 /* 65nm SoCs only */
+
#define MVS_MAX_PORTS 8
#define MVS_MAX_SLOTS 32
@@ -537,6 +541,7 @@ struct mvs_channel {
#define MVS_Q_GENIIE 4
#define MVS_Q_SOC 8
#define MVS_Q_CT 16
+#define MVS_Q_SOC65 32
int pm_level; /* power management level */
struct mvs_slot slot[MVS_MAX_SLOTS];
diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c
index 19fe51f..9e9f93e 100644
--- a/sys/dev/mvs/mvs_soc.c
+++ b/sys/dev/mvs/mvs_soc.c
@@ -135,6 +135,8 @@ mvs_attach(device_t dev)
if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&ctlr->r_rid, RF_ACTIVE)))
return ENXIO;
+ if (ATA_INL(ctlr->r_mem, PORT_BASE(0) + SATA_PHYCFG_OFS) != 0)
+ ctlr->quirks |= MVS_Q_SOC65;
/* Setup our own memory management for channels. */
ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
OpenPOWER on IntegriCloud