OMAP: DSS2: Have separate irq handlers for DISPC and DSI
Subsystems (5)
PATCH 1/1 OMAP: DSS2: Have separate irq handlers for DISPC and DSI
Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.
On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register DSS_IRQSTATUS which tells if the interrupt came from DISPC or DSI.
On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no DSS_IRQSTATUS register.
Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.
Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.
The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.
--- arch/arm/mach-omap2/omap_hwmod_2420_data.c | 13 +++---- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 12 +++--- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 21 +++++++----- drivers/video/omap2/dss/dispc.c | 39 ++++++++++++++++++++-- drivers/video/omap2/dss/dsi.c | 30 ++++++++++++++++- drivers/video/omap2/dss/dss.c | 50 ++++----------------------- drivers/video/omap2/dss/dss.h | 6 +++ drivers/video/omap2/dss/dss_features.c | 5 ++- drivers/video/omap2/dss/dss_features.h | 17 +++++---- 9 files changed, 115 insertions(+), 78 deletions(-)
arch/arm/mach-omap2/omap_hwmod_2420_data.c +6 -7
@@ -506,11 +506,6 @@ static struct omap_hwmod_class omap2420_dss_hwmod_class = { .sysc = &omap2420_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap2420_dss_irqs[] = { - { .irq =25 }, -}; -static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = { { .name ="dispc" , .dma_req =5 }, };
@@ -559,8 +554,6 @@ static struct omap_hwmod omap2420_dss_core_hwmod = { .name = "dss_core", .class = &omap2420_dss_hwmod_class, .main_clk = "dss1_fck", /* instead of dss_fck */ - .mpu_irqs = omap2420_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap2420_dss_irqs), .sdma_reqs = omap2420_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap2420_dss_sdma_chs), .prcm = {
@@ -603,6 +596,10 @@ static struct omap_hwmod_class omap2420_dispc_hwmod_class = { .sysc = &omap2420_dispc_sysc, }; +static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = { + { .irq =25 }, +}; +static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = { { .pa_start =0x48050400 ,
@@ -635,6 +632,8 @@ static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {static struct omap_hwmod omap2420_dss_dispc_hwmod = { .name ="dss_dispc" , .class = &omap2420_dispc_hwmod_class, + .mpu_irqs = omap2420_dispc_irqs, + .mpu_irqs_cnt =ARRAY_SIZE (omap2420_dispc_irqs), .main_clk ="dss1_fck" , .prcm = { .omap2 = {
arch/arm/mach-omap2/omap_hwmod_2430_data.c +6 -6
@@ -505,10 +505,6 @@ static struct omap_hwmod_class omap2430_dss_hwmod_class = { .sysc = &omap2430_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap2430_dss_irqs[] = { - { .irq =25 }, -};static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = { { .name ="dispc" , .dma_req =5 }, };
@@ -551,8 +547,6 @@ static struct omap_hwmod omap2430_dss_core_hwmod = { .name = "dss_core", .class = &omap2430_dss_hwmod_class, .main_clk = "dss1_fck", /* instead of dss_fck */ - .mpu_irqs = omap2430_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap2430_dss_irqs), .sdma_reqs = omap2430_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap2430_dss_sdma_chs), .prcm = {
@@ -595,6 +589,10 @@ static struct omap_hwmod_class omap2430_dispc_hwmod_class = { .sysc = &omap2430_dispc_sysc, }; +static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = { + { .irq =25 }, +}; +static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = { { .pa_start =0x48050400 ,
@@ -621,6 +619,8 @@ static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {static struct omap_hwmod omap2430_dss_dispc_hwmod = { .name ="dss_dispc" , .class = &omap2430_dispc_hwmod_class, + .mpu_irqs = omap2430_dispc_irqs, + .mpu_irqs_cnt =ARRAY_SIZE (omap2430_dispc_irqs), .main_clk ="dss1_fck" , .prcm = { .omap2 = {
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +12 -9
@@ -702,11 +702,6 @@ static struct omap_hwmod_class omap3xxx_dss_hwmod_class = { .sysc = &omap3xxx_dss_sysc, }; -/* dss */ -static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = { - { .irq =25 }, -}; -static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = { { .name ="dispc" , .dma_req =5 }, { .name ="dsi1" , .dma_req =74 },
@@ -778,8 +773,6 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = { .name = "dss_core", .class = &omap3xxx_dss_hwmod_class, .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ - .mpu_irqs = omap3xxx_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), .sdma_reqs = omap3xxx_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
@@ -806,8 +799,6 @@ static struct omap_hwmod omap3xxx_dss_core_hwmod = { .name = "dss_core", .class = &omap3xxx_dss_hwmod_class, .main_clk = "dss1_alwon_fck", /* instead of dss_fck */ - .mpu_irqs = omap3xxx_dss_irqs, - .mpu_irqs_cnt = ARRAY_SIZE(omap3xxx_dss_irqs), .sdma_reqs = omap3xxx_dss_sdma_chs, .sdma_reqs_cnt = ARRAY_SIZE(omap3xxx_dss_sdma_chs),
@@ -853,6 +844,10 @@ static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = { .sysc = &omap3xxx_dispc_sysc, }; +static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = { + { .irq =25 }, +}; +static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = { { .pa_start =0x48050400 ,
@@ -886,6 +881,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {static struct omap_hwmod omap3xxx_dss_dispc_hwmod = { .name ="dss_dispc" , .class = &omap3xxx_dispc_hwmod_class, + .mpu_irqs = omap3xxx_dispc_irqs, + .mpu_irqs_cnt =ARRAY_SIZE (omap3xxx_dispc_irqs), .main_clk ="dss1_alwon_fck" , .prcm = { .omap2 = {
@@ -911,6 +908,10 @@ static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = { .name = "dsi", }; +static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = { + { .irq =25 }, +}; +/* dss_dsi1 */ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = { {
@@ -944,6 +945,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = { .name ="dss_dsi1" , .class = &omap3xxx_dsi_hwmod_class, + .mpu_irqs = omap3xxx_dsi1_irqs, + .mpu_irqs_cnt =ARRAY_SIZE (omap3xxx_dsi1_irqs), .main_clk ="dss1_alwon_fck" , .prcm = { .omap2 = {
drivers/video/omap2/dss/dispc.c +36 -3
@@ -32,6 +32,7 @@#include <linux/delay.h> #include <linux/workqueue.h> #include <linux/hardirq.h> +#include <linux/interrupt.h> #include <plat/sram.h> #include <plat/clock.h>
@@ -178,6 +179,7 @@ struct dispc_irq_stats { static struct { struct platform_device *pdev; void __iomem *base; + int irq; u32 fifo_size[3];
@@ -2930,6 +2932,18 @@ void dispc_irq_handler(void)spin_unlock (&dispc.irq_lock); } +static irqreturn_t omap_dispc_irq_handler (int irq,void *arg) +{ +if (dss_has_feature (FEAT_COMMON_IRQ_DISPC_DSI )) { +if (!(dss_get_irq_source () &DSS_IRQ_SRC_DISPC )) +return IRQ_HANDLED ; + } + +dispc_irq_handler (); + +return IRQ_HANDLED ; +} +static void dispc_error_worker (struct work_struct *work) {int i;
@@ -3322,6 +3336,7 @@ int dispc_setup_plane(enum omap_plane plane,static int omap_dispchw_probe (struct platform_device *pdev) {u32 rev; +int r =0 ;struct resource *dispc_mem; dispc.pdev = pdev;
@@ -3338,12 +3353,27 @@ static int omap_dispchw_probe(struct platform_device *pdev) dispc_mem =platform_get_resource (dispc.pdev,IORESOURCE_MEM ,0 );if (!dispc_mem) {DSSERR ("can't get IORESOURCE_MEM DISPC\n" ); -return -EINVAL ; + r = -EINVAL ; + goto fail0; } dispc.base =ioremap (dispc_mem->start,resource_size (dispc_mem));if (!dispc.base) {DSSERR ("can't ioremap DISPC\n" ); -return -ENOMEM ; + r = -ENOMEM ; + goto fail0; + } + dispc.irq =platform_get_irq (dispc.pdev,0 ); +if (dispc.irq <0 ) { +DSSERR ("omap2 dispc: platform_get_irq failed\n" ); + r = -ENODEV ; + goto fail1; + } + + r =request_irq (dispc.irq, omap_dispc_irq_handler,IRQF_SHARED , +"OMAP DISPC" , dispc.pdev); +if (r <0 ) { +DSSERR ("omap2 dispc: request_irq failed\n" ); + goto fail1; }enable_clocks (1 );
@@ -3359,12 +3389,15 @@ static int omap_dispchw_probe(struct platform_device *pdev) FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));enable_clocks (0 ); - +fail1: +iounmap (dispc.base); +fail0:return 0 ; }static int omap_dispchw_remove (struct platform_device *pdev) { +free_irq (dispc.irq,NULL );iounmap (dispc.base);return 0 ; }
drivers/video/omap2/dss/dsi.c +29 -1
@@ -38,6 +38,7 @@#include <plat/clock.h> #include "dss.h" +#include "dss_features.h" /*#define VERBOSE_IRQ*/ #define DSI_CATCH_MISSING_TE
@@ -222,6 +223,7 @@ static struct {struct platform_device *pdev;void __iomem *base; +int irq;struct dsi_clock_info current_cinfo;
@@ -580,7 +582,17 @@ void dsi_irq_handler(void)#endif } +static irqreturn_t omap_dsi_irq_handler (int irq,void *arg) +{ +if (dss_has_feature (FEAT_COMMON_IRQ_DISPC_DSI )) { +if (!(dss_get_irq_source () &DSS_IRQ_SRC_DSI )) +return IRQ_HANDLED ; + } +dsi_irq_handler (); + +return IRQ_HANDLED ; +}static void _dsi_initialize_irq (void ) {u32 l;
@@ -3294,12 +3306,25 @@ static int dsi_init(struct platform_device *pdev) r = -ENOMEM ; goto err1; } + dsi.irq =platform_get_irq (dsi.pdev,0 ); +if (dsi.irq <0 ) { +DSSERR ("omap2 dsi: platform_get_irq failed\n" ); + r = -ENODEV ; + goto err2; + } + + r =request_irq (dsi.irq, omap_dsi_irq_handler,IRQF_SHARED , +"OMAP DSI1" , dsi.pdev); +if (r <0 ) { +DSSERR ("omap2 dsi: request_irq failed\n" ); + goto err2; + } dsi.vdds_dsi_reg =dsi_get_vdds_dsi ();if (IS_ERR (dsi.vdds_dsi_reg)) {DSSERR ("can't get VDDS_DSI regulator\n" ); r =PTR_ERR (dsi.vdds_dsi_reg); - goto err2; + goto err3; }enable_clocks (1 );
@@ -3311,6 +3336,8 @@ static int dsi_init(struct platform_device *pdev)enable_clocks (0 );return 0 ; +err3: +free_irq (dsi.irq,NULL ); err2:iounmap (dsi.base); err1:
@@ -3326,6 +3353,7 @@ static void dsi_exit(void) dsi.vdds_dsi_reg =NULL ; } +free_irq (dsi.irq,NULL );iounmap (dsi.base);destroy_workqueue (dsi.workqueue);
drivers/video/omap2/dss/dss.c +8 -42
97 lines not on this page · raw message
drivers/video/omap2/dss/dss.h +6 -0
@@ -125,6 +125,11 @@ enum dss_clk_source { DSS_SRC_DSS1_ALWON_FCLK, }; +enum dss_irq_source { +DSS_IRQ_SRC_DISPC =1 <<0 , +DSS_IRQ_SRC_DSI =1 <<1 , +}; +struct dss_clock_info {/* rates that we get with dividers below */ unsigned long fck;
@@ -243,6 +248,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo);int dss_calc_clock_div (bool is_tft,unsigned long req_pck,struct dss_clock_info *dss_cinfo,struct dispc_clock_info *dispc_cinfo); +enum dss_irq_source dss_get_irq_source (void );/* SDI */ #ifdef CONFIG_OMAP2_DSS_SDI
drivers/video/omap2/dss/dss_features.c +3 -2
@@ -157,7 +157,7 @@ static struct omap_dss_features omap3430_dss_features = { .has_feature =FEAT_GLOBAL_ALPHA |FEAT_LCDENABLEPOL |FEAT_LCDENABLESIGNAL |FEAT_PCKFREEENABLE | - FEAT_FUNCGATED, + FEAT_FUNCGATED | FEAT_COMMON_IRQ_DISPC_DSI, .num_mgrs = 2, .num_ovls = 3,
@@ -172,7 +172,8 @@ static struct omap_dss_features omap3630_dss_features = { .has_feature =FEAT_GLOBAL_ALPHA |FEAT_LCDENABLEPOL |FEAT_LCDENABLESIGNAL |FEAT_PCKFREEENABLE | - FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, +FEAT_PRE_MULT_ALPHA |FEAT_FUNCGATED | + FEAT_COMMON_IRQ_DISPC_DSI, .num_mgrs = 2, .num_ovls = 3,
drivers/video/omap2/dss/dss_features.h +9 -8
@@ -25,14 +25,15 @@/* DSS has feature id */ enum dss_feat_id { -FEAT_GLOBAL_ALPHA =1 <<0 , -FEAT_GLOBAL_ALPHA_VID1 =1 <<1 , -FEAT_PRE_MULT_ALPHA =1 <<2 , -FEAT_LCDENABLEPOL =1 <<3 , -FEAT_LCDENABLESIGNAL =1 <<4 , -FEAT_PCKFREEENABLE =1 <<5 , -FEAT_FUNCGATED =1 <<6 , -FEAT_MGR_LCD2 =1 <<7 , +FEAT_GLOBAL_ALPHA =1 <<0 , +FEAT_GLOBAL_ALPHA_VID1 =1 <<1 , +FEAT_PRE_MULT_ALPHA =1 <<2 , +FEAT_LCDENABLEPOL =1 <<3 , +FEAT_LCDENABLESIGNAL =1 <<4 , +FEAT_PCKFREEENABLE =1 <<5 , +FEAT_FUNCGATED =1 <<6 , +FEAT_MGR_LCD2 =1 <<7 , +FEAT_COMMON_IRQ_DISPC_DSI =1 <<8 , };/* DSS register field id */
Signature · 1 line
1.7.1
Hi,
Quoted 12 lines · Archit
Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.
On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register
DSS_IRQSTATUSwhich tells if the interrupt came from DISPC or DSI.On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no
DSS_IRQSTATUSregister.Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.
Quoted 7 lines
Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.
The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.
Yes, I think this looks much cleaner.
However, I'm not sure if it's necessary to check the DSS_IRQSTATUS. It depends a bit on how DSS_IRQSTATUS works. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up in DSI_IRQSTATUS, the DSI bit in DSS_IRQSTATUS is up), we can do without it.
For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.
Now, if DSI_IRQSTATUS is all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well check DSI_IRQSTATUS, and exit if it's all zeroes.
If, on the other hand, DSI_IRQSTATUS has any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.
So in both cases the end result is the same, and we can do with less code by not using DSS_IRQSTATUS.
However, I'm not 100% sure DSS_IRQSTATUS works like that, but it would sound logical and I don't know how could it work otherwise.
Tomi
Hi,
Quoted 39 lines · Tomi
Hi,
Quoted 12 lines · Archit
Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.
On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register
DSS_IRQSTATUSwhich tells if the interrupt came from DISPC or DSI.On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no
DSS_IRQSTATUSregister.Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.
Quoted 7 lines
Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.
The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.
Yes, I think this looks much cleaner.
However, I'm not sure if it's necessary to check the
DSS_IRQSTATUS. It depends a bit on howDSS_IRQSTATUSworks. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up inDSI_IRQSTATUS, the DSI bit inDSS_IRQSTATUSis up), we can do without it.For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.
Now, if
DSI_IRQSTATUSis all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well checkDSI_IRQSTATUS, and exit if it's all zeroes.
Quoted 8 lines
If, on the other hand,
DSI_IRQSTATUShas any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.So in both cases the end result is the same, and we can do with less code by not using
DSS_IRQSTATUS.However, I'm not 100% sure
DSS_IRQSTATUSworks like that, but it would sound logical and I don't know how could it work otherwise.
I can give it a try.
There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in DSS_IRQSTATUS is not mentioned anywhere though
Quoted 3 lines
Tomi
Quoted 59 lines · archit taneja
Hi,
Quoted 56 lines · Tomi
Hi,
Quoted 22 lines · Archit
Currently, the core DSS platform device requests for an irq line for OMAP2 and
OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There
is a registerDSS_IRQSTATUSwhich tells if the interrupt came from DISPC or DSI.On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no
DSS_IRQSTATUSregister.Hence, it makes more sense to have separate irq handlers corresponding to the
DSS sub modules instead of having a common handler.Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared
among the IRQ handlers.Quoted 7 lines
The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3
hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss
feature is also added to tell whether the irq lines is shared between DISPC and
DSI or not.Yes, I think this looks much cleaner.
However, I'm not sure if it's necessary to check the
DSS_IRQSTATUS. It depends a bit on howDSS_IRQSTATUSworks. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up inDSI_IRQSTATUS, the DSI bit inDSS_IRQSTATUSis up), we can do without it.For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.
Now, if
DSI_IRQSTATUSis all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well checkDSI_IRQSTATUS, and exit if it's all zeroes.If, on the other hand,
DSI_IRQSTATUShas any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.So in both cases the end result is the same, and we can do with less code by not using
DSS_IRQSTATUS.
Quoted 8 lines
Quoted 2 lines
However, I'm not 100% sure
DSS_IRQSTATUSworks like that, but it would sound logical and I don't know how could it work otherwise.I can give it a try.
There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in
DSS_IRQSTATUSis not mentioned anywhere though
PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in prcm_interrupt_handler some time back. I don't know how DSS_IRQSTATUS works under the hood, but be careful of such assumptions :-)
Regards,
Mike
Quoted 9 lines
Quoted 3 lines
Tomi
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, 2011-02-18 at 03:45 -0600, Turquette, Mike wrote:
<snip>
Quoted 6 lines
PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in
prcm_interrupt_handlersome time back. I don't know howDSS_IRQSTATUSworks under the hood, but be careful of such assumptions :-)
That's how DISPC_IRQ* and DSI_IRQ* also works. But that's not what this discussion was about =). DISPC and DSI have a shared interrupt line, and there's a DSS_IRQSTATUS register with two bits, telling if the interrupt was for DISPC or DSI.
Tomi
Quoted 10 lines · Tomi
On Fri, 2011-02-18 at 03:45 -0600, Turquette, Mike wrote:
<snip>
Quoted 6 lines
PRM_IRQSTATUS_* registers will have status bits set even when the corresponding PRM_IRQENABLE_* bits are not set. The common assumption was that status bits would not be set if interrupts weren't enabled and this caused us some issues in
prcm_interrupt_handlersome time back. I don't know howDSS_IRQSTATUSworks under the hood, but be careful of such assumptions :-)
And, there is no DSS_IRQENABLE at all in our case :)
Quoted 9 lines
That's how DISPC_IRQ* and DSI_IRQ* also works. But that's not what this discussion was about =). DISPC and DSI have a shared interrupt line, and there's a
DSS_IRQSTATUSregister with two bits, telling if the interrupt was for DISPC or DSI.Tomi
Quoted 48 lines · Archit
Hi,
Quoted 45 lines · Tomi
Hi,
Quoted 12 lines · Archit
Currently, the core DSS platform device requests for an irq line for OMAP2 and OMAP3. Make DISPC and DSI platform devices request for a shared IRQ line.
On OMAP3, the logical OR of DSI and DISPC interrupt lines goes to the MPU. There is a register
DSS_IRQSTATUSwhich tells if the interrupt came from DISPC or DSI.On OMAP2, there is no DSI, only DISPC interrupts goto the MPU. There is no
DSS_IRQSTATUSregister.Hence, it makes more sense to have separate irq handlers corresponding to the DSS sub modules instead of having a common handler.
Quoted 7 lines
Since on OMAP3 the logical OR of the lines goes to MPU, the irq line is shared among the IRQ handlers.
The hwmod irq info has been removed for DSS to DISPC and DSI for OMAP2 and OMAP3 hwmod databases. The Probes of DISPC and DSI now request for irq handlers. A dss feature is also added to tell whether the irq lines is shared between DISPC and DSI or not.
Yes, I think this looks much cleaner.
However, I'm not sure if it's necessary to check the
DSS_IRQSTATUS. It depends a bit on howDSS_IRQSTATUSworks. If it just mirrors the DISPC/DSI_IRQSTATUS (ie, if there's any bit up inDSI_IRQSTATUS, the DSI bit inDSS_IRQSTATUSis up), we can do without it.For example let's say we haven't enabled any interrupts in DSI, so preferably we want to spend as little time in the dsi irq handler as possible.
Now, if
DSI_IRQSTATUSis all zeroes, and thus DSS_IRQSTATUS.DSI is also zero, we can skip the DSI handler by checking DSS_IRQSTATUS.DSI as you do in this patch. But we could as well checkDSI_IRQSTATUS, and exit if it's all zeroes.If, on the other hand,
DSI_IRQSTATUShas any bit up, then also DSS_IRQSTATUS.DSI is up, and we have to check the DSI interrupts anyway.So in both cases the end result is the same, and we can do with less code by not using
DSS_IRQSTATUS.
Quoted 8 lines
Quoted 2 lines
However, I'm not 100% sure
DSS_IRQSTATUSworks like that, but it would sound logical and I don't know how could it work otherwise.I can give it a try.
There is a figure in the OMAP3 TRM titled "DISPC and DSS Interrupts tree" which shows its logical OR. How the bits are set in
DSS_IRQSTATUSis not mentioned anywhere though
Well, if DSS_IRQSTATUS doesn't work as I described above, in the worst case we will just run a few more lines of code in the irq handler, as we check for registered interrupts. But that would only happen if either DISPC or DSI has no interrupts enabled, which is... never?
So I think it should work fine anyway.
Tomi
Hi,
On Friday 18 February 2011 03:30 PM, Valkeinen, Tomi wrote:
<snip>
Quoted 8 lines
Well, if
DSS_IRQSTATUSdoesn't work as I described above, in the worst case we will just run a few more lines of code in the irq handler, as we check for registered interrupts. But that would only happen if either DISPC or DSI has no interrupts enabled, which is... never?So I think it should work fine anyway.
Tomi
I tried to read IRQSTATUS registers in 2 the cases:
With DSS_IRQSTATUS:
[ 51.166503] DSS_IRQSTATUS 2 -> DSI [ 51.170135] DSS_IRQSTATUS 2 -> DSI [ 51.173095] DSI_IRQSTATUS 20001 -> TE_TRIGGER | VC0_IRQ [ 51.208282] DSS_IRQSTATUS 1 -> DISPC [ 51.211242] DISPC_IRQSTATUS 81 [ 51.214508] DSS_IRQSTATUS 2 -> FRAMEDONE | GFX_END_WINDOW [ 51.217437] DSI_IRQSTATUS 20001 -> TE_TRIGGER | VC0_IRQ
The cat /proc/interrupts increments by 2 for every manual update call.
Without DSS_IRQSTATUS:
Doing a ./upd (from omapfb-tests) on 3430sdp with Taal:
[ 77.060668] DISPC irqstatus 0 [ 77.064270] DSI irqstatus 20001-> TE_TRIGGER | VC0_IRQ [ 77.104888] DISPC irqstatus 81 -> FRAMEDONE | GFX_END_WINDOW [ 77.108154] DSI irqstatus 20001 -> TE_TRIGGER | VC0_IRQ
VC0_IRQSTATUS came as 0x24 -> BTA_ACK | PACKET_SENT
The cat /proc/interrupts increments by 2 for every manual update call as before.
One strange thing I see though is the increment with and without printks in the irq handler in both the cases. I always see increments of 2 when I put prints. I see 3 when I don't. That's a bit peculiar.
Behavior looks as expected. I guess we can go without DSS_IRQSTATUS then. Should I send out a patch? Also, should we remove DSS_IRQSTATUS in totality from the code now?
Archit
Quoted 2 lines · Archit
Hi,
<snip>
Quoted 3 lines
One strange thing I see though is the increment with and without printks in the irq handler in both the cases. I always see increments of 2 when I put prints. I see 3 when I don't. That's a bit peculiar.
Hmm. That's probably because prints make it slower. TE_TRIGGER and VC0_IRQ probably happen at different times. If you have printks, they are combined into one interrupt. If no printk, the code is faster and handles them separately.
Quoted 3 lines
Behavior looks as expected. I guess we can go without
DSS_IRQSTATUSthen. Should I send out a patch? Also, should we removeDSS_IRQSTATUSin totality from the code now?
Ok. Yes, please send a patch. Is DSS_IRQSTATUS used anywhere after the patch? I guess not. But let's leave the define there, as the register still exists.
Tomi