diff options
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 431 |
1 files changed, 255 insertions, 176 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 014d26574bb6..af33fc713e1a 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -27,43 +27,65 @@ #include <mach/dma.h> #include <mach/mcbsp.h> -static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; +struct omap_mcbsp **mcbsp_ptr; +int omap_mcbsp_count; -#define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \ - mcbsp[id].pdata->ops && \ - mcbsp[id].pdata->ops->check && \ - (mcbsp[id].pdata->ops->check(id) == 0)) +void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val) +{ + if (cpu_class_is_omap1() || cpu_is_omap2420()) + __raw_writew((u16)val, io_base + reg); + else + __raw_writel(val, io_base + reg); +} + +int omap_mcbsp_read(void __iomem *io_base, u16 reg) +{ + if (cpu_class_is_omap1() || cpu_is_omap2420()) + return __raw_readw(io_base + reg); + else + return __raw_readl(io_base + reg); +} + +#define OMAP_MCBSP_READ(base, reg) \ + omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg) +#define OMAP_MCBSP_WRITE(base, reg, val) \ + omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val) + +#define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) +#define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; static void omap_mcbsp_dump_reg(u8 id) { - dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id); - dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); - dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); - dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); - dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); - dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); - dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); - dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); - dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); - dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); - dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); - dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); - dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); - dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n", - OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); - dev_dbg(mcbsp[id].dev, "***********************\n"); + struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); + + dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); + dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, DRR2)); + dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, DRR1)); + dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, DXR2)); + dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, DXR1)); + dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, SPCR2)); + dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, SPCR1)); + dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, RCR2)); + dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, RCR1)); + dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, XCR2)); + dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, XCR1)); + dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, SRGR2)); + dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, SRGR1)); + dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", + OMAP_MCBSP_READ(mcbsp->io_base, PCR0)); + dev_dbg(mcbsp->dev, "***********************\n"); } static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) @@ -126,16 +148,18 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) */ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; 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); - io_base = mcbsp[id].io_base; - dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n", - mcbsp[id].id, io_base); + io_base = mcbsp->io_base; + dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", + mcbsp->id, mcbsp->phys_base); /* We write the given config */ OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); @@ -158,23 +182,26 @@ EXPORT_SYMBOL(omap_mcbsp_config); */ 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[id].lock); + spin_lock(&mcbsp->lock); - if (!mcbsp[id].free) { - dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", - mcbsp[id].id); - spin_unlock(&mcbsp[id].lock); + if (!mcbsp->free) { + dev_err(mcbsp->dev, "McBSP%d is currently in use\n", + mcbsp->id); + spin_unlock(&mcbsp->lock); return -EINVAL; } - mcbsp[id].io_type = io_type; + mcbsp->io_type = io_type; - spin_unlock(&mcbsp[id].lock); + spin_unlock(&mcbsp->lock); return 0; } @@ -182,53 +209,60 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { + struct omap_mcbsp *mcbsp; int err; 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 (mcbsp[id].pdata->ops->request) - mcbsp[id].pdata->ops->request(id); + if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) + mcbsp->pdata->ops->request(id); - clk_enable(mcbsp[id].clk); + clk_enable(mcbsp->clk); - spin_lock(&mcbsp[id].lock); - if (!mcbsp[id].free) { - dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", - mcbsp[id].id); - spin_unlock(&mcbsp[id].lock); + 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 -1; } - mcbsp[id].free = 0; - spin_unlock(&mcbsp[id].lock); + mcbsp->free = 0; + spin_unlock(&mcbsp->lock); + + /* + * Make sure that transmitter, receiver and sample-rate generator are + * not running before activating IRQs. + */ + OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR1, 0); + OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR2, 0); - if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { + if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* We need to get IRQs here */ - err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, - 0, "McBSP", (void *) (&mcbsp[id])); + init_completion(&mcbsp->tx_irq_completion); + err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, + 0, "McBSP", (void *)mcbsp); if (err != 0) { - dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d " - "for McBSP%d\n", mcbsp[id].tx_irq, - mcbsp[id].id); + dev_err(mcbsp->dev, "Unable to request TX IRQ %d " + "for McBSP%d\n", mcbsp->tx_irq, + mcbsp->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])); + init_completion(&mcbsp->rx_irq_completion); + err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, + 0, "McBSP", (void *)mcbsp); if (err != 0) { - dev_err(mcbsp[id].dev, "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])); + dev_err(mcbsp->dev, "Unable to request RX IRQ %d " + "for McBSP%d\n", mcbsp->rx_irq, + mcbsp->id); + free_irq(mcbsp->tx_irq, (void *)mcbsp); return err; } - - init_completion(&(mcbsp[id].rx_irq_completion)); } return 0; @@ -237,31 +271,34 @@ EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { + struct omap_mcbsp *mcbsp; + 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); - if (mcbsp[id].pdata->ops->free) - mcbsp[id].pdata->ops->free(id); + if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) + mcbsp->pdata->ops->free(id); - clk_disable(mcbsp[id].clk); + clk_disable(mcbsp->clk); - spin_lock(&mcbsp[id].lock); - if (mcbsp[id].free) { - dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n", - mcbsp[id].id); - spin_unlock(&mcbsp[id].lock); + spin_lock(&mcbsp->lock); + if (mcbsp->free) { + dev_err(mcbsp->dev, "McBSP%d was not reserved\n", + mcbsp->id); + spin_unlock(&mcbsp->lock); return; } - mcbsp[id].free = 1; - spin_unlock(&mcbsp[id].lock); + mcbsp->free = 1; + spin_unlock(&mcbsp->lock); - if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { + if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { /* Free IRQs */ - free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); - free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); + free_irq(mcbsp->rx_irq, (void *)mcbsp); + free_irq(mcbsp->tx_irq, (void *)mcbsp); } } EXPORT_SYMBOL(omap_mcbsp_free); @@ -273,18 +310,19 @@ EXPORT_SYMBOL(omap_mcbsp_free); */ void omap_mcbsp_start(unsigned int id) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; u16 w; 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); + io_base = mcbsp->io_base; - io_base = mcbsp[id].io_base; - - mcbsp[id].rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; - mcbsp[id].tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; + mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; + mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; /* Start the sample generator */ w = OMAP_MCBSP_READ(io_base, SPCR2); @@ -310,7 +348,8 @@ EXPORT_SYMBOL(omap_mcbsp_start); void omap_mcbsp_stop(unsigned int id) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -318,7 +357,8 @@ void omap_mcbsp_stop(unsigned int id) return; } - io_base = mcbsp[id].io_base; + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; /* Reset transmitter */ w = OMAP_MCBSP_READ(io_base, SPCR2); @@ -337,14 +377,17 @@ EXPORT_SYMBOL(omap_mcbsp_stop); /* polled mcbsp i/o operations */ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) { - u32 base; + struct omap_mcbsp *mcbsp; + void __iomem *base; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } - base = mcbsp[id].io_base; + mcbsp = id_to_mcbsp_ptr(id); + base = mcbsp->io_base; + writew(buf, base + OMAP_MCBSP_REG_DXR1); /* if frame sync error - clear the error */ if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { @@ -366,8 +409,8 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) (XRST), base + OMAP_MCBSP_REG_SPCR2); udelay(10); - dev_err(mcbsp[id].dev, "Could not write to" - " McBSP%d Register\n", mcbsp[id].id); + dev_err(mcbsp->dev, "Could not write to" + " McBSP%d Register\n", mcbsp->id); return -2; } } @@ -379,14 +422,16 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite); int omap_mcbsp_pollread(unsigned int id, u16 *buf) { - u32 base; + struct omap_mcbsp *mcbsp; + void __iomem *base; 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); - base = mcbsp[id].io_base; + base = mcbsp->io_base; /* if frame sync error - clear the error */ if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { /* clear error */ @@ -407,8 +452,8 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) (RRST), base + OMAP_MCBSP_REG_SPCR1); udelay(10); - dev_err(mcbsp[id].dev, "Could not read from" - " McBSP%d Register\n", mcbsp[id].id); + dev_err(mcbsp->dev, "Could not read from" + " McBSP%d Register\n", mcbsp->id); return -2; } } @@ -424,7 +469,8 @@ EXPORT_SYMBOL(omap_mcbsp_pollread); */ void omap_mcbsp_xmit_word(unsigned int id, u32 word) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; omap_mcbsp_word_length word_length; if (!omap_mcbsp_check_valid_id(id)) { @@ -432,10 +478,11 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word) return; } - io_base = mcbsp[id].io_base; - word_length = mcbsp[id].tx_word_length; + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + word_length = mcbsp->tx_word_length; - wait_for_completion(&(mcbsp[id].tx_irq_completion)); + wait_for_completion(&mcbsp->tx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); @@ -445,7 +492,8 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word); u32 omap_mcbsp_recv_word(unsigned int id) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; u16 word_lsb, word_msb = 0; omap_mcbsp_word_length word_length; @@ -453,11 +501,12 @@ u32 omap_mcbsp_recv_word(unsigned int id) printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } + mcbsp = id_to_mcbsp_ptr(id); - word_length = mcbsp[id].rx_word_length; - io_base = mcbsp[id].io_base; + word_length = mcbsp->rx_word_length; + io_base = mcbsp->io_base; - wait_for_completion(&(mcbsp[id].rx_irq_completion)); + wait_for_completion(&mcbsp->rx_irq_completion); if (word_length > OMAP_MCBSP_WORD_16) word_msb = OMAP_MCBSP_READ(io_base, DRR2); @@ -469,7 +518,8 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word); int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) { - u32 io_base; + struct omap_mcbsp *mcbsp; + void __iomem *io_base; omap_mcbsp_word_length tx_word_length; omap_mcbsp_word_length rx_word_length; u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; @@ -478,10 +528,10 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } - - io_base = mcbsp[id].io_base; - tx_word_length = mcbsp[id].tx_word_length; - rx_word_length = mcbsp[id].rx_word_length; + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + tx_word_length = mcbsp->tx_word_length; + rx_word_length = mcbsp->rx_word_length; if (tx_word_length != rx_word_length) return -EINVAL; @@ -496,8 +546,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); udelay(10); - dev_err(mcbsp[id].dev, "McBSP%d transmitter not " - "ready\n", mcbsp[id].id); + dev_err(mcbsp->dev, "McBSP%d transmitter not " + "ready\n", mcbsp->id); return -EAGAIN; } } @@ -517,8 +567,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); udelay(10); - dev_err(mcbsp[id].dev, "McBSP%d receiver not " - "ready\n", mcbsp[id].id); + dev_err(mcbsp->dev, "McBSP%d receiver not " + "ready\n", mcbsp->id); return -EAGAIN; } } @@ -534,7 +584,9 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) { - u32 io_base, clock_word = 0; + struct omap_mcbsp *mcbsp; + u32 clock_word = 0; + void __iomem *io_base; omap_mcbsp_word_length tx_word_length; omap_mcbsp_word_length rx_word_length; u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; @@ -544,9 +596,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) return -ENODEV; } - io_base = mcbsp[id].io_base; - tx_word_length = mcbsp[id].tx_word_length; - rx_word_length = mcbsp[id].rx_word_length; + mcbsp = id_to_mcbsp_ptr(id); + io_base = mcbsp->io_base; + + tx_word_length = mcbsp->tx_word_length; + rx_word_length = mcbsp->rx_word_length; if (tx_word_length != rx_word_length) return -EINVAL; @@ -561,8 +615,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); udelay(10); - dev_err(mcbsp[id].dev, "McBSP%d transmitter not " - "ready\n", mcbsp[id].id); + dev_err(mcbsp->dev, "McBSP%d transmitter not " + "ready\n", mcbsp->id); return -EAGAIN; } } @@ -582,8 +636,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) udelay(10); OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); udelay(10); - dev_err(mcbsp[id].dev, "McBSP%d receiver not " - "ready\n", mcbsp[id].id); + dev_err(mcbsp->dev, "McBSP%d receiver not " + "ready\n", mcbsp->id); return -EAGAIN; } } @@ -609,6 +663,7 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); 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; @@ -618,50 +673,51 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } + mcbsp = id_to_mcbsp_ptr(id); - if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", + if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback, - &mcbsp[id], + mcbsp, &dma_tx_ch)) { - dev_err(mcbsp[id].dev, " Unable to request DMA channel for " + dev_err(mcbsp->dev, " Unable to request DMA channel for " "McBSP%d TX. Trying IRQ based TX\n", - mcbsp[id].id); + mcbsp->id); return -EAGAIN; } - mcbsp[id].dma_tx_lch = dma_tx_ch; + mcbsp->dma_tx_lch = dma_tx_ch; - dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id, + dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id, dma_tx_ch); - init_completion(&(mcbsp[id].tx_dma_completion)); + 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[id].dma_tx_sync; + sync_dev = mcbsp->dma_tx_sync; - omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, + 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[id].dma_tx_lch, + omap_set_dma_dest_params(mcbsp->dma_tx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1, + mcbsp->phys_base + OMAP_MCBSP_REG_DXR1, 0, 0); - omap_set_dma_src_params(mcbsp[id].dma_tx_lch, + omap_set_dma_src_params(mcbsp->dma_tx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); - omap_start_dma(mcbsp[id].dma_tx_lch); - wait_for_completion(&(mcbsp[id].tx_dma_completion)); + omap_start_dma(mcbsp->dma_tx_lch); + wait_for_completion(&mcbsp->tx_dma_completion); return 0; } @@ -670,6 +726,7 @@ 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; @@ -679,50 +736,51 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); return -ENODEV; } + mcbsp = id_to_mcbsp_ptr(id); - if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", + if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback, - &mcbsp[id], + mcbsp, &dma_rx_ch)) { - dev_err(mcbsp[id].dev, "Unable to request DMA channel for " + dev_err(mcbsp->dev, "Unable to request DMA channel for " "McBSP%d RX. Trying IRQ based RX\n", - mcbsp[id].id); + mcbsp->id); return -EAGAIN; } - mcbsp[id].dma_rx_lch = dma_rx_ch; + mcbsp->dma_rx_lch = dma_rx_ch; - dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id, + dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id, dma_rx_ch); - init_completion(&(mcbsp[id].rx_dma_completion)); + 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[id].dma_rx_sync; + sync_dev = mcbsp->dma_rx_sync; - omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, + 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[id].dma_rx_lch, + omap_set_dma_src_params(mcbsp->dma_rx_lch, src_port, OMAP_DMA_AMODE_CONSTANT, - mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1, + mcbsp->phys_base + OMAP_MCBSP_REG_DRR1, 0, 0); - omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, + omap_set_dma_dest_params(mcbsp->dma_rx_lch, dest_port, OMAP_DMA_AMODE_POST_INC, buffer, 0, 0); - omap_start_dma(mcbsp[id].dma_rx_lch); - wait_for_completion(&(mcbsp[id].rx_dma_completion)); + omap_start_dma(mcbsp->dma_rx_lch); + wait_for_completion(&mcbsp->rx_dma_completion); return 0; } @@ -737,12 +795,14 @@ EXPORT_SYMBOL(omap_mcbsp_recv_buffer); void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg *spi_cfg) { + struct omap_mcbsp *mcbsp; struct omap_mcbsp_reg_cfg mcbsp_cfg; 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); memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); @@ -803,9 +863,10 @@ EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. */ -static int __init omap_mcbsp_probe(struct platform_device *pdev) +static int __devinit omap_mcbsp_probe(struct platform_device *pdev) { struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; + struct omap_mcbsp *mcbsp; int id = pdev->id - 1; int ret = 0; @@ -818,47 +879,63 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); - if (id >= OMAP_MAX_MCBSP_COUNT) { + if (id >= omap_mcbsp_count) { dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); ret = -EINVAL; goto exit; } - spin_lock_init(&mcbsp[id].lock); - mcbsp[id].id = id + 1; - mcbsp[id].free = 1; - mcbsp[id].dma_tx_lch = -1; - mcbsp[id].dma_rx_lch = -1; + mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL); + if (!mcbsp) { + ret = -ENOMEM; + goto exit; + } + mcbsp_ptr[id] = mcbsp; + + spin_lock_init(&mcbsp->lock); + mcbsp->id = id + 1; + mcbsp->free = 1; + mcbsp->dma_tx_lch = -1; + mcbsp->dma_rx_lch = -1; + + mcbsp->phys_base = pdata->phys_base; + mcbsp->io_base = ioremap(pdata->phys_base, SZ_4K); + if (!mcbsp->io_base) { + ret = -ENOMEM; + goto err_ioremap; + } - mcbsp[id].phys_base = pdata->phys_base; - mcbsp[id].io_base = pdata->virt_base; /* Default I/O is IRQ based */ - mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; - mcbsp[id].tx_irq = pdata->tx_irq; - mcbsp[id].rx_irq = pdata->rx_irq; - mcbsp[id].dma_rx_sync = pdata->dma_rx_sync; - mcbsp[id].dma_tx_sync = pdata->dma_tx_sync; + mcbsp->io_type = OMAP_MCBSP_IRQ_IO; + mcbsp->tx_irq = pdata->tx_irq; + mcbsp->rx_irq = pdata->rx_irq; + mcbsp->dma_rx_sync = pdata->dma_rx_sync; + mcbsp->dma_tx_sync = pdata->dma_tx_sync; if (pdata->clk_name) - mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name); - if (IS_ERR(mcbsp[id].clk)) { - mcbsp[id].free = 0; + mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name); + if (IS_ERR(mcbsp->clk)) { dev_err(&pdev->dev, "Invalid clock configuration for McBSP%d.\n", - mcbsp[id].id); - ret = -EINVAL; - goto exit; + mcbsp->id); + ret = PTR_ERR(mcbsp->clk); + goto err_clk; } - mcbsp[id].pdata = pdata; - mcbsp[id].dev = &pdev->dev; - platform_set_drvdata(pdev, &mcbsp[id]); + mcbsp->pdata = pdata; + mcbsp->dev = &pdev->dev; + platform_set_drvdata(pdev, mcbsp); + return 0; +err_clk: + iounmap(mcbsp->io_base); +err_ioremap: + mcbsp->free = 0; exit: return ret; } -static int omap_mcbsp_remove(struct platform_device *pdev) +static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); @@ -872,6 +949,8 @@ static int omap_mcbsp_remove(struct platform_device *pdev) clk_disable(mcbsp->clk); clk_put(mcbsp->clk); + iounmap(mcbsp->io_base); + mcbsp->clk = NULL; mcbsp->free = 0; mcbsp->dev = NULL; @@ -882,7 +961,7 @@ static int omap_mcbsp_remove(struct platform_device *pdev) static struct platform_driver omap_mcbsp_driver = { .probe = omap_mcbsp_probe, - .remove = omap_mcbsp_remove, + .remove = __devexit_p(omap_mcbsp_remove), .driver = { .name = "omap-mcbsp", }, |