int             irq_base;       /* base for cascaded on-chip IRQs */
        spinlock_t      lock;
        void __iomem    *base;
+       struct sa1111_platform_data *pdata;
 #ifdef CONFIG_PM
        void            *saved_state;
 #endif
        sachip->dev = me;
        dev_set_drvdata(sachip->dev, sachip);
 
+       sachip->pdata = pd;
        sachip->phys = mem->start;
        sachip->irq = irq;
 
  *     sa1111_enable_device - enable an on-chip SA1111 function block
  *     @sadev: SA1111 function block device to enable
  */
-void sa1111_enable_device(struct sa1111_dev *sadev)
+int sa1111_enable_device(struct sa1111_dev *sadev)
 {
        struct sa1111 *sachip = sa1111_chip_driver(sadev);
        unsigned long flags;
        unsigned int val;
+       int ret = 0;
 
-       spin_lock_irqsave(&sachip->lock, flags);
-       val = sa1111_readl(sachip->base + SA1111_SKPCR);
-       sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
-       spin_unlock_irqrestore(&sachip->lock, flags);
+       if (sachip->pdata && sachip->pdata->enable)
+               ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
+
+       if (ret == 0) {
+               spin_lock_irqsave(&sachip->lock, flags);
+               val = sa1111_readl(sachip->base + SA1111_SKPCR);
+               sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
+               spin_unlock_irqrestore(&sachip->lock, flags);
+       }
+       return ret;
 }
 EXPORT_SYMBOL(sa1111_enable_device);
 
        val = sa1111_readl(sachip->base + SA1111_SKPCR);
        sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
        spin_unlock_irqrestore(&sachip->lock, flags);
+
+       if (sachip->pdata && sachip->pdata->disable)
+               sachip->pdata->disable(sachip->pdata->data, sadev->devid);
 }
 EXPORT_SYMBOL(sa1111_disable_device);
 
 
 #define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
 
 /*
- * These frob the SKPCR register.
+ * These frob the SKPCR register, and call platform specific
+ * enable/disable functions.
  */
-void sa1111_enable_device(struct sa1111_dev *);
+int sa1111_enable_device(struct sa1111_dev *);
 void sa1111_disable_device(struct sa1111_dev *);
 
 unsigned int sa1111_pll_clock(struct sa1111_dev *);
 
 struct sa1111_platform_data {
        int     irq_base;       /* base for cascaded on-chip IRQs */
+       void    *data;
+       int     (*enable)(void *, unsigned);
+       void    (*disable)(void *, unsigned);
 };
 
 #endif  /* _ASM_ARCH_SA1111 */
 
        struct ps2if *ps2if = io->port_data;
        int ret;
 
-       sa1111_enable_device(ps2if->dev);
+       ret = sa1111_enable_device(ps2if->dev);
+       if (ret)
+               return ret;
 
        ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
                          SA1111_DRIVER_NAME(ps2if->dev), ps2if);
        if (ret) {
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
                        ps2if->dev->irq[0], ret);
+               sa1111_disable_device(ps2if->dev);
                return ret;
        }
 
                printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
                        ps2if->dev->irq[1], ret);
                free_irq(ps2if->dev->irq[0], ps2if);
+               sa1111_disable_device(ps2if->dev);
                return ret;
        }
 
 
 static int pcmcia_probe(struct sa1111_dev *dev)
 {
        void __iomem *base;
+       int ret;
+
+       ret = sa1111_enable_device(dev);
+       if (ret)
+               return ret;
 
        dev_set_drvdata(&dev->dev, NULL);
 
-       if (!request_mem_region(dev->res.start, 512,
-                               SA1111_DRIVER_NAME(dev)))
+       if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
+               sa1111_disable_device(dev);
                return -EBUSY;
+       }
 
        base = dev->mapbase;
 
        }
 
        release_mem_region(dev->res.start, 512);
+       sa1111_disable_device(dev);
        return 0;
 }
 
 
 
 /*-------------------------------------------------------------------------*/
 
-static void sa1111_start_hc(struct sa1111_dev *dev)
+static int sa1111_start_hc(struct sa1111_dev *dev)
 {
        unsigned int usb_rst = 0;
+       int ret;
 
        printk(KERN_DEBUG "%s: starting SA-1111 OHCI USB Controller\n",
               __FILE__);
         * Now, carefully enable the USB clock, and take
         * the USB host controller out of reset.
         */
-       sa1111_enable_device(dev);
-       udelay(11);
-       sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
+       ret = sa1111_enable_device(dev);
+       if (ret == 0) {
+               udelay(11);
+               sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
+       }
+
+       return ret;
 }
 
 static void sa1111_stop_hc(struct sa1111_dev *dev)
        }
        hcd->regs = dev->mapbase;
 
-       sa1111_start_hc(dev);
+       ret = sa1111_start_hc(dev);
+       if (ret)
+               goto err2;
+
        ohci_hcd_init(hcd_to_ohci(hcd));
 
        retval = usb_add_hcd(hcd, dev->irq[1], 0);
                return retval;
 
        sa1111_stop_hc(dev);
+ err2:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
        usb_put_hcd(hcd);