summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-10-02 22:03:21 +0000
committermav <mav@FreeBSD.org>2012-10-02 22:03:21 +0000
commit63f83ebad921990694d019d89af0426a4c81269a (patch)
treec3c802ebee9675b618bf2ba179494cce0dc814ca /sys/dev/ata
parent4143500b7bd8c48ee7602a796783fc0a455a6d40 (diff)
downloadFreeBSD-src-63f83ebad921990694d019d89af0426a4c81269a.zip
FreeBSD-src-63f83ebad921990694d019d89af0426a4c81269a.tar.gz
Implement SATA revision (speed) control for legacy SATA controller for
both boot (via loader tunables) and run-time (via `camcontrol negotiate`). Tested to work at least on NVIDIA MCP55 chipset. H/w provided by: glebius
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/ata-all.c9
-rw-r--r--sys/dev/ata/ata-all.h1
-rw-r--r--sys/dev/ata/ata-sata.c21
3 files changed, 27 insertions, 4 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 07cb91f..e061744 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -172,6 +172,15 @@ ata_attach(device_t dev)
TASK_INIT(&ch->conntask, 0, ata_conn_event, dev);
#ifdef ATA_CAM
for (i = 0; i < 16; i++) {
+ ch->user[i].revision = 0;
+ snprintf(buf, sizeof(buf), "dev%d.sata_rev", i);
+ if (resource_int_value(device_get_name(dev),
+ device_get_unit(dev), buf, &mode) != 0 &&
+ resource_int_value(device_get_name(dev),
+ device_get_unit(dev), "sata_rev", &mode) != 0)
+ mode = -1;
+ if (mode >= 0)
+ ch->user[i].revision = mode;
ch->user[i].mode = 0;
snprintf(buf, sizeof(buf), "dev%d.mode", i);
if (resource_string_value(device_get_name(dev),
diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h
index 8209808..7154d56 100644
--- a/sys/dev/ata/ata-all.h
+++ b/sys/dev/ata/ata-all.h
@@ -142,6 +142,7 @@
#define ATA_SC_SPD_NO_SPEED 0x00000000
#define ATA_SC_SPD_SPEED_GEN1 0x00000010
#define ATA_SC_SPD_SPEED_GEN2 0x00000020
+#define ATA_SC_SPD_SPEED_GEN3 0x00000040
#define ATA_SC_IPM_MASK 0x00000f00
#define ATA_SC_IPM_NONE 0x00000000
diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c
index 465e4b2..931c60e 100644
--- a/sys/dev/ata/ata-sata.c
+++ b/sys/dev/ata/ata-sata.c
@@ -152,8 +152,12 @@ int
ata_sata_phy_reset(device_t dev, int port, int quick)
{
struct ata_channel *ch = device_get_softc(dev);
- int loop, retry;
- uint32_t val;
+ int loop, retry, sata_rev;
+ uint32_t val, val1;
+
+ sata_rev = ch->user[port < 0 ? 0 : port].revision;
+ if (sata_rev > 0)
+ quick = 0;
if (quick) {
if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
@@ -173,9 +177,18 @@ ata_sata_phy_reset(device_t dev, int port, int quick)
device_printf(dev, "p%d: hard reset ...\n", port);
}
}
+ if (sata_rev == 1)
+ val1 = ATA_SC_SPD_SPEED_GEN1;
+ else if (sata_rev == 2)
+ val1 = ATA_SC_SPD_SPEED_GEN2;
+ else if (sata_rev == 3)
+ val1 = ATA_SC_SPD_SPEED_GEN3;
+ else
+ val1 = 0;
for (retry = 0; retry < 10; retry++) {
for (loop = 0; loop < 10; loop++) {
- if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET))
+ if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET |
+ val1 | ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER))
goto fail;
ata_udelay(100);
if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
@@ -186,7 +199,7 @@ ata_sata_phy_reset(device_t dev, int port, int quick)
ata_udelay(5000);
for (loop = 0; loop < 10; loop++) {
if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
- ATA_SC_DET_IDLE | ((ch->pm_level > 0) ? 0 :
+ ATA_SC_DET_IDLE | val1 | ((ch->pm_level > 0) ? 0 :
ATA_SC_IPM_DIS_PARTIAL | ATA_SC_IPM_DIS_SLUMBER)))
goto fail;
ata_udelay(100);
OpenPOWER on IntegriCloud