Merge branch 'hwmon-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
[sfrench/cifs-2.6.git] / arch / arm / mach-pxa / generic.c
index 5efa84749f374fae50ade0adfcb67c5b8bacf494..390524c4710f543384861206557a72cc514a1175 100644 (file)
 #include <linux/pm.h>
 #include <linux/string.h>
 
+#include <linux/sched.h>
+#include <asm/cnt32_to_63.h>
+#include <asm/div64.h>
+
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 
 #include "generic.h"
 
+/*
+ * This is the PXA2xx sched_clock implementation. This has a resolution
+ * of at least 308ns and a maximum value that depends on the value of
+ * CLOCK_TICK_RATE.
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ */
+unsigned long long sched_clock(void)
+{
+       unsigned long long v = cnt32_to_63(OSCR);
+       /* Note: top bit ov v needs cleared unless multiplier is even. */
+
+#if    CLOCK_TICK_RATE == 3686400
+       /* 1E9 / 3686400 => 78125 / 288, max value = 32025597s (370 days). */
+       /* The <<1 is used to get rid of tick.hi top bit */
+       v *= 78125<<1;
+       do_div(v, 288<<1);
+#elif  CLOCK_TICK_RATE == 3250000
+       /* 1E9 / 3250000 => 4000 / 13, max value = 709490156s (8211 days) */
+       v *= 4000;
+       do_div(v, 13);
+#elif  CLOCK_TICK_RATE == 3249600
+       /* 1E9 / 3249600 => 625000 / 2031, max value = 4541295s (52 days) */
+       v *= 625000;
+       do_div(v, 2031);
+#else
+#warning "consider fixing sched_clock for your value of CLOCK_TICK_RATE"
+       /*
+        * 96-bit math to perform tick * NSEC_PER_SEC / CLOCK_TICK_RATE for
+        * any value of CLOCK_TICK_RATE. Max value is in the 80 thousand
+        * years range and truncation to unsigned long long limits it to
+        * sched_clock's max range of ~584 years.  This is nice but with
+        * higher computation cost.
+        */
+       {
+               union {
+                       unsigned long long val;
+                       struct { unsigned long lo, hi; };
+               } x;
+               unsigned long long y;
+
+               x.val = v;
+               x.hi &= 0x7fffffff;
+               y = (unsigned long long)x.lo * NSEC_PER_SEC;
+               x.lo = y;
+               y = (y >> 32) + (unsigned long long)x.hi * NSEC_PER_SEC;
+               x.hi = do_div(y, CLOCK_TICK_RATE);
+               do_div(x.val, CLOCK_TICK_RATE);
+               x.hi += y;
+               v = x.val;
+       }
+#endif
+
+       return v;
+}
+
 /*
  * Handy function to set GPIO alternate functions
  */
@@ -204,13 +266,6 @@ static struct platform_device udc_device = {
        }
 };
 
-static struct pxafb_mach_info pxa_fb_info;
-
-void __init set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info)
-{
-       memcpy(&pxa_fb_info,hard_pxa_fb_info,sizeof(struct pxafb_mach_info));
-}
-
 static struct resource pxafb_resources[] = {
        [0] = {
                .start  = 0x44000000,
@@ -230,7 +285,6 @@ static struct platform_device pxafb_device = {
        .name           = "pxa2xx-fb",
        .id             = -1,
        .dev            = {
-               .platform_data  = &pxa_fb_info,
                .dma_mask       = &fb_dma_mask,
                .coherent_dma_mask = 0xffffffff,
        },
@@ -238,6 +292,11 @@ static struct platform_device pxafb_device = {
        .resource       = pxafb_resources,
 };
 
+void __init set_pxa_fb_info(struct pxafb_mach_info *info)
+{
+       pxafb_device.dev.platform_data = info;
+}
+
 void __init set_pxa_fb_parent(struct device *parent_dev)
 {
        pxafb_device.dev.parent = parent_dev;
@@ -279,6 +338,27 @@ static struct platform_device i2c_device = {
        .num_resources  = ARRAY_SIZE(i2c_resources),
 };
 
+#ifdef CONFIG_PXA27x
+static struct resource i2c_power_resources[] = {
+       {
+               .start  = 0x40f00180,
+               .end    = 0x40f001a3,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_PWRI2C,
+               .end    = IRQ_PWRI2C,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device i2c_power_device = {
+       .name           = "pxa2xx-i2c",
+       .id             = 1,
+       .resource       = i2c_power_resources,
+       .num_resources  = ARRAY_SIZE(i2c_resources),
+};
+#endif
+
 void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 {
        i2c_device.dev.platform_data = info;
@@ -333,6 +413,9 @@ static struct platform_device *devices[] __initdata = {
        &stuart_device,
        &pxaficp_device,
        &i2c_device,
+#ifdef CONFIG_PXA27x
+       &i2c_power_device,
+#endif
        &i2s_device,
        &pxartc_device,
 };