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 struct resource omap7xx_mcbsp_res[][6] = { 93 { 94 { 95 .start = OMAP7XX_MCBSP1_BASE, 96 .end = OMAP7XX_MCBSP1_BASE + SZ_256, 97 .flags = IORESOURCE_MEM, 98 }, 99 { 100 .name = "rx", 101 .start = INT_7XX_McBSP1RX, 102 .flags = IORESOURCE_IRQ, 103 }, 104 { 105 .name = "tx", 106 .start = INT_7XX_McBSP1TX, 107 .flags = IORESOURCE_IRQ, 108 }, 109 { 110 .name = "rx", 111 .start = 9, 112 .flags = IORESOURCE_DMA, 113 }, 114 { 115 .name = "tx", 116 .start = 8, 117 .flags = IORESOURCE_DMA, 118 }, 119 }, 120 { 121 { 122 .start = OMAP7XX_MCBSP2_BASE, 123 .end = OMAP7XX_MCBSP2_BASE + SZ_256, 124 .flags = IORESOURCE_MEM, 125 }, 126 { 127 .name = "rx", 128 .start = INT_7XX_McBSP2RX, 129 .flags = IORESOURCE_IRQ, 130 }, 131 { 132 .name = "tx", 133 .start = INT_7XX_McBSP2TX, 134 .flags = IORESOURCE_IRQ, 135 }, 136 { 137 .name = "rx", 138 .start = 11, 139 .flags = IORESOURCE_DMA, 140 }, 141 { 142 .name = "tx", 143 .start = 10, 144 .flags = IORESOURCE_DMA, 145 }, 146 }, 147 }; 148 149 #define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0] 150 151 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = { 152 { 153 .ops = &omap1_mcbsp_ops, 154 }, 155 { 156 .ops = &omap1_mcbsp_ops, 157 }, 158 }; 159 #define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1]) 160 #define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res) 161 162 struct resource omap15xx_mcbsp_res[][6] = { 163 { 164 { 165 .start = OMAP1510_MCBSP1_BASE, 166 .end = OMAP1510_MCBSP1_BASE + SZ_256, 167 .flags = IORESOURCE_MEM, 168 }, 169 { 170 .name = "rx", 171 .start = INT_McBSP1RX, 172 .flags = IORESOURCE_IRQ, 173 }, 174 { 175 .name = "tx", 176 .start = INT_McBSP1TX, 177 .flags = IORESOURCE_IRQ, 178 }, 179 { 180 .name = "rx", 181 .start = 9, 182 .flags = IORESOURCE_DMA, 183 }, 184 { 185 .name = "tx", 186 .start = 8, 187 .flags = IORESOURCE_DMA, 188 }, 189 }, 190 { 191 { 192 .start = OMAP1510_MCBSP2_BASE, 193 .end = OMAP1510_MCBSP2_BASE + SZ_256, 194 .flags = IORESOURCE_MEM, 195 }, 196 { 197 .name = "rx", 198 .start = INT_1510_SPI_RX, 199 .flags = IORESOURCE_IRQ, 200 }, 201 { 202 .name = "tx", 203 .start = INT_1510_SPI_TX, 204 .flags = IORESOURCE_IRQ, 205 }, 206 { 207 .name = "rx", 208 .start = 17, 209 .flags = IORESOURCE_DMA, 210 }, 211 { 212 .name = "tx", 213 .start = 16, 214 .flags = IORESOURCE_DMA, 215 }, 216 }, 217 { 218 { 219 .start = OMAP1510_MCBSP3_BASE, 220 .end = OMAP1510_MCBSP3_BASE + SZ_256, 221 .flags = IORESOURCE_MEM, 222 }, 223 { 224 .name = "rx", 225 .start = INT_McBSP3RX, 226 .flags = IORESOURCE_IRQ, 227 }, 228 { 229 .name = "tx", 230 .start = INT_McBSP3TX, 231 .flags = IORESOURCE_IRQ, 232 }, 233 { 234 .name = "rx", 235 .start = 11, 236 .flags = IORESOURCE_DMA, 237 }, 238 { 239 .name = "tx", 240 .start = 10, 241 .flags = IORESOURCE_DMA, 242 }, 243 }, 244 }; 245 246 #define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0] 247 248 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { 249 { 250 .ops = &omap1_mcbsp_ops, 251 }, 252 { 253 .ops = &omap1_mcbsp_ops, 254 }, 255 { 256 .ops = &omap1_mcbsp_ops, 257 }, 258 }; 259 #define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1]) 260 #define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res) 261 262 struct resource omap16xx_mcbsp_res[][6] = { 263 { 264 { 265 .start = OMAP1610_MCBSP1_BASE, 266 .end = OMAP1610_MCBSP1_BASE + SZ_256, 267 .flags = IORESOURCE_MEM, 268 }, 269 { 270 .name = "rx", 271 .start = INT_McBSP1RX, 272 .flags = IORESOURCE_IRQ, 273 }, 274 { 275 .name = "tx", 276 .start = INT_McBSP1TX, 277 .flags = IORESOURCE_IRQ, 278 }, 279 { 280 .name = "rx", 281 .start = 9, 282 .flags = IORESOURCE_DMA, 283 }, 284 { 285 .name = "tx", 286 .start = 8, 287 .flags = IORESOURCE_DMA, 288 }, 289 }, 290 { 291 { 292 .start = OMAP1610_MCBSP2_BASE, 293 .end = OMAP1610_MCBSP2_BASE + SZ_256, 294 .flags = IORESOURCE_MEM, 295 }, 296 { 297 .name = "rx", 298 .start = INT_1610_McBSP2_RX, 299 .flags = IORESOURCE_IRQ, 300 }, 301 { 302 .name = "tx", 303 .start = INT_1610_McBSP2_TX, 304 .flags = IORESOURCE_IRQ, 305 }, 306 { 307 .name = "rx", 308 .start = 17, 309 .flags = IORESOURCE_DMA, 310 }, 311 { 312 .name = "tx", 313 .start = 16, 314 .flags = IORESOURCE_DMA, 315 }, 316 }, 317 { 318 { 319 .start = OMAP1610_MCBSP3_BASE, 320 .end = OMAP1610_MCBSP3_BASE + SZ_256, 321 .flags = IORESOURCE_MEM, 322 }, 323 { 324 .name = "rx", 325 .start = INT_McBSP3RX, 326 .flags = IORESOURCE_IRQ, 327 }, 328 { 329 .name = "tx", 330 .start = INT_McBSP3TX, 331 .flags = IORESOURCE_IRQ, 332 }, 333 { 334 .name = "rx", 335 .start = 11, 336 .flags = IORESOURCE_DMA, 337 }, 338 { 339 .name = "tx", 340 .start = 10, 341 .flags = IORESOURCE_DMA, 342 }, 343 }, 344 }; 345 346 #define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0] 347 348 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { 349 { 350 .ops = &omap1_mcbsp_ops, 351 }, 352 { 353 .ops = &omap1_mcbsp_ops, 354 }, 355 { 356 .ops = &omap1_mcbsp_ops, 357 }, 358 }; 359 #define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1]) 360 #define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res) 361 362 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, 363 struct omap_mcbsp_platform_data *config, int size) 364 { 365 int i; 366 367 omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *), 368 GFP_KERNEL); 369 if (!omap_mcbsp_devices) { 370 printk(KERN_ERR "Could not register McBSP devices\n"); 371 return; 372 } 373 374 for (i = 0; i < size; i++) { 375 struct platform_device *new_mcbsp; 376 int ret; 377 378 new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1); 379 if (!new_mcbsp) 380 continue; 381 platform_device_add_resources(new_mcbsp, &res[i * res_count], 382 res_count); 383 config[i].reg_size = 2; 384 config[i].reg_step = 2; 385 new_mcbsp->dev.platform_data = &config[i]; 386 ret = platform_device_add(new_mcbsp); 387 if (ret) { 388 platform_device_put(new_mcbsp); 389 continue; 390 } 391 omap_mcbsp_devices[i] = new_mcbsp; 392 } 393 } 394 395 static int __init omap1_mcbsp_init(void) 396 { 397 if (!cpu_class_is_omap1()) 398 return -ENODEV; 399 400 if (cpu_is_omap7xx()) 401 omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0, 402 OMAP7XX_MCBSP_RES_SZ, 403 omap7xx_mcbsp_pdata, 404 OMAP7XX_MCBSP_COUNT); 405 406 if (cpu_is_omap15xx()) 407 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0, 408 OMAP15XX_MCBSP_RES_SZ, 409 omap15xx_mcbsp_pdata, 410 OMAP15XX_MCBSP_COUNT); 411 412 if (cpu_is_omap16xx()) 413 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0, 414 OMAP16XX_MCBSP_RES_SZ, 415 omap16xx_mcbsp_pdata, 416 OMAP16XX_MCBSP_COUNT); 417 418 return 0; 419 } 420 421 arch_initcall(omap1_mcbsp_init); 422