From patchwork Mon Mar 28 14:27:01 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: manjugk manjugk X-Patchwork-Id: 668571 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2SEWF5w008383 for ; Mon, 28 Mar 2011 14:32:15 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754110Ab1C1OcN (ORCPT ); Mon, 28 Mar 2011 10:32:13 -0400 Received: from bear.ext.ti.com ([192.94.94.41]:41665 "EHLO bear.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754592Ab1C1OcL (ORCPT ); Mon, 28 Mar 2011 10:32:11 -0400 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id p2SEVtlr009347 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 28 Mar 2011 09:31:57 -0500 Received: from ucmsshproxy.india.ext.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with SMTP id p2SEVpJo003573; Mon, 28 Mar 2011 20:01:51 +0530 (IST) Received: from localhost (unknown [10.24.244.236]) by ucmsshproxy.india.ext.ti.com (Postfix) with ESMTP id 3B7AD158005; Mon, 28 Mar 2011 20:01:51 +0530 (IST) From: "G, Manjunath Kondaiah" To: linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: khilman@ti.com, paul@pwsan.com, tony@atomide.com Subject: [PATCH v4 3/4] OMAP: PM: DMA: Enable runtime pm Date: Mon, 28 Mar 2011 19:57:01 +0530 Message-Id: <1301322422-29886-4-git-send-email-manjugk@ti.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1301322422-29886-1-git-send-email-manjugk@ti.com> References: <1301322422-29886-1-git-send-email-manjugk@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 28 Mar 2011 14:32:15 +0000 (UTC) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 5af9bb2..3c39794 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; static struct omap_system_dma_plat_info *p; static struct omap_dma_dev_attr *d; +static struct device *dev; static int enable_1510_mode; static u32 errata; @@ -172,6 +174,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) unsigned long reg; u32 l; + pm_runtime_get_sync(dev); if (cpu_class_is_omap1()) { switch (dst_port) { case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ @@ -188,6 +191,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) break; default: BUG(); + pm_runtime_put_autosuspend(dev); return; } l = omap_readl(reg); @@ -206,6 +210,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) ccr &= ~(1 << 6); p->dma_write(ccr, CCR, lch); } + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_priority); @@ -215,6 +220,8 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; + pm_runtime_get_sync(dev); + l = p->dma_read(CSDP, lch); l &= ~0x03; l |= data_type; @@ -269,6 +276,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, p->dma_write(elem_count, CEN, lch); p->dma_write(frame_count, CFN, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -276,6 +284,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) { BUG_ON(omap_dma_in_1510_mode()); + pm_runtime_get_sync(dev); if (cpu_class_is_omap1()) { u16 w; @@ -329,11 +338,13 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) color &= 0xffffff; p->dma_write(color, COLOR, lch); } + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_color_mode); void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) { + pm_runtime_get_sync(dev); if (cpu_class_is_omap2()) { u32 csdp; @@ -342,11 +353,13 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) csdp |= (mode << 16); p->dma_write(csdp, CSDP, lch); } + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_write_mode); void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) { + pm_runtime_get_sync(dev); if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { u32 l; @@ -355,6 +368,7 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) l |= mode; p->dma_write(l, LCH_CTRL, lch); } + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -365,6 +379,8 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, { u32 l; + pm_runtime_get_sync(dev); + if (cpu_class_is_omap1()) { u16 w; @@ -383,11 +399,13 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, p->dma_write(src_ei, CSEI, lch); p->dma_write(src_fi, CSFI, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_src_params); void omap_set_dma_params(int lch, struct omap_dma_channel_params *params) { + pm_runtime_get_sync(dev); omap_set_dma_transfer_params(lch, params->data_type, params->elem_count, params->frame_count, params->sync_mode, params->trigger, @@ -402,6 +420,7 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params *params) if (params->read_prio || params->write_prio) omap_dma_set_prio_lch(lch, params->read_prio, params->write_prio); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_params); @@ -410,8 +429,10 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; + pm_runtime_get_sync(dev); p->dma_write(eidx, CSEI, lch); p->dma_write(fidx, CSFI, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -419,11 +440,13 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CSDP, lch); l &= ~(1 << 6); if (enable) l |= (1 << 6); p->dma_write(l, CSDP, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -432,6 +455,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CSDP, lch); l &= ~(0x03 << 7); @@ -469,6 +493,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) l |= (burst << 7); p->dma_write(l, CSDP, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -478,6 +503,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, int dst_ei, int dst_fi) { u32 l; + pm_runtime_get_sync(dev); if (cpu_class_is_omap1()) { l = p->dma_read(CSDP, lch); @@ -495,6 +521,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, p->dma_write(dst_ei, CDEI, lch); p->dma_write(dst_fi, CDFI, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -502,21 +529,25 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) { if (cpu_class_is_omap2()) return; + pm_runtime_get_sync(dev); p->dma_write(eidx, CDEI, lch); p->dma_write(fidx, CDFI, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_dest_index); void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CSDP, lch); l &= ~(1 << 13); if (enable) l |= 1 << 13; p->dma_write(l, CSDP, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -524,6 +555,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) { unsigned int burst = 0; u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CSDP, lch); l &= ~(0x03 << 14); @@ -555,10 +587,12 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) default: printk(KERN_ERR "Invalid DMA burst mode\n"); BUG(); + pm_runtime_put_autosuspend(dev); return; } l |= (burst << 14); p->dma_write(l, CSDP, lch); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -566,6 +600,7 @@ static inline void omap_enable_channel_irq(int lch) { u32 status; + pm_runtime_get_sync(dev); /* Clear CSR */ if (cpu_class_is_omap1()) status = p->dma_read(CSR, lch); @@ -574,12 +609,15 @@ static inline void omap_enable_channel_irq(int lch) /* Enable some nice interrupts. */ p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch); + pm_runtime_put_autosuspend(dev); } static void omap_disable_channel_irq(int lch) { + pm_runtime_get_sync(dev); if (cpu_class_is_omap2()) p->dma_write(0, CICR, lch); + pm_runtime_put_autosuspend(dev); } void omap_enable_dma_irq(int lch, u16 bits) @@ -597,6 +635,7 @@ EXPORT_SYMBOL(omap_disable_dma_irq); static inline void enable_lnk(int lch) { u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CLNK_CTRL, lch); @@ -614,12 +653,14 @@ static inline void enable_lnk(int lch) #endif p->dma_write(l, CLNK_CTRL, lch); + pm_runtime_put_autosuspend(dev); } static inline void disable_lnk(int lch) { u32 l; + pm_runtime_get_sync(dev); l = p->dma_read(CLNK_CTRL, lch); /* Disable interrupts */ @@ -637,6 +678,7 @@ static inline void disable_lnk(int lch) p->dma_write(l, CLNK_CTRL, lch); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; + pm_runtime_put_autosuspend(dev); } static inline void omap2_enable_irq_lch(int lch) @@ -647,11 +689,13 @@ static inline void omap2_enable_irq_lch(int lch) if (!cpu_class_is_omap2()) return; + pm_runtime_get_sync(dev); spin_lock_irqsave(&dma_chan_lock, flags); val = p->dma_read(IRQENABLE_L0, lch); val |= 1 << lch; p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); + pm_runtime_put_autosuspend(dev); } static inline void omap2_disable_irq_lch(int lch) @@ -662,11 +706,13 @@ static inline void omap2_disable_irq_lch(int lch) if (!cpu_class_is_omap2()) return; + pm_runtime_get_sync(dev); spin_lock_irqsave(&dma_chan_lock, flags); val = p->dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); + pm_runtime_put_autosuspend(dev); } int omap_request_dma(int dev_id, const char *dev_name, @@ -677,6 +723,7 @@ int omap_request_dma(int dev_id, const char *dev_name, unsigned long flags; struct omap_dma_lch *chan; + pm_runtime_get_sync(dev); spin_lock_irqsave(&dma_chan_lock, flags); for (ch = 0; ch < dma_chan_count; ch++) { if (free_ch == -1 && dma_chan[ch].dev_id == -1) { @@ -687,6 +734,7 @@ int omap_request_dma(int dev_id, const char *dev_name, } if (free_ch == -1) { spin_unlock_irqrestore(&dma_chan_lock, flags); + pm_runtime_put_autosuspend(dev); return -EBUSY; } chan = dma_chan + free_ch; @@ -744,6 +792,7 @@ int omap_request_dma(int dev_id, const char *dev_name, } *dma_ch_out = free_ch; + pm_runtime_put_autosuspend(dev); return 0; } @@ -759,6 +808,7 @@ void omap_free_dma(int lch) return; } + pm_runtime_get_sync(dev); if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ p->dma_write(0, CICR, lch); @@ -781,6 +831,7 @@ void omap_free_dma(int lch) omap_clear_dma(lch); } + pm_runtime_put_autosuspend(dev); spin_lock_irqsave(&dma_chan_lock, flags); dma_chan[lch].dev_id = -1; dma_chan[lch].next_lch = -1; @@ -818,7 +869,9 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; + pm_runtime_get_sync(dev); p->dma_write(reg, GCR, 0); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -841,6 +894,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } + pm_runtime_get_sync(dev); l = p->dma_read(CCR, lch); l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) @@ -849,6 +903,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, l |= ((read_prio & 0x1) << 6); p->dma_write(l, CCR, lch); + pm_runtime_put_autosuspend(dev); return 0; } @@ -862,9 +917,11 @@ void omap_clear_dma(int lch) { unsigned long flags; + pm_runtime_get_sync(dev); local_irq_save(flags); p->clear_dma(lch); local_irq_restore(flags); + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_clear_dma); @@ -872,6 +929,8 @@ void omap_start_dma(int lch) { u32 l; + pm_runtime_get_sync(dev); + /* * The CPC/CDAC register needs to be initialized to zero * before starting dma transfer. @@ -903,6 +962,7 @@ void omap_start_dma(int lch) enable_lnk(cur_lch); omap_enable_channel_irq(cur_lch); + pm_runtime_get_sync(dev); cur_lch = next_lch; } while (next_lch != -1); } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) @@ -927,6 +987,7 @@ void omap_stop_dma(int lch) u32 l; unsigned long flags; + pm_runtime_get_sync(dev); /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) p->dma_write(0, CICR, lch); @@ -989,6 +1050,7 @@ void omap_stop_dma(int lch) } dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_stop_dma); @@ -1031,6 +1093,7 @@ dma_addr_t omap_get_dma_src_pos(int lch) { dma_addr_t offset = 0; + pm_runtime_get_sync(dev); if (cpu_is_omap15xx()) offset = p->dma_read(CPC, lch); else @@ -1042,6 +1105,7 @@ dma_addr_t omap_get_dma_src_pos(int lch) if (cpu_class_is_omap1()) offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000); + pm_runtime_put_autosuspend(dev); return offset; } EXPORT_SYMBOL(omap_get_dma_src_pos); @@ -1058,6 +1122,7 @@ dma_addr_t omap_get_dma_dst_pos(int lch) { dma_addr_t offset = 0; + pm_runtime_get_sync(dev); if (cpu_is_omap15xx()) offset = p->dma_read(CPC, lch); else @@ -1073,13 +1138,20 @@ dma_addr_t omap_get_dma_dst_pos(int lch) if (cpu_class_is_omap1()) offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000); + pm_runtime_put_autosuspend(dev); return offset; } EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; + u32 reg_data; + + pm_runtime_get_sync(dev); + reg_data = p->dma_read(CCR, lch); + pm_runtime_put_autosuspend(dev); + reg_data &= reg_data & OMAP_DMA_CCR_EN; + return ((reg_data != 0) ? 1 : 0); } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1087,14 +1159,20 @@ int omap_dma_running(void) { int lch; + pm_runtime_get_sync(dev); if (cpu_class_is_omap1()) - if (omap_lcd_dma_running()) + if (omap_lcd_dma_running()) { + pm_runtime_put_autosuspend(dev); return 1; + } for (lch = 0; lch < dma_chan_count; lch++) - if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) + if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) { + pm_runtime_put_autosuspend(dev); return 1; + } + pm_runtime_put_autosuspend(dev); return 0; } @@ -1105,12 +1183,15 @@ int omap_dma_running(void) */ void omap_dma_link_lch(int lch_head, int lch_queue) { + pm_runtime_get_sync(dev); if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8), CCR, lch_head); + pm_runtime_put_autosuspend(dev); return; } + pm_runtime_put_autosuspend(dev); printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); BUG(); return; @@ -1124,6 +1205,7 @@ void omap_dma_link_lch(int lch_head, int lch_queue) } dma_chan[lch_head].next_lch = lch_queue; + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_dma_link_lch); @@ -1132,12 +1214,15 @@ EXPORT_SYMBOL(omap_dma_link_lch); */ void omap_dma_unlink_lch(int lch_head, int lch_queue) { + pm_runtime_get_sync(dev); if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), CCR, lch_head); + pm_runtime_put_autosuspend(dev); return; } + pm_runtime_put_autosuspend(dev); printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); BUG(); return; @@ -1158,6 +1243,7 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) } dma_chan[lch_head].next_lch = -1; + pm_runtime_put_autosuspend(dev); } EXPORT_SYMBOL(omap_dma_unlink_lch); @@ -1167,6 +1253,7 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) { u32 l; + pm_runtime_get_sync(dev); /* Check if this is the first link in chain */ if (dma_chan[lch_head].next_linked_ch == -1) { dma_chan[lch_head].next_linked_ch = lch_queue; @@ -1194,6 +1281,7 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); p->dma_write(l, CLNK_CTRL, lch_queue); + pm_runtime_put_autosuspend(dev); } /** @@ -1467,6 +1555,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Increment the q_tail */ OMAP_DMA_CHAIN_INCQTAIL(chain_id); + pm_runtime_get_sync(dev); /* Set the params to the free channel */ if (src_start != 0) p->dma_write(src_start, CSSA, lch); @@ -1546,6 +1635,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } } + pm_runtime_put_autosuspend(dev); return 0; } @@ -1586,6 +1676,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } + pm_runtime_get_sync(dev); l = p->dma_read(CCR, channels[0]); l |= (1 << 7); dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; @@ -1599,6 +1690,7 @@ int omap_start_dma_chain_transfers(int chain_id) dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; + pm_runtime_put_autosuspend(dev); return 0; } EXPORT_SYMBOL(omap_start_dma_chain_transfers); @@ -1630,6 +1722,7 @@ int omap_stop_dma_chain_transfers(int chain_id) } channels = dma_linked_lch[chain_id].linked_dmach_q; + pm_runtime_get_sync(dev); if (IS_DMA_ERRATA(DMA_ERRATA_i88) && p->midlemode) { spin_lock_irqsave(&dma_chan_lock, flags); p->midlemode(true); @@ -1658,6 +1751,7 @@ int omap_stop_dma_chain_transfers(int chain_id) p->midlemode(false); spin_unlock_irqrestore(&dma_chan_lock, flags); } + pm_runtime_put_autosuspend(dev); return 0; } @@ -1699,8 +1793,10 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; + pm_runtime_get_sync(dev); *ei = p->dma_read(CCEN, lch); *fi = p->dma_read(CCFN, lch); + pm_runtime_put_autosuspend(dev); return 0; } @@ -1719,6 +1815,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) { int lch; int *channels; + int reg_data; /* Check for input params */ if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1737,7 +1834,10 @@ int omap_get_dma_chain_dst_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return p->dma_read(CDAC, lch); + pm_runtime_get_sync(dev); + reg_data = p->dma_read(CDAC, lch); + pm_runtime_put_autosuspend(dev); + return reg_data; } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1753,6 +1853,7 @@ int omap_get_dma_chain_src_pos(int chain_id) { int lch; int *channels; + int reg_data; /* Check for input params */ if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1771,7 +1872,10 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return p->dma_read(CSAC, lch); + pm_runtime_get_sync(dev); + reg_data = p->dma_read(CSAC, lch); + pm_runtime_put_autosuspend(dev); + return reg_data; } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1811,6 +1915,8 @@ static int omap1_dma_handle_ch(int ch) if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, csr, dma_chan[ch].data); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return 1; } @@ -1895,8 +2001,11 @@ static int omap2_dma_handle_ch(int ch) OMAP_DMA_DYNAMIC_CHAIN) disable_lnk(ch); - if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) + if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) { OMAP_DMA_CHAIN_INCQHEAD(chain_id); + pm_runtime_get_sync(dev); + } + status = p->dma_read(CSR, ch); p->dma_write(status, CSR, ch); @@ -1905,6 +2014,8 @@ static int omap2_dma_handle_ch(int ch) if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); return 0; } @@ -1945,17 +2056,20 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { + pm_runtime_get_sync(dev); omap_dma_global_context.dma_irqenable_l0 = p->dma_read(IRQENABLE_L0, 0); omap_dma_global_context.dma_ocp_sysconfig = p->dma_read(OCP_SYSCONFIG, 0); omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0); + pm_runtime_put_autosuspend(dev); } void omap_dma_global_context_restore(void) { int ch; + pm_runtime_get_sync(dev); p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0); p->dma_write(omap_dma_global_context.dma_ocp_sysconfig, OCP_SYSCONFIG, 0); @@ -1968,6 +2082,7 @@ void omap_dma_global_context_restore(void) for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) omap_clear_dma(ch); + pm_runtime_put_autosuspend(dev); } static int __devinit omap_system_dma_probe(struct platform_device *pdev) @@ -1984,6 +2099,7 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev) return -EINVAL; } + dev = &pdev->dev; d = p->dma_attr; errata = p->errata; @@ -2005,6 +2121,11 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev) } } + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + spin_lock_init(&dma_chan_lock); for (ch = 0; ch < dma_chan_count; ch++) { omap_clear_dma(ch); @@ -2070,6 +2191,16 @@ static int __devinit omap_system_dma_probe(struct platform_device *pdev) dma_chan[1].dev_id = 1; } p->show_dma_caps(); + + /* + * Note: If dma channels are reserved through boot paramters, + * then dma device is always enabled. + */ + if (omap_dma_reserve_channels) + pm_runtime_get(dev); + + pm_runtime_put_autosuspend(dev); + return 0; exit_dma_irq_fail: @@ -2091,6 +2222,9 @@ static int __devexit omap_system_dma_remove(struct platform_device *pdev) { int dma_irq; + if (omap_dma_reserve_channels) + pm_runtime_put_autosuspend(dev); + if (cpu_class_is_omap2()) { char irq_name[4]; strcpy(irq_name, "0"); @@ -2125,6 +2259,7 @@ arch_initcall(omap_system_dma_init); static void __exit omap_system_dma_exit(void) { + pm_runtime_disable(dev); platform_driver_unregister(&omap_system_dma_driver); }