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