X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmach-pxa%2Fgeneric.c;h=9de1278d234f86d655880c6f587e10b785cb843a;hb=refs%2Fheads%2Fvserver;hp=b1575b8dc1cd3e043f78794c56df9d57e6e96afa;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index b1575b8dc..9de1278d2 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -20,9 +20,14 @@ #include #include #include -#include +#include #include #include +#include + +#include +#include +#include #include #include @@ -34,9 +39,69 @@ #include #include #include +#include +#include #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 */ @@ -91,14 +156,42 @@ EXPORT_SYMBOL(pxa_set_cken); * and cache flush area. */ static struct map_desc standard_io_desc[] __initdata = { - /* virtual physical length type */ - { 0xf2000000, 0x40000000, 0x02000000, MT_DEVICE }, /* Devs */ - { 0xf4000000, 0x44000000, 0x00100000, MT_DEVICE }, /* LCD */ - { 0xf6000000, 0x48000000, 0x00100000, MT_DEVICE }, /* Mem Ctl */ - { 0xf8000000, 0x4c000000, 0x00100000, MT_DEVICE }, /* USB host */ - { 0xfa000000, 0x50000000, 0x00100000, MT_DEVICE }, /* Camera */ - { 0xfe000000, 0x58000000, 0x00100000, MT_DEVICE }, /* IMem ctl */ - { 0xff000000, 0x00000000, 0x00100000, MT_DEVICE } /* UNCACHED_PHYS_0 */ + { /* Devs */ + .virtual = 0xf2000000, + .pfn = __phys_to_pfn(0x40000000), + .length = 0x02000000, + .type = MT_DEVICE + }, { /* LCD */ + .virtual = 0xf4000000, + .pfn = __phys_to_pfn(0x44000000), + .length = 0x00100000, + .type = MT_DEVICE + }, { /* Mem Ctl */ + .virtual = 0xf6000000, + .pfn = __phys_to_pfn(0x48000000), + .length = 0x00100000, + .type = MT_DEVICE + }, { /* USB host */ + .virtual = 0xf8000000, + .pfn = __phys_to_pfn(0x4c000000), + .length = 0x00100000, + .type = MT_DEVICE + }, { /* Camera */ + .virtual = 0xfa000000, + .pfn = __phys_to_pfn(0x50000000), + .length = 0x00100000, + .type = MT_DEVICE + }, { /* IMem ctl */ + .virtual = 0xfe000000, + .pfn = __phys_to_pfn(0x58000000), + .length = 0x00100000, + .type = MT_DEVICE + }, { /* UNCACHED_PHYS_0 */ + .virtual = 0xff000000, + .pfn = __phys_to_pfn(0x00000000), + .length = 0x00100000, + .type = MT_DEVICE + } }; void __init pxa_map_io(void) @@ -173,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, @@ -199,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, }, @@ -207,6 +292,16 @@ 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; +} + static struct platform_device ffuart_device = { .name = "pxa2xx-uart", .id = 0, @@ -219,6 +314,74 @@ static struct platform_device stuart_device = { .name = "pxa2xx-uart", .id = 2, }; +static struct platform_device hwuart_device = { + .name = "pxa2xx-uart", + .id = 3, +}; + +static struct resource i2c_resources[] = { + { + .start = 0x40301680, + .end = 0x403016a3, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_I2C, + .end = IRQ_I2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device i2c_device = { + .name = "pxa2xx-i2c", + .id = 0, + .resource = i2c_resources, + .num_resources = ARRAY_SIZE(i2c_resources), +}; + +void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) +{ + i2c_device.dev.platform_data = info; +} + +static struct resource i2s_resources[] = { + { + .start = 0x40400000, + .end = 0x40400083, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_I2S, + .end = IRQ_I2S, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device i2s_device = { + .name = "pxa2xx-i2s", + .id = -1, + .resource = i2s_resources, + .num_resources = ARRAY_SIZE(i2s_resources), +}; + +static u64 pxaficp_dmamask = ~(u32)0; + +static struct platform_device pxaficp_device = { + .name = "pxa2xx-ir", + .id = -1, + .dev = { + .dma_mask = &pxaficp_dmamask, + .coherent_dma_mask = 0xffffffff, + }, +}; + +void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) +{ + pxaficp_device.dev.platform_data = info; +} + +static struct platform_device pxartc_device = { + .name = "sa1100-rtc", + .id = -1, +}; static struct platform_device *devices[] __initdata = { &pxamci_device, @@ -227,11 +390,27 @@ static struct platform_device *devices[] __initdata = { &ffuart_device, &btuart_device, &stuart_device, + &pxaficp_device, + &i2c_device, + &i2s_device, + &pxartc_device, }; static int __init pxa_init(void) { - return platform_add_devices(devices, ARRAY_SIZE(devices)); + int cpuid, ret; + + ret = platform_add_devices(devices, ARRAY_SIZE(devices)); + if (ret) + return ret; + + /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ + cpuid = read_cpuid(CPUID_ID); + if (((cpuid >> 4) & 0xfff) == 0x2d0 || + ((cpuid >> 4) & 0xfff) == 0x290) + ret = platform_device_register(&hwuart_device); + + return ret; } subsys_initcall(pxa_init);