forked from luck/tmp_suning_uos_patched
Merge branch 'samsung_dma' into next
This commit is contained in:
commit
0745c9a5e3
|
@ -11,7 +11,7 @@ if ARCH_EXYNOS4
|
|||
|
||||
config CPU_EXYNOS4210
|
||||
bool
|
||||
select S3C_PL330_DMA
|
||||
select SAMSUNG_DMADEV
|
||||
help
|
||||
Enable EXYNOS4210 CPU support
|
||||
|
||||
|
|
|
@ -43,6 +43,11 @@ static struct clk clk_sclk_usbphy1 = {
|
|||
.name = "sclk_usbphy1",
|
||||
};
|
||||
|
||||
static struct clk dummy_apb_pclk = {
|
||||
.name = "apb_pclk",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
|
||||
{
|
||||
return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
|
||||
|
@ -454,12 +459,12 @@ static struct clk init_clocks_off[] = {
|
|||
.enable = exynos4_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 10),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.0",
|
||||
.enable = exynos4_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 0),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.1",
|
||||
.enable = exynos4_clk_ip_fsys_ctrl,
|
||||
.ctrlbit = (1 << 1),
|
||||
|
@ -1210,5 +1215,7 @@ void __init exynos4_register_clocks(void)
|
|||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
s3c24xx_register_clock(&dummy_apb_pclk);
|
||||
|
||||
s3c_pwmclk_init();
|
||||
}
|
||||
|
|
|
@ -21,151 +21,228 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/irqs.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <plat/s3c-pl330-pdata.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
static u64 dma_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource exynos4_pdma0_resource[] = {
|
||||
[0] = {
|
||||
.start = EXYNOS4_PA_PDMA0,
|
||||
.end = EXYNOS4_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA0,
|
||||
.end = IRQ_PDMA0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
struct dma_pl330_peri pdma0_peri[28] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ0,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ2,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART4_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART4_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS4_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS4_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_MICIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMOUT,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_PCM0_RX,
|
||||
[1] = DMACH_PCM0_TX,
|
||||
[2] = DMACH_PCM2_RX,
|
||||
[3] = DMACH_PCM2_TX,
|
||||
[4] = DMACH_MSM_REQ0,
|
||||
[5] = DMACH_MSM_REQ2,
|
||||
[6] = DMACH_SPI0_RX,
|
||||
[7] = DMACH_SPI0_TX,
|
||||
[8] = DMACH_SPI2_RX,
|
||||
[9] = DMACH_SPI2_TX,
|
||||
[10] = DMACH_I2S0S_TX,
|
||||
[11] = DMACH_I2S0_RX,
|
||||
[12] = DMACH_I2S0_TX,
|
||||
[13] = DMACH_I2S2_RX,
|
||||
[14] = DMACH_I2S2_TX,
|
||||
[15] = DMACH_UART0_RX,
|
||||
[16] = DMACH_UART0_TX,
|
||||
[17] = DMACH_UART2_RX,
|
||||
[18] = DMACH_UART2_TX,
|
||||
[19] = DMACH_UART4_RX,
|
||||
[20] = DMACH_UART4_TX,
|
||||
[21] = DMACH_SLIMBUS0_RX,
|
||||
[22] = DMACH_SLIMBUS0_TX,
|
||||
[23] = DMACH_SLIMBUS2_RX,
|
||||
[24] = DMACH_SLIMBUS2_TX,
|
||||
[25] = DMACH_SLIMBUS4_RX,
|
||||
[26] = DMACH_SLIMBUS4_TX,
|
||||
[27] = DMACH_AC97_MICIN,
|
||||
[28] = DMACH_AC97_PCMIN,
|
||||
[29] = DMACH_AC97_PCMOUT,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
struct dma_pl330_platdata exynos4_pdma0_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
|
||||
.peri = pdma0_peri,
|
||||
};
|
||||
|
||||
static struct platform_device exynos4_device_pdma0 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(exynos4_pdma0_resource),
|
||||
.resource = exynos4_pdma0_resource,
|
||||
.dev = {
|
||||
struct amba_device exynos4_device_pdma0 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.0",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &exynos4_pdma0_pdata,
|
||||
},
|
||||
.res = {
|
||||
.start = EXYNOS4_PA_PDMA0,
|
||||
.end = EXYNOS4_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
.irq = {IRQ_PDMA0, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
static struct resource exynos4_pdma1_resource[] = {
|
||||
[0] = {
|
||||
.start = EXYNOS4_PA_PDMA1,
|
||||
.end = EXYNOS4_PA_PDMA1 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA1,
|
||||
.end = IRQ_PDMA1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
struct dma_pl330_peri pdma1_peri[25] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ1,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ3,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS5_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SLIMBUS5_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_PCM0_RX,
|
||||
[1] = DMACH_PCM0_TX,
|
||||
[2] = DMACH_PCM1_RX,
|
||||
[3] = DMACH_PCM1_TX,
|
||||
[4] = DMACH_MSM_REQ1,
|
||||
[5] = DMACH_MSM_REQ3,
|
||||
[6] = DMACH_SPI1_RX,
|
||||
[7] = DMACH_SPI1_TX,
|
||||
[8] = DMACH_I2S0S_TX,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S1_RX,
|
||||
[12] = DMACH_I2S1_TX,
|
||||
[13] = DMACH_UART0_RX,
|
||||
[14] = DMACH_UART0_TX,
|
||||
[15] = DMACH_UART1_RX,
|
||||
[16] = DMACH_UART1_TX,
|
||||
[17] = DMACH_UART3_RX,
|
||||
[18] = DMACH_UART3_TX,
|
||||
[19] = DMACH_SLIMBUS1_RX,
|
||||
[20] = DMACH_SLIMBUS1_TX,
|
||||
[21] = DMACH_SLIMBUS3_RX,
|
||||
[22] = DMACH_SLIMBUS3_TX,
|
||||
[23] = DMACH_SLIMBUS5_RX,
|
||||
[24] = DMACH_SLIMBUS5_TX,
|
||||
[25] = DMACH_SLIMBUS0AUX_RX,
|
||||
[26] = DMACH_SLIMBUS0AUX_TX,
|
||||
[27] = DMACH_SPDIF,
|
||||
[28] = DMACH_MAX,
|
||||
[29] = DMACH_MAX,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
struct dma_pl330_platdata exynos4_pdma1_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
|
||||
.peri = pdma1_peri,
|
||||
};
|
||||
|
||||
static struct platform_device exynos4_device_pdma1 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(exynos4_pdma1_resource),
|
||||
.resource = exynos4_pdma1_resource,
|
||||
.dev = {
|
||||
struct amba_device exynos4_device_pdma1 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.1",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &exynos4_pdma1_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *exynos4_dmacs[] __initdata = {
|
||||
&exynos4_device_pdma0,
|
||||
&exynos4_device_pdma1,
|
||||
.res = {
|
||||
.start = EXYNOS4_PA_PDMA1,
|
||||
.end = EXYNOS4_PA_PDMA1 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
.irq = {IRQ_PDMA1, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
static int __init exynos4_dma_init(void)
|
||||
{
|
||||
platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
|
||||
amba_device_register(&exynos4_device_pdma0, &iomem_resource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common S3C DMA API driver for PL330 */
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
/* This platform uses the common DMA API driver for PL330 */
|
||||
#include <plat/dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#ifndef __ASM_ARCH_DMA_H
|
||||
#define __ASM_ARCH_DMA_H __FILE__
|
||||
|
||||
#include <plat/dma.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
|
||||
|
@ -51,6 +50,18 @@ enum dma_ch {
|
|||
DMACH_MAX, /* the end entry */
|
||||
};
|
||||
|
||||
static inline bool samsung_dma_has_circular(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool samsung_dma_is_dmadev(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <plat/dma.h>
|
||||
|
||||
#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
|
||||
|
||||
/* we have 4 dma channels */
|
||||
|
@ -163,7 +174,7 @@ struct s3c2410_dma_chan {
|
|||
struct s3c2410_dma_client *client;
|
||||
|
||||
/* channel configuration */
|
||||
enum s3c2410_dmasrc source;
|
||||
enum dma_data_direction source;
|
||||
enum dma_ch req_ch;
|
||||
unsigned long dev_addr;
|
||||
unsigned long load_timeout;
|
||||
|
@ -196,9 +207,4 @@ struct s3c2410_dma_chan {
|
|||
|
||||
typedef unsigned long dma_device_t;
|
||||
|
||||
static inline bool s3c_dma_has_circular(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* __ASM_ARCH_DMA_H */
|
||||
|
|
|
@ -148,11 +148,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {
|
|||
|
||||
static void s3c2412_dma_direction(struct s3c2410_dma_chan *chan,
|
||||
struct s3c24xx_dma_map *map,
|
||||
enum s3c2410_dmasrc dir)
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
unsigned long chsel;
|
||||
|
||||
if (dir == S3C2410_DMASRC_HW)
|
||||
if (dir == DMA_FROM_DEVICE)
|
||||
chsel = map->channels_rx[0];
|
||||
else
|
||||
chsel = map->channels[0];
|
||||
|
|
|
@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
|
|||
u32 control0, control1;
|
||||
|
||||
switch (chan->source) {
|
||||
case S3C2410_DMASRC_HW:
|
||||
case DMA_FROM_DEVICE:
|
||||
src = chan->dev_addr;
|
||||
dst = data;
|
||||
control0 = PL080_CONTROL_SRC_AHB2;
|
||||
control0 |= PL080_CONTROL_DST_INCR;
|
||||
break;
|
||||
|
||||
case S3C2410_DMASRC_MEM:
|
||||
case DMA_TO_DEVICE:
|
||||
src = data;
|
||||
dst = chan->dev_addr;
|
||||
control0 = PL080_CONTROL_DST_AHB2;
|
||||
|
@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);
|
|||
|
||||
|
||||
int s3c2410_dma_devconfig(enum dma_ch channel,
|
||||
enum s3c2410_dmasrc source,
|
||||
enum dma_data_direction source,
|
||||
unsigned long devaddr)
|
||||
{
|
||||
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
||||
|
@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
|
|||
pr_debug("%s: peripheral %d\n", __func__, peripheral);
|
||||
|
||||
switch (source) {
|
||||
case S3C2410_DMASRC_HW:
|
||||
case DMA_FROM_DEVICE:
|
||||
config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
|
||||
config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
|
||||
break;
|
||||
case S3C2410_DMASRC_MEM:
|
||||
case DMA_TO_DEVICE:
|
||||
config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
|
||||
config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
|
||||
break;
|
||||
|
|
|
@ -58,11 +58,15 @@ enum dma_ch {
|
|||
DMACH_MAX /* the end */
|
||||
};
|
||||
|
||||
static __inline__ bool s3c_dma_has_circular(void)
|
||||
static inline bool samsung_dma_has_circular(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool samsung_dma_is_dmadev(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define S3C2410_DMAF_CIRCULAR (1 << 0)
|
||||
|
||||
#include <plat/dma.h>
|
||||
|
@ -95,7 +99,7 @@ struct s3c2410_dma_chan {
|
|||
unsigned char peripheral;
|
||||
|
||||
unsigned int flags;
|
||||
enum s3c2410_dmasrc source;
|
||||
enum dma_data_direction source;
|
||||
|
||||
|
||||
dma_addr_t dev_addr;
|
||||
|
|
|
@ -9,14 +9,14 @@ if ARCH_S5P64X0
|
|||
|
||||
config CPU_S5P6440
|
||||
bool
|
||||
select S3C_PL330_DMA
|
||||
select SAMSUNG_DMADEV
|
||||
select S5P_HRT
|
||||
help
|
||||
Enable S5P6440 CPU support
|
||||
|
||||
config CPU_S5P6450
|
||||
bool
|
||||
select S3C_PL330_DMA
|
||||
select SAMSUNG_DMADEV
|
||||
select S5P_HRT
|
||||
help
|
||||
Enable S5P6450 CPU support
|
||||
|
|
|
@ -146,7 +146,7 @@ static struct clk init_clocks_off[] = {
|
|||
.enable = s5p64x0_hclk0_ctrl,
|
||||
.ctrlbit = (1 << 8),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.parent = &clk_hclk_low.clk,
|
||||
.enable = s5p64x0_hclk0_ctrl,
|
||||
.ctrlbit = (1 << 12),
|
||||
|
@ -499,6 +499,11 @@ static struct clksrc_clk *sysclks[] = {
|
|||
&clk_pclk_low,
|
||||
};
|
||||
|
||||
static struct clk dummy_apb_pclk = {
|
||||
.name = "apb_pclk",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init_or_cpufreq s5p6440_setup_clocks(void)
|
||||
{
|
||||
struct clk *xtal_clk;
|
||||
|
@ -581,5 +586,7 @@ void __init s5p6440_register_clocks(void)
|
|||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
s3c24xx_register_clock(&dummy_apb_pclk);
|
||||
|
||||
s3c_pwmclk_init();
|
||||
}
|
||||
|
|
|
@ -179,7 +179,7 @@ static struct clk init_clocks_off[] = {
|
|||
.enable = s5p64x0_hclk0_ctrl,
|
||||
.ctrlbit = (1 << 3),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.parent = &clk_hclk_low.clk,
|
||||
.enable = s5p64x0_hclk0_ctrl,
|
||||
.ctrlbit = (1 << 12),
|
||||
|
@ -553,6 +553,11 @@ static struct clksrc_clk *sysclks[] = {
|
|||
&clk_sclk_audio0,
|
||||
};
|
||||
|
||||
static struct clk dummy_apb_pclk = {
|
||||
.name = "apb_pclk",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
void __init_or_cpufreq s5p6450_setup_clocks(void)
|
||||
{
|
||||
struct clk *xtal_clk;
|
||||
|
@ -632,5 +637,7 @@ void __init s5p6450_register_clocks(void)
|
|||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
s3c24xx_register_clock(&dummy_apb_pclk);
|
||||
|
||||
s3c_pwmclk_init();
|
||||
}
|
||||
|
|
|
@ -21,128 +21,219 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/regs-clock.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
#include <plat/devs.h>
|
||||
#include <plat/s3c-pl330-pdata.h>
|
||||
#include <plat/irqs.h>
|
||||
|
||||
static u64 dma_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource s5p64x0_pdma_resource[] = {
|
||||
[0] = {
|
||||
.start = S5P64X0_PA_PDMA,
|
||||
.end = S5P64X0_PA_PDMA + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_DMA0,
|
||||
.end = IRQ_DMA0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
struct dma_pl330_peri s5p6440_pdma_peri[22] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5p6440_pdma_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_MAX,
|
||||
[9] = DMACH_MAX,
|
||||
[10] = DMACH_PCM0_TX,
|
||||
[11] = DMACH_PCM0_RX,
|
||||
[12] = DMACH_I2S0_TX,
|
||||
[13] = DMACH_I2S0_RX,
|
||||
[14] = DMACH_SPI0_TX,
|
||||
[15] = DMACH_SPI0_RX,
|
||||
[16] = DMACH_MAX,
|
||||
[17] = DMACH_MAX,
|
||||
[18] = DMACH_MAX,
|
||||
[19] = DMACH_MAX,
|
||||
[20] = DMACH_SPI1_TX,
|
||||
[21] = DMACH_SPI1_RX,
|
||||
[22] = DMACH_MAX,
|
||||
[23] = DMACH_MAX,
|
||||
[24] = DMACH_MAX,
|
||||
[25] = DMACH_MAX,
|
||||
[26] = DMACH_MAX,
|
||||
[27] = DMACH_MAX,
|
||||
[28] = DMACH_MAX,
|
||||
[29] = DMACH_PWM,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
struct dma_pl330_platdata s5p6440_pdma_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(s5p6440_pdma_peri),
|
||||
.peri = s5p6440_pdma_peri,
|
||||
};
|
||||
|
||||
struct dma_pl330_peri s5p6450_pdma_peri[32] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART4_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART4_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_USI_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_USI_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PWM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART5_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART5_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5p6450_pdma_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_UART4_RX,
|
||||
[9] = DMACH_UART4_TX,
|
||||
[10] = DMACH_PCM0_TX,
|
||||
[11] = DMACH_PCM0_RX,
|
||||
[12] = DMACH_I2S0_TX,
|
||||
[13] = DMACH_I2S0_RX,
|
||||
[14] = DMACH_SPI0_TX,
|
||||
[15] = DMACH_SPI0_RX,
|
||||
[16] = DMACH_PCM1_TX,
|
||||
[17] = DMACH_PCM1_RX,
|
||||
[18] = DMACH_PCM2_TX,
|
||||
[19] = DMACH_PCM2_RX,
|
||||
[20] = DMACH_SPI1_TX,
|
||||
[21] = DMACH_SPI1_RX,
|
||||
[22] = DMACH_USI_TX,
|
||||
[23] = DMACH_USI_RX,
|
||||
[24] = DMACH_MAX,
|
||||
[25] = DMACH_I2S1_TX,
|
||||
[26] = DMACH_I2S1_RX,
|
||||
[27] = DMACH_I2S2_TX,
|
||||
[28] = DMACH_I2S2_RX,
|
||||
[29] = DMACH_PWM,
|
||||
[30] = DMACH_UART5_RX,
|
||||
[31] = DMACH_UART5_TX,
|
||||
},
|
||||
struct dma_pl330_platdata s5p6450_pdma_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(s5p6450_pdma_peri),
|
||||
.peri = s5p6450_pdma_peri,
|
||||
};
|
||||
|
||||
static struct platform_device s5p64x0_device_pdma = {
|
||||
.name = "s3c-pl330",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(s5p64x0_pdma_resource),
|
||||
.resource = s5p64x0_pdma_resource,
|
||||
.dev = {
|
||||
struct amba_device s5p64x0_device_pdma = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.res = {
|
||||
.start = S5P64X0_PA_PDMA,
|
||||
.end = S5P64X0_PA_PDMA + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
.irq = {IRQ_DMA0, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
static int __init s5p64x0_dma_init(void)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
|
||||
unsigned int id = __raw_readl(S5P64X0_SYS_ID) & 0xFF000;
|
||||
|
||||
if (id == 0x50000)
|
||||
s5p64x0_device_pdma.dev.platform_data = &s5p6450_pdma_pdata;
|
||||
else
|
||||
s5p64x0_device_pdma.dev.platform_data = &s5p6440_pdma_pdata;
|
||||
|
||||
platform_device_register(&s5p64x0_device_pdma);
|
||||
amba_device_register(&s5p64x0_device_pdma, &iomem_resource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common S3C DMA API driver for PL330 */
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
/* This platform uses the common common DMA API driver for PL330 */
|
||||
#include <plat/dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
||||
|
|
|
@ -10,7 +10,7 @@ if ARCH_S5PC100
|
|||
config CPU_S5PC100
|
||||
bool
|
||||
select S5P_EXT_INT
|
||||
select S3C_PL330_DMA
|
||||
select SAMSUNG_DMADEV
|
||||
help
|
||||
Enable S5PC100 CPU support
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ static struct clk s5p_clk_otgphy = {
|
|||
.name = "otg_phy",
|
||||
};
|
||||
|
||||
static struct clk dummy_apb_pclk = {
|
||||
.name = "apb_pclk",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk *clk_src_mout_href_list[] = {
|
||||
[0] = &s5p_clk_27m,
|
||||
[1] = &clk_fin_hpll,
|
||||
|
@ -454,13 +459,13 @@ static struct clk init_clocks_off[] = {
|
|||
.enable = s5pc100_d1_0_ctrl,
|
||||
.ctrlbit = (1 << 2),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.1",
|
||||
.parent = &clk_div_d1_bus.clk,
|
||||
.enable = s5pc100_d1_0_ctrl,
|
||||
.ctrlbit = (1 << 1),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.0",
|
||||
.parent = &clk_div_d1_bus.clk,
|
||||
.enable = s5pc100_d1_0_ctrl,
|
||||
|
@ -1276,5 +1281,7 @@ void __init s5pc100_register_clocks(void)
|
|||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
s3c24xx_register_clock(&dummy_apb_pclk);
|
||||
|
||||
s3c_pwmclk_init();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
/*
|
||||
/* linux/arch/arm/mach-s5pc100/dma.c
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.com>
|
||||
*
|
||||
|
@ -17,150 +21,245 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/irqs.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <plat/s3c-pl330-pdata.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
static u64 dma_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource s5pc100_pdma0_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PC100_PA_PDMA0,
|
||||
.end = S5PC100_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA0,
|
||||
.end = IRQ_PDMA0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
struct dma_pl330_peri pdma0_peri[30] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = DMACH_IRDA,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_MICIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMOUT,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_EXTERNAL,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PWM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPDIF,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_HSI_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_HSI_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pc100_pdma0_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_IRDA,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S0S_TX,
|
||||
[12] = DMACH_I2S1_RX,
|
||||
[13] = DMACH_I2S1_TX,
|
||||
[14] = DMACH_I2S2_RX,
|
||||
[15] = DMACH_I2S2_TX,
|
||||
[16] = DMACH_SPI0_RX,
|
||||
[17] = DMACH_SPI0_TX,
|
||||
[18] = DMACH_SPI1_RX,
|
||||
[19] = DMACH_SPI1_TX,
|
||||
[20] = DMACH_SPI2_RX,
|
||||
[21] = DMACH_SPI2_TX,
|
||||
[22] = DMACH_AC97_MICIN,
|
||||
[23] = DMACH_AC97_PCMIN,
|
||||
[24] = DMACH_AC97_PCMOUT,
|
||||
[25] = DMACH_EXTERNAL,
|
||||
[26] = DMACH_PWM,
|
||||
[27] = DMACH_SPDIF,
|
||||
[28] = DMACH_HSI_RX,
|
||||
[29] = DMACH_HSI_TX,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
struct dma_pl330_platdata s5pc100_pdma0_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
|
||||
.peri = pdma0_peri,
|
||||
};
|
||||
|
||||
static struct platform_device s5pc100_device_pdma0 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_pdma0_resource),
|
||||
.resource = s5pc100_pdma0_resource,
|
||||
.dev = {
|
||||
struct amba_device s5pc100_device_pdma0 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.0",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pc100_pdma0_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pc100_pdma1_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PC100_PA_PDMA1,
|
||||
.end = S5PC100_PA_PDMA1 + SZ_4K,
|
||||
.res = {
|
||||
.start = S5PC100_PA_PDMA0,
|
||||
.end = S5PC100_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA1,
|
||||
.end = IRQ_PDMA1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
.irq = {IRQ_PDMA0, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
struct dma_pl330_peri pdma1_peri[30] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = DMACH_IRDA,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ0,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ1,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ2,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ3,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pc100_pdma1_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_IRDA,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S0S_TX,
|
||||
[12] = DMACH_I2S1_RX,
|
||||
[13] = DMACH_I2S1_TX,
|
||||
[14] = DMACH_I2S2_RX,
|
||||
[15] = DMACH_I2S2_TX,
|
||||
[16] = DMACH_SPI0_RX,
|
||||
[17] = DMACH_SPI0_TX,
|
||||
[18] = DMACH_SPI1_RX,
|
||||
[19] = DMACH_SPI1_TX,
|
||||
[20] = DMACH_SPI2_RX,
|
||||
[21] = DMACH_SPI2_TX,
|
||||
[22] = DMACH_PCM0_RX,
|
||||
[23] = DMACH_PCM0_TX,
|
||||
[24] = DMACH_PCM1_RX,
|
||||
[25] = DMACH_PCM1_TX,
|
||||
[26] = DMACH_MSM_REQ0,
|
||||
[27] = DMACH_MSM_REQ1,
|
||||
[28] = DMACH_MSM_REQ2,
|
||||
[29] = DMACH_MSM_REQ3,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
struct dma_pl330_platdata s5pc100_pdma1_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
|
||||
.peri = pdma1_peri,
|
||||
};
|
||||
|
||||
static struct platform_device s5pc100_device_pdma1 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pc100_pdma1_resource),
|
||||
.resource = s5pc100_pdma1_resource,
|
||||
.dev = {
|
||||
struct amba_device s5pc100_device_pdma1 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.1",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pc100_pdma1_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *s5pc100_dmacs[] __initdata = {
|
||||
&s5pc100_device_pdma0,
|
||||
&s5pc100_device_pdma1,
|
||||
.res = {
|
||||
.start = S5PC100_PA_PDMA1,
|
||||
.end = S5PC100_PA_PDMA1 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
.irq = {IRQ_PDMA1, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
static int __init s5pc100_dma_init(void)
|
||||
{
|
||||
platform_add_devices(s5pc100_dmacs, ARRAY_SIZE(s5pc100_dmacs));
|
||||
amba_device_register(&s5pc100_device_pdma0, &iomem_resource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common S3C DMA API driver for PL330 */
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
/* This platform uses the common DMA API driver for PL330 */
|
||||
#include <plat/dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
||||
|
|
|
@ -11,7 +11,7 @@ if ARCH_S5PV210
|
|||
|
||||
config CPU_S5PV210
|
||||
bool
|
||||
select S3C_PL330_DMA
|
||||
select SAMSUNG_DMADEV
|
||||
select S5P_EXT_INT
|
||||
select S5P_HRT
|
||||
select S5PV210_PM if PM
|
||||
|
|
|
@ -203,6 +203,11 @@ static struct clk clk_pcmcdclk2 = {
|
|||
.name = "pcmcdclk",
|
||||
};
|
||||
|
||||
static struct clk dummy_apb_pclk = {
|
||||
.name = "apb_pclk",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct clk *clkset_vpllsrc_list[] = {
|
||||
[0] = &clk_fin_vpll,
|
||||
[1] = &clk_sclk_hdmi27m,
|
||||
|
@ -289,13 +294,13 @@ static struct clk_ops clk_fout_apll_ops = {
|
|||
|
||||
static struct clk init_clocks_off[] = {
|
||||
{
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.0",
|
||||
.parent = &clk_hclk_psys.clk,
|
||||
.enable = s5pv210_clk_ip0_ctrl,
|
||||
.ctrlbit = (1 << 3),
|
||||
}, {
|
||||
.name = "pdma",
|
||||
.name = "dma",
|
||||
.devname = "s3c-pl330.1",
|
||||
.parent = &clk_hclk_psys.clk,
|
||||
.enable = s5pv210_clk_ip0_ctrl,
|
||||
|
@ -1161,5 +1166,6 @@ void __init s5pv210_register_clocks(void)
|
|||
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
|
||||
|
||||
s3c24xx_register_clock(&dummy_apb_pclk);
|
||||
s3c_pwmclk_init();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
/*
|
||||
/* linux/arch/arm/mach-s5pv210/dma.c
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.com>
|
||||
*
|
||||
|
@ -17,151 +21,239 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <plat/devs.h>
|
||||
#include <plat/irqs.h>
|
||||
|
||||
#include <mach/map.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <plat/s3c-pl330-pdata.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
static u64 dma_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct resource s5pv210_pdma0_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV210_PA_PDMA0,
|
||||
.end = S5PV210_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA0,
|
||||
.end = IRQ_PDMA0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
struct dma_pl330_peri pdma0_peri[28] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_MICIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMIN,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_AC97_PCMOUT,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PWM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPDIF,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pv210_pdma0_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_MAX,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S0S_TX,
|
||||
[12] = DMACH_I2S1_RX,
|
||||
[13] = DMACH_I2S1_TX,
|
||||
[14] = DMACH_MAX,
|
||||
[15] = DMACH_MAX,
|
||||
[16] = DMACH_SPI0_RX,
|
||||
[17] = DMACH_SPI0_TX,
|
||||
[18] = DMACH_SPI1_RX,
|
||||
[19] = DMACH_SPI1_TX,
|
||||
[20] = DMACH_MAX,
|
||||
[21] = DMACH_MAX,
|
||||
[22] = DMACH_AC97_MICIN,
|
||||
[23] = DMACH_AC97_PCMIN,
|
||||
[24] = DMACH_AC97_PCMOUT,
|
||||
[25] = DMACH_MAX,
|
||||
[26] = DMACH_PWM,
|
||||
[27] = DMACH_SPDIF,
|
||||
[28] = DMACH_MAX,
|
||||
[29] = DMACH_MAX,
|
||||
[30] = DMACH_MAX,
|
||||
[31] = DMACH_MAX,
|
||||
},
|
||||
struct dma_pl330_platdata s5pv210_pdma0_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma0_peri),
|
||||
.peri = pdma0_peri,
|
||||
};
|
||||
|
||||
static struct platform_device s5pv210_device_pdma0 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_pdma0_resource),
|
||||
.resource = s5pv210_pdma0_resource,
|
||||
.dev = {
|
||||
struct amba_device s5pv210_device_pdma0 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.0",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pv210_pdma0_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource s5pv210_pdma1_resource[] = {
|
||||
[0] = {
|
||||
.start = S5PV210_PA_PDMA1,
|
||||
.end = S5PV210_PA_PDMA1 + SZ_4K,
|
||||
.res = {
|
||||
.start = S5PV210_PA_PDMA0,
|
||||
.end = S5PV210_PA_PDMA0 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_PDMA1,
|
||||
.end = IRQ_PDMA1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
.irq = {IRQ_PDMA0, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
struct dma_pl330_peri pdma1_peri[32] = {
|
||||
{
|
||||
.peri_id = (u8)DMACH_UART0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_UART3_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S0S_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_I2S2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_SPI1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MAX,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM0_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM1_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ0,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ1,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ2,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_MSM_REQ3,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_RX,
|
||||
.rqtype = DEVTOMEM,
|
||||
}, {
|
||||
.peri_id = (u8)DMACH_PCM2_TX,
|
||||
.rqtype = MEMTODEV,
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_pl330_platdata s5pv210_pdma1_pdata = {
|
||||
.peri = {
|
||||
[0] = DMACH_UART0_RX,
|
||||
[1] = DMACH_UART0_TX,
|
||||
[2] = DMACH_UART1_RX,
|
||||
[3] = DMACH_UART1_TX,
|
||||
[4] = DMACH_UART2_RX,
|
||||
[5] = DMACH_UART2_TX,
|
||||
[6] = DMACH_UART3_RX,
|
||||
[7] = DMACH_UART3_TX,
|
||||
[8] = DMACH_MAX,
|
||||
[9] = DMACH_I2S0_RX,
|
||||
[10] = DMACH_I2S0_TX,
|
||||
[11] = DMACH_I2S0S_TX,
|
||||
[12] = DMACH_I2S1_RX,
|
||||
[13] = DMACH_I2S1_TX,
|
||||
[14] = DMACH_I2S2_RX,
|
||||
[15] = DMACH_I2S2_TX,
|
||||
[16] = DMACH_SPI0_RX,
|
||||
[17] = DMACH_SPI0_TX,
|
||||
[18] = DMACH_SPI1_RX,
|
||||
[19] = DMACH_SPI1_TX,
|
||||
[20] = DMACH_MAX,
|
||||
[21] = DMACH_MAX,
|
||||
[22] = DMACH_PCM0_RX,
|
||||
[23] = DMACH_PCM0_TX,
|
||||
[24] = DMACH_PCM1_RX,
|
||||
[25] = DMACH_PCM1_TX,
|
||||
[26] = DMACH_MSM_REQ0,
|
||||
[27] = DMACH_MSM_REQ1,
|
||||
[28] = DMACH_MSM_REQ2,
|
||||
[29] = DMACH_MSM_REQ3,
|
||||
[30] = DMACH_PCM2_RX,
|
||||
[31] = DMACH_PCM2_TX,
|
||||
},
|
||||
struct dma_pl330_platdata s5pv210_pdma1_pdata = {
|
||||
.nr_valid_peri = ARRAY_SIZE(pdma1_peri),
|
||||
.peri = pdma1_peri,
|
||||
};
|
||||
|
||||
static struct platform_device s5pv210_device_pdma1 = {
|
||||
.name = "s3c-pl330",
|
||||
.id = 1,
|
||||
.num_resources = ARRAY_SIZE(s5pv210_pdma1_resource),
|
||||
.resource = s5pv210_pdma1_resource,
|
||||
.dev = {
|
||||
struct amba_device s5pv210_device_pdma1 = {
|
||||
.dev = {
|
||||
.init_name = "dma-pl330.1",
|
||||
.dma_mask = &dma_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s5pv210_pdma1_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *s5pv210_dmacs[] __initdata = {
|
||||
&s5pv210_device_pdma0,
|
||||
&s5pv210_device_pdma1,
|
||||
.res = {
|
||||
.start = S5PV210_PA_PDMA1,
|
||||
.end = S5PV210_PA_PDMA1 + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
.irq = {IRQ_PDMA1, NO_IRQ},
|
||||
.periphid = 0x00041330,
|
||||
};
|
||||
|
||||
static int __init s5pv210_dma_init(void)
|
||||
{
|
||||
platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs));
|
||||
amba_device_register(&s5pv210_device_pdma0, &iomem_resource);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#ifndef __MACH_DMA_H
|
||||
#define __MACH_DMA_H
|
||||
|
||||
/* This platform uses the common S3C DMA API driver for PL330 */
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
/* This platform uses the common DMA API driver for PL330 */
|
||||
#include <plat/dma-pl330.h>
|
||||
|
||||
#endif /* __MACH_DMA_H */
|
||||
|
|
|
@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);
|
|||
*
|
||||
* configure the dma source/destination hardware type and address
|
||||
*
|
||||
* source: S3C2410_DMASRC_HW: source is hardware
|
||||
* S3C2410_DMASRC_MEM: source is memory
|
||||
* source: DMA_FROM_DEVICE: source is hardware
|
||||
* DMA_TO_DEVICE: source is memory
|
||||
*
|
||||
* devaddr: physical address of the source
|
||||
*/
|
||||
|
||||
int s3c2410_dma_devconfig(enum dma_ch channel,
|
||||
enum s3c2410_dmasrc source,
|
||||
enum dma_data_direction source,
|
||||
unsigned long devaddr)
|
||||
{
|
||||
struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
|
||||
|
@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
|
|||
hwcfg |= S3C2410_DISRCC_INC;
|
||||
|
||||
switch (source) {
|
||||
case S3C2410_DMASRC_HW:
|
||||
case DMA_FROM_DEVICE:
|
||||
/* source is hardware */
|
||||
pr_debug("%s: hw source, devaddr=%08lx, hwcfg=%d\n",
|
||||
__func__, devaddr, hwcfg);
|
||||
|
@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(enum dma_ch channel,
|
|||
chan->addr_reg = dma_regaddr(chan, S3C2410_DMA_DIDST);
|
||||
break;
|
||||
|
||||
case S3C2410_DMASRC_MEM:
|
||||
case DMA_TO_DEVICE:
|
||||
/* source is memory */
|
||||
pr_debug("%s: mem source, devaddr=%08lx, hwcfg=%d\n",
|
||||
__func__, devaddr, hwcfg);
|
||||
|
|
|
@ -300,11 +300,14 @@ config S3C_DMA
|
|||
help
|
||||
Internal configuration for S3C DMA core
|
||||
|
||||
config S3C_PL330_DMA
|
||||
config SAMSUNG_DMADEV
|
||||
bool
|
||||
select PL330
|
||||
select DMADEVICES
|
||||
select PL330_DMA if (CPU_EXYNOS4210 || CPU_S5PV210 || CPU_S5PC100 || \
|
||||
CPU_S5P6450 || CPU_S5P6440)
|
||||
select ARM_AMBA
|
||||
help
|
||||
S3C DMA API Driver for PL330 DMAC.
|
||||
Use DMA device engine for PL330 DMAC.
|
||||
|
||||
comment "Power management"
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
|
|||
|
||||
# DMA support
|
||||
|
||||
obj-$(CONFIG_S3C_DMA) += dma.o
|
||||
obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o
|
||||
|
||||
obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o
|
||||
obj-$(CONFIG_SAMSUNG_DMADEV) += dma-ops.o
|
||||
|
||||
# PM support
|
||||
|
||||
|
|
131
arch/arm/plat-samsung/dma-ops.c
Normal file
131
arch/arm/plat-samsung/dma-ops.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* linux/arch/arm/plat-samsung/dma-ops.c
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung DMA Operations
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
static inline bool pl330_filter(struct dma_chan *chan, void *param)
|
||||
{
|
||||
struct dma_pl330_peri *peri = chan->private;
|
||||
return peri->peri_id == (unsigned)param;
|
||||
}
|
||||
|
||||
static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
|
||||
struct samsung_dma_info *info)
|
||||
{
|
||||
struct dma_chan *chan;
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_slave_config slave_config;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(info->cap, mask);
|
||||
|
||||
chan = dma_request_channel(mask, pl330_filter, (void *)dma_ch);
|
||||
|
||||
if (info->direction == DMA_FROM_DEVICE) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = info->direction;
|
||||
slave_config.src_addr = info->fifo;
|
||||
slave_config.src_addr_width = info->width;
|
||||
slave_config.src_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
} else if (info->direction == DMA_TO_DEVICE) {
|
||||
memset(&slave_config, 0, sizeof(struct dma_slave_config));
|
||||
slave_config.direction = info->direction;
|
||||
slave_config.dst_addr = info->fifo;
|
||||
slave_config.dst_addr_width = info->width;
|
||||
slave_config.dst_maxburst = 1;
|
||||
dmaengine_slave_config(chan, &slave_config);
|
||||
}
|
||||
|
||||
return (unsigned)chan;
|
||||
}
|
||||
|
||||
static int samsung_dmadev_release(unsigned ch,
|
||||
struct s3c2410_dma_client *client)
|
||||
{
|
||||
dma_release_channel((struct dma_chan *)ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int samsung_dmadev_prepare(unsigned ch,
|
||||
struct samsung_dma_prep_info *info)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
struct dma_chan *chan = (struct dma_chan *)ch;
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
|
||||
switch (info->cap) {
|
||||
case DMA_SLAVE:
|
||||
sg_init_table(&sg, 1);
|
||||
sg_dma_len(&sg) = info->len;
|
||||
sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
|
||||
info->len, offset_in_page(info->buf));
|
||||
sg_dma_address(&sg) = info->buf;
|
||||
|
||||
desc = chan->device->device_prep_slave_sg(chan,
|
||||
&sg, 1, info->direction, DMA_PREP_INTERRUPT);
|
||||
break;
|
||||
case DMA_CYCLIC:
|
||||
desc = chan->device->device_prep_dma_cyclic(chan,
|
||||
info->buf, info->len, info->period, info->direction);
|
||||
break;
|
||||
default:
|
||||
dev_err(&chan->dev->device, "unsupported format\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!desc) {
|
||||
dev_err(&chan->dev->device, "cannot prepare cyclic dma\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
desc->callback = info->fp;
|
||||
desc->callback_param = info->fp_param;
|
||||
|
||||
dmaengine_submit((struct dma_async_tx_descriptor *)desc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int samsung_dmadev_trigger(unsigned ch)
|
||||
{
|
||||
dma_async_issue_pending((struct dma_chan *)ch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int samsung_dmadev_flush(unsigned ch)
|
||||
{
|
||||
return dmaengine_terminate_all((struct dma_chan *)ch);
|
||||
}
|
||||
|
||||
struct samsung_dma_ops dmadev_ops = {
|
||||
.request = samsung_dmadev_request,
|
||||
.release = samsung_dmadev_release,
|
||||
.prepare = samsung_dmadev_prepare,
|
||||
.trigger = samsung_dmadev_trigger,
|
||||
.started = NULL,
|
||||
.flush = samsung_dmadev_flush,
|
||||
.stop = samsung_dmadev_flush,
|
||||
};
|
||||
|
||||
void *samsung_dmadev_get_ops(void)
|
||||
{
|
||||
return &dmadev_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(samsung_dmadev_get_ops);
|
63
arch/arm/plat-samsung/include/plat/dma-ops.h
Normal file
63
arch/arm/plat-samsung/include/plat/dma-ops.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/* arch/arm/plat-samsung/include/plat/dma-ops.h
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung DMA support
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __SAMSUNG_DMA_OPS_H_
|
||||
#define __SAMSUNG_DMA_OPS_H_ __FILE__
|
||||
|
||||
#include <linux/dmaengine.h>
|
||||
|
||||
struct samsung_dma_prep_info {
|
||||
enum dma_transaction_type cap;
|
||||
enum dma_data_direction direction;
|
||||
dma_addr_t buf;
|
||||
unsigned long period;
|
||||
unsigned long len;
|
||||
void (*fp)(void *data);
|
||||
void *fp_param;
|
||||
};
|
||||
|
||||
struct samsung_dma_info {
|
||||
enum dma_transaction_type cap;
|
||||
enum dma_data_direction direction;
|
||||
enum dma_slave_buswidth width;
|
||||
dma_addr_t fifo;
|
||||
struct s3c2410_dma_client *client;
|
||||
};
|
||||
|
||||
struct samsung_dma_ops {
|
||||
unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
|
||||
int (*release)(unsigned ch, struct s3c2410_dma_client *client);
|
||||
int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
|
||||
int (*trigger)(unsigned ch);
|
||||
int (*started)(unsigned ch);
|
||||
int (*flush)(unsigned ch);
|
||||
int (*stop)(unsigned ch);
|
||||
};
|
||||
|
||||
extern void *samsung_dmadev_get_ops(void);
|
||||
extern void *s3c_dma_get_ops(void);
|
||||
|
||||
static inline void *__samsung_dma_get_ops(void)
|
||||
{
|
||||
if (samsung_dma_is_dmadev())
|
||||
return samsung_dmadev_get_ops();
|
||||
else
|
||||
return s3c_dma_get_ops();
|
||||
}
|
||||
|
||||
/*
|
||||
* samsung_dma_get_ops
|
||||
* get the set of samsung dma operations
|
||||
*/
|
||||
#define samsung_dma_get_ops() __samsung_dma_get_ops()
|
||||
|
||||
#endif /* __SAMSUNG_DMA_OPS_H_ */
|
|
@ -8,11 +8,8 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __S3C_DMA_PL330_H_
|
||||
#define __S3C_DMA_PL330_H_
|
||||
|
||||
#define S3C2410_DMAF_AUTOSTART (1 << 0)
|
||||
#define S3C2410_DMAF_CIRCULAR (1 << 1)
|
||||
#ifndef __DMA_PL330_H_
|
||||
#define __DMA_PL330_H_ __FILE__
|
||||
|
||||
/*
|
||||
* PL330 can assign any channel to communicate with
|
||||
|
@ -20,7 +17,7 @@
|
|||
* For the sake of consistency across client drivers,
|
||||
* We keep the channel names unchanged and only add
|
||||
* missing peripherals are added.
|
||||
* Order is not important since S3C PL330 API driver
|
||||
* Order is not important since DMA PL330 API driver
|
||||
* use these just as IDs.
|
||||
*/
|
||||
enum dma_ch {
|
||||
|
@ -88,11 +85,20 @@ enum dma_ch {
|
|||
DMACH_MAX,
|
||||
};
|
||||
|
||||
static inline bool s3c_dma_has_circular(void)
|
||||
struct s3c2410_dma_client {
|
||||
char *name;
|
||||
};
|
||||
|
||||
static inline bool samsung_dma_has_circular(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#include <plat/dma.h>
|
||||
static inline bool samsung_dma_is_dmadev(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* __S3C_DMA_PL330_H_ */
|
||||
#include <plat/dma-ops.h>
|
||||
|
||||
#endif /* __DMA_PL330_H_ */
|
|
@ -47,7 +47,7 @@ struct s3c24xx_dma_selection {
|
|||
|
||||
void (*direction)(struct s3c2410_dma_chan *chan,
|
||||
struct s3c24xx_dma_map *map,
|
||||
enum s3c2410_dmasrc dir);
|
||||
enum dma_data_direction dir);
|
||||
};
|
||||
|
||||
extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
|
||||
|
|
|
@ -10,17 +10,14 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
enum s3c2410_dma_buffresult {
|
||||
S3C2410_RES_OK,
|
||||
S3C2410_RES_ERR,
|
||||
S3C2410_RES_ABORT
|
||||
};
|
||||
|
||||
enum s3c2410_dmasrc {
|
||||
S3C2410_DMASRC_HW, /* source is memory */
|
||||
S3C2410_DMASRC_MEM /* source is hardware */
|
||||
};
|
||||
|
||||
/* enum s3c2410_chan_op
|
||||
*
|
||||
* operation codes passed to the DMA code by the user, and also used
|
||||
|
@ -112,7 +109,7 @@ extern int s3c2410_dma_config(enum dma_ch channel, int xferunit);
|
|||
*/
|
||||
|
||||
extern int s3c2410_dma_devconfig(enum dma_ch channel,
|
||||
enum s3c2410_dmasrc source, unsigned long devaddr);
|
||||
enum dma_data_direction source, unsigned long devaddr);
|
||||
|
||||
/* s3c2410_dma_getposition
|
||||
*
|
||||
|
@ -126,3 +123,4 @@ extern int s3c2410_dma_set_opfn(enum dma_ch, s3c2410_dma_opfn_t rtn);
|
|||
extern int s3c2410_dma_set_buffdone_fn(enum dma_ch, s3c2410_dma_cbfn_t rtn);
|
||||
|
||||
|
||||
#include <plat/dma-ops.h>
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h
|
||||
*
|
||||
* Copyright (C) 2010 Samsung Electronics Co. Ltd.
|
||||
* Jaswinder Singh <jassi.brar@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifndef __S3C_PL330_PDATA_H
|
||||
#define __S3C_PL330_PDATA_H
|
||||
|
||||
#include <plat/s3c-dma-pl330.h>
|
||||
|
||||
/*
|
||||
* Every PL330 DMAC has max 32 peripheral interfaces,
|
||||
* of which some may be not be really used in your
|
||||
* DMAC's configuration.
|
||||
* Populate this array of 32 peri i/fs with relevant
|
||||
* channel IDs for used peri i/f and DMACH_MAX for
|
||||
* those unused.
|
||||
*
|
||||
* The platforms just need to provide this info
|
||||
* to the S3C DMA API driver for PL330.
|
||||
*/
|
||||
struct s3c_pl330_platdata {
|
||||
enum dma_ch peri[32];
|
||||
};
|
||||
|
||||
#endif /* __S3C_PL330_PDATA_H */
|
130
arch/arm/plat-samsung/s3c-dma-ops.c
Normal file
130
arch/arm/plat-samsung/s3c-dma-ops.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* linux/arch/arm/plat-samsung/s3c-dma-ops.c
|
||||
*
|
||||
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
*
|
||||
* Samsung S3C-DMA Operations
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
struct cb_data {
|
||||
void (*fp) (void *);
|
||||
void *fp_param;
|
||||
unsigned ch;
|
||||
struct list_head node;
|
||||
};
|
||||
|
||||
static LIST_HEAD(dma_list);
|
||||
|
||||
static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
|
||||
int size, enum s3c2410_dma_buffresult res)
|
||||
{
|
||||
struct cb_data *data = param;
|
||||
|
||||
data->fp(data->fp_param);
|
||||
}
|
||||
|
||||
static unsigned s3c_dma_request(enum dma_ch dma_ch,
|
||||
struct samsung_dma_info *info)
|
||||
{
|
||||
struct cb_data *data;
|
||||
|
||||
if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
|
||||
s3c2410_dma_free(dma_ch, info->client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
|
||||
data->ch = dma_ch;
|
||||
list_add_tail(&data->node, &dma_list);
|
||||
|
||||
s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
|
||||
|
||||
if (info->cap == DMA_CYCLIC)
|
||||
s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
|
||||
|
||||
s3c2410_dma_config(dma_ch, info->width);
|
||||
|
||||
return (unsigned)dma_ch;
|
||||
}
|
||||
|
||||
static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
|
||||
{
|
||||
struct cb_data *data;
|
||||
|
||||
list_for_each_entry(data, &dma_list, node)
|
||||
if (data->ch == ch)
|
||||
break;
|
||||
list_del(&data->node);
|
||||
|
||||
s3c2410_dma_free(ch, client);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
|
||||
{
|
||||
struct cb_data *data;
|
||||
int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
|
||||
|
||||
list_for_each_entry(data, &dma_list, node)
|
||||
if (data->ch == ch)
|
||||
break;
|
||||
|
||||
if (!data->fp) {
|
||||
s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
|
||||
data->fp = info->fp;
|
||||
data->fp_param = info->fp_param;
|
||||
}
|
||||
|
||||
s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int s3c_dma_trigger(unsigned ch)
|
||||
{
|
||||
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START);
|
||||
}
|
||||
|
||||
static inline int s3c_dma_started(unsigned ch)
|
||||
{
|
||||
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED);
|
||||
}
|
||||
|
||||
static inline int s3c_dma_flush(unsigned ch)
|
||||
{
|
||||
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH);
|
||||
}
|
||||
|
||||
static inline int s3c_dma_stop(unsigned ch)
|
||||
{
|
||||
return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
|
||||
}
|
||||
|
||||
static struct samsung_dma_ops s3c_dma_ops = {
|
||||
.request = s3c_dma_request,
|
||||
.release = s3c_dma_release,
|
||||
.prepare = s3c_dma_prepare,
|
||||
.trigger = s3c_dma_trigger,
|
||||
.started = s3c_dma_started,
|
||||
.flush = s3c_dma_flush,
|
||||
.stop = s3c_dma_stop,
|
||||
};
|
||||
|
||||
void *s3c_dma_get_ops(void)
|
||||
{
|
||||
return &s3c_dma_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(s3c_dma_get_ops);
|
File diff suppressed because it is too large
Load Diff
|
@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL
|
|||
config PL330_DMA
|
||||
tristate "DMA API Driver for PL330"
|
||||
select DMA_ENGINE
|
||||
depends on PL330
|
||||
depends on ARM_AMBA
|
||||
select PL330
|
||||
help
|
||||
Select if your platform has one or more PL330 DMACs.
|
||||
You need to provide platform specific settings via
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/pl330.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#define NR_DEFAULT_DESC 16
|
||||
|
||||
|
@ -68,6 +70,14 @@ struct dma_pl330_chan {
|
|||
* NULL if the channel is available to be acquired.
|
||||
*/
|
||||
void *pl330_chid;
|
||||
|
||||
/* For D-to-M and M-to-D channels */
|
||||
int burst_sz; /* the peripheral fifo width */
|
||||
int burst_len; /* the number of burst */
|
||||
dma_addr_t fifo_addr;
|
||||
|
||||
/* for cyclic capability */
|
||||
bool cyclic;
|
||||
};
|
||||
|
||||
struct dma_pl330_dmac {
|
||||
|
@ -83,6 +93,8 @@ struct dma_pl330_dmac {
|
|||
|
||||
/* Peripheral channels connected to this DMAC */
|
||||
struct dma_pl330_chan *peripherals; /* keep at end */
|
||||
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
struct dma_pl330_desc {
|
||||
|
@ -152,6 +164,31 @@ static inline void free_desc_list(struct list_head *list)
|
|||
spin_unlock_irqrestore(&pdmac->pool_lock, flags);
|
||||
}
|
||||
|
||||
static inline void handle_cyclic_desc_list(struct list_head *list)
|
||||
{
|
||||
struct dma_pl330_desc *desc;
|
||||
struct dma_pl330_chan *pch;
|
||||
unsigned long flags;
|
||||
|
||||
if (list_empty(list))
|
||||
return;
|
||||
|
||||
list_for_each_entry(desc, list, node) {
|
||||
dma_async_tx_callback callback;
|
||||
|
||||
/* Change status to reload it */
|
||||
desc->status = PREP;
|
||||
pch = desc->pchan;
|
||||
callback = desc->txd.callback;
|
||||
if (callback)
|
||||
callback(desc->txd.callback_param);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
list_splice_tail_init(list, &pch->work_list);
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
}
|
||||
|
||||
static inline void fill_queue(struct dma_pl330_chan *pch)
|
||||
{
|
||||
struct dma_pl330_desc *desc;
|
||||
|
@ -205,7 +242,10 @@ static void pl330_tasklet(unsigned long data)
|
|||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
|
||||
free_desc_list(&list);
|
||||
if (pch->cyclic)
|
||||
handle_cyclic_desc_list(&list);
|
||||
else
|
||||
free_desc_list(&list);
|
||||
}
|
||||
|
||||
static void dma_pl330_rqcb(void *token, enum pl330_op_err err)
|
||||
|
@ -236,6 +276,7 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
|
|||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
pch->completed = chan->cookie = 1;
|
||||
pch->cyclic = false;
|
||||
|
||||
pch->pl330_chid = pl330_request_channel(&pdmac->pif);
|
||||
if (!pch->pl330_chid) {
|
||||
|
@ -253,25 +294,52 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)
|
|||
static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg)
|
||||
{
|
||||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||||
struct dma_pl330_desc *desc;
|
||||
struct dma_pl330_desc *desc, *_dt;
|
||||
unsigned long flags;
|
||||
struct dma_pl330_dmac *pdmac = pch->dmac;
|
||||
struct dma_slave_config *slave_config;
|
||||
LIST_HEAD(list);
|
||||
|
||||
/* Only supports DMA_TERMINATE_ALL */
|
||||
if (cmd != DMA_TERMINATE_ALL)
|
||||
switch (cmd) {
|
||||
case DMA_TERMINATE_ALL:
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
/* FLUSH the PL330 Channel thread */
|
||||
pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
|
||||
|
||||
/* Mark all desc done */
|
||||
list_for_each_entry_safe(desc, _dt, &pch->work_list , node) {
|
||||
desc->status = DONE;
|
||||
pch->completed = desc->txd.cookie;
|
||||
list_move_tail(&desc->node, &list);
|
||||
}
|
||||
|
||||
list_splice_tail_init(&list, &pdmac->desc_pool);
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
break;
|
||||
case DMA_SLAVE_CONFIG:
|
||||
slave_config = (struct dma_slave_config *)arg;
|
||||
|
||||
if (slave_config->direction == DMA_TO_DEVICE) {
|
||||
if (slave_config->dst_addr)
|
||||
pch->fifo_addr = slave_config->dst_addr;
|
||||
if (slave_config->dst_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->dst_addr_width);
|
||||
if (slave_config->dst_maxburst)
|
||||
pch->burst_len = slave_config->dst_maxburst;
|
||||
} else if (slave_config->direction == DMA_FROM_DEVICE) {
|
||||
if (slave_config->src_addr)
|
||||
pch->fifo_addr = slave_config->src_addr;
|
||||
if (slave_config->src_addr_width)
|
||||
pch->burst_sz = __ffs(slave_config->src_addr_width);
|
||||
if (slave_config->src_maxburst)
|
||||
pch->burst_len = slave_config->src_maxburst;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dev_err(pch->dmac->pif.dev, "Not supported command.\n");
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&pch->lock, flags);
|
||||
|
||||
/* FLUSH the PL330 Channel thread */
|
||||
pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH);
|
||||
|
||||
/* Mark all desc done */
|
||||
list_for_each_entry(desc, &pch->work_list, node)
|
||||
desc->status = DONE;
|
||||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
|
||||
pl330_tasklet((unsigned long) pch);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -288,6 +356,9 @@ static void pl330_free_chan_resources(struct dma_chan *chan)
|
|||
pl330_release_channel(pch->pl330_chid);
|
||||
pch->pl330_chid = NULL;
|
||||
|
||||
if (pch->cyclic)
|
||||
list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
|
||||
|
||||
spin_unlock_irqrestore(&pch->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -453,7 +524,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
|
|||
|
||||
if (peri) {
|
||||
desc->req.rqtype = peri->rqtype;
|
||||
desc->req.peri = peri->peri_id;
|
||||
desc->req.peri = pch->chan.chan_id;
|
||||
} else {
|
||||
desc->req.rqtype = MEMTOMEM;
|
||||
desc->req.peri = 0;
|
||||
|
@ -524,6 +595,51 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
|
|||
return burst_len;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic(
|
||||
struct dma_chan *chan, dma_addr_t dma_addr, size_t len,
|
||||
size_t period_len, enum dma_data_direction direction)
|
||||
{
|
||||
struct dma_pl330_desc *desc;
|
||||
struct dma_pl330_chan *pch = to_pchan(chan);
|
||||
dma_addr_t dst;
|
||||
dma_addr_t src;
|
||||
|
||||
desc = pl330_get_desc(pch);
|
||||
if (!desc) {
|
||||
dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n",
|
||||
__func__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
case DMA_TO_DEVICE:
|
||||
desc->rqcfg.src_inc = 1;
|
||||
desc->rqcfg.dst_inc = 0;
|
||||
src = dma_addr;
|
||||
dst = pch->fifo_addr;
|
||||
break;
|
||||
case DMA_FROM_DEVICE:
|
||||
desc->rqcfg.src_inc = 0;
|
||||
desc->rqcfg.dst_inc = 1;
|
||||
src = pch->fifo_addr;
|
||||
dst = dma_addr;
|
||||
break;
|
||||
default:
|
||||
dev_err(pch->dmac->pif.dev, "%s:%d Invalid dma direction\n",
|
||||
__func__, __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc->rqcfg.brst_size = pch->burst_sz;
|
||||
desc->rqcfg.brst_len = 1;
|
||||
|
||||
pch->cyclic = true;
|
||||
|
||||
fill_px(&desc->px, dst, src, period_len);
|
||||
|
||||
return &desc->txd;
|
||||
}
|
||||
|
||||
static struct dma_async_tx_descriptor *
|
||||
pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst,
|
||||
dma_addr_t src, size_t len, unsigned long flags)
|
||||
|
@ -579,7 +695,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
struct dma_pl330_peri *peri = chan->private;
|
||||
struct scatterlist *sg;
|
||||
unsigned long flags;
|
||||
int i, burst_size;
|
||||
int i;
|
||||
dma_addr_t addr;
|
||||
|
||||
if (unlikely(!pch || !sgl || !sg_len || !peri))
|
||||
|
@ -595,8 +711,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
addr = peri->fifo_addr;
|
||||
burst_size = peri->burst_sz;
|
||||
addr = pch->fifo_addr;
|
||||
|
||||
first = NULL;
|
||||
|
||||
|
@ -644,7 +759,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
|
|||
sg_dma_address(sg), addr, sg_dma_len(sg));
|
||||
}
|
||||
|
||||
desc->rqcfg.brst_size = burst_size;
|
||||
desc->rqcfg.brst_size = pch->burst_sz;
|
||||
desc->rqcfg.brst_len = 1;
|
||||
}
|
||||
|
||||
|
@ -696,6 +811,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
goto probe_err1;
|
||||
}
|
||||
|
||||
pdmac->clk = clk_get(&adev->dev, "dma");
|
||||
if (IS_ERR(pdmac->clk)) {
|
||||
dev_err(&adev->dev, "Cannot get operation clock.\n");
|
||||
ret = -EINVAL;
|
||||
goto probe_err1;
|
||||
}
|
||||
|
||||
amba_set_drvdata(adev, pdmac);
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
/* to use the runtime PM helper functions */
|
||||
pm_runtime_enable(&adev->dev);
|
||||
|
||||
/* enable the power domain */
|
||||
if (pm_runtime_get_sync(&adev->dev)) {
|
||||
dev_err(&adev->dev, "failed to get runtime pm\n");
|
||||
ret = -ENODEV;
|
||||
goto probe_err1;
|
||||
}
|
||||
#else
|
||||
/* enable dma clk */
|
||||
clk_enable(pdmac->clk);
|
||||
#endif
|
||||
|
||||
irq = adev->irq[0];
|
||||
ret = request_irq(irq, pl330_irq_handler, 0,
|
||||
dev_name(&adev->dev), pi);
|
||||
|
@ -732,6 +871,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
case MEMTODEV:
|
||||
case DEVTOMEM:
|
||||
dma_cap_set(DMA_SLAVE, pd->cap_mask);
|
||||
dma_cap_set(DMA_CYCLIC, pd->cap_mask);
|
||||
break;
|
||||
default:
|
||||
dev_err(&adev->dev, "DEVTODEV Not Supported\n");
|
||||
|
@ -758,6 +898,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
|
||||
pd->device_free_chan_resources = pl330_free_chan_resources;
|
||||
pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy;
|
||||
pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic;
|
||||
pd->device_tx_status = pl330_tx_status;
|
||||
pd->device_prep_slave_sg = pl330_prep_slave_sg;
|
||||
pd->device_control = pl330_control;
|
||||
|
@ -769,8 +910,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
goto probe_err4;
|
||||
}
|
||||
|
||||
amba_set_drvdata(adev, pdmac);
|
||||
|
||||
dev_info(&adev->dev,
|
||||
"Loaded driver for PL330 DMAC-%d\n", adev->periphid);
|
||||
dev_info(&adev->dev,
|
||||
|
@ -831,6 +970,13 @@ static int __devexit pl330_remove(struct amba_device *adev)
|
|||
res = &adev->res;
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
pm_runtime_put(&adev->dev);
|
||||
pm_runtime_disable(&adev->dev);
|
||||
#else
|
||||
clk_disable(pdmac->clk);
|
||||
#endif
|
||||
|
||||
kfree(pdmac);
|
||||
|
||||
return 0;
|
||||
|
@ -844,10 +990,49 @@ static struct amba_id pl330_ids[] = {
|
|||
{ 0, 0 },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int pl330_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
|
||||
|
||||
if (!pdmac) {
|
||||
dev_err(dev, "failed to get dmac\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
clk_disable(pdmac->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pl330_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct dma_pl330_dmac *pdmac = dev_get_drvdata(dev);
|
||||
|
||||
if (!pdmac) {
|
||||
dev_err(dev, "failed to get dmac\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
clk_enable(pdmac->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pl330_runtime_suspend NULL
|
||||
#define pl330_runtime_resume NULL
|
||||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
||||
static const struct dev_pm_ops pl330_pm_ops = {
|
||||
.runtime_suspend = pl330_runtime_suspend,
|
||||
.runtime_resume = pl330_runtime_resume,
|
||||
};
|
||||
|
||||
static struct amba_driver pl330_driver = {
|
||||
.drv = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "dma-pl330",
|
||||
.pm = &pl330_pm_ops,
|
||||
},
|
||||
.id_table = pl330_ids,
|
||||
.probe = pl330_probe,
|
||||
|
|
|
@ -913,9 +913,9 @@ static void finalize_request(struct s3cmci_host *host)
|
|||
}
|
||||
|
||||
static void s3cmci_dma_setup(struct s3cmci_host *host,
|
||||
enum s3c2410_dmasrc source)
|
||||
enum dma_data_direction source)
|
||||
{
|
||||
static enum s3c2410_dmasrc last_source = -1;
|
||||
static enum dma_data_direction last_source = -1;
|
||||
static int setup_ok;
|
||||
|
||||
if (last_source == source)
|
||||
|
@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
|
|||
|
||||
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
|
||||
|
||||
s3cmci_dma_setup(host, rw ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
|
||||
s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
|
||||
|
||||
dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
||||
|
|
|
@ -131,6 +131,12 @@
|
|||
#define RXBUSY (1<<2)
|
||||
#define TXBUSY (1<<3)
|
||||
|
||||
struct s3c64xx_spi_dma_data {
|
||||
unsigned ch;
|
||||
enum dma_data_direction direction;
|
||||
enum dma_ch dmach;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver.
|
||||
* @clk: Pointer to the spi clock.
|
||||
|
@ -164,13 +170,14 @@ struct s3c64xx_spi_driver_data {
|
|||
struct work_struct work;
|
||||
struct list_head queue;
|
||||
spinlock_t lock;
|
||||
enum dma_ch rx_dmach;
|
||||
enum dma_ch tx_dmach;
|
||||
unsigned long sfr_start;
|
||||
struct completion xfer_completion;
|
||||
unsigned state;
|
||||
unsigned cur_mode, cur_bpw;
|
||||
unsigned cur_speed;
|
||||
struct s3c64xx_spi_dma_data rx_dma;
|
||||
struct s3c64xx_spi_dma_data tx_dma;
|
||||
struct samsung_dma_ops *ops;
|
||||
};
|
||||
|
||||
static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
|
||||
|
@ -226,6 +233,78 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
|
|||
writel(val, regs + S3C64XX_SPI_CH_CFG);
|
||||
}
|
||||
|
||||
static void s3c64xx_spi_dmacb(void *data)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd;
|
||||
struct s3c64xx_spi_dma_data *dma = data;
|
||||
unsigned long flags;
|
||||
|
||||
if (dma->direction == DMA_FROM_DEVICE)
|
||||
sdd = container_of(data,
|
||||
struct s3c64xx_spi_driver_data, rx_dma);
|
||||
else
|
||||
sdd = container_of(data,
|
||||
struct s3c64xx_spi_driver_data, tx_dma);
|
||||
|
||||
spin_lock_irqsave(&sdd->lock, flags);
|
||||
|
||||
if (dma->direction == DMA_FROM_DEVICE) {
|
||||
sdd->state &= ~RXBUSY;
|
||||
if (!(sdd->state & TXBUSY))
|
||||
complete(&sdd->xfer_completion);
|
||||
} else {
|
||||
sdd->state &= ~TXBUSY;
|
||||
if (!(sdd->state & RXBUSY))
|
||||
complete(&sdd->xfer_completion);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&sdd->lock, flags);
|
||||
}
|
||||
|
||||
static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
|
||||
unsigned len, dma_addr_t buf)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd;
|
||||
struct samsung_dma_prep_info info;
|
||||
|
||||
if (dma->direction == DMA_FROM_DEVICE)
|
||||
sdd = container_of((void *)dma,
|
||||
struct s3c64xx_spi_driver_data, rx_dma);
|
||||
else
|
||||
sdd = container_of((void *)dma,
|
||||
struct s3c64xx_spi_driver_data, tx_dma);
|
||||
|
||||
info.cap = DMA_SLAVE;
|
||||
info.len = len;
|
||||
info.fp = s3c64xx_spi_dmacb;
|
||||
info.fp_param = dma;
|
||||
info.direction = dma->direction;
|
||||
info.buf = buf;
|
||||
|
||||
sdd->ops->prepare(dma->ch, &info);
|
||||
sdd->ops->trigger(dma->ch);
|
||||
}
|
||||
|
||||
static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
|
||||
{
|
||||
struct samsung_dma_info info;
|
||||
|
||||
sdd->ops = samsung_dma_get_ops();
|
||||
|
||||
info.cap = DMA_SLAVE;
|
||||
info.client = &s3c64xx_spi_dma_client;
|
||||
info.width = sdd->cur_bpw / 8;
|
||||
|
||||
info.direction = sdd->rx_dma.direction;
|
||||
info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
|
||||
sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
|
||||
info.direction = sdd->tx_dma.direction;
|
||||
info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
|
||||
sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
|
||||
struct spi_device *spi,
|
||||
struct spi_transfer *xfer, int dma_mode)
|
||||
|
@ -258,10 +337,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
|
|||
chcfg |= S3C64XX_SPI_CH_TXCH_ON;
|
||||
if (dma_mode) {
|
||||
modecfg |= S3C64XX_SPI_MODE_TXDMA_ON;
|
||||
s3c2410_dma_config(sdd->tx_dmach, sdd->cur_bpw / 8);
|
||||
s3c2410_dma_enqueue(sdd->tx_dmach, (void *)sdd,
|
||||
xfer->tx_dma, xfer->len);
|
||||
s3c2410_dma_ctrl(sdd->tx_dmach, S3C2410_DMAOP_START);
|
||||
prepare_dma(&sdd->tx_dma, xfer->len, xfer->tx_dma);
|
||||
} else {
|
||||
switch (sdd->cur_bpw) {
|
||||
case 32:
|
||||
|
@ -293,10 +369,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
|
|||
writel(((xfer->len * 8 / sdd->cur_bpw) & 0xffff)
|
||||
| S3C64XX_SPI_PACKET_CNT_EN,
|
||||
regs + S3C64XX_SPI_PACKET_CNT);
|
||||
s3c2410_dma_config(sdd->rx_dmach, sdd->cur_bpw / 8);
|
||||
s3c2410_dma_enqueue(sdd->rx_dmach, (void *)sdd,
|
||||
xfer->rx_dma, xfer->len);
|
||||
s3c2410_dma_ctrl(sdd->rx_dmach, S3C2410_DMAOP_START);
|
||||
prepare_dma(&sdd->rx_dma, xfer->len, xfer->rx_dma);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,46 +555,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
|
|||
}
|
||||
}
|
||||
|
||||
static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan, void *buf_id,
|
||||
int size, enum s3c2410_dma_buffresult res)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd = buf_id;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sdd->lock, flags);
|
||||
|
||||
if (res == S3C2410_RES_OK)
|
||||
sdd->state &= ~RXBUSY;
|
||||
else
|
||||
dev_err(&sdd->pdev->dev, "DmaAbrtRx-%d\n", size);
|
||||
|
||||
/* If the other done */
|
||||
if (!(sdd->state & TXBUSY))
|
||||
complete(&sdd->xfer_completion);
|
||||
|
||||
spin_unlock_irqrestore(&sdd->lock, flags);
|
||||
}
|
||||
|
||||
static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan, void *buf_id,
|
||||
int size, enum s3c2410_dma_buffresult res)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd = buf_id;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sdd->lock, flags);
|
||||
|
||||
if (res == S3C2410_RES_OK)
|
||||
sdd->state &= ~TXBUSY;
|
||||
else
|
||||
dev_err(&sdd->pdev->dev, "DmaAbrtTx-%d \n", size);
|
||||
|
||||
/* If the other done */
|
||||
if (!(sdd->state & RXBUSY))
|
||||
complete(&sdd->xfer_completion);
|
||||
|
||||
spin_unlock_irqrestore(&sdd->lock, flags);
|
||||
}
|
||||
|
||||
#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32)
|
||||
|
||||
static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
|
||||
|
@ -696,12 +729,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
|
|||
if (use_dma) {
|
||||
if (xfer->tx_buf != NULL
|
||||
&& (sdd->state & TXBUSY))
|
||||
s3c2410_dma_ctrl(sdd->tx_dmach,
|
||||
S3C2410_DMAOP_FLUSH);
|
||||
sdd->ops->stop(sdd->tx_dma.ch);
|
||||
if (xfer->rx_buf != NULL
|
||||
&& (sdd->state & RXBUSY))
|
||||
s3c2410_dma_ctrl(sdd->rx_dmach,
|
||||
S3C2410_DMAOP_FLUSH);
|
||||
sdd->ops->stop(sdd->rx_dma.ch);
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
@ -739,30 +770,6 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,
|
|||
msg->complete(msg->context);
|
||||
}
|
||||
|
||||
static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
|
||||
{
|
||||
if (s3c2410_dma_request(sdd->rx_dmach,
|
||||
&s3c64xx_spi_dma_client, NULL) < 0) {
|
||||
dev_err(&sdd->pdev->dev, "cannot get RxDMA\n");
|
||||
return 0;
|
||||
}
|
||||
s3c2410_dma_set_buffdone_fn(sdd->rx_dmach, s3c64xx_spi_dma_rxcb);
|
||||
s3c2410_dma_devconfig(sdd->rx_dmach, S3C2410_DMASRC_HW,
|
||||
sdd->sfr_start + S3C64XX_SPI_RX_DATA);
|
||||
|
||||
if (s3c2410_dma_request(sdd->tx_dmach,
|
||||
&s3c64xx_spi_dma_client, NULL) < 0) {
|
||||
dev_err(&sdd->pdev->dev, "cannot get TxDMA\n");
|
||||
s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
|
||||
return 0;
|
||||
}
|
||||
s3c2410_dma_set_buffdone_fn(sdd->tx_dmach, s3c64xx_spi_dma_txcb);
|
||||
s3c2410_dma_devconfig(sdd->tx_dmach, S3C2410_DMASRC_MEM,
|
||||
sdd->sfr_start + S3C64XX_SPI_TX_DATA);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void s3c64xx_spi_work(struct work_struct *work)
|
||||
{
|
||||
struct s3c64xx_spi_driver_data *sdd = container_of(work,
|
||||
|
@ -799,8 +806,8 @@ static void s3c64xx_spi_work(struct work_struct *work)
|
|||
spin_unlock_irqrestore(&sdd->lock, flags);
|
||||
|
||||
/* Free DMA channels */
|
||||
s3c2410_dma_free(sdd->tx_dmach, &s3c64xx_spi_dma_client);
|
||||
s3c2410_dma_free(sdd->rx_dmach, &s3c64xx_spi_dma_client);
|
||||
sdd->ops->release(sdd->rx_dma.ch, &s3c64xx_spi_dma_client);
|
||||
sdd->ops->release(sdd->tx_dma.ch, &s3c64xx_spi_dma_client);
|
||||
}
|
||||
|
||||
static int s3c64xx_spi_transfer(struct spi_device *spi,
|
||||
|
@ -1017,8 +1024,10 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
|
|||
sdd->cntrlr_info = sci;
|
||||
sdd->pdev = pdev;
|
||||
sdd->sfr_start = mem_res->start;
|
||||
sdd->tx_dmach = dmatx_res->start;
|
||||
sdd->rx_dmach = dmarx_res->start;
|
||||
sdd->tx_dma.dmach = dmatx_res->start;
|
||||
sdd->tx_dma.direction = DMA_TO_DEVICE;
|
||||
sdd->rx_dma.dmach = dmarx_res->start;
|
||||
sdd->rx_dma.direction = DMA_FROM_DEVICE;
|
||||
|
||||
sdd->cur_bpw = 8;
|
||||
|
||||
|
@ -1106,7 +1115,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
|
|||
pdev->id, master->num_chipselect);
|
||||
dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
|
||||
mem_res->end, mem_res->start,
|
||||
sdd->rx_dmach, sdd->tx_dmach);
|
||||
sdd->rx_dma.dmach, sdd->tx_dma.dmach);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -19,12 +19,8 @@ struct dma_pl330_peri {
|
|||
* Peri_Req i/f of the DMAC that is
|
||||
* peripheral could be reached from.
|
||||
*/
|
||||
u8 peri_id; /* {0, 31} */
|
||||
u8 peri_id; /* specific dma id */
|
||||
enum pl330_reqtype rqtype;
|
||||
|
||||
/* For M->D and D->M Channels */
|
||||
int burst_sz; /* in power of 2 */
|
||||
dma_addr_t fifo_addr;
|
||||
};
|
||||
|
||||
struct dma_pl330_platdata {
|
||||
|
|
|
@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
|
|||
|
||||
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
|
||||
s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
|
||||
if (!dma_data->ops)
|
||||
dma_data->ops = samsung_dma_get_ops();
|
||||
|
||||
dma_data->ops->started(dma_data->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
|
|||
|
||||
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
|
||||
|
||||
s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
|
||||
if (!dma_data->ops)
|
||||
dma_data->ops = samsung_dma_get_ops();
|
||||
|
||||
dma_data->ops->started(dma_data->channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ struct runtime_data {
|
|||
spinlock_t lock;
|
||||
int state;
|
||||
unsigned int dma_loaded;
|
||||
unsigned int dma_limit;
|
||||
unsigned int dma_period;
|
||||
dma_addr_t dma_start;
|
||||
dma_addr_t dma_pos;
|
||||
|
@ -62,77 +61,79 @@ struct runtime_data {
|
|||
struct s3c_dma_params *params;
|
||||
};
|
||||
|
||||
static void audio_buffdone(void *data);
|
||||
|
||||
/* dma_enqueue
|
||||
*
|
||||
* place a dma buffer onto the queue for the dma system
|
||||
* to handle.
|
||||
*/
|
||||
*/
|
||||
static void dma_enqueue(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct runtime_data *prtd = substream->runtime->private_data;
|
||||
dma_addr_t pos = prtd->dma_pos;
|
||||
unsigned int limit;
|
||||
int ret;
|
||||
struct samsung_dma_prep_info dma_info;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
if (s3c_dma_has_circular())
|
||||
limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
|
||||
else
|
||||
limit = prtd->dma_limit;
|
||||
limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
|
||||
|
||||
pr_debug("%s: loaded %d, limit %d\n",
|
||||
__func__, prtd->dma_loaded, limit);
|
||||
|
||||
while (prtd->dma_loaded < limit) {
|
||||
unsigned long len = prtd->dma_period;
|
||||
dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
|
||||
dma_info.direction =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
|
||||
? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
dma_info.fp = audio_buffdone;
|
||||
dma_info.fp_param = substream;
|
||||
dma_info.period = prtd->dma_period;
|
||||
dma_info.len = prtd->dma_period*limit;
|
||||
|
||||
while (prtd->dma_loaded < limit) {
|
||||
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
|
||||
|
||||
if ((pos + len) > prtd->dma_end) {
|
||||
len = prtd->dma_end - pos;
|
||||
pr_debug("%s: corrected dma len %ld\n", __func__, len);
|
||||
if ((pos + dma_info.period) > prtd->dma_end) {
|
||||
dma_info.period = prtd->dma_end - pos;
|
||||
pr_debug("%s: corrected dma len %ld\n",
|
||||
__func__, dma_info.period);
|
||||
}
|
||||
|
||||
ret = s3c2410_dma_enqueue(prtd->params->channel,
|
||||
substream, pos, len);
|
||||
dma_info.buf = pos;
|
||||
prtd->params->ops->prepare(prtd->params->ch, &dma_info);
|
||||
|
||||
if (ret == 0) {
|
||||
prtd->dma_loaded++;
|
||||
pos += prtd->dma_period;
|
||||
if (pos >= prtd->dma_end)
|
||||
pos = prtd->dma_start;
|
||||
} else
|
||||
break;
|
||||
prtd->dma_loaded++;
|
||||
pos += prtd->dma_period;
|
||||
if (pos >= prtd->dma_end)
|
||||
pos = prtd->dma_start;
|
||||
}
|
||||
|
||||
prtd->dma_pos = pos;
|
||||
}
|
||||
|
||||
static void audio_buffdone(struct s3c2410_dma_chan *channel,
|
||||
void *dev_id, int size,
|
||||
enum s3c2410_dma_buffresult result)
|
||||
static void audio_buffdone(void *data)
|
||||
{
|
||||
struct snd_pcm_substream *substream = dev_id;
|
||||
struct runtime_data *prtd;
|
||||
struct snd_pcm_substream *substream = data;
|
||||
struct runtime_data *prtd = substream->runtime->private_data;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
|
||||
return;
|
||||
if (prtd->state & ST_RUNNING) {
|
||||
prtd->dma_pos += prtd->dma_period;
|
||||
if (prtd->dma_pos >= prtd->dma_end)
|
||||
prtd->dma_pos = prtd->dma_start;
|
||||
|
||||
prtd = substream->runtime->private_data;
|
||||
if (substream)
|
||||
snd_pcm_period_elapsed(substream);
|
||||
|
||||
if (substream)
|
||||
snd_pcm_period_elapsed(substream);
|
||||
|
||||
spin_lock(&prtd->lock);
|
||||
if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
|
||||
prtd->dma_loaded--;
|
||||
dma_enqueue(substream);
|
||||
spin_lock(&prtd->lock);
|
||||
if (!samsung_dma_has_circular()) {
|
||||
prtd->dma_loaded--;
|
||||
dma_enqueue(substream);
|
||||
}
|
||||
spin_unlock(&prtd->lock);
|
||||
}
|
||||
|
||||
spin_unlock(&prtd->lock);
|
||||
}
|
||||
|
||||
static int dma_hw_params(struct snd_pcm_substream *substream,
|
||||
|
@ -144,8 +145,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
|
|||
unsigned long totbytes = params_buffer_bytes(params);
|
||||
struct s3c_dma_params *dma =
|
||||
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
||||
int ret = 0;
|
||||
|
||||
struct samsung_dma_info dma_info;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
|
@ -163,30 +163,26 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
|
|||
pr_debug("params %p, client %p, channel %d\n", prtd->params,
|
||||
prtd->params->client, prtd->params->channel);
|
||||
|
||||
ret = s3c2410_dma_request(prtd->params->channel,
|
||||
prtd->params->client, NULL);
|
||||
prtd->params->ops = samsung_dma_get_ops();
|
||||
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "failed to get dma channel\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* use the circular buffering if we have it available. */
|
||||
if (s3c_dma_has_circular())
|
||||
s3c2410_dma_setflags(prtd->params->channel,
|
||||
S3C2410_DMAF_CIRCULAR);
|
||||
dma_info.cap = (samsung_dma_has_circular() ?
|
||||
DMA_CYCLIC : DMA_SLAVE);
|
||||
dma_info.client = prtd->params->client;
|
||||
dma_info.direction =
|
||||
(substream->stream == SNDRV_PCM_STREAM_PLAYBACK
|
||||
? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
dma_info.width = prtd->params->dma_size;
|
||||
dma_info.fifo = prtd->params->dma_addr;
|
||||
prtd->params->ch = prtd->params->ops->request(
|
||||
prtd->params->channel, &dma_info);
|
||||
}
|
||||
|
||||
s3c2410_dma_set_buffdone_fn(prtd->params->channel,
|
||||
audio_buffdone);
|
||||
|
||||
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
|
||||
|
||||
runtime->dma_bytes = totbytes;
|
||||
|
||||
spin_lock_irq(&prtd->lock);
|
||||
prtd->dma_loaded = 0;
|
||||
prtd->dma_limit = runtime->hw.periods_min;
|
||||
prtd->dma_period = params_period_bytes(params);
|
||||
prtd->dma_start = runtime->dma_addr;
|
||||
prtd->dma_pos = prtd->dma_start;
|
||||
|
@ -206,7 +202,8 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
|
|||
snd_pcm_set_runtime_buffer(substream, NULL);
|
||||
|
||||
if (prtd->params) {
|
||||
s3c2410_dma_free(prtd->params->channel, prtd->params->client);
|
||||
prtd->params->ops->release(prtd->params->ch,
|
||||
prtd->params->client);
|
||||
prtd->params = NULL;
|
||||
}
|
||||
|
||||
|
@ -225,23 +222,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
|
|||
if (!prtd->params)
|
||||
return 0;
|
||||
|
||||
/* channel needs configuring for mem=>device, increment memory addr,
|
||||
* sync to pclk, half-word transfers to the IIS-FIFO. */
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
s3c2410_dma_devconfig(prtd->params->channel,
|
||||
S3C2410_DMASRC_MEM,
|
||||
prtd->params->dma_addr);
|
||||
} else {
|
||||
s3c2410_dma_devconfig(prtd->params->channel,
|
||||
S3C2410_DMASRC_HW,
|
||||
prtd->params->dma_addr);
|
||||
}
|
||||
|
||||
s3c2410_dma_config(prtd->params->channel,
|
||||
prtd->params->dma_size);
|
||||
|
||||
/* flush the DMA channel */
|
||||
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
|
||||
prtd->params->ops->flush(prtd->params->ch);
|
||||
|
||||
prtd->dma_loaded = 0;
|
||||
prtd->dma_pos = prtd->dma_start;
|
||||
|
||||
|
@ -265,14 +248,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
|
|||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
prtd->state |= ST_RUNNING;
|
||||
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
|
||||
prtd->params->ops->trigger(prtd->params->ch);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
prtd->state &= ~ST_RUNNING;
|
||||
s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
|
||||
prtd->params->ops->stop(prtd->params->ch);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -291,21 +274,12 @@ dma_pointer(struct snd_pcm_substream *substream)
|
|||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct runtime_data *prtd = runtime->private_data;
|
||||
unsigned long res;
|
||||
dma_addr_t src, dst;
|
||||
|
||||
pr_debug("Entered %s\n", __func__);
|
||||
|
||||
spin_lock(&prtd->lock);
|
||||
s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
|
||||
res = prtd->dma_pos - prtd->dma_start;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
|
||||
res = dst - prtd->dma_start;
|
||||
else
|
||||
res = src - prtd->dma_start;
|
||||
|
||||
spin_unlock(&prtd->lock);
|
||||
|
||||
pr_debug("Pointer %x %x\n", src, dst);
|
||||
pr_debug("Pointer offset: %lu\n", res);
|
||||
|
||||
/* we seem to be getting the odd error from the pcm library due
|
||||
* to out-of-bounds pointers. this is maybe due to the dma engine
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* ALSA PCM interface for the Samsung S3C24xx CPU
|
||||
* ALSA PCM interface for the Samsung SoC
|
||||
*/
|
||||
|
||||
#ifndef _S3C_AUDIO_H
|
||||
|
@ -17,6 +17,8 @@ struct s3c_dma_params {
|
|||
int channel; /* Channel ID */
|
||||
dma_addr_t dma_addr;
|
||||
int dma_size; /* Size of the DMA transfer */
|
||||
unsigned ch;
|
||||
struct samsung_dma_ops *ops;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user