From 63f83ebad921990694d019d89af0426a4c81269a Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 2 Oct 2012 22:03:21 +0000 Subject: 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 --- sys/dev/ata/ata-all.c | 9 +++++++++ sys/dev/ata/ata-all.h | 1 + sys/dev/ata/ata-sata.c | 21 +++++++++++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'sys/dev/ata') 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); -- cgit v1.1