From 7560e3f3581ed415828d3f431b8622fa38c2d133 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 7 Mar 2012 09:30:06 +0100 Subject: dmaengine i.MX SDMA: do not depend on grouped clocks the current i.MX clock support groups together unrelated clocks to a single clock which is then used by the driver. This can't be accomplished with the generic clock framework so we instead request the individual clocks in the driver. For i.MX there are generally three different clocks: ipg: bus clock (needed to access registers) ahb: dma relevant clock, sometimes referred to as hclk in the datasheet per: bit clock, pixel clock This patch changes the driver to request the individual clocks. Currently all clk_get will get the same clock until the SoCs are converted to the generic clock framework Signed-off-by: Sascha Hauer --- drivers/dma/imx-sdma.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index d3e38e28bb6b..fddccae6b476 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -322,7 +322,8 @@ struct sdma_engine { struct sdma_context_data *context; dma_addr_t context_phys; struct dma_device dma_device; - struct clk *clk; + struct clk *clk_ipg; + struct clk *clk_ahb; struct mutex channel_0_lock; struct sdma_script_start_addrs *script_addrs; }; @@ -859,7 +860,8 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) sdmac->peripheral_type = data->peripheral_type; sdmac->event_id0 = data->dma_request; - clk_enable(sdmac->sdma->clk); + clk_enable(sdmac->sdma->clk_ipg); + clk_enable(sdmac->sdma->clk_ahb); ret = sdma_request_channel(sdmac); if (ret) @@ -896,7 +898,8 @@ static void sdma_free_chan_resources(struct dma_chan *chan) dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys); - clk_disable(sdma->clk); + clk_disable(sdma->clk_ipg); + clk_disable(sdma->clk_ahb); } static struct dma_async_tx_descriptor *sdma_prep_slave_sg( @@ -1169,12 +1172,14 @@ static void sdma_load_firmware(const struct firmware *fw, void *context) addr = (void *)header + header->script_addrs_start; ram_code = (void *)header + header->ram_code_start; - clk_enable(sdma->clk); + clk_enable(sdma->clk_ipg); + clk_enable(sdma->clk_ahb); /* download the RAM image for SDMA */ sdma_load_script(sdma, ram_code, header->ram_code_size, addr->ram_code_start_addr); - clk_disable(sdma->clk); + clk_disable(sdma->clk_ipg); + clk_disable(sdma->clk_ahb); sdma_add_scripts(sdma, addr); @@ -1216,7 +1221,8 @@ static int __init sdma_init(struct sdma_engine *sdma) return -ENODEV; } - clk_enable(sdma->clk); + clk_enable(sdma->clk_ipg); + clk_enable(sdma->clk_ahb); /* Be sure SDMA has not started yet */ writel_relaxed(0, sdma->regs + SDMA_H_C0PTR); @@ -1269,12 +1275,14 @@ static int __init sdma_init(struct sdma_engine *sdma) /* Initializes channel's priorities */ sdma_set_channel_priority(&sdma->channel[0], 7); - clk_disable(sdma->clk); + clk_disable(sdma->clk_ipg); + clk_disable(sdma->clk_ahb); return 0; err_dma_alloc: - clk_disable(sdma->clk); + clk_disable(sdma->clk_ipg); + clk_disable(sdma->clk_ahb); dev_err(sdma->dev, "initialisation failed with %d\n", ret); return ret; } @@ -1313,12 +1321,21 @@ static int __init sdma_probe(struct platform_device *pdev) goto err_request_region; } - sdma->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(sdma->clk)) { - ret = PTR_ERR(sdma->clk); + sdma->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(sdma->clk_ipg)) { + ret = PTR_ERR(sdma->clk_ipg); goto err_clk; } + sdma->clk_ahb = devm_clk_get(&pdev->dev, "ahb"); + if (IS_ERR(sdma->clk_ahb)) { + ret = PTR_ERR(sdma->clk_ahb); + goto err_clk; + } + + clk_prepare(sdma->clk_ipg); + clk_prepare(sdma->clk_ahb); + sdma->regs = ioremap(iores->start, resource_size(iores)); if (!sdma->regs) { ret = -ENOMEM; @@ -1426,7 +1443,6 @@ err_alloc: err_request_irq: iounmap(sdma->regs); err_ioremap: - clk_put(sdma->clk); err_clk: release_mem_region(iores->start, resource_size(iores)); err_request_region: -- cgit 1.4.1 From 4fa030a43ddb0d8fe3f2530d6162c11a3b3d31de Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 18 Mar 2012 23:48:13 +0100 Subject: dmaengine i.MX ipu: clk_prepare/unprepare clock Signed-off-by: Sascha Hauer --- drivers/dma/ipu/ipu_idmac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/dma') diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 62e3f8ec2461..5ec72044ea4c 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -1715,7 +1715,7 @@ static int __init ipu_probe(struct platform_device *pdev) } /* Make sure IPU HSP clock is running */ - clk_enable(ipu_data.ipu_clk); + clk_prepare_enable(ipu_data.ipu_clk); /* Disable all interrupts */ idmac_write_ipureg(&ipu_data, 0, IPU_INT_CTRL_1); @@ -1747,7 +1747,7 @@ static int __init ipu_probe(struct platform_device *pdev) err_idmac_init: err_attach_irq: ipu_irq_detach_irq(&ipu_data, pdev); - clk_disable(ipu_data.ipu_clk); + clk_disable_unprepare(ipu_data.ipu_clk); clk_put(ipu_data.ipu_clk); err_clk_get: iounmap(ipu_data.reg_ic); @@ -1765,7 +1765,7 @@ static int __exit ipu_remove(struct platform_device *pdev) ipu_idmac_exit(ipu); ipu_irq_detach_irq(ipu, pdev); - clk_disable(ipu->ipu_clk); + clk_disable_unprepare(ipu->ipu_clk); clk_put(ipu->ipu_clk); iounmap(ipu->reg_ic); iounmap(ipu->reg_ipu); -- cgit 1.4.1 From c510182b1c68e2f2bf61e69f6c65bcf61a188809 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 19 Feb 2012 13:30:26 +0100 Subject: ARM: Orion: XOR: Add support for clk Some orion platforms can gate the XOR driver clock. If the clock exisits, unable/disable it as appropriate. Signed-off-by: Andrew Lunn Tested-by: Jamie Lentin Signed-off-by: Mike Turquette --- arch/arm/mach-kirkwood/common.c | 10 +++++----- drivers/dma/mv_xor.c | 15 +++++++++++++++ drivers/dma/mv_xor.h | 1 + 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/dma') diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c index b9b341ff91b4..ab27d06ac4a5 100644 --- a/arch/arm/mach-kirkwood/common.c +++ b/arch/arm/mach-kirkwood/common.c @@ -87,7 +87,7 @@ static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx) void __init kirkwood_clk_init(void) { struct clk *runit, *ge0, *ge1, *sata0, *sata1, *usb0, *sdio; - struct clk *crypto; + struct clk *crypto, *xor0, *xor1; tclk = clk_register_fixed_rate(NULL, "tclk", NULL, CLK_IS_ROOT, kirkwood_tclk); @@ -100,8 +100,8 @@ void __init kirkwood_clk_init(void) usb0 = kirkwood_register_gate("usb0", CGC_BIT_USB0); sdio = kirkwood_register_gate("sdio", CGC_BIT_SDIO); crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO); - kirkwood_register_gate("xor0", CGC_BIT_XOR0); - kirkwood_register_gate("xor1", CGC_BIT_XOR1); + xor0 = kirkwood_register_gate("xor0", CGC_BIT_XOR0); + xor1 = kirkwood_register_gate("xor1", CGC_BIT_XOR1); kirkwood_register_gate("pex0", CGC_BIT_PEX0); kirkwood_register_gate("pex1", CGC_BIT_PEX1); kirkwood_register_gate("audio", CGC_BIT_AUDIO); @@ -120,6 +120,8 @@ void __init kirkwood_clk_init(void) orion_clkdev_add(NULL, "orion_nand", runit); orion_clkdev_add(NULL, "mvsdio", sdio); orion_clkdev_add(NULL, "mv_crypto", crypto); + orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".0", xor0); + orion_clkdev_add(NULL, MV_XOR_SHARED_NAME ".1", xor1); } /***************************************************************************** @@ -336,7 +338,6 @@ void __init kirkwood_crypto_init(void) void __init kirkwood_xor0_init(void) { kirkwood_clk_ctrl |= CGC_XOR0; - orion_xor0_init(XOR0_PHYS_BASE, XOR0_HIGH_PHYS_BASE, IRQ_KIRKWOOD_XOR_00, IRQ_KIRKWOOD_XOR_01); } @@ -348,7 +349,6 @@ void __init kirkwood_xor0_init(void) void __init kirkwood_xor1_init(void) { kirkwood_clk_ctrl |= CGC_XOR1; - orion_xor1_init(XOR1_PHYS_BASE, XOR1_HIGH_PHYS_BASE, IRQ_KIRKWOOD_XOR_10, IRQ_KIRKWOOD_XOR_11); } diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index fa5d55fea46c..0b12e68bf79c 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "dmaengine.h" @@ -1307,11 +1308,25 @@ static int mv_xor_shared_probe(struct platform_device *pdev) if (dram) mv_xor_conf_mbus_windows(msp, dram); + /* Not all platforms can gate the clock, so it is not + * an error if the clock does not exists. + */ + msp->clk = clk_get(&pdev->dev, NULL); + if (!IS_ERR(msp->clk)) + clk_prepare_enable(msp->clk); + return 0; } static int mv_xor_shared_remove(struct platform_device *pdev) { + struct mv_xor_shared_private *msp = platform_get_drvdata(pdev); + + if (!IS_ERR(msp->clk)) { + clk_disable_unprepare(msp->clk); + clk_put(msp->clk); + } + return 0; } diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h index 654876b7ba1d..a5b422f5a8ab 100644 --- a/drivers/dma/mv_xor.h +++ b/drivers/dma/mv_xor.h @@ -55,6 +55,7 @@ struct mv_xor_shared_private { void __iomem *xor_base; void __iomem *xor_high_base; + struct clk *clk; }; -- cgit 1.4.1