mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 18:41:23 +00:00
b7e97d2211
Pull slave-dmaengine updates from Vinod Koul: "This time we have Andy updates on dw_dmac which is attempting to make this IP block available as PCI and platform device though not fully complete this time. We also have TI EDMA moving the dma driver to use dmaengine APIs, also have a new driver for mmp-tdma, along with bunch of small updates. Now for your excitement the merge is little unusual here, while merging the auto merge on linux-next picks wrong choice for pl330 (drivers/dma/pl330.c) and this causes build failure. The correct resolution is in linux-next. (DMA: PL330: Fix build error) I didn't back merge your tree this time as you are better than me so no point in doing that for me :)" Fixed the pl330 conflict as in linux-next, along with trivial header file conflicts due to changed includes. * 'next' of git://git.infradead.org/users/vkoul/slave-dma: (29 commits) dma: tegra: fix interrupt name issue with apb dma. dw_dmac: fix a regression in dwc_prep_dma_memcpy dw_dmac: introduce software emulation of LLP transfers dw_dmac: autoconfigure data_width or get it via platform data dw_dmac: autoconfigure block_size or use platform data dw_dmac: get number of channels from hardware if possible dw_dmac: fill optional encoded parameters in register structure dw_dmac: mark dwc_dump_chan_regs as inline DMA: PL330: return ENOMEM instead of 0 from pl330_alloc_chan_resources DMA: PL330: Remove redundant runtime_suspend/resume functions DMA: PL330: Remove controller clock enable/disable dmaengine: use kmem_cache_zalloc instead of kmem_cache_alloc/memset DMA: PL330: Set the capability of pdm0 and pdm1 as DMA_PRIVATE ARM: EXYNOS: Set the capability of pdm0 and pdm1 as DMA_PRIVATE dma: tegra: use list_move_tail instead of list_del/list_add_tail mxs/dma: Enlarge the CCW descriptor area to 4 pages dw_dmac: utilize slave_id to pass request line dmaengine: mmp_tdma: add dt support dmaengine: mmp-pdma support spi: davici - make davinci select edma ...
201 lines
4.7 KiB
C
201 lines
4.7 KiB
C
/*
|
|
* arch/arm/mach-spear13xx/spear13xx.c
|
|
*
|
|
* SPEAr13XX machines common source file
|
|
*
|
|
* Copyright (C) 2012 ST Microelectronics
|
|
* Viresh Kumar <viresh.linux@gmail.com>
|
|
*
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* License version 2. This program is licensed "as is" without any
|
|
* warranty of any kind, whether express or implied.
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "SPEAr13xx: " fmt
|
|
|
|
#include <linux/amba/pl022.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/dw_dmac.h>
|
|
#include <linux/err.h>
|
|
#include <linux/of_irq.h>
|
|
#include <asm/hardware/cache-l2x0.h>
|
|
#include <asm/hardware/gic.h>
|
|
#include <asm/mach/map.h>
|
|
#include <asm/smp_twd.h>
|
|
#include <mach/dma.h>
|
|
#include <mach/generic.h>
|
|
#include <mach/spear.h>
|
|
|
|
/* common dw_dma filter routine to be used by peripherals */
|
|
bool dw_dma_filter(struct dma_chan *chan, void *slave)
|
|
{
|
|
struct dw_dma_slave *dws = (struct dw_dma_slave *)slave;
|
|
|
|
if (chan->device->dev == dws->dma_dev) {
|
|
chan->private = slave;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/* ssp device registration */
|
|
static struct dw_dma_slave ssp_dma_param[] = {
|
|
{
|
|
/* Tx */
|
|
.cfg_hi = DWC_CFGH_DST_PER(DMA_REQ_SSP0_TX),
|
|
.cfg_lo = 0,
|
|
.src_master = DMA_MASTER_MEMORY,
|
|
.dst_master = DMA_MASTER_SSP0,
|
|
}, {
|
|
/* Rx */
|
|
.cfg_hi = DWC_CFGH_SRC_PER(DMA_REQ_SSP0_RX),
|
|
.cfg_lo = 0,
|
|
.src_master = DMA_MASTER_SSP0,
|
|
.dst_master = DMA_MASTER_MEMORY,
|
|
}
|
|
};
|
|
|
|
struct pl022_ssp_controller pl022_plat_data = {
|
|
.bus_id = 0,
|
|
.enable_dma = 1,
|
|
.dma_filter = dw_dma_filter,
|
|
.dma_rx_param = &ssp_dma_param[1],
|
|
.dma_tx_param = &ssp_dma_param[0],
|
|
.num_chipselect = 3,
|
|
};
|
|
|
|
/* CF device registration */
|
|
struct dw_dma_slave cf_dma_priv = {
|
|
.cfg_hi = 0,
|
|
.cfg_lo = 0,
|
|
.src_master = 0,
|
|
.dst_master = 0,
|
|
};
|
|
|
|
/* dmac device registeration */
|
|
struct dw_dma_platform_data dmac_plat_data = {
|
|
.nr_channels = 8,
|
|
.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
|
|
.chan_priority = CHAN_PRIORITY_DESCENDING,
|
|
.block_size = 4095U,
|
|
.nr_masters = 2,
|
|
.data_width = { 3, 3, 0, 0 },
|
|
};
|
|
|
|
void __init spear13xx_l2x0_init(void)
|
|
{
|
|
/*
|
|
* 512KB (64KB/way), 8-way associativity, parity supported
|
|
*
|
|
* FIXME: 9th bit, of Auxillary Controller register must be set
|
|
* for some spear13xx devices for stable L2 operation.
|
|
*
|
|
* Enable Early BRESP, L2 prefetch for Instruction and Data,
|
|
* write alloc and 'Full line of zero' options
|
|
*
|
|
*/
|
|
|
|
writel_relaxed(0x06, VA_L2CC_BASE + L2X0_PREFETCH_CTRL);
|
|
|
|
/*
|
|
* Program following latencies in order to make
|
|
* SPEAr1340 work at 600 MHz
|
|
*/
|
|
writel_relaxed(0x221, VA_L2CC_BASE + L2X0_TAG_LATENCY_CTRL);
|
|
writel_relaxed(0x441, VA_L2CC_BASE + L2X0_DATA_LATENCY_CTRL);
|
|
l2x0_init(VA_L2CC_BASE, 0x70A60001, 0xfe00ffff);
|
|
}
|
|
|
|
/*
|
|
* Following will create 16MB static virtual/physical mappings
|
|
* PHYSICAL VIRTUAL
|
|
* 0xB3000000 0xFE000000
|
|
* 0xE0000000 0xFD000000
|
|
* 0xEC000000 0xFC000000
|
|
* 0xED000000 0xFB000000
|
|
*/
|
|
struct map_desc spear13xx_io_desc[] __initdata = {
|
|
{
|
|
.virtual = (unsigned long)VA_PERIP_GRP2_BASE,
|
|
.pfn = __phys_to_pfn(PERIP_GRP2_BASE),
|
|
.length = SZ_16M,
|
|
.type = MT_DEVICE
|
|
}, {
|
|
.virtual = (unsigned long)VA_PERIP_GRP1_BASE,
|
|
.pfn = __phys_to_pfn(PERIP_GRP1_BASE),
|
|
.length = SZ_16M,
|
|
.type = MT_DEVICE
|
|
}, {
|
|
.virtual = (unsigned long)VA_A9SM_AND_MPMC_BASE,
|
|
.pfn = __phys_to_pfn(A9SM_AND_MPMC_BASE),
|
|
.length = SZ_16M,
|
|
.type = MT_DEVICE
|
|
}, {
|
|
.virtual = (unsigned long)VA_L2CC_BASE,
|
|
.pfn = __phys_to_pfn(L2CC_BASE),
|
|
.length = SZ_4K,
|
|
.type = MT_DEVICE
|
|
},
|
|
};
|
|
|
|
/* This will create static memory mapping for selected devices */
|
|
void __init spear13xx_map_io(void)
|
|
{
|
|
iotable_init(spear13xx_io_desc, ARRAY_SIZE(spear13xx_io_desc));
|
|
}
|
|
|
|
static void __init spear13xx_clk_init(void)
|
|
{
|
|
if (of_machine_is_compatible("st,spear1310"))
|
|
spear1310_clk_init();
|
|
else if (of_machine_is_compatible("st,spear1340"))
|
|
spear1340_clk_init();
|
|
else
|
|
pr_err("%s: Unknown machine\n", __func__);
|
|
}
|
|
|
|
static void __init spear13xx_timer_init(void)
|
|
{
|
|
char pclk_name[] = "osc_24m_clk";
|
|
struct clk *gpt_clk, *pclk;
|
|
|
|
spear13xx_clk_init();
|
|
|
|
/* get the system timer clock */
|
|
gpt_clk = clk_get_sys("gpt0", NULL);
|
|
if (IS_ERR(gpt_clk)) {
|
|
pr_err("%s:couldn't get clk for gpt\n", __func__);
|
|
BUG();
|
|
}
|
|
|
|
/* get the suitable parent clock for timer*/
|
|
pclk = clk_get(NULL, pclk_name);
|
|
if (IS_ERR(pclk)) {
|
|
pr_err("%s:couldn't get %s as parent for gpt\n", __func__,
|
|
pclk_name);
|
|
BUG();
|
|
}
|
|
|
|
clk_set_parent(gpt_clk, pclk);
|
|
clk_put(gpt_clk);
|
|
clk_put(pclk);
|
|
|
|
spear_setup_of_timer();
|
|
twd_local_timer_of_register();
|
|
}
|
|
|
|
struct sys_timer spear13xx_timer = {
|
|
.init = spear13xx_timer_init,
|
|
};
|
|
|
|
static const struct of_device_id gic_of_match[] __initconst = {
|
|
{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
|
|
{ /* Sentinel */ }
|
|
};
|
|
|
|
void __init spear13xx_dt_init_irq(void)
|
|
{
|
|
of_irq_init(gic_of_match);
|
|
}
|