Преглед изворни кода

ahci_platform: Provide for vendor specific init

Some AHCI implementations may use Vendor Specific HBA[A0h, FFh]
and/or Port[70h, 7Fh] registers to 'prepare' for initialization.
For that, the platform needs memory mapped address of AHCI registers.

This patch adds the 'mmio' argument and reorders the call to
platform init function.

Signed-off-by: Jassi Brar <jassi.brar@samsung.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Jassi Brar пре 15 година
родитељ
комит
08354809d6
2 измењених фајлова са 18 додато и 11 уклоњено
  1. 15 10
      drivers/ata/ahci_platform.c
  2. 3 1
      include/linux/ahci_platform.h

+ 15 - 10
drivers/ata/ahci_platform.c

@@ -54,19 +54,13 @@ static int __init ahci_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (pdata && pdata->init) {
-		rc = pdata->init(dev);
-		if (rc)
-			return rc;
-	}
-
 	if (pdata && pdata->ata_port_info)
 	if (pdata && pdata->ata_port_info)
 		pi = *pdata->ata_port_info;
 		pi = *pdata->ata_port_info;
 
 
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	if (!hpriv) {
 	if (!hpriv) {
-		rc = -ENOMEM;
-		goto err0;
+		dev_err(dev, "can't alloc ahci_host_priv\n");
+		return -ENOMEM;
 	}
 	}
 
 
 	hpriv->flags |= (unsigned long)pi.private_data;
 	hpriv->flags |= (unsigned long)pi.private_data;
@@ -74,8 +68,19 @@ static int __init ahci_probe(struct platform_device *pdev)
 	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
 	hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
 	if (!hpriv->mmio) {
 	if (!hpriv->mmio) {
 		dev_err(dev, "can't map %pR\n", mem);
 		dev_err(dev, "can't map %pR\n", mem);
-		rc = -ENOMEM;
-		goto err0;
+		return -ENOMEM;
+	}
+
+	/*
+	 * Some platforms might need to prepare for mmio region access,
+	 * which could be done in the following init call. So, the mmio
+	 * region shouldn't be accessed before init (if provided) has
+	 * returned successfully.
+	 */
+	if (pdata && pdata->init) {
+		rc = pdata->init(dev, hpriv->mmio);
+		if (rc)
+			return rc;
 	}
 	}
 
 
 	ahci_save_initial_config(dev, hpriv,
 	ahci_save_initial_config(dev, hpriv,

+ 3 - 1
include/linux/ahci_platform.h

@@ -15,11 +15,13 @@
 #ifndef _AHCI_PLATFORM_H
 #ifndef _AHCI_PLATFORM_H
 #define _AHCI_PLATFORM_H
 #define _AHCI_PLATFORM_H
 
 
+#include <linux/compiler.h>
+
 struct device;
 struct device;
 struct ata_port_info;
 struct ata_port_info;
 
 
 struct ahci_platform_data {
 struct ahci_platform_data {
-	int (*init)(struct device *dev);
+	int (*init)(struct device *dev, void __iomem *addr);
 	void (*exit)(struct device *dev);
 	void (*exit)(struct device *dev);
 	const struct ata_port_info *ata_port_info;
 	const struct ata_port_info *ata_port_info;
 	unsigned int force_port_map;
 	unsigned int force_port_map;