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