Loading arch/arm/plat-omap/include/plat/mcbsp.h +0 −25 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ #ifndef __ASM_ARCH_OMAP_MCBSP_H #define __ASM_ARCH_OMAP_MCBSP_H #include <linux/completion.h> #include <linux/spinlock.h> #include <mach/hardware.h> Loading Loading @@ -340,10 +339,6 @@ typedef enum { OMAP_MCBSP5 } omap_mcbsp_id; typedef int __bitwise omap_mcbsp_io_type_t; #define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1) #define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2) typedef enum { OMAP_MCBSP_WORD_8 = 0, OMAP_MCBSP_WORD_12, Loading Loading @@ -393,22 +388,12 @@ struct omap_mcbsp { omap_mcbsp_word_length rx_word_length; omap_mcbsp_word_length tx_word_length; omap_mcbsp_io_type_t io_type; /* IRQ or poll */ /* IRQ based TX/RX */ int rx_irq; int tx_irq; /* DMA stuff */ u8 dma_rx_sync; short dma_rx_lch; u8 dma_tx_sync; short dma_tx_lch; /* Completion queues */ struct completion tx_irq_completion; struct completion rx_irq_completion; struct completion tx_dma_completion; struct completion rx_dma_completion; /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; Loading Loading @@ -467,20 +452,10 @@ int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); void omap_mcbsp_start(unsigned int id, int tx, int rx); void omap_mcbsp_stop(unsigned int id, int tx, int rx); void omap_mcbsp_xmit_word(unsigned int id, u32 word); u32 omap_mcbsp_recv_word(unsigned int id); int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); /* McBSP functional clock source changing function */ extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id); /* Polled read/write functions */ int omap_mcbsp_pollread(unsigned int id, u16 * buf); int omap_mcbsp_pollwrite(unsigned int id, u16 buf); int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type); /* McBSP signal muxing API */ void omap2_mcbsp1_mux_clkr_src(u8 mux); void omap2_mcbsp1_mux_fsr_src(u8 mux); Loading arch/arm/plat-omap/mcbsp.c +19 −363 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/wait.h> #include <linux/completion.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/clk.h> Loading @@ -25,7 +23,6 @@ #include <linux/io.h> #include <linux/slab.h> #include <plat/dma.h> #include <plat/mcbsp.h> #include <plat/omap_device.h> #include <linux/pm_runtime.h> Loading Loading @@ -136,8 +133,6 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) irqst_spcr2); /* Writing zero to XSYNC_ERR clears the IRQ */ MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); } else { complete(&mcbsp_tx->tx_irq_completion); } return IRQ_HANDLED; Loading @@ -156,41 +151,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) irqst_spcr1); /* Writing zero to RSYNC_ERR clears the IRQ */ MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); } else { 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 = data; dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", MCBSP_READ(mcbsp_dma_tx, 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 = data; dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", MCBSP_READ(mcbsp_dma_rx, 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); } /* * omap_mcbsp_config simply write a config to the * appropriate McBSP. Loading Loading @@ -758,37 +723,6 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} #endif /* * We can choose between IRQ based or polled IO. * This needs to be called before omap_mcbsp_request(). */ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); spin_lock(&mcbsp->lock); if (!mcbsp->free) { dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id); spin_unlock(&mcbsp->lock); return -EINVAL; } mcbsp->io_type = io_type; spin_unlock(&mcbsp->lock); return 0; } EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; Loading Loading @@ -833,9 +767,6 @@ int omap_mcbsp_request(unsigned int id) MCBSP_WRITE(mcbsp, SPCR1, 0); MCBSP_WRITE(mcbsp, SPCR2, 0); if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* We need to get IRQs here */ init_completion(&mcbsp->tx_irq_completion); err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0, "McBSP", (void *)mcbsp); if (err != 0) { Loading @@ -846,7 +777,6 @@ int omap_mcbsp_request(unsigned int id) } if (mcbsp->rx_irq) { init_completion(&mcbsp->rx_irq_completion); err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0, "McBSP", (void *)mcbsp); Loading @@ -857,7 +787,6 @@ int omap_mcbsp_request(unsigned int id) goto err_free_irq; } } } return 0; err_free_irq: Loading Loading @@ -901,12 +830,9 @@ void omap_mcbsp_free(unsigned int id) pm_runtime_put_sync(mcbsp->dev); if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* Free IRQs */ if (mcbsp->rx_irq) free_irq(mcbsp->rx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp); } reg_cache = mcbsp->reg_cache; Loading Loading @@ -1043,271 +969,6 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) } EXPORT_SYMBOL(omap_mcbsp_stop); /* polled mcbsp i/o operations */ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); MCBSP_WRITE(mcbsp, DXR1, buf); /* if frame sync error - clear the error */ if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) { /* clear error */ MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2)); /* resend */ return -1; } else { /* wait for transmit confirmation */ int attemps = 0; while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) { if (attemps++ > 1000) { MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); udelay(10); MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2) | (XRST)); udelay(10); dev_err(mcbsp->dev, "Could not write to" " McBSP%d Register\n", mcbsp->id); return -2; } } } return 0; } EXPORT_SYMBOL(omap_mcbsp_pollwrite); int omap_mcbsp_pollread(unsigned int id, u16 *buf) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); /* if frame sync error - clear the error */ if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) { /* clear error */ MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1)); /* resend */ return -1; } else { /* wait for receive confirmation */ int attemps = 0; while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { if (attemps++ > 1000) { MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); udelay(10); MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1) | (RRST)); udelay(10); dev_err(mcbsp->dev, "Could not read from" " McBSP%d Register\n", mcbsp->id); return -2; } } } *buf = MCBSP_READ(mcbsp, DRR1); return 0; } EXPORT_SYMBOL(omap_mcbsp_pollread); /* * IRQ based word transmission. */ void omap_mcbsp_xmit_word(unsigned int id, u32 word) { struct omap_mcbsp *mcbsp; omap_mcbsp_word_length word_length; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; } mcbsp = id_to_mcbsp_ptr(id); word_length = mcbsp->tx_word_length; wait_for_completion(&mcbsp->tx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) MCBSP_WRITE(mcbsp, DXR2, word >> 16); MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); } EXPORT_SYMBOL(omap_mcbsp_xmit_word); u32 omap_mcbsp_recv_word(unsigned int id) { struct omap_mcbsp *mcbsp; u16 word_lsb, word_msb = 0; omap_mcbsp_word_length word_length; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); word_length = mcbsp->rx_word_length; wait_for_completion(&mcbsp->rx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) word_msb = MCBSP_READ(mcbsp, DRR2); word_lsb = MCBSP_READ(mcbsp, DRR1); return (word_lsb | (word_msb << 16)); } EXPORT_SYMBOL(omap_mcbsp_recv_word); /* * 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) { struct omap_mcbsp *mcbsp; int dma_tx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, mcbsp, &dma_tx_ch)) { dev_err(mcbsp->dev, " Unable to request DMA channel for " "McBSP%d TX. Trying IRQ based TX\n", mcbsp->id); return -EAGAIN; } mcbsp->dma_tx_lch = dma_tx_ch; dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id, dma_tx_ch); init_completion(&mcbsp->tx_dma_completion); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } if (cpu_class_is_omap2()) sync_dev = mcbsp->dma_tx_sync; omap_set_dma_transfer_params(mcbsp->dma_tx_lch, OMAP_DMA_DATA_TYPE_S16, length >> 1, 1, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0); omap_set_dma_dest_params(mcbsp->dma_tx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, mcbsp->phys_base + OMAP_MCBSP_REG_DXR1, 0, 0); omap_set_dma_src_params(mcbsp->dma_tx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); omap_start_dma(mcbsp->dma_tx_lch); wait_for_completion(&mcbsp->tx_dma_completion); return 0; } EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) { struct omap_mcbsp *mcbsp; int dma_rx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, mcbsp, &dma_rx_ch)) { dev_err(mcbsp->dev, "Unable to request DMA channel for " "McBSP%d RX. Trying IRQ based RX\n", mcbsp->id); return -EAGAIN; } mcbsp->dma_rx_lch = dma_rx_ch; dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id, dma_rx_ch); init_completion(&mcbsp->rx_dma_completion); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } if (cpu_class_is_omap2()) sync_dev = mcbsp->dma_rx_sync; omap_set_dma_transfer_params(mcbsp->dma_rx_lch, OMAP_DMA_DATA_TYPE_S16, length >> 1, 1, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0); omap_set_dma_src_params(mcbsp->dma_rx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, mcbsp->phys_base + OMAP_MCBSP_REG_DRR1, 0, 0); omap_set_dma_dest_params(mcbsp->dma_rx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); omap_start_dma(mcbsp->dma_rx_lch); wait_for_completion(&mcbsp->rx_dma_completion); return 0; } EXPORT_SYMBOL(omap_mcbsp_recv_buffer); #ifdef CONFIG_ARCH_OMAP3 #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) Loading Loading @@ -1619,8 +1280,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) spin_lock_init(&mcbsp->lock); mcbsp->id = id + 1; mcbsp->free = true; mcbsp->dma_tx_lch = -1; mcbsp->dma_rx_lch = -1; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (!res) { Loading @@ -1646,9 +1305,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) else mcbsp->phys_dma_base = res->start; /* Default I/O is IRQ based */ mcbsp->io_type = OMAP_MCBSP_IRQ_IO; mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); Loading Loading
arch/arm/plat-omap/include/plat/mcbsp.h +0 −25 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ #ifndef __ASM_ARCH_OMAP_MCBSP_H #define __ASM_ARCH_OMAP_MCBSP_H #include <linux/completion.h> #include <linux/spinlock.h> #include <mach/hardware.h> Loading Loading @@ -340,10 +339,6 @@ typedef enum { OMAP_MCBSP5 } omap_mcbsp_id; typedef int __bitwise omap_mcbsp_io_type_t; #define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1) #define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2) typedef enum { OMAP_MCBSP_WORD_8 = 0, OMAP_MCBSP_WORD_12, Loading Loading @@ -393,22 +388,12 @@ struct omap_mcbsp { omap_mcbsp_word_length rx_word_length; omap_mcbsp_word_length tx_word_length; omap_mcbsp_io_type_t io_type; /* IRQ or poll */ /* IRQ based TX/RX */ int rx_irq; int tx_irq; /* DMA stuff */ u8 dma_rx_sync; short dma_rx_lch; u8 dma_tx_sync; short dma_tx_lch; /* Completion queues */ struct completion tx_irq_completion; struct completion rx_irq_completion; struct completion tx_dma_completion; struct completion rx_dma_completion; /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; Loading Loading @@ -467,20 +452,10 @@ int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); void omap_mcbsp_start(unsigned int id, int tx, int rx); void omap_mcbsp_stop(unsigned int id, int tx, int rx); void omap_mcbsp_xmit_word(unsigned int id, u32 word); u32 omap_mcbsp_recv_word(unsigned int id); int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length); /* McBSP functional clock source changing function */ extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id); /* Polled read/write functions */ int omap_mcbsp_pollread(unsigned int id, u16 * buf); int omap_mcbsp_pollwrite(unsigned int id, u16 buf); int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type); /* McBSP signal muxing API */ void omap2_mcbsp1_mux_clkr_src(u8 mux); void omap2_mcbsp1_mux_fsr_src(u8 mux); Loading
arch/arm/plat-omap/mcbsp.c +19 −363 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/wait.h> #include <linux/completion.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/clk.h> Loading @@ -25,7 +23,6 @@ #include <linux/io.h> #include <linux/slab.h> #include <plat/dma.h> #include <plat/mcbsp.h> #include <plat/omap_device.h> #include <linux/pm_runtime.h> Loading Loading @@ -136,8 +133,6 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) irqst_spcr2); /* Writing zero to XSYNC_ERR clears the IRQ */ MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); } else { complete(&mcbsp_tx->tx_irq_completion); } return IRQ_HANDLED; Loading @@ -156,41 +151,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) irqst_spcr1); /* Writing zero to RSYNC_ERR clears the IRQ */ MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); } else { 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 = data; dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", MCBSP_READ(mcbsp_dma_tx, 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 = data; dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", MCBSP_READ(mcbsp_dma_rx, 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); } /* * omap_mcbsp_config simply write a config to the * appropriate McBSP. Loading Loading @@ -758,37 +723,6 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} #endif /* * We can choose between IRQ based or polled IO. * This needs to be called before omap_mcbsp_request(). */ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); spin_lock(&mcbsp->lock); if (!mcbsp->free) { dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id); spin_unlock(&mcbsp->lock); return -EINVAL; } mcbsp->io_type = io_type; spin_unlock(&mcbsp->lock); return 0; } EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; Loading Loading @@ -833,9 +767,6 @@ int omap_mcbsp_request(unsigned int id) MCBSP_WRITE(mcbsp, SPCR1, 0); MCBSP_WRITE(mcbsp, SPCR2, 0); if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* We need to get IRQs here */ init_completion(&mcbsp->tx_irq_completion); err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0, "McBSP", (void *)mcbsp); if (err != 0) { Loading @@ -846,7 +777,6 @@ int omap_mcbsp_request(unsigned int id) } if (mcbsp->rx_irq) { init_completion(&mcbsp->rx_irq_completion); err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0, "McBSP", (void *)mcbsp); Loading @@ -857,7 +787,6 @@ int omap_mcbsp_request(unsigned int id) goto err_free_irq; } } } return 0; err_free_irq: Loading Loading @@ -901,12 +830,9 @@ void omap_mcbsp_free(unsigned int id) pm_runtime_put_sync(mcbsp->dev); if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* Free IRQs */ if (mcbsp->rx_irq) free_irq(mcbsp->rx_irq, (void *)mcbsp); free_irq(mcbsp->tx_irq, (void *)mcbsp); } reg_cache = mcbsp->reg_cache; Loading Loading @@ -1043,271 +969,6 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) } EXPORT_SYMBOL(omap_mcbsp_stop); /* polled mcbsp i/o operations */ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); MCBSP_WRITE(mcbsp, DXR1, buf); /* if frame sync error - clear the error */ if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) { /* clear error */ MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2)); /* resend */ return -1; } else { /* wait for transmit confirmation */ int attemps = 0; while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) { if (attemps++ > 1000) { MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); udelay(10); MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2) | (XRST)); udelay(10); dev_err(mcbsp->dev, "Could not write to" " McBSP%d Register\n", mcbsp->id); return -2; } } } return 0; } EXPORT_SYMBOL(omap_mcbsp_pollwrite); int omap_mcbsp_pollread(unsigned int id, u16 *buf) { struct omap_mcbsp *mcbsp; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); /* if frame sync error - clear the error */ if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) { /* clear error */ MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1)); /* resend */ return -1; } else { /* wait for receive confirmation */ int attemps = 0; while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { if (attemps++ > 1000) { MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); udelay(10); MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1) | (RRST)); udelay(10); dev_err(mcbsp->dev, "Could not read from" " McBSP%d Register\n", mcbsp->id); return -2; } } } *buf = MCBSP_READ(mcbsp, DRR1); return 0; } EXPORT_SYMBOL(omap_mcbsp_pollread); /* * IRQ based word transmission. */ void omap_mcbsp_xmit_word(unsigned int id, u32 word) { struct omap_mcbsp *mcbsp; omap_mcbsp_word_length word_length; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return; } mcbsp = id_to_mcbsp_ptr(id); word_length = mcbsp->tx_word_length; wait_for_completion(&mcbsp->tx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) MCBSP_WRITE(mcbsp, DXR2, word >> 16); MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); } EXPORT_SYMBOL(omap_mcbsp_xmit_word); u32 omap_mcbsp_recv_word(unsigned int id) { struct omap_mcbsp *mcbsp; u16 word_lsb, word_msb = 0; omap_mcbsp_word_length word_length; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); word_length = mcbsp->rx_word_length; wait_for_completion(&mcbsp->rx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) word_msb = MCBSP_READ(mcbsp, DRR2); word_lsb = MCBSP_READ(mcbsp, DRR1); return (word_lsb | (word_msb << 16)); } EXPORT_SYMBOL(omap_mcbsp_recv_word); /* * 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) { struct omap_mcbsp *mcbsp; int dma_tx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, mcbsp, &dma_tx_ch)) { dev_err(mcbsp->dev, " Unable to request DMA channel for " "McBSP%d TX. Trying IRQ based TX\n", mcbsp->id); return -EAGAIN; } mcbsp->dma_tx_lch = dma_tx_ch; dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id, dma_tx_ch); init_completion(&mcbsp->tx_dma_completion); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } if (cpu_class_is_omap2()) sync_dev = mcbsp->dma_tx_sync; omap_set_dma_transfer_params(mcbsp->dma_tx_lch, OMAP_DMA_DATA_TYPE_S16, length >> 1, 1, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0); omap_set_dma_dest_params(mcbsp->dma_tx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, mcbsp->phys_base + OMAP_MCBSP_REG_DXR1, 0, 0); omap_set_dma_src_params(mcbsp->dma_tx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); omap_start_dma(mcbsp->dma_tx_lch); wait_for_completion(&mcbsp->tx_dma_completion); return 0; } EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length) { struct omap_mcbsp *mcbsp; int dma_rx_ch; int src_port = 0; int dest_port = 0; int sync_dev = 0; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } mcbsp = id_to_mcbsp_ptr(id); if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, mcbsp, &dma_rx_ch)) { dev_err(mcbsp->dev, "Unable to request DMA channel for " "McBSP%d RX. Trying IRQ based RX\n", mcbsp->id); return -EAGAIN; } mcbsp->dma_rx_lch = dma_rx_ch; dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id, dma_rx_ch); init_completion(&mcbsp->rx_dma_completion); if (cpu_class_is_omap1()) { src_port = OMAP_DMA_PORT_TIPB; dest_port = OMAP_DMA_PORT_EMIFF; } if (cpu_class_is_omap2()) sync_dev = mcbsp->dma_rx_sync; omap_set_dma_transfer_params(mcbsp->dma_rx_lch, OMAP_DMA_DATA_TYPE_S16, length >> 1, 1, OMAP_DMA_SYNC_ELEMENT, sync_dev, 0); omap_set_dma_src_params(mcbsp->dma_rx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, mcbsp->phys_base + OMAP_MCBSP_REG_DRR1, 0, 0); omap_set_dma_dest_params(mcbsp->dma_rx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); omap_start_dma(mcbsp->dma_rx_lch); wait_for_completion(&mcbsp->rx_dma_completion); return 0; } EXPORT_SYMBOL(omap_mcbsp_recv_buffer); #ifdef CONFIG_ARCH_OMAP3 #define max_thres(m) (mcbsp->pdata->buffer_size) #define valid_threshold(m, val) ((val) <= max_thres(m)) Loading Loading @@ -1619,8 +1280,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) spin_lock_init(&mcbsp->lock); mcbsp->id = id + 1; mcbsp->free = true; mcbsp->dma_tx_lch = -1; mcbsp->dma_rx_lch = -1; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); if (!res) { Loading @@ -1646,9 +1305,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) else mcbsp->phys_dma_base = res->start; /* Default I/O is IRQ based */ mcbsp->io_type = OMAP_MCBSP_IRQ_IO; mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); Loading