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>
7 #include <linux/firmware.h>
9 #include <linux/delay.h>
11 #include <ifxmips_gptu.h>
13 #include <linux/tapi/tapi.h>
19 #include "vmmc-cmds.h"
21 #include "vmmc-port.h"
22 #include "vmmc-stream.h"
23 #include "vmmc-link.h"
24 #include "vmmc-coder.h"
26 struct vmmc_capabilities
{
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
;
43 #define MPS_FIRMWARE_MAGIC 0xcc123456
45 struct vmmc_firmware_head
{
47 uint32_t crc_start_addr
;
48 uint32_t crc_end_addr
;
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
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
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)
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
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
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, \
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
);
116 static void vmmc_setup_fifos(struct vmmc
*vmmc
)
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
);
123 mps_configure_fifo(vmmc
->mps
, &vmmc
->fifo_event
, &vmmc_fifo_config_event
);
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,
138 static void vmmc_push_data_paket(struct vmmc
*vmmc
, int type
, unsigned int chan
,
139 void __iomem
*addr
, size_t len
)
143 data
[0] = VMMC_VOICE_DATA(type
, chan
, 8);
144 data
[1] = CPHYSADDR(addr
);
147 mps_fifo_in(&vmmc
->mbox_data
.downstream
, data
, 3);
150 static struct sk_buff
*vmmc_alloc_data_paket(struct vmmc
*vmmc
)
154 skb
= alloc_skb(512, GFP_KERNEL
);
156 skb_queue_tail(&vmmc
->recv_queue
, skb
);
161 static void vmmc_provide_paket(struct vmmc
*vmmc
)
163 struct sk_buff
*skb
= vmmc_alloc_data_paket(vmmc
);
164 vmmc_push_data_paket(vmmc
, CMD_ADDRESS_PACKET
, 0, skb
->data
, skb
->len
);
167 static void vmmc_recv_paket(struct vmmc
*vmmc
, unsigned int chan
, void __iomem
*addr
, size_t len
)
172 skb_queue_walk_safe(&vmmc
->recv_queue
, skb
, tmp
) {
173 if (skb
->data
== addr
)
177 if (skb
== (struct sk_buff
*)(&vmmc
->recv_queue
)) {
182 dma_cache_inv((u32
)addr
, len
);
183 skb_unlink(skb
, &vmmc
->recv_queue
);
185 if (!vmmc
->coder
[chan
].stream
) {
191 tapi_stream_recv(&vmmc
->tdev
, vmmc
->coder
[chan
].stream
, skb
);
194 void vmmc_send_paket(struct vmmc
*vmmc
, unsigned int chan
, struct sk_buff
*skb
)
196 skb_queue_tail(&vmmc
->send_queue
, skb
);
198 dma_cache_wback((u32
)skb
->data
, skb
->len
);
199 vmmc_push_data_paket(vmmc
, CMD_RTP_VOICE_DATA_PACKET
, chan
, skb
->data
,
203 static void vmmc_free_paket(struct vmmc
*vmmc
, void __iomem
*addr
, size_t len
)
208 skb_queue_walk_safe(&vmmc
->send_queue
, skb
, tmp
) {
209 if (skb
->data
== addr
)
213 if (skb
== (struct sk_buff
*)(&vmmc
->send_queue
)) {
216 skb_unlink(skb
, &vmmc
->send_queue
);
222 static void vmmc_write_cram_data(struct vmmc
*vmmc
, unsigned int id
,
223 uint32_t *data
, size_t length
)
225 size_t transfer_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
);
237 data
+= transfer_length
>> 2;
238 offset
+= transfer_length
>> 1;
239 length
-= transfer_length
;
243 int vmmc_command_read(struct vmmc
*vmmc
, uint32_t cmd
, uint32_t *result
)
245 struct mps_mailbox
*mbox
= &vmmc
->mbox_cmd
;
247 INIT_COMPLETION(vmmc
->cmd_completion
);
249 mps_fifo_in(&mbox
->downstream
, &cmd
, 1);
251 wait_for_completion(&vmmc
->cmd_completion
);
253 mps_fifo_out(&mbox
->upstream
, result
, 1);
254 mps_fifo_out(&mbox
->upstream
, result
, (*result
& 0xff) / 4);
259 int vmmc_command_write(struct vmmc
*vmmc
, uint32_t cmd
,
260 const uint32_t *data
)
262 struct mps_mailbox
*mbox
= &vmmc
->mbox_cmd
;
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]);
270 while (mps_fifo_len(&mbox
->downstream
) < (cmd
& 0xff) + 4)
273 mps_fifo_in(&mbox
->downstream
, &cmd
, 1);
274 mps_fifo_in(&mbox
->downstream
, data
, DIV_ROUND_UP((cmd
& 0xff), 4));
281 static int vmmc_modules_sync(struct tapi_device
*tapi
)
283 struct vmmc
*vmmc
= tdev_to_vmmc(tapi
);
284 struct vmmc_module
*module
;
286 list_for_each_entry(module
, &vmmc
->modules
, head
)
287 vmmc_module_sync(module
);
292 static const struct tapi_ops vmmc_tapi_ops
= {
293 .send_dtmf_event
= vmmc_port_send_dtmf_event
,
294 .ring
= vmmc_port_ring
,
296 .sync
= vmmc_modules_sync
,
298 .stream_alloc
= vmmc_stream_alloc
,
299 .stream_free
= vmmc_stream_free
,
300 .stream_send
= vmmc_stream_send
,
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
,
308 static void setup_alm(struct vmmc
*vmmc
)
312 vmmc
->tdev
.ports
= kcalloc(2, sizeof(*vmmc
->tdev
.ports
), GFP_KERNEL
);
313 vmmc
->ports
= kcalloc(2, sizeof(*vmmc
->ports
), GFP_KERNEL
);
315 for (i
= 0; i
< 2; ++i
)
316 vmmc_port_init(vmmc
, &vmmc
->ports
[i
], &vmmc
->tdev
.ports
[i
], i
);
318 skb_queue_head_init(&vmmc
->send_queue
);
319 skb_queue_head_init(&vmmc
->recv_queue
);
321 for (i
= 0; i
< 10; ++i
)
322 vmmc_provide_paket(vmmc
);
324 vmmc
->tdev
.num_ports
= 2;
325 vmmc
->tdev
.ops
= &vmmc_tapi_ops
;
326 tapi_device_register(&vmmc
->tdev
, "vmmc", vmmc
->dev
);
329 static void vmmc_init_timer(struct vmmc
*vmmc
)
332 unsigned int timer_flags
;
334 unsigned long loops
, count
;
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);
344 printk("FAILED TO INIT TIMER\n");
347 ret
= ifxmips_start_timer (timer
, 0);
349 printk("FAILED TO START TIMER\n");
355 ifxmips_get_count_value(timer
, &count
);
358 *((volatile uint32_t *) (KSEG1
+ 0x1e100a00 + 0x0014)) = 0x000005c5;
361 static void vmmc_free_timer(struct vmmc
*vmmc
)
363 ifxmips_free_timer(TIMER1B
);
366 static void vmmc_get_capabilities(struct vmmc
*vmmc
)
371 vmmc_command_read(vmmc
,
372 MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD
, sizeof(uint32_t)), data
);
374 len
= ((data
[0] >> 16) & 0xff) - sizeof(uint32_t);
376 if (len
> sizeof(data
))
379 vmmc_command_read(vmmc
,
380 MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD
, len
), data
);
384 /* for (;len > 0; --len) {
385 printk("fw cap(%d): %.2x\n", 10-len, data[10-len]);
391 static void vmmc_get_firmware_version(struct vmmc
*vmmc
)
395 vmmc_command_read(vmmc
, MPS_CMD_GET_VERSION
, data
);
397 printk("firmware version: %x\n", *data
);
399 vmmc_get_capabilities(vmmc
);
402 static irqreturn_t
vmmc_firmware_loaded_irq(int irq
, void *devid
)
404 struct vmmc
*vmmc
= devid
;
405 complete(&vmmc
->firmware_loaded_completion
);
406 printk("Firmware loaded irq\n");
411 static irqreturn_t
vmmc_cmd_error_irq(int irq
, void *devid
)
413 /* struct vmmc *vmmc = devid;*/
415 printk("cmd error!!!!\n");
420 static irqreturn_t
vmmc_recv_ov_irq(int irq
, void *devid
)
422 struct vmmc
*vmmc
= devid
;
424 VMMC_CMD_SERR_ACK(0),
425 VMMC_CMD_SERR_ACK_DATA1(1)
427 uint32_t voice_data
[64];
431 mps_fifo_in(&vmmc
->mbox_cmd
.downstream
, data
, 2);
432 mps_fifo_out(&vmmc
->mbox_data
.upstream
, voice_data
, 15);
434 printk("recv overflow: %x\n", voice_data
[0]);
439 static irqreturn_t
vmmc_event_fifo_irq(int irq
, void *devid
)
441 struct vmmc
*vmmc
= devid
;
442 uint32_t event
, event_id
;
446 mps_fifo_out(&vmmc
->fifo_event
, &event
, 1);
448 event_id
= event
& VMMC_EVENT_ID_MASK
;
449 chan
= VMMC_MSG_GET_CHAN(event
);
452 mps_fifo_out(&vmmc
->fifo_event
, &data
, 1);
455 case VMMC_EVENT_HOOK_ID
:
456 vmmc_alm_hook_event_handler(vmmc
, chan
, data
);
458 case VMMC_EVENT_DTMF_ID
:
459 vmmc_sig_dtmf_event_handler(vmmc
, chan
, data
);
462 printk("Ein unbekanntes Event: %x %x\n", event
, data
);
469 static irqreturn_t
vmmc_mbox_data_irq_handler(int irq
, void *devid
)
471 struct vmmc
*vmmc
= devid
;
472 struct mps_mailbox
*mbox
= &vmmc
->mbox_data
;
473 unsigned int count
, type
, chan
;
478 mps_fifo_out(&mbox
->upstream
, data
, 1);
480 count
= (data
[0] & 0xff) / 8;
481 type
= (data
[0] >> 24) & 0xff;
482 chan
= (data
[0] >> 16) & 0xff;
485 mps_fifo_out(&mbox
->upstream
, data
, 2);
487 addr
= (void __iomem
*)CKSEG0ADDR(data
[0]);
491 case CMD_ADDRESS_PACKET
:
492 vmmc_free_paket(vmmc
, addr
, len
);
494 case CMD_RTP_VOICE_DATA_PACKET
:
495 vmmc_provide_paket(vmmc
);
496 vmmc_recv_paket(vmmc
, chan
, addr
, len
);
505 static irqreturn_t
vmmc_mbox_cmd_irq_handler(int irq
, void *devid
)
507 struct vmmc
*vmmc
= devid
;
509 complete(&vmmc
->cmd_completion
);
514 static void vmmc_load_firmware(const struct firmware
*fw
, void *context
)
516 struct vmmc
*vmmc
= context
;
517 struct vmmc_firmware_head
*fw_head
;
519 enum mps_boot_config config
;
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);
528 if (fw
->size
< sizeof(*fw_head
))
531 fw_head
= (struct vmmc_firmware_head
*)((uint8_t *)fw
->data
+ fw
->size
- sizeof(*fw_head
));
533 if (fw_head
->magic
!= MPS_FIRMWARE_MAGIC
) {
534 config
= MPS_BOOT_LEGACY
;
535 tail_size
= sizeof(uint32_t);
537 config
= MPS_BOOT_ENCRYPTED
;
538 tail_size
= sizeof(*fw_head
) - sizeof(uint32_t);
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
);
552 static int vmmc_request_irqs(struct vmmc
*vmmc
)
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
);
563 ret
= request_irq(vmmc
->irq_mbox_cmd
, vmmc_mbox_cmd_irq_handler
, 0,
564 "vmmc cmd mailbox irq", vmmc
);
566 ret
= request_irq(vmmc
->irq_mbox_data
, vmmc_mbox_data_irq_handler
, 0,
567 "vmmc data mailbox irq", vmmc
);
572 static int __devinit
vmmc_probe(struct platform_device
*pdev
)
577 vmmc
= kzalloc(sizeof(*vmmc
), GFP_KERNEL
);
582 vmmc
->dev
= &pdev
->dev
;
583 vmmc
->mps
= device_to_mps(pdev
->dev
.parent
);
590 INIT_LIST_HEAD(&vmmc
->modules
);
591 init_completion(&vmmc
->cmd_completion
);
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
;
599 platform_set_drvdata(pdev
, vmmc
);
601 vmmc_request_irqs(vmmc
);
603 request_firmware_nowait(THIS_MODULE
, 1, "danube_firmware.bin", &pdev
->dev
,
604 GFP_KERNEL
, vmmc
, vmmc_load_firmware
);
614 static int __devexit
vmmc_remove(struct platform_device
*pdev
)
616 struct vmmc
*vmmc
= platform_get_drvdata(pdev
);
617 vmmc_free_timer(vmmc
);
619 tapi_device_unregister(&vmmc
->tdev
);
624 static struct platform_driver vmmc_driver
= {
626 .remove
= __devexit_p(vmmc_remove
),
633 static int __init
vmmc_init(void)
635 return platform_driver_register(&vmmc_driver
);
637 module_init(vmmc_init
);
639 static void __exit
vmmc_exit(void)
641 platform_driver_unregister(&vmmc_driver
);
643 module_exit(vmmc_exit
);
645 MODULE_LICENSE("GPL");
646 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");