1 /* 2 * linux/arch/arm/mach-omap2/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/module.h> 14 #include <linux/init.h> 15 #include <linux/clk.h> 16 #include <linux/err.h> 17 #include <linux/io.h> 18 #include <linux/platform_device.h> 19 20 #include <mach/dma.h> 21 #include <mach/mux.h> 22 #include <mach/cpu.h> 23 #include <mach/mcbsp.h> 24 25 struct mcbsp_internal_clk { 26 struct clk clk; 27 struct clk **childs; 28 int n_childs; 29 }; 30 31 #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) 32 static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) 33 { 34 const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; 35 int i; 36 37 mclk->n_childs = ARRAY_SIZE(clk_names); 38 mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), 39 GFP_KERNEL); 40 41 for (i = 0; i < mclk->n_childs; i++) { 42 /* We fake a platform device to get correct device id */ 43 struct platform_device pdev; 44 45 pdev.dev.bus = &platform_bus_type; 46 pdev.id = mclk->clk.id; 47 mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); 48 if (IS_ERR(mclk->childs[i])) 49 printk(KERN_ERR "Could not get clock %s (%d).\n", 50 clk_names[i], mclk->clk.id); 51 } 52 } 53 54 static int omap_mcbsp_clk_enable(struct clk *clk) 55 { 56 struct mcbsp_internal_clk *mclk = container_of(clk, 57 struct mcbsp_internal_clk, clk); 58 int i; 59 60 for (i = 0; i < mclk->n_childs; i++) 61 clk_enable(mclk->childs[i]); 62 return 0; 63 } 64 65 static void omap_mcbsp_clk_disable(struct clk *clk) 66 { 67 struct mcbsp_internal_clk *mclk = container_of(clk, 68 struct mcbsp_internal_clk, clk); 69 int i; 70 71 for (i = 0; i < mclk->n_childs; i++) 72 clk_disable(mclk->childs[i]); 73 } 74 75 static struct mcbsp_internal_clk omap_mcbsp_clks[] = { 76 { 77 .clk = { 78 .name = "mcbsp_clk", 79 .id = 1, 80 .enable = omap_mcbsp_clk_enable, 81 .disable = omap_mcbsp_clk_disable, 82 }, 83 }, 84 { 85 .clk = { 86 .name = "mcbsp_clk", 87 .id = 2, 88 .enable = omap_mcbsp_clk_enable, 89 .disable = omap_mcbsp_clk_disable, 90 }, 91 }, 92 { 93 .clk = { 94 .name = "mcbsp_clk", 95 .id = 3, 96 .enable = omap_mcbsp_clk_enable, 97 .disable = omap_mcbsp_clk_disable, 98 }, 99 }, 100 { 101 .clk = { 102 .name = "mcbsp_clk", 103 .id = 4, 104 .enable = omap_mcbsp_clk_enable, 105 .disable = omap_mcbsp_clk_disable, 106 }, 107 }, 108 { 109 .clk = { 110 .name = "mcbsp_clk", 111 .id = 5, 112 .enable = omap_mcbsp_clk_enable, 113 .disable = omap_mcbsp_clk_disable, 114 }, 115 }, 116 }; 117 118 #define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) 119 #else 120 #define omap_mcbsp_clks_size 0 121 static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; 122 static inline void omap_mcbsp_clk_init(struct clk *clk) 123 { } 124 #endif 125 126 static void omap2_mcbsp2_mux_setup(void) 127 { 128 omap_cfg_reg(Y15_24XX_MCBSP2_CLKX); 129 omap_cfg_reg(R14_24XX_MCBSP2_FSX); 130 omap_cfg_reg(W15_24XX_MCBSP2_DR); 131 omap_cfg_reg(V15_24XX_MCBSP2_DX); 132 omap_cfg_reg(V14_24XX_GPIO117); 133 /* 134 * TODO: Need to add MUX settings for OMAP 2430 SDP 135 */ 136 } 137 138 static void omap2_mcbsp_request(unsigned int id) 139 { 140 if (cpu_is_omap2420() && (id == OMAP_MCBSP2)) 141 omap2_mcbsp2_mux_setup(); 142 } 143 144 static struct omap_mcbsp_ops omap2_mcbsp_ops = { 145 .request = omap2_mcbsp_request, 146 }; 147 148 #ifdef CONFIG_ARCH_OMAP2420 149 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { 150 { 151 .phys_base = OMAP24XX_MCBSP1_BASE, 152 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 153 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 154 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 155 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 156 .ops = &omap2_mcbsp_ops, 157 .clk_name = "mcbsp_clk", 158 }, 159 { 160 .phys_base = OMAP24XX_MCBSP2_BASE, 161 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 162 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 163 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 164 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 165 .ops = &omap2_mcbsp_ops, 166 .clk_name = "mcbsp_clk", 167 }, 168 }; 169 #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) 170 #else 171 #define omap2420_mcbsp_pdata NULL 172 #define OMAP2420_MCBSP_PDATA_SZ 0 173 #endif 174 175 #ifdef CONFIG_ARCH_OMAP2430 176 static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { 177 { 178 .phys_base = OMAP24XX_MCBSP1_BASE, 179 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 180 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 181 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 182 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 183 .ops = &omap2_mcbsp_ops, 184 .clk_name = "mcbsp_clk", 185 }, 186 { 187 .phys_base = OMAP24XX_MCBSP2_BASE, 188 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 189 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 190 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 191 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 192 .ops = &omap2_mcbsp_ops, 193 .clk_name = "mcbsp_clk", 194 }, 195 { 196 .phys_base = OMAP2430_MCBSP3_BASE, 197 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX, 198 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX, 199 .rx_irq = INT_24XX_MCBSP3_IRQ_RX, 200 .tx_irq = INT_24XX_MCBSP3_IRQ_TX, 201 .ops = &omap2_mcbsp_ops, 202 .clk_name = "mcbsp_clk", 203 }, 204 { 205 .phys_base = OMAP2430_MCBSP4_BASE, 206 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX, 207 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX, 208 .rx_irq = INT_24XX_MCBSP4_IRQ_RX, 209 .tx_irq = INT_24XX_MCBSP4_IRQ_TX, 210 .ops = &omap2_mcbsp_ops, 211 .clk_name = "mcbsp_clk", 212 }, 213 { 214 .phys_base = OMAP2430_MCBSP5_BASE, 215 .dma_rx_sync = OMAP24XX_DMA_MCBSP5_RX, 216 .dma_tx_sync = OMAP24XX_DMA_MCBSP5_TX, 217 .rx_irq = INT_24XX_MCBSP5_IRQ_RX, 218 .tx_irq = INT_24XX_MCBSP5_IRQ_TX, 219 .ops = &omap2_mcbsp_ops, 220 .clk_name = "mcbsp_clk", 221 }, 222 }; 223 #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) 224 #else 225 #define omap2430_mcbsp_pdata NULL 226 #define OMAP2430_MCBSP_PDATA_SZ 0 227 #endif 228 229 #ifdef CONFIG_ARCH_OMAP34XX 230 static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { 231 { 232 .phys_base = OMAP34XX_MCBSP1_BASE, 233 .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX, 234 .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX, 235 .rx_irq = INT_24XX_MCBSP1_IRQ_RX, 236 .tx_irq = INT_24XX_MCBSP1_IRQ_TX, 237 .ops = &omap2_mcbsp_ops, 238 .clk_name = "mcbsp_clk", 239 }, 240 { 241 .phys_base = OMAP34XX_MCBSP2_BASE, 242 .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX, 243 .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX, 244 .rx_irq = INT_24XX_MCBSP2_IRQ_RX, 245 .tx_irq = INT_24XX_MCBSP2_IRQ_TX, 246 .ops = &omap2_mcbsp_ops, 247 .clk_name = "mcbsp_clk", 248 }, 249 { 250 .phys_base = OMAP34XX_MCBSP3_BASE, 251 .dma_rx_sync = OMAP24XX_DMA_MCBSP3_RX, 252 .dma_tx_sync = OMAP24XX_DMA_MCBSP3_TX, 253 .rx_irq = INT_24XX_MCBSP3_IRQ_RX, 254 .tx_irq = INT_24XX_MCBSP3_IRQ_TX, 255 .ops = &omap2_mcbsp_ops, 256 .clk_name = "mcbsp_clk", 257 }, 258 { 259 .phys_base = OMAP34XX_MCBSP4_BASE, 260 .dma_rx_sync = OMAP24XX_DMA_MCBSP4_RX, 261 .dma_tx_sync = OMAP24XX_DMA_MCBSP4_TX, 262 .rx_irq = INT_24XX_MCBSP4_IRQ_RX, 263 .tx_irq = INT_24XX_MCBSP4_IRQ_TX, 264 .ops = &omap2_mcbsp_ops, 265 .clk_name = "mcbsp_clk", 266 }, 267 { 268 .phys_base = OMAP34XX_MCBSP5_BASE, 269 .dma_rx_sync = OMAP24XX_DMA_MCBSP5_RX, 270 .dma_tx_sync = OMAP24XX_DMA_MCBSP5_TX, 271 .rx_irq = INT_24XX_MCBSP5_IRQ_RX, 272 .tx_irq = INT_24XX_MCBSP5_IRQ_TX, 273 .ops = &omap2_mcbsp_ops, 274 .clk_name = "mcbsp_clk", 275 }, 276 }; 277 #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) 278 #else 279 #define omap34xx_mcbsp_pdata NULL 280 #define OMAP34XX_MCBSP_PDATA_SZ 0 281 #endif 282 283 static int __init omap2_mcbsp_init(void) 284 { 285 int i; 286 287 for (i = 0; i < omap_mcbsp_clks_size; i++) { 288 /* Once we call clk_get inside init, we do not register it */ 289 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); 290 clk_register(&omap_mcbsp_clks[i].clk); 291 } 292 293 if (cpu_is_omap2420()) 294 omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; 295 if (cpu_is_omap2430()) 296 omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ; 297 if (cpu_is_omap34xx()) 298 omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ; 299 300 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *), 301 GFP_KERNEL); 302 if (!mcbsp_ptr) 303 return -ENOMEM; 304 305 if (cpu_is_omap2420()) 306 omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata, 307 OMAP2420_MCBSP_PDATA_SZ); 308 if (cpu_is_omap2430()) 309 omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata, 310 OMAP2430_MCBSP_PDATA_SZ); 311 if (cpu_is_omap34xx()) 312 omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata, 313 OMAP34XX_MCBSP_PDATA_SZ); 314 315 return omap_mcbsp_init(); 316 } 317 arch_initcall(omap2_mcbsp_init); 318