From 62ccc6118960204769809a1ea9d162cf2c1c95e1 Mon Sep 17 00:00:00 2001
From: peter chang <dpf@google.com>
Date: Tue, 14 Nov 2017 13:43:15 -0800
Subject: [PATCH] ahci: lewisburg MAP / PCS register handling
registers are now 32-bits and the existing offsets mean that the
wrong registers are being updated.
Change-Id: I992b31bc9e789f9dfbeb29afeb0b7777e325ea71
---
drivers/ata/ahci.c | 34 +++++++++++++++++++++++++++-------
drivers/ata/ahci.h | 4 ++++
drivers/ata/libahci.c | 19 +++++++++++++++++++
3 files changed, 50 insertions(+), 7 deletions(-)
@@ -71,6 +71,7 @@ enum board_ids {
/* board IDs for specific chipsets in alphabetical order */
board_ahci_avn,
+ board_ahci_lbg,
board_ahci_mcp65,
board_ahci_mcp77,
board_ahci_mcp89,
@@ -174,6 +175,14 @@ static const struct ata_port_info ahci_port_info[] = {
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_avn_ops,
},
+ [board_ahci_lbg] = {
+ AHCI_HFLAGS (AHCI_HFLAG_32BIT_MAP_PCS |
+ AHCI_HFLAG_PCI_PORT_MAP),
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_ops,
+ },
[board_ahci_mcp65] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
AHCI_HFLAG_YES_NCQ),
@@ -374,14 +383,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
- { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0x2823), board_ahci_lbg }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Lewisburg RAID*/
- { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa182), board_ahci_lbg }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d2), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa1d6), board_ahci }, /* Lewisburg RAID*/
- { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+ { PCI_VDEVICE(INTEL, 0xa202), board_ahci_lbg }, /* Lewisburg AHCI*/
{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
@@ -630,12 +639,23 @@ static int ahci_pci_reset_controller(struct ata_host *host)
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
struct ahci_host_priv *hpriv = host->private_data;
u16 tmp16;
+ u32 tmp32;
/* configure PCS */
- pci_read_config_word(pdev, 0x92, &tmp16);
- if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
- tmp16 |= hpriv->port_map;
- pci_write_config_word(pdev, 0x92, tmp16);
+ if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
+ pci_read_config_dword(pdev, 0x94, &tmp32);
+ else {
+ pci_read_config_word(pdev, 0x92, &tmp16);
+ tmp32 = tmp16;
+ }
+ if ((tmp32 & hpriv->port_map) != hpriv->port_map) {
+ tmp32 |= hpriv->port_map;
+ if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS)
+ pci_write_config_dword(pdev, 0x94, tmp32);
+ else {
+ tmp16 = tmp32;
+ pci_write_config_word(pdev, 0x92, tmp16);
+ }
}
}
@@ -251,6 +251,10 @@ enum {
AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */
AHCI_HFLAG_NO_WRITE_TO_RO = (1 << 24), /* don't write to read
only registers */
+ AHCI_HFLAG_32BIT_MAP_PCS = (1 << 25), /* MAP/PCS register
+ 32-bits wide */
+ AHCI_HFLAG_PCI_PORT_MAP = (1 << 26), /* port map in pci
+ config space */
/* ap->flags bits */
@@ -40,6 +40,7 @@
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
+#include <linux/pci.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
@@ -523,6 +524,24 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
port_map &= hpriv->mask_port_map;
}
+ if (hpriv->flags & AHCI_HFLAG_PCI_PORT_MAP) {
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u16 disabled;
+
+ if (hpriv->flags & AHCI_HFLAG_32BIT_MAP_PCS) {
+ u32 tmp;
+
+ pci_read_config_dword(pdev, 0x90, &tmp);
+ disabled = (tmp >> 16) & 0xffff;
+ } else {
+ pci_read_config_word(pdev, 0x90, &disabled);
+ disabled = (disabled >> 8) & 0xff;
+ }
+
+ dev_info(dev, "port_map:%x disabled:%x\n", port_map, disabled);
+ port_map &= ~disabled;
+ }
+
/* cross check port_map and cap.n_ports */
if (port_map) {
int map_ports = 0;
--
2.15.0.448.gf294e3d99a-goog