]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
libata: Merge branch 'for-3.13-fixes' into for-3.14
authorTejun Heo <tj@kernel.org>
Tue, 3 Dec 2013 12:39:51 +0000 (07:39 -0500)
committerTejun Heo <tj@kernel.org>
Tue, 3 Dec 2013 12:39:51 +0000 (07:39 -0500)
Pulling in for-3.13-fixes for the ahci_imx fix as further changes
depend on it.

Signed-off-by: Tejun Heo <tj@kernel.org>
Documentation/devicetree/bindings/ata/sata_rcar.txt [new file with mode: 0644]
drivers/ata/ahci.c
drivers/ata/ata_generic.c
drivers/ata/libata-eh.c
drivers/ata/sata_rcar.c

diff --git a/Documentation/devicetree/bindings/ata/sata_rcar.txt b/Documentation/devicetree/bindings/ata/sata_rcar.txt
new file mode 100644 (file)
index 0000000..1e61113
--- /dev/null
@@ -0,0 +1,18 @@
+* 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>;
+};
index 14f1e95063380a5e2a315428fc8a4d5e8bcc39d3..ef8642e12a7627e364b92ff4002a7ed632d209db 100644 (file)
@@ -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
@@ -661,6 +663,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)
@@ -777,6 +783,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)
 {
@@ -1209,15 +1257,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
index f8f38a08abc570e271b487f3ab761d26ceef0f27..7d196656adb5581533517a6ed0ec49d8c2966b58 100644 (file)
@@ -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),  },
index 92d7797223be12c41fb8cbcef92035781a779111..6d87570083187bbbe749fe566195f854707a641c 100644 (file)
@@ -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) {
index 1dae9a9009f785d9e442bfac7e6552657161dd48..2b25bd83fc9d46a2682a0affb409ccf7488abe3d 100644 (file)
@@ -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>
 
 #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,