#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/clk.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 
 
 static LIST_HEAD(clocks);
 
-DEFINE_MUTEX(clocks_mutex);
+/* We originally used an mutex here, but some contexts (see resume)
+ * are calling functions such as clk_set_parent() with IRQs disabled
+ * causing an BUG to be triggered.
+ */
+DEFINE_SPINLOCK(clocks_lock);
 
 /* enable and disable calls for use with the clk struct */
 
        else
                idno = to_platform_device(dev)->id;
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
 
        list_for_each_entry(p, &clocks, list) {
                if (p->id == idno &&
                }
        }
 
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
        return clk;
 }
 
 
        clk_enable(clk->parent);
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
 
        if ((clk->usage++) == 0)
                (clk->enable)(clk, 1);
 
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
        return 0;
 }
 
        if (IS_ERR(clk) || clk == NULL)
                return;
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
 
        if ((--clk->usage) == 0)
                (clk->enable)(clk, 0);
 
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
        clk_disable(clk->parent);
 }
 
        if (clk->set_rate == NULL)
                return -EINVAL;
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
        ret = (clk->set_rate)(clk, rate);
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
 
        return ret;
 }
        if (IS_ERR(clk))
                return -EINVAL;
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
 
        if (clk->set_parent)
                ret = (clk->set_parent)(clk, parent);
 
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
 
        return ret;
 }
 
        /* add to the list of available clocks */
 
-       mutex_lock(&clocks_mutex);
+       spin_lock(&clocks_lock);
        list_add(&clk->list, &clocks);
-       mutex_unlock(&clocks_mutex);
+       spin_unlock(&clocks_lock);
 
        return 0;
 }
 
 #include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
-#include <linux/mutex.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 
        if (clk_get_rate(clock_upll) > (94 * MHZ)) {
                clk_usb_bus.rate = clk_get_rate(clock_upll) / 2;
 
-               mutex_lock(&clocks_mutex);
+               spin_lock(&clocks_lock);
 
                clkdivn = __raw_readl(S3C2410_CLKDIVN);
                clkdivn |= S3C2440_CLKDIVN_UCLK;
                __raw_writel(clkdivn, S3C2410_CLKDIVN);
 
-               mutex_unlock(&clocks_mutex);
+               spin_unlock(&clocks_lock);
        }
 
        return 0;