xref: /openbmc/linux/arch/arm/mach-omap1/mcbsp.c (revision b6dcefde)
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/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/irqs.h>
21 #include <plat/dma.h>
22 #include <plat/mux.h>
23 #include <plat/cpu.h>
24 #include <plat/mcbsp.h>
25 #include <plat/dsp_common.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 
34 static void omap1_mcbsp_request(unsigned int id)
35 {
36 	/*
37 	 * On 1510, 1610 and 1710, McBSP1 and McBSP3
38 	 * are DSP public peripherals.
39 	 */
40 	if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
41 		if (dsp_use++ == 0) {
42 			api_clk = clk_get(NULL, "api_ck");
43 			dsp_clk = clk_get(NULL, "dsp_ck");
44 			if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
45 				clk_enable(api_clk);
46 				clk_enable(dsp_clk);
47 
48 				omap_dsp_request_mem();
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 			omap_dsp_release_mem();
65 			if (!IS_ERR(api_clk)) {
66 				clk_disable(api_clk);
67 				clk_put(api_clk);
68 			}
69 			if (!IS_ERR(dsp_clk)) {
70 				clk_disable(dsp_clk);
71 				clk_put(dsp_clk);
72 			}
73 		}
74 	}
75 }
76 
77 static struct omap_mcbsp_ops omap1_mcbsp_ops = {
78 	.request	= omap1_mcbsp_request,
79 	.free		= omap1_mcbsp_free,
80 };
81 
82 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
83 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
84 	{
85 		.phys_base	= OMAP7XX_MCBSP1_BASE,
86 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
87 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
88 		.rx_irq		= INT_7XX_McBSP1RX,
89 		.tx_irq		= INT_7XX_McBSP1TX,
90 		.ops		= &omap1_mcbsp_ops,
91 	},
92 	{
93 		.phys_base	= OMAP7XX_MCBSP2_BASE,
94 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
95 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
96 		.rx_irq		= INT_7XX_McBSP2RX,
97 		.tx_irq		= INT_7XX_McBSP2TX,
98 		.ops		= &omap1_mcbsp_ops,
99 	},
100 };
101 #define OMAP7XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap7xx_mcbsp_pdata)
102 #else
103 #define omap7xx_mcbsp_pdata		NULL
104 #define OMAP7XX_MCBSP_PDATA_SZ		0
105 #endif
106 
107 #ifdef CONFIG_ARCH_OMAP15XX
108 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
109 	{
110 		.phys_base	= OMAP1510_MCBSP1_BASE,
111 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
112 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
113 		.rx_irq		= INT_McBSP1RX,
114 		.tx_irq		= INT_McBSP1TX,
115 		.ops		= &omap1_mcbsp_ops,
116 	},
117 	{
118 		.phys_base	= OMAP1510_MCBSP2_BASE,
119 		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
120 		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
121 		.rx_irq		= INT_1510_SPI_RX,
122 		.tx_irq		= INT_1510_SPI_TX,
123 		.ops		= &omap1_mcbsp_ops,
124 	},
125 	{
126 		.phys_base	= OMAP1510_MCBSP3_BASE,
127 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
128 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
129 		.rx_irq		= INT_McBSP3RX,
130 		.tx_irq		= INT_McBSP3TX,
131 		.ops		= &omap1_mcbsp_ops,
132 	},
133 };
134 #define OMAP15XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap15xx_mcbsp_pdata)
135 #else
136 #define omap15xx_mcbsp_pdata		NULL
137 #define OMAP15XX_MCBSP_PDATA_SZ		0
138 #endif
139 
140 #ifdef CONFIG_ARCH_OMAP16XX
141 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
142 	{
143 		.phys_base	= OMAP1610_MCBSP1_BASE,
144 		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
145 		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
146 		.rx_irq		= INT_McBSP1RX,
147 		.tx_irq		= INT_McBSP1TX,
148 		.ops		= &omap1_mcbsp_ops,
149 	},
150 	{
151 		.phys_base	= OMAP1610_MCBSP2_BASE,
152 		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
153 		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
154 		.rx_irq		= INT_1610_McBSP2_RX,
155 		.tx_irq		= INT_1610_McBSP2_TX,
156 		.ops		= &omap1_mcbsp_ops,
157 	},
158 	{
159 		.phys_base	= OMAP1610_MCBSP3_BASE,
160 		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
161 		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
162 		.rx_irq		= INT_McBSP3RX,
163 		.tx_irq		= INT_McBSP3TX,
164 		.ops		= &omap1_mcbsp_ops,
165 	},
166 };
167 #define OMAP16XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap16xx_mcbsp_pdata)
168 #else
169 #define omap16xx_mcbsp_pdata		NULL
170 #define OMAP16XX_MCBSP_PDATA_SZ		0
171 #endif
172 
173 int __init omap1_mcbsp_init(void)
174 {
175 	if (cpu_is_omap7xx())
176 		omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
177 	if (cpu_is_omap15xx())
178 		omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
179 	if (cpu_is_omap16xx())
180 		omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
181 
182 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
183 								GFP_KERNEL);
184 	if (!mcbsp_ptr)
185 		return -ENOMEM;
186 
187 	if (cpu_is_omap7xx())
188 		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_pdata,
189 						OMAP7XX_MCBSP_PDATA_SZ);
190 
191 	if (cpu_is_omap15xx())
192 		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
193 						OMAP15XX_MCBSP_PDATA_SZ);
194 
195 	if (cpu_is_omap16xx())
196 		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
197 						OMAP16XX_MCBSP_PDATA_SZ);
198 
199 	return omap_mcbsp_init();
200 }
201 
202 arch_initcall(omap1_mcbsp_init);
203