blob: ca7a0cc1707c29779bf3b6d9c279da4d558682c7 [file] [log] [blame]
Eduardo Valentin44ec9a32008-07-03 12:24:40 +03001/*
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
Tony Lindgrendd7667a2009-01-15 13:09:51 +020020#include <mach/irqs.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010021#include <mach/dma.h>
Russell King80b02c12009-01-08 10:01:47 +000022#include <mach/irqs.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010023#include <mach/mux.h>
24#include <mach/cpu.h>
25#include <mach/mcbsp.h>
26#include <mach/dsp_common.h>
Eduardo Valentin44ec9a32008-07-03 12:24:40 +030027
28#define DPS_RSTCT2_PER_EN (1 << 0)
29#define DSP_RSTCT2_WD_PER_EN (1 << 1)
30
31struct mcbsp_internal_clk {
32 struct clk clk;
33 struct clk **childs;
34 int n_childs;
35};
36
37#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
38static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
39{
40 const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" };
41 int i;
42
43 mclk->n_childs = ARRAY_SIZE(clk_names);
44 mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
45 GFP_KERNEL);
46
47 for (i = 0; i < mclk->n_childs; i++) {
48 /* We fake a platform device to get correct device id */
49 struct platform_device pdev;
50
51 pdev.dev.bus = &platform_bus_type;
52 pdev.id = mclk->clk.id;
53 mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
54 if (IS_ERR(mclk->childs[i]))
55 printk(KERN_ERR "Could not get clock %s (%d).\n",
56 clk_names[i], mclk->clk.id);
57 }
58}
59
60static int omap_mcbsp_clk_enable(struct clk *clk)
61{
62 struct mcbsp_internal_clk *mclk = container_of(clk,
63 struct mcbsp_internal_clk, clk);
64 int i;
65
66 for (i = 0; i < mclk->n_childs; i++)
67 clk_enable(mclk->childs[i]);
68 return 0;
69}
70
71static void omap_mcbsp_clk_disable(struct clk *clk)
72{
73 struct mcbsp_internal_clk *mclk = container_of(clk,
74 struct mcbsp_internal_clk, clk);
75 int i;
76
77 for (i = 0; i < mclk->n_childs; i++)
78 clk_disable(mclk->childs[i]);
79}
80
81static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
82 {
83 .clk = {
84 .name = "mcbsp_clk",
85 .id = 1,
86 .enable = omap_mcbsp_clk_enable,
87 .disable = omap_mcbsp_clk_disable,
88 },
89 },
90 {
91 .clk = {
92 .name = "mcbsp_clk",
93 .id = 3,
94 .enable = omap_mcbsp_clk_enable,
95 .disable = omap_mcbsp_clk_disable,
96 },
97 },
98};
99
100#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
101#else
102#define omap_mcbsp_clks_size 0
103static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
104static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
105{ }
106#endif
107
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300108static void omap1_mcbsp_request(unsigned int id)
109{
110 /*
111 * On 1510, 1610 and 1710, McBSP1 and McBSP3
112 * are DSP public peripherals.
113 */
114 if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
115 omap_dsp_request_mem();
116 /*
117 * DSP external peripheral reset
118 * FIXME: This should be moved to dsp code
119 */
120 __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
121 DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
122 }
123}
124
125static void omap1_mcbsp_free(unsigned int id)
126{
127 if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
128 omap_dsp_release_mem();
129}
130
131static struct omap_mcbsp_ops omap1_mcbsp_ops = {
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300132 .request = omap1_mcbsp_request,
133 .free = omap1_mcbsp_free,
134};
135
136#ifdef CONFIG_ARCH_OMAP730
137static struct omap_mcbsp_platform_data omap730_mcbsp_pdata[] = {
138 {
Russell King65846902008-09-03 23:46:18 +0100139 .phys_base = OMAP730_MCBSP1_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300140 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
141 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
142 .rx_irq = INT_730_McBSP1RX,
143 .tx_irq = INT_730_McBSP1TX,
144 .ops = &omap1_mcbsp_ops,
145 },
146 {
Russell King65846902008-09-03 23:46:18 +0100147 .phys_base = OMAP730_MCBSP2_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300148 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
149 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
150 .rx_irq = INT_730_McBSP2RX,
151 .tx_irq = INT_730_McBSP2TX,
152 .ops = &omap1_mcbsp_ops,
153 },
154};
155#define OMAP730_MCBSP_PDATA_SZ ARRAY_SIZE(omap730_mcbsp_pdata)
156#else
157#define omap730_mcbsp_pdata NULL
158#define OMAP730_MCBSP_PDATA_SZ 0
159#endif
160
161#ifdef CONFIG_ARCH_OMAP15XX
162static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
163 {
Russell King65846902008-09-03 23:46:18 +0100164 .phys_base = OMAP1510_MCBSP1_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300165 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
166 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
167 .rx_irq = INT_McBSP1RX,
168 .tx_irq = INT_McBSP1TX,
169 .ops = &omap1_mcbsp_ops,
170 .clk_name = "mcbsp_clk",
171 },
172 {
Russell King65846902008-09-03 23:46:18 +0100173 .phys_base = OMAP1510_MCBSP2_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300174 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
175 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
176 .rx_irq = INT_1510_SPI_RX,
177 .tx_irq = INT_1510_SPI_TX,
178 .ops = &omap1_mcbsp_ops,
179 },
180 {
Russell King65846902008-09-03 23:46:18 +0100181 .phys_base = OMAP1510_MCBSP3_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300182 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
183 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
184 .rx_irq = INT_McBSP3RX,
185 .tx_irq = INT_McBSP3TX,
186 .ops = &omap1_mcbsp_ops,
187 .clk_name = "mcbsp_clk",
188 },
189};
190#define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata)
191#else
192#define omap15xx_mcbsp_pdata NULL
193#define OMAP15XX_MCBSP_PDATA_SZ 0
194#endif
195
196#ifdef CONFIG_ARCH_OMAP16XX
197static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
198 {
Russell King65846902008-09-03 23:46:18 +0100199 .phys_base = OMAP1610_MCBSP1_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300200 .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
201 .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
202 .rx_irq = INT_McBSP1RX,
203 .tx_irq = INT_McBSP1TX,
204 .ops = &omap1_mcbsp_ops,
205 .clk_name = "mcbsp_clk",
206 },
207 {
Russell King65846902008-09-03 23:46:18 +0100208 .phys_base = OMAP1610_MCBSP2_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300209 .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
210 .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
211 .rx_irq = INT_1610_McBSP2_RX,
212 .tx_irq = INT_1610_McBSP2_TX,
213 .ops = &omap1_mcbsp_ops,
214 },
215 {
Russell King65846902008-09-03 23:46:18 +0100216 .phys_base = OMAP1610_MCBSP3_BASE,
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300217 .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
218 .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
219 .rx_irq = INT_McBSP3RX,
220 .tx_irq = INT_McBSP3TX,
221 .ops = &omap1_mcbsp_ops,
222 .clk_name = "mcbsp_clk",
223 },
224};
225#define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata)
226#else
227#define omap16xx_mcbsp_pdata NULL
228#define OMAP16XX_MCBSP_PDATA_SZ 0
229#endif
230
231int __init omap1_mcbsp_init(void)
232{
233 int i;
234
235 for (i = 0; i < omap_mcbsp_clks_size; i++) {
236 if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
237 omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
238 clk_register(&omap_mcbsp_clks[i].clk);
239 }
240 }
241
242 if (cpu_is_omap730())
Chandra Shekharb4b58f52008-10-08 10:01:39 +0300243 omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ;
244 if (cpu_is_omap15xx())
245 omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
246 if (cpu_is_omap16xx())
247 omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
248
249 mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
250 GFP_KERNEL);
251 if (!mcbsp_ptr)
252 return -ENOMEM;
253
254 if (cpu_is_omap730())
Eduardo Valentin44ec9a32008-07-03 12:24:40 +0300255 omap_mcbsp_register_board_cfg(omap730_mcbsp_pdata,
256 OMAP730_MCBSP_PDATA_SZ);
257
258 if (cpu_is_omap15xx())
259 omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
260 OMAP15XX_MCBSP_PDATA_SZ);
261
262 if (cpu_is_omap16xx())
263 omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
264 OMAP16XX_MCBSP_PDATA_SZ);
265
266 return omap_mcbsp_init();
267}
268
269arch_initcall(omap1_mcbsp_init);