3 * sep_main_mod.c - Security Processor Driver main group of functions
5 * Copyright(c) 2009 Intel Corporation. All rights reserved.
6 * Copyright(c) 2009 Discretix. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along with
19 * this program; if not, write to the Free Software Foundation, Inc., 59
20 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * Mark Allyn mark.a.allyn@intel.com
28 * 2009.06.26 Initial publish
32 #include <linux/init.h>
33 #include <linux/module.h>
35 #include <linux/cdev.h>
36 #include <linux/kdev_t.h>
37 #include <linux/mutex.h>
39 #include <linux/poll.h>
40 #include <linux/wait.h>
41 #include <asm/ioctl.h>
42 #include <linux/ioport.h>
44 #include <linux/interrupt.h>
45 #include <linux/pagemap.h>
46 #include <asm/cacheflush.h>
47 #include "sep_driver_hw_defs.h"
48 #include "sep_driver_config.h"
49 #include "sep_driver_api.h"
50 #include "sep_driver_ext_api.h"
53 /*----------------------------------------
55 -----------------------------------------*/
58 #define INT_MODULE_PARM(n, v) int n = v; module_param(n, int, 0)
60 /*--------------------------------------
62 -----------------------------------------*/
66 /*--------------------------------------------
68 --------------------------------------------*/
70 /* debug messages level */
71 INT_MODULE_PARM(sepDebug, 0x0);
72 MODULE_PARM_DESC(sepDebug, "Flag to enable SEP debug messages");
74 /* major and minor device numbers */
75 static dev_t g_sep_device_number;
77 /* the files operations structure of the driver */
78 static struct file_operations g_sep_fops;
80 /* cdev struct of the driver */
81 static struct cdev g_sep_cdev;
84 mutex for the access to the internals of the sep driver
86 static DEFINE_MUTEX(sep_mutex);
89 /* wait queue head (event) of the driver */
90 static DECLARE_WAIT_QUEUE_HEAD(g_sep_event);
94 /*------------------------------------------------
96 ---------------------------------------------------*/
99 interrupt handler function
101 irqreturn_t sep_inthandler(int irq, void *dev_id);
104 this function registers the driver to the file system
106 static int sep_register_driver_to_fs(void);
109 this function unregisters driver from fs
111 static void sep_unregister_driver_from_fs(void);
114 this function calculates the size of data that can be inserted into the lli
115 table from this array the condition is that either the table is full
116 (all etnries are entered), or there are no more entries in the lli array
118 static unsigned long sep_calculate_lli_table_max_size(
119 struct sep_lli_entry_t *lli_in_array_ptr,
120 unsigned long num_array_entries);
122 this functions builds ont lli table from the lli_array according to the
125 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
126 struct sep_lli_entry_t *lli_table_ptr,
127 unsigned long *num_processed_entries_ptr,
128 unsigned long *num_table_entries_ptr,
129 unsigned long table_data_size);
132 this function goes over the list of the print created tables and prints
135 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
136 unsigned long num_table_entries,
137 unsigned long table_data_size);
142 This function raises interrupt to SEPm that signals that is has a new
145 static void sep_send_command_handler(void);
149 This function raises interrupt to SEP that signals that is has a
152 static void sep_send_reply_command_handler(void);
155 This function handles the allocate data pool memory request
156 This function returns calculates the physical address of the allocated memory
157 and the offset of this area from the mapped address. Therefore, the FVOs in
158 user space can calculate the exact virtual address of this allocated memory
160 static int sep_allocate_data_pool_memory_handler(unsigned long arg);
164 This function handles write into allocated data pool command
166 static int sep_write_into_data_pool_handler(unsigned long arg);
169 this function handles the read from data pool command
171 static int sep_read_from_data_pool_handler(unsigned long arg);
174 this function handles tha request for creation of the DMA table
175 for the synchronic symmetric operations (AES,DES)
177 static int sep_create_sync_dma_tables_handler(unsigned long arg);
180 this function handles the request to create the DMA tables for flow
182 static int sep_create_flow_dma_tables_handler(unsigned long arg);
185 This API handles the end transaction request
187 static int sep_end_transaction_handler(unsigned long arg);
191 this function handles add tables to flow
193 static int sep_add_flow_tables_handler(unsigned long arg);
196 this function add the flow add message to the specific flow
198 static int sep_add_flow_tables_message_handler(unsigned long arg);
201 this function handles the request for SEP start
203 static int sep_start_handler(void);
206 this function handles the request for SEP initialization
208 static int sep_init_handler(unsigned long arg);
211 this function handles the request cache and resident reallocation
213 static int sep_realloc_cache_resident_handler(unsigned long arg);
217 This api handles the setting of API mode to blocking or non-blocking
219 static int sep_set_api_mode_handler(unsigned long arg);
221 /* handler for flow done interrupt */
222 static void sep_flow_done_handler(struct work_struct *work);
225 This function locks all the physical pages of the kernel virtual buffer
226 and construct a basic lli array, where each entry holds the physical
227 page address and the size that application data holds in this physical pages
229 static int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
230 unsigned long data_size,
231 unsigned long *num_pages_ptr,
232 struct sep_lli_entry_t **lli_array_ptr,
233 struct page ***page_array_ptr);
236 This function creates one DMA table for flow and returns its data,
237 and pointer to its info entry
239 static int sep_prepare_one_flow_dma_table(unsigned long virt_buff_addr,
240 unsigned long virt_buff_size,
241 struct sep_lli_entry_t *table_data,
242 struct sep_lli_entry_t **info_entry_ptr,
243 struct sep_flow_context_t *flow_data_ptr,
244 bool isKernelVirtualAddress);
247 This function creates a list of tables for flow and returns the data for the
248 first and last tables of the list
250 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
251 unsigned long first_buff_addr,
252 struct sep_flow_context_t *flow_data_ptr,
253 struct sep_lli_entry_t *first_table_data_ptr,
254 struct sep_lli_entry_t *last_table_data_ptr,
255 bool isKernelVirtualAddress);
258 this function find a space for the new flow dma table
260 static int sep_find_free_flow_dma_table_space(
261 unsigned long **table_address_ptr);
264 this function goes over all the flow tables connected to the given table and
267 static void sep_deallocated_flow_tables(
268 struct sep_lli_entry_t *first_table_ptr);
271 This function handler the set flow id command
273 static int sep_set_flow_id_handler(unsigned long arg);
276 This function returns pointer to the flow data structure
277 that conatins the given id
279 static int sep_find_flow_context(unsigned long flow_id,
280 struct sep_flow_context_t **flow_data_ptr);
284 this function returns the physical and virtual addresses of the static pool
286 static int sep_get_static_pool_addr_handler(unsigned long arg);
289 this address gets the offset of the physical address from the start of
292 static int sep_get_physical_mapped_offset_handler(unsigned long arg);
296 this function handles the request for get time
298 static int sep_get_time_handler(unsigned long arg);
301 calculates time and sets it at the predefined address
303 static int sep_set_time(unsigned long *address_ptr,
304 unsigned long *time_in_sec_ptr);
307 PATCH for configuring the DMA to single burst instead of multi-burst
309 static void sep_configure_dma_burst(void);
312 This function locks all the physical pages of the
313 application virtual buffer and construct a basic lli
314 array, where each entry holds the physical page address
315 and the size that application data holds in this physical pages
317 static int sep_lock_user_pages(unsigned long app_virt_addr,
318 unsigned long data_size,
319 unsigned long *num_pages_ptr,
320 struct sep_lli_entry_t **lli_array_ptr,
321 struct page ***page_array_ptr);
323 /*---------------------------------------------
325 -----------------------------------------------*/
328 this function locks SEP by locking the semaphore
332 mutex_lock(&sep_mutex);
338 this function unlocks SEP
343 mutex_unlock(&sep_mutex);
347 this function returns the address of the message shared area
349 void sep_map_shared_area(unsigned long *mappedAddr_ptr)
351 *mappedAddr_ptr = sep_dev->shared_area_addr;
355 this function returns the address of the message shared area
357 void sep_send_msg_rdy_cmd()
359 sep_send_command_handler();
362 /* this functions frees all the resources that were allocated for the building
363 of the LLI DMA tables */
364 void sep_free_dma_resources()
366 sep_free_dma_table_data_handler();
369 /* poll(suspend), until reply from sep */
370 void sep_driver_poll()
372 unsigned long retVal = 0;
374 #ifdef SEP_DRIVER_POLLING_MODE
376 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF))
377 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
379 sep_dev->sep_to_host_reply_counter++;
381 /* poll, until reply from sep */
382 wait_event(g_sep_event,
383 (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter));
388 /*----------------------------------------------------------------------
389 open function of the character driver - must only lock the mutex
390 must also release the memory data pool allocations
391 ------------------------------------------------------------------------*/
392 static int sep_open(struct inode *inode_ptr, struct file *file_ptr)
399 ---------------------*/
401 dbg("SEP Driver:--------> open start\n");
405 /* check the blocking mode */
406 if (sep_dev->block_mode_flag)
408 mutex_lock(&sep_mutex);
410 error = mutex_trylock(&sep_mutex);
412 /* check the error */
415 "SEP Driver: down_interruptible failed\n");
420 /* release data pool allocations */
421 sep_dev->data_pool_bytes_allocated = 0;
425 dbg("SEP Driver:<-------- open end\n");
433 /*------------------------------------------------------------
435 -------------------------------------------------------------*/
436 static int sep_release(struct inode *inode_ptr, struct file *file_ptr)
440 ---------------------*/
442 dbg("----------->SEP Driver: sep_release start\n");
444 #if 0/*!SEP_DRIVER_POLLING_MODE*/
446 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
448 /* release IRQ line */
449 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
453 /* unlock the sep mutex */
454 mutex_unlock(&sep_mutex);
456 dbg("SEP Driver:<-------- sep_release end\n");
464 /*---------------------------------------------------------------
465 map function - this functions maps the message shared area
466 -----------------------------------------------------------------*/
467 static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
470 unsigned long phys_addr;
472 /*-----------------------
474 -------------------------*/
476 dbg("-------->SEP Driver: mmap start\n");
478 /* check that the size of the mapped range is as the size of the message
480 if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
482 "SEP Driver mmap requested size is more than allowed\n");
483 printk(KERN_WARNING "SEP Driver mmap requested size is more \
485 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
487 printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n",
493 "SEP Driver:g_message_shared_area_addr is %08lx\n",
494 sep_dev->message_shared_area_addr);
496 /* get physical address */
497 phys_addr = sep_dev->phys_shared_area_addr;
499 edbg( "SEP Driver: phys_addr is %08lx\n",
502 if (remap_pfn_range(vma,
504 phys_addr >> PAGE_SHIFT,
505 vma->vm_end - vma->vm_start,
506 vma->vm_page_prot)) {
508 "SEP Driver remap_page_range failed\n");
509 printk(KERN_WARNING "SEP Driver remap_page_range failed\n");
513 dbg("SEP Driver:<-------- mmap end\n");
519 /*-----------------------------------------------
521 *----------------------------------------------*/
522 static unsigned int sep_poll(struct file *filp, poll_table *wait)
526 unsigned int mask = 0;
529 unsigned long retVal = 0;
531 /*----------------------------------------------
533 -------------------------------------------------*/
535 dbg("---------->SEP Driver poll: start\n");
538 #if SEP_DRIVER_POLLING_MODE
540 while (sep_dev->host_to_sep_send_counter != (retVal & 0x7FFFFFFF)) {
541 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
543 for (count = 0; count < 10 * 4; count += 4)
544 edbg("Poll Debug Word %lu of the message is %lu\n", count,
545 *((unsigned long *)(sep_dev->shared_area_addr +
546 SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES + count)));
549 sep_dev->sep_to_host_reply_counter++;
551 /* add the event to the polling wait table */
552 poll_wait(filp, &g_sep_event, wait);
557 "sep_dev->host_to_sep_send_counter is %lu\n",
558 sep_dev->host_to_sep_send_counter);
560 "sep_dev->sep_to_host_reply_counter is %lu\n",
561 sep_dev->sep_to_host_reply_counter);
563 /* check if the data is ready */
564 if (sep_dev->host_to_sep_send_counter == sep_dev->sep_to_host_reply_counter) {
565 for (count = 0; count < 12 * 4; count += 4)
566 edbg("Sep Mesg Word %lu of the message is %lu\n", count,
567 *((unsigned long *)(sep_dev->shared_area_addr + count)));
569 for (count = 0; count < 10 * 4; count += 4)
570 edbg("Debug Data Word %lu of the message is %lu\n", count,
571 *((unsigned long *)(sep_dev->shared_area_addr + 0x1800 + count)));
573 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR2_REG_ADDR);
574 edbg( "retVal is %lu\n", retVal);
575 /* check if the this is sep reply or request */
578 "SEP Driver: sep request in\n");
580 mask |= POLLOUT | POLLWRNORM;
582 edbg( "SEP Driver: sep reply in\n");
583 mask |= POLLIN | POLLRDNORM;
587 dbg("SEP Driver:<-------- poll exit\n");
592 static int sep_ioctl(struct inode *inode,
601 /*------------------------
603 ------------------------*/
606 dbg("------------>SEP Driver: ioctl start\n");
608 edbg("SEP Driver: cmd is %x\n", cmd);
610 /* check that the command is for sep device */
611 if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
615 case SEP_IOCSENDSEPCOMMAND:
617 /* send command to SEP */
618 sep_send_command_handler();
621 "SEP Driver: after sep_send_command_handler\n");
625 case SEP_IOCSENDSEPRPLYCOMMAND:
627 /* send reply command to SEP */
628 sep_send_reply_command_handler();
632 case SEP_IOCALLOCDATAPOLL:
634 /* allocate data pool */
635 error = sep_allocate_data_pool_memory_handler(arg);
639 case SEP_IOCWRITEDATAPOLL:
641 /* write data into memory pool */
642 error = sep_write_into_data_pool_handler(arg);
646 case SEP_IOCREADDATAPOLL:
648 /* read data from data pool into application memory */
649 error = sep_read_from_data_pool_handler(arg);
653 case SEP_IOCCREATESYMDMATABLE:
655 /* create dma table for synhronic operation */
656 error = sep_create_sync_dma_tables_handler(arg);
660 case SEP_IOCCREATEFLOWDMATABLE:
662 /* create flow dma tables */
663 error = sep_create_flow_dma_tables_handler(arg);
667 case SEP_IOCFREEDMATABLEDATA:
670 error = sep_free_dma_table_data_handler();
674 case SEP_IOCSETFLOWID:
677 error = sep_set_flow_id_handler(arg);
681 case SEP_IOCADDFLOWTABLE:
683 /* add tables to the dynamic flow */
684 error = sep_add_flow_tables_handler(arg);
688 case SEP_IOCADDFLOWMESSAGE:
690 /* add message of add tables to flow */
691 error = sep_add_flow_tables_message_handler(arg);
695 case SEP_IOCSEPSTART:
697 /* start command to sep */
698 error = sep_start_handler();
703 /* init command to sep */
704 error = sep_init_handler(arg);
707 case SEP_IOCSETAPIMODE:
709 /* set non- blocking mode */
710 error = sep_set_api_mode_handler(arg);
714 case SEP_IOCGETSTATICPOOLADDR:
716 /* get the physical and virtual addresses of the static pool */
717 error = sep_get_static_pool_addr_handler(arg);
721 case SEP_IOCENDTRANSACTION:
723 error = sep_end_transaction_handler(arg);
727 case SEP_IOCREALLOCCACHERES:
729 error = sep_realloc_cache_resident_handler(arg);
733 case SEP_IOCGETMAPPEDADDROFFSET:
735 error = sep_get_physical_mapped_offset_handler(arg);
740 error = sep_get_time_handler(arg);
749 dbg("SEP Driver:<-------- ioctl end\n");
756 this function registers the driver to the file system
758 static int sep_register_driver_to_fs(void)
763 /*---------------------
765 -----------------------*/
767 ret_val = alloc_chrdev_region(&g_sep_device_number, 0, 1, "sep_sec_driver");
770 "sep_driver:major number allocation failed, retval is %d\n", ret_val);
774 /* set the files operations structure */
775 g_sep_fops.owner = THIS_MODULE;
776 g_sep_fops.ioctl = sep_ioctl;
777 g_sep_fops.poll = sep_poll;
778 g_sep_fops.open = sep_open;
779 g_sep_fops.release = sep_release;
780 g_sep_fops.mmap = sep_mmap;
783 cdev_init(&g_sep_cdev, &g_sep_fops);
784 g_sep_cdev.owner = THIS_MODULE;
786 /* register the driver with the kernel */
787 ret_val = cdev_add(&g_sep_cdev, g_sep_device_number, 1);
791 "sep_driver:cdev_add failed, retval is %d\n",
793 goto end_function_unregister_devnum;
798 end_function_unregister_devnum:
800 /* unregister dev numbers */
801 unregister_chrdev_region(g_sep_device_number, 1);
809 this function unregisters driver from fs
811 static void sep_unregister_driver_from_fs(void)
813 /*-------------------
815 ---------------------*/
817 cdev_del(&g_sep_cdev);
819 /* unregister dev numbers */
820 unregister_chrdev_region(g_sep_device_number, 1);
823 /*--------------------------------------------------------------
825 ----------------------------------------------------------------*/
826 static int __init sep_init(void)
834 /* size to of memory for allocation */
837 /*------------------------
839 ------------------------*/
841 dbg("SEP Driver:-------->Init start\n");
842 edbg("sep->shared_area_addr = %lx\n",
843 (unsigned long)&sep_dev->shared_area_addr);
847 /* transaction counter that coordinates the transactions between SEP
849 sep_dev->host_to_sep_send_counter = 0;
851 /* counter for the messages from sep */
852 sep_dev->sep_to_host_reply_counter = 0;
854 /* counter for the number of bytes allocated in the pool
855 for the current transaction */
856 sep_dev->data_pool_bytes_allocated = 0;
858 /* set the starting mode to blocking */
859 sep_dev->block_mode_flag = 1;
862 ret_val = sep_register_driver_to_device();
865 "sep_driver:sep_driver_to_device failed, ret_val is %d\n",
867 goto end_function_unregister_from_fs;
870 /* calculate the total size for allocation */
871 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
872 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
873 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
874 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
875 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
876 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
880 /* allocate the shared area */
881 if (sep_map_and_alloc_shared_area(size,
882 &sep_dev->shared_area_addr,
883 &sep_dev->phys_shared_area_addr)) {
885 /* allocation failed */
886 goto end_function_unmap_io_memory;
889 /* now set the memory regions */
890 sep_dev->message_shared_area_addr = sep_dev->shared_area_addr;
893 "SEP Driver: g_message_shared_area_addr is %08lx\n",
894 sep_dev->message_shared_area_addr);
896 #if (SEP_DRIVER_RECONFIG_MESSAGE_AREA == 1)
898 /* send the new SHARED MESSAGE AREA to the SEP */
899 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR1_REG_ADDR,
900 sep_dev->phys_shared_area_addr);
902 /* poll for SEP response */
903 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
904 while (retVal != 0xffffffff && retVal != sep_dev->phys_shared_area_addr)
905 retVal = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR1_REG_ADDR);
907 /* check the return value (register) */
908 if (retVal != sep_dev->phys_shared_area_addr) {
910 goto end_function_deallocate_message_area;
915 /* init the flow contextes */
916 for (counter = 0; counter < SEP_DRIVER_NUM_FLOWS; counter++)
917 sep_dev->flows_data_array[counter].flow_id = SEP_FREE_FLOW_ID;
919 sep_dev->flow_wq_ptr = create_singlethread_workqueue("sepflowwq");
920 if (sep_dev->flow_wq_ptr == 0) {
923 "sep_driver:flow queue creation failed\n");
924 goto end_function_deallocate_sep_shared_area;
928 "SEP Driver: create flow workqueue \n");
930 /* register driver to fs */
931 ret_val = sep_register_driver_to_fs();
933 goto end_function_deallocate_sep_shared_area;
935 /* load the rom code */
940 end_function_unregister_from_fs:
942 /* unregister from fs */
943 sep_unregister_driver_from_fs();
945 end_function_deallocate_sep_shared_area:
947 /* de-allocate shared area */
948 sep_unmap_and_free_shared_area(size,
949 sep_dev->shared_area_addr,
950 sep_dev->phys_shared_area_addr);
952 end_function_unmap_io_memory:
954 iounmap((void *)sep_dev->reg_base_address);
956 /* release io memory region */
957 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
961 dbg("SEP Driver:<-------- Init end\n");
969 /*-------------------------------------------------------------
971 --------------------------------------------------------------*/
972 static void __exit sep_exit(void)
977 /*-----------------------------
979 --------------------------------*/
981 dbg("SEP Driver:--------> Exit start\n");
983 /* unregister from fs */
984 sep_unregister_driver_from_fs();
986 /* calculate the total size for de-allocation */
987 size = SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES +
988 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES +
989 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES +
990 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES +
991 SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES +
992 SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES;
995 /* free shared area */
996 sep_unmap_and_free_shared_area(size,
997 sep_dev->shared_area_addr,
998 sep_dev->phys_shared_area_addr);
1001 "SEP Driver: free pages SEP SHARED AREA \n");
1003 iounmap((void *)sep_dev->reg_base_address);
1005 edbg( "SEP Driver: iounmap \n");
1007 /* release io memory region */
1008 release_mem_region(SEP_IO_MEM_REGION_START_ADDRESS, SEP_IO_MEM_REGION_SIZE);
1010 edbg( "SEP Driver: release_mem_region \n");
1012 dbg("SEP Driver:<-------- Exit end\n");
1017 interrupt handler function
1019 irqreturn_t sep_inthandler(int irq, void *dev_id)
1022 irqreturn_t int_error;
1025 unsigned long error;
1028 unsigned long reg_val;
1031 unsigned long flow_id;
1034 struct sep_flow_context_t *flow_context_ptr;
1036 /*-----------------------------
1038 -----------------------------*/
1040 int_error = IRQ_HANDLED;
1042 /* read the IRR register to check if this is SEP interrupt */
1043 reg_val = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1044 edbg( "SEP Interrupt - reg is %08lx\n",
1047 /* check if this is the flow interrupt */
1048 if (0/*reg_val & (0x1 << 11)*/) {
1049 /* read GPRO to find out the which flow is done */
1050 flow_id = sep_read_reg(sep_dev, HW_HOST_IRR_REG_ADDR);
1052 /* find the contex of the flow */
1053 error = sep_find_flow_context(flow_id >> 28, &flow_context_ptr);
1055 goto end_function_with_error;
1057 INIT_WORK(&flow_context_ptr->flow_wq, sep_flow_done_handler);
1059 /* queue the work */
1060 queue_work(sep_dev->flow_wq_ptr, &flow_context_ptr->flow_wq);
1063 /* check if this is reply interrupt from SEP */
1064 if (reg_val & (0x1 << 13)) {
1065 /* update the counter of reply messages */
1066 sep_dev->sep_to_host_reply_counter++;
1068 /* wake up the waiting process */
1069 wake_up(&g_sep_event);
1071 int_error = IRQ_NONE;
1076 end_function_with_error:
1078 /* clear the interrupt */
1079 sep_write_reg(sep_dev, HW_HOST_ICR_REG_ADDR, reg_val);
1088 This function prepares only input DMA table for synhronic symmetric
1091 int sep_prepare_input_dma_table(unsigned long app_virt_addr,
1092 unsigned long data_size,
1093 unsigned long block_size,
1094 unsigned long *lli_table_ptr,
1095 unsigned long *num_entries_ptr,
1096 unsigned long *table_data_size_ptr,
1097 bool isKernelVirtualAddress)
1100 /* pointer to the info entry of the table - the last entry */
1101 struct sep_lli_entry_t *info_entry_ptr;
1103 /* array of pointers ot page */
1104 struct sep_lli_entry_t *lli_array_ptr;
1106 /* points to the first entry to be processed in the lli_in_array */
1107 unsigned long current_entry;
1109 /* num entries in the virtual buffer */
1110 unsigned long sep_lli_entries;
1112 /* lli table pointer */
1113 struct sep_lli_entry_t *in_lli_table_ptr;
1115 /* the total data in one table */
1116 unsigned long table_data_size;
1118 /* number of entries in lli table */
1119 unsigned long num_entries_in_table;
1121 /* next table address */
1122 unsigned long lli_table_alloc_addr;
1125 unsigned long result;
1127 /*------------------------
1129 --------------------------*/
1131 dbg("SEP Driver:--------> sep_prepare_input_dma_table start\n");
1133 edbg( "SEP Driver:data_size is %lu\n", data_size);
1134 edbg( "SEP Driver:block_size is %lu\n", block_size);
1136 /* initialize the pages pointers */
1137 sep_dev->in_page_array = 0;
1138 sep_dev->in_num_pages = 0;
1140 if (data_size == 0) {
1141 /* special case - created 2 entries table with zero data */
1142 in_lli_table_ptr = (struct sep_lli_entry_t *)(sep_dev->shared_area_addr +
1143 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES);
1144 in_lli_table_ptr->physical_address = sep_dev->shared_area_addr +
1145 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1146 in_lli_table_ptr->block_size = 0;
1149 in_lli_table_ptr->physical_address = 0xFFFFFFFF;
1150 in_lli_table_ptr->block_size = 0;
1152 *lli_table_ptr = sep_dev->phys_shared_area_addr +
1153 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1154 *num_entries_ptr = 2;
1155 *table_data_size_ptr = 0;
1160 /* check if the pages are in Kernel Virtual Address layout */
1161 if (isKernelVirtualAddress == true)
1162 /* lock the pages of the kernel buffer and translate them to pages */
1163 result = sep_lock_kernel_pages(app_virt_addr,
1165 &sep_dev->in_num_pages,
1167 &sep_dev->in_page_array);
1169 /* lock the pages of the user buffer and translate them to pages */
1170 result = sep_lock_user_pages(app_virt_addr,
1172 &sep_dev->in_num_pages,
1174 &sep_dev->in_page_array);
1180 "SEP Driver:output sep_dev->in_num_pages is %lu\n",
1181 sep_dev->in_num_pages);
1185 sep_lli_entries = sep_dev->in_num_pages;
1187 /* initiate to point after the message area */
1188 lli_table_alloc_addr = sep_dev->shared_area_addr +
1189 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1191 /* loop till all the entries in in array are not processed */
1192 while (current_entry < sep_lli_entries) {
1193 /* set the new input and output tables */
1194 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1196 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1197 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1199 /* calculate the maximum size of data for input table */
1200 table_data_size = sep_calculate_lli_table_max_size(
1201 &lli_array_ptr[current_entry],
1202 (sep_lli_entries - current_entry));
1204 /* now calculate the table size so that it will be module block size */
1205 table_data_size = (table_data_size / block_size) * block_size;
1208 "SEP Driver:output table_data_size is %lu\n",
1211 /* construct input lli table */
1212 sep_build_lli_table(&lli_array_ptr[current_entry],
1215 &num_entries_in_table,
1218 if (info_entry_ptr == 0) {
1219 /* set the output parameters to physical addresses */
1220 *lli_table_ptr = sep_shared_area_virt_to_phys(
1221 (unsigned long)in_lli_table_ptr);
1222 *num_entries_ptr = num_entries_in_table;
1223 *table_data_size_ptr = table_data_size;
1226 "SEP Driver:output lli_table_in_ptr is %08lx\n",
1229 /* update the info entry of the previous in table */
1230 info_entry_ptr->physical_address = sep_shared_area_virt_to_phys(
1231 (unsigned long)in_lli_table_ptr);
1232 info_entry_ptr->block_size = ((num_entries_in_table) << 24) |
1236 /* save the pointer to the info entry of the current tables */
1237 info_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1240 /* print input tables */
1241 sep_debug_print_lli_tables((struct sep_lli_entry_t *)
1242 sep_shared_area_phys_to_virt(*lli_table_ptr),
1244 *table_data_size_ptr);
1246 /* the array of the pages */
1247 kfree(lli_array_ptr);
1251 dbg("SEP Driver:<-------- sep_prepare_input_dma_table end\n");
1258 This function builds input and output DMA tables for synhronic
1259 symmetric operations (AES, DES). It also checks that each table
1260 is of the modular block size
1262 int sep_prepare_input_output_dma_table(unsigned long app_virt_in_addr,
1263 unsigned long app_virt_out_addr,
1264 unsigned long data_size,
1265 unsigned long block_size,
1266 unsigned long *lli_table_in_ptr,
1267 unsigned long *lli_table_out_ptr,
1268 unsigned long *in_num_entries_ptr,
1269 unsigned long *out_num_entries_ptr,
1270 unsigned long *table_data_size_ptr,
1271 bool isKernelVirtualAddress)
1274 /* array of pointers of page */
1275 struct sep_lli_entry_t *lli_in_array;
1277 /* array of pointers of page */
1278 struct sep_lli_entry_t *lli_out_array;
1284 /*------------------------
1286 --------------------------*/
1288 dbg("SEP Driver:--------> sep_prepare_input_output_dma_table start\n");
1292 /* initialize the pages pointers */
1293 sep_dev->in_page_array = 0;
1294 sep_dev->out_page_array = 0;
1296 /* check if the pages are in Kernel Virtual Address layout */
1297 if (isKernelVirtualAddress == true) {
1298 /* lock the pages of the kernel buffer and translate them to pages */
1299 result = sep_lock_kernel_pages(app_virt_in_addr,
1301 &sep_dev->in_num_pages,
1303 &sep_dev->in_page_array);
1306 "SEP Driver: sep_lock_kernel_pages for input virtual buffer failed\n");
1310 /* lock the pages of the user buffer and translate them to pages */
1311 result = sep_lock_user_pages(app_virt_in_addr,
1313 &sep_dev->in_num_pages,
1315 &sep_dev->in_page_array);
1318 "SEP Driver: sep_lock_user_pages for input virtual buffer failed\n");
1323 if (isKernelVirtualAddress == true) {
1324 result = sep_lock_kernel_pages(app_virt_out_addr,
1326 &sep_dev->out_num_pages,
1328 &sep_dev->out_page_array);
1331 "SEP Driver: sep_lock_kernel_pages for output virtual buffer failed\n");
1332 goto end_function_with_error1;
1335 result = sep_lock_user_pages(app_virt_out_addr,
1337 &sep_dev->out_num_pages,
1339 &sep_dev->out_page_array);
1342 "SEP Driver: sep_lock_user_pages for output virtual buffer failed\n");
1343 goto end_function_with_error1;
1349 "sep_dev->in_num_pages is %lu\n", sep_dev->in_num_pages);
1351 "sep_dev->out_num_pages is %lu\n", sep_dev->out_num_pages);
1353 "SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP is %x\n",
1354 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP);
1357 /* call the fucntion that creates table from the lli arrays */
1358 result = sep_construct_dma_tables_from_lli(lli_in_array,
1359 sep_dev->in_num_pages,
1361 sep_dev->out_num_pages,
1366 out_num_entries_ptr,
1367 table_data_size_ptr);
1370 "SEP Driver: sep_construct_dma_tables_from_lli failed\n");
1371 goto end_function_with_error2;
1374 /* fall through - free the lli entry arrays */
1376 dbg("in_num_entries_ptr is %08lx\n",
1377 *in_num_entries_ptr);
1378 dbg("out_num_entries_ptr is %08lx\n",
1379 *out_num_entries_ptr);
1380 dbg("table_data_size_ptr is %08lx\n",
1381 *table_data_size_ptr);
1384 end_function_with_error2:
1386 kfree(lli_out_array);
1388 end_function_with_error1:
1390 kfree(lli_in_array);
1394 dbg("SEP Driver:<-------- sep_prepare_input_output_dma_table end result = %d\n", (int)result);
1402 This function creates the input and output dma tables for
1403 symmetric operations (AES/DES) according to the block size from LLI arays
1405 int sep_construct_dma_tables_from_lli(struct sep_lli_entry_t *lli_in_array,
1406 unsigned long sep_in_lli_entries,
1407 struct sep_lli_entry_t *lli_out_array,
1408 unsigned long sep_out_lli_entries,
1409 unsigned long block_size,
1410 unsigned long *lli_table_in_ptr,
1411 unsigned long *lli_table_out_ptr,
1412 unsigned long *in_num_entries_ptr,
1413 unsigned long *out_num_entries_ptr,
1414 unsigned long *table_data_size_ptr)
1416 /* points to the area where next lli table can be allocated */
1417 unsigned long lli_table_alloc_addr;
1419 /* input lli table */
1420 struct sep_lli_entry_t *in_lli_table_ptr;
1422 /* output lli table */
1423 struct sep_lli_entry_t *out_lli_table_ptr;
1425 /* pointer to the info entry of the table - the last entry */
1426 struct sep_lli_entry_t *info_in_entry_ptr;
1428 /* pointer to the info entry of the table - the last entry */
1429 struct sep_lli_entry_t *info_out_entry_ptr;
1431 /* points to the first entry to be processed in the lli_in_array */
1432 unsigned long current_in_entry;
1434 /* points to the first entry to be processed in the lli_out_array */
1435 unsigned long current_out_entry;
1437 /* max size of the input table */
1438 unsigned long in_table_data_size;
1440 /* max size of the output table */
1441 unsigned long out_table_data_size;
1443 /* flag te signifies if this is the first tables build from the arrays */
1444 unsigned long first_table_flag;
1446 /* the data size that should be in table */
1447 unsigned long table_data_size;
1449 /* number of etnries in the input table */
1450 unsigned long num_entries_in_table;
1452 /* number of etnries in the output table */
1453 unsigned long num_entries_out_table;
1455 /*---------------------
1457 ------------------------*/
1459 dbg("SEP Driver:--------> sep_construct_dma_tables_from_lli start\n");
1461 /* initiate to pint after the message area */
1462 lli_table_alloc_addr = sep_dev->shared_area_addr +
1463 SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES;
1465 current_in_entry = 0;
1466 current_out_entry = 0;
1467 first_table_flag = 1;
1468 info_in_entry_ptr = 0;
1469 info_out_entry_ptr = 0;
1471 /* loop till all the entries in in array are not processed */
1472 while (current_in_entry < sep_in_lli_entries) {
1473 /* set the new input and output tables */
1474 in_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1476 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1477 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1479 /* set the first output tables */
1480 out_lli_table_ptr = (struct sep_lli_entry_t *)lli_table_alloc_addr;
1482 lli_table_alloc_addr += sizeof(struct sep_lli_entry_t) *
1483 SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP;
1485 /* calculate the maximum size of data for input table */
1486 in_table_data_size =
1487 sep_calculate_lli_table_max_size(
1488 &lli_in_array[current_in_entry],
1489 (sep_in_lli_entries - current_in_entry));
1491 /* calculate the maximum size of data for output table */
1492 out_table_data_size =
1493 sep_calculate_lli_table_max_size(
1494 &lli_out_array[current_out_entry],
1495 (sep_out_lli_entries - current_out_entry));
1498 "SEP Driver:in_table_data_size is %lu\n", in_table_data_size);
1500 "SEP Driver:out_table_data_size is %lu\n", out_table_data_size);
1502 /* check where the data is smallest */
1503 table_data_size = in_table_data_size;
1504 if (table_data_size > out_table_data_size)
1505 table_data_size = out_table_data_size;
1507 /* now calculate the table size so that it will be module block size */
1508 table_data_size = (table_data_size / block_size) * block_size;
1510 dbg("SEP Driver:table_data_size is %lu\n", table_data_size);
1512 /* construct input lli table */
1513 sep_build_lli_table(&lli_in_array[current_in_entry],
1516 &num_entries_in_table,
1519 /* construct output lli table */
1520 sep_build_lli_table(&lli_out_array[current_out_entry],
1523 &num_entries_out_table,
1526 /* if info entry is null - this is the first table built */
1527 if (info_in_entry_ptr == 0) {
1528 /* set the output parameters to physical addresses */
1530 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1531 *in_num_entries_ptr = num_entries_in_table;
1532 *lli_table_out_ptr =
1533 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1534 *out_num_entries_ptr = num_entries_out_table;
1535 *table_data_size_ptr = table_data_size;
1538 "SEP Driver:output lli_table_in_ptr is %08lx\n", *lli_table_in_ptr);
1540 "SEP Driver:output lli_table_out_ptr is %08lx\n", *lli_table_out_ptr);
1542 /* update the info entry of the previous in table */
1543 info_in_entry_ptr->physical_address =
1544 sep_shared_area_virt_to_phys((unsigned long)in_lli_table_ptr);
1545 info_in_entry_ptr->block_size =
1546 ((num_entries_in_table) << 24) | (table_data_size);
1548 /* update the info entry of the previous in table */
1549 info_out_entry_ptr->physical_address =
1550 sep_shared_area_virt_to_phys((unsigned long)out_lli_table_ptr);
1551 info_out_entry_ptr->block_size =
1552 ((num_entries_out_table) << 24) | (table_data_size);
1555 /* save the pointer to the info entry of the current tables */
1556 info_in_entry_ptr = in_lli_table_ptr + num_entries_in_table - 1;
1557 info_out_entry_ptr = out_lli_table_ptr + num_entries_out_table - 1;
1560 "SEP Driver:output num_entries_out_table is %lu\n",
1561 (unsigned long)num_entries_out_table);
1563 "SEP Driver:output info_in_entry_ptr is %lu\n",
1564 (unsigned long)info_in_entry_ptr);
1566 "SEP Driver:output info_out_entry_ptr is %lu\n",
1567 (unsigned long)info_out_entry_ptr);
1570 /* print input tables */
1571 sep_debug_print_lli_tables(
1572 (struct sep_lli_entry_t *)
1573 sep_shared_area_phys_to_virt(*lli_table_in_ptr),
1574 *in_num_entries_ptr,
1575 *table_data_size_ptr);
1577 /* print output tables */
1578 sep_debug_print_lli_tables(
1579 (struct sep_lli_entry_t *)
1580 sep_shared_area_phys_to_virt(*lli_table_out_ptr),
1581 *out_num_entries_ptr,
1582 *table_data_size_ptr);
1584 dbg("SEP Driver:<-------- sep_construct_dma_tables_from_lli end\n");
1590 this function calculates the size of data that can be inserted into the lli
1591 table from this array the condition is that either the table is full
1592 (all etnries are entered), or there are no more entries in the lli array
1594 unsigned long sep_calculate_lli_table_max_size(
1595 struct sep_lli_entry_t *lli_in_array_ptr,
1596 unsigned long num_array_entries)
1598 /* table data size */
1599 unsigned long table_data_size;
1602 unsigned long counter;
1604 /*---------------------
1606 ----------------------*/
1608 table_data_size = 0;
1610 /* calculate the data in the out lli table if till we fill the whole
1611 table or till the data has ended */
1613 (counter < (SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP - 1)) &&
1614 (counter < num_array_entries); counter++)
1615 table_data_size += lli_in_array_ptr[counter].block_size;
1617 return table_data_size;
1621 this functions builds ont lli table from the lli_array according to
1622 the given size of data
1624 static void sep_build_lli_table(struct sep_lli_entry_t *lli_array_ptr,
1625 struct sep_lli_entry_t *lli_table_ptr,
1626 unsigned long *num_processed_entries_ptr,
1627 unsigned long *num_table_entries_ptr,
1628 unsigned long table_data_size)
1630 /* current table data size */
1631 unsigned long curr_table_data_size;
1633 /* counter of lli array entry */
1634 unsigned long array_counter;
1636 /*-----------------------
1638 ---------------------------*/
1640 dbg("SEP Driver:--------> sep_build_lli_table start\n");
1642 /* init currrent table data size and lli array entry counter */
1643 curr_table_data_size = 0;
1645 *num_table_entries_ptr = 1;
1648 "SEP Driver:table_data_size is %lu\n",
1651 /* fill the table till table size reaches the needed amount */
1652 while (curr_table_data_size < table_data_size) {
1653 /* update the number of entries in table */
1654 (*num_table_entries_ptr)++;
1656 lli_table_ptr->physical_address =
1657 lli_array_ptr[array_counter].physical_address;
1658 lli_table_ptr->block_size = lli_array_ptr[array_counter].block_size;
1659 curr_table_data_size += lli_table_ptr->block_size;
1662 "SEP Driver:lli_table_ptr is %08lx\n",
1663 (unsigned long)lli_table_ptr);
1665 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1666 lli_table_ptr->physical_address);
1668 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1669 lli_table_ptr->block_size);
1671 /* check for overflow of the table data */
1672 if (curr_table_data_size > table_data_size) {
1674 "SEP Driver:curr_table_data_size > table_data_size\n");
1676 /* update the size of block in the table */
1677 lli_table_ptr->block_size -= (curr_table_data_size - table_data_size);
1679 /* update the physical address in the lli array */
1680 lli_array_ptr[array_counter].physical_address +=
1681 lli_table_ptr->block_size;
1683 /* update the block size left in the lli array */
1684 lli_array_ptr[array_counter].block_size =
1685 (curr_table_data_size - table_data_size);
1687 /* advance to the next entry in the lli_array */
1691 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1692 lli_table_ptr->physical_address);
1694 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1695 lli_table_ptr->block_size);
1697 /* move to the next entry in table */
1701 /* set the info entry to default */
1702 lli_table_ptr->physical_address = 0xffffffff;
1703 lli_table_ptr->block_size = 0;
1706 "SEP Driver:lli_table_ptr is %08lx\n",
1707 (unsigned long)lli_table_ptr);
1709 "SEP Driver:lli_table_ptr->physical_address is %08lx\n",
1710 lli_table_ptr->physical_address);
1712 "SEP Driver:lli_table_ptr->block_size is %lu\n",
1713 lli_table_ptr->block_size);
1716 /* set the output parameter */
1717 *num_processed_entries_ptr += array_counter;
1720 "SEP Driver:*num_processed_entries_ptr is %lu\n",
1721 *num_processed_entries_ptr);
1724 dbg("SEP Driver:<-------- sep_build_lli_table end\n");
1730 this function goes over the list of the print created tables and
1733 static void sep_debug_print_lli_tables(struct sep_lli_entry_t *lli_table_ptr,
1734 unsigned long num_table_entries,
1735 unsigned long table_data_size)
1737 unsigned long table_count;
1739 unsigned long entries_count;
1740 /*-----------------------------
1742 -------------------------------*/
1744 dbg("SEP Driver:--------> sep_debug_print_lli_tables start\n");
1747 while ((unsigned long)lli_table_ptr != 0xffffffff) {
1748 edbg("SEP Driver: lli table %08lx, table_data_size is %lu\n",
1749 table_count, table_data_size);
1750 edbg("SEP Driver: num_table_entries is %lu\n", num_table_entries);
1752 /* print entries of the table (without info entry) */
1753 for (entries_count = 0;
1754 entries_count < num_table_entries;
1755 entries_count++, lli_table_ptr++) {
1756 edbg("SEP Driver:lli_table_ptr address is %08lx\n",
1757 (unsigned long)lli_table_ptr);
1758 edbg("SEP Driver:phys address is %08lx block size is %lu\n",
1759 lli_table_ptr->physical_address, lli_table_ptr->block_size);
1762 /* point to the info entry */
1766 "SEP Driver:phys lli_table_ptr->block_size is %lu\n",
1767 lli_table_ptr->block_size);
1769 "SEP Driver:phys lli_table_ptr->physical_address is %08lx\n",
1770 lli_table_ptr->physical_address);
1773 table_data_size = lli_table_ptr->block_size & 0xffffff;
1774 num_table_entries = (lli_table_ptr->block_size >> 24) & 0xff;
1775 lli_table_ptr = (struct sep_lli_entry_t *)
1776 (lli_table_ptr->physical_address);
1778 edbg("SEP Driver:phys table_data_size is %lu num_table_entries is %lu lli_table_ptr is%lu\n",
1779 table_data_size, num_table_entries, (unsigned long)lli_table_ptr);
1781 if ((unsigned long)lli_table_ptr != 0xffffffff)
1782 lli_table_ptr = (struct sep_lli_entry_t *)sep_shared_area_phys_to_virt(
1783 (unsigned long)lli_table_ptr);
1788 dbg("SEP Driver:<-------- sep_debug_print_lli_tables end\n");
1793 This function locks all the physical pages of the application virtual buffer
1794 and construct a basic lli array, where each entry holds the physical page
1795 address and the size that application data holds in this physical pages
1797 int sep_lock_user_pages(unsigned long app_virt_addr,
1798 unsigned long data_size,
1799 unsigned long *num_pages_ptr,
1800 struct sep_lli_entry_t **lli_array_ptr,
1801 struct page ***page_array_ptr)
1807 /* the the page of the end address of the user space buffer */
1808 unsigned long end_page;
1810 /* the page of the start address of the user space buffer */
1811 unsigned long start_page;
1813 /* the range in pages */
1814 unsigned long num_pages;
1816 /* array of pointers ot page */
1817 struct page **page_array;
1820 struct sep_lli_entry_t *lli_array;
1823 unsigned long count;
1828 /*------------------------
1830 --------------------------*/
1832 dbg("SEP Driver:--------> sep_lock_user_pages start\n");
1836 /* set start and end pages and num pages */
1837 end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
1838 start_page = app_virt_addr >> PAGE_SHIFT;
1839 num_pages = end_page - start_page + 1;
1842 "SEP Driver: app_virt_addr is %08lx\n",
1845 "SEP Driver: data_size is %lu\n",
1848 "SEP Driver: start_page is %lu\n",
1851 "SEP Driver: end_page is %lu\n",
1854 "SEP Driver: num_pages is %lu\n",
1857 /* allocate array of pages structure pointers */
1858 page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
1861 "SEP Driver: kmalloc for page_array failed\n");
1867 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
1870 "SEP Driver: kmalloc for lli_array failed\n");
1873 goto end_function_with_error1;
1876 /* convert the application virtual address into a set of physical */
1877 down_read(¤t->mm->mmap_sem);
1878 result = get_user_pages(current, current->mm, app_virt_addr, num_pages, 1, 0,
1881 up_read(¤t->mm->mmap_sem);
1883 /* check the number of pages locked - if not all then exit with error */
1884 if (result != num_pages) {
1885 dbg("SEP Driver: not all pages locked by get_user_pages\n");
1888 goto end_function_with_error2;
1891 /* flush the cache */
1892 for (count = 0; count < num_pages; count++)
1893 flush_dcache_page(page_array[count]);
1895 /* set the start address of the first page - app data may start not at
1896 the beginning of the page */
1897 lli_array[0].physical_address = (
1898 (unsigned long)page_to_phys(page_array[0])) +
1899 (app_virt_addr & (~PAGE_MASK)) ;
1901 /* check that not all the data is in the first page only */
1902 if ((PAGE_SIZE - (app_virt_addr & (~PAGE_MASK))) >= data_size)
1903 lli_array[0].block_size = data_size;
1905 lli_array[0].block_size = PAGE_SIZE - (app_virt_addr & (~PAGE_MASK));
1908 dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
1909 lli_array[0].physical_address,
1910 lli_array[0].block_size);
1912 /* go from the second page to the prev before last */
1913 for (count = 1; count < (num_pages - 1); count++) {
1914 lli_array[count].physical_address =
1915 (unsigned long)page_to_phys(page_array[count]);
1916 lli_array[count].block_size = PAGE_SIZE;
1919 "lli_array[%lu].physical_address is %08lx, \
1920 lli_array[%lu].block_size is %lu\n",
1921 count, lli_array[count].physical_address,
1923 lli_array[count].block_size);
1926 /* if more then 1 pages locked - then update for the last page size needed */
1927 if (num_pages > 1) {
1928 /* update the address of the last page */
1929 lli_array[count].physical_address =
1930 (unsigned long)page_to_phys(page_array[count]);
1932 /* set the size of the last page */
1933 lli_array[count].block_size = (app_virt_addr + data_size) &
1936 if (lli_array[count].block_size == 0) {
1937 dbg("app_virt_addr is %08lx\n", app_virt_addr);
1938 dbg("data_size is %lu\n", data_size);
1942 "lli_array[%lu].physical_address is %08lx, \
1943 lli_array[%lu].block_size is %lu\n",
1944 count, lli_array[count].physical_address,
1946 lli_array[count].block_size);
1949 /* set output params */
1950 *lli_array_ptr = lli_array;
1951 *num_pages_ptr = num_pages;
1952 *page_array_ptr = page_array;
1956 end_function_with_error2:
1958 /* release the cache */
1959 for (count = 0; count < num_pages; count++)
1960 page_cache_release(page_array[count]);
1962 /* free lli array */
1965 end_function_with_error1:
1967 /* free page array */
1972 dbg("SEP Driver:<-------- sep_lock_user_pages end\n");
1978 This function locks all the physical pages of the kernel virtual buffer
1979 and construct a basic lli array, where each entry holds the physical
1980 page address and the size that application data holds in this physical pages
1982 int sep_lock_kernel_pages(unsigned long kernel_virt_addr,
1983 unsigned long data_size,
1984 unsigned long *num_pages_ptr,
1985 struct sep_lli_entry_t **lli_array_ptr,
1986 struct page ***page_array_ptr)
1992 /* the the page of the end address of the user space buffer */
1993 unsigned long end_page;
1995 /* the page of the start address of the user space buffer */
1996 unsigned long start_page;
1998 /* the range in pages */
1999 unsigned long num_pages;
2002 struct sep_lli_entry_t *lli_array;
2004 /* next kernel address to map */
2005 unsigned long next_kernel_address;
2008 unsigned long count;
2011 /*------------------------
2013 --------------------------*/
2015 dbg("SEP Driver:--------> sep_lock_kernel_pages start\n");
2019 /* set start and end pages and num pages */
2020 end_page = (kernel_virt_addr + data_size - 1) >> PAGE_SHIFT;
2021 start_page = kernel_virt_addr >> PAGE_SHIFT;
2022 num_pages = end_page - start_page + 1;
2025 "SEP Driver: kernel_virt_addr is %08lx\n",
2028 "SEP Driver: data_size is %lu\n",
2031 "SEP Driver: start_page is %lx\n",
2034 "SEP Driver: end_page is %lx\n",
2037 "SEP Driver: num_pages is %lu\n",
2040 lli_array = kmalloc(sizeof(struct sep_lli_entry_t) * num_pages, GFP_ATOMIC);
2043 "SEP Driver: kmalloc for lli_array failed\n");
2049 /* set the start address of the first page - app data may start not at
2050 the beginning of the page */
2051 lli_array[0].physical_address =
2052 (unsigned long)virt_to_phys((unsigned long *)kernel_virt_addr);
2054 /* check that not all the data is in the first page only */
2055 if ((PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK))) >= data_size)
2056 lli_array[0].block_size = data_size;
2058 lli_array[0].block_size =
2059 PAGE_SIZE - (kernel_virt_addr & (~PAGE_MASK));
2062 dbg("lli_array[0].physical_address is %08lx, lli_array[0].block_size is %lu\n",
2063 lli_array[0].physical_address,
2064 lli_array[0].block_size);
2066 /* advance the address to the start of the next page */
2067 next_kernel_address = (kernel_virt_addr & PAGE_MASK) + PAGE_SIZE;
2069 /* go from the second page to the prev before last */
2070 for (count = 1; count < (num_pages - 1); count++) {
2071 lli_array[count].physical_address =
2072 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2073 lli_array[count].block_size = PAGE_SIZE;
2076 "lli_array[%lu].physical_address is %08lx, \
2077 lli_array[%lu].block_size is %lu\n",
2078 count, lli_array[count].physical_address, count,
2079 lli_array[count].block_size);
2081 next_kernel_address += PAGE_SIZE;
2084 /* if more then 1 pages locked - then update for the last page size needed */
2085 if (num_pages > 1) {
2086 /* update the address of the last page */
2087 lli_array[count].physical_address =
2088 (unsigned long)virt_to_phys((unsigned long *)next_kernel_address);
2090 /* set the size of the last page */
2091 lli_array[count].block_size =
2092 (kernel_virt_addr + data_size) & (~PAGE_MASK);
2094 if (lli_array[count].block_size == 0) {
2095 dbg("app_virt_addr is %08lx\n",
2097 dbg("data_size is %lu\n", data_size);
2102 "lli_array[%lu].physical_address is %08lx, \
2103 lli_array[%lu].block_size is %lu\n",
2104 count, lli_array[count].physical_address,
2106 lli_array[count].block_size);
2109 /* set output params */
2110 *lli_array_ptr = lli_array;
2111 *num_pages_ptr = num_pages;
2112 *page_array_ptr = 0;
2117 dbg("SEP Driver:<-------- sep_lock_kernel_pages end\n");
2123 This function releases all the application virtual buffer physical pages,
2124 that were previously locked
2126 int sep_free_dma_pages(struct page **page_array_ptr,
2127 unsigned long num_pages,
2128 unsigned long dirtyFlag)
2131 unsigned long count;
2133 /*-------------------
2135 ---------------------*/
2138 for (count = 0; count < num_pages; count++) {
2139 /* the out array was written, therefore the data was changed */
2140 if (!PageReserved(page_array_ptr[count]))
2141 SetPageDirty(page_array_ptr[count]);
2142 page_cache_release(page_array_ptr[count]);
2145 /* free in pages - the data was only read, therefore no update was done
2147 for (count = 0; count < num_pages; count++)
2148 page_cache_release(page_array_ptr[count]);
2152 /* free the array */
2153 kfree(page_array_ptr);
2159 This function raises interrupt to SEP that signals that is has a new
2162 static void sep_send_command_handler()
2165 unsigned long count;
2167 dbg("SEP Driver:--------> sep_send_command_handler start\n");
2174 for (count = 0; count < 12 * 4; count += 4)
2175 edbg("Word %lu of the message is %lu\n", count,
2176 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2178 /* update counter */
2179 sep_dev->host_to_sep_send_counter++;
2181 /* send interrupt to SEP */
2182 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
2184 dbg("SEP Driver:<-------- sep_send_command_handler end\n");
2190 This function raises interrupt to SEPm that signals that is has a
2191 new command from HOST
2193 static void sep_send_reply_command_handler()
2195 unsigned long count;
2197 dbg("SEP Driver:--------> sep_send_reply_command_handler start\n");
2202 for (count = 0; count < 12 * 4; count += 4)
2203 edbg("Word %lu of the message is %lu\n", count,
2204 *((unsigned long *)(sep_dev->shared_area_addr + count)));
2207 /* update counter */
2208 sep_dev->host_to_sep_send_counter++;
2210 /* send the interrupt to SEP */
2211 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR,
2212 sep_dev->host_to_sep_send_counter);
2214 /* update both counters */
2215 sep_dev->host_to_sep_send_counter++;
2217 sep_dev->sep_to_host_reply_counter++;
2219 dbg("SEP Driver:<-------- sep_send_reply_command_handler end\n");
2227 This function handles the allocate data pool memory request
2228 This function returns calculates the physical address of the
2229 allocated memory, and the offset of this area from the mapped address.
2230 Therefore, the FVOs in user space can calculate the exact virtual
2231 address of this allocated memory
2233 static int sep_allocate_data_pool_memory_handler(unsigned long arg)
2238 /* command paramaters */
2239 struct sep_driver_alloc_t command_args;
2241 /*-------------------------
2243 ----------------------------*/
2245 dbg("SEP Driver:--------> sep_allocate_data_pool_memory_handler start\n");
2248 error = copy_from_user(&command_args,
2250 sizeof(struct sep_driver_alloc_t));
2254 /* allocate memory */
2256 (sep_dev->data_pool_bytes_allocated + command_args.num_bytes) >
2257 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES) {
2262 /* set the virtual and physical address */
2263 command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2264 sep_dev->data_pool_bytes_allocated;
2265 command_args.phys_address = sep_dev->phys_shared_area_addr +
2266 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
2267 sep_dev->data_pool_bytes_allocated;
2269 /* write the memory back to the user space */
2270 error = copy_to_user((void *)arg,
2271 (void *)&command_args,
2272 sizeof(struct sep_driver_alloc_t));
2276 /* set the allocation */
2277 sep_dev->data_pool_bytes_allocated += command_args.num_bytes;
2281 dbg("SEP Driver:<-------- sep_allocate_data_pool_memory_handler end\n");
2287 This function handles write into allocated data pool command
2289 static int sep_write_into_data_pool_handler(unsigned long arg)
2294 /* virtual address */
2295 unsigned long virt_address;
2297 /* application in address */
2298 unsigned long app_in_address;
2300 /* number of bytes */
2301 unsigned long num_bytes;
2303 /* address of the data pool */
2304 unsigned long data_pool_area_addr;
2306 /*--------------------------
2308 -----------------------------*/
2310 dbg("SEP Driver:--------> sep_write_into_data_pool_handler start\n");
2312 /* get the application address */
2313 error = get_user(app_in_address,
2314 &(((struct sep_driver_write_t *)arg)->app_address));
2318 /* get the virtual kernel address address */
2319 error = get_user(virt_address,
2320 &(((struct sep_driver_write_t *)arg)->datapool_address));
2324 /* get the number of bytes */
2325 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2329 /* calculate the start of the data pool */
2330 data_pool_area_addr = sep_dev->shared_area_addr +
2331 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2334 /* check that the range of the virtual kernel address is correct */
2335 if ((virt_address < data_pool_area_addr) ||
2336 (virt_address > (data_pool_area_addr +
2337 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2342 /* copy the application data */
2343 error = copy_from_user((void *)virt_address,
2344 (void *)app_in_address,
2349 dbg("SEP Driver:<-------- sep_write_into_data_pool_handler end\n");
2355 this function handles the read from data pool command
2357 static int sep_read_from_data_pool_handler(unsigned long arg)
2362 /* virtual address of dest application buffer */
2363 unsigned long app_out_address;
2365 /* virtual address of the data pool */
2366 unsigned long virt_address;
2369 unsigned long num_bytes;
2371 /* address of the data pool */
2372 unsigned long data_pool_area_addr;
2374 /*------------------------
2376 -----------------------------*/
2378 dbg("SEP Driver:--------> sep_read_from_data_pool_handler start\n");
2380 /* get the application address */
2381 error = get_user(app_out_address,
2382 &(((struct sep_driver_write_t *)arg)->app_address));
2386 /* get the virtual kernel address address */
2387 error = get_user(virt_address,
2388 &(((struct sep_driver_write_t *)arg)->datapool_address));
2392 /* get the number of bytes */
2393 error = get_user(num_bytes, &(((struct sep_driver_write_t *)arg)->num_bytes));
2397 /* calculate the start of the data pool */
2398 data_pool_area_addr = sep_dev->shared_area_addr +
2399 SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES;
2401 /* check that the range of the virtual kernel address is correct */
2402 if ((virt_address < data_pool_area_addr) ||
2403 (virt_address > (data_pool_area_addr +
2404 SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES))) {
2409 /* copy the application data */
2410 error = copy_to_user((void *)app_out_address, (void *)virt_address,
2415 dbg("SEP Driver:<-------- sep_read_from_data_pool_handler end\n");
2422 this function handles tha request for creation of the DMA table
2423 for the synchronic symmetric operations (AES,DES)
2425 static int sep_create_sync_dma_tables_handler(unsigned long arg)
2430 /* command arguments */
2431 struct sep_driver_build_sync_table_t command_args;
2433 /*------------------------
2435 --------------------------*/
2437 dbg("SEP Driver:--------> sep_create_sync_dma_tables_handler start\n");
2439 error = copy_from_user(&command_args,
2441 sizeof(struct sep_driver_build_sync_table_t));
2446 "app_in_address is %08lx\n",
2447 command_args.app_in_address);
2449 "app_out_address is %08lx\n",
2450 command_args.app_out_address);
2452 "data_size is %lu\n",
2453 command_args.data_in_size);
2455 "block_size is %lu\n",
2456 command_args.block_size);
2459 /* check if we need to build only input table or input/output */
2460 if (command_args.app_out_address)
2461 /* prepare input and output tables */
2462 error = sep_prepare_input_output_dma_table(command_args.app_in_address,
2463 command_args.app_out_address,
2464 command_args.data_in_size,
2465 command_args.block_size,
2466 &command_args.in_table_address,
2467 &command_args.out_table_address,
2468 &command_args.in_table_num_entries,
2469 &command_args.out_table_num_entries,
2470 &command_args.table_data_size,
2471 command_args.isKernelVirtualAddress);
2473 /* prepare input tables */
2474 error = sep_prepare_input_dma_table(command_args.app_in_address,
2475 command_args.data_in_size,
2476 command_args.block_size,
2477 &command_args.in_table_address,
2478 &command_args.in_table_num_entries,
2479 &command_args.table_data_size,
2480 command_args.isKernelVirtualAddress);
2486 error = copy_to_user((void *)arg,
2487 (void *)&command_args,
2488 sizeof(struct sep_driver_build_sync_table_t));
2492 dbg("SEP Driver:<-------- sep_create_sync_dma_tables_handler end\n");
2498 this function handles the request for freeing dma table for synhronic actions
2500 int sep_free_dma_table_data_handler()
2502 /*-------------------------
2504 -----------------------------*/
2506 dbg("SEP Driver:--------> sep_free_dma_table_data_handler start\n");
2508 /* free input pages array */
2509 sep_free_dma_pages(sep_dev->in_page_array,
2510 sep_dev->in_num_pages,
2513 /* free output pages array if needed */
2514 if (sep_dev->out_page_array)
2515 sep_free_dma_pages(sep_dev->out_page_array,
2516 sep_dev->out_num_pages,
2519 /* reset all the values */
2520 sep_dev->in_page_array = 0;
2521 sep_dev->out_page_array = 0;
2522 sep_dev->in_num_pages = 0;
2523 sep_dev->out_num_pages = 0;
2526 dbg("SEP Driver:<-------- sep_free_dma_table_data_handler end\n");
2532 this function handles the request to create the DMA tables for flow
2534 static int sep_create_flow_dma_tables_handler(unsigned long arg)
2539 /* command arguments */
2540 struct sep_driver_build_flow_table_t command_args;
2542 /* first table - output */
2543 struct sep_lli_entry_t first_table_data;
2545 /* dma table data */
2546 struct sep_lli_entry_t last_table_data;
2548 /* pointer to the info entry of the previuos DMA table */
2549 struct sep_lli_entry_t *prev_info_entry_ptr;
2551 /* pointer to the flow data strucutre */
2552 struct sep_flow_context_t *flow_context_ptr;
2554 /*------------------------
2556 --------------------------*/
2558 dbg("SEP Driver:--------> sep_create_flow_dma_tables_handler start\n");
2560 /* init variables */
2561 prev_info_entry_ptr = 0;
2562 first_table_data.physical_address = 0xffffffff;
2564 /* find the free structure for flow data */
2565 error = sep_find_flow_context(SEP_FREE_FLOW_ID, &flow_context_ptr);
2569 error = copy_from_user(&command_args,
2571 sizeof(struct sep_driver_build_flow_table_t));
2575 /* create flow tables */
2576 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2577 command_args.virt_buff_data_addr,
2581 command_args.isKernelVirtualAddress);
2583 goto end_function_with_error;
2585 /* check if flow is static */
2586 if (!command_args.flow_type)
2587 /* point the info entry of the last to the info entry of the first */
2588 last_table_data = first_table_data;
2590 /* set output params */
2591 command_args.first_table_addr = first_table_data.physical_address;
2592 command_args.first_table_num_entries =
2593 ((first_table_data.block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS) &
2594 SEP_NUM_ENTRIES_MASK);
2595 command_args.first_table_data_size =
2596 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2598 /* send the parameters to user application */
2599 error = copy_to_user((void *)arg,
2601 sizeof(struct sep_driver_build_flow_table_t));
2603 goto end_function_with_error;
2605 /* all the flow created - update the flow entry with temp id */
2606 flow_context_ptr->flow_id = SEP_TEMP_FLOW_ID;
2608 /* set the processing tables data in the context */
2609 if (command_args.input_output_flag == SEP_DRIVER_IN_FLAG)
2610 flow_context_ptr->input_tables_in_process = first_table_data;
2612 flow_context_ptr->output_tables_in_process = first_table_data;
2616 end_function_with_error:
2618 /* free the allocated tables */
2619 sep_deallocated_flow_tables(&first_table_data);
2623 dbg("SEP Driver:<-------- sep_create_flow_dma_tables_handler end\n");
2630 this functio n handles add tables to flow
2632 static int sep_add_flow_tables_handler(unsigned long arg)
2637 /* number of entries */
2638 unsigned long num_entries;
2640 /* command arguments */
2641 struct sep_driver_add_flow_table_t command_args;
2643 /* pointer to the flow data strucutre */
2644 struct sep_flow_context_t *flow_context_ptr;
2646 /* first dma table data */
2647 struct sep_lli_entry_t first_table_data;
2649 /* last dma table data */
2650 struct sep_lli_entry_t last_table_data;
2652 /* pointer to the info entry of the current DMA table */
2653 struct sep_lli_entry_t *info_entry_ptr;
2655 /*--------------------------
2657 ----------------------------*/
2659 dbg("SEP Driver:--------> sep_add_flow_tables_handler start\n");
2661 /* get input parameters */
2662 error = copy_from_user(&command_args,
2664 sizeof(struct sep_driver_add_flow_table_t));
2668 /* find the flow structure for the flow id */
2669 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2673 /* prepare the flow dma tables */
2674 error = sep_prepare_flow_dma_tables(command_args.num_virtual_buffers,
2675 command_args.virt_buff_data_addr,
2679 command_args.isKernelVirtualAddress);
2681 goto end_function_with_error;
2683 /* now check if there is already an existing add table for this flow */
2684 if (command_args.inputOutputFlag == SEP_DRIVER_IN_FLAG) {
2685 /* this buffer was for input buffers */
2686 if (flow_context_ptr->input_tables_flag) {
2687 /* add table already exists - add the new tables to the end
2689 num_entries = (flow_context_ptr->last_input_table.block_size >>
2690 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2693 (struct sep_lli_entry_t *)
2694 (flow_context_ptr->last_input_table.physical_address +
2695 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2697 /* connect to list of tables */
2698 *info_entry_ptr = first_table_data;
2700 /* set the first table data */
2701 first_table_data = flow_context_ptr->first_input_table;
2703 /* set the input flag */
2704 flow_context_ptr->input_tables_flag = 1;
2706 /* set the first table data */
2707 flow_context_ptr->first_input_table = first_table_data;
2709 /* set the last table data */
2710 flow_context_ptr->last_input_table = last_table_data;
2711 } else /* this is output tables */ {
2712 /* this buffer was for input buffers */
2713 if (flow_context_ptr->output_tables_flag) {
2714 /* add table already exists - add the new tables to
2715 the end of the previous */
2716 num_entries = (flow_context_ptr->last_output_table.block_size >>
2717 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
2720 (struct sep_lli_entry_t *)
2721 (flow_context_ptr->last_output_table.physical_address +
2722 (sizeof(struct sep_lli_entry_t) * (num_entries - 1)));
2724 /* connect to list of tables */
2725 *info_entry_ptr = first_table_data;
2727 /* set the first table data */
2728 first_table_data = flow_context_ptr->first_output_table;
2730 /* set the input flag */
2731 flow_context_ptr->output_tables_flag = 1;
2733 /* set the first table data */
2734 flow_context_ptr->first_output_table = first_table_data;
2736 /* set the last table data */
2737 flow_context_ptr->last_output_table = last_table_data;
2740 /* set output params */
2741 command_args.first_table_addr = first_table_data.physical_address;
2742 command_args.first_table_num_entries = ((first_table_data.block_size >>
2743 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK);
2744 command_args.first_table_data_size =
2745 (first_table_data.block_size & SEP_TABLE_DATA_SIZE_MASK);
2747 /* send the parameters to user application */
2748 error = copy_to_user((void *)arg,
2750 sizeof(struct sep_driver_add_flow_table_t));
2752 goto end_function_with_error;
2754 end_function_with_error:
2756 /* free the allocated tables */
2757 sep_deallocated_flow_tables(&first_table_data);
2761 dbg("SEP Driver:<-------- sep_add_flow_tables_handler end\n");
2767 this function add the flow add message to the specific flow
2769 static int sep_add_flow_tables_message_handler(unsigned long arg)
2775 struct sep_driver_add_message_t command_args;
2778 struct sep_flow_context_t *flow_context_ptr;
2780 /*----------------------------
2782 ------------------------------*/
2784 dbg("SEP Driver:--------> sep_add_flow_tables_message_handler start\n");
2786 error = copy_from_user(&command_args,
2788 sizeof(struct sep_driver_add_message_t));
2793 if (command_args.message_size_in_bytes >
2794 SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES) {
2799 /* find the flow context */
2800 error = sep_find_flow_context(command_args.flow_id, &flow_context_ptr);
2804 /* copy the message into context */
2805 flow_context_ptr->message_size_in_bytes = command_args.message_size_in_bytes;
2807 error = copy_from_user(flow_context_ptr->message,
2808 (void *)command_args.message_address,
2809 command_args.message_size_in_bytes);
2814 dbg("SEP Driver:<-------- sep_add_flow_tables_message_handler end\n");
2821 this function returns the physical and virtual addresses of the static pool
2823 static int sep_get_static_pool_addr_handler(unsigned long arg)
2828 /* command arguments */
2829 struct sep_driver_static_pool_addr_t command_args;
2831 /*-----------------------------
2833 ------------------------------*/
2835 dbg("SEP Driver:--------> sep_get_static_pool_addr_handler start\n");
2837 /*prepare the output parameters in the struct */
2838 command_args.physical_static_address = sep_dev->phys_shared_area_addr +
2839 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2840 command_args.virtual_static_address = sep_dev->shared_area_addr +
2841 SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
2843 edbg("SEP Driver:physical_static_address is %08lx, virtual_static_address %08lx\n",
2844 command_args.physical_static_address,
2845 command_args.virtual_static_address);
2847 /* send the parameters to user application */
2848 error = copy_to_user((void *)arg,
2850 sizeof(struct sep_driver_static_pool_addr_t));
2856 dbg("SEP Driver:<-------- sep_get_static_pool_addr_handler end\n");
2862 this address gets the offset of the physical address from the start
2865 static int sep_get_physical_mapped_offset_handler(unsigned long arg)
2870 /* command arguments */
2871 struct sep_driver_get_mapped_offset_t command_args;
2873 /*-----------------------------
2875 ------------------------------*/
2877 dbg("SEP Driver:--------> sep_get_physical_mapped_offset_handler start\n");
2879 error = copy_from_user(&command_args,
2881 sizeof(struct sep_driver_get_mapped_offset_t));
2885 if (command_args.physical_address < sep_dev->phys_shared_area_addr) {
2890 /*prepare the output parameters in the struct */
2891 command_args.offset = command_args.physical_address -
2892 sep_dev->phys_shared_area_addr;
2894 edbg("SEP Driver:physical_address is %08lx, offset is %lu\n",
2895 command_args.physical_address,
2896 command_args.offset);
2898 /* send the parameters to user application */
2899 error = copy_to_user((void *)arg,
2901 sizeof(struct sep_driver_get_mapped_offset_t));
2907 dbg("SEP Driver:<-------- sep_get_physical_mapped_offset_handler end\n");
2916 static int sep_start_handler(void)
2919 unsigned long reg_val;
2922 unsigned long error;
2924 /*-----------------------------
2926 ------------------------------*/
2928 dbg("SEP Driver:--------> sep_start_handler start\n");
2932 /* wait in polling for message from SEP */
2934 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
2937 /* check the value */
2938 if (reg_val == 0x1) {
2939 /* fatal error - read erro status from GPRO */
2940 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
2946 dbg("SEP Driver:<-------- sep_start_handler end\n");
2952 this function handles the request for SEP initialization
2954 static int sep_init_handler(unsigned long arg)
2956 /* word from message */
2957 unsigned long message_word;
2960 unsigned long *message_ptr;
2962 /* command arguments */
2963 struct sep_driver_init_t command_args;
2966 unsigned long counter;
2969 unsigned long error;
2972 unsigned long reg_val;
2974 /*-------------------
2976 ---------------------*/
2978 dbg("SEP Driver:--------> sep_init_handler start\n");
2982 error = copy_from_user(&command_args, (void *)arg,
2983 sizeof(struct sep_driver_init_t));
2985 dbg("SEP Driver:--------> sep_init_handler - finished copy_from_user \n");
2990 /* PATCH - configure the DMA to single -burst instead of multi-burst */
2991 /*sep_configure_dma_burst();*/
2993 dbg("SEP Driver:--------> sep_init_handler - finished sep_configure_dma_burst \n");
2995 message_ptr = (unsigned long *)command_args.message_addr;
2997 /* set the base address of the SRAM */
2998 sep_write_reg(sep_dev, HW_SRAM_ADDR_REG_ADDR, HW_CC_SRAM_BASE_ADDRESS);
3001 counter < command_args.message_size_in_words;
3002 counter++, message_ptr++) {
3003 get_user(message_word, message_ptr);
3005 /* write data to SRAM */
3006 sep_write_reg(sep_dev, HW_SRAM_DATA_REG_ADDR,
3010 "SEP Driver:message_word is %lu\n",
3013 /* wait for write complete */
3014 sep_wait_sram_write(sep_dev);
3017 dbg("SEP Driver:--------> sep_init_handler - finished getting messages from user space\n");
3020 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR,
3024 reg_val = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
3025 } while (!(reg_val & 0xFFFFFFFD));
3027 dbg("SEP Driver:--------> sep_init_handler - finished waiting for reg_val & 0xFFFFFFFD \n");
3029 /* check the value */
3030 if (reg_val == 0x1) {
3032 "SEP Driver:init failed\n");
3034 error = sep_read_reg(sep_dev, 0x8060);
3036 "SEP Driver:sw monitor is %lu\n",
3039 /* fatal error - read erro status from GPRO */
3040 error = sep_read_reg(sep_dev, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
3042 "SEP Driver:error is %lu\n", error);
3048 dbg("SEP Driver:<-------- sep_init_handler end\n");
3055 this function handles the request cache and resident reallocation
3057 static int sep_realloc_cache_resident_handler(unsigned long arg)
3062 /* physical cache addr */
3063 unsigned long phys_cache_address;
3065 /* physical resident addr */
3066 unsigned long phys_resident_address;
3068 /* command arguments */
3069 struct sep_driver_realloc_cache_resident_t command_args;
3071 /*------------------
3073 ---------------------*/
3076 error = copy_from_user(&command_args,
3078 sizeof(struct sep_driver_realloc_cache_resident_t));
3082 /* copy cache and resident to the their intended locations */
3083 error = sep_copy_cache_resident_to_area(command_args.cache_addr,
3084 command_args.cache_size_in_bytes,
3085 command_args.resident_addr,
3086 command_args.resident_size_in_bytes,
3087 &phys_cache_address,
3088 &phys_resident_address);
3092 /* lock the area (if needed) */
3093 sep_lock_cache_resident_area();
3095 command_args.new_base_addr = sep_dev->phys_shared_area_addr;
3097 /* find the new base address according to the lowest address between
3098 cache, resident and shared area */
3099 if (phys_resident_address < command_args.new_base_addr)
3100 command_args.new_base_addr = phys_resident_address;
3101 if (phys_cache_address < command_args.new_base_addr)
3102 command_args.new_base_addr = phys_cache_address;
3104 /* set the return parameters */
3105 command_args.new_cache_addr = phys_cache_address;
3106 command_args.new_resident_addr = phys_resident_address;
3109 /* set the new shared area */
3110 command_args.new_shared_area_addr = sep_dev->phys_shared_area_addr;
3113 "SEP Driver:command_args.new_shared_area_addr is %08lx\n",
3114 command_args.new_shared_area_addr);
3116 "SEP Driver:command_args.new_base_addr is %08lx\n",
3117 command_args.new_base_addr);
3119 "SEP Driver:command_args.new_resident_addr is %08lx\n",
3120 command_args.new_resident_addr);
3122 "SEP Driver:command_args.new_cache_addr is %08lx\n",
3123 command_args.new_cache_addr);
3125 /* return to user */
3126 error = copy_to_user((void *)arg,
3127 (void *)&command_args,
3128 sizeof(struct sep_driver_realloc_cache_resident_t));
3136 this function handles the request for get time
3138 static int sep_get_time_handler(unsigned long arg)
3143 /* command arguments */
3144 struct sep_driver_get_time_t command_args;
3146 /*------------------------
3148 --------------------------*/
3150 error = sep_set_time(&command_args.time_physical_address,
3151 &command_args.time_value);
3153 /* return to user */
3154 error = copy_to_user((void *)arg,
3155 (void *)&command_args,
3156 sizeof(struct sep_driver_get_time_t));
3163 This api handles the setting of API mode to blocking or non-blocking
3165 static int sep_set_api_mode_handler(unsigned long arg)
3171 unsigned long mode_flag;
3173 /*----------------------------
3175 -----------------------------*/
3177 dbg("SEP Driver:--------> sep_set_api_mode_handler start\n");
3180 mode_flag, &(((struct sep_driver_set_api_mode_t *)arg)->mode));
3184 /* set the global flag */
3185 sep_dev->block_mode_flag = mode_flag;
3190 dbg("SEP Driver:<-------- sep_set_api_mode_handler end\n");
3196 This API handles the end transaction request
3198 static int sep_end_transaction_handler(unsigned long arg)
3200 /*----------------------------
3202 -----------------------------*/
3204 dbg("SEP Driver:--------> sep_end_transaction_handler start\n");
3206 #if 0/*!SEP_DRIVER_POLLING_MODE*/
3208 sep_write_reg(sep_dev, HW_HOST_IMR_REG_ADDR, 0x7FFF);
3210 /* release IRQ line */
3211 free_irq(SEP_DIRVER_IRQ_NUM, &sep_dev->reg_base_address);
3213 /* lock the sep mutex */
3214 mutex_unlock(&sep_mutex);
3217 dbg("SEP Driver:<-------- sep_end_transaction_handler end\n");
3222 /* handler for flow done interrupt */
3223 static void sep_flow_done_handler(struct work_struct *work)
3225 /* flow context_ptr */
3226 struct sep_flow_context_t *flow_data_ptr;
3227 /*-------------------------
3229 ---------------------------*/
3231 /* obtain the mutex */
3232 mutex_lock(&sep_mutex);
3234 /* get the pointer to context */
3235 flow_data_ptr = (struct sep_flow_context_t *)work;
3237 /* free all the current input tables in sep */
3238 sep_deallocated_flow_tables(&flow_data_ptr->input_tables_in_process);
3240 /* free all the current tables output tables in SEP (if needed) */
3241 if (flow_data_ptr->output_tables_in_process.physical_address != 0xffffffff)
3242 sep_deallocated_flow_tables(&flow_data_ptr->output_tables_in_process);
3244 /* check if we have additional tables to be sent to SEP only input
3245 flag may be checked */
3246 if (flow_data_ptr->input_tables_flag) {
3247 /* copy the message to the shared RAM and signal SEP */
3248 memcpy((void *)flow_data_ptr->message,
3249 (void *)sep_dev->shared_area_addr,
3250 flow_data_ptr->message_size_in_bytes);
3252 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR2_REG_ADDR, 0x2);
3254 mutex_unlock(&sep_mutex);
3259 This function creates a list of tables for flow and returns the data for
3260 the first and last tables of the list
3262 static int sep_prepare_flow_dma_tables(unsigned long num_virtual_buffers,
3263 unsigned long first_buff_addr,
3264 struct sep_flow_context_t *flow_data_ptr,
3265 struct sep_lli_entry_t *first_table_data_ptr,
3266 struct sep_lli_entry_t *last_table_data_ptr,
3267 bool isKernelVirtualAddress)
3272 /* virtaul address of one buffer */
3273 unsigned long virt_buff_addr;
3275 /* virtual size of one buffer */
3276 unsigned long virt_buff_size;
3278 /* table data for each created table */
3279 struct sep_lli_entry_t table_data;
3282 struct sep_lli_entry_t *info_entry_ptr;
3284 /* prevouis info entry */
3285 struct sep_lli_entry_t *prev_info_entry_ptr;
3290 /*-------------------------------
3292 ----------------------------------*/
3296 prev_info_entry_ptr = 0;
3298 /* init the first table to default */
3299 table_data.physical_address = 0xffffffff;
3300 first_table_data_ptr->physical_address = 0xffffffff;
3301 table_data.block_size = 0;
3303 for (i = 0; i < num_virtual_buffers; i++) {
3304 /* get the virtual buffer address */
3305 error = get_user(virt_buff_addr, &first_buff_addr);
3309 /* get the virtual buffer size */
3311 error = get_user(virt_buff_size, &first_buff_addr);
3315 /* advance the address to point to the next pair of address|size */
3318 /* now prepare the one flow LLI table from the data */
3319 error = sep_prepare_one_flow_dma_table(virt_buff_addr,
3324 isKernelVirtualAddress);
3329 /* if this is the first table - save it to return to the user
3331 *first_table_data_ptr = table_data;
3333 /* set the pointer to info entry */
3334 prev_info_entry_ptr = info_entry_ptr;
3336 /* not first table - the previous table info entry should
3338 prev_info_entry_ptr->block_size =
3339 (0x1 << SEP_INT_FLAG_OFFSET_IN_BITS) |
3340 (table_data.block_size);
3342 /* set the pointer to info entry */
3343 prev_info_entry_ptr = info_entry_ptr;
3347 /* set the last table data */
3348 *last_table_data_ptr = table_data;
3357 This function creates one DMA table for flow and returns its data,
3358 and pointer to its info entry
3360 static int sep_prepare_one_flow_dma_table(
3361 unsigned long virt_buff_addr,
3362 unsigned long virt_buff_size,
3363 struct sep_lli_entry_t *table_data,
3364 struct sep_lli_entry_t **info_entry_ptr,
3365 struct sep_flow_context_t *flow_data_ptr,
3366 bool isKernelVirtualAddress)
3371 /* the range in pages */
3372 unsigned long lli_array_size;
3374 /* array of pointers ot page */
3375 struct sep_lli_entry_t *lli_array;
3377 /* pointer to the entry in the dma table */
3378 struct sep_lli_entry_t *flow_dma_table_entry_ptr;
3380 /* address of the dma table */
3381 unsigned long *start_dma_table_ptr;
3383 /* total table data counter */
3384 unsigned long dma_table_data_count;
3386 /* pointer that will keep the pointer t the pages of the virtual buffer */
3387 struct page **page_array_ptr;
3390 unsigned long entry_count;
3392 /*-------------------------------
3394 ----------------------------------*/
3396 /* find the space for the new table */
3397 error = sep_find_free_flow_dma_table_space(&start_dma_table_ptr);
3401 /* check if the pages are in Kernel Virtual Address layout */
3402 if (isKernelVirtualAddress == true)
3403 /* lock kernel buffer in the memory */
3404 error = sep_lock_kernel_pages(virt_buff_addr,
3410 /* lock user buffer in the memory */
3411 error = sep_lock_user_pages(virt_buff_addr,
3420 /* set the pointer to page array at the beginning of table - this table is
3421 now considered taken */
3422 *start_dma_table_ptr = lli_array_size;
3424 /* point to the place of the pages pointers of the table */
3425 start_dma_table_ptr++;
3427 /* set the pages pointer */
3428 *start_dma_table_ptr = (unsigned long)page_array_ptr;
3430 /* set the pointer to the first entry */
3431 flow_dma_table_entry_ptr = (struct sep_lli_entry_t *)(++start_dma_table_ptr);
3433 /* now create the entries for table */
3434 for (dma_table_data_count = entry_count = 0;
3435 entry_count < lli_array_size;
3437 flow_dma_table_entry_ptr->physical_address =
3438 lli_array[entry_count].physical_address;
3440 flow_dma_table_entry_ptr->block_size =
3441 lli_array[entry_count].block_size;
3443 /* set the total data of a table */
3444 dma_table_data_count += lli_array[entry_count].block_size;
3446 flow_dma_table_entry_ptr++;
3449 /* set the physical address */
3450 table_data->physical_address = virt_to_phys(start_dma_table_ptr);
3452 /* set the num_entries and total data size */
3453 table_data->block_size = ((lli_array_size + 1) <<
3454 SEP_NUM_ENTRIES_OFFSET_IN_BITS) |
3455 (dma_table_data_count);
3457 /* set the info entry */
3458 flow_dma_table_entry_ptr->physical_address = 0xffffffff;
3459 flow_dma_table_entry_ptr->block_size = 0;
3461 /* set the pointer to info entry */
3462 *info_entry_ptr = flow_dma_table_entry_ptr;
3464 /* the array of the lli entries */
3474 This function returns pointer to the flow data structure
3475 that conatins the given id
3477 static int sep_find_flow_context(
3478 unsigned long flow_id,
3479 struct sep_flow_context_t **flow_data_ptr)
3482 unsigned long count;
3487 /*-----------------------
3489 ---------------------------*/
3494 always search for flow with id default first - in case we
3495 already started working on the flow there can be no situation
3496 when 2 flows are with default flag
3498 for (count = 0; count < SEP_DRIVER_NUM_FLOWS; count++) {
3499 if (sep_dev->flows_data_array[count].flow_id == flow_id) {
3500 *flow_data_ptr = &sep_dev->flows_data_array[count];
3505 if (count == SEP_DRIVER_NUM_FLOWS)
3513 this function find a space for the new flow dma table
3515 static int sep_find_free_flow_dma_table_space(
3516 unsigned long **table_address_ptr)
3521 /* pointer to the id field of the flow dma table */
3522 unsigned long *start_table_ptr;
3524 /* start address of the flow dma area */
3525 unsigned long flow_dma_area_start_addr;
3527 /* end address of the flow dma area */
3528 unsigned long flow_dma_area_end_addr;
3530 /* maximum table size in words */
3531 unsigned long table_size_in_words;
3533 /*---------------------
3535 -----------------------*/
3539 /* find the start address of the flow DMA table area */
3540 flow_dma_area_start_addr = sep_dev->shared_area_addr +
3541 SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES;
3543 /* set end address of the flow table area */
3544 flow_dma_area_end_addr = flow_dma_area_start_addr +
3545 SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES;
3547 /* set table size in words */
3548 table_size_in_words = SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE *
3549 (sizeof(struct sep_lli_entry_t) / sizeof(long)) + 2;
3551 /* set the pointer to the start address of DMA area */
3552 start_table_ptr = (unsigned long *)flow_dma_area_start_addr;
3554 /* find the space for the next table */
3555 while (((*start_table_ptr & 0x7FFFFFFF) != 0) &&
3556 ((unsigned long)start_table_ptr <
3557 flow_dma_area_end_addr))
3558 start_table_ptr += table_size_in_words;
3560 /* check if we reached the end of floa tables area */
3561 if ((unsigned long)start_table_ptr >= flow_dma_area_end_addr)
3564 *table_address_ptr = start_table_ptr;
3570 this function goes over all the flow tables connected to the given
3571 table and deallocate them
3573 static void sep_deallocated_flow_tables(struct sep_lli_entry_t *first_table_ptr)
3576 unsigned long *table_ptr;
3578 /* end address of the flow dma area */
3579 unsigned long num_entries;
3581 unsigned long num_pages;
3584 struct page **pages_ptr;
3586 /* maximum table size in words */
3587 struct sep_lli_entry_t *info_entry_ptr;
3589 /*-------------------------------
3591 ---------------------------------*/
3593 /* set the pointer to the first table */
3594 table_ptr = (unsigned long *)first_table_ptr->physical_address;
3596 /* set the num of entries */
3597 num_entries = (first_table_ptr->block_size >> SEP_NUM_ENTRIES_OFFSET_IN_BITS)
3598 & SEP_NUM_ENTRIES_MASK;
3600 /* go over all the connected tables */
3601 while (*table_ptr != 0xffffffff) {
3602 /* get number of pages */
3603 num_pages = *(table_ptr - 2);
3605 /* get the pointer to the pages */
3606 pages_ptr = (struct page **)(*(table_ptr - 1));
3608 /* free the pages */
3609 sep_free_dma_pages(pages_ptr, num_pages, 1);
3611 /* goto to the info entry */
3612 info_entry_ptr = ((struct sep_lli_entry_t *)table_ptr) +
3615 table_ptr = (unsigned long *)info_entry_ptr->physical_address;
3616 num_entries = (info_entry_ptr->block_size >>
3617 SEP_NUM_ENTRIES_OFFSET_IN_BITS) & SEP_NUM_ENTRIES_MASK;
3624 This function handler the set flow id command
3626 static int sep_set_flow_id_handler(unsigned long arg)
3632 unsigned long flow_id;
3634 /* pointer to flow data structre */
3635 struct sep_flow_context_t *flow_data_ptr;
3637 /*----------------------
3639 -----------------------*/
3641 dbg("------------>SEP Driver: sep_set_flow_id_handler start\n");
3643 error = get_user(flow_id,
3644 &(((struct sep_driver_set_flow_id_t *)arg)->flow_id));
3648 /* find the flow data structure that was just used for creating new flow
3649 - its id should be default */
3650 error = sep_find_flow_context(SEP_TEMP_FLOW_ID, &flow_data_ptr);
3655 flow_data_ptr->flow_id = flow_id;
3659 dbg("SEP Driver:<-------- sep_set_flow_id_handler end\n");
3667 calculates time and sets it at the predefined address
3669 static int sep_set_time(unsigned long *address_ptr,
3670 unsigned long *time_in_sec_ptr)
3673 struct timeval time;
3675 /* address of time in the kernel */
3676 unsigned long time_addr;
3679 /*------------------------
3681 --------------------------*/
3683 dbg("SEP Driver:--------> sep_set_time start\n");
3686 do_gettimeofday(&time);
3688 /* set value in the SYSTEM MEMORY offset */
3689 time_addr = sep_dev->message_shared_area_addr +
3690 SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES;
3692 *(unsigned long *)time_addr = SEP_TIME_VAL_TOKEN;
3693 *(unsigned long *)(time_addr + 4) = time.tv_sec;
3696 "SEP Driver:time.tv_sec is %lu\n",
3699 "SEP Driver:time_addr is %lu\n",
3702 "SEP Driver:g_message_shared_area_addr is %lu\n",
3703 sep_dev->message_shared_area_addr);
3705 /* set the output parameters if needed */
3707 *address_ptr = sep_shared_area_virt_to_phys(time_addr);
3709 if (time_in_sec_ptr)
3710 *time_in_sec_ptr = time.tv_sec;
3712 dbg("SEP Driver:<-------- sep_set_time end\n");
3717 static void sep_wait_busy(struct sep_device *dev)
3722 reg = sep_read_reg(sep_dev, HW_HOST_SEP_BUSY_REG_ADDR);
3727 PATCH for configuring the DMA to single burst instead of multi-burst
3729 static void sep_configure_dma_burst(void)
3732 #define HW_AHB_RD_WR_BURSTS_REG_ADDR 0x0E10UL
3734 dbg("SEP Driver:<-------- sep_configure_dma_burst start \n");
3736 /* request access to registers from SEP */
3737 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
3739 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (write reg) \n");
3741 sep_wait_busy(sep_dev);
3743 dbg("SEP Driver:<-------- sep_configure_dma_burst finished request access to registers from SEP (while(revVal) wait loop) \n");
3745 /* set the DMA burst register to single burst*/
3746 sep_write_reg(sep_dev, HW_AHB_RD_WR_BURSTS_REG_ADDR, 0x0UL);
3748 /* release the sep busy */
3749 sep_write_reg(sep_dev, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x0UL);
3750 sep_wait_busy(sep_dev);
3752 dbg("SEP Driver:<-------- sep_configure_dma_burst done \n");
3756 module_init(sep_init);
3757 module_exit(sep_exit);
3759 MODULE_LICENSE("GPL");