only support EABI on ARM targets
[openwrt.git] / package / lqtapi / src / mps / vmmc-core.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/platform_device.h>
4 #include <linux/slab.h>
5 #include <linux/interrupt.h>
6
7 #include <linux/firmware.h>
8
9 #include <linux/delay.h>
10
11 #include <ifxmips_gptu.h>
12
13 #include <linux/tapi/tapi.h>
14
15 #include "vmmc.h"
16 #include "mps.h"
17 #include "mps-msg.h"
18 #include "mps-irq.h"
19 #include "vmmc-cmds.h"
20
21 #include "vmmc-port.h"
22 #include "vmmc-stream.h"
23 #include "vmmc-link.h"
24 #include "vmmc-coder.h"
25
26 struct vmmc_capabilities {
27 uint8_t num_alm;
28 uint8_t num_pcm;
29 uint8_t num_signal;
30 uint8_t num_coder;
31 uint8_t num_agc;
32 uint8_t num_eq;
33 uint8_t num_nlec;
34 uint8_t num_wlec;
35 uint8_t num_nwlec;
36 uint8_t num_wwlec;
37 uint8_t num_tone_generators;
38 uint8_t num_dtmf_generators;
39 uint8_t num_caller_id_senders;
40 uint8_t num_caller_id_recivers;
41 };
42
43 #define MPS_FIRMWARE_MAGIC 0xcc123456
44
45 struct vmmc_firmware_head {
46 uint32_t crc;
47 uint32_t crc_start_addr;
48 uint32_t crc_end_addr;
49 uint32_t version;
50 uint32_t encrypted;
51 uint32_t magic;
52 uint32_t mem;
53 } __packed;
54
55 #define VMMC_FIFO_UPSTREAM_CMD_BASE_ADDR 0x00
56 #define VMMC_FIFO_UPSTREAM_CMD_SIZE_ADDR 0x04
57 #define VMMC_FIFO_DOWNSTREAM_CMD_BASE_ADDR 0x08
58 #define VMMC_FIFO_DOWNSTREAM_CMD_SIZE_ADDR 0x0c
59 #define VMMC_FIFO_UPSTREAM_DATA_BASE_ADDR 0x10
60 #define VMMC_FIFO_UPSTREAM_DATA_SIZE_ADDR 0x14
61 #define VMMC_FIFO_DOWNSTREAM_DATA_BASE_ADDR 0x18
62 #define VMMC_FIFO_DOWNSTREAM_DATA_SIZE_ADDR 0x1c
63 #define VMMC_FIFO_UPSTREAM_CMD_TAIL_ADDR 0x20
64 #define VMMC_FIFO_UPSTREAM_CMD_HEAD_ADDR 0x24
65 #define VMMC_FIFO_DOWNSTREAM_CMD_TAIL_ADDR 0x28
66 #define VMMC_FIFO_DOWNSTREAM_CMD_HEAD_ADDR 0x2c
67 #define VMMC_FIFO_UPSTREAM_DATA_TAIL_ADDR 0x30
68 #define VMMC_FIFO_UPSTREAM_DATA_HEAD_ADDR 0x34
69 #define VMMC_FIFO_DOWNSTREAM_DATA_TAIL_ADDR 0x38
70 #define VMMC_FIFO_DOWNSTREAM_DATA_HEAD_ADDR 0x3c
71
72 #define VMMC_FIFO_EVENT_BASE_ADDR 0x180
73 #define VMMC_FIFO_EVENT_SIZE_ADDR 0x184
74 #define VMMC_FIFO_EVENT_TAIL_ADDR 0x188
75 #define VMMC_FIFO_EVENT_HEAD_ADDR 0x18c
76
77
78 /* Calculates the base of the fifo behind the given fifo */
79 #define VMMC_NEXT_FIFO_BASE0(_fifo) \
80 (VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
81 #define VMMC_NEXT_FIFO_BASE1(_fifo) \
82 (VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
83 #define VMMC_NEXT_FIFO_BASE2(_fifo) \
84 (VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
85
86 /* Fifo sizes */
87 #define VMMC_FIFO_UPSTREAM_CMD_SIZE 64
88 #define VMMC_FIFO_DOWNSTREAM_CMD_SIZE 64
89 #define VMMC_FIFO_UPSTREAM_DATA_SIZE 64
90 #define VMMC_FIFO_DOWNSTREAM_DATA_SIZE 128
91 #define VMMC_FIFO_EVENT_SIZE 64
92
93 /* Fifo addresses */
94 #define VMMC_FIFO_UPSTREAM_CMD_BASE 0x40
95 #define VMMC_FIFO_DOWNSTREAM_CMD_BASE VMMC_NEXT_FIFO_BASE0(UPSTREAM_CMD)
96 #define VMMC_FIFO_UPSTREAM_DATA_BASE VMMC_NEXT_FIFO_BASE1(DOWNSTREAM_CMD)
97 #define VMMC_FIFO_DOWNSTREAM_DATA_BASE VMMC_NEXT_FIFO_BASE2(UPSTREAM_DATA)
98 #define VMMC_FIFO_EVENT_BASE 0x190
99
100 #define VMMC_DECLARE_FIFO_CONFIG(_name, _fifo) \
101 static const struct mps_fifo_config _name = { \
102 .tail_addr = VMMC_FIFO_ ## _fifo ## _TAIL_ADDR, \
103 .head_addr = VMMC_FIFO_ ## _fifo ## _HEAD_ADDR, \
104 .base_addr = VMMC_FIFO_ ## _fifo ## _BASE_ADDR, \
105 .size_addr = VMMC_FIFO_ ## _fifo ## _SIZE_ADDR, \
106 .base = VMMC_FIFO_ ## _fifo ## _BASE, \
107 .size = VMMC_FIFO_ ## _fifo ## _SIZE, \
108 }
109
110 VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_cmd, UPSTREAM_CMD);
111 VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_cmd, DOWNSTREAM_CMD);
112 VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_data, UPSTREAM_DATA);
113 VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_data, DOWNSTREAM_DATA);
114 VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_event, EVENT);
115
116 static void vmmc_setup_fifos(struct vmmc *vmmc)
117 {
118 mps_configure_mailbox(vmmc->mps, &vmmc->mbox_cmd,
119 &vmmc_fifo_config_upstream_cmd, &vmmc_fifo_config_downstream_cmd);
120 mps_configure_mailbox(vmmc->mps, &vmmc->mbox_data,
121 &vmmc_fifo_config_upstream_data, &vmmc_fifo_config_downstream_data);
122
123 mps_configure_fifo(vmmc->mps, &vmmc->fifo_event, &vmmc_fifo_config_event);
124 }
125
126 static uint32_t cram_data[] = {
127 0x00200000, 0x00008e59, 0x165235cd, 0x17e2f141, 0xe3eef301, 0x0a431281,
128 0x04fdf20d, 0x7fe363d5, 0xfd4b7333, 0x7ffffd44, 0xfcf80298, 0xfecd00c9,
129 0xff900042, 0xfff70003, 0x000923b7, 0xe92a354d, 0xc8981f44, 0x9c0f1257,
130 0x26aacf33, 0x27db9836, 0x10586f5b, 0x9c167d2d, 0x94b679a7, 0x8c227660,
131 0x83fa7491, 0x7ce0826a, 0x7ff87ff4, 0x296b4e22, 0x76e67fff, 0x008ffc04,
132 0x02cbfb36, 0x026afeba, 0x009effc3, 0x0013fffd, 0x23b7e92a, 0x354dc898,
133 0x1f449c0f, 0x125726aa, 0xcf3327db, 0x98361058, 0x74bc93d6, 0x7ebc8f61,
134 0x7d068986, 0x7b46833b, 0x7a3b7f00, 0x287a47b1, 0x05800367, 0x20ae2715,
135 0x0fb5da12, 0x1935f53b, 0x01230240, 0xfc717f00, 0x2000d346,
136 };
137
138 static void vmmc_push_data_paket(struct vmmc *vmmc, int type, unsigned int chan,
139 void __iomem *addr, size_t len)
140 {
141 uint32_t data[3];
142
143 data[0] = VMMC_VOICE_DATA(type, chan, 8);
144 data[1] = CPHYSADDR(addr);
145 data[2] = len;
146
147 mps_fifo_in(&vmmc->mbox_data.downstream, data, 3);
148 }
149
150 static struct sk_buff *vmmc_alloc_data_paket(struct vmmc *vmmc)
151 {
152 struct sk_buff *skb;
153
154 skb = alloc_skb(512, GFP_KERNEL);
155
156 skb_queue_tail(&vmmc->recv_queue, skb);
157
158 return skb;
159 }
160
161 static void vmmc_provide_paket(struct vmmc *vmmc)
162 {
163 struct sk_buff *skb = vmmc_alloc_data_paket(vmmc);
164 vmmc_push_data_paket(vmmc, CMD_ADDRESS_PACKET, 0, skb->data, skb->len);
165 }
166
167 static void vmmc_recv_paket(struct vmmc *vmmc, unsigned int chan, void __iomem *addr, size_t len)
168 {
169 struct sk_buff *skb;
170 struct sk_buff *tmp;
171
172 skb_queue_walk_safe(&vmmc->recv_queue, skb, tmp) {
173 if (skb->data == addr)
174 break;
175 }
176
177 if (skb == (struct sk_buff *)(&vmmc->recv_queue)) {
178 printk("AHHHH\n");
179 return;
180 }
181
182 dma_cache_inv((u32)addr, len);
183 skb_unlink(skb, &vmmc->recv_queue);
184
185 if (!vmmc->coder[chan].stream) {
186 kfree_skb(skb);
187 return;
188 }
189
190 skb_put(skb, len);
191 tapi_stream_recv(&vmmc->tdev, vmmc->coder[chan].stream, skb);
192 }
193
194 void vmmc_send_paket(struct vmmc *vmmc, unsigned int chan, struct sk_buff *skb)
195 {
196 skb_queue_tail(&vmmc->send_queue, skb);
197
198 dma_cache_wback((u32)skb->data, skb->len);
199 vmmc_push_data_paket(vmmc, CMD_RTP_VOICE_DATA_PACKET, chan, skb->data,
200 skb->len);
201 }
202
203 static void vmmc_free_paket(struct vmmc *vmmc, void __iomem *addr, size_t len)
204 {
205 struct sk_buff *skb;
206 struct sk_buff *tmp;
207
208 skb_queue_walk_safe(&vmmc->send_queue, skb, tmp) {
209 if (skb->data == addr)
210 break;
211 }
212
213 if (skb == (struct sk_buff *)(&vmmc->send_queue)) {
214 printk("AHHHH\n");
215 } else {
216 skb_unlink(skb, &vmmc->send_queue);
217 kfree_skb(skb);
218 }
219 }
220
221
222 static void vmmc_write_cram_data(struct vmmc *vmmc, unsigned int id,
223 uint32_t *data, size_t length)
224 {
225 size_t transfer_length;
226 size_t offset = 0;
227 uint32_t cmd;
228
229 length *= 4;
230 offset = 0x5;
231
232 while (length) {
233 transfer_length = length > 56 ? 56 : length;
234 cmd = VMMC_CMD_ALM_COEF(id, offset, transfer_length);
235 vmmc_command_write(vmmc, cmd, data);
236
237 data += transfer_length >> 2;
238 offset += transfer_length >> 1;
239 length -= transfer_length;
240 }
241 }
242
243 int vmmc_command_read(struct vmmc *vmmc, uint32_t cmd, uint32_t *result)
244 {
245 struct mps_mailbox *mbox = &vmmc->mbox_cmd;
246
247 INIT_COMPLETION(vmmc->cmd_completion);
248
249 mps_fifo_in(&mbox->downstream, &cmd, 1);
250
251 wait_for_completion(&vmmc->cmd_completion);
252
253 mps_fifo_out(&mbox->upstream, result, 1);
254 mps_fifo_out(&mbox->upstream, result, (*result & 0xff) / 4);
255
256 return 0;
257 }
258
259 int vmmc_command_write(struct vmmc *vmmc, uint32_t cmd,
260 const uint32_t *data)
261 {
262 struct mps_mailbox *mbox = &vmmc->mbox_cmd;
263 /* int i;
264
265 printk("cmd: %x\n", cmd);
266 for (i = 0; i < DIV_ROUND_UP((cmd & 0xff), 4); ++i) {
267 printk("data[%d] = %x\n", i, data[i]);
268 }
269 */
270 while (mps_fifo_len(&mbox->downstream) < (cmd & 0xff) + 4)
271 mdelay(100);
272
273 mps_fifo_in(&mbox->downstream, &cmd, 1);
274 mps_fifo_in(&mbox->downstream, data, DIV_ROUND_UP((cmd & 0xff), 4));
275
276 mdelay(100);
277
278 return 0;
279 }
280
281 static int vmmc_modules_sync(struct tapi_device *tapi)
282 {
283 struct vmmc *vmmc = tdev_to_vmmc(tapi);
284 struct vmmc_module *module;
285
286 list_for_each_entry(module, &vmmc->modules, head)
287 vmmc_module_sync(module);
288
289 return 0;
290 }
291
292 static const struct tapi_ops vmmc_tapi_ops = {
293 .send_dtmf_event = vmmc_port_send_dtmf_event,
294 .ring = vmmc_port_ring,
295
296 .sync = vmmc_modules_sync,
297
298 .stream_alloc = vmmc_stream_alloc,
299 .stream_free = vmmc_stream_free,
300 .stream_send = vmmc_stream_send,
301
302 .link_alloc = vmmc_tapi_link_alloc,
303 .link_free = vmmc_tapi_link_free,
304 .link_enable = vmmc_tapi_link_enable,
305 .link_disable = vmmc_tapi_link_disable,
306 };
307
308 static void setup_alm(struct vmmc *vmmc)
309 {
310 int i;
311
312 vmmc->tdev.ports = kcalloc(2, sizeof(*vmmc->tdev.ports), GFP_KERNEL);
313 vmmc->ports = kcalloc(2, sizeof(*vmmc->ports), GFP_KERNEL);
314
315 for (i = 0; i < 2; ++i)
316 vmmc_port_init(vmmc, &vmmc->ports[i], &vmmc->tdev.ports[i], i);
317
318 skb_queue_head_init(&vmmc->send_queue);
319 skb_queue_head_init(&vmmc->recv_queue);
320
321 for (i = 0; i < 10; ++i)
322 vmmc_provide_paket(vmmc);
323
324 vmmc->tdev.num_ports = 2;
325 vmmc->tdev.ops = &vmmc_tapi_ops;
326 tapi_device_register(&vmmc->tdev, "vmmc", vmmc->dev);
327 }
328
329 static void vmmc_init_timer(struct vmmc *vmmc)
330 {
331 unsigned int timer;
332 unsigned int timer_flags;
333 int ret;
334 unsigned long loops, count;
335
336 timer = TIMER1B;
337
338 timer_flags =
339 TIMER_FLAG_16BIT | TIMER_FLAG_COUNTER | TIMER_FLAG_CYCLIC |
340 TIMER_FLAG_DOWN | TIMER_FLAG_FALL_EDGE | TIMER_FLAG_SYNC |
341 TIMER_FLAG_CALLBACK_IN_IRQ;
342 ret = ifxmips_request_timer (timer, timer_flags, 1, 0, 0);
343 if (ret < 0) {
344 printk("FAILED TO INIT TIMER\n");
345 return;
346 }
347 ret = ifxmips_start_timer (timer, 0);
348 if (ret < 0) {
349 printk("FAILED TO START TIMER\n");
350 return;
351 }
352 do
353 {
354 loops++;
355 ifxmips_get_count_value(timer, &count);
356 } while (count);
357
358 *((volatile uint32_t *) (KSEG1 + 0x1e100a00 + 0x0014)) = 0x000005c5;
359 }
360
361 static void vmmc_free_timer(struct vmmc *vmmc)
362 {
363 ifxmips_free_timer(TIMER1B);
364 }
365
366 static void vmmc_get_capabilities(struct vmmc *vmmc)
367 {
368 uint32_t data[10];
369 uint8_t len;
370
371 vmmc_command_read(vmmc,
372 MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, sizeof(uint32_t)), data);
373
374 len = ((data[0] >> 16) & 0xff) - sizeof(uint32_t);
375
376 if (len > sizeof(data))
377 len = sizeof(data);
378
379 vmmc_command_read(vmmc,
380 MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, len), data);
381
382 len /= 4;
383
384 /* for (;len > 0; --len) {
385 printk("fw cap(%d): %.2x\n", 10-len, data[10-len]);
386 }
387 */
388 setup_alm(vmmc);
389 }
390
391 static void vmmc_get_firmware_version(struct vmmc *vmmc)
392 {
393 uint32_t data[1];
394
395 vmmc_command_read(vmmc, MPS_CMD_GET_VERSION, data);
396
397 printk("firmware version: %x\n", *data);
398
399 vmmc_get_capabilities(vmmc);
400 }
401
402 static irqreturn_t vmmc_firmware_loaded_irq(int irq, void *devid)
403 {
404 struct vmmc *vmmc = devid;
405 complete(&vmmc->firmware_loaded_completion);
406 printk("Firmware loaded irq\n");
407
408 return IRQ_HANDLED;
409 }
410
411 static irqreturn_t vmmc_cmd_error_irq(int irq, void *devid)
412 {
413 /* struct vmmc *vmmc = devid;*/
414
415 printk("cmd error!!!!\n");
416
417 return IRQ_HANDLED;
418 }
419
420 static irqreturn_t vmmc_recv_ov_irq(int irq, void *devid)
421 {
422 struct vmmc *vmmc = devid;
423 uint32_t data[2] = {
424 VMMC_CMD_SERR_ACK(0),
425 VMMC_CMD_SERR_ACK_DATA1(1)
426 };
427 uint32_t voice_data[64];
428
429 return IRQ_HANDLED;
430
431 mps_fifo_in(&vmmc->mbox_cmd.downstream, data, 2);
432 mps_fifo_out(&vmmc->mbox_data.upstream, voice_data, 15);
433
434 printk("recv overflow: %x\n", voice_data[0]);
435
436 return IRQ_HANDLED;
437 }
438
439 static irqreturn_t vmmc_event_fifo_irq(int irq, void *devid)
440 {
441 struct vmmc *vmmc = devid;
442 uint32_t event, event_id;
443 uint32_t data = 0;
444 unsigned int chan;
445
446 mps_fifo_out(&vmmc->fifo_event, &event, 1);
447
448 event_id = event & VMMC_EVENT_ID_MASK;
449 chan = VMMC_MSG_GET_CHAN(event);
450
451 if (event & 0xff)
452 mps_fifo_out(&vmmc->fifo_event, &data, 1);
453
454 switch (event_id) {
455 case VMMC_EVENT_HOOK_ID:
456 vmmc_alm_hook_event_handler(vmmc, chan, data);
457 break;
458 case VMMC_EVENT_DTMF_ID:
459 vmmc_sig_dtmf_event_handler(vmmc, chan, data);
460 break;
461 default:
462 printk("Ein unbekanntes Event: %x %x\n", event, data);
463 break;
464 }
465
466 return IRQ_HANDLED;
467 }
468
469 static irqreturn_t vmmc_mbox_data_irq_handler(int irq, void *devid)
470 {
471 struct vmmc *vmmc = devid;
472 struct mps_mailbox *mbox = &vmmc->mbox_data;
473 unsigned int count, type, chan;
474 uint32_t data[2];
475 void __iomem *addr;
476 size_t len;
477
478 mps_fifo_out(&mbox->upstream, data, 1);
479
480 count = (data[0] & 0xff) / 8;
481 type = (data[0] >> 24) & 0xff;
482 chan = (data[0] >> 16) & 0xff;
483
484 while (count) {
485 mps_fifo_out(&mbox->upstream, data, 2);
486
487 addr = (void __iomem *)CKSEG0ADDR(data[0]);
488 len = data[1];
489
490 switch (type) {
491 case CMD_ADDRESS_PACKET:
492 vmmc_free_paket(vmmc, addr, len);
493 break;
494 case CMD_RTP_VOICE_DATA_PACKET:
495 vmmc_provide_paket(vmmc);
496 vmmc_recv_paket(vmmc, chan, addr, len);
497 break;
498 }
499 --count;
500 }
501
502 return IRQ_HANDLED;
503 }
504
505 static irqreturn_t vmmc_mbox_cmd_irq_handler(int irq, void *devid)
506 {
507 struct vmmc *vmmc = devid;
508
509 complete(&vmmc->cmd_completion);
510
511 return IRQ_HANDLED;
512 }
513
514 static void vmmc_load_firmware(const struct firmware *fw, void *context)
515 {
516 struct vmmc *vmmc = context;
517 struct vmmc_firmware_head *fw_head;
518 size_t tail_size;
519 enum mps_boot_config config;
520
521 if (!fw) {
522 printk("failed to load tapi firmware\n");
523 // request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", vmmc->dev,
524 // GFP_KERNEL, vmmc, vmmc_load_firmware);
525 return;
526 }
527
528 if (fw->size < sizeof(*fw_head))
529 return;
530
531 fw_head = (struct vmmc_firmware_head *)((uint8_t *)fw->data + fw->size - sizeof(*fw_head));
532
533 if (fw_head->magic != MPS_FIRMWARE_MAGIC) {
534 config = MPS_BOOT_LEGACY;
535 tail_size = sizeof(uint32_t);
536 } else {
537 config = MPS_BOOT_ENCRYPTED;
538 tail_size = sizeof(*fw_head) - sizeof(uint32_t);
539 }
540
541 vmmc_setup_fifos(vmmc);
542 init_completion(&vmmc->firmware_loaded_completion);
543 mps_load_firmware(vmmc->mps, fw->data, fw->size - tail_size, config);
544 wait_for_completion_timeout(&vmmc->firmware_loaded_completion, 5*HZ);
545 vmmc_init_timer(vmmc);
546 vmmc_write_cram_data(vmmc, 0, cram_data, ARRAY_SIZE(cram_data));
547 vmmc_write_cram_data(vmmc, 1, cram_data, ARRAY_SIZE(cram_data));
548 vmmc_get_firmware_version(vmmc);
549 vmmc_init_coders(vmmc);
550 }
551
552 static int vmmc_request_irqs(struct vmmc *vmmc)
553 {
554 int ret;
555
556 ret = request_irq(vmmc->irq_fw_loaded, vmmc_firmware_loaded_irq, 0, "vmmc fw loaded", vmmc);
557 ret = request_irq(vmmc->irq_event_fifo, vmmc_event_fifo_irq, 0, "vmmc event fifo", vmmc);
558 ret = request_irq(vmmc->irq_cmd_error, vmmc_cmd_error_irq, 0,
559 "cmd error irq", vmmc);
560 ret = request_irq(MPS_IRQ_RCV_OVERFLOW, vmmc_recv_ov_irq, 0,
561 "recv_ov irq", vmmc);
562
563 ret = request_irq(vmmc->irq_mbox_cmd, vmmc_mbox_cmd_irq_handler, 0,
564 "vmmc cmd mailbox irq", vmmc);
565
566 ret = request_irq(vmmc->irq_mbox_data, vmmc_mbox_data_irq_handler, 0,
567 "vmmc data mailbox irq", vmmc);
568
569 return ret;
570 }
571
572 static int __devinit vmmc_probe(struct platform_device *pdev)
573 {
574 struct vmmc *vmmc;
575 int ret = 0;
576
577 vmmc = kzalloc(sizeof(*vmmc), GFP_KERNEL);
578
579 if (!vmmc)
580 return -ENOMEM;
581
582 vmmc->dev = &pdev->dev;
583 vmmc->mps = device_to_mps(pdev->dev.parent);
584
585 if (!vmmc->mps) {
586 goto err_free;
587 ret = -EBUSY;
588 }
589
590 INIT_LIST_HEAD(&vmmc->modules);
591 init_completion(&vmmc->cmd_completion);
592
593 vmmc->irq_fw_loaded = MPS_IRQ_DOWNLOAD_DONE;
594 vmmc->irq_mbox_cmd = MPS_IRQ_CMD_UPSTREAM;
595 vmmc->irq_mbox_data = MPS_IRQ_DATA_UPSTREAM;
596 vmmc->irq_event_fifo = MPS_IRQ_EVENT;
597 vmmc->irq_cmd_error = MPS_IRQ_CMD_ERROR;
598
599 platform_set_drvdata(pdev, vmmc);
600
601 vmmc_request_irqs(vmmc);
602
603 request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", &pdev->dev,
604 GFP_KERNEL, vmmc, vmmc_load_firmware);
605
606 return 0;
607
608 err_free:
609 kfree(vmmc);
610
611 return ret;
612 }
613
614 static int __devexit vmmc_remove(struct platform_device *pdev)
615 {
616 struct vmmc *vmmc = platform_get_drvdata(pdev);
617 vmmc_free_timer(vmmc);
618
619 tapi_device_unregister(&vmmc->tdev);
620
621 return 0;
622 }
623
624 static struct platform_driver vmmc_driver = {
625 .probe = vmmc_probe,
626 .remove = __devexit_p(vmmc_remove),
627 .driver = {
628 .name = "vmmc",
629 .owner = THIS_MODULE
630 },
631 };
632
633 static int __init vmmc_init(void)
634 {
635 return platform_driver_register(&vmmc_driver);
636 }
637 module_init(vmmc_init);
638
639 static void __exit vmmc_exit(void)
640 {
641 platform_driver_unregister(&vmmc_driver);
642 }
643 module_exit(vmmc_exit);
644
645 MODULE_LICENSE("GPL");
646 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
This page took 0.104173 seconds and 5 git commands to generate.