int riwt_off;
        void (*fix_mac_speed)(void *priv, unsigned int speed);
        void (*bus_setup)(void __iomem *ioaddr);
-       int (*init)(struct platform_device *pdev);
-       void (*exit)(struct platform_device *pdev);
+       void *(*setup)(struct platform_device *pdev);
+       int (*init)(struct platform_device *pdev, void *priv);
+       void (*exit)(struct platform_device *pdev, void *priv);
        void *custom_cfg;
        void *custom_data;
        void *bsp_priv;
  o bus_setup: perform HW setup of the bus. For example, on some ST platforms
             this field is used to configure the AMBA  bridge to generate more
             efficient STBus traffic.
- o init/exit: callbacks used for calling a custom initialization;
+ o setup/init/exit: callbacks used for calling a custom initialization;
             this is sometime necessary on some platforms (e.g. ST boxes)
             where the HW needs to have set some PIO lines or system cfg
-            registers.
+            registers. setup should return a pointer to private data,
+            which will be stored in bsp_priv, and then passed to init and
+            exit callbacks. init/exit callbacks should not use or modify
+            platform data.
  o custom_cfg/custom_data: this is a custom configuration that can be passed
                           while initializing the resources.
  o bsp_priv: another private pointer.
 
                }
        }
 
+       /* Custom setup (if needed) */
+       if (plat_dat->setup) {
+               plat_dat->bsp_priv = plat_dat->setup(pdev);
+               if (IS_ERR(plat_dat->bsp_priv))
+                       return PTR_ERR(plat_dat->bsp_priv);
+       }
+
        /* Custom initialisation (if needed)*/
        if (plat_dat->init) {
-               ret = plat_dat->init(pdev);
+               ret = plat_dat->init(pdev, plat_dat->bsp_priv);
                if (unlikely(ret))
                        return ret;
        }
        int ret = stmmac_dvr_remove(ndev);
 
        if (priv->plat->exit)
-               priv->plat->exit(pdev);
+               priv->plat->exit(pdev, priv->plat->bsp_priv);
+
+       if (priv->plat->free)
+               priv->plat->free(pdev, priv->plat->bsp_priv);
 
        return ret;
 }
 
        ret = stmmac_suspend(ndev);
        if (priv->plat->exit)
-               priv->plat->exit(pdev);
+               priv->plat->exit(pdev, priv->plat->bsp_priv);
 
        return ret;
 }
        struct platform_device *pdev = to_platform_device(dev);
 
        if (priv->plat->init)
-               priv->plat->init(pdev);
+               priv->plat->init(pdev, priv->plat->bsp_priv);
 
        return stmmac_resume(ndev);
 }
 
        int max_speed;
        void (*fix_mac_speed)(void *priv, unsigned int speed);
        void (*bus_setup)(void __iomem *ioaddr);
-       int (*init)(struct platform_device *pdev);
-       void (*exit)(struct platform_device *pdev);
+       void *(*setup)(struct platform_device *pdev);
+       void (*free)(struct platform_device *pdev, void *priv);
+       int (*init)(struct platform_device *pdev, void *priv);
+       void (*exit)(struct platform_device *pdev, void *priv);
        void *custom_cfg;
        void *custom_data;
        void *bsp_priv;