1 /* 2 * linux/arch/arm/mach-omap1/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/ioport.h> 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/clk.h> 17 #include <linux/err.h> 18 #include <linux/io.h> 19 #include <linux/platform_device.h> 20 #include <linux/slab.h> 21 22 #include <linux/omap-dma.h> 23 #include <mach/mux.h> 24 #include "soc.h" 25 #include <linux/platform_data/asoc-ti-mcbsp.h> 26 27 #include <mach/irqs.h> 28 29 #include "iomap.h" 30 #include "dma.h" 31 32 #define DPS_RSTCT2_PER_EN (1 << 0) 33 #define DSP_RSTCT2_WD_PER_EN (1 << 1) 34 35 static int dsp_use; 36 static struct clk *api_clk; 37 static struct clk *dsp_clk; 38 static struct platform_device **omap_mcbsp_devices; 39 40 static void omap1_mcbsp_request(unsigned int id) 41 { 42 /* 43 * On 1510, 1610 and 1710, McBSP1 and McBSP3 44 * are DSP public peripherals. 45 */ 46 if (id == 0 || id == 2) { 47 if (dsp_use++ == 0) { 48 api_clk = clk_get(NULL, "api_ck"); 49 dsp_clk = clk_get(NULL, "dsp_ck"); 50 if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) { 51 clk_enable(api_clk); 52 clk_enable(dsp_clk); 53 54 /* 55 * DSP external peripheral reset 56 * FIXME: This should be moved to dsp code 57 */ 58 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN | 59 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2); 60 } 61 } 62 } 63 } 64 65 static void omap1_mcbsp_free(unsigned int id) 66 { 67 if (id == 0 || id == 2) { 68 if (--dsp_use == 0) { 69 if (!IS_ERR(api_clk)) { 70 clk_disable(api_clk); 71 clk_put(api_clk); 72 } 73 if (!IS_ERR(dsp_clk)) { 74 clk_disable(dsp_clk); 75 clk_put(dsp_clk); 76 } 77 } 78 } 79 } 80 81 static struct omap_mcbsp_ops omap1_mcbsp_ops = { 82 .request = omap1_mcbsp_request, 83 .free = omap1_mcbsp_free, 84 }; 85 86 #define OMAP7XX_MCBSP1_BASE 0xfffb1000 87 #define OMAP7XX_MCBSP2_BASE 0xfffb1800 88 89 #define OMAP1510_MCBSP1_BASE 0xe1011800 90 #define OMAP1510_MCBSP2_BASE 0xfffb1000 91 #define OMAP1510_MCBSP3_BASE 0xe1017000 92 93 #define OMAP1610_MCBSP1_BASE 0xe1011800 94 #define OMAP1610_MCBSP2_BASE 0xfffb1000 95 #define OMAP1610_MCBSP3_BASE 0xe1017000 96 97 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) 98 struct resource omap7xx_mcbsp_res[][6] = { 99 { 100 { 101 .start = OMAP7XX_MCBSP1_BASE, 102 .end = OMAP7XX_MCBSP1_BASE + SZ_256, 103 .flags = IORESOURCE_MEM, 104 }, 105 { 106 .name = "rx", 107 .start = INT_7XX_McBSP1RX, 108 .flags = IORESOURCE_IRQ, 109 }, 110 { 111 .name = "tx", 112 .start = INT_7XX_McBSP1TX, 113 .flags = IORESOURCE_IRQ, 114 }, 115 { 116 .name = "rx", 117 .start = OMAP_DMA_MCBSP1_RX, 118 .flags = IORESOURCE_DMA, 119 }, 120 { 121 .name = "tx", 122 .start = OMAP_DMA_MCBSP1_TX, 123 .flags = IORESOURCE_DMA, 124 }, 125 }, 126 { 127 { 128 .start = OMAP7XX_MCBSP2_BASE, 129 .end = OMAP7XX_MCBSP2_BASE + SZ_256, 130 .flags = IORESOURCE_MEM, 131 }, 132 { 133 .name = "rx", 134 .start = INT_7XX_McBSP2RX, 135 .flags = IORESOURCE_IRQ, 136 }, 137 { 138 .name = "tx", 139 .start = INT_7XX_McBSP2TX, 140 .flags = IORESOURCE_IRQ, 141 }, 142 { 143 .name = "rx", 144 .start = OMAP_DMA_MCBSP3_RX, 145 .flags = IORESOURCE_DMA, 146 }, 147 { 148 .name = "tx", 149 .start = OMAP_DMA_MCBSP3_TX, 150 .flags = IORESOURCE_DMA, 151 }, 152 }, 153 }; 154 155 #define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0] 156 157 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = { 158 { 159 .ops = &omap1_mcbsp_ops, 160 }, 161 { 162 .ops = &omap1_mcbsp_ops, 163 }, 164 }; 165 #define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1]) 166 #define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res) 167 #else 168 #define omap7xx_mcbsp_res_0 NULL 169 #define omap7xx_mcbsp_pdata NULL 170 #define OMAP7XX_MCBSP_RES_SZ 0 171 #define OMAP7XX_MCBSP_COUNT 0 172 #endif 173 174 #ifdef CONFIG_ARCH_OMAP15XX 175 struct resource omap15xx_mcbsp_res[][6] = { 176 { 177 { 178 .start = OMAP1510_MCBSP1_BASE, 179 .end = OMAP1510_MCBSP1_BASE + SZ_256, 180 .flags = IORESOURCE_MEM, 181 }, 182 { 183 .name = "rx", 184 .start = INT_McBSP1RX, 185 .flags = IORESOURCE_IRQ, 186 }, 187 { 188 .name = "tx", 189 .start = INT_McBSP1TX, 190 .flags = IORESOURCE_IRQ, 191 }, 192 { 193 .name = "rx", 194 .start = OMAP_DMA_MCBSP1_RX, 195 .flags = IORESOURCE_DMA, 196 }, 197 { 198 .name = "tx", 199 .start = OMAP_DMA_MCBSP1_TX, 200 .flags = IORESOURCE_DMA, 201 }, 202 }, 203 { 204 { 205 .start = OMAP1510_MCBSP2_BASE, 206 .end = OMAP1510_MCBSP2_BASE + SZ_256, 207 .flags = IORESOURCE_MEM, 208 }, 209 { 210 .name = "rx", 211 .start = INT_1510_SPI_RX, 212 .flags = IORESOURCE_IRQ, 213 }, 214 { 215 .name = "tx", 216 .start = INT_1510_SPI_TX, 217 .flags = IORESOURCE_IRQ, 218 }, 219 { 220 .name = "rx", 221 .start = OMAP_DMA_MCBSP2_RX, 222 .flags = IORESOURCE_DMA, 223 }, 224 { 225 .name = "tx", 226 .start = OMAP_DMA_MCBSP2_TX, 227 .flags = IORESOURCE_DMA, 228 }, 229 }, 230 { 231 { 232 .start = OMAP1510_MCBSP3_BASE, 233 .end = OMAP1510_MCBSP3_BASE + SZ_256, 234 .flags = IORESOURCE_MEM, 235 }, 236 { 237 .name = "rx", 238 .start = INT_McBSP3RX, 239 .flags = IORESOURCE_IRQ, 240 }, 241 { 242 .name = "tx", 243 .start = INT_McBSP3TX, 244 .flags = IORESOURCE_IRQ, 245 }, 246 { 247 .name = "rx", 248 .start = OMAP_DMA_MCBSP3_RX, 249 .flags = IORESOURCE_DMA, 250 }, 251 { 252 .name = "tx", 253 .start = OMAP_DMA_MCBSP3_TX, 254 .flags = IORESOURCE_DMA, 255 }, 256 }, 257 }; 258 259 #define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0] 260 261 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { 262 { 263 .ops = &omap1_mcbsp_ops, 264 }, 265 { 266 .ops = &omap1_mcbsp_ops, 267 }, 268 { 269 .ops = &omap1_mcbsp_ops, 270 }, 271 }; 272 #define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1]) 273 #define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res) 274 #else 275 #define omap15xx_mcbsp_res_0 NULL 276 #define omap15xx_mcbsp_pdata NULL 277 #define OMAP15XX_MCBSP_RES_SZ 0 278 #define OMAP15XX_MCBSP_COUNT 0 279 #endif 280 281 #ifdef CONFIG_ARCH_OMAP16XX 282 struct resource omap16xx_mcbsp_res[][6] = { 283 { 284 { 285 .start = OMAP1610_MCBSP1_BASE, 286 .end = OMAP1610_MCBSP1_BASE + SZ_256, 287 .flags = IORESOURCE_MEM, 288 }, 289 { 290 .name = "rx", 291 .start = INT_McBSP1RX, 292 .flags = IORESOURCE_IRQ, 293 }, 294 { 295 .name = "tx", 296 .start = INT_McBSP1TX, 297 .flags = IORESOURCE_IRQ, 298 }, 299 { 300 .name = "rx", 301 .start = OMAP_DMA_MCBSP1_RX, 302 .flags = IORESOURCE_DMA, 303 }, 304 { 305 .name = "tx", 306 .start = OMAP_DMA_MCBSP1_TX, 307 .flags = IORESOURCE_DMA, 308 }, 309 }, 310 { 311 { 312 .start = OMAP1610_MCBSP2_BASE, 313 .end = OMAP1610_MCBSP2_BASE + SZ_256, 314 .flags = IORESOURCE_MEM, 315 }, 316 { 317 .name = "rx", 318 .start = INT_1610_McBSP2_RX, 319 .flags = IORESOURCE_IRQ, 320 }, 321 { 322 .name = "tx", 323 .start = INT_1610_McBSP2_TX, 324 .flags = IORESOURCE_IRQ, 325 }, 326 { 327 .name = "rx", 328 .start = OMAP_DMA_MCBSP2_RX, 329 .flags = IORESOURCE_DMA, 330 }, 331 { 332 .name = "tx", 333 .start = OMAP_DMA_MCBSP2_TX, 334 .flags = IORESOURCE_DMA, 335 }, 336 }, 337 { 338 { 339 .start = OMAP1610_MCBSP3_BASE, 340 .end = OMAP1610_MCBSP3_BASE + SZ_256, 341 .flags = IORESOURCE_MEM, 342 }, 343 { 344 .name = "rx", 345 .start = INT_McBSP3RX, 346 .flags = IORESOURCE_IRQ, 347 }, 348 { 349 .name = "tx", 350 .start = INT_McBSP3TX, 351 .flags = IORESOURCE_IRQ, 352 }, 353 { 354 .name = "rx", 355 .start = OMAP_DMA_MCBSP3_RX, 356 .flags = IORESOURCE_DMA, 357 }, 358 { 359 .name = "tx", 360 .start = OMAP_DMA_MCBSP3_TX, 361 .flags = IORESOURCE_DMA, 362 }, 363 }, 364 }; 365 366 #define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0] 367 368 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { 369 { 370 .ops = &omap1_mcbsp_ops, 371 }, 372 { 373 .ops = &omap1_mcbsp_ops, 374 }, 375 { 376 .ops = &omap1_mcbsp_ops, 377 }, 378 }; 379 #define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1]) 380 #define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res) 381 #else 382 #define omap16xx_mcbsp_res_0 NULL 383 #define omap16xx_mcbsp_pdata NULL 384 #define OMAP16XX_MCBSP_RES_SZ 0 385 #define OMAP16XX_MCBSP_COUNT 0 386 #endif 387 388 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, 389 struct omap_mcbsp_platform_data *config, int size) 390 { 391 int i; 392 393 omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *), 394 GFP_KERNEL); 395 if (!omap_mcbsp_devices) { 396 printk(KERN_ERR "Could not register McBSP devices\n"); 397 return; 398 } 399 400 for (i = 0; i < size; i++) { 401 struct platform_device *new_mcbsp; 402 int ret; 403 404 new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1); 405 if (!new_mcbsp) 406 continue; 407 platform_device_add_resources(new_mcbsp, &res[i * res_count], 408 res_count); 409 config[i].reg_size = 2; 410 config[i].reg_step = 2; 411 new_mcbsp->dev.platform_data = &config[i]; 412 ret = platform_device_add(new_mcbsp); 413 if (ret) { 414 platform_device_put(new_mcbsp); 415 continue; 416 } 417 omap_mcbsp_devices[i] = new_mcbsp; 418 } 419 } 420 421 static int __init omap1_mcbsp_init(void) 422 { 423 if (!cpu_class_is_omap1()) 424 return -ENODEV; 425 426 if (cpu_is_omap7xx()) 427 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0, 428 OMAP7XX_MCBSP_RES_SZ, 429 omap7xx_mcbsp_pdata, 430 OMAP7XX_MCBSP_COUNT); 431 432 if (cpu_is_omap15xx()) 433 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0, 434 OMAP15XX_MCBSP_RES_SZ, 435 omap15xx_mcbsp_pdata, 436 OMAP15XX_MCBSP_COUNT); 437 438 if (cpu_is_omap16xx()) 439 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0, 440 OMAP16XX_MCBSP_RES_SZ, 441 omap16xx_mcbsp_pdata, 442 OMAP16XX_MCBSP_COUNT); 443 444 return 0; 445 } 446 447 arch_initcall(omap1_mcbsp_init); 448