⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcbsp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
			}		}	}	return 0;}int omap_mcbsp_pollread(unsigned int id, u16 * buf){	u32 base = mcbsp[id].io_base;	/* if frame sync error - clear the error */	if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {		/* clear error */		writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR),		       base + OMAP_MCBSP_REG_SPCR1);		/* resend */		return -1;	} else {		/* wait for recieve confirmation */		int attemps = 0;		while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) {			if (attemps++ > 1000) {				writew(readw(base + OMAP_MCBSP_REG_SPCR1) &				       (~RRST),				       base + OMAP_MCBSP_REG_SPCR1);				udelay(10);				writew(readw(base + OMAP_MCBSP_REG_SPCR1) |				       (RRST),				       base + OMAP_MCBSP_REG_SPCR1);				udelay(10);				printk(KERN_ERR				       " Could not read from McBSP Register\n");				return -2;			}		}	}	*buf = readw(base + OMAP_MCBSP_REG_DRR1);	return 0;}/* * IRQ based word transmission. */void omap_mcbsp_xmit_word(unsigned int id, u32 word){	u32 io_base;	omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;	if (omap_mcbsp_check(id) < 0)		return;	io_base = mcbsp[id].io_base;	wait_for_completion(&(mcbsp[id].tx_irq_completion));	if (word_length > OMAP_MCBSP_WORD_16)		OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);	OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);}u32 omap_mcbsp_recv_word(unsigned int id){	u32 io_base;	u16 word_lsb, word_msb = 0;	omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;	if (omap_mcbsp_check(id) < 0)		return -EINVAL;	io_base = mcbsp[id].io_base;	wait_for_completion(&(mcbsp[id].rx_irq_completion));	if (word_length > OMAP_MCBSP_WORD_16)		word_msb = OMAP_MCBSP_READ(io_base, DRR2);	word_lsb = OMAP_MCBSP_READ(io_base, DRR1);	return (word_lsb | (word_msb << 16));}/* * Simple DMA based buffer rx/tx routines. * Nothing fancy, just a single buffer tx/rx through DMA. * The DMA resources are released once the transfer is done. * For anything fancier, you should use your own customized DMA * routines and callbacks. */int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length){	int dma_tx_ch;	if (omap_mcbsp_check(id) < 0)		return -EINVAL;	if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,			     &mcbsp[id],			     &dma_tx_ch)) {		printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);		return -EAGAIN;	}	mcbsp[id].dma_tx_lch = dma_tx_ch;	DBG("TX DMA on channel %d\n", dma_tx_ch);	init_completion(&(mcbsp[id].tx_dma_completion));	omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,				     OMAP_DMA_DATA_TYPE_S16,				     length >> 1, 1,				     OMAP_DMA_SYNC_ELEMENT,				     0, 0);	omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,				 OMAP_DMA_PORT_TIPB,				 OMAP_DMA_AMODE_CONSTANT,				 mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,				 0, 0);	omap_set_dma_src_params(mcbsp[id].dma_tx_lch,				OMAP_DMA_PORT_EMIFF,				OMAP_DMA_AMODE_POST_INC,				buffer,				0, 0);	omap_start_dma(mcbsp[id].dma_tx_lch);	wait_for_completion(&(mcbsp[id].tx_dma_completion));	return 0;}int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length){	int dma_rx_ch;	if (omap_mcbsp_check(id) < 0)		return -EINVAL;	if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,			     &mcbsp[id],			     &dma_rx_ch)) {		printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);		return -EAGAIN;	}	mcbsp[id].dma_rx_lch = dma_rx_ch;	DBG("RX DMA on channel %d\n", dma_rx_ch);	init_completion(&(mcbsp[id].rx_dma_completion));	omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,				     OMAP_DMA_DATA_TYPE_S16,				     length >> 1, 1,				     OMAP_DMA_SYNC_ELEMENT,				     0, 0);	omap_set_dma_src_params(mcbsp[id].dma_rx_lch,				OMAP_DMA_PORT_TIPB,				OMAP_DMA_AMODE_CONSTANT,				mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,				0, 0);	omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,				 OMAP_DMA_PORT_EMIFF,				 OMAP_DMA_AMODE_POST_INC,				 buffer,				 0, 0);	omap_start_dma(mcbsp[id].dma_rx_lch);	wait_for_completion(&(mcbsp[id].rx_dma_completion));	return 0;}/* * SPI wrapper. * Since SPI setup is much simpler than the generic McBSP one, * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. * Once this is done, you can call omap_mcbsp_start(). */void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg){	struct omap_mcbsp_reg_cfg mcbsp_cfg;	if (omap_mcbsp_check(id) < 0)		return;	memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));	/* SPI has only one frame */	mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));	mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));        /* Clock stop mode */	if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)		mcbsp_cfg.spcr1 |= (1 << 12);	else		mcbsp_cfg.spcr1 |= (3 << 11);	/* Set clock parities */	if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)		mcbsp_cfg.pcr0 |= CLKRP;	else		mcbsp_cfg.pcr0 &= ~CLKRP;	if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)		mcbsp_cfg.pcr0 &= ~CLKXP;	else		mcbsp_cfg.pcr0 |= CLKXP;	/* Set SCLKME to 0 and CLKSM to 1 */	mcbsp_cfg.pcr0 &= ~SCLKME;	mcbsp_cfg.srgr2 |= CLKSM;	/* Set FSXP */	if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)		mcbsp_cfg.pcr0 &= ~FSXP;	else		mcbsp_cfg.pcr0 |= FSXP;	if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {		mcbsp_cfg.pcr0 |= CLKXM;		mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);		mcbsp_cfg.pcr0 |= FSXM;		mcbsp_cfg.srgr2 &= ~FSGM;		mcbsp_cfg.xcr2 |= XDATDLY(1);		mcbsp_cfg.rcr2 |= RDATDLY(1);	}	else {		mcbsp_cfg.pcr0 &= ~CLKXM;		mcbsp_cfg.srgr1 |= CLKGDV(1);		mcbsp_cfg.pcr0 &= ~FSXM;		mcbsp_cfg.xcr2 &= ~XDATDLY(3);		mcbsp_cfg.rcr2 &= ~RDATDLY(3);	}	mcbsp_cfg.xcr2 &= ~XPHASE;	mcbsp_cfg.rcr2 &= ~RPHASE;	omap_mcbsp_config(id, &mcbsp_cfg);}/* * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. */struct omap_mcbsp_info {	u32 virt_base;	u8 dma_rx_sync, dma_tx_sync;	u16 rx_irq, tx_irq;};#ifdef CONFIG_ARCH_OMAP730static const struct omap_mcbsp_info mcbsp_730[] = {	[0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,		.rx_irq = INT_730_McBSP1RX,		.tx_irq = INT_730_McBSP1TX },	[1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,		.rx_irq = INT_730_McBSP2RX,		.tx_irq = INT_730_McBSP2TX },};#endif#ifdef CONFIG_ARCH_OMAP15XXstatic const struct omap_mcbsp_info mcbsp_1510[] = {	[0] = { .virt_base = OMAP1510_MCBSP1_BASE,		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,		.rx_irq = INT_McBSP1RX,		.tx_irq = INT_McBSP1TX },	[1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),		.dma_rx_sync = OMAP_DMA_MCBSP2_RX,		.dma_tx_sync = OMAP_DMA_MCBSP2_TX,		.rx_irq = INT_1510_SPI_RX,		.tx_irq = INT_1510_SPI_TX },	[2] = { .virt_base = OMAP1510_MCBSP3_BASE,		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,		.rx_irq = INT_McBSP3RX,		.tx_irq = INT_McBSP3TX },};#endif#if defined(CONFIG_ARCH_OMAP16XX)static const struct omap_mcbsp_info mcbsp_1610[] = {	[0] = { .virt_base = OMAP1610_MCBSP1_BASE,		.dma_rx_sync = OMAP_DMA_MCBSP1_RX,		.dma_tx_sync = OMAP_DMA_MCBSP1_TX,		.rx_irq = INT_McBSP1RX,		.tx_irq = INT_McBSP1TX },	[1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),		.dma_rx_sync = OMAP_DMA_MCBSP2_RX,		.dma_tx_sync = OMAP_DMA_MCBSP2_TX,		.rx_irq = INT_1610_McBSP2_RX,		.tx_irq = INT_1610_McBSP2_TX },	[2] = { .virt_base = OMAP1610_MCBSP3_BASE,		.dma_rx_sync = OMAP_DMA_MCBSP3_RX,		.dma_tx_sync = OMAP_DMA_MCBSP3_TX,		.rx_irq = INT_McBSP3RX,		.tx_irq = INT_McBSP3TX },};#endifstatic int __init omap_mcbsp_init(void){	int mcbsp_count = 0, i;	static const struct omap_mcbsp_info *mcbsp_info;	printk("Initializing OMAP McBSP system\n");	mcbsp_dsp_ck = clk_get(0, "dsp_ck");	if (IS_ERR(mcbsp_dsp_ck)) {		printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");		return PTR_ERR(mcbsp_dsp_ck);	}	mcbsp_api_ck = clk_get(0, "api_ck");	if (IS_ERR(mcbsp_api_ck)) {		printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");		return PTR_ERR(mcbsp_api_ck);	}	mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");	if (IS_ERR(mcbsp_dspxor_ck)) {		printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");		return PTR_ERR(mcbsp_dspxor_ck);	}#ifdef CONFIG_ARCH_OMAP730	if (cpu_is_omap730()) {		mcbsp_info = mcbsp_730;		mcbsp_count = ARRAY_SIZE(mcbsp_730);	}#endif#ifdef CONFIG_ARCH_OMAP15XX	if (cpu_is_omap1510()) {		mcbsp_info = mcbsp_1510;		mcbsp_count = ARRAY_SIZE(mcbsp_1510);	}#endif#if defined(CONFIG_ARCH_OMAP16XX)	if (cpu_is_omap16xx()) {		mcbsp_info = mcbsp_1610;		mcbsp_count = ARRAY_SIZE(mcbsp_1610);	}#endif	for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {		if (i >= mcbsp_count) {			mcbsp[i].io_base = 0;			mcbsp[i].free = 0;                        continue;		}		mcbsp[i].id = i + 1;		mcbsp[i].free = 1;		mcbsp[i].dma_tx_lch = -1;		mcbsp[i].dma_rx_lch = -1;		mcbsp[i].io_base = mcbsp_info[i].virt_base;		mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;		mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;		mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;		mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;		spin_lock_init(&mcbsp[i].lock);	}	return 0;}arch_initcall(omap_mcbsp_init);EXPORT_SYMBOL(omap_mcbsp_config);EXPORT_SYMBOL(omap_mcbsp_request);EXPORT_SYMBOL(omap_mcbsp_free);EXPORT_SYMBOL(omap_mcbsp_start);EXPORT_SYMBOL(omap_mcbsp_stop);EXPORT_SYMBOL(omap_mcbsp_xmit_word);EXPORT_SYMBOL(omap_mcbsp_recv_word);EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);EXPORT_SYMBOL(omap_mcbsp_recv_buffer);EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -