diff --git a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c index f083705c9..8136b7aa7 100644 --- a/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c +++ b/target/linux/xburst/files-2.6.31/arch/mips/jz4740/proc.c @@ -166,26 +166,6 @@ static int cgm_write_proc(struct file *file, const char *buffer, unsigned long c } -/* USAGE: - * echo n > /proc/jz/ipu // n = [1,...,9], alloc mem, 2^n pages. - * echo FF > /proc/jz/ipu // 255, free all buffer - * echo xxxx > /proc/jz/ipu // free buffer which addr is xxxx - * echo llll > /proc/jz/ipu // add_wired_entry(l,l,l,l) - * echo 0 > /proc/jz/ipu // debug, print ipu_buf - * od -X /proc/jz/ipu // read mem addr - */ - -typedef struct _ipu_buf { - unsigned int addr; /* phys addr */ - unsigned int page_shift; -} ipu_buf_t; - -#define IPU_BUF_MAX 4 /* 4 buffers */ - -static struct _ipu_buf ipu_buf[IPU_BUF_MAX]; -static int ipu_buf_cnt = 0; -static unsigned char g_asid=0; - extern void local_flush_tlb_all(void); /* CP0 hazard avoidance. */ @@ -235,244 +215,6 @@ void show_tlb(void) local_irq_restore(flags); } -static void ipu_add_wired_entry(unsigned long pid, - unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - struct task_struct *g, *p; - - /* We will lock an 4MB page size entry to map the 4MB reserved IPU memory */ - wired = read_c0_wired(); - if (wired) return; - - do_each_thread(g, p) { - if (p->pid == pid ) - g_asid = p->mm->context[0]; - } while_each_thread(g, p); - - local_irq_save(flags); - - entrylo0 = entrylo0 >> 6; /* PFN */ - entrylo0 |= 0x6 | (0 << 3); /* Write-through cacheable, dirty, valid */ - - /* Save old context and create impossible VPN2 value */ - old_ctx = read_c0_entryhi() & 0xff; - old_pagemask = read_c0_pagemask(); - write_c0_wired(wired + 1); - write_c0_index(wired); - BARRIER; - entryhi &= ~0xff; /* new add, 20070906 */ - entryhi |= g_asid; /* new add, 20070906 */ -// entryhi |= old_ctx; /* new add, 20070906 */ - write_c0_pagemask(pagemask); - write_c0_entryhi(entryhi); - write_c0_entrylo0(entrylo0); - write_c0_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - write_c0_entryhi(old_ctx); - BARRIER; - write_c0_pagemask(old_pagemask); - local_flush_tlb_all(); - local_irq_restore(flags); -#if defined(DEBUG) - printk("\nold_ctx=%03d\n", old_ctx); - - show_tlb(); -#endif -} - -static void ipu_del_wired_entry( void ) -{ - unsigned long flags; - unsigned long wired; - - /* Free all lock entry */ - local_irq_save(flags); - wired = read_c0_wired(); - if (wired) - write_c0_wired(0); - local_irq_restore(flags); -} - -static inline void ipu_buf_get( unsigned int page_shift ) -{ - unsigned char * virt_addr; - int i; - for ( i=0; i< IPU_BUF_MAX; ++i ) { - if ( ipu_buf[i].addr == 0 ) { - break; - } - } - - if ( (ipu_buf_cnt = i) == IPU_BUF_MAX ) { - printk("Error, no free ipu buffer.\n"); - return ; - } - - virt_addr = (unsigned char *)__get_free_pages(GFP_KERNEL, page_shift); - - if ( virt_addr ) { - ipu_buf[ipu_buf_cnt].addr = (unsigned int)virt_to_phys((void *)virt_addr); - ipu_buf[ipu_buf_cnt].page_shift = page_shift; - - for (i = 0; i < (1<= IPU_BUF_MAX ) { /* failed alloc mem, rturn 0 */ - printk("no free buffer.\n"); - *pint = 0; - } - else - *pint = (unsigned int )ipu_buf[ipu_buf_cnt].addr; /* phys addr */ - len += sizeof(unsigned int); - -#if defined(DEBUG) - show_tlb(); -#endif - return len; - -} - -static int ipu_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -{ - unsigned int val ; - int cnt,i; - char buf[12]; - unsigned long pid, entrylo0, entrylo1, entryhi, pagemask; -#if defined(DEBUG) - printk("ipu write count=%u\n", count); -#endif - if (count == (8*5+1)) { - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer+8*0, 8); - pid = simple_strtoul(buf, 0, 16); - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer+8*1, 8); - entrylo0 = simple_strtoul(buf, 0, 16); - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer+8*2, 8); - entrylo1 = simple_strtoul(buf, 0, 16); - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer+8*3, 8); - entryhi = simple_strtoul(buf, 0, 16); - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer+8*4, 8); - pagemask = simple_strtoul(buf, 0, 16); - -#if defined(DEBUG) - printk("pid=0x%08x, entrylo0=0x%08x, entrylo1=0x%08x, entryhi=0x%08x, pagemask=0x%08x\n", - pid, entrylo0, entrylo1, entryhi, pagemask); -#endif - ipu_add_wired_entry( pid, entrylo0, entrylo1, entryhi, pagemask); - return 41; - } else if ( count <= 8+1 ) { - for (i=0;i<12;i++) buf[i]=0; - strncpy(buf, buffer, 8); - val = simple_strtoul(buf, 0, 16); - } else if (count == 44) { - for (i = 0; i < 12; i++) - buf[i] = 0; - strncpy(buf, buffer, 10); - pid = simple_strtoul(buf, 0, 16); - for (i = 0; i < 12; i++) - buf[i] = 0; - strncpy(buf, buffer + 11, 10); - entryhi = simple_strtoul(buf, 0, 16);//vaddr - for (i = 0; i < 12; i++) - buf[i] = 0; - strncpy(buf, buffer + 22, 10); - entrylo0 = simple_strtoul(buf, 0, 16);//paddr - for (i = 0; i < 12; i++) - buf[i] = 0; - strncpy(buf, buffer + 33, 10); - pagemask = simple_strtoul(buf, 0, 16); - pagemask = 0x3ff << 13; /* Fixed to 4MB page size */ - ipu_add_wired_entry(pid, entrylo0, 0, entryhi, pagemask); - return 44; - } else { - printk("ipu write count error, count=%d\n.", (unsigned int)count); - return -1; - } - - /* val: 1-9, page_shift, val>= 10: ipu_buf.addr */ - if ( val == 0 ) { /* debug, print ipu_buf info */ - for ( cnt=0; cnt /proc/jz/imem // n = [0,...,10], allocate memory, 2^n pages - * echo xxxxxxxx > /proc/jz/imem // free buffer which addr is xxxxxxxx - * echo FF > /proc/jz/ipu // FF, free all buffers - * od -X /proc/jz/imem // return the allocated buffer address and the max order of free buffer - */ - -//#define DEBUG_IMEM 1 - -#define IMEM_MAX_ORDER 10 /* max 2^10 * 4096 = 4MB */ - -static unsigned int jz_imem_base; /* physical base address of ipu memory */ - -static unsigned int allocated_phys_addr = 0; - -/* - * Allocated buffer list - */ -typedef struct imem_list { - unsigned int phys_start; /* physical start addr */ - unsigned int phys_end; /* physical end addr */ - struct imem_list *next; -} imem_list_t; - -static struct imem_list *imem_list_head = NULL; /* up sorted by phys_start */ - -#ifdef DEBUG_IMEM -static void dump_imem_list(void) -{ - struct imem_list *imem; - - printk("*** dump_imem_list 0x%x ***\n", (u32)imem_list_head); - imem = imem_list_head; - while (imem) { - printk("imem=0x%x phys_start=0x%x phys_end=0x%x next=0x%x\n", (u32)imem, imem->phys_start, imem->phys_end, (u32)imem->next); - imem = imem->next; - } -} -#endif - -/* allocate 2^order pages inside the 4MB memory */ -static int imem_alloc(unsigned int order) -{ - int alloc_ok = 0; - unsigned int start, end; - unsigned int size = (1 << order) * PAGE_SIZE; - struct imem_list *imem, *imemn, *imemp; - - allocated_phys_addr = 0; - - start = jz_imem_base; - end = start + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; - - imem = imem_list_head; - while (imem) { - if ((imem->phys_start - start) >= size) { - /* we got a valid address range */ - alloc_ok = 1; - break; - } - - start = imem->phys_end + 1; - imem = imem->next; - } - - if (!alloc_ok) { - if ((end - start) >= size) - alloc_ok = 1; - } - - if (alloc_ok) { - end = start + size - 1; - allocated_phys_addr = start; - - /* add to imem_list, up sorted by phys_start */ - imemn = kmalloc(sizeof(struct imem_list), GFP_KERNEL); - if (!imemn) { - return -ENOMEM; - } - imemn->phys_start = start; - imemn->phys_end = end; - imemn->next = NULL; - - if (!imem_list_head) - imem_list_head = imemn; - else { - imem = imemp = imem_list_head; - while (imem) { - if (start < imem->phys_start) { - break; - } - - imemp = imem; - imem = imem->next; - } - - if (imem == imem_list_head) { - imem_list_head = imemn; - imemn->next = imem; - } - else { - imemn->next = imemp->next; - imemp->next = imemn; - } - } - } - -#ifdef DEBUG_IMEM - dump_imem_list(); -#endif - return 0; -} - -static void imem_free(unsigned int phys_addr) -{ - struct imem_list *imem, *imemp; - - imem = imemp = imem_list_head; - while (imem) { - if (phys_addr == imem->phys_start) { - if (imem == imem_list_head) { - imem_list_head = imem->next; - } - else { - imemp->next = imem->next; - } - - kfree(imem); - break; - } - - imemp = imem; - imem = imem->next; - } - -#ifdef DEBUG_IMEM - dump_imem_list(); -#endif -} - -static void imem_free_all(void) -{ - struct imem_list *imem; - - imem = imem_list_head; - while (imem) { - kfree(imem); - imem = imem->next; - } - - imem_list_head = NULL; - - allocated_phys_addr = 0; - -#ifdef DEBUG_IMEM - dump_imem_list(); -#endif -} - -/* - * Return the allocated buffer address and the max order of free buffer - */ -static int imem_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = 0; - unsigned int start_addr, end_addr, max_order, max_size; - struct imem_list *imem; - - unsigned int *tmp = (unsigned int *)(page + len); - - start_addr = jz_imem_base; - end_addr = start_addr + (1 << IMEM_MAX_ORDER) * PAGE_SIZE; - - if (!imem_list_head) - max_size = end_addr - start_addr; - else { - max_size = 0; - imem = imem_list_head; - while (imem) { - if (max_size < (imem->phys_start - start_addr)) - max_size = imem->phys_start - start_addr; - - start_addr = imem->phys_end + 1; - imem = imem->next; - } - - if (max_size < (end_addr - start_addr)) - max_size = end_addr - start_addr; - } - - if (max_size > 0) { - max_order = get_order(max_size); - if (((1 << max_order) * PAGE_SIZE) > max_size) - max_order--; - } - else { - max_order = 0xffffffff; /* No any free buffer */ - } - - *tmp++ = allocated_phys_addr; /* address allocated by 'echo n > /proc/jz/imem' */ - *tmp = max_order; /* max order of current free buffers */ - - len += 2 * sizeof(unsigned int); - - return len; -} - -static int imem_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) -{ - unsigned int val; - - val = simple_strtoul(buffer, 0, 16); - - if (val == 0xff) { - /* free all memory */ - imem_free_all(); - ipu_del_wired_entry(); - } - else if ((val >= 0) && (val <= IMEM_MAX_ORDER)) { - /* allocate 2^val pages */ - imem_alloc(val); - } - else { - /* free buffer which phys_addr is val */ - imem_free(val); - } - - return count; -} - /* * /proc/jz/xxx entry * @@ -791,14 +294,6 @@ static int __init jz_proc_init(void) res->data = NULL; } - /* Image process unit */ - res = create_proc_entry("ipu", 0644, proc_jz_root); - if (res) { - res->read_proc = ipu_read_proc; - res->write_proc = ipu_write_proc; - res->data = NULL; - } - /* udc hotplug */ res = create_proc_entry("udc", 0644, proc_jz_root); if (res) { @@ -807,33 +302,6 @@ static int __init jz_proc_init(void) res->data = NULL; } - /* - * Reserve a 4MB memory for IPU on JZ4740. - */ - jz_imem_base = (unsigned int)__get_free_pages(GFP_KERNEL, IMEM_MAX_ORDER); - if (jz_imem_base) { - /* imem (IPU memory management) */ - res = create_proc_entry("imem", 0644, proc_jz_root); - if (res) { - res->read_proc = imem_read_proc; - res->write_proc = imem_write_proc; - res->data = NULL; - } - - /* Set page reserved */ - virt_addr = jz_imem_base; - for (i = 0; i < (1 << IMEM_MAX_ORDER); i++) { - SetPageReserved(virt_to_page((void *)virt_addr)); - virt_addr += PAGE_SIZE; - } - - /* Convert to physical address */ - jz_imem_base = virt_to_phys((void *)jz_imem_base); - - printk("Total %dMB memory at 0x%x was reserved for IPU\n", - (unsigned int)((1 << IMEM_MAX_ORDER) * PAGE_SIZE)/1000000, jz_imem_base); - } - return 0; }