diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-04-12 12:53:13 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 11:16:40 +0200 |
commit | ad8740d35fde10a46e9a58a742ea34d1dd603cdb (patch) | |
tree | 794d7cbf64ab090d26125a70084e8fc978cf414a /arch | |
parent | ed08f930139b1174d442042a043d6a2b8402933c (diff) |
mach-ux500: full alignment with 2.6.35
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 3 | ||||
-rw-r--r-- | arch/arm/mach-ux500/board-u5500-mcde.c | 277 | ||||
-rw-r--r-- | arch/arm/mach-ux500/cpu.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-ux500/devices-common.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/headsmp.S | 1 |
5 files changed, 298 insertions, 2 deletions
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 0610367502f..29fad2c935f 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -23,7 +23,8 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-u8500uib.o board-mop500-pins.o \ board-mop500-mcde.o board-mop500-msp.o board-mop500-bm.o \ -obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o +obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o \ + board-u5500-mcde.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-ux500/board-u5500-mcde.c b/arch/arm/mach-ux500/board-u5500-mcde.c new file mode 100644 index 00000000000..38811d5db1f --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-mcde.c @@ -0,0 +1,277 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com> + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL), version 2. + */ +#include <linux/platform_device.h> +#include <linux/kernel.h> +#include <linux/gpio.h> +#include <linux/delay.h> +#include <video/mcde_display.h> +#include <video/mcde_display-generic_dsi.h> +#include <video/mcde_fb.h> +#include <video/mcde_dss.h> + +#define DSI_UNIT_INTERVAL_0 0xB + +#define PRIMARY_DISPLAY_ID 0 + +static bool rotate_main = true; +static int display_initialized_during_boot; + +static int __init startup_graphics_setup(char *str) +{ + + if (get_option(&str, &display_initialized_during_boot) != 1) + display_initialized_during_boot = 0; + + switch (display_initialized_during_boot) { + case 1: + pr_info("Startup graphics support\n"); + break; + case 0: + default: + pr_info("No startup graphics supported\n"); + break; + }; + + return 1; +} +__setup("startup_graphics=", startup_graphics_setup); + +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY +static struct mcde_port port0 = { + .type = MCDE_PORTTYPE_DSI, + .mode = MCDE_PORTMODE_CMD, + .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP, + .ifc = DSI_VIDEO_MODE, + .link = 0, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC + .sync_src = MCDE_SYNCSRC_OFF, + .update_auto_trig = true, +#else + .sync_src = MCDE_SYNCSRC_BTA, + .update_auto_trig = false, +#endif + .phy = { + .dsi = { + .virt_id = 0, + .num_data_lanes = 2, + .ui = DSI_UNIT_INTERVAL_0, + .clk_cont = false, + .data_lanes_swap = false, + }, + }, +}; + +struct mcde_display_generic_platform_data generic_display0_pdata = { + .reset_gpio = 226, + .reset_delay = 10, + .sleep_out_delay = 140, +#ifdef CONFIG_REGULATOR + .regulator_id = "ldo-h", + .min_supply_voltage = 2500000, /* 2.5V */ + .max_supply_voltage = 2700000 /* 2.7V */ +#endif +}; + +struct mcde_display_device generic_display0 = { + .name = "mcde_disp_generic", + .id = PRIMARY_DISPLAY_ID, + .port = &port0, + .chnl_id = MCDE_CHNL_A, + .fifo = MCDE_FIFO_A, + .default_pixel_format = MCDE_OVLYPIXFMT_RGB565, + .native_x_res = 864, + .native_y_res = 480, +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC + .synchronized_update = true, +#else + .synchronized_update = false, +#endif + /* TODO: Remove rotation buffers once ESRAM driver is completed */ + .rotbuf1 = U5500_ESRAM_BASE, + .rotbuf2 = U5500_ESRAM_BASE + 0x10000, + .dev = { + .platform_data = &generic_display0_pdata, + }, +}; +#endif /* CONFIG_DISPLAY_GENERIC_DSI_PRIMARY */ + +static struct fb_info *fbs[2] = { NULL, NULL}; +static struct mcde_display_device *displays[2] = { NULL, NULL }; +/* +* This function will create the framebuffer for the display that is registered. +*/ +static int display_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *dev) +{ + struct mcde_display_device *ddev = dev; + u16 width, height; + u16 virtual_width, virtual_height; + u32 rotate = FB_ROTATE_UR; + + if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED) + return 0; + + if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= ARRAY_SIZE(fbs)) + return 0; + + mcde_dss_get_native_resolution(ddev, &width, &height); + + if (ddev->id == PRIMARY_DISPLAY_ID && rotate_main) { + swap(width, height); + rotate = FB_ROTATE_CW; + } + + virtual_width = width; + virtual_height = height * 2; +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC + if (ddev->id == PRIMARY_DISPLAY_ID) + virtual_height = height; +#endif + + /* Create frame buffer */ + fbs[ddev->id] = mcde_fb_create(ddev, + width, height, + virtual_width, virtual_height, + ddev->default_pixel_format, + rotate); + + if (IS_ERR(fbs[ddev->id])) + pr_warning("Failed to create fb for display %s\n", ddev->name); + else + pr_info("Framebuffer created (%s)\n", ddev->name); + + return 0; +} + +static struct notifier_block display_nb = { + .notifier_call = display_postregistered_callback, +}; + +/* +* This function is used to refresh the display (lcd, hdmi, tvout) with black +* when the framebuffer is registered. +* The main display will not be updated if startup graphics is displayed +* from u-boot. +*/ +#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC +static int framebuffer_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + u8 *addr; + int i; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; + + info = event_data->info; + mfb = to_mcde_fb(info); + var = info->var; + fix = info->fix; + addr = ioremap(fix.smem_start, + var.yres_virtual * fix.line_length); + memset(addr, 0x00, var.yres_virtual * fix.line_length); + /* Apply overlay info */ + for (i = 0; i < mfb->num_ovlys; i++) { + struct mcde_overlay *ovly = mfb->ovlys[i]; + struct mcde_overlay_info ovly_info; + struct mcde_fb *mfb = to_mcde_fb(info); + memset(&ovly_info, 0, sizeof(ovly_info)); + ovly_info.paddr = fix.smem_start + + fix.line_length * var.yoffset; + if (ovly_info.paddr + fix.line_length * var.yres + > fix.smem_start + fix.smem_len) + ovly_info.paddr = fix.smem_start; + ovly_info.fmt = mfb->pix_fmt; + ovly_info.stride = fix.line_length; + ovly_info.w = var.xres; + ovly_info.h = var.yres; + ovly_info.dirty.w = var.xres; + ovly_info.dirty.h = var.yres; + (void) mcde_dss_apply_overlay(ovly, &ovly_info); + ret = mcde_dss_update_overlay(ovly); + if (ret) + break; + } + + return ret; +} +#else +static int framebuffer_postregistered_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + int ret = 0; + struct fb_event *event_data = data; + struct fb_info *info; + struct fb_var_screeninfo var; + struct fb_fix_screeninfo fix; + struct mcde_fb *mfb; + u8 *addr; + + if (event != FB_EVENT_FB_REGISTERED) + return 0; + + if (!event_data) + return 0; + + info = event_data->info; + mfb = to_mcde_fb(info); + if (mfb->id == 0 && display_initialized_during_boot) + goto out; + + var = info->var; + fix = info->fix; + addr = ioremap(fix.smem_start, + var.yres_virtual * fix.line_length); + memset(addr, 0x00, var.yres_virtual * fix.line_length); + var.yoffset = var.yoffset ? 0 : var.yres; + if (info->fbops->fb_pan_display) + ret = info->fbops->fb_pan_display(&var, info); +out: + return ret; +} +#endif + + +static struct notifier_block framebuffer_nb = { + .notifier_call = framebuffer_postregistered_callback, +}; + +int __init init_display_devices_u5500(void) +{ + int ret; + + ret = fb_register_client(&framebuffer_nb); + if (ret) + pr_warning("Failed to register framebuffer notifier\n"); + + ret = mcde_dss_register_notifier(&display_nb); + if (ret) + pr_warning("Failed to register dss notifier\n"); + +#ifdef CONFIG_DISPLAY_GENERIC_PRIMARY + if (display_initialized_during_boot) + generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY; + ret = mcde_display_device_register(&generic_display0); + if (ret) + pr_warning("Failed to register generic display device 0\n"); + displays[0] = &generic_display0; +#endif + return ret; +} + +module_init(init_display_devices_u5500); diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index a1467757fb1..d8a62845791 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/mfd/db8500-prcmu.h> #include <linux/mfd/db5500-prcmu.h> +#include <linux/delay.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> @@ -32,6 +33,15 @@ void __iomem *_PRCMU_BASE; static void __iomem *l2x0_base; #endif +static void ux500_restart(char mode, const char *cmd) +{ + prcmu_system_reset(); + + mdelay(1000); + printk("Reboot via PRCMU failed -- System halted\n"); + while (1); +} + void __init ux500_init_irq(void) { void __iomem *dist_base; @@ -54,8 +64,11 @@ void __init ux500_init_irq(void) */ if (cpu_is_u5500()) db5500_prcmu_early_init(); - if (cpu_is_u8500()) + if (cpu_is_u8500()) { prcmu_early_init(); + arm_pm_restart = ux500_restart; + } + clk_init(); } diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 13a4ce046ae..b2424483645 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -12,8 +12,10 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/amba/bus.h> +#include <linux/pm.h> #include <plat/gpio.h> +extern struct dev_power_domain ux500_dev_power_domain; #include <mach/hardware.h> @@ -38,6 +40,7 @@ dbx500_add_amba_device(const char *name, resource_size_t base, dev->dma_mask = DMA_BIT_MASK(32); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.pwr_domain = &ux500_dev_power_domain; dev->irq[0] = irq; dev->irq[1] = NO_IRQ; @@ -68,6 +71,7 @@ dbx500_add_platform_device(const char *name, int id, void *pdata, dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + dev->dev.pwr_domain = &ux500_dev_power_domain; ret = platform_device_add_resources(dev, res, resnum); if (ret) diff --git a/arch/arm/mach-ux500/headsmp.S b/arch/arm/mach-ux500/headsmp.S index 64fa451edcf..a6be2cdf2b2 100644 --- a/arch/arm/mach-ux500/headsmp.S +++ b/arch/arm/mach-ux500/headsmp.S @@ -23,6 +23,7 @@ ENTRY(u8500_secondary_startup) ldmia r4, {r5, r6} sub r4, r4, r5 add r6, r6, r4 + dsb pen: ldr r7, [r6] cmp r7, r0 bne pen |