ARM: OMAP: HWMOD: Unify DSS resets for OMAPs
This patch adds a custom DSS reset function used on OMAPs from OMAP2 forward. The function doesn't actually do a reset, it only waits for the reset to complete. The reason for this is that on OMAP4 there is no possibility to do a SW reset, and on OMAP2/3 doing a SW reset for dss_core resets all the other DSS modules also, thus breaking the HWMOD model where every DSS module is handled independently. This fixes the problem with DSS reset on OMAP4, caused by the fact that because there's no SW reset for dss_core on OMAP4, the HWMOD framework doesn't try to reset dss_core and thus the DSS clocks were never enabled at the same time. This causes causes the HWMOD reset to fail for dss_dispc and dss_rfbi. The common reset function will also allow us to fix another problem in the future: before doing a reset we need to disable DSS outputs, which are in some cases enabled by the bootloader, as otherwise DSS HW seems to get more or less stuck, requiring a power reset to recover. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> [paul@pwsan.com: modified to build arch/arm/mach-omap2/display.o unconditionally to avoid an error when !CONFIG_OMAP2_DSS] Signed-off-by: Paul Walmsley <paul@pwsan.com>
This commit is contained in:
parent
3ce32676bb
commit
13662dc5b1
6 changed files with 43 additions and 11 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
# Common support
|
||||
obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
|
||||
common.o gpio.o dma.o wd_timer.o
|
||||
common.o gpio.o dma.o wd_timer.o display.o
|
||||
|
||||
omap-2-3-common = irq.o sdrc.o
|
||||
hwmod-common = omap_hwmod.o \
|
||||
|
@ -264,7 +264,4 @@ smsc911x-$(CONFIG_SMSC911X) := gpmc-smsc911x.o
|
|||
obj-y += $(smsc911x-m) $(smsc911x-y)
|
||||
obj-$(CONFIG_ARCH_OMAP4) += hwspinlock.o
|
||||
|
||||
disp-$(CONFIG_OMAP2_DSS) := display.o
|
||||
obj-y += $(disp-m) $(disp-y)
|
||||
|
||||
obj-y += common-board-devices.o twl-common.o
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <plat/omap_hwmod.h>
|
||||
#include <plat/omap_device.h>
|
||||
#include <plat/omap-pm.h>
|
||||
#include <plat/common.h>
|
||||
|
||||
#include "control.h"
|
||||
|
||||
|
@ -172,3 +173,37 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
|
|||
|
||||
return r;
|
||||
}
|
||||
|
||||
#define MAX_MODULE_SOFTRESET_WAIT 10000
|
||||
int omap_dss_reset(struct omap_hwmod *oh)
|
||||
{
|
||||
struct omap_hwmod_opt_clk *oc;
|
||||
int c = 0;
|
||||
int i, r;
|
||||
|
||||
if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
|
||||
pr_err("dss_core: hwmod data doesn't contain reset data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
|
||||
if (oc->_clk)
|
||||
clk_enable(oc->_clk);
|
||||
|
||||
omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
|
||||
& SYSS_RESETDONE_MASK),
|
||||
MAX_MODULE_SOFTRESET_WAIT, c);
|
||||
|
||||
if (c == MAX_MODULE_SOFTRESET_WAIT)
|
||||
pr_warning("dss_core: waiting for reset to finish failed\n");
|
||||
else
|
||||
pr_debug("dss_core: softreset done\n");
|
||||
|
||||
for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
|
||||
if (oc->_clk)
|
||||
clk_disable(oc->_clk);
|
||||
|
||||
r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <plat/omap_hwmod.h>
|
||||
#include <plat/serial.h>
|
||||
#include <plat/dma.h>
|
||||
#include <plat/common.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
|
||||
|
@ -51,6 +52,7 @@ static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
|
|||
struct omap_hwmod_class omap2_dss_hwmod_class = {
|
||||
.name = "dss",
|
||||
.sysc = &omap2_dss_sysc,
|
||||
.reset = omap_dss_reset,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <plat/mmc.h>
|
||||
#include <plat/i2c.h>
|
||||
#include <plat/dmtimer.h>
|
||||
#include <plat/common.h>
|
||||
|
||||
#include "omap_hwmod_common_data.h"
|
||||
|
||||
|
@ -1187,6 +1188,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
|
|||
static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
|
||||
.name = "dss",
|
||||
.sysc = &omap44xx_dss_sysc,
|
||||
.reset = omap_dss_reset,
|
||||
};
|
||||
|
||||
/* dss */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/delay.h>
|
||||
|
||||
#include <plat/i2c.h>
|
||||
#include <plat/omap_hwmod.h>
|
||||
|
||||
struct sys_timer;
|
||||
|
||||
|
@ -55,6 +56,8 @@ void am35xx_init_early(void);
|
|||
void ti816x_init_early(void);
|
||||
void omap4430_init_early(void);
|
||||
|
||||
extern int omap_dss_reset(struct omap_hwmod *);
|
||||
|
||||
void omap_sram_init(void);
|
||||
|
||||
/*
|
||||
|
|
|
@ -307,15 +307,8 @@ struct omap_dss_board_info {
|
|||
void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
|
||||
/* Init with the board info */
|
||||
extern int omap_display_init(struct omap_dss_board_info *board_data);
|
||||
#else
|
||||
static inline int omap_display_init(struct omap_dss_board_info *board_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct omap_display_platform_data {
|
||||
struct omap_dss_board_info *board_data;
|
||||
|
|
Loading…
Reference in a new issue