Commit 6ab9028d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata

Pull libata fixes from Tejun Heo:
 "Mostly device-specific fixes.  The only thing which isn't is the fix
  for zpodd oops-on-detach bug"

* 'for-3.15-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  ahci: imx: PLL clock needs 100us to settle down
  ata: pata_at91 only works on sam9
  libata: clean up ZPODD when a port is detached
  ahci: imx: software workaround for phy reset issue in resume
  ahci: imx: add namespace for register enums
  ahci: disable DEVSLP for Intel Valleyview
parents 1f5518b4 3685f251
...@@ -815,7 +815,7 @@ config PATA_AT32 ...@@ -815,7 +815,7 @@ config PATA_AT32
config PATA_AT91 config PATA_AT91
tristate "PATA support for AT91SAM9260" tristate "PATA support for AT91SAM9260"
depends on ARM && ARCH_AT91 depends on ARM && SOC_AT91SAM9
help help
This option enables support for IDE devices on the Atmel AT91SAM9260 SoC. This option enables support for IDE devices on the Atmel AT91SAM9260 SoC.
......
...@@ -1115,6 +1115,17 @@ static bool ahci_broken_online(struct pci_dev *pdev) ...@@ -1115,6 +1115,17 @@ static bool ahci_broken_online(struct pci_dev *pdev)
return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff); return pdev->bus->number == (val >> 8) && pdev->devfn == (val & 0xff);
} }
static bool ahci_broken_devslp(struct pci_dev *pdev)
{
/* device with broken DEVSLP but still showing SDS capability */
static const struct pci_device_id ids[] = {
{ PCI_VDEVICE(INTEL, 0x0f23)}, /* Valleyview SoC */
{}
};
return pci_match_id(ids, pdev);
}
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
static void ahci_gtf_filter_workaround(struct ata_host *host) static void ahci_gtf_filter_workaround(struct ata_host *host)
{ {
...@@ -1364,6 +1375,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1364,6 +1375,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
/* must set flag prior to save config in order to take effect */
if (ahci_broken_devslp(pdev))
hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
/* save initial config */ /* save initial config */
ahci_pci_save_initial_config(pdev, hpriv); ahci_pci_save_initial_config(pdev, hpriv);
......
...@@ -236,6 +236,7 @@ enum { ...@@ -236,6 +236,7 @@ enum {
port start (wait until port start (wait until
error-handling stage) */ error-handling stage) */
AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */ AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */
AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
/* ap->flags bits */ /* ap->flags bits */
......
...@@ -29,9 +29,25 @@ ...@@ -29,9 +29,25 @@
#include "ahci.h" #include "ahci.h"
enum { enum {
PORT_PHY_CTL = 0x178, /* Port0 PHY Control */ /* Timer 1-ms Register */
PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */ IMX_TIMER1MS = 0x00e0,
HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ /* Port0 PHY Control Register */
IMX_P0PHYCR = 0x0178,
IMX_P0PHYCR_TEST_PDDQ = 1 << 20,
IMX_P0PHYCR_CR_READ = 1 << 19,
IMX_P0PHYCR_CR_WRITE = 1 << 18,
IMX_P0PHYCR_CR_CAP_DATA = 1 << 17,
IMX_P0PHYCR_CR_CAP_ADDR = 1 << 16,
/* Port0 PHY Status Register */
IMX_P0PHYSR = 0x017c,
IMX_P0PHYSR_CR_ACK = 1 << 18,
IMX_P0PHYSR_CR_DATA_OUT = 0xffff << 0,
/* Lane0 Output Status Register */
IMX_LANE0_OUT_STAT = 0x2003,
IMX_LANE0_OUT_STAT_RX_PLL_STATE = 1 << 1,
/* Clock Reset Register */
IMX_CLOCK_RESET = 0x7f3f,
IMX_CLOCK_RESET_RESET = 1 << 0,
}; };
enum ahci_imx_type { enum ahci_imx_type {
...@@ -54,9 +70,149 @@ MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support ...@@ -54,9 +70,149 @@ MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support
static void ahci_imx_host_stop(struct ata_host *host); static void ahci_imx_host_stop(struct ata_host *host);
static int imx_phy_crbit_assert(void __iomem *mmio, u32 bit, bool assert)
{
int timeout = 10;
u32 crval;
u32 srval;
/* Assert or deassert the bit */
crval = readl(mmio + IMX_P0PHYCR);
if (assert)
crval |= bit;
else
crval &= ~bit;
writel(crval, mmio + IMX_P0PHYCR);
/* Wait for the cr_ack signal */
do {
srval = readl(mmio + IMX_P0PHYSR);
if ((assert ? srval : ~srval) & IMX_P0PHYSR_CR_ACK)
break;
usleep_range(100, 200);
} while (--timeout);
return timeout ? 0 : -ETIMEDOUT;
}
static int imx_phy_reg_addressing(u16 addr, void __iomem *mmio)
{
u32 crval = addr;
int ret;
/* Supply the address on cr_data_in */
writel(crval, mmio + IMX_P0PHYCR);
/* Assert the cr_cap_addr signal */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, true);
if (ret)
return ret;
/* Deassert cr_cap_addr */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_ADDR, false);
if (ret)
return ret;
return 0;
}
static int imx_phy_reg_write(u16 val, void __iomem *mmio)
{
u32 crval = val;
int ret;
/* Supply the data on cr_data_in */
writel(crval, mmio + IMX_P0PHYCR);
/* Assert the cr_cap_data signal */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, true);
if (ret)
return ret;
/* Deassert cr_cap_data */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_CAP_DATA, false);
if (ret)
return ret;
if (val & IMX_CLOCK_RESET_RESET) {
/*
* In case we're resetting the phy, it's unable to acknowledge,
* so we return immediately here.
*/
crval |= IMX_P0PHYCR_CR_WRITE;
writel(crval, mmio + IMX_P0PHYCR);
goto out;
}
/* Assert the cr_write signal */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, true);
if (ret)
return ret;
/* Deassert cr_write */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_WRITE, false);
if (ret)
return ret;
out:
return 0;
}
static int imx_phy_reg_read(u16 *val, void __iomem *mmio)
{
int ret;
/* Assert the cr_read signal */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, true);
if (ret)
return ret;
/* Capture the data from cr_data_out[] */
*val = readl(mmio + IMX_P0PHYSR) & IMX_P0PHYSR_CR_DATA_OUT;
/* Deassert cr_read */
ret = imx_phy_crbit_assert(mmio, IMX_P0PHYCR_CR_READ, false);
if (ret)
return ret;
return 0;
}
static int imx_sata_phy_reset(struct ahci_host_priv *hpriv)
{
void __iomem *mmio = hpriv->mmio;
int timeout = 10;
u16 val;
int ret;
/* Reset SATA PHY by setting RESET bit of PHY register CLOCK_RESET */
ret = imx_phy_reg_addressing(IMX_CLOCK_RESET, mmio);
if (ret)
return ret;
ret = imx_phy_reg_write(IMX_CLOCK_RESET_RESET, mmio);
if (ret)
return ret;
/* Wait for PHY RX_PLL to be stable */
do {
usleep_range(100, 200);
ret = imx_phy_reg_addressing(IMX_LANE0_OUT_STAT, mmio);
if (ret)
return ret;
ret = imx_phy_reg_read(&val, mmio);
if (ret)
return ret;
if (val & IMX_LANE0_OUT_STAT_RX_PLL_STATE)
break;
} while (--timeout);
return timeout ? 0 : -ETIMEDOUT;
}
static int imx_sata_enable(struct ahci_host_priv *hpriv) static int imx_sata_enable(struct ahci_host_priv *hpriv)
{ {
struct imx_ahci_priv *imxpriv = hpriv->plat_data; struct imx_ahci_priv *imxpriv = hpriv->plat_data;
struct device *dev = &imxpriv->ahci_pdev->dev;
int ret; int ret;
if (imxpriv->no_device) if (imxpriv->no_device)
...@@ -101,6 +257,14 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv) ...@@ -101,6 +257,14 @@ static int imx_sata_enable(struct ahci_host_priv *hpriv)
regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13, regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
IMX6Q_GPR13_SATA_MPLL_CLK_EN, IMX6Q_GPR13_SATA_MPLL_CLK_EN,
IMX6Q_GPR13_SATA_MPLL_CLK_EN); IMX6Q_GPR13_SATA_MPLL_CLK_EN);
usleep_range(100, 200);
ret = imx_sata_phy_reset(hpriv);
if (ret) {
dev_err(dev, "failed to reset phy: %d\n", ret);
goto disable_regulator;
}
} }
usleep_range(1000, 2000); usleep_range(1000, 2000);
...@@ -156,8 +320,8 @@ static void ahci_imx_error_handler(struct ata_port *ap) ...@@ -156,8 +320,8 @@ static void ahci_imx_error_handler(struct ata_port *ap)
* without full reset once the pddq mode is enabled making it * without full reset once the pddq mode is enabled making it
* impossible to use as part of libata LPM. * impossible to use as part of libata LPM.
*/ */
reg_val = readl(mmio + PORT_PHY_CTL); reg_val = readl(mmio + IMX_P0PHYCR);
writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL); writel(reg_val | IMX_P0PHYCR_TEST_PDDQ, mmio + IMX_P0PHYCR);
imx_sata_disable(hpriv); imx_sata_disable(hpriv);
imxpriv->no_device = true; imxpriv->no_device = true;
} }
...@@ -217,6 +381,7 @@ static int imx_ahci_probe(struct platform_device *pdev) ...@@ -217,6 +381,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
if (!imxpriv) if (!imxpriv)
return -ENOMEM; return -ENOMEM;
imxpriv->ahci_pdev = pdev;
imxpriv->no_device = false; imxpriv->no_device = false;
imxpriv->first_time = true; imxpriv->first_time = true;
imxpriv->type = (enum ahci_imx_type)of_id->data; imxpriv->type = (enum ahci_imx_type)of_id->data;
...@@ -248,7 +413,7 @@ static int imx_ahci_probe(struct platform_device *pdev) ...@@ -248,7 +413,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
/* /*
* Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL, * Configure the HWINIT bits of the HOST_CAP and HOST_PORTS_IMPL,
* and IP vendor specific register HOST_TIMER1MS. * and IP vendor specific register IMX_TIMER1MS.
* Configure CAP_SSS (support stagered spin up). * Configure CAP_SSS (support stagered spin up).
* Implement the port0. * Implement the port0.
* Get the ahb clock rate, and configure the TIMER1MS register. * Get the ahb clock rate, and configure the TIMER1MS register.
...@@ -265,7 +430,7 @@ static int imx_ahci_probe(struct platform_device *pdev) ...@@ -265,7 +430,7 @@ static int imx_ahci_probe(struct platform_device *pdev)
} }
reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000; reg_val = clk_get_rate(imxpriv->ahb_clk) / 1000;
writel(reg_val, hpriv->mmio + HOST_TIMER1MS); writel(reg_val, hpriv->mmio + IMX_TIMER1MS);
ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0); ret = ahci_platform_init_host(pdev, hpriv, &ahci_imx_port_info, 0, 0);
if (ret) if (ret)
......
...@@ -452,6 +452,13 @@ void ahci_save_initial_config(struct device *dev, ...@@ -452,6 +452,13 @@ void ahci_save_initial_config(struct device *dev,
cap &= ~HOST_CAP_SNTF; cap &= ~HOST_CAP_SNTF;
} }
if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) {
dev_info(dev,
"controller can't do DEVSLP, turning off\n");
cap2 &= ~HOST_CAP2_SDS;
cap2 &= ~HOST_CAP2_SADM;
}
if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) { if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
dev_info(dev, "controller can do FBS, turning on CAP_FBS\n"); dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
cap |= HOST_CAP_FBS; cap |= HOST_CAP_FBS;
......
...@@ -6314,6 +6314,8 @@ int ata_host_activate(struct ata_host *host, int irq, ...@@ -6314,6 +6314,8 @@ int ata_host_activate(struct ata_host *host, int irq,
static void ata_port_detach(struct ata_port *ap) static void ata_port_detach(struct ata_port *ap)
{ {
unsigned long flags; unsigned long flags;
struct ata_link *link;
struct ata_device *dev;
if (!ap->ops->error_handler) if (!ap->ops->error_handler)
goto skip_eh; goto skip_eh;
...@@ -6333,6 +6335,13 @@ static void ata_port_detach(struct ata_port *ap) ...@@ -6333,6 +6335,13 @@ static void ata_port_detach(struct ata_port *ap)
cancel_delayed_work_sync(&ap->hotplug_task); cancel_delayed_work_sync(&ap->hotplug_task);
skip_eh: skip_eh:
/* clean up zpodd on port removal */
ata_for_each_link(link, ap, HOST_FIRST) {
ata_for_each_dev(dev, link, ALL) {
if (zpodd_dev_enabled(dev))
zpodd_exit(dev);
}
}
if (ap->pmp_link) { if (ap->pmp_link) {
int i; int i;
for (i = 0; i < SATA_PMP_MAX_PORTS; i++) for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment