1 /* 2 * linux/arch/arm/mach-omap2/mcbsp.c 3 * 4 * Copyright (C) 2008 Instituto Nokia de Tecnologia 5 * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Multichannel mode not supported. 12 */ 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/clk.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 #include <linux/platform_device.h> 19 #include <linux/slab.h> 20 21 #include <mach/irqs.h> 22 #include <plat/dma.h> 23 #include <plat/cpu.h> 24 #include <plat/mcbsp.h> 25 26 #include "control.h" 27 28 29 /* McBSP internal signal muxing functions */ 30 31 void omap2_mcbsp1_mux_clkr_src(u8 mux) 32 { 33 u32 v; 34 35 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 36 if (mux == CLKR_SRC_CLKR) 37 v &= OMAP2_MCBSP1_CLKR_MASK; 38 else if (mux == CLKR_SRC_CLKX) 39 v |= OMAP2_MCBSP1_CLKR_MASK; 40 omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); 41 } 42 EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src); 43 44 void omap2_mcbsp1_mux_fsr_src(u8 mux) 45 { 46 u32 v; 47 48 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 49 if (mux == FSR_SRC_FSR) 50 v &= OMAP2_MCBSP1_FSR_MASK; 51 else if (mux == FSR_SRC_FSX) 52 v |= OMAP2_MCBSP1_FSR_MASK; 53 omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); 54 } 55 EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src); 56 57 /* McBSP CLKS source switching function */ 58 59 int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) 60 { 61 struct omap_mcbsp *mcbsp; 62 struct clk *fck_src; 63 char *fck_src_name; 64 int r; 65 66 if (!omap_mcbsp_check_valid_id(id)) { 67 pr_err("%s: Invalid id (%d)\n", __func__, id + 1); 68 return -EINVAL; 69 } 70 mcbsp = id_to_mcbsp_ptr(id); 71 72 if (fck_src_id == MCBSP_CLKS_PAD_SRC) 73 fck_src_name = "pad_fck"; 74 else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) 75 fck_src_name = "prcm_fck"; 76 else 77 return -EINVAL; 78 79 fck_src = clk_get(mcbsp->dev, fck_src_name); 80 if (IS_ERR_OR_NULL(fck_src)) { 81 pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks", 82 fck_src_name); 83 return -EINVAL; 84 } 85 86 clk_disable(mcbsp->fclk); 87 88 r = clk_set_parent(mcbsp->fclk, fck_src); 89 if (IS_ERR_VALUE(r)) { 90 pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n", 91 "clks", fck_src_name); 92 clk_put(fck_src); 93 return -EINVAL; 94 } 95 96 clk_enable(mcbsp->fclk); 97 98 clk_put(fck_src); 99 100 return 0; 101 } 102 EXPORT_SYMBOL(omap2_mcbsp_set_clks_src); 103 104 105 /* Platform data */ 106 107 #ifdef CONFIG_ARCH_OMAP2420 108 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { 109 { 110 .phys_base = OMAP24XX_MCBSP1_BASE, 111 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 112 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 113 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 114 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 115 }, 116 { 117 .phys_base = OMAP24XX_MCBSP2_BASE, 118 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 119 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 120 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 121 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 122 }, 123 }; 124 #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) 125 #define OMAP2420_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1) 126 #else 127 #define omap2420_mcbsp_pdata NULL 128 #define OMAP2420_MCBSP_PDATA_SZ 0 129 #define OMAP2420_MCBSP_REG_NUM 0 130 #endif 131 132 #ifdef CONFIG_ARCH_OMAP2430 133 static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { 134 { 135 .phys_base = OMAP24XX_MCBSP1_BASE, 136 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 137 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 138 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 139 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 140 }, 141 { 142 .phys_base = OMAP24XX_MCBSP2_BASE, 143 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 144 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 145 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 146 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 147 }, 148 { 149 .phys_base = OMAP2430_MCBSP3_BASE, 150 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX, 151 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX, 152 .rx_irq = INT_24XX_MCBSP3_IRQ_RX, 153 .tx_irq = INT_24XX_MCBSP3_IRQ_TX, 154 }, 155 { 156 .phys_base = OMAP2430_MCBSP4_BASE, 157 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX, 158 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX, 159 .rx_irq = INT_24XX_MCBSP4_IRQ_RX, 160 .tx_irq = INT_24XX_MCBSP4_IRQ_TX, 161 }, 162 { 163 .phys_base = OMAP2430_MCBSP5_BASE, 164 .dma_rx_sync = OMAP24XX_DMA_MCBSP5_RX, 165 .dma_tx_sync = OMAP24XX_DMA_MCBSP5_TX, 166 .rx_irq = INT_24XX_MCBSP5_IRQ_RX, 167 .tx_irq = INT_24XX_MCBSP5_IRQ_TX, 168 }, 169 }; 170 #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) 171 #define OMAP2430_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1) 172 #else 173 #define omap2430_mcbsp_pdata NULL 174 #define OMAP2430_MCBSP_PDATA_SZ 0 175 #define OMAP2430_MCBSP_REG_NUM 0 176 #endif 177 178 #ifdef CONFIG_ARCH_OMAP3 179 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { 180 { 181 .phys_base = OMAP34XX_MCBSP1_BASE, 182 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 183 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 184 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 185 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 186 .buffer_size = 0x80, /* The FIFO has 128 locations */ 187 }, 188 { 189 .phys_base = OMAP34XX_MCBSP2_BASE, 190 .phys_base_st = OMAP34XX_MCBSP2_ST_BASE, 191 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 192 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 193 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 194 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 195 .buffer_size = 0x500, /* The FIFO has 1024 + 256 locations */ 196 }, 197 { 198 .phys_base = OMAP34XX_MCBSP3_BASE, 199 .phys_base_st = OMAP34XX_MCBSP3_ST_BASE, 200 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX, 201 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX, 202 .rx_irq = INT_24XX_MCBSP3_IRQ_RX, 203 .tx_irq = INT_24XX_MCBSP3_IRQ_TX, 204 .buffer_size = 0x80, /* The FIFO has 128 locations */ 205 }, 206 { 207 .phys_base = OMAP34XX_MCBSP4_BASE, 208 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX, 209 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX, 210 .rx_irq = INT_24XX_MCBSP4_IRQ_RX, 211 .tx_irq = INT_24XX_MCBSP4_IRQ_TX, 212 .buffer_size = 0x80, /* The FIFO has 128 locations */ 213 }, 214 { 215 .phys_base = OMAP34XX_MCBSP5_BASE, 216 .dma_rx_sync = OMAP24XX_DMA_MCBSP5_RX, 217 .dma_tx_sync = OMAP24XX_DMA_MCBSP5_TX, 218 .rx_irq = INT_24XX_MCBSP5_IRQ_RX, 219 .tx_irq = INT_24XX_MCBSP5_IRQ_TX, 220 .buffer_size = 0x80, /* The FIFO has 128 locations */ 221 }, 222 }; 223 #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) 224 #define OMAP34XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1) 225 #else 226 #define omap34xx_mcbsp_pdata NULL 227 #define OMAP34XX_MCBSP_PDATA_SZ 0 228 #define OMAP34XX_MCBSP_REG_NUM 0 229 #endif 230 231 static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = { 232 { 233 .phys_base = OMAP44XX_MCBSP1_BASE, 234 .dma_rx_sync = OMAP44XX_DMA_MCBSP1_RX, 235 .dma_tx_sync = OMAP44XX_DMA_MCBSP1_TX, 236 .tx_irq = OMAP44XX_IRQ_MCBSP1, 237 }, 238 { 239 .phys_base = OMAP44XX_MCBSP2_BASE, 240 .dma_rx_sync = OMAP44XX_DMA_MCBSP2_RX, 241 .dma_tx_sync = OMAP44XX_DMA_MCBSP2_TX, 242 .tx_irq = OMAP44XX_IRQ_MCBSP2, 243 /* XXX .ops ? */ 244 }, 245 { 246 .phys_base = OMAP44XX_MCBSP3_BASE, 247 .dma_rx_sync = OMAP44XX_DMA_MCBSP3_RX, 248 .dma_tx_sync = OMAP44XX_DMA_MCBSP3_TX, 249 .tx_irq = OMAP44XX_IRQ_MCBSP3, 250 /* XXX .ops ? */ 251 }, 252 { 253 .phys_base = OMAP44XX_MCBSP4_BASE, 254 .dma_rx_sync = OMAP44XX_DMA_MCBSP4_RX, 255 .dma_tx_sync = OMAP44XX_DMA_MCBSP4_TX, 256 .tx_irq = OMAP44XX_IRQ_MCBSP4, 257 /* XXX .ops ? */ 258 }, 259 }; 260 #define OMAP44XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap44xx_mcbsp_pdata) 261 #define OMAP44XX_MCBSP_REG_NUM (OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1) 262 263 static int __init omap2_mcbsp_init(void) 264 { 265 if (cpu_is_omap2420()) { 266 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; 267 omap_mcbsp_cache_size = OMAP2420_MCBSP_REG_NUM * sizeof(u16); 268 } else if (cpu_is_omap2430()) { 269 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ; 270 omap_mcbsp_cache_size = OMAP2430_MCBSP_REG_NUM * sizeof(u32); 271 } else if (cpu_is_omap34xx()) { 272 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ; 273 omap_mcbsp_cache_size = OMAP34XX_MCBSP_REG_NUM * sizeof(u32); 274 } else if (cpu_is_omap44xx()) { 275 omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ; 276 omap_mcbsp_cache_size = OMAP44XX_MCBSP_REG_NUM * sizeof(u32); 277 } 278 279 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), 280 GFP_KERNEL); 281 if (!mcbsp_ptr) 282 return -ENOMEM; 283 284 if (cpu_is_omap2420()) 285 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata, 286 OMAP2420_MCBSP_PDATA_SZ); 287 if (cpu_is_omap2430()) 288 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata, 289 OMAP2430_MCBSP_PDATA_SZ); 290 if (cpu_is_omap34xx()) 291 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata, 292 OMAP34XX_MCBSP_PDATA_SZ); 293 if (cpu_is_omap44xx()) 294 omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata, 295 OMAP44XX_MCBSP_PDATA_SZ); 296 297 return omap_mcbsp_init(); 298 } 299 arch_initcall(omap2_mcbsp_init); 300