diff options
| -rw-r--r-- | arch/arm/plat-omap/devices.c | 48 | ||||
| -rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 662 | ||||
| -rw-r--r-- | include/asm-arm/arch-omap/mcbsp.h | 62 |
3 files changed, 361 insertions, 411 deletions
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 4a53f9ba6c43..81002b722da1 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <asm/arch/mux.h> | 24 | #include <asm/arch/mux.h> |
| 25 | #include <asm/arch/gpio.h> | 25 | #include <asm/arch/gpio.h> |
| 26 | #include <asm/arch/menelaus.h> | 26 | #include <asm/arch/menelaus.h> |
| 27 | #include <asm/arch/mcbsp.h> | ||
| 27 | 28 | ||
| 28 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) | 29 | #if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE) |
| 29 | 30 | ||
| @@ -145,6 +146,53 @@ static inline void omap_init_kp(void) {} | |||
| 145 | #endif | 146 | #endif |
| 146 | 147 | ||
| 147 | /*-------------------------------------------------------------------------*/ | 148 | /*-------------------------------------------------------------------------*/ |
| 149 | #if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE) | ||
| 150 | |||
| 151 | static struct platform_device **omap_mcbsp_devices; | ||
| 152 | |||
| 153 | void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, | ||
| 154 | int size) | ||
| 155 | { | ||
| 156 | int i; | ||
| 157 | |||
| 158 | if (size > OMAP_MAX_MCBSP_COUNT) { | ||
| 159 | printk(KERN_WARNING "Registered too many McBSPs platform_data." | ||
| 160 | " Using maximum (%d) available.\n", | ||
| 161 | OMAP_MAX_MCBSP_COUNT); | ||
| 162 | size = OMAP_MAX_MCBSP_COUNT; | ||
| 163 | } | ||
| 164 | |||
| 165 | omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *), | ||
| 166 | GFP_KERNEL); | ||
| 167 | if (!omap_mcbsp_devices) { | ||
| 168 | printk(KERN_ERR "Could not register McBSP devices\n"); | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | |||
| 172 | for (i = 0; i < size; i++) { | ||
| 173 | struct platform_device *new_mcbsp; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1); | ||
| 177 | if (!new_mcbsp) | ||
| 178 | continue; | ||
| 179 | new_mcbsp->dev.platform_data = &config[i]; | ||
| 180 | ret = platform_device_add(new_mcbsp); | ||
| 181 | if (ret) { | ||
| 182 | platform_device_put(new_mcbsp); | ||
| 183 | continue; | ||
| 184 | } | ||
| 185 | omap_mcbsp_devices[i] = new_mcbsp; | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | #else | ||
| 190 | void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, | ||
| 191 | int size) | ||
| 192 | { } | ||
| 193 | #endif | ||
| 194 | |||
| 195 | /*-------------------------------------------------------------------------*/ | ||
| 148 | 196 | ||
| 149 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | 197 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) |
| 150 | 198 | ||
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index c0018b1b6673..c7f74064696c 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| 17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 18 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
| 19 | #include <linux/completion.h> | 20 | #include <linux/completion.h> |
| 20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| @@ -24,83 +25,53 @@ | |||
| 24 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 25 | 26 | ||
| 26 | #include <asm/arch/dma.h> | 27 | #include <asm/arch/dma.h> |
| 27 | #include <asm/arch/mux.h> | ||
| 28 | #include <asm/arch/irqs.h> | ||
| 29 | #include <asm/arch/dsp_common.h> | ||
| 30 | #include <asm/arch/mcbsp.h> | 28 | #include <asm/arch/mcbsp.h> |
| 31 | 29 | ||
| 32 | #ifdef CONFIG_MCBSP_DEBUG | ||
| 33 | #define DBG(x...) printk(x) | ||
| 34 | #else | ||
| 35 | #define DBG(x...) do { } while (0) | ||
| 36 | #endif | ||
| 37 | |||
| 38 | struct omap_mcbsp { | ||
| 39 | u32 io_base; | ||
| 40 | u8 id; | ||
| 41 | u8 free; | ||
| 42 | omap_mcbsp_word_length rx_word_length; | ||
| 43 | omap_mcbsp_word_length tx_word_length; | ||
| 44 | |||
| 45 | omap_mcbsp_io_type_t io_type; /* IRQ or poll */ | ||
| 46 | /* IRQ based TX/RX */ | ||
| 47 | int rx_irq; | ||
| 48 | int tx_irq; | ||
| 49 | |||
| 50 | /* DMA stuff */ | ||
| 51 | u8 dma_rx_sync; | ||
| 52 | short dma_rx_lch; | ||
| 53 | u8 dma_tx_sync; | ||
| 54 | short dma_tx_lch; | ||
| 55 | |||
| 56 | /* Completion queues */ | ||
| 57 | struct completion tx_irq_completion; | ||
| 58 | struct completion rx_irq_completion; | ||
| 59 | struct completion tx_dma_completion; | ||
| 60 | struct completion rx_dma_completion; | ||
| 61 | |||
| 62 | /* Protect the field .free, while checking if the mcbsp is in use */ | ||
| 63 | spinlock_t lock; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; | 30 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; |
| 67 | #ifdef CONFIG_ARCH_OMAP1 | 31 | |
| 68 | static struct clk *mcbsp_dsp_ck; | 32 | #define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \ |
| 69 | static struct clk *mcbsp_api_ck; | 33 | mcbsp[id].pdata->ops && \ |
| 70 | static struct clk *mcbsp_dspxor_ck; | 34 | mcbsp[id].pdata->ops->check && \ |
| 71 | #endif | 35 | (mcbsp[id].pdata->ops->check(id) == 0)) |
| 72 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 73 | static struct clk *mcbsp1_ick; | ||
| 74 | static struct clk *mcbsp1_fck; | ||
| 75 | static struct clk *mcbsp2_ick; | ||
| 76 | static struct clk *mcbsp2_fck; | ||
| 77 | #endif | ||
| 78 | 36 | ||
| 79 | static void omap_mcbsp_dump_reg(u8 id) | 37 | static void omap_mcbsp_dump_reg(u8 id) |
| 80 | { | 38 | { |
| 81 | DBG("**** MCBSP%d regs ****\n", mcbsp[id].id); | 39 | dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id); |
| 82 | DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); | 40 | dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n", |
| 83 | DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); | 41 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); |
| 84 | DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); | 42 | dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n", |
| 85 | DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); | 43 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); |
| 86 | DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); | 44 | dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n", |
| 87 | DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); | 45 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); |
| 88 | DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); | 46 | dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n", |
| 89 | DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); | 47 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); |
| 90 | DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); | 48 | dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n", |
| 91 | DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); | 49 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); |
| 92 | DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); | 50 | dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n", |
| 93 | DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); | 51 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); |
| 94 | DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); | 52 | dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n", |
| 95 | DBG("***********************\n"); | 53 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); |
| 54 | dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n", | ||
| 55 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); | ||
| 56 | dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n", | ||
| 57 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); | ||
| 58 | dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n", | ||
| 59 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); | ||
| 60 | dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n", | ||
| 61 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); | ||
| 62 | dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n", | ||
| 63 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); | ||
| 64 | dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n", | ||
| 65 | OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); | ||
| 66 | dev_dbg(mcbsp[id].dev, "***********************\n"); | ||
| 96 | } | 67 | } |
| 97 | 68 | ||
| 98 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) | 69 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) |
| 99 | { | 70 | { |
| 100 | struct omap_mcbsp *mcbsp_tx = dev_id; | 71 | struct omap_mcbsp *mcbsp_tx = dev_id; |
| 101 | 72 | ||
| 102 | DBG("TX IRQ callback : 0x%x\n", | 73 | dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", |
| 103 | OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); | 74 | OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); |
| 104 | 75 | ||
| 105 | complete(&mcbsp_tx->tx_irq_completion); | 76 | complete(&mcbsp_tx->tx_irq_completion); |
| 106 | 77 | ||
| @@ -111,8 +82,8 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) | |||
| 111 | { | 82 | { |
| 112 | struct omap_mcbsp *mcbsp_rx = dev_id; | 83 | struct omap_mcbsp *mcbsp_rx = dev_id; |
| 113 | 84 | ||
| 114 | DBG("RX IRQ callback : 0x%x\n", | 85 | dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", |
| 115 | OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); | 86 | OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); |
| 116 | 87 | ||
| 117 | complete(&mcbsp_rx->rx_irq_completion); | 88 | complete(&mcbsp_rx->rx_irq_completion); |
| 118 | 89 | ||
| @@ -123,8 +94,8 @@ static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | |||
| 123 | { | 94 | { |
| 124 | struct omap_mcbsp *mcbsp_dma_tx = data; | 95 | struct omap_mcbsp *mcbsp_dma_tx = data; |
| 125 | 96 | ||
| 126 | DBG("TX DMA callback : 0x%x\n", | 97 | dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", |
| 127 | OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); | 98 | OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); |
| 128 | 99 | ||
| 129 | /* We can free the channels */ | 100 | /* We can free the channels */ |
| 130 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); | 101 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); |
| @@ -137,8 +108,8 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
| 137 | { | 108 | { |
| 138 | struct omap_mcbsp *mcbsp_dma_rx = data; | 109 | struct omap_mcbsp *mcbsp_dma_rx = data; |
| 139 | 110 | ||
| 140 | DBG("RX DMA callback : 0x%x\n", | 111 | dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", |
| 141 | OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); | 112 | OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); |
| 142 | 113 | ||
| 143 | /* We can free the channels */ | 114 | /* We can free the channels */ |
| 144 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); | 115 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); |
| @@ -155,9 +126,16 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
| 155 | */ | 126 | */ |
| 156 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | 127 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) |
| 157 | { | 128 | { |
| 158 | u32 io_base = mcbsp[id].io_base; | 129 | u32 io_base; |
| 159 | 130 | ||
| 160 | DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id + 1, io_base); | 131 | if (!omap_mcbsp_check_valid_id(id)) { |
| 132 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 133 | return; | ||
| 134 | } | ||
| 135 | |||
| 136 | io_base = mcbsp[id].io_base; | ||
| 137 | dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n", | ||
| 138 | mcbsp[id].id, io_base); | ||
| 161 | 139 | ||
| 162 | /* We write the given config */ | 140 | /* We write the given config */ |
| 163 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); | 141 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); |
| @@ -174,97 +152,22 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | |||
| 174 | } | 152 | } |
| 175 | EXPORT_SYMBOL(omap_mcbsp_config); | 153 | EXPORT_SYMBOL(omap_mcbsp_config); |
| 176 | 154 | ||
| 177 | static int omap_mcbsp_check(unsigned int id) | ||
| 178 | { | ||
| 179 | if (cpu_is_omap730()) { | ||
| 180 | if (id > OMAP_MAX_MCBSP_COUNT - 1) { | ||
| 181 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", | ||
| 182 | id + 1); | ||
| 183 | return -1; | ||
| 184 | } | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) { | ||
| 189 | if (id > OMAP_MAX_MCBSP_COUNT) { | ||
| 190 | printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", | ||
| 191 | id + 1); | ||
| 192 | return -1; | ||
| 193 | } | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | return -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 201 | static void omap_mcbsp_dsp_request(void) | ||
| 202 | { | ||
| 203 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | ret = omap_dsp_request_mem(); | ||
| 207 | if (ret < 0) { | ||
| 208 | printk(KERN_ERR "Could not get dsp memory: %i\n", ret); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | |||
| 212 | clk_enable(mcbsp_dsp_ck); | ||
| 213 | clk_enable(mcbsp_api_ck); | ||
| 214 | |||
| 215 | /* enable 12MHz clock to mcbsp 1 & 3 */ | ||
| 216 | clk_enable(mcbsp_dspxor_ck); | ||
| 217 | |||
| 218 | /* | ||
| 219 | * DSP external peripheral reset | ||
| 220 | * FIXME: This should be moved to dsp code | ||
| 221 | */ | ||
| 222 | __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1, | ||
| 223 | DSP_RSTCT2); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | static void omap_mcbsp_dsp_free(void) | ||
| 228 | { | ||
| 229 | if (cpu_is_omap15xx() || cpu_is_omap16xx()) { | ||
| 230 | omap_dsp_release_mem(); | ||
| 231 | clk_disable(mcbsp_dspxor_ck); | ||
| 232 | clk_disable(mcbsp_dsp_ck); | ||
| 233 | clk_disable(mcbsp_api_ck); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | #endif | ||
| 237 | |||
| 238 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 239 | static void omap2_mcbsp2_mux_setup(void) | ||
| 240 | { | ||
| 241 | if (cpu_is_omap2420()) { | ||
| 242 | omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); | ||
| 243 | omap_cfg_reg(R14_24XX_MCBSP2_FSX); | ||
| 244 | omap_cfg_reg(W15_24XX_MCBSP2_DR); | ||
| 245 | omap_cfg_reg(V15_24XX_MCBSP2_DX); | ||
| 246 | omap_cfg_reg(V14_24XX_GPIO117); | ||
| 247 | } | ||
| 248 | /* | ||
| 249 | * Need to add MUX settings for OMAP 2430 SDP | ||
| 250 | */ | ||
| 251 | } | ||
| 252 | #endif | ||
| 253 | |||
| 254 | /* | 155 | /* |
| 255 | * We can choose between IRQ based or polled IO. | 156 | * We can choose between IRQ based or polled IO. |
| 256 | * This needs to be called before omap_mcbsp_request(). | 157 | * This needs to be called before omap_mcbsp_request(). |
| 257 | */ | 158 | */ |
| 258 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | 159 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) |
| 259 | { | 160 | { |
| 260 | if (omap_mcbsp_check(id) < 0) | 161 | if (!omap_mcbsp_check_valid_id(id)) { |
| 261 | return -EINVAL; | 162 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
| 163 | return -ENODEV; | ||
| 164 | } | ||
| 262 | 165 | ||
| 263 | spin_lock(&mcbsp[id].lock); | 166 | spin_lock(&mcbsp[id].lock); |
| 264 | 167 | ||
| 265 | if (!mcbsp[id].free) { | 168 | if (!mcbsp[id].free) { |
| 266 | printk(KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", | 169 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", |
| 267 | id + 1); | 170 | mcbsp[id].id); |
| 268 | spin_unlock(&mcbsp[id].lock); | 171 | spin_unlock(&mcbsp[id].lock); |
| 269 | return -EINVAL; | 172 | return -EINVAL; |
| 270 | } | 173 | } |
| @@ -281,34 +184,20 @@ int omap_mcbsp_request(unsigned int id) | |||
| 281 | { | 184 | { |
| 282 | int err; | 185 | int err; |
| 283 | 186 | ||
| 284 | if (omap_mcbsp_check(id) < 0) | 187 | if (!omap_mcbsp_check_valid_id(id)) { |
| 285 | return -EINVAL; | 188 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
| 286 | 189 | return -ENODEV; | |
| 287 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 288 | /* | ||
| 289 | * On 1510, 1610 and 1710, McBSP1 and McBSP3 | ||
| 290 | * are DSP public peripherals. | ||
| 291 | */ | ||
| 292 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
| 293 | omap_mcbsp_dsp_request(); | ||
| 294 | #endif | ||
| 295 | |||
| 296 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 297 | if (cpu_is_omap24xx()) { | ||
| 298 | if (id == OMAP_MCBSP1) { | ||
| 299 | clk_enable(mcbsp1_ick); | ||
| 300 | clk_enable(mcbsp1_fck); | ||
| 301 | } else { | ||
| 302 | clk_enable(mcbsp2_ick); | ||
| 303 | clk_enable(mcbsp2_fck); | ||
| 304 | } | ||
| 305 | } | 190 | } |
| 306 | #endif | 191 | |
| 192 | if (mcbsp[id].pdata->ops->request) | ||
| 193 | mcbsp[id].pdata->ops->request(id); | ||
| 194 | |||
| 195 | clk_enable(mcbsp[id].clk); | ||
| 307 | 196 | ||
| 308 | spin_lock(&mcbsp[id].lock); | 197 | spin_lock(&mcbsp[id].lock); |
| 309 | if (!mcbsp[id].free) { | 198 | if (!mcbsp[id].free) { |
| 310 | printk(KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", | 199 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", |
| 311 | id + 1); | 200 | mcbsp[id].id); |
| 312 | spin_unlock(&mcbsp[id].lock); | 201 | spin_unlock(&mcbsp[id].lock); |
| 313 | return -1; | 202 | return -1; |
| 314 | } | 203 | } |
| @@ -321,9 +210,9 @@ int omap_mcbsp_request(unsigned int id) | |||
| 321 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, | 210 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, |
| 322 | 0, "McBSP", (void *) (&mcbsp[id])); | 211 | 0, "McBSP", (void *) (&mcbsp[id])); |
| 323 | if (err != 0) { | 212 | if (err != 0) { |
| 324 | printk(KERN_ERR "OMAP-McBSP: Unable to " | 213 | dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d " |
| 325 | "request TX IRQ %d for McBSP%d\n", | 214 | "for McBSP%d\n", mcbsp[id].tx_irq, |
| 326 | mcbsp[id].tx_irq, mcbsp[id].id); | 215 | mcbsp[id].id); |
| 327 | return err; | 216 | return err; |
| 328 | } | 217 | } |
| 329 | 218 | ||
| @@ -332,9 +221,9 @@ int omap_mcbsp_request(unsigned int id) | |||
| 332 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, | 221 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, |
| 333 | 0, "McBSP", (void *) (&mcbsp[id])); | 222 | 0, "McBSP", (void *) (&mcbsp[id])); |
| 334 | if (err != 0) { | 223 | if (err != 0) { |
| 335 | printk(KERN_ERR "OMAP-McBSP: Unable to " | 224 | dev_err(mcbsp[id].dev, "Unable to request RX IRQ %d " |
| 336 | "request RX IRQ %d for McBSP%d\n", | 225 | "for McBSP%d\n", mcbsp[id].rx_irq, |
| 337 | mcbsp[id].rx_irq, mcbsp[id].id); | 226 | mcbsp[id].id); |
| 338 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 227 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); |
| 339 | return err; | 228 | return err; |
| 340 | } | 229 | } |
| @@ -348,32 +237,20 @@ EXPORT_SYMBOL(omap_mcbsp_request); | |||
| 348 | 237 | ||
| 349 | void omap_mcbsp_free(unsigned int id) | 238 | void omap_mcbsp_free(unsigned int id) |
| 350 | { | 239 | { |
| 351 | if (omap_mcbsp_check(id) < 0) | 240 | if (!omap_mcbsp_check_valid_id(id)) { |
| 241 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 352 | return; | 242 | return; |
| 353 | |||
| 354 | #ifdef CONFIG_ARCH_OMAP1 | ||
| 355 | if (cpu_class_is_omap1()) { | ||
| 356 | if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) | ||
| 357 | omap_mcbsp_dsp_free(); | ||
| 358 | } | 243 | } |
| 359 | #endif | 244 | |
| 360 | 245 | if (mcbsp[id].pdata->ops->free) | |
| 361 | #ifdef CONFIG_ARCH_OMAP2 | 246 | mcbsp[id].pdata->ops->free(id); |
| 362 | if (cpu_is_omap24xx()) { | 247 | |
| 363 | if (id == OMAP_MCBSP1) { | 248 | clk_disable(mcbsp[id].clk); |
| 364 | clk_disable(mcbsp1_ick); | ||
| 365 | clk_disable(mcbsp1_fck); | ||
| 366 | } else { | ||
| 367 | clk_disable(mcbsp2_ick); | ||
| 368 | clk_disable(mcbsp2_fck); | ||
| 369 | } | ||
| 370 | } | ||
| 371 | #endif | ||
| 372 | 249 | ||
| 373 | spin_lock(&mcbsp[id].lock); | 250 | spin_lock(&mcbsp[id].lock); |
| 374 | if (mcbsp[id].free) { | 251 | if (mcbsp[id].free) { |
| 375 | printk(KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", | 252 | dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n", |
| 376 | id + 1); | 253 | mcbsp[id].id); |
| 377 | spin_unlock(&mcbsp[id].lock); | 254 | spin_unlock(&mcbsp[id].lock); |
| 378 | return; | 255 | return; |
| 379 | } | 256 | } |
| @@ -399,8 +276,10 @@ void omap_mcbsp_start(unsigned int id) | |||
| 399 | u32 io_base; | 276 | u32 io_base; |
| 400 | u16 w; | 277 | u16 w; |
| 401 | 278 | ||
| 402 | if (omap_mcbsp_check(id) < 0) | 279 | if (!omap_mcbsp_check_valid_id(id)) { |
| 280 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 403 | return; | 281 | return; |
| 282 | } | ||
| 404 | 283 | ||
| 405 | io_base = mcbsp[id].io_base; | 284 | io_base = mcbsp[id].io_base; |
| 406 | 285 | ||
| @@ -434,8 +313,10 @@ void omap_mcbsp_stop(unsigned int id) | |||
| 434 | u32 io_base; | 313 | u32 io_base; |
| 435 | u16 w; | 314 | u16 w; |
| 436 | 315 | ||
| 437 | if (omap_mcbsp_check(id) < 0) | 316 | if (!omap_mcbsp_check_valid_id(id)) { |
| 317 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 438 | return; | 318 | return; |
| 319 | } | ||
| 439 | 320 | ||
| 440 | io_base = mcbsp[id].io_base; | 321 | io_base = mcbsp[id].io_base; |
| 441 | 322 | ||
| @@ -456,7 +337,14 @@ EXPORT_SYMBOL(omap_mcbsp_stop); | |||
| 456 | /* polled mcbsp i/o operations */ | 337 | /* polled mcbsp i/o operations */ |
| 457 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | 338 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) |
| 458 | { | 339 | { |
| 459 | u32 base = mcbsp[id].io_base; | 340 | u32 base; |
| 341 | |||
| 342 | if (!omap_mcbsp_check_valid_id(id)) { | ||
| 343 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 344 | return -ENODEV; | ||
| 345 | } | ||
| 346 | |||
| 347 | base = mcbsp[id].io_base; | ||
| 460 | writew(buf, base + OMAP_MCBSP_REG_DXR1); | 348 | writew(buf, base + OMAP_MCBSP_REG_DXR1); |
| 461 | /* if frame sync error - clear the error */ | 349 | /* if frame sync error - clear the error */ |
| 462 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { | 350 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { |
| @@ -478,8 +366,8 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | |||
| 478 | (XRST), | 366 | (XRST), |
| 479 | base + OMAP_MCBSP_REG_SPCR2); | 367 | base + OMAP_MCBSP_REG_SPCR2); |
| 480 | udelay(10); | 368 | udelay(10); |
| 481 | printk(KERN_ERR | 369 | dev_err(mcbsp[id].dev, "Could not write to" |
| 482 | " Could not write to McBSP Register\n"); | 370 | " McBSP%d Register\n", mcbsp[id].id); |
| 483 | return -2; | 371 | return -2; |
| 484 | } | 372 | } |
| 485 | } | 373 | } |
| @@ -491,7 +379,14 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite); | |||
| 491 | 379 | ||
| 492 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) | 380 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) |
| 493 | { | 381 | { |
| 494 | u32 base = mcbsp[id].io_base; | 382 | u32 base; |
| 383 | |||
| 384 | if (!omap_mcbsp_check_valid_id(id)) { | ||
| 385 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 386 | return -ENODEV; | ||
| 387 | } | ||
| 388 | |||
| 389 | base = mcbsp[id].io_base; | ||
| 495 | /* if frame sync error - clear the error */ | 390 | /* if frame sync error - clear the error */ |
| 496 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { | 391 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { |
| 497 | /* clear error */ | 392 | /* clear error */ |
| @@ -512,8 +407,8 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) | |||
| 512 | (RRST), | 407 | (RRST), |
| 513 | base + OMAP_MCBSP_REG_SPCR1); | 408 | base + OMAP_MCBSP_REG_SPCR1); |
| 514 | udelay(10); | 409 | udelay(10); |
| 515 | printk(KERN_ERR | 410 | dev_err(mcbsp[id].dev, "Could not read from" |
| 516 | " Could not read from McBSP Register\n"); | 411 | " McBSP%d Register\n", mcbsp[id].id); |
| 517 | return -2; | 412 | return -2; |
| 518 | } | 413 | } |
| 519 | } | 414 | } |
| @@ -530,12 +425,15 @@ EXPORT_SYMBOL(omap_mcbsp_pollread); | |||
| 530 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) | 425 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) |
| 531 | { | 426 | { |
| 532 | u32 io_base; | 427 | u32 io_base; |
| 533 | omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length; | 428 | omap_mcbsp_word_length word_length; |
| 534 | 429 | ||
| 535 | if (omap_mcbsp_check(id) < 0) | 430 | if (!omap_mcbsp_check_valid_id(id)) { |
| 431 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 536 | return; | 432 | return; |
| 433 | } | ||
| 537 | 434 | ||
| 538 | io_base = mcbsp[id].io_base; | 435 | io_base = mcbsp[id].io_base; |
| 436 | word_length = mcbsp[id].tx_word_length; | ||
| 539 | 437 | ||
| 540 | wait_for_completion(&(mcbsp[id].tx_irq_completion)); | 438 | wait_for_completion(&(mcbsp[id].tx_irq_completion)); |
| 541 | 439 | ||
| @@ -549,11 +447,14 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
| 549 | { | 447 | { |
| 550 | u32 io_base; | 448 | u32 io_base; |
| 551 | u16 word_lsb, word_msb = 0; | 449 | u16 word_lsb, word_msb = 0; |
| 552 | omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length; | 450 | omap_mcbsp_word_length word_length; |
| 553 | 451 | ||
| 554 | if (omap_mcbsp_check(id) < 0) | 452 | if (!omap_mcbsp_check_valid_id(id)) { |
| 555 | return -EINVAL; | 453 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
| 454 | return -ENODEV; | ||
| 455 | } | ||
| 556 | 456 | ||
| 457 | word_length = mcbsp[id].rx_word_length; | ||
| 557 | io_base = mcbsp[id].io_base; | 458 | io_base = mcbsp[id].io_base; |
| 558 | 459 | ||
| 559 | wait_for_completion(&(mcbsp[id].rx_irq_completion)); | 460 | wait_for_completion(&(mcbsp[id].rx_irq_completion)); |
| @@ -568,11 +469,20 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word); | |||
| 568 | 469 | ||
| 569 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | 470 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) |
| 570 | { | 471 | { |
| 571 | u32 io_base = mcbsp[id].io_base; | 472 | u32 io_base; |
| 572 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | 473 | omap_mcbsp_word_length tx_word_length; |
| 573 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | 474 | omap_mcbsp_word_length rx_word_length; |
| 574 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 475 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
| 575 | 476 | ||
| 477 | if (!omap_mcbsp_check_valid_id(id)) { | ||
| 478 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 479 | return -ENODEV; | ||
| 480 | } | ||
| 481 | |||
| 482 | io_base = mcbsp[id].io_base; | ||
| 483 | tx_word_length = mcbsp[id].tx_word_length; | ||
| 484 | rx_word_length = mcbsp[id].rx_word_length; | ||
| 485 | |||
| 576 | if (tx_word_length != rx_word_length) | 486 | if (tx_word_length != rx_word_length) |
| 577 | return -EINVAL; | 487 | return -EINVAL; |
| 578 | 488 | ||
| @@ -586,7 +496,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
| 586 | udelay(10); | 496 | udelay(10); |
| 587 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 497 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
| 588 | udelay(10); | 498 | udelay(10); |
| 589 | printk(KERN_ERR "McBSP transmitter not ready\n"); | 499 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " |
| 500 | "ready\n", mcbsp[id].id); | ||
| 590 | return -EAGAIN; | 501 | return -EAGAIN; |
| 591 | } | 502 | } |
| 592 | } | 503 | } |
| @@ -606,7 +517,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
| 606 | udelay(10); | 517 | udelay(10); |
| 607 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 518 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
| 608 | udelay(10); | 519 | udelay(10); |
| 609 | printk(KERN_ERR "McBSP receiver not ready\n"); | 520 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " |
| 521 | "ready\n", mcbsp[id].id); | ||
| 610 | return -EAGAIN; | 522 | return -EAGAIN; |
| 611 | } | 523 | } |
| 612 | } | 524 | } |
| @@ -622,11 +534,20 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | |||
| 622 | 534 | ||
| 623 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | 535 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) |
| 624 | { | 536 | { |
| 625 | u32 io_base = mcbsp[id].io_base, clock_word = 0; | 537 | u32 io_base, clock_word = 0; |
| 626 | omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length; | 538 | omap_mcbsp_word_length tx_word_length; |
| 627 | omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length; | 539 | omap_mcbsp_word_length rx_word_length; |
| 628 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 540 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
| 629 | 541 | ||
| 542 | if (!omap_mcbsp_check_valid_id(id)) { | ||
| 543 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 544 | return -ENODEV; | ||
| 545 | } | ||
| 546 | |||
| 547 | io_base = mcbsp[id].io_base; | ||
| 548 | tx_word_length = mcbsp[id].tx_word_length; | ||
| 549 | rx_word_length = mcbsp[id].rx_word_length; | ||
| 550 | |||
| 630 | if (tx_word_length != rx_word_length) | 551 | if (tx_word_length != rx_word_length) |
| 631 | return -EINVAL; | 552 | return -EINVAL; |
| 632 | 553 | ||
| @@ -640,7 +561,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
| 640 | udelay(10); | 561 | udelay(10); |
| 641 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 562 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
| 642 | udelay(10); | 563 | udelay(10); |
| 643 | printk(KERN_ERR "McBSP transmitter not ready\n"); | 564 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " |
| 565 | "ready\n", mcbsp[id].id); | ||
| 644 | return -EAGAIN; | 566 | return -EAGAIN; |
| 645 | } | 567 | } |
| 646 | } | 568 | } |
| @@ -660,7 +582,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
| 660 | udelay(10); | 582 | udelay(10); |
| 661 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 583 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
| 662 | udelay(10); | 584 | udelay(10); |
| 663 | printk(KERN_ERR "McBSP receiver not ready\n"); | 585 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " |
| 586 | "ready\n", mcbsp[id].id); | ||
| 664 | return -EAGAIN; | 587 | return -EAGAIN; |
| 665 | } | 588 | } |
| 666 | } | 589 | } |
| @@ -691,20 +614,24 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, | |||
| 691 | int dest_port = 0; | 614 | int dest_port = 0; |
| 692 | int sync_dev = 0; | 615 | int sync_dev = 0; |
| 693 | 616 | ||
| 694 | if (omap_mcbsp_check(id) < 0) | 617 | if (!omap_mcbsp_check_valid_id(id)) { |
| 695 | return -EINVAL; | 618 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
| 619 | return -ENODEV; | ||
| 620 | } | ||
| 696 | 621 | ||
| 697 | if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", | 622 | if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", |
| 698 | omap_mcbsp_tx_dma_callback, | 623 | omap_mcbsp_tx_dma_callback, |
| 699 | &mcbsp[id], | 624 | &mcbsp[id], |
| 700 | &dma_tx_ch)) { | 625 | &dma_tx_ch)) { |
| 701 | printk(KERN_ERR "OMAP-McBSP: Unable to request DMA channel for" | 626 | dev_err(mcbsp[id].dev, " Unable to request DMA channel for " |
| 702 | " McBSP%d TX. Trying IRQ based TX\n", id + 1); | 627 | "McBSP%d TX. Trying IRQ based TX\n", |
| 628 | mcbsp[id].id); | ||
| 703 | return -EAGAIN; | 629 | return -EAGAIN; |
| 704 | } | 630 | } |
| 705 | mcbsp[id].dma_tx_lch = dma_tx_ch; | 631 | mcbsp[id].dma_tx_lch = dma_tx_ch; |
| 706 | 632 | ||
| 707 | DBG("TX DMA on channel %d\n", dma_tx_ch); | 633 | dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id, |
| 634 | dma_tx_ch); | ||
| 708 | 635 | ||
| 709 | init_completion(&(mcbsp[id].tx_dma_completion)); | 636 | init_completion(&(mcbsp[id].tx_dma_completion)); |
| 710 | 637 | ||
| @@ -712,7 +639,7 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, | |||
| 712 | src_port = OMAP_DMA_PORT_TIPB; | 639 | src_port = OMAP_DMA_PORT_TIPB; |
| 713 | dest_port = OMAP_DMA_PORT_EMIFF; | 640 | dest_port = OMAP_DMA_PORT_EMIFF; |
| 714 | } | 641 | } |
| 715 | if (cpu_is_omap24xx()) | 642 | if (cpu_class_is_omap2()) |
| 716 | sync_dev = mcbsp[id].dma_tx_sync; | 643 | sync_dev = mcbsp[id].dma_tx_sync; |
| 717 | 644 | ||
| 718 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 645 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, |
| @@ -748,20 +675,24 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | |||
| 748 | int dest_port = 0; | 675 | int dest_port = 0; |
| 749 | int sync_dev = 0; | 676 | int sync_dev = 0; |
| 750 | 677 | ||
| 751 | if (omap_mcbsp_check(id) < 0) | 678 | if (!omap_mcbsp_check_valid_id(id)) { |
| 752 | return -EINVAL; | 679 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
| 680 | return -ENODEV; | ||
| 681 | } | ||
| 753 | 682 | ||
| 754 | if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", | 683 | if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", |
| 755 | omap_mcbsp_rx_dma_callback, | 684 | omap_mcbsp_rx_dma_callback, |
| 756 | &mcbsp[id], | 685 | &mcbsp[id], |
| 757 | &dma_rx_ch)) { | 686 | &dma_rx_ch)) { |
| 758 | printk(KERN_ERR "Unable to request DMA channel for McBSP%d RX." | 687 | dev_err(mcbsp[id].dev, "Unable to request DMA channel for " |
| 759 | " Trying IRQ based RX\n", id + 1); | 688 | "McBSP%d RX. Trying IRQ based RX\n", |
| 689 | mcbsp[id].id); | ||
| 760 | return -EAGAIN; | 690 | return -EAGAIN; |
| 761 | } | 691 | } |
| 762 | mcbsp[id].dma_rx_lch = dma_rx_ch; | 692 | mcbsp[id].dma_rx_lch = dma_rx_ch; |
| 763 | 693 | ||
| 764 | DBG("RX DMA on channel %d\n", dma_rx_ch); | 694 | dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id, |
| 695 | dma_rx_ch); | ||
| 765 | 696 | ||
| 766 | init_completion(&(mcbsp[id].rx_dma_completion)); | 697 | init_completion(&(mcbsp[id].rx_dma_completion)); |
| 767 | 698 | ||
| @@ -769,7 +700,7 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | |||
| 769 | src_port = OMAP_DMA_PORT_TIPB; | 700 | src_port = OMAP_DMA_PORT_TIPB; |
| 770 | dest_port = OMAP_DMA_PORT_EMIFF; | 701 | dest_port = OMAP_DMA_PORT_EMIFF; |
| 771 | } | 702 | } |
| 772 | if (cpu_is_omap24xx()) | 703 | if (cpu_class_is_omap2()) |
| 773 | sync_dev = mcbsp[id].dma_rx_sync; | 704 | sync_dev = mcbsp[id].dma_rx_sync; |
| 774 | 705 | ||
| 775 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 706 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, |
| @@ -808,8 +739,10 @@ void omap_mcbsp_set_spi_mode(unsigned int id, | |||
| 808 | { | 739 | { |
| 809 | struct omap_mcbsp_reg_cfg mcbsp_cfg; | 740 | struct omap_mcbsp_reg_cfg mcbsp_cfg; |
| 810 | 741 | ||
| 811 | if (omap_mcbsp_check(id) < 0) | 742 | if (!omap_mcbsp_check_valid_id(id)) { |
| 743 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
| 812 | return; | 744 | return; |
| 745 | } | ||
| 813 | 746 | ||
| 814 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); | 747 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); |
| 815 | 748 | ||
| @@ -870,182 +803,93 @@ EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | |||
| 870 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 803 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |
| 871 | * 730 has only 2 McBSP, and both of them are MPU peripherals. | 804 | * 730 has only 2 McBSP, and both of them are MPU peripherals. |
| 872 | */ | 805 | */ |
| 873 | struct omap_mcbsp_info { | 806 | static int __init omap_mcbsp_probe(struct platform_device *pdev) |
| 874 | u32 virt_base; | 807 | { |
| 875 | u8 dma_rx_sync, dma_tx_sync; | 808 | struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; |
| 876 | u16 rx_irq, tx_irq; | 809 | int id = pdev->id - 1; |
| 877 | }; | 810 | int ret = 0; |
| 878 | 811 | ||
| 879 | #ifdef CONFIG_ARCH_OMAP730 | 812 | if (!pdata) { |
| 880 | static const struct omap_mcbsp_info mcbsp_730[] = { | 813 | dev_err(&pdev->dev, "McBSP device initialized without" |
| 881 | [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE), | 814 | "platform data\n"); |
| 882 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 815 | ret = -EINVAL; |
| 883 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 816 | goto exit; |
| 884 | .rx_irq = INT_730_McBSP1RX, | 817 | } |
| 885 | .tx_irq = INT_730_McBSP1TX }, | 818 | |
| 886 | [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE), | 819 | dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); |
| 887 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | 820 | |
| 888 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | 821 | if (id >= OMAP_MAX_MCBSP_COUNT) { |
| 889 | .rx_irq = INT_730_McBSP2RX, | 822 | dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); |
| 890 | .tx_irq = INT_730_McBSP2TX }, | 823 | ret = -EINVAL; |
| 891 | }; | 824 | goto exit; |
| 892 | #endif | 825 | } |
| 893 | 826 | ||
| 894 | #ifdef CONFIG_ARCH_OMAP15XX | 827 | spin_lock_init(&mcbsp[id].lock); |
| 895 | static const struct omap_mcbsp_info mcbsp_1510[] = { | 828 | mcbsp[id].id = id + 1; |
| 896 | [0] = { .virt_base = OMAP1510_MCBSP1_BASE, | 829 | mcbsp[id].free = 1; |
| 897 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 830 | mcbsp[id].dma_tx_lch = -1; |
| 898 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 831 | mcbsp[id].dma_rx_lch = -1; |
| 899 | .rx_irq = INT_McBSP1RX, | 832 | |
| 900 | .tx_irq = INT_McBSP1TX }, | 833 | mcbsp[id].io_base = pdata->virt_base; |
| 901 | [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE), | 834 | /* Default I/O is IRQ based */ |
| 902 | .dma_rx_sync = OMAP_DMA_MCBSP2_RX, | 835 | mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; |
| 903 | .dma_tx_sync = OMAP_DMA_MCBSP2_TX, | 836 | mcbsp[id].tx_irq = pdata->tx_irq; |
| 904 | .rx_irq = INT_1510_SPI_RX, | 837 | mcbsp[id].rx_irq = pdata->rx_irq; |
| 905 | .tx_irq = INT_1510_SPI_TX }, | 838 | mcbsp[id].dma_rx_sync = pdata->dma_rx_sync; |
| 906 | [2] = { .virt_base = OMAP1510_MCBSP3_BASE, | 839 | mcbsp[id].dma_tx_sync = pdata->dma_tx_sync; |
| 907 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | 840 | |
| 908 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | 841 | if (pdata->clk_name) |
| 909 | .rx_irq = INT_McBSP3RX, | 842 | mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name); |
| 910 | .tx_irq = INT_McBSP3TX }, | 843 | if (IS_ERR(mcbsp[id].clk)) { |
| 911 | }; | 844 | mcbsp[id].free = 0; |
| 912 | #endif | 845 | dev_err(&pdev->dev, |
| 913 | 846 | "Invalid clock configuration for McBSP%d.\n", | |
| 914 | #if defined(CONFIG_ARCH_OMAP16XX) | 847 | mcbsp[id].id); |
| 915 | static const struct omap_mcbsp_info mcbsp_1610[] = { | 848 | ret = -EINVAL; |
| 916 | [0] = { .virt_base = OMAP1610_MCBSP1_BASE, | 849 | goto exit; |
| 917 | .dma_rx_sync = OMAP_DMA_MCBSP1_RX, | 850 | } |
| 918 | .dma_tx_sync = OMAP_DMA_MCBSP1_TX, | 851 | |
| 919 | .rx_irq = INT_McBSP1RX, | 852 | mcbsp[id].pdata = pdata; |
| 920 | .tx_irq = INT_McBSP1TX }, | 853 | mcbsp[id].dev = &pdev->dev; |
| 921 | [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE), | 854 | platform_set_drvdata(pdev, &mcbsp[id]); |
| 922 | .dma_rx_sync = OMAP_DMA_MCBSP2_RX, | 855 | |
| 923 | .dma_tx_sync = OMAP_DMA_MCBSP2_TX, | 856 | exit: |
| 924 | .rx_irq = INT_1610_McBSP2_RX, | 857 | return ret; |
| 925 | .tx_irq = INT_1610_McBSP2_TX }, | 858 | } |
| 926 | [2] = { .virt_base = OMAP1610_MCBSP3_BASE, | ||
| 927 | .dma_rx_sync = OMAP_DMA_MCBSP3_RX, | ||
| 928 | .dma_tx_sync = OMAP_DMA_MCBSP3_TX, | ||
| 929 | .rx_irq = INT_McBSP3RX, | ||
| 930 | .tx_irq = INT_McBSP3TX }, | ||
| 931 | }; | ||
| 932 | #endif | ||
| 933 | |||
| 934 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
| 935 | static const struct omap_mcbsp_info mcbsp_24xx[] = { | ||
| 936 | [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE), | ||
| 937 | .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, | ||
| 938 | .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, | ||
| 939 | .rx_irq = INT_24XX_MCBSP1_IRQ_RX, | ||
| 940 | .tx_irq = INT_24XX_MCBSP1_IRQ_TX, | ||
| 941 | }, | ||
| 942 | [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE), | ||
| 943 | .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, | ||
| 944 | .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, | ||
| 945 | .rx_irq = INT_24XX_MCBSP2_IRQ_RX, | ||
| 946 | .tx_irq = INT_24XX_MCBSP2_IRQ_TX, | ||
| 947 | }, | ||
| 948 | }; | ||
| 949 | #endif | ||
| 950 | 859 | ||
| 951 | static int __init omap_mcbsp_init(void) | 860 | static int omap_mcbsp_remove(struct platform_device *pdev) |
| 952 | { | 861 | { |
| 953 | int mcbsp_count = 0, i; | 862 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); |
| 954 | static const struct omap_mcbsp_info *mcbsp_info; | ||
| 955 | 863 | ||
| 956 | printk(KERN_INFO "Initializing OMAP McBSP system\n"); | 864 | platform_set_drvdata(pdev, NULL); |
| 865 | if (mcbsp) { | ||
| 957 | 866 | ||
| 958 | #ifdef CONFIG_ARCH_OMAP1 | 867 | if (mcbsp->pdata && mcbsp->pdata->ops && |
| 959 | mcbsp_dsp_ck = clk_get(0, "dsp_ck"); | 868 | mcbsp->pdata->ops->free) |
| 960 | if (IS_ERR(mcbsp_dsp_ck)) { | 869 | mcbsp->pdata->ops->free(mcbsp->id); |
| 961 | printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n"); | ||
| 962 | return PTR_ERR(mcbsp_dsp_ck); | ||
| 963 | } | ||
| 964 | mcbsp_api_ck = clk_get(0, "api_ck"); | ||
| 965 | if (IS_ERR(mcbsp_api_ck)) { | ||
| 966 | printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n"); | ||
| 967 | return PTR_ERR(mcbsp_api_ck); | ||
| 968 | } | ||
| 969 | mcbsp_dspxor_ck = clk_get(0, "dspxor_ck"); | ||
| 970 | if (IS_ERR(mcbsp_dspxor_ck)) { | ||
| 971 | printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n"); | ||
| 972 | return PTR_ERR(mcbsp_dspxor_ck); | ||
| 973 | } | ||
| 974 | #endif | ||
| 975 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 976 | mcbsp1_ick = clk_get(0, "mcbsp1_ick"); | ||
| 977 | if (IS_ERR(mcbsp1_ick)) { | ||
| 978 | printk(KERN_ERR "mcbsp: could not acquire " | ||
| 979 | "mcbsp1_ick handle.\n"); | ||
| 980 | return PTR_ERR(mcbsp1_ick); | ||
| 981 | } | ||
| 982 | mcbsp1_fck = clk_get(0, "mcbsp1_fck"); | ||
| 983 | if (IS_ERR(mcbsp1_fck)) { | ||
| 984 | printk(KERN_ERR "mcbsp: could not acquire " | ||
| 985 | "mcbsp1_fck handle.\n"); | ||
| 986 | return PTR_ERR(mcbsp1_fck); | ||
| 987 | } | ||
| 988 | mcbsp2_ick = clk_get(0, "mcbsp2_ick"); | ||
| 989 | if (IS_ERR(mcbsp2_ick)) { | ||
| 990 | printk(KERN_ERR "mcbsp: could not acquire " | ||
| 991 | "mcbsp2_ick handle.\n"); | ||
| 992 | return PTR_ERR(mcbsp2_ick); | ||
| 993 | } | ||
| 994 | mcbsp2_fck = clk_get(0, "mcbsp2_fck"); | ||
| 995 | if (IS_ERR(mcbsp2_fck)) { | ||
| 996 | printk(KERN_ERR "mcbsp: could not acquire " | ||
| 997 | "mcbsp2_fck handle.\n"); | ||
| 998 | return PTR_ERR(mcbsp2_fck); | ||
| 999 | } | ||
| 1000 | #endif | ||
| 1001 | 870 | ||
| 1002 | #ifdef CONFIG_ARCH_OMAP730 | 871 | clk_disable(mcbsp->clk); |
| 1003 | if (cpu_is_omap730()) { | 872 | clk_put(mcbsp->clk); |
| 1004 | mcbsp_info = mcbsp_730; | 873 | |
| 1005 | mcbsp_count = ARRAY_SIZE(mcbsp_730); | 874 | mcbsp->clk = NULL; |
| 1006 | } | 875 | mcbsp->free = 0; |
| 1007 | #endif | 876 | mcbsp->dev = NULL; |
| 1008 | #ifdef CONFIG_ARCH_OMAP15XX | ||
| 1009 | if (cpu_is_omap15xx()) { | ||
| 1010 | mcbsp_info = mcbsp_1510; | ||
| 1011 | mcbsp_count = ARRAY_SIZE(mcbsp_1510); | ||
| 1012 | } | ||
| 1013 | #endif | ||
| 1014 | #if defined(CONFIG_ARCH_OMAP16XX) | ||
| 1015 | if (cpu_is_omap16xx()) { | ||
| 1016 | mcbsp_info = mcbsp_1610; | ||
| 1017 | mcbsp_count = ARRAY_SIZE(mcbsp_1610); | ||
| 1018 | } | ||
| 1019 | #endif | ||
| 1020 | #if defined(CONFIG_ARCH_OMAP24XX) | ||
| 1021 | if (cpu_is_omap24xx()) { | ||
| 1022 | mcbsp_info = mcbsp_24xx; | ||
| 1023 | mcbsp_count = ARRAY_SIZE(mcbsp_24xx); | ||
| 1024 | omap2_mcbsp2_mux_setup(); | ||
| 1025 | } | ||
| 1026 | #endif | ||
| 1027 | for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) { | ||
| 1028 | if (i >= mcbsp_count) { | ||
| 1029 | mcbsp[i].io_base = 0; | ||
| 1030 | mcbsp[i].free = 0; | ||
| 1031 | continue; | ||
| 1032 | } | ||
| 1033 | mcbsp[i].id = i + 1; | ||
| 1034 | mcbsp[i].free = 1; | ||
| 1035 | mcbsp[i].dma_tx_lch = -1; | ||
| 1036 | mcbsp[i].dma_rx_lch = -1; | ||
| 1037 | |||
| 1038 | mcbsp[i].io_base = mcbsp_info[i].virt_base; | ||
| 1039 | /* Default I/O is IRQ based */ | ||
| 1040 | mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; | ||
| 1041 | mcbsp[i].tx_irq = mcbsp_info[i].tx_irq; | ||
| 1042 | mcbsp[i].rx_irq = mcbsp_info[i].rx_irq; | ||
| 1043 | mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync; | ||
| 1044 | mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync; | ||
| 1045 | spin_lock_init(&mcbsp[i].lock); | ||
| 1046 | } | 877 | } |
| 1047 | 878 | ||
| 1048 | return 0; | 879 | return 0; |
| 1049 | } | 880 | } |
| 1050 | 881 | ||
| 1051 | arch_initcall(omap_mcbsp_init); | 882 | static struct platform_driver omap_mcbsp_driver = { |
| 883 | .probe = omap_mcbsp_probe, | ||
| 884 | .remove = omap_mcbsp_remove, | ||
| 885 | .driver = { | ||
| 886 | .name = "omap-mcbsp", | ||
| 887 | }, | ||
| 888 | }; | ||
| 889 | |||
| 890 | int __init omap_mcbsp_init(void) | ||
| 891 | { | ||
| 892 | /* Register the McBSP driver */ | ||
| 893 | return platform_driver_register(&omap_mcbsp_driver); | ||
| 894 | } | ||
| 895 | |||
diff --git a/include/asm-arm/arch-omap/mcbsp.h b/include/asm-arm/arch-omap/mcbsp.h index c7a0cc1c4e93..26c78f67dc8e 100644 --- a/include/asm-arm/arch-omap/mcbsp.h +++ b/include/asm-arm/arch-omap/mcbsp.h | |||
| @@ -24,7 +24,11 @@ | |||
| 24 | #ifndef __ASM_ARCH_OMAP_MCBSP_H | 24 | #ifndef __ASM_ARCH_OMAP_MCBSP_H |
| 25 | #define __ASM_ARCH_OMAP_MCBSP_H | 25 | #define __ASM_ARCH_OMAP_MCBSP_H |
| 26 | 26 | ||
| 27 | #include <linux/completion.h> | ||
| 28 | #include <linux/spinlock.h> | ||
| 29 | |||
| 27 | #include <asm/hardware.h> | 30 | #include <asm/hardware.h> |
| 31 | #include <asm/arch/clock.h> | ||
| 28 | 32 | ||
| 29 | #define OMAP730_MCBSP1_BASE 0xfffb1000 | 33 | #define OMAP730_MCBSP1_BASE 0xfffb1000 |
| 30 | #define OMAP730_MCBSP2_BASE 0xfffb1800 | 34 | #define OMAP730_MCBSP2_BASE 0xfffb1800 |
| @@ -40,6 +44,9 @@ | |||
| 40 | #define OMAP24XX_MCBSP1_BASE 0x48074000 | 44 | #define OMAP24XX_MCBSP1_BASE 0x48074000 |
| 41 | #define OMAP24XX_MCBSP2_BASE 0x48076000 | 45 | #define OMAP24XX_MCBSP2_BASE 0x48076000 |
| 42 | 46 | ||
| 47 | #define OMAP34XX_MCBSP1_BASE 0x48074000 | ||
| 48 | #define OMAP34XX_MCBSP2_BASE 0x49022000 | ||
| 49 | |||
| 43 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) | 50 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) |
| 44 | 51 | ||
| 45 | #define OMAP_MCBSP_REG_DRR2 0x00 | 52 | #define OMAP_MCBSP_REG_DRR2 0x00 |
| @@ -74,7 +81,8 @@ | |||
| 74 | #define OMAP_MCBSP_REG_XCERG 0x3A | 81 | #define OMAP_MCBSP_REG_XCERG 0x3A |
| 75 | #define OMAP_MCBSP_REG_XCERH 0x3C | 82 | #define OMAP_MCBSP_REG_XCERH 0x3C |
| 76 | 83 | ||
| 77 | #define OMAP_MAX_MCBSP_COUNT 3 | 84 | #define OMAP_MAX_MCBSP_COUNT 3 |
| 85 | #define MAX_MCBSP_CLOCKS 3 | ||
| 78 | 86 | ||
| 79 | #define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1) | 87 | #define AUDIO_MCBSP_DATAWRITE (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1) |
| 80 | #define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1) | 88 | #define AUDIO_MCBSP_DATAREAD (OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1) |
| @@ -117,7 +125,8 @@ | |||
| 117 | #define OMAP_MCBSP_REG_XCERG 0x74 | 125 | #define OMAP_MCBSP_REG_XCERG 0x74 |
| 118 | #define OMAP_MCBSP_REG_XCERH 0x78 | 126 | #define OMAP_MCBSP_REG_XCERH 0x78 |
| 119 | 127 | ||
| 120 | #define OMAP_MAX_MCBSP_COUNT 2 | 128 | #define OMAP_MAX_MCBSP_COUNT 2 |
| 129 | #define MAX_MCBSP_CLOCKS 2 | ||
| 121 | 130 | ||
| 122 | #define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1) | 131 | #define AUDIO_MCBSP_DATAWRITE (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1) |
| 123 | #define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1) | 132 | #define AUDIO_MCBSP_DATAREAD (OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1) |
| @@ -298,6 +307,55 @@ struct omap_mcbsp_spi_cfg { | |||
| 298 | omap_mcbsp_word_length word_length; | 307 | omap_mcbsp_word_length word_length; |
| 299 | }; | 308 | }; |
| 300 | 309 | ||
| 310 | /* Platform specific configuration */ | ||
| 311 | struct omap_mcbsp_ops { | ||
| 312 | void (*request)(unsigned int); | ||
| 313 | void (*free)(unsigned int); | ||
| 314 | int (*check)(unsigned int); | ||
| 315 | }; | ||
| 316 | |||
| 317 | struct omap_mcbsp_platform_data { | ||
| 318 | u32 virt_base; | ||
| 319 | u8 dma_rx_sync, dma_tx_sync; | ||
| 320 | u16 rx_irq, tx_irq; | ||
| 321 | struct omap_mcbsp_ops *ops; | ||
| 322 | char const *clk_name; | ||
| 323 | }; | ||
| 324 | |||
| 325 | struct omap_mcbsp { | ||
| 326 | struct device *dev; | ||
| 327 | u32 io_base; | ||
| 328 | u8 id; | ||
| 329 | u8 free; | ||
| 330 | omap_mcbsp_word_length rx_word_length; | ||
| 331 | omap_mcbsp_word_length tx_word_length; | ||
| 332 | |||
| 333 | omap_mcbsp_io_type_t io_type; /* IRQ or poll */ | ||
| 334 | /* IRQ based TX/RX */ | ||
| 335 | int rx_irq; | ||
| 336 | int tx_irq; | ||
| 337 | |||
| 338 | /* DMA stuff */ | ||
| 339 | u8 dma_rx_sync; | ||
| 340 | short dma_rx_lch; | ||
| 341 | u8 dma_tx_sync; | ||
| 342 | short dma_tx_lch; | ||
| 343 | |||
| 344 | /* Completion queues */ | ||
| 345 | struct completion tx_irq_completion; | ||
| 346 | struct completion rx_irq_completion; | ||
| 347 | struct completion tx_dma_completion; | ||
| 348 | struct completion rx_dma_completion; | ||
| 349 | |||
| 350 | /* Protect the field .free, while checking if the mcbsp is in use */ | ||
| 351 | spinlock_t lock; | ||
| 352 | struct omap_mcbsp_platform_data *pdata; | ||
| 353 | struct clk *clk; | ||
| 354 | }; | ||
| 355 | |||
| 356 | int omap_mcbsp_init(void); | ||
| 357 | void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, | ||
| 358 | int size); | ||
| 301 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); | 359 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); |
| 302 | int omap_mcbsp_request(unsigned int id); | 360 | int omap_mcbsp_request(unsigned int id); |
| 303 | void omap_mcbsp_free(unsigned int id); | 361 | void omap_mcbsp_free(unsigned int id); |
