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 omap15xx_mcbsp_res[][6] = { 93 { 94 { 95 .start = OMAP1510_MCBSP1_BASE, 96 .end = OMAP1510_MCBSP1_BASE + SZ_256, 97 .flags = IORESOURCE_MEM, 98 }, 99 { 100 .name = "rx", 101 .start = INT_McBSP1RX, 102 .flags = IORESOURCE_IRQ, 103 }, 104 { 105 .name = "tx", 106 .start = INT_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 = OMAP1510_MCBSP2_BASE, 123 .end = OMAP1510_MCBSP2_BASE + SZ_256, 124 .flags = IORESOURCE_MEM, 125 }, 126 { 127 .name = "rx", 128 .start = INT_1510_SPI_RX, 129 .flags = IORESOURCE_IRQ, 130 }, 131 { 132 .name = "tx", 133 .start = INT_1510_SPI_TX, 134 .flags = IORESOURCE_IRQ, 135 }, 136 { 137 .name = "rx", 138 .start = 17, 139 .flags = IORESOURCE_DMA, 140 }, 141 { 142 .name = "tx", 143 .start = 16, 144 .flags = IORESOURCE_DMA, 145 }, 146 }, 147 { 148 { 149 .start = OMAP1510_MCBSP3_BASE, 150 .end = OMAP1510_MCBSP3_BASE + SZ_256, 151 .flags = IORESOURCE_MEM, 152 }, 153 { 154 .name = "rx", 155 .start = INT_McBSP3RX, 156 .flags = IORESOURCE_IRQ, 157 }, 158 { 159 .name = "tx", 160 .start = INT_McBSP3TX, 161 .flags = IORESOURCE_IRQ, 162 }, 163 { 164 .name = "rx", 165 .start = 11, 166 .flags = IORESOURCE_DMA, 167 }, 168 { 169 .name = "tx", 170 .start = 10, 171 .flags = IORESOURCE_DMA, 172 }, 173 }, 174 }; 175 176 #define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0] 177 178 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { 179 { 180 .ops = &omap1_mcbsp_ops, 181 }, 182 { 183 .ops = &omap1_mcbsp_ops, 184 }, 185 { 186 .ops = &omap1_mcbsp_ops, 187 }, 188 }; 189 #define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1]) 190 #define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res) 191 192 struct resource omap16xx_mcbsp_res[][6] = { 193 { 194 { 195 .start = OMAP1610_MCBSP1_BASE, 196 .end = OMAP1610_MCBSP1_BASE + SZ_256, 197 .flags = IORESOURCE_MEM, 198 }, 199 { 200 .name = "rx", 201 .start = INT_McBSP1RX, 202 .flags = IORESOURCE_IRQ, 203 }, 204 { 205 .name = "tx", 206 .start = INT_McBSP1TX, 207 .flags = IORESOURCE_IRQ, 208 }, 209 { 210 .name = "rx", 211 .start = 9, 212 .flags = IORESOURCE_DMA, 213 }, 214 { 215 .name = "tx", 216 .start = 8, 217 .flags = IORESOURCE_DMA, 218 }, 219 }, 220 { 221 { 222 .start = OMAP1610_MCBSP2_BASE, 223 .end = OMAP1610_MCBSP2_BASE + SZ_256, 224 .flags = IORESOURCE_MEM, 225 }, 226 { 227 .name = "rx", 228 .start = INT_1610_McBSP2_RX, 229 .flags = IORESOURCE_IRQ, 230 }, 231 { 232 .name = "tx", 233 .start = INT_1610_McBSP2_TX, 234 .flags = IORESOURCE_IRQ, 235 }, 236 { 237 .name = "rx", 238 .start = 17, 239 .flags = IORESOURCE_DMA, 240 }, 241 { 242 .name = "tx", 243 .start = 16, 244 .flags = IORESOURCE_DMA, 245 }, 246 }, 247 { 248 { 249 .start = OMAP1610_MCBSP3_BASE, 250 .end = OMAP1610_MCBSP3_BASE + SZ_256, 251 .flags = IORESOURCE_MEM, 252 }, 253 { 254 .name = "rx", 255 .start = INT_McBSP3RX, 256 .flags = IORESOURCE_IRQ, 257 }, 258 { 259 .name = "tx", 260 .start = INT_McBSP3TX, 261 .flags = IORESOURCE_IRQ, 262 }, 263 { 264 .name = "rx", 265 .start = 11, 266 .flags = IORESOURCE_DMA, 267 }, 268 { 269 .name = "tx", 270 .start = 10, 271 .flags = IORESOURCE_DMA, 272 }, 273 }, 274 }; 275 276 #define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0] 277 278 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { 279 { 280 .ops = &omap1_mcbsp_ops, 281 }, 282 { 283 .ops = &omap1_mcbsp_ops, 284 }, 285 { 286 .ops = &omap1_mcbsp_ops, 287 }, 288 }; 289 #define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1]) 290 #define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res) 291 292 static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, 293 struct omap_mcbsp_platform_data *config, int size) 294 { 295 int i; 296 297 omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *), 298 GFP_KERNEL); 299 if (!omap_mcbsp_devices) { 300 printk(KERN_ERR "Could not register McBSP devices\n"); 301 return; 302 } 303 304 for (i = 0; i < size; i++) { 305 struct platform_device *new_mcbsp; 306 int ret; 307 308 new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1); 309 if (!new_mcbsp) 310 continue; 311 platform_device_add_resources(new_mcbsp, &res[i * res_count], 312 res_count); 313 config[i].reg_size = 2; 314 config[i].reg_step = 2; 315 new_mcbsp->dev.platform_data = &config[i]; 316 ret = platform_device_add(new_mcbsp); 317 if (ret) { 318 platform_device_put(new_mcbsp); 319 continue; 320 } 321 omap_mcbsp_devices[i] = new_mcbsp; 322 } 323 } 324 325 static int __init omap1_mcbsp_init(void) 326 { 327 if (!cpu_class_is_omap1()) 328 return -ENODEV; 329 330 if (cpu_is_omap15xx()) 331 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0, 332 OMAP15XX_MCBSP_RES_SZ, 333 omap15xx_mcbsp_pdata, 334 OMAP15XX_MCBSP_COUNT); 335 336 if (cpu_is_omap16xx()) 337 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0, 338 OMAP16XX_MCBSP_RES_SZ, 339 omap16xx_mcbsp_pdata, 340 OMAP16XX_MCBSP_COUNT); 341 342 return 0; 343 } 344 345 arch_initcall(omap1_mcbsp_init); 346