fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / arm / mach-sa1100 / generic.c
index 4fe5a5a..e510295 100644 (file)
@@ -9,7 +9,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
+#include <linux/sched.h>       /* just for sched_clock() - funny that */
+#include <linux/platform_device.h>
 
 #include <asm/div64.h>
+#include <asm/cnt32_to_63.h>
 #include <asm/hardware.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <asm/mach/flash.h>
 #include <asm/irq.h>
 
 #include "generic.h"
@@ -116,15 +119,21 @@ EXPORT_SYMBOL(cpufreq_get);
 
 /*
  * This is the SA11x0 sched_clock implementation.  This has
- * a resolution of 271ns, and a maximum value of 1165s.
+ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
+ *
+ * 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.
+ *
  *  ( * 1E9 / 3686400 => * 78125 / 288)
  */
 unsigned long long sched_clock(void)
 {
-       unsigned long long v;
+       unsigned long long v = cnt32_to_63(OSCR);
 
-       v = (unsigned long long)OSCR * 78125;
-       do_div(v, 288);
+       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
+       v *= 78125<<1;
+       do_div(v, 288<<1);
 
        return v;
 }
@@ -161,7 +170,7 @@ static u64 sa11x0udc_dma_mask = 0xffffffffUL;
 
 static struct platform_device sa11x0udc_device = {
        .name           = "sa11x0-udc",
-       .id             = 0,
+       .id             = -1,
        .dev            = {
                .dma_mask = &sa11x0udc_dma_mask,
                .coherent_dma_mask = 0xffffffff,
@@ -212,7 +221,7 @@ static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
 
 static struct platform_device sa11x0mcp_device = {
        .name           = "sa11x0-mcp",
-       .id             = 0,
+       .id             = -1,
        .dev = {
                .dma_mask = &sa11x0mcp_dma_mask,
                .coherent_dma_mask = 0xffffffff,
@@ -221,6 +230,11 @@ static struct platform_device sa11x0mcp_device = {
        .resource       = sa11x0mcp_resources,
 };
 
+void sa11x0_set_mcp_data(struct mcp_plat_data *data)
+{
+       sa11x0mcp_device.dev.platform_data = data;
+}
+
 static struct resource sa11x0ssp_resources[] = {
        [0] = {
                .start  = 0x80070000,
@@ -233,7 +247,7 @@ static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
 
 static struct platform_device sa11x0ssp_device = {
        .name           = "sa11x0-ssp",
-       .id             = 0,
+       .id             = -1,
        .dev = {
                .dma_mask = &sa11x0ssp_dma_mask,
                .coherent_dma_mask = 0xffffffff,
@@ -257,7 +271,7 @@ static struct resource sa11x0fb_resources[] = {
 
 static struct platform_device sa11x0fb_device = {
        .name           = "sa11x0-fb",
-       .id             = 0,
+       .id             = -1,
        .dev = {
                .coherent_dma_mask = 0xffffffff,
        },
@@ -267,7 +281,58 @@ static struct platform_device sa11x0fb_device = {
 
 static struct platform_device sa11x0pcmcia_device = {
        .name           = "sa11x0-pcmcia",
-       .id             = 0,
+       .id             = -1,
+};
+
+static struct platform_device sa11x0mtd_device = {
+       .name           = "flash",
+       .id             = -1,
+};
+
+void sa11x0_set_flash_data(struct flash_platform_data *flash,
+                          struct resource *res, int nr)
+{
+       flash->name = "sa1100";
+       sa11x0mtd_device.dev.platform_data = flash;
+       sa11x0mtd_device.resource = res;
+       sa11x0mtd_device.num_resources = nr;
+}
+
+static struct resource sa11x0ir_resources[] = {
+       {
+               .start  = __PREG(Ser2UTCR0),
+               .end    = __PREG(Ser2UTCR0) + 0x24 - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = __PREG(Ser2HSCR0),
+               .end    = __PREG(Ser2HSCR0) + 0x1c - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = __PREG(Ser2HSCR2),
+               .end    = __PREG(Ser2HSCR2) + 0x04 - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = IRQ_Ser2ICP,
+               .end    = IRQ_Ser2ICP,
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device sa11x0ir_device = {
+       .name           = "sa11x0-ir",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(sa11x0ir_resources),
+       .resource       = sa11x0ir_resources,
+};
+
+void sa11x0_set_irda_data(struct irda_platform_data *irda)
+{
+       sa11x0ir_device.dev.platform_data = irda;
+}
+
+static struct platform_device sa11x0rtc_device = {
+       .name           = "sa1100-rtc",
+       .id             = -1,
 };
 
 static struct platform_device *sa11x0_devices[] __initdata = {
@@ -278,12 +343,17 @@ static struct platform_device *sa11x0_devices[] __initdata = {
        &sa11x0ssp_device,
        &sa11x0pcmcia_device,
        &sa11x0fb_device,
+       &sa11x0mtd_device,
+       &sa11x0rtc_device,
 };
 
 static int __init sa1100_init(void)
 {
        pm_power_off = sa1100_power_off;
 
+       if (sa11x0ir_device.dev.platform_data)
+               platform_device_register(&sa11x0ir_device);
+
        return platform_add_devices(sa11x0_devices, ARRAY_SIZE(sa11x0_devices));
 }
 
@@ -315,11 +385,27 @@ EXPORT_SYMBOL(sa1100fb_lcd_power);
  */
 
 static struct map_desc standard_io_desc[] __initdata = {
- /* virtual     physical    length      type */
-  { 0xf8000000, 0x80000000, 0x00100000, MT_DEVICE }, /* PCM */
-  { 0xfa000000, 0x90000000, 0x00100000, MT_DEVICE }, /* SCM */
-  { 0xfc000000, 0xa0000000, 0x00100000, MT_DEVICE }, /* MER */
-  { 0xfe000000, 0xb0000000, 0x00200000, MT_DEVICE }  /* LCD + DMA */
+       {       /* PCM */
+               .virtual        =  0xf8000000,
+               .pfn            = __phys_to_pfn(0x80000000),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       }, {    /* SCM */
+               .virtual        =  0xfa000000,
+               .pfn            = __phys_to_pfn(0x90000000),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       }, {    /* MER */
+               .virtual        =  0xfc000000,
+               .pfn            = __phys_to_pfn(0xa0000000),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       }, {    /* LCD + DMA */
+               .virtual        =  0xfe000000,
+               .pfn            = __phys_to_pfn(0xb0000000),
+               .length         = 0x00200000,
+               .type           = MT_DEVICE
+       },
 };
 
 void __init sa1100_map_io(void)