ahci_platform: Provide for vendor specific init
authorJassi Brar <jassi.brar@samsung.com>
Fri, 25 Jun 2010 09:21:19 +0000 (18:21 +0900)
committerJeff Garzik <jgarzik@redhat.com>
Sun, 1 Aug 2010 23:36:03 +0000 (19:36 -0400)
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>
drivers/ata/ahci_platform.c
include/linux/ahci_platform.h

index 5e11b160f247a10c6ae456f7d9bb02ec0ba743a4..68ef6b563b7de5f2209f063104ba89ea5d1ad60c 100644 (file)
@@ -54,19 +54,13 @@ static int __init ahci_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       if (pdata && pdata->init) {
-               rc = pdata->init(dev);
-               if (rc)
-                       return rc;
-       }
-
        if (pdata && pdata->ata_port_info)
                pi = *pdata->ata_port_info;
 
        hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
        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;
@@ -74,8 +68,19 @@ static int __init ahci_probe(struct platform_device *pdev)
        hpriv->mmio = devm_ioremap(dev, mem->start, resource_size(mem));
        if (!hpriv->mmio) {
                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,
index f7dd576dd5a41fcb6818e666689e1610c2b3ac56..be3d9a77d6edd66cbf0208bf9145490a90981129 100644 (file)
 #ifndef _AHCI_PLATFORM_H
 #define _AHCI_PLATFORM_H
 
+#include <linux/compiler.h>
+
 struct device;
 struct ata_port_info;
 
 struct ahci_platform_data {
-       int (*init)(struct device *dev);
+       int (*init)(struct device *dev, void __iomem *addr);
        void (*exit)(struct device *dev);
        const struct ata_port_info *ata_port_info;
        unsigned int force_port_map;