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

📄 omap-mcbsp.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	OMAP_MCBSP_WRITE(io_base, SRGR2,			 SRGR2_CLKSM | SRGR2_FSGM |			 SRGR2_FPER(bits_per_sample * 2 - 1));#else	OMAP_MCBSP_WRITE(io_base, SRGR1,			 SRGR1_FWID(bits_per_sample -				    1) | SRGR1_CLKGDV(clkgdv));	OMAP_MCBSP_WRITE(io_base, SRGR2,			 (SRGR2_GSYNC | SRGR2_CLKSP | SRGR2_FSGM |			  SRGR2_FPER(bits_per_sample * 2 - 1)));#endif				/* end of #ifdef MCBSP_MASTER */	return (0);}/***************** INTERRUPT MODE *************/#ifdef MCBSP_IRQ_MODE/* NOTE: Legacy Code being carried forward. These functions are purely non-operational currently */static irqreturn_tomap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs){	struct omap_mcbsp *mcbsp_tx = (struct omap_mcbsp *)(dev_id);	DBG("TX IRQ callback : 0x%x\n",	    OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));	complete(&mcbsp_tx->tx_irq_completion);	return IRQ_HANDLED;}static irqreturn_tomap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs){	struct omap_mcbsp *mcbsp_rx = (struct omap_mcbsp *)(dev_id);	DBG("RX IRQ callback : 0x%x\n",	    OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));	complete(&mcbsp_rx->rx_irq_completion);	return IRQ_HANDLED;}static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data){	struct omap_mcbsp *mcbsp_dma_tx = (struct omap_mcbsp *)(data);	DBG("TX DMA callback : 0x%x\n",	    OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));	/* We can free the channels */	omap_free_dma(mcbsp_dma_tx->dma_tx_lch);	mcbsp_dma_tx->dma_tx_lch = -1;	complete(&mcbsp_dma_tx->tx_dma_completion);}static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data){	struct omap_mcbsp *mcbsp_dma_rx = (struct omap_mcbsp *)(data);	DBG("RX DMA callback : 0x%x\n",	    OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));	/* We can free the channels */	omap_free_dma(mcbsp_dma_rx->dma_rx_lch);	mcbsp_dma_rx->dma_rx_lch = -1;	complete(&mcbsp_dma_rx->rx_dma_completion);}static int omap_mcbsp_check(unsigned int id){	if (cpu_is_omap730()) {		if (id > OMAP_MAX_MCBSP_COUNT - 1) {			printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",			       id + 1);			return -1;		}		return 0;	}	if (cpu_is_omap1510() || cpu_is_omap1610() || cpu_is_omap1710()) {		if (id > OMAP_MAX_MCBSP_COUNT) {			printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n",			       id + 1);			return -1;		}		return 0;	}	return -1;}int omap_mcbsp_request(unsigned int id){	int err;	if (omap_mcbsp_check(id) < 0)		return -EINVAL;	spin_lock(&mcbsp[id].lock);	if (!mcbsp[id].free) {		printk(KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n",		       id + 1);		spin_unlock(&mcbsp[id].lock);		return -1;	}	mcbsp[id].free = 0;	spin_unlock(&mcbsp[id].lock);	/* We need to get IRQs here */	err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,			  "McBSP", (void *)(&mcbsp[id]));	if (err != 0) {		printk(KERN_ERR		       "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",		       mcbsp[id].tx_irq, mcbsp[id].id);		return err;	}	init_completion(&(mcbsp[id].tx_irq_completion));	err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,			  "McBSP", (void *)(&mcbsp[id]));	if (err != 0) {		printk(KERN_ERR		       "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",		       mcbsp[id].rx_irq, mcbsp[id].id);		free_irq(mcbsp[id].tx_irq, (void *)(&mcbsp[id]));		return err;	}	init_completion(&(mcbsp[id].rx_irq_completion));	return 0;}void omap_mcbsp_free(unsigned int id){	if (omap_mcbsp_check(id) < 0)		return;	spin_lock(&mcbsp[id].lock);	if (mcbsp[id].free) {		printk(KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n",		       id + 1);		spin_unlock(&mcbsp[id].lock);		return;	}	mcbsp[id].free = 1;	spin_unlock(&mcbsp[id].lock);	/* Free IRQs */	free_irq(mcbsp[id].rx_irq, (void *)(&mcbsp[id]));	free_irq(mcbsp[id].tx_irq, (void *)(&mcbsp[id]));}/* * 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. */intomap_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);	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);	omap_set_dma_src_params(mcbsp[id].dma_tx_lch,				OMAP_DMA_PORT_EMIFF,				OMAP_DMA_AMODE_POST_INC, buffer);	omap_start_dma(mcbsp[id].dma_tx_lch);	wait_for_completion(&(mcbsp[id].tx_dma_completion));	return 0;}intomap_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);	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);	omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,				 OMAP_DMA_PORT_EMIFF,				 OMAP_DMA_AMODE_POST_INC, buffer);	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_begin(). */voidomap_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);}#endif				/* End of #ifdef MCBSP_IRQ_MODE */#ifdef MCBSP_DIRECT_RWint omap_mcbsp_write(unsigned int id, u16 buf){	u32 base = mcbsp[id].virt_base;	writew(buf, base + OMAP_MCBSP_REG_DXR1);	// if frame sync error - clear the error	if (readw(base + OMAP_MCBSP_REG_SPCR2) & SPCR2_XSYNCERR) {		// clear error		writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~SPCR2_XSYNCERR),		       base + OMAP_MCBSP_REG_SPCR2);		// resend		return -1;	} else {		// wait for transmit confirmation		int attemps = 0;		while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & SPCR2_XRDY)) {			if (attemps++ > 1000) {				writew(readw(base + OMAP_MCBSP_REG_SPCR2) &				       (~SPCR2_XRST),				       base + OMAP_MCBSP_REG_SPCR2);				udelay(10);				writew(readw(base + OMAP_MCBSP_REG_SPCR2) |				       (SPCR2_XRST),				       base + OMAP_MCBSP_REG_SPCR2);				udelay(10);				printk(KERN_ERR				       " Could not write to McBSP Register\n");				return -2;			}		}	}	return 0;}int omap_mcbsp_read(unsigned int id, u16 * buf){	u32 base = mcbsp[id].virt_base;	// if frame sync error - clear the error	if (readw(base + OMAP_MCBSP_REG_SPCR1) & SPCR1_RSYNCERR) {		// clear error		writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~SPCR1_RSYNCERR),		       base + OMAP_MCBSP_REG_SPCR1);		// resend		return -1;	} else {		// wait for transmit confirmation		int attemps = 0;		while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & SPCR1_RRDY)) {			if (attemps++ > 1000) {				writew(readw(base + OMAP_MCBSP_REG_SPCR1) &				       (~SPCR1_RRST),				       base + OMAP_MCBSP_REG_SPCR1);				udelay(10);				writew(readw(base + OMAP_MCBSP_REG_SPCR1) |				       (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;}#endif				/* End of #ifdef MCBSP_DIRECT_RW *//***************** Module init */static int __init omap_mcbsp_init(void){	u8 count = 0;	printk("Initializing OMAP McBSP system for ");#ifdef CONFIG_ARCH_OMAP16XX	if (cpu_is_omap1610()) {		mcbsp = mcbsp_1610;		printk("OMAP 1610\n");	}	if (cpu_is_omap1710()) {		mcbsp = mcbsp_1710;		printk("OMAP 1710\n");	}#endif#ifdef CONFIG_ARCH_OMAP24XX	if (cpu_is_omap2420()) {		mcbsp = mcbsp_2420;		printk("OMAP 2420\n");	}#endif	if (NULL == mcbsp) {		printk(KERN_ERR "Unsupported processor- Cannot Initialize\n");		return -EPERM;	}	/* Initialize all other params of the structure */	for (; count < OMAP_MAX_MCBSP_COUNT; count++) {		mcbsp[count].free = 1;#ifdef MCBSP_IRQ_MODE		mcbsp[count].rx_word_length = 0;		mcbsp[count].tx_word_length = 0;		mcbsp[count].id = count + 1;		spin_lock_init(&mcbsp[count].lock);#endif	}			/* End of for() */	return (0);}				/* End of omap_mcbsp_init */arch_initcall(omap_mcbsp_init);EXPORT_SYMBOL(omap_mcbsp_begin);EXPORT_SYMBOL(omap_mcbsp_end);EXPORT_SYMBOL(omap_mcbsp_set_rate);#ifdef MCBSP_DIRECT_RWEXPORT_SYMBOL(omap_mcbsp_read);EXPORT_SYMBOL(omap_mcbsp_write);#endif#ifdef MCBSP_IRQ_MODEEXPORT_SYMBOL(omap_mcbsp_request);EXPORT_SYMBOL(omap_mcbsp_free);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);#endif				/* End of #ifdef MCBSP_IRQ_MODE */MODULE_AUTHOR("MontaVista");MODULE_DESCRIPTION("McBsp Driver for OMAP 1610/1710/2420.");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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