diff options
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 431 |
1 files changed, 255 insertions, 176 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 014d26574bb6..af33fc713e1a 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -27,43 +27,65 @@ | |||
27 | #include <mach/dma.h> | 27 | #include <mach/dma.h> |
28 | #include <mach/mcbsp.h> | 28 | #include <mach/mcbsp.h> |
29 | 29 | ||
30 | static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT]; | 30 | struct omap_mcbsp **mcbsp_ptr; |
31 | int omap_mcbsp_count; | ||
31 | 32 | ||
32 | #define omap_mcbsp_check_valid_id(id) (mcbsp[id].pdata && \ | 33 | void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val) |
33 | mcbsp[id].pdata->ops && \ | 34 | { |
34 | mcbsp[id].pdata->ops->check && \ | 35 | if (cpu_class_is_omap1() || cpu_is_omap2420()) |
35 | (mcbsp[id].pdata->ops->check(id) == 0)) | 36 | __raw_writew((u16)val, io_base + reg); |
37 | else | ||
38 | __raw_writel(val, io_base + reg); | ||
39 | } | ||
40 | |||
41 | int omap_mcbsp_read(void __iomem *io_base, u16 reg) | ||
42 | { | ||
43 | if (cpu_class_is_omap1() || cpu_is_omap2420()) | ||
44 | return __raw_readw(io_base + reg); | ||
45 | else | ||
46 | return __raw_readl(io_base + reg); | ||
47 | } | ||
48 | |||
49 | #define OMAP_MCBSP_READ(base, reg) \ | ||
50 | omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg) | ||
51 | #define OMAP_MCBSP_WRITE(base, reg, val) \ | ||
52 | omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val) | ||
53 | |||
54 | #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) | ||
55 | #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; | ||
36 | 56 | ||
37 | static void omap_mcbsp_dump_reg(u8 id) | 57 | static void omap_mcbsp_dump_reg(u8 id) |
38 | { | 58 | { |
39 | dev_dbg(mcbsp[id].dev, "**** McBSP%d regs ****\n", mcbsp[id].id); | 59 | struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); |
40 | dev_dbg(mcbsp[id].dev, "DRR2: 0x%04x\n", | 60 | |
41 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2)); | 61 | dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); |
42 | dev_dbg(mcbsp[id].dev, "DRR1: 0x%04x\n", | 62 | dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", |
43 | OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1)); | 63 | OMAP_MCBSP_READ(mcbsp->io_base, DRR2)); |
44 | dev_dbg(mcbsp[id].dev, "DXR2: 0x%04x\n", | 64 | dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", |
45 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2)); | 65 | OMAP_MCBSP_READ(mcbsp->io_base, DRR1)); |
46 | dev_dbg(mcbsp[id].dev, "DXR1: 0x%04x\n", | 66 | dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", |
47 | OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1)); | 67 | OMAP_MCBSP_READ(mcbsp->io_base, DXR2)); |
48 | dev_dbg(mcbsp[id].dev, "SPCR2: 0x%04x\n", | 68 | dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", |
49 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2)); | 69 | OMAP_MCBSP_READ(mcbsp->io_base, DXR1)); |
50 | dev_dbg(mcbsp[id].dev, "SPCR1: 0x%04x\n", | 70 | dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", |
51 | OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1)); | 71 | OMAP_MCBSP_READ(mcbsp->io_base, SPCR2)); |
52 | dev_dbg(mcbsp[id].dev, "RCR2: 0x%04x\n", | 72 | dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", |
53 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2)); | 73 | OMAP_MCBSP_READ(mcbsp->io_base, SPCR1)); |
54 | dev_dbg(mcbsp[id].dev, "RCR1: 0x%04x\n", | 74 | dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", |
55 | OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1)); | 75 | OMAP_MCBSP_READ(mcbsp->io_base, RCR2)); |
56 | dev_dbg(mcbsp[id].dev, "XCR2: 0x%04x\n", | 76 | dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", |
57 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2)); | 77 | OMAP_MCBSP_READ(mcbsp->io_base, RCR1)); |
58 | dev_dbg(mcbsp[id].dev, "XCR1: 0x%04x\n", | 78 | dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", |
59 | OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1)); | 79 | OMAP_MCBSP_READ(mcbsp->io_base, XCR2)); |
60 | dev_dbg(mcbsp[id].dev, "SRGR2: 0x%04x\n", | 80 | dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", |
61 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2)); | 81 | OMAP_MCBSP_READ(mcbsp->io_base, XCR1)); |
62 | dev_dbg(mcbsp[id].dev, "SRGR1: 0x%04x\n", | 82 | dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", |
63 | OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1)); | 83 | OMAP_MCBSP_READ(mcbsp->io_base, SRGR2)); |
64 | dev_dbg(mcbsp[id].dev, "PCR0: 0x%04x\n", | 84 | dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", |
65 | OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0)); | 85 | OMAP_MCBSP_READ(mcbsp->io_base, SRGR1)); |
66 | dev_dbg(mcbsp[id].dev, "***********************\n"); | 86 | dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", |
87 | OMAP_MCBSP_READ(mcbsp->io_base, PCR0)); | ||
88 | dev_dbg(mcbsp->dev, "***********************\n"); | ||
67 | } | 89 | } |
68 | 90 | ||
69 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) | 91 | static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) |
@@ -126,16 +148,18 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
126 | */ | 148 | */ |
127 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | 149 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) |
128 | { | 150 | { |
129 | u32 io_base; | 151 | struct omap_mcbsp *mcbsp; |
152 | void __iomem *io_base; | ||
130 | 153 | ||
131 | if (!omap_mcbsp_check_valid_id(id)) { | 154 | if (!omap_mcbsp_check_valid_id(id)) { |
132 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 155 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
133 | return; | 156 | return; |
134 | } | 157 | } |
158 | mcbsp = id_to_mcbsp_ptr(id); | ||
135 | 159 | ||
136 | io_base = mcbsp[id].io_base; | 160 | io_base = mcbsp->io_base; |
137 | dev_dbg(mcbsp[id].dev, "Configuring McBSP%d io_base: 0x%8x\n", | 161 | dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", |
138 | mcbsp[id].id, io_base); | 162 | mcbsp->id, mcbsp->phys_base); |
139 | 163 | ||
140 | /* We write the given config */ | 164 | /* We write the given config */ |
141 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); | 165 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); |
@@ -158,23 +182,26 @@ EXPORT_SYMBOL(omap_mcbsp_config); | |||
158 | */ | 182 | */ |
159 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | 183 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) |
160 | { | 184 | { |
185 | struct omap_mcbsp *mcbsp; | ||
186 | |||
161 | if (!omap_mcbsp_check_valid_id(id)) { | 187 | if (!omap_mcbsp_check_valid_id(id)) { |
162 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 188 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
163 | return -ENODEV; | 189 | return -ENODEV; |
164 | } | 190 | } |
191 | mcbsp = id_to_mcbsp_ptr(id); | ||
165 | 192 | ||
166 | spin_lock(&mcbsp[id].lock); | 193 | spin_lock(&mcbsp->lock); |
167 | 194 | ||
168 | if (!mcbsp[id].free) { | 195 | if (!mcbsp->free) { |
169 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", | 196 | dev_err(mcbsp->dev, "McBSP%d is currently in use\n", |
170 | mcbsp[id].id); | 197 | mcbsp->id); |
171 | spin_unlock(&mcbsp[id].lock); | 198 | spin_unlock(&mcbsp->lock); |
172 | return -EINVAL; | 199 | return -EINVAL; |
173 | } | 200 | } |
174 | 201 | ||
175 | mcbsp[id].io_type = io_type; | 202 | mcbsp->io_type = io_type; |
176 | 203 | ||
177 | spin_unlock(&mcbsp[id].lock); | 204 | spin_unlock(&mcbsp->lock); |
178 | 205 | ||
179 | return 0; | 206 | return 0; |
180 | } | 207 | } |
@@ -182,53 +209,60 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); | |||
182 | 209 | ||
183 | int omap_mcbsp_request(unsigned int id) | 210 | int omap_mcbsp_request(unsigned int id) |
184 | { | 211 | { |
212 | struct omap_mcbsp *mcbsp; | ||
185 | int err; | 213 | int err; |
186 | 214 | ||
187 | if (!omap_mcbsp_check_valid_id(id)) { | 215 | if (!omap_mcbsp_check_valid_id(id)) { |
188 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 216 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
189 | return -ENODEV; | 217 | return -ENODEV; |
190 | } | 218 | } |
219 | mcbsp = id_to_mcbsp_ptr(id); | ||
191 | 220 | ||
192 | if (mcbsp[id].pdata->ops->request) | 221 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) |
193 | mcbsp[id].pdata->ops->request(id); | 222 | mcbsp->pdata->ops->request(id); |
194 | 223 | ||
195 | clk_enable(mcbsp[id].clk); | 224 | clk_enable(mcbsp->clk); |
196 | 225 | ||
197 | spin_lock(&mcbsp[id].lock); | 226 | spin_lock(&mcbsp->lock); |
198 | if (!mcbsp[id].free) { | 227 | if (!mcbsp->free) { |
199 | dev_err(mcbsp[id].dev, "McBSP%d is currently in use\n", | 228 | dev_err(mcbsp->dev, "McBSP%d is currently in use\n", |
200 | mcbsp[id].id); | 229 | mcbsp->id); |
201 | spin_unlock(&mcbsp[id].lock); | 230 | spin_unlock(&mcbsp->lock); |
202 | return -1; | 231 | return -1; |
203 | } | 232 | } |
204 | 233 | ||
205 | mcbsp[id].free = 0; | 234 | mcbsp->free = 0; |
206 | spin_unlock(&mcbsp[id].lock); | 235 | spin_unlock(&mcbsp->lock); |
236 | |||
237 | /* | ||
238 | * Make sure that transmitter, receiver and sample-rate generator are | ||
239 | * not running before activating IRQs. | ||
240 | */ | ||
241 | OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR1, 0); | ||
242 | OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR2, 0); | ||
207 | 243 | ||
208 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { | 244 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { |
209 | /* We need to get IRQs here */ | 245 | /* We need to get IRQs here */ |
210 | err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, | 246 | init_completion(&mcbsp->tx_irq_completion); |
211 | 0, "McBSP", (void *) (&mcbsp[id])); | 247 | err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, |
248 | 0, "McBSP", (void *)mcbsp); | ||
212 | if (err != 0) { | 249 | if (err != 0) { |
213 | dev_err(mcbsp[id].dev, "Unable to request TX IRQ %d " | 250 | dev_err(mcbsp->dev, "Unable to request TX IRQ %d " |
214 | "for McBSP%d\n", mcbsp[id].tx_irq, | 251 | "for McBSP%d\n", mcbsp->tx_irq, |
215 | mcbsp[id].id); | 252 | mcbsp->id); |
216 | return err; | 253 | return err; |
217 | } | 254 | } |
218 | 255 | ||
219 | init_completion(&(mcbsp[id].tx_irq_completion)); | 256 | init_completion(&mcbsp->rx_irq_completion); |
220 | 257 | err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, | |
221 | err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, | 258 | 0, "McBSP", (void *)mcbsp); |
222 | 0, "McBSP", (void *) (&mcbsp[id])); | ||
223 | if (err != 0) { | 259 | if (err != 0) { |
224 | dev_err(mcbsp[id].dev, "Unable to request RX IRQ %d " | 260 | dev_err(mcbsp->dev, "Unable to request RX IRQ %d " |
225 | "for McBSP%d\n", mcbsp[id].rx_irq, | 261 | "for McBSP%d\n", mcbsp->rx_irq, |
226 | mcbsp[id].id); | 262 | mcbsp->id); |
227 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 263 | free_irq(mcbsp->tx_irq, (void *)mcbsp); |
228 | return err; | 264 | return err; |
229 | } | 265 | } |
230 | |||
231 | init_completion(&(mcbsp[id].rx_irq_completion)); | ||
232 | } | 266 | } |
233 | 267 | ||
234 | return 0; | 268 | return 0; |
@@ -237,31 +271,34 @@ EXPORT_SYMBOL(omap_mcbsp_request); | |||
237 | 271 | ||
238 | void omap_mcbsp_free(unsigned int id) | 272 | void omap_mcbsp_free(unsigned int id) |
239 | { | 273 | { |
274 | struct omap_mcbsp *mcbsp; | ||
275 | |||
240 | if (!omap_mcbsp_check_valid_id(id)) { | 276 | if (!omap_mcbsp_check_valid_id(id)) { |
241 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 277 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
242 | return; | 278 | return; |
243 | } | 279 | } |
280 | mcbsp = id_to_mcbsp_ptr(id); | ||
244 | 281 | ||
245 | if (mcbsp[id].pdata->ops->free) | 282 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) |
246 | mcbsp[id].pdata->ops->free(id); | 283 | mcbsp->pdata->ops->free(id); |
247 | 284 | ||
248 | clk_disable(mcbsp[id].clk); | 285 | clk_disable(mcbsp->clk); |
249 | 286 | ||
250 | spin_lock(&mcbsp[id].lock); | 287 | spin_lock(&mcbsp->lock); |
251 | if (mcbsp[id].free) { | 288 | if (mcbsp->free) { |
252 | dev_err(mcbsp[id].dev, "McBSP%d was not reserved\n", | 289 | dev_err(mcbsp->dev, "McBSP%d was not reserved\n", |
253 | mcbsp[id].id); | 290 | mcbsp->id); |
254 | spin_unlock(&mcbsp[id].lock); | 291 | spin_unlock(&mcbsp->lock); |
255 | return; | 292 | return; |
256 | } | 293 | } |
257 | 294 | ||
258 | mcbsp[id].free = 1; | 295 | mcbsp->free = 1; |
259 | spin_unlock(&mcbsp[id].lock); | 296 | spin_unlock(&mcbsp->lock); |
260 | 297 | ||
261 | if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) { | 298 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { |
262 | /* Free IRQs */ | 299 | /* Free IRQs */ |
263 | free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id])); | 300 | free_irq(mcbsp->rx_irq, (void *)mcbsp); |
264 | free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id])); | 301 | free_irq(mcbsp->tx_irq, (void *)mcbsp); |
265 | } | 302 | } |
266 | } | 303 | } |
267 | EXPORT_SYMBOL(omap_mcbsp_free); | 304 | EXPORT_SYMBOL(omap_mcbsp_free); |
@@ -273,18 +310,19 @@ EXPORT_SYMBOL(omap_mcbsp_free); | |||
273 | */ | 310 | */ |
274 | void omap_mcbsp_start(unsigned int id) | 311 | void omap_mcbsp_start(unsigned int id) |
275 | { | 312 | { |
276 | u32 io_base; | 313 | struct omap_mcbsp *mcbsp; |
314 | void __iomem *io_base; | ||
277 | u16 w; | 315 | u16 w; |
278 | 316 | ||
279 | if (!omap_mcbsp_check_valid_id(id)) { | 317 | if (!omap_mcbsp_check_valid_id(id)) { |
280 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 318 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
281 | return; | 319 | return; |
282 | } | 320 | } |
321 | mcbsp = id_to_mcbsp_ptr(id); | ||
322 | io_base = mcbsp->io_base; | ||
283 | 323 | ||
284 | io_base = mcbsp[id].io_base; | 324 | mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; |
285 | 325 | mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; | |
286 | mcbsp[id].rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; | ||
287 | mcbsp[id].tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; | ||
288 | 326 | ||
289 | /* Start the sample generator */ | 327 | /* Start the sample generator */ |
290 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 328 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
@@ -310,7 +348,8 @@ EXPORT_SYMBOL(omap_mcbsp_start); | |||
310 | 348 | ||
311 | void omap_mcbsp_stop(unsigned int id) | 349 | void omap_mcbsp_stop(unsigned int id) |
312 | { | 350 | { |
313 | u32 io_base; | 351 | struct omap_mcbsp *mcbsp; |
352 | void __iomem *io_base; | ||
314 | u16 w; | 353 | u16 w; |
315 | 354 | ||
316 | if (!omap_mcbsp_check_valid_id(id)) { | 355 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -318,7 +357,8 @@ void omap_mcbsp_stop(unsigned int id) | |||
318 | return; | 357 | return; |
319 | } | 358 | } |
320 | 359 | ||
321 | io_base = mcbsp[id].io_base; | 360 | mcbsp = id_to_mcbsp_ptr(id); |
361 | io_base = mcbsp->io_base; | ||
322 | 362 | ||
323 | /* Reset transmitter */ | 363 | /* Reset transmitter */ |
324 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 364 | w = OMAP_MCBSP_READ(io_base, SPCR2); |
@@ -337,14 +377,17 @@ EXPORT_SYMBOL(omap_mcbsp_stop); | |||
337 | /* polled mcbsp i/o operations */ | 377 | /* polled mcbsp i/o operations */ |
338 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | 378 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) |
339 | { | 379 | { |
340 | u32 base; | 380 | struct omap_mcbsp *mcbsp; |
381 | void __iomem *base; | ||
341 | 382 | ||
342 | if (!omap_mcbsp_check_valid_id(id)) { | 383 | if (!omap_mcbsp_check_valid_id(id)) { |
343 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 384 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
344 | return -ENODEV; | 385 | return -ENODEV; |
345 | } | 386 | } |
346 | 387 | ||
347 | base = mcbsp[id].io_base; | 388 | mcbsp = id_to_mcbsp_ptr(id); |
389 | base = mcbsp->io_base; | ||
390 | |||
348 | writew(buf, base + OMAP_MCBSP_REG_DXR1); | 391 | writew(buf, base + OMAP_MCBSP_REG_DXR1); |
349 | /* if frame sync error - clear the error */ | 392 | /* if frame sync error - clear the error */ |
350 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { | 393 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { |
@@ -366,8 +409,8 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | |||
366 | (XRST), | 409 | (XRST), |
367 | base + OMAP_MCBSP_REG_SPCR2); | 410 | base + OMAP_MCBSP_REG_SPCR2); |
368 | udelay(10); | 411 | udelay(10); |
369 | dev_err(mcbsp[id].dev, "Could not write to" | 412 | dev_err(mcbsp->dev, "Could not write to" |
370 | " McBSP%d Register\n", mcbsp[id].id); | 413 | " McBSP%d Register\n", mcbsp->id); |
371 | return -2; | 414 | return -2; |
372 | } | 415 | } |
373 | } | 416 | } |
@@ -379,14 +422,16 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite); | |||
379 | 422 | ||
380 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) | 423 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) |
381 | { | 424 | { |
382 | u32 base; | 425 | struct omap_mcbsp *mcbsp; |
426 | void __iomem *base; | ||
383 | 427 | ||
384 | if (!omap_mcbsp_check_valid_id(id)) { | 428 | if (!omap_mcbsp_check_valid_id(id)) { |
385 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 429 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
386 | return -ENODEV; | 430 | return -ENODEV; |
387 | } | 431 | } |
432 | mcbsp = id_to_mcbsp_ptr(id); | ||
388 | 433 | ||
389 | base = mcbsp[id].io_base; | 434 | base = mcbsp->io_base; |
390 | /* if frame sync error - clear the error */ | 435 | /* if frame sync error - clear the error */ |
391 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { | 436 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { |
392 | /* clear error */ | 437 | /* clear error */ |
@@ -407,8 +452,8 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) | |||
407 | (RRST), | 452 | (RRST), |
408 | base + OMAP_MCBSP_REG_SPCR1); | 453 | base + OMAP_MCBSP_REG_SPCR1); |
409 | udelay(10); | 454 | udelay(10); |
410 | dev_err(mcbsp[id].dev, "Could not read from" | 455 | dev_err(mcbsp->dev, "Could not read from" |
411 | " McBSP%d Register\n", mcbsp[id].id); | 456 | " McBSP%d Register\n", mcbsp->id); |
412 | return -2; | 457 | return -2; |
413 | } | 458 | } |
414 | } | 459 | } |
@@ -424,7 +469,8 @@ EXPORT_SYMBOL(omap_mcbsp_pollread); | |||
424 | */ | 469 | */ |
425 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) | 470 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) |
426 | { | 471 | { |
427 | u32 io_base; | 472 | struct omap_mcbsp *mcbsp; |
473 | void __iomem *io_base; | ||
428 | omap_mcbsp_word_length word_length; | 474 | omap_mcbsp_word_length word_length; |
429 | 475 | ||
430 | if (!omap_mcbsp_check_valid_id(id)) { | 476 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -432,10 +478,11 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word) | |||
432 | return; | 478 | return; |
433 | } | 479 | } |
434 | 480 | ||
435 | io_base = mcbsp[id].io_base; | 481 | mcbsp = id_to_mcbsp_ptr(id); |
436 | word_length = mcbsp[id].tx_word_length; | 482 | io_base = mcbsp->io_base; |
483 | word_length = mcbsp->tx_word_length; | ||
437 | 484 | ||
438 | wait_for_completion(&(mcbsp[id].tx_irq_completion)); | 485 | wait_for_completion(&mcbsp->tx_irq_completion); |
439 | 486 | ||
440 | if (word_length > OMAP_MCBSP_WORD_16) | 487 | if (word_length > OMAP_MCBSP_WORD_16) |
441 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | 488 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); |
@@ -445,7 +492,8 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_word); | |||
445 | 492 | ||
446 | u32 omap_mcbsp_recv_word(unsigned int id) | 493 | u32 omap_mcbsp_recv_word(unsigned int id) |
447 | { | 494 | { |
448 | u32 io_base; | 495 | struct omap_mcbsp *mcbsp; |
496 | void __iomem *io_base; | ||
449 | u16 word_lsb, word_msb = 0; | 497 | u16 word_lsb, word_msb = 0; |
450 | omap_mcbsp_word_length word_length; | 498 | omap_mcbsp_word_length word_length; |
451 | 499 | ||
@@ -453,11 +501,12 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
453 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 501 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
454 | return -ENODEV; | 502 | return -ENODEV; |
455 | } | 503 | } |
504 | mcbsp = id_to_mcbsp_ptr(id); | ||
456 | 505 | ||
457 | word_length = mcbsp[id].rx_word_length; | 506 | word_length = mcbsp->rx_word_length; |
458 | io_base = mcbsp[id].io_base; | 507 | io_base = mcbsp->io_base; |
459 | 508 | ||
460 | wait_for_completion(&(mcbsp[id].rx_irq_completion)); | 509 | wait_for_completion(&mcbsp->rx_irq_completion); |
461 | 510 | ||
462 | if (word_length > OMAP_MCBSP_WORD_16) | 511 | if (word_length > OMAP_MCBSP_WORD_16) |
463 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | 512 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); |
@@ -469,7 +518,8 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word); | |||
469 | 518 | ||
470 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | 519 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) |
471 | { | 520 | { |
472 | u32 io_base; | 521 | struct omap_mcbsp *mcbsp; |
522 | void __iomem *io_base; | ||
473 | omap_mcbsp_word_length tx_word_length; | 523 | omap_mcbsp_word_length tx_word_length; |
474 | omap_mcbsp_word_length rx_word_length; | 524 | omap_mcbsp_word_length rx_word_length; |
475 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 525 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
@@ -478,10 +528,10 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
478 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 528 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
479 | return -ENODEV; | 529 | return -ENODEV; |
480 | } | 530 | } |
481 | 531 | mcbsp = id_to_mcbsp_ptr(id); | |
482 | io_base = mcbsp[id].io_base; | 532 | io_base = mcbsp->io_base; |
483 | tx_word_length = mcbsp[id].tx_word_length; | 533 | tx_word_length = mcbsp->tx_word_length; |
484 | rx_word_length = mcbsp[id].rx_word_length; | 534 | rx_word_length = mcbsp->rx_word_length; |
485 | 535 | ||
486 | if (tx_word_length != rx_word_length) | 536 | if (tx_word_length != rx_word_length) |
487 | return -EINVAL; | 537 | return -EINVAL; |
@@ -496,8 +546,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
496 | udelay(10); | 546 | udelay(10); |
497 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 547 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
498 | udelay(10); | 548 | udelay(10); |
499 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " | 549 | dev_err(mcbsp->dev, "McBSP%d transmitter not " |
500 | "ready\n", mcbsp[id].id); | 550 | "ready\n", mcbsp->id); |
501 | return -EAGAIN; | 551 | return -EAGAIN; |
502 | } | 552 | } |
503 | } | 553 | } |
@@ -517,8 +567,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
517 | udelay(10); | 567 | udelay(10); |
518 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 568 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
519 | udelay(10); | 569 | udelay(10); |
520 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " | 570 | dev_err(mcbsp->dev, "McBSP%d receiver not " |
521 | "ready\n", mcbsp[id].id); | 571 | "ready\n", mcbsp->id); |
522 | return -EAGAIN; | 572 | return -EAGAIN; |
523 | } | 573 | } |
524 | } | 574 | } |
@@ -534,7 +584,9 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | |||
534 | 584 | ||
535 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | 585 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) |
536 | { | 586 | { |
537 | u32 io_base, clock_word = 0; | 587 | struct omap_mcbsp *mcbsp; |
588 | u32 clock_word = 0; | ||
589 | void __iomem *io_base; | ||
538 | omap_mcbsp_word_length tx_word_length; | 590 | omap_mcbsp_word_length tx_word_length; |
539 | omap_mcbsp_word_length rx_word_length; | 591 | omap_mcbsp_word_length rx_word_length; |
540 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 592 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
@@ -544,9 +596,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
544 | return -ENODEV; | 596 | return -ENODEV; |
545 | } | 597 | } |
546 | 598 | ||
547 | io_base = mcbsp[id].io_base; | 599 | mcbsp = id_to_mcbsp_ptr(id); |
548 | tx_word_length = mcbsp[id].tx_word_length; | 600 | io_base = mcbsp->io_base; |
549 | rx_word_length = mcbsp[id].rx_word_length; | 601 | |
602 | tx_word_length = mcbsp->tx_word_length; | ||
603 | rx_word_length = mcbsp->rx_word_length; | ||
550 | 604 | ||
551 | if (tx_word_length != rx_word_length) | 605 | if (tx_word_length != rx_word_length) |
552 | return -EINVAL; | 606 | return -EINVAL; |
@@ -561,8 +615,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
561 | udelay(10); | 615 | udelay(10); |
562 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 616 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); |
563 | udelay(10); | 617 | udelay(10); |
564 | dev_err(mcbsp[id].dev, "McBSP%d transmitter not " | 618 | dev_err(mcbsp->dev, "McBSP%d transmitter not " |
565 | "ready\n", mcbsp[id].id); | 619 | "ready\n", mcbsp->id); |
566 | return -EAGAIN; | 620 | return -EAGAIN; |
567 | } | 621 | } |
568 | } | 622 | } |
@@ -582,8 +636,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
582 | udelay(10); | 636 | udelay(10); |
583 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 637 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); |
584 | udelay(10); | 638 | udelay(10); |
585 | dev_err(mcbsp[id].dev, "McBSP%d receiver not " | 639 | dev_err(mcbsp->dev, "McBSP%d receiver not " |
586 | "ready\n", mcbsp[id].id); | 640 | "ready\n", mcbsp->id); |
587 | return -EAGAIN; | 641 | return -EAGAIN; |
588 | } | 642 | } |
589 | } | 643 | } |
@@ -609,6 +663,7 @@ EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | |||
609 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, | 663 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, |
610 | unsigned int length) | 664 | unsigned int length) |
611 | { | 665 | { |
666 | struct omap_mcbsp *mcbsp; | ||
612 | int dma_tx_ch; | 667 | int dma_tx_ch; |
613 | int src_port = 0; | 668 | int src_port = 0; |
614 | int dest_port = 0; | 669 | int dest_port = 0; |
@@ -618,50 +673,51 @@ int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, | |||
618 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 673 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
619 | return -ENODEV; | 674 | return -ENODEV; |
620 | } | 675 | } |
676 | mcbsp = id_to_mcbsp_ptr(id); | ||
621 | 677 | ||
622 | if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", | 678 | if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX", |
623 | omap_mcbsp_tx_dma_callback, | 679 | omap_mcbsp_tx_dma_callback, |
624 | &mcbsp[id], | 680 | mcbsp, |
625 | &dma_tx_ch)) { | 681 | &dma_tx_ch)) { |
626 | dev_err(mcbsp[id].dev, " Unable to request DMA channel for " | 682 | dev_err(mcbsp->dev, " Unable to request DMA channel for " |
627 | "McBSP%d TX. Trying IRQ based TX\n", | 683 | "McBSP%d TX. Trying IRQ based TX\n", |
628 | mcbsp[id].id); | 684 | mcbsp->id); |
629 | return -EAGAIN; | 685 | return -EAGAIN; |
630 | } | 686 | } |
631 | mcbsp[id].dma_tx_lch = dma_tx_ch; | 687 | mcbsp->dma_tx_lch = dma_tx_ch; |
632 | 688 | ||
633 | dev_err(mcbsp[id].dev, "McBSP%d TX DMA on channel %d\n", mcbsp[id].id, | 689 | dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id, |
634 | dma_tx_ch); | 690 | dma_tx_ch); |
635 | 691 | ||
636 | init_completion(&(mcbsp[id].tx_dma_completion)); | 692 | init_completion(&mcbsp->tx_dma_completion); |
637 | 693 | ||
638 | if (cpu_class_is_omap1()) { | 694 | if (cpu_class_is_omap1()) { |
639 | src_port = OMAP_DMA_PORT_TIPB; | 695 | src_port = OMAP_DMA_PORT_TIPB; |
640 | dest_port = OMAP_DMA_PORT_EMIFF; | 696 | dest_port = OMAP_DMA_PORT_EMIFF; |
641 | } | 697 | } |
642 | if (cpu_class_is_omap2()) | 698 | if (cpu_class_is_omap2()) |
643 | sync_dev = mcbsp[id].dma_tx_sync; | 699 | sync_dev = mcbsp->dma_tx_sync; |
644 | 700 | ||
645 | omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch, | 701 | omap_set_dma_transfer_params(mcbsp->dma_tx_lch, |
646 | OMAP_DMA_DATA_TYPE_S16, | 702 | OMAP_DMA_DATA_TYPE_S16, |
647 | length >> 1, 1, | 703 | length >> 1, 1, |
648 | OMAP_DMA_SYNC_ELEMENT, | 704 | OMAP_DMA_SYNC_ELEMENT, |
649 | sync_dev, 0); | 705 | sync_dev, 0); |
650 | 706 | ||
651 | omap_set_dma_dest_params(mcbsp[id].dma_tx_lch, | 707 | omap_set_dma_dest_params(mcbsp->dma_tx_lch, |
652 | src_port, | 708 | src_port, |
653 | OMAP_DMA_AMODE_CONSTANT, | 709 | OMAP_DMA_AMODE_CONSTANT, |
654 | mcbsp[id].phys_base + OMAP_MCBSP_REG_DXR1, | 710 | mcbsp->phys_base + OMAP_MCBSP_REG_DXR1, |
655 | 0, 0); | 711 | 0, 0); |
656 | 712 | ||
657 | omap_set_dma_src_params(mcbsp[id].dma_tx_lch, | 713 | omap_set_dma_src_params(mcbsp->dma_tx_lch, |
658 | dest_port, | 714 | dest_port, |
659 | OMAP_DMA_AMODE_POST_INC, | 715 | OMAP_DMA_AMODE_POST_INC, |
660 | buffer, | 716 | buffer, |
661 | 0, 0); | 717 | 0, 0); |
662 | 718 | ||
663 | omap_start_dma(mcbsp[id].dma_tx_lch); | 719 | omap_start_dma(mcbsp->dma_tx_lch); |
664 | wait_for_completion(&(mcbsp[id].tx_dma_completion)); | 720 | wait_for_completion(&mcbsp->tx_dma_completion); |
665 | 721 | ||
666 | return 0; | 722 | return 0; |
667 | } | 723 | } |
@@ -670,6 +726,7 @@ EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | |||
670 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | 726 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, |
671 | unsigned int length) | 727 | unsigned int length) |
672 | { | 728 | { |
729 | struct omap_mcbsp *mcbsp; | ||
673 | int dma_rx_ch; | 730 | int dma_rx_ch; |
674 | int src_port = 0; | 731 | int src_port = 0; |
675 | int dest_port = 0; | 732 | int dest_port = 0; |
@@ -679,50 +736,51 @@ int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | |||
679 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 736 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
680 | return -ENODEV; | 737 | return -ENODEV; |
681 | } | 738 | } |
739 | mcbsp = id_to_mcbsp_ptr(id); | ||
682 | 740 | ||
683 | if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", | 741 | if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", |
684 | omap_mcbsp_rx_dma_callback, | 742 | omap_mcbsp_rx_dma_callback, |
685 | &mcbsp[id], | 743 | mcbsp, |
686 | &dma_rx_ch)) { | 744 | &dma_rx_ch)) { |
687 | dev_err(mcbsp[id].dev, "Unable to request DMA channel for " | 745 | dev_err(mcbsp->dev, "Unable to request DMA channel for " |
688 | "McBSP%d RX. Trying IRQ based RX\n", | 746 | "McBSP%d RX. Trying IRQ based RX\n", |
689 | mcbsp[id].id); | 747 | mcbsp->id); |
690 | return -EAGAIN; | 748 | return -EAGAIN; |
691 | } | 749 | } |
692 | mcbsp[id].dma_rx_lch = dma_rx_ch; | 750 | mcbsp->dma_rx_lch = dma_rx_ch; |
693 | 751 | ||
694 | dev_err(mcbsp[id].dev, "McBSP%d RX DMA on channel %d\n", mcbsp[id].id, | 752 | dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id, |
695 | dma_rx_ch); | 753 | dma_rx_ch); |
696 | 754 | ||
697 | init_completion(&(mcbsp[id].rx_dma_completion)); | 755 | init_completion(&mcbsp->rx_dma_completion); |
698 | 756 | ||
699 | if (cpu_class_is_omap1()) { | 757 | if (cpu_class_is_omap1()) { |
700 | src_port = OMAP_DMA_PORT_TIPB; | 758 | src_port = OMAP_DMA_PORT_TIPB; |
701 | dest_port = OMAP_DMA_PORT_EMIFF; | 759 | dest_port = OMAP_DMA_PORT_EMIFF; |
702 | } | 760 | } |
703 | if (cpu_class_is_omap2()) | 761 | if (cpu_class_is_omap2()) |
704 | sync_dev = mcbsp[id].dma_rx_sync; | 762 | sync_dev = mcbsp->dma_rx_sync; |
705 | 763 | ||
706 | omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch, | 764 | omap_set_dma_transfer_params(mcbsp->dma_rx_lch, |
707 | OMAP_DMA_DATA_TYPE_S16, | 765 | OMAP_DMA_DATA_TYPE_S16, |
708 | length >> 1, 1, | 766 | length >> 1, 1, |
709 | OMAP_DMA_SYNC_ELEMENT, | 767 | OMAP_DMA_SYNC_ELEMENT, |
710 | sync_dev, 0); | 768 | sync_dev, 0); |
711 | 769 | ||
712 | omap_set_dma_src_params(mcbsp[id].dma_rx_lch, | 770 | omap_set_dma_src_params(mcbsp->dma_rx_lch, |
713 | src_port, | 771 | src_port, |
714 | OMAP_DMA_AMODE_CONSTANT, | 772 | OMAP_DMA_AMODE_CONSTANT, |
715 | mcbsp[id].phys_base + OMAP_MCBSP_REG_DRR1, | 773 | mcbsp->phys_base + OMAP_MCBSP_REG_DRR1, |
716 | 0, 0); | 774 | 0, 0); |
717 | 775 | ||
718 | omap_set_dma_dest_params(mcbsp[id].dma_rx_lch, | 776 | omap_set_dma_dest_params(mcbsp->dma_rx_lch, |
719 | dest_port, | 777 | dest_port, |
720 | OMAP_DMA_AMODE_POST_INC, | 778 | OMAP_DMA_AMODE_POST_INC, |
721 | buffer, | 779 | buffer, |
722 | 0, 0); | 780 | 0, 0); |
723 | 781 | ||
724 | omap_start_dma(mcbsp[id].dma_rx_lch); | 782 | omap_start_dma(mcbsp->dma_rx_lch); |
725 | wait_for_completion(&(mcbsp[id].rx_dma_completion)); | 783 | wait_for_completion(&mcbsp->rx_dma_completion); |
726 | 784 | ||
727 | return 0; | 785 | return 0; |
728 | } | 786 | } |
@@ -737,12 +795,14 @@ EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | |||
737 | void omap_mcbsp_set_spi_mode(unsigned int id, | 795 | void omap_mcbsp_set_spi_mode(unsigned int id, |
738 | const struct omap_mcbsp_spi_cfg *spi_cfg) | 796 | const struct omap_mcbsp_spi_cfg *spi_cfg) |
739 | { | 797 | { |
798 | struct omap_mcbsp *mcbsp; | ||
740 | struct omap_mcbsp_reg_cfg mcbsp_cfg; | 799 | struct omap_mcbsp_reg_cfg mcbsp_cfg; |
741 | 800 | ||
742 | if (!omap_mcbsp_check_valid_id(id)) { | 801 | if (!omap_mcbsp_check_valid_id(id)) { |
743 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 802 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
744 | return; | 803 | return; |
745 | } | 804 | } |
805 | mcbsp = id_to_mcbsp_ptr(id); | ||
746 | 806 | ||
747 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); | 807 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); |
748 | 808 | ||
@@ -803,9 +863,10 @@ EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | |||
803 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 863 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |
804 | * 730 has only 2 McBSP, and both of them are MPU peripherals. | 864 | * 730 has only 2 McBSP, and both of them are MPU peripherals. |
805 | */ | 865 | */ |
806 | static int __init omap_mcbsp_probe(struct platform_device *pdev) | 866 | static int __devinit omap_mcbsp_probe(struct platform_device *pdev) |
807 | { | 867 | { |
808 | struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; | 868 | struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; |
869 | struct omap_mcbsp *mcbsp; | ||
809 | int id = pdev->id - 1; | 870 | int id = pdev->id - 1; |
810 | int ret = 0; | 871 | int ret = 0; |
811 | 872 | ||
@@ -818,47 +879,63 @@ static int __init omap_mcbsp_probe(struct platform_device *pdev) | |||
818 | 879 | ||
819 | dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); | 880 | dev_dbg(&pdev->dev, "Initializing OMAP McBSP (%d).\n", pdev->id); |
820 | 881 | ||
821 | if (id >= OMAP_MAX_MCBSP_COUNT) { | 882 | if (id >= omap_mcbsp_count) { |
822 | dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); | 883 | dev_err(&pdev->dev, "Invalid McBSP device id (%d)\n", id); |
823 | ret = -EINVAL; | 884 | ret = -EINVAL; |
824 | goto exit; | 885 | goto exit; |
825 | } | 886 | } |
826 | 887 | ||
827 | spin_lock_init(&mcbsp[id].lock); | 888 | mcbsp = kzalloc(sizeof(struct omap_mcbsp), GFP_KERNEL); |
828 | mcbsp[id].id = id + 1; | 889 | if (!mcbsp) { |
829 | mcbsp[id].free = 1; | 890 | ret = -ENOMEM; |
830 | mcbsp[id].dma_tx_lch = -1; | 891 | goto exit; |
831 | mcbsp[id].dma_rx_lch = -1; | 892 | } |
893 | mcbsp_ptr[id] = mcbsp; | ||
894 | |||
895 | spin_lock_init(&mcbsp->lock); | ||
896 | mcbsp->id = id + 1; | ||
897 | mcbsp->free = 1; | ||
898 | mcbsp->dma_tx_lch = -1; | ||
899 | mcbsp->dma_rx_lch = -1; | ||
900 | |||
901 | mcbsp->phys_base = pdata->phys_base; | ||
902 | mcbsp->io_base = ioremap(pdata->phys_base, SZ_4K); | ||
903 | if (!mcbsp->io_base) { | ||
904 | ret = -ENOMEM; | ||
905 | goto err_ioremap; | ||
906 | } | ||
832 | 907 | ||
833 | mcbsp[id].phys_base = pdata->phys_base; | ||
834 | mcbsp[id].io_base = pdata->virt_base; | ||
835 | /* Default I/O is IRQ based */ | 908 | /* Default I/O is IRQ based */ |
836 | mcbsp[id].io_type = OMAP_MCBSP_IRQ_IO; | 909 | mcbsp->io_type = OMAP_MCBSP_IRQ_IO; |
837 | mcbsp[id].tx_irq = pdata->tx_irq; | 910 | mcbsp->tx_irq = pdata->tx_irq; |
838 | mcbsp[id].rx_irq = pdata->rx_irq; | 911 | mcbsp->rx_irq = pdata->rx_irq; |
839 | mcbsp[id].dma_rx_sync = pdata->dma_rx_sync; | 912 | mcbsp->dma_rx_sync = pdata->dma_rx_sync; |
840 | mcbsp[id].dma_tx_sync = pdata->dma_tx_sync; | 913 | mcbsp->dma_tx_sync = pdata->dma_tx_sync; |
841 | 914 | ||
842 | if (pdata->clk_name) | 915 | if (pdata->clk_name) |
843 | mcbsp[id].clk = clk_get(&pdev->dev, pdata->clk_name); | 916 | mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name); |
844 | if (IS_ERR(mcbsp[id].clk)) { | 917 | if (IS_ERR(mcbsp->clk)) { |
845 | mcbsp[id].free = 0; | ||
846 | dev_err(&pdev->dev, | 918 | dev_err(&pdev->dev, |
847 | "Invalid clock configuration for McBSP%d.\n", | 919 | "Invalid clock configuration for McBSP%d.\n", |
848 | mcbsp[id].id); | 920 | mcbsp->id); |
849 | ret = -EINVAL; | 921 | ret = PTR_ERR(mcbsp->clk); |
850 | goto exit; | 922 | goto err_clk; |
851 | } | 923 | } |
852 | 924 | ||
853 | mcbsp[id].pdata = pdata; | 925 | mcbsp->pdata = pdata; |
854 | mcbsp[id].dev = &pdev->dev; | 926 | mcbsp->dev = &pdev->dev; |
855 | platform_set_drvdata(pdev, &mcbsp[id]); | 927 | platform_set_drvdata(pdev, mcbsp); |
928 | return 0; | ||
856 | 929 | ||
930 | err_clk: | ||
931 | iounmap(mcbsp->io_base); | ||
932 | err_ioremap: | ||
933 | mcbsp->free = 0; | ||
857 | exit: | 934 | exit: |
858 | return ret; | 935 | return ret; |
859 | } | 936 | } |
860 | 937 | ||
861 | static int omap_mcbsp_remove(struct platform_device *pdev) | 938 | static int __devexit omap_mcbsp_remove(struct platform_device *pdev) |
862 | { | 939 | { |
863 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); | 940 | struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); |
864 | 941 | ||
@@ -872,6 +949,8 @@ static int omap_mcbsp_remove(struct platform_device *pdev) | |||
872 | clk_disable(mcbsp->clk); | 949 | clk_disable(mcbsp->clk); |
873 | clk_put(mcbsp->clk); | 950 | clk_put(mcbsp->clk); |
874 | 951 | ||
952 | iounmap(mcbsp->io_base); | ||
953 | |||
875 | mcbsp->clk = NULL; | 954 | mcbsp->clk = NULL; |
876 | mcbsp->free = 0; | 955 | mcbsp->free = 0; |
877 | mcbsp->dev = NULL; | 956 | mcbsp->dev = NULL; |
@@ -882,7 +961,7 @@ static int omap_mcbsp_remove(struct platform_device *pdev) | |||
882 | 961 | ||
883 | static struct platform_driver omap_mcbsp_driver = { | 962 | static struct platform_driver omap_mcbsp_driver = { |
884 | .probe = omap_mcbsp_probe, | 963 | .probe = omap_mcbsp_probe, |
885 | .remove = omap_mcbsp_remove, | 964 | .remove = __devexit_p(omap_mcbsp_remove), |
886 | .driver = { | 965 | .driver = { |
887 | .name = "omap-mcbsp", | 966 | .name = "omap-mcbsp", |
888 | }, | 967 | }, |