Commit fbd918a2 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull libata updates from Tejun Heo:
 "Support for some new embedded controllers.

  A couple late (<= a week) fixes have stable cc'd and one patch ("SATA:
  MV: Add support for the optional PHYs") got committed yesterday
  because otherwise the resulting kernel would fail boot on an embedded
  board due to interdependent changes in its platform tree.

  Other than that, nothing too noteworthy"

* 'for-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/libata:
  SATA: MV: Add support for the optional PHYs
  sata-highbank: Remove unnecessary ahci_platform.h include
  libata: disable LPM for some WD SATA-I devices
  ARM: mvebu: update the SATA compatible string for Armada 370/XP
  ata: sata_mv: fix disk hotplug for Armada 370/XP SoCs
  ata: sata_mv: introduce compatible string "marvell, armada-370-sata"
  ata: pata_samsung_cf: Remove unused macros
  ata: pata_samsung_cf: Use devm_ioremap_resource()
  ata: pata_samsung_cf: Merge pata_samsung_cf.h into pata_samsung_cf.c
  ata: pata_samsung_cf: Move plat/regs-ata.h to drivers/ata
  drivers: ata: Mark the function as static in libahci.c
  drivers: ata: Mark the function ahci_init_interrupts() as static in ahci.c
  ahci: imx: fix the error handling in imx_ahci_probe()
  ahci: imx: ahci_imx_softreset() can be static
  ahci: imx: Add i.MX53 support
  ahci: imx: Pull out the clock enable/disable calls
  libata, dt: Document sata_rcar bindings
  sata_rcar: Add R-Car Gen2 SATA PHY support
  ahci: mcp89: enter AHCI mode under Apple BIOS emulation
  ata: libata-eh: Remove unnecessary snprintf arithmetic
parents f075e0f6 b7db4f2e
* Marvell Orion SATA
Required Properties:
- compatibility : "marvell,orion-sata"
- compatibility : "marvell,orion-sata" or "marvell,armada-370-sata"
- reg : Address range of controller
- interrupts : Interrupt controller is using
- nr-ports : Number of SATA ports in use.
......
* Renesas R-Car SATA
Required properties:
- compatible : should contain one of the following:
- "renesas,sata-r8a7779" for R-Car H1
- "renesas,sata-r8a7790" for R-Car H2
- "renesas,sata-r8a7791" for R-Car M2
- reg : address and length of the SATA registers;
- interrupts : must consist of one interrupt specifier.
Example:
sata: sata@fc600000 {
compatible = "renesas,sata-r8a7779";
reg = <0xfc600000 0x2000>;
interrupt-parent = <&gic>;
interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -152,7 +152,7 @@ timer@20300 {
};
sata@a0000 {
compatible = "marvell,orion-sata";
compatible = "marvell,armada-370-sata";
reg = <0xa0000 0x5000>;
interrupts = <55>;
clocks = <&gateclk 15>, <&gateclk 30>;
......
/* linux/arch/arm/plat-samsung/include/plat/regs-ata.h
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung CF-ATA register definitions
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_PLAT_REGS_ATA_H
#define __ASM_PLAT_REGS_ATA_H __FILE__
#define S3C_CFATA_REG(x) (x)
#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
#define S3C_ATA_STATUS S3C_CFATA_REG(0x4)
#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
#define S3C_ATA_SWRST S3C_CFATA_REG(0xc)
#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
#define S3C_ATA_MDMA_TIME S3C_CFATA_REG(0x28)
#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
#define S3C_ATA_UDMA_TIME S3C_CFATA_REG(0x30)
#define S3C_ATA_XFR_NUM S3C_CFATA_REG(0x34)
#define S3C_ATA_XFR_CNT S3C_CFATA_REG(0x38)
#define S3C_ATA_TBUF_START S3C_CFATA_REG(0x3c)
#define S3C_ATA_TBUF_SIZE S3C_CFATA_REG(0x40)
#define S3C_ATA_SBUF_START S3C_CFATA_REG(0x44)
#define S3C_ATA_SBUF_SIZE S3C_CFATA_REG(0x48)
#define S3C_ATA_CADR_TBUF S3C_CFATA_REG(0x4c)
#define S3C_ATA_CADR_SBUF S3C_CFATA_REG(0x50)
#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
#define S3C_ATA_PIO_READY S3C_CFATA_REG(0x78)
#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
#define S3C_CFATA_MUX_TRUEIDE 0x01
#define S3C_ATA_CFG_SWAP 0x40
#define S3C_ATA_CFG_IORDYEN 0x02
#endif /* __ASM_PLAT_REGS_ATA_H */
......@@ -83,6 +83,8 @@ enum board_ids {
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
#ifdef CONFIG_PM
......@@ -664,6 +666,10 @@ static int ahci_pci_device_resume(struct pci_dev *pdev)
if (rc)
return rc;
/* Apple BIOS helpfully mangles the registers on resume */
if (is_mcp89_apple(pdev))
ahci_mcp89_apple_enable(pdev);
if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
rc = ahci_pci_reset_controller(host);
if (rc)
......@@ -780,6 +786,48 @@ static void ahci_p5wdh_workaround(struct ata_host *host)
}
}
/*
* Macbook7,1 firmware forcibly disables MCP89 AHCI and changes PCI ID when
* booting in BIOS compatibility mode. We restore the registers but not ID.
*/
static void ahci_mcp89_apple_enable(struct pci_dev *pdev)
{
u32 val;
printk(KERN_INFO "ahci: enabling MCP89 AHCI mode\n");
pci_read_config_dword(pdev, 0xf8, &val);
val |= 1 << 0x1b;
/* the following changes the device ID, but appears not to affect function */
/* val = (val & ~0xf0000000) | 0x80000000; */
pci_write_config_dword(pdev, 0xf8, val);
pci_read_config_dword(pdev, 0x54c, &val);
val |= 1 << 0xc;
pci_write_config_dword(pdev, 0x54c, val);
pci_read_config_dword(pdev, 0x4a4, &val);
val &= 0xff;
val |= 0x01060100;
pci_write_config_dword(pdev, 0x4a4, val);
pci_read_config_dword(pdev, 0x54c, &val);
val &= ~(1 << 0xc);
pci_write_config_dword(pdev, 0x54c, val);
pci_read_config_dword(pdev, 0xf8, &val);
val &= ~(1 << 0x1b);
pci_write_config_dword(pdev, 0xf8, val);
}
static bool is_mcp89_apple(struct pci_dev *pdev)
{
return pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
pdev->subsystem_device == 0xcb89;
}
/* only some SB600 ahci controllers can do 64bit DMA */
static bool ahci_sb600_enable_64bit(struct pci_dev *pdev)
{
......@@ -1100,7 +1148,7 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
{}
#endif
int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
static int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv)
{
int rc;
unsigned int maxvec;
......@@ -1212,15 +1260,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pdev->vendor == PCI_VENDOR_ID_MARVELL && !marvell_enable)
return -ENODEV;
/*
* For some reason, MCP89 on MacBook 7,1 doesn't work with
* ahci, use ata_generic instead.
*/
if (pdev->vendor == PCI_VENDOR_ID_NVIDIA &&
pdev->device == PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA &&
pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
pdev->subsystem_device == 0xcb89)
return -ENODEV;
/* Apple BIOS on MCP89 prevents us using AHCI */
if (is_mcp89_apple(pdev))
ahci_mcp89_apple_enable(pdev);
/* Promise's PDC42819 is a SAS/SATA controller that has an AHCI mode.
* At the moment, we can only use the AHCI mode. Let the users know
......
This diff is collapsed.
......@@ -221,13 +221,6 @@ static struct pci_device_id ata_generic[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), },
{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE),
.driver_data = ATA_GEN_FORCE_DMA },
/*
* For some reason, MCP89 on MacBook 7,1 doesn't work with
* ahci, use ata_generic instead.
*/
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP89_SATA,
PCI_VENDOR_ID_APPLE, 0xcb89,
.driver_data = ATA_GEN_FORCE_DMA },
#if !defined(CONFIG_PATA_TOSHIBA) && !defined(CONFIG_PATA_TOSHIBA_MODULE)
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), },
......
......@@ -1764,7 +1764,7 @@ static void ahci_handle_port_interrupt(struct ata_port *ap,
}
}
void ahci_port_intr(struct ata_port *ap)
static void ahci_port_intr(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
u32 status;
......@@ -1797,7 +1797,7 @@ irqreturn_t ahci_thread_fn(int irq, void *dev_instance)
}
EXPORT_SYMBOL_GPL(ahci_thread_fn);
void ahci_hw_port_interrupt(struct ata_port *ap)
static void ahci_hw_port_interrupt(struct ata_port *ap)
{
void __iomem *port_mmio = ahci_port_base(ap);
struct ahci_port_priv *pp = ap->private_data;
......
......@@ -2222,6 +2222,16 @@ int ata_dev_configure(struct ata_device *dev)
if (rc)
return rc;
/* some WD SATA-1 drives have issues with LPM, turn on NOLPM for them */
if ((dev->horkage & ATA_HORKAGE_WD_BROKEN_LPM) &&
(id[ATA_ID_SATA_CAPABILITY] & 0xe) == 0x2)
dev->horkage |= ATA_HORKAGE_NOLPM;
if (dev->horkage & ATA_HORKAGE_NOLPM) {
ata_dev_warn(dev, "LPM support broken, forcing max_power\n");
dev->link->ap->target_lpm_policy = ATA_LPM_MAX_POWER;
}
/* let ACPI work its magic */
rc = ata_acpi_on_devcfg(dev);
if (rc)
......@@ -4216,6 +4226,23 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "Micron_M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
{ "Crucial_CT???M500SSD1", NULL, ATA_HORKAGE_NO_NCQ_TRIM, },
/*
* Some WD SATA-I drives spin up and down erratically when the link
* is put into the slumber mode. We don't have full list of the
* affected devices. Disable LPM if the device matches one of the
* known prefixes and is SATA-1. As a side effect LPM partial is
* lost too.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=57211
*/
{ "WDC WD800JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD1200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD1600JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD2000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD2500JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD3000JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
{ "WDC WD3200JD-*", NULL, ATA_HORKAGE_WD_BROKEN_LPM },
/* End Marker */
{ }
};
......
......@@ -2402,7 +2402,7 @@ static void ata_eh_link_report(struct ata_link *link)
struct ata_port *ap = link->ap;
struct ata_eh_context *ehc = &link->eh_context;
const char *frozen, *desc;
char tries_buf[6];
char tries_buf[6] = "";
int tag, nr_failed = 0;
if (ehc->i.flags & ATA_EHI_QUIET)
......@@ -2433,9 +2433,8 @@ static void ata_eh_link_report(struct ata_link *link)
if (ap->pflags & ATA_PFLAG_FROZEN)
frozen = " frozen";
memset(tries_buf, 0, sizeof(tries_buf));
if (ap->eh_tries < ATA_EH_MAX_TRIES)
snprintf(tries_buf, sizeof(tries_buf) - 1, " t%d",
snprintf(tries_buf, sizeof(tries_buf), " t%d",
ap->eh_tries);
if (ehc->i.dev) {
......
......@@ -111,12 +111,14 @@ static const char *ata_lpm_policy_names[] = {
[ATA_LPM_MIN_POWER] = "min_power",
};
static ssize_t ata_scsi_lpm_store(struct device *dev,
static ssize_t ata_scsi_lpm_store(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct Scsi_Host *shost = class_to_shost(dev);
struct Scsi_Host *shost = class_to_shost(device);
struct ata_port *ap = ata_shost_to_port(shost);
struct ata_link *link;
struct ata_device *dev;
enum ata_lpm_policy policy;
unsigned long flags;
......@@ -132,10 +134,20 @@ static ssize_t ata_scsi_lpm_store(struct device *dev,
return -EINVAL;
spin_lock_irqsave(ap->lock, flags);
ata_for_each_link(link, ap, EDGE) {
ata_for_each_dev(dev, &ap->link, ENABLED) {
if (dev->horkage & ATA_HORKAGE_NOLPM) {
count = -EOPNOTSUPP;
goto out_unlock;
}
}
}
ap->target_lpm_policy = policy;
ata_port_schedule_eh(ap);
out_unlock:
spin_unlock_irqrestore(ap->lock, flags);
return count;
}
......
......@@ -24,11 +24,34 @@
#include <linux/slab.h>
#include <linux/platform_data/ata-samsung_cf.h>
#include <plat/regs-ata.h>
#define DRV_NAME "pata_samsung_cf"
#define DRV_VERSION "0.1"
#define S3C_CFATA_REG(x) (x)
#define S3C_CFATA_MUX S3C_CFATA_REG(0x0)
#define S3C_ATA_CTRL S3C_CFATA_REG(0x0)
#define S3C_ATA_CMD S3C_CFATA_REG(0x8)
#define S3C_ATA_IRQ S3C_CFATA_REG(0x10)
#define S3C_ATA_IRQ_MSK S3C_CFATA_REG(0x14)
#define S3C_ATA_CFG S3C_CFATA_REG(0x18)
#define S3C_ATA_PIO_TIME S3C_CFATA_REG(0x2c)
#define S3C_ATA_PIO_DTR S3C_CFATA_REG(0x54)
#define S3C_ATA_PIO_FED S3C_CFATA_REG(0x58)
#define S3C_ATA_PIO_SCR S3C_CFATA_REG(0x5c)
#define S3C_ATA_PIO_LLR S3C_CFATA_REG(0x60)
#define S3C_ATA_PIO_LMR S3C_CFATA_REG(0x64)
#define S3C_ATA_PIO_LHR S3C_CFATA_REG(0x68)
#define S3C_ATA_PIO_DVR S3C_CFATA_REG(0x6c)
#define S3C_ATA_PIO_CSD S3C_CFATA_REG(0x70)
#define S3C_ATA_PIO_DAD S3C_CFATA_REG(0x74)
#define S3C_ATA_PIO_RDATA S3C_CFATA_REG(0x7c)
#define S3C_CFATA_MUX_TRUEIDE 0x01
#define S3C_ATA_CFG_SWAP 0x40
#define S3C_ATA_CFG_IORDYEN 0x02
enum s3c_cpu_type {
TYPE_S3C64XX,
TYPE_S5PC100,
......@@ -495,22 +518,10 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
info->irq = platform_get_irq(pdev, 0);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(dev, "failed to get mem resource\n");
return -EINVAL;
}
if (!devm_request_mem_region(dev, res->start,
resource_size(res), DRV_NAME)) {
dev_err(dev, "error requesting register region\n");
return -EBUSY;
}
info->ide_addr = devm_ioremap(dev, res->start, resource_size(res));
if (!info->ide_addr) {
dev_err(dev, "failed to map IO base address\n");
return -ENOMEM;
}
info->ide_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(info->ide_addr))
return PTR_ERR(info->ide_addr);
info->clk = devm_clk_get(&pdev->dev, "cfcon");
if (IS_ERR(info->clk)) {
......
......@@ -29,7 +29,6 @@
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/libata.h>
#include <linux/ahci_platform.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/export.h>
......
......@@ -60,6 +60,7 @@
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
#include <linux/mbus.h>
......@@ -304,6 +305,7 @@ enum {
MV5_LTMODE = 0x30,
MV5_PHY_CTL = 0x0C,
SATA_IFCFG = 0x050,
LP_PHY_CTL = 0x058,
MV_M2_PREAMP_MASK = 0x7e0,
......@@ -431,6 +433,7 @@ enum {
MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */
MV_HP_FIX_LP_PHY_CTL = (1 << 13), /* fix speed in LP_PHY_CTL ? */
/* Port private flags (pp_flags) */
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
......@@ -562,6 +565,12 @@ struct mv_host_priv {
*/
struct clk *clk;
struct clk **port_clks;
/*
* Some devices have a SATA PHY which can be enabled/disabled
* in order to save power. These are optional: if the platform
* devices does not have any phy, they won't be used.
*/
struct phy **port_phys;
/*
* These consistent DMA memory pools give us guaranteed
* alignment for hardware-accessed data structures,
......@@ -1358,6 +1367,7 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
if (ofs != 0xffffffffU) {
void __iomem *addr = mv_ap_base(link->ap) + ofs;
struct mv_host_priv *hpriv = link->ap->host->private_data;
if (sc_reg_in == SCR_CONTROL) {
/*
* Workaround for 88SX60x1 FEr SATA#26:
......@@ -1374,6 +1384,18 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
*/
if ((val & 0xf) == 1 || (readl(addr) & 0xf) == 1)
val |= 0xf000;
if (hpriv->hp_flags & MV_HP_FIX_LP_PHY_CTL) {
void __iomem *lp_phy_addr =
mv_ap_base(link->ap) + LP_PHY_CTL;
/*
* Set PHY speed according to SControl speed.
*/
if ((val & 0xf0) == 0x10)
writelfl(0x7, lp_phy_addr);
else
writelfl(0x227, lp_phy_addr);
}
}
writelfl(val, addr);
return 0;
......@@ -4076,6 +4098,11 @@ static int mv_platform_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!hpriv->port_clks)
return -ENOMEM;
hpriv->port_phys = devm_kzalloc(&pdev->dev,
sizeof(struct phy *) * n_ports,
GFP_KERNEL);
if (!hpriv->port_phys)
return -ENOMEM;
host->private_data = hpriv;
hpriv->n_ports = n_ports;
hpriv->board_idx = chip_soc;
......@@ -4097,6 +4124,17 @@ static int mv_platform_probe(struct platform_device *pdev)
hpriv->port_clks[port] = clk_get(&pdev->dev, port_number);
if (!IS_ERR(hpriv->port_clks[port]))
clk_prepare_enable(hpriv->port_clks[port]);
sprintf(port_number, "port%d", port);
hpriv->port_phys[port] = devm_phy_get(&pdev->dev, port_number);
if (IS_ERR(hpriv->port_phys[port])) {
rc = PTR_ERR(hpriv->port_phys[port]);
hpriv->port_phys[port] = NULL;
if ((rc != -EPROBE_DEFER) && (rc != -ENODEV))
dev_warn(&pdev->dev, "error getting phy");
goto err;
} else
phy_power_on(hpriv->port_phys[port]);
}
/*
......@@ -4110,6 +4148,15 @@ static int mv_platform_probe(struct platform_device *pdev)
if (rc)
goto err;
/*
* To allow disk hotplug on Armada 370/XP SoCs, the PHY speed must be
* updated in the LP_PHY_CTL register.
*/
if (pdev->dev.of_node &&
of_device_is_compatible(pdev->dev.of_node,
"marvell,armada-370-sata"))
hpriv->hp_flags |= MV_HP_FIX_LP_PHY_CTL;
/* initialize adapter */
rc = mv_init_host(host);
if (rc)
......@@ -4132,6 +4179,8 @@ static int mv_platform_probe(struct platform_device *pdev)
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
if (hpriv->port_phys[port])
phy_power_off(hpriv->port_phys[port]);
}
return rc;
......@@ -4161,6 +4210,8 @@ static int mv_platform_remove(struct platform_device *pdev)
clk_disable_unprepare(hpriv->port_clks[port]);
clk_put(hpriv->port_clks[port]);
}
if (hpriv->port_phys[port])
phy_power_off(hpriv->port_phys[port]);
}
return 0;
}
......@@ -4209,6 +4260,7 @@ static int mv_platform_resume(struct platform_device *pdev)
#ifdef CONFIG_OF
static struct of_device_id mv_sata_dt_ids[] = {
{ .compatible = "marvell,armada-370-sata", },
{ .compatible = "marvell,orion-sata", },
{},
};
......
......@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/ata.h>
#include <linux/libata.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/err.h>
......@@ -123,12 +124,37 @@
#define SATA_RCAR_DMA_BOUNDARY 0x1FFFFFFEUL
/* Gen2 Physical Layer Control Registers */
#define RCAR_GEN2_PHY_CTL1_REG 0x1704
#define RCAR_GEN2_PHY_CTL1 0x34180002
#define RCAR_GEN2_PHY_CTL1_SS 0xC180 /* Spread Spectrum */
#define RCAR_GEN2_PHY_CTL2_REG 0x170C
#define RCAR_GEN2_PHY_CTL2 0x00002303
#define RCAR_GEN2_PHY_CTL3_REG 0x171C
#define RCAR_GEN2_PHY_CTL3 0x000B0194
#define RCAR_GEN2_PHY_CTL4_REG 0x1724
#define RCAR_GEN2_PHY_CTL4 0x00030994
#define RCAR_GEN2_PHY_CTL5_REG 0x1740
#define RCAR_GEN2_PHY_CTL5 0x03004001
#define RCAR_GEN2_PHY_CTL5_DC BIT(1) /* DC connection */
#define RCAR_GEN2_PHY_CTL5_TR BIT(2) /* Termination Resistor */
enum sata_rcar_type {
RCAR_GEN1_SATA,
RCAR_GEN2_SATA,
};
struct sata_rcar_priv {
void __iomem *base;
struct clk *clk;
enum sata_rcar_type type;
};
static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv)
static void sata_rcar_gen1_phy_preinit(struct sata_rcar_priv *priv)
{
void __iomem *base = priv->base;
......@@ -141,8 +167,8 @@ static void sata_rcar_phy_initialize(struct sata_rcar_priv *priv)
iowrite32(0, base + SATAPHYRESET_REG);
}
static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val,
int group)
static void sata_rcar_gen1_phy_write(struct sata_rcar_priv *priv, u16 reg,
u32 val, int group)
{
void __iomem *base = priv->base;
int timeout;
......@@ -170,6 +196,29 @@ static void sata_rcar_phy_write(struct sata_rcar_priv *priv, u16 reg, u32 val,
iowrite32(0, base + SATAPHYADDR_REG);
}
static void sata_rcar_gen1_phy_init(struct sata_rcar_priv *priv)
{
sata_rcar_gen1_phy_preinit(priv);
sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
sata_rcar_gen1_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
sata_rcar_gen1_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
sata_rcar_gen1_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
sata_rcar_gen1_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
}
static void sata_rcar_gen2_phy_init(struct sata_rcar_priv *priv)
{
void __iomem *base = priv->base;
iowrite32(RCAR_GEN2_PHY_CTL1, base + RCAR_GEN2_PHY_CTL1_REG);
iowrite32(RCAR_GEN2_PHY_CTL2, base + RCAR_GEN2_PHY_CTL2_REG);
iowrite32(RCAR_GEN2_PHY_CTL3, base + RCAR_GEN2_PHY_CTL3_REG);
iowrite32(RCAR_GEN2_PHY_CTL4, base + RCAR_GEN2_PHY_CTL4_REG);
iowrite32(RCAR_GEN2_PHY_CTL5 | RCAR_GEN2_PHY_CTL5_DC |
RCAR_GEN2_PHY_CTL5_TR, base + RCAR_GEN2_PHY_CTL5_REG);
}
static void sata_rcar_freeze(struct ata_port *ap)
{
struct sata_rcar_priv *priv = ap->host->private_data;
......@@ -738,13 +787,17 @@ static void sata_rcar_init_controller(struct ata_host *host)
u32 val;
/* reset and setup phy */
sata_rcar_phy_initialize(priv);
sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 0);
sata_rcar_phy_write(priv, SATAPCTLR1_REG, 0x00200188, 1);
sata_rcar_phy_write(priv, SATAPCTLR3_REG, 0x0000A061, 0);
sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 0);
sata_rcar_phy_write(priv, SATAPCTLR2_REG, 0x20000000, 1);
sata_rcar_phy_write(priv, SATAPCTLR4_REG, 0x28E80000, 0);
switch (priv->type) {
case RCAR_GEN1_SATA:
sata_rcar_gen1_phy_init(priv);
break;
case RCAR_GEN2_SATA:
sata_rcar_gen2_phy_init(priv);
break;
default:
dev_warn(host->dev, "SATA phy is not initialized\n");
break;
}
/* SATA-IP reset state */
val = ioread32(base + ATAPI_CONTROL1_REG);
......@@ -770,8 +823,40 @@ static void sata_rcar_init_controller(struct ata_host *host)
iowrite32(ATAPI_INT_ENABLE_SATAINT, base + ATAPI_INT_ENABLE_REG);
}
static struct of_device_id sata_rcar_match[] = {
{
/* Deprecated by "renesas,sata-r8a7779" */
.compatible = "renesas,rcar-sata",
.data = (void *)RCAR_GEN1_SATA,
},
{
.compatible = "renesas,sata-r8a7779",
.data = (void *)RCAR_GEN1_SATA,
},
{
.compatible = "renesas,sata-r8a7790",
.data = (void *)RCAR_GEN2_SATA
},
{
.compatible = "renesas,sata-r8a7791",
.data = (void *)RCAR_GEN2_SATA
},
{ },
};
MODULE_DEVICE_TABLE(of, sata_rcar_match);
static const struct platform_device_id sata_rcar_id_table[] = {
{ "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */
{ "sata-r8a7779", RCAR_GEN1_SATA },
{ "sata-r8a7790", RCAR_GEN2_SATA },
{ "sata-r8a7791", RCAR_GEN2_SATA },
{ },
};
MODULE_DEVICE_TABLE(platform, sata_rcar_id_table);
static int sata_rcar_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
struct ata_host *host;
struct sata_rcar_priv *priv;
struct resource *mem;
......@@ -787,6 +872,12 @@ static int sata_rcar_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
of_id = of_match_device(sata_rcar_match, &pdev->dev);
if (of_id)
priv->type = (enum sata_rcar_type)of_id->data;
else
priv->type = platform_get_device_id(pdev)->driver_data;
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "failed to get access to sata clock\n");
......@@ -892,15 +983,10 @@ static const struct dev_pm_ops sata_rcar_pm_ops = {
};
#endif
static struct of_device_id sata_rcar_match[] = {
{ .compatible = "renesas,rcar-sata", },
{},
};
MODULE_DEVICE_TABLE(of, sata_rcar_match);
static struct platform_driver sata_rcar_driver = {
.probe = sata_rcar_probe,
.remove = sata_rcar_remove,
.id_table = sata_rcar_id_table,
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
......
......@@ -419,6 +419,8 @@ enum {
ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */
ATA_HORKAGE_ATAPI_DMADIR = (1 << 18), /* device requires dmadir */
ATA_HORKAGE_NO_NCQ_TRIM = (1 << 19), /* don't use queued TRIM */
ATA_HORKAGE_NOLPM = (1 << 20), /* don't use LPM */
ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
......
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