From 2512fd29db4eb09e82d182596304c7aaf76d2c5c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 15 Jan 2009 18:26:05 +0200 Subject: [PATCH] REMOVE OMAP LEGACY CODE: Remove dspgateway This is moved into a dspgateway branch against the mainline tree. Signed-off-by: Tony Lindgren --- arch/arm/Kconfig | 1 - arch/arm/include/asm/pgtable.h | 1 - arch/arm/mach-omap1/Makefile | 2 - arch/arm/mach-omap1/mmu.c | 351 -- arch/arm/mach-omap1/mmu.h | 119 - arch/arm/mach-omap2/Makefile | 2 - arch/arm/mach-omap2/mmu.c | 330 -- arch/arm/mach-omap2/mmu.h | 117 - arch/arm/plat-omap/Kconfig | 8 - arch/arm/plat-omap/Makefile | 3 - arch/arm/plat-omap/include/mach/dsp.h | 118 - arch/arm/plat-omap/include/mach/dsp_common.h | 53 +- arch/arm/plat-omap/include/mach/mmu.h | 211 -- arch/arm/plat-omap/mmu.c | 1563 --------- drivers/Makefile | 1 - drivers/dsp/dspgateway/Kconfig | 24 - drivers/dsp/dspgateway/Makefile | 15 - drivers/dsp/dspgateway/dsp.h | 391 --- drivers/dsp/dspgateway/dsp_common.c | 639 ---- drivers/dsp/dspgateway/dsp_core.c | 646 ---- drivers/dsp/dspgateway/dsp_ctl.c | 1069 ------ drivers/dsp/dspgateway/dsp_ctl_core.c | 132 - drivers/dsp/dspgateway/dsp_mbcmd.h | 147 - drivers/dsp/dspgateway/dsp_mem.c | 484 --- drivers/dsp/dspgateway/error.c | 227 -- drivers/dsp/dspgateway/hardware_dsp.h | 34 - drivers/dsp/dspgateway/ipbuf.c | 353 -- drivers/dsp/dspgateway/ipbuf.h | 193 -- drivers/dsp/dspgateway/mblog.c | 280 -- drivers/dsp/dspgateway/mmu.h | 140 - drivers/dsp/dspgateway/omap1_dsp.h | 114 - drivers/dsp/dspgateway/omap2_dsp.h | 95 - drivers/dsp/dspgateway/proclist.h | 87 - drivers/dsp/dspgateway/task.c | 3041 ------------------ drivers/dsp/dspgateway/taskwatch.c | 164 - drivers/dsp/dspgateway/uaccess_dsp.S | 77 - drivers/dsp/dspgateway/uaccess_dsp.h | 176 - include/linux/kfifo.h | 35 - kernel/kfifo.c | 57 - 39 files changed, 14 insertions(+), 11486 deletions(-) delete mode 100644 arch/arm/mach-omap1/mmu.c delete mode 100644 arch/arm/mach-omap1/mmu.h delete mode 100644 arch/arm/mach-omap2/mmu.c delete mode 100644 arch/arm/mach-omap2/mmu.h delete mode 100644 arch/arm/plat-omap/include/mach/dsp.h delete mode 100644 arch/arm/plat-omap/include/mach/mmu.h delete mode 100644 arch/arm/plat-omap/mmu.c delete mode 100644 drivers/dsp/dspgateway/Kconfig delete mode 100644 drivers/dsp/dspgateway/Makefile delete mode 100644 drivers/dsp/dspgateway/dsp.h delete mode 100644 drivers/dsp/dspgateway/dsp_common.c delete mode 100644 drivers/dsp/dspgateway/dsp_core.c delete mode 100644 drivers/dsp/dspgateway/dsp_ctl.c delete mode 100644 drivers/dsp/dspgateway/dsp_ctl_core.c delete mode 100644 drivers/dsp/dspgateway/dsp_mbcmd.h delete mode 100644 drivers/dsp/dspgateway/dsp_mem.c delete mode 100644 drivers/dsp/dspgateway/error.c delete mode 100644 drivers/dsp/dspgateway/hardware_dsp.h delete mode 100644 drivers/dsp/dspgateway/ipbuf.c delete mode 100644 drivers/dsp/dspgateway/ipbuf.h delete mode 100644 drivers/dsp/dspgateway/mblog.c delete mode 100644 drivers/dsp/dspgateway/mmu.h delete mode 100644 drivers/dsp/dspgateway/omap1_dsp.h delete mode 100644 drivers/dsp/dspgateway/omap2_dsp.h delete mode 100644 drivers/dsp/dspgateway/proclist.h delete mode 100644 drivers/dsp/dspgateway/task.c delete mode 100644 drivers/dsp/dspgateway/taskwatch.c delete mode 100644 drivers/dsp/dspgateway/uaccess_dsp.S delete mode 100644 drivers/dsp/dspgateway/uaccess_dsp.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7b180ac7389..e7fb2016a1a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1329,7 +1329,6 @@ source "drivers/staging/Kconfig" if ARCH_OMAP source "drivers/cbus/Kconfig" -source "drivers/dsp/dspgateway/Kconfig" endif endmenu diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index fef8fc16db5..110295c5461 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -317,7 +317,6 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } #define pmd_none(pmd) (!pmd_val(pmd)) #define pmd_present(pmd) (pmd_val(pmd)) #define pmd_bad(pmd) (pmd_val(pmd) & 2) -#define pmd_table(pmd) ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE) #define copy_pmd(pmdpd,pmdps) \ do { \ diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index d8b7e1cbfc8..6867cd3ad0b 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile @@ -14,10 +14,8 @@ obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o obj-$(CONFIG_PM) += pm.o sleep.o # DSP -obj-$(CONFIG_OMAP_MMU_FWK) += mmu_mach.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o -mmu_mach-objs := mmu.o led-y := leds.o diff --git a/arch/arm/mach-omap1/mmu.c b/arch/arm/mach-omap1/mmu.c deleted file mode 100644 index 75dd310a907..00000000000 --- a/arch/arm/mach-omap1/mmu.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * linux/arch/arm/mach-omap1/mmu.c - * - * Support for non-MPU OMAP1 MMUs. - * - * Copyright (C) 2002-2005 Nokia Corporation - * - * Written by Toshihiro Kobayashi - * and Paul Mundt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "mmu.h" -#include -#include - -static void *dspvect_page; -#define DSP_INIT_PAGE 0xfff000 - -#define MMUFAULT_MASK (OMAP_MMU_FAULT_ST_PERM |\ - OMAP_MMU_FAULT_ST_TLB_MISS |\ - OMAP_MMU_FAULT_ST_TRANS) - -static unsigned int get_cam_l_va_mask(u16 pgsz) -{ - switch (pgsz) { - case OMAP_MMU_CAM_PAGESIZE_1MB: - return OMAP_MMU_CAM_L_VA_TAG_L1_MASK | - OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1MB; - case OMAP_MMU_CAM_PAGESIZE_64KB: - return OMAP_MMU_CAM_L_VA_TAG_L1_MASK | - OMAP_MMU_CAM_L_VA_TAG_L2_MASK_64KB; - case OMAP_MMU_CAM_PAGESIZE_4KB: - return OMAP_MMU_CAM_L_VA_TAG_L1_MASK | - OMAP_MMU_CAM_L_VA_TAG_L2_MASK_4KB; - case OMAP_MMU_CAM_PAGESIZE_1KB: - return OMAP_MMU_CAM_L_VA_TAG_L1_MASK | - OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1KB; - } - return 0; -} - -#define get_cam_va_mask(pgsz) \ - ((u32)OMAP_MMU_CAM_H_VA_TAG_H_MASK << 22 | \ - (u32)get_cam_l_va_mask(pgsz) << 6) - -static int intmem_usecount; - -/* for safety */ -void dsp_mem_usecount_clear(void) -{ - if (intmem_usecount != 0) { - printk(KERN_WARNING - "MMU: unbalanced memory request/release detected.\n" - " intmem_usecount is not zero at where " - "it should be! ... fixed to be zero.\n"); - intmem_usecount = 0; - omap_dsp_release_mem(); - } -} -EXPORT_SYMBOL_GPL(dsp_mem_usecount_clear); - -void omap_mmu_itack(struct omap_mmu *mmu) -{ - omap_mmu_write_reg(mmu, OMAP_MMU_IT_ACK_IT_ACK, OMAP_MMU_IT_ACK); -} -EXPORT_SYMBOL(omap_mmu_itack); - -static int omap1_mmu_mem_enable(struct omap_mmu *mmu, void *addr) -{ - int ret = 0; - - if (omap_mmu_internal_memory(mmu, addr)) { - if (intmem_usecount++ == 0) - ret = omap_dsp_request_mem(); - } - - return ret; -} - -static int omap1_mmu_mem_disable(struct omap_mmu *mmu, void *addr) -{ - int ret = 0; - - if (omap_mmu_internal_memory(mmu, addr)) { - if (--intmem_usecount == 0) - omap_dsp_release_mem(); - } else - ret = -EIO; - - return ret; -} - -static inline void -omap1_mmu_read_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - /* read a TLB entry */ - omap_mmu_write_reg(mmu, OMAP_MMU_LD_TLB_RD, OMAP_MMU_LD_TLB); - - cr->cam_h = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM_H); - cr->cam_l = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM_L); - cr->ram_h = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM_H); - cr->ram_l = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM_L); -} - -static inline void -omap1_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - /* Set the CAM and RAM entries */ - omap_mmu_write_reg(mmu, cr->cam_h, OMAP_MMU_CAM_H); - omap_mmu_write_reg(mmu, cr->cam_l, OMAP_MMU_CAM_L); - omap_mmu_write_reg(mmu, cr->ram_h, OMAP_MMU_RAM_H); - omap_mmu_write_reg(mmu, cr->ram_l, OMAP_MMU_RAM_L); -} - -static ssize_t omap1_mmu_show(struct omap_mmu *mmu, char *buf, - struct omap_mmu_tlb_lock *tlb_lock) -{ - int i, len; - - len = sprintf(buf, "P: preserved, V: valid\n" - "ety P V size cam_va ram_pa ap\n"); - /* 00: P V 4KB 0x300000 0x10171800 FA */ - - for (i = 0; i < mmu->nr_tlb_entries; i++) { - struct omap_mmu_tlb_entry ent; - struct cam_ram_regset cr; - struct omap_mmu_tlb_lock entry_lock; - char *pgsz_str, *ap_str; - - /* read a TLB entry */ - entry_lock.base = tlb_lock->base; - entry_lock.victim = i; - omap_mmu_read_tlb(mmu, &entry_lock, &cr); - - ent.pgsz = cr.cam_l & OMAP_MMU_CAM_PAGESIZE_MASK; - ent.prsvd = cr.cam_l & OMAP_MMU_CAM_P; - ent.valid = cr.cam_l & OMAP_MMU_CAM_V; - ent.ap = cr.ram_l & OMAP_MMU_RAM_L_AP_MASK; - ent.va = (u32)(cr.cam_h & OMAP_MMU_CAM_H_VA_TAG_H_MASK) << 22 | - (u32)(cr.cam_l & get_cam_l_va_mask(ent.pgsz)) << 6; - ent.pa = (unsigned long)cr.ram_h << 16 | - (cr.ram_l & OMAP_MMU_RAM_L_RAM_LSB_MASK); - - pgsz_str = (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1MB) ? " 1MB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_64KB) ? "64KB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_4KB) ? " 4KB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1KB) ? " 1KB": - " ???"; - ap_str = (ent.ap == OMAP_MMU_RAM_L_AP_RO) ? "RO": - (ent.ap == OMAP_MMU_RAM_L_AP_FA) ? "FA": - (ent.ap == OMAP_MMU_RAM_L_AP_NA) ? "NA": - "??"; - - if (i == tlb_lock->base) - len += sprintf(buf + len, "lock base = %d\n", - tlb_lock->base); - if (i == tlb_lock->victim) - len += sprintf(buf + len, "victim = %d\n", - tlb_lock->victim); - len += sprintf(buf + len, - /* 00: P V 4KB 0x300000 0x10171800 FA */ - "%02d: %c %c %s 0x%06lx 0x%08lx %s\n", - i, - ent.prsvd ? 'P' : ' ', - ent.valid ? 'V' : ' ', - pgsz_str, ent.va, ent.pa, ap_str); - } - - return len; -} - -static int exmap_setup_preserved_entries(struct omap_mmu *mmu) -{ - int n = 0; - - exmap_setup_preserved_mem_page(mmu, dspvect_page, DSP_INIT_PAGE, n++); - - return n; -} - -static void exmap_clear_preserved_entries(struct omap_mmu *mmu) -{ - exmap_clear_mem_page(mmu, DSP_INIT_PAGE); -} - -static int omap1_mmu_startup(struct omap_mmu *mmu) -{ - dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0); - if (dspvect_page == NULL) { - dev_err(mmu->dev, "MMU %s: failed to allocate memory " - "for vector table\n", mmu->name); - return -ENOMEM; - } - - mmu->nr_exmap_preserved = exmap_setup_preserved_entries(mmu); - - return 0; -} - -static void omap1_mmu_shutdown(struct omap_mmu *mmu) -{ - exmap_clear_preserved_entries(mmu); - - if (dspvect_page != NULL) { - unsigned long virt; - - down_read(&mmu->exmap_sem); - - virt = (unsigned long)omap_mmu_to_virt(mmu, DSP_INIT_PAGE); - flush_tlb_kernel_range(virt, virt + PAGE_SIZE); - free_page((unsigned long)dspvect_page); - dspvect_page = NULL; - - up_read(&mmu->exmap_sem); - } -} - -static inline unsigned long omap1_mmu_cam_va(struct cam_ram_regset *cr) -{ - unsigned int page_size = cr->cam_l & OMAP_MMU_CAM_PAGESIZE_MASK; - - return (u32)(cr->cam_h & OMAP_MMU_CAM_H_VA_TAG_H_MASK) << 22 | - (u32)(cr->cam_l & get_cam_l_va_mask(page_size)) << 6; -} - -static struct cam_ram_regset * -omap1_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry) -{ - struct cam_ram_regset *cr; - - if (entry->va & ~(get_cam_va_mask(entry->pgsz))) { - dev_err(mmu->dev, "MMU %s: mapping vadr (0x%06lx) is not on" - " an aligned boundary\n", mmu->name, entry->va); - return ERR_PTR(-EINVAL); - } - - cr = kmalloc(sizeof(struct cam_ram_regset), GFP_KERNEL); - - cr->cam_h = entry->va >> 22; - cr->cam_l = (entry->va >> 6 & get_cam_l_va_mask(entry->pgsz)) | - entry->prsvd | entry->pgsz; - cr->ram_h = entry->pa >> 16; - cr->ram_l = (entry->pa & OMAP_MMU_RAM_L_RAM_LSB_MASK) | entry->ap; - - return cr; -} - -static inline int omap1_mmu_cam_ram_valid(struct cam_ram_regset *cr) -{ - return cr->cam_l & OMAP_MMU_CAM_V; -} - -static void omap1_mmu_interrupt(struct omap_mmu *mmu) -{ - unsigned long status; - unsigned long adh, adl; - unsigned long dp; - unsigned long va; - - status = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_ST); - adh = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD_H); - adl = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD_L); - dp = adh & OMAP_MMU_FAULT_AD_H_DP; - va = (((adh & OMAP_MMU_FAULT_AD_H_ADR_MASK) << 16) | adl); - - /* if the fault is masked, nothing to do */ - if ((status & MMUFAULT_MASK) == 0) { - pr_debug("MMU interrupt, but ignoring.\n"); - /* - * note: in OMAP1710, - * when CACHE + DMA domain gets out of idle in DSP, - * MMU interrupt occurs but MMU_FAULT_ST is not set. - * in this case, we just ignore the interrupt. - */ - if (status) { - pr_debug("%s%s%s%s\n", - (status & OMAP_MMU_FAULT_ST_PREF)? - " (prefetch err)" : "", - (status & OMAP_MMU_FAULT_ST_PERM)? - " (permission fault)" : "", - (status & OMAP_MMU_FAULT_ST_TLB_MISS)? - " (TLB miss)" : "", - (status & OMAP_MMU_FAULT_ST_TRANS) ? - " (translation fault)": ""); - pr_debug("fault address = %#08lx\n", va); - } - enable_irq(mmu->irq); - return; - } - - pr_info("%s%s%s%s\n", - (status & OMAP_MMU_FAULT_ST_PREF)? - (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_PREF)? - " prefetch err": - " (prefetch err)": - "", - (status & OMAP_MMU_FAULT_ST_PERM)? - (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_PERM)? - " permission fault": - " (permission fault)": - "", - (status & OMAP_MMU_FAULT_ST_TLB_MISS)? - (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_TLB_MISS)? - " TLB miss": - " (TLB miss)": - "", - (status & OMAP_MMU_FAULT_ST_TRANS)? - (MMUFAULT_MASK & OMAP_MMU_FAULT_ST_TRANS)? - " translation fault": - " (translation fault)": - ""); - pr_info("fault address = %#08lx\n", va); - - mmu->fault_address = va; - schedule_work(&mmu->irq_work); -} - -static pgprot_t omap1_mmu_pte_get_attr(struct omap_mmu_tlb_entry *entry) -{ - /* 4KB AP position as default */ - u32 attr = entry->ap >> 4; - attr <<= ((entry->pgsz == OMAP_MMU_CAM_PAGESIZE_1MB) ? 6:0); - return attr; -} - -struct omap_mmu_ops omap1_mmu_ops = { - .startup = omap1_mmu_startup, - .shutdown = omap1_mmu_shutdown, - .mem_enable = omap1_mmu_mem_enable, - .mem_disable = omap1_mmu_mem_disable, - .read_tlb = omap1_mmu_read_tlb, - .load_tlb = omap1_mmu_load_tlb, - .show = omap1_mmu_show, - .cam_va = omap1_mmu_cam_va, - .cam_ram_alloc = omap1_mmu_cam_ram_alloc, - .cam_ram_valid = omap1_mmu_cam_ram_valid, - .interrupt = omap1_mmu_interrupt, - .pte_get_attr = omap1_mmu_pte_get_attr, -}; -EXPORT_SYMBOL_GPL(omap1_mmu_ops); diff --git a/arch/arm/mach-omap1/mmu.h b/arch/arm/mach-omap1/mmu.h deleted file mode 100644 index b0255af2b1d..00000000000 --- a/arch/arm/mach-omap1/mmu.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __MACH_OMAP1_MMU_H -#define __MACH_OMAP1_MMU_H - -#include -#include - -#define MMU_LOCK_BASE_MASK (0x3f << 10) -#define MMU_LOCK_VICTIM_MASK (0x3f << 4) - -#define OMAP_MMU_PREFETCH 0x00 -#define OMAP_MMU_WALKING_ST 0x04 -#define OMAP_MMU_CNTL 0x08 -#define OMAP_MMU_FAULT_AD_H 0x0c -#define OMAP_MMU_FAULT_AD_L 0x10 -#define OMAP_MMU_FAULT_ST 0x14 -#define OMAP_MMU_IT_ACK 0x18 -#define OMAP_MMU_TTB_H 0x1c -#define OMAP_MMU_TTB_L 0x20 -#define OMAP_MMU_LOCK 0x24 -#define OMAP_MMU_LD_TLB 0x28 -#define OMAP_MMU_CAM_H 0x2c -#define OMAP_MMU_CAM_L 0x30 -#define OMAP_MMU_RAM_H 0x34 -#define OMAP_MMU_RAM_L 0x38 -#define OMAP_MMU_GFLUSH 0x3c -#define OMAP_MMU_FLUSH_ENTRY 0x40 -#define OMAP_MMU_READ_CAM_H 0x44 -#define OMAP_MMU_READ_CAM_L 0x48 -#define OMAP_MMU_READ_RAM_H 0x4c -#define OMAP_MMU_READ_RAM_L 0x50 - -#define OMAP_MMU_CNTL_BURST_16MNGT_EN 0x0020 -#define OMAP_MMU_CNTL_WTL_EN 0x0004 -#define OMAP_MMU_CNTL_MMU_EN 0x0002 -#define OMAP_MMU_CNTL_RESET_SW 0x0001 - -#define OMAP_MMU_FAULT_AD_H_DP 0x0100 -#define OMAP_MMU_FAULT_AD_H_ADR_MASK 0x00ff - -#define OMAP_MMU_FAULT_ST_PREF 0x0008 -#define OMAP_MMU_FAULT_ST_PERM 0x0004 -#define OMAP_MMU_FAULT_ST_TLB_MISS 0x0002 -#define OMAP_MMU_FAULT_ST_TRANS 0x0001 - -#define OMAP_MMU_IT_ACK_IT_ACK 0x0001 - -#define OMAP_MMU_CAM_H_VA_TAG_H_MASK 0x0003 - -#define OMAP_MMU_CAM_L_VA_TAG_L1_MASK 0xc000 -#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1MB 0x0000 -#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_64KB 0x3c00 -#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_4KB 0x3fc0 -#define OMAP_MMU_CAM_L_VA_TAG_L2_MASK_1KB 0x3ff0 -#define OMAP_MMU_CAM_L_P 0x0008 -#define OMAP_MMU_CAM_L_V 0x0004 -#define OMAP_MMU_CAM_L_PAGESIZE_MASK 0x0003 -#define OMAP_MMU_CAM_L_PAGESIZE_1MB 0x0000 -#define OMAP_MMU_CAM_L_PAGESIZE_64KB 0x0001 -#define OMAP_MMU_CAM_L_PAGESIZE_4KB 0x0002 -#define OMAP_MMU_CAM_L_PAGESIZE_1KB 0x0003 - -#define OMAP_MMU_CAM_P OMAP_MMU_CAM_L_P -#define OMAP_MMU_CAM_V OMAP_MMU_CAM_L_V -#define OMAP_MMU_CAM_PAGESIZE_MASK OMAP_MMU_CAM_L_PAGESIZE_MASK -#define OMAP_MMU_CAM_PAGESIZE_1MB OMAP_MMU_CAM_L_PAGESIZE_1MB -#define OMAP_MMU_CAM_PAGESIZE_64KB OMAP_MMU_CAM_L_PAGESIZE_64KB -#define OMAP_MMU_CAM_PAGESIZE_4KB OMAP_MMU_CAM_L_PAGESIZE_4KB -#define OMAP_MMU_CAM_PAGESIZE_1KB OMAP_MMU_CAM_L_PAGESIZE_1KB -#define OMAP_MMU_CAM_PAGESIZE_16MB -1 /* unused in omap1 */ - -#define OMAP_MMU_RAM_L_RAM_LSB_MASK 0xfc00 -#define OMAP_MMU_RAM_L_AP_MASK 0x0300 -#define OMAP_MMU_RAM_L_AP_NA 0x0000 -#define OMAP_MMU_RAM_L_AP_RO 0x0200 -#define OMAP_MMU_RAM_L_AP_FA 0x0300 - -#define OMAP_MMU_LD_TLB_RD 0x0002 - -#define INIT_TLB_ENTRY(ent, v, p, ps) \ -do { \ - (ent)->va = (v); \ - (ent)->pa = (p); \ - (ent)->pgsz = (ps); \ - (ent)->prsvd = 0; \ - (ent)->ap = OMAP_MMU_RAM_L_AP_FA; \ - (ent)->tlb = 1; \ -} while (0) - -#define INIT_TLB_ENTRY_4KB_PRESERVED(ent, v, p) \ -do { \ - (ent)->va = (v); \ - (ent)->pa = (p); \ - (ent)->pgsz = OMAP_MMU_CAM_PAGESIZE_4KB; \ - (ent)->prsvd = OMAP_MMU_CAM_P; \ - (ent)->ap = OMAP_MMU_RAM_L_AP_FA; \ -} while (0) - -struct omap_mmu_tlb_entry { - unsigned long va; - unsigned long pa; - unsigned int pgsz, prsvd, valid; - - u16 ap; - unsigned int tlb; -}; - -static inline unsigned short -omap_mmu_read_reg(struct omap_mmu *mmu, unsigned long reg) -{ - return __raw_readw(mmu->base + reg); -} - -static inline void omap_mmu_write_reg(struct omap_mmu *mmu, - unsigned short val, unsigned long reg) -{ - __raw_writew(val, mmu->base + reg); -} - -#endif /* __MACH_OMAP1_MMU_H */ diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 3897347e17e..00b2fb8da46 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -35,10 +35,8 @@ obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o # DSP -obj-$(CONFIG_OMAP_MMU_FWK) += mmu_mach.o obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o mailbox_mach-objs := mailbox.o -mmu_mach-objs := mmu.o # Specific board support obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o diff --git a/arch/arm/mach-omap2/mmu.c b/arch/arm/mach-omap2/mmu.c deleted file mode 100644 index 6fc3303af51..00000000000 --- a/arch/arm/mach-omap2/mmu.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/mmu.c - * - * Support for non-MPU OMAP2 MMUs. - * - * Copyright (C) 2002-2007 Nokia Corporation - * - * Written by Toshihiro Kobayashi - * and Paul Mundt - * - * TWL support: Hiroshi DOYU - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "mmu.h" -#include -#include -#include - -static void *dspvect_page; -#define DSP_INIT_PAGE 0xfff000 - -static inline void -omap2_mmu_read_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - cr->cam = omap_mmu_read_reg(mmu, OMAP_MMU_READ_CAM); - cr->ram = omap_mmu_read_reg(mmu, OMAP_MMU_READ_RAM); -} - -static inline void -omap2_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - /* Set the CAM and RAM entries */ - omap_mmu_write_reg(mmu, cr->cam | OMAP_MMU_CAM_V, OMAP_MMU_CAM); - omap_mmu_write_reg(mmu, cr->ram, OMAP_MMU_RAM); -} - -static void exmap_setup_iomap_page(struct omap_mmu *mmu, unsigned long phys, - unsigned long dsp_io_adr, int index) -{ - unsigned long dspadr; - void *virt; - struct omap_mmu_tlb_entry tlb_ent; - - dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1); - virt = omap_mmu_to_virt(mmu, dspadr); - exmap_set_armmmu(mmu, (unsigned long)virt, phys, PAGE_SIZE); - INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(mmu->exmap_tbl + index, NULL, virt); - INIT_TLB_ENTRY_4KB_ES32_PRESERVED(&tlb_ent, dspadr, phys); - omap_mmu_load_pte_entry(mmu, &tlb_ent); -} - -static void exmap_clear_iomap_page(struct omap_mmu *mmu, - unsigned long dsp_io_adr) -{ - unsigned long dspadr; - void *virt; - - dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1); - virt = omap_mmu_to_virt(mmu, dspadr); - exmap_clear_armmmu(mmu, (unsigned long)virt, PAGE_SIZE); - /* DSP MMU is shutting down. not handled here. */ -} - -#define OMAP24XX_MAILBOX_BASE (L4_24XX_BASE + 0x94000) -#define OMAP2420_GPT5_BASE (L4_24XX_BASE + 0x7c000) -#define OMAP2420_GPT6_BASE (L4_24XX_BASE + 0x7e000) -#define OMAP2420_GPT7_BASE (L4_24XX_BASE + 0x80000) -#define OMAP2420_GPT8_BASE (L4_24XX_BASE + 0x82000) -#define OMAP24XX_EAC_BASE (L4_24XX_BASE + 0x90000) -#define OMAP24XX_STI_BASE (L4_24XX_BASE + 0x68000) -#define OMAP24XX_STI_CH_BASE (L4_24XX_BASE + 0x0c000000) - -static int exmap_setup_preserved_entries(struct omap_mmu *mmu) -{ - int i, n = 0; - - exmap_setup_preserved_mem_page(mmu, dspvect_page, DSP_INIT_PAGE, n++); - - /* REVISIT: This will need to be revisited for 3430 */ - exmap_setup_iomap_page(mmu, OMAP2_PRCM_BASE, 0x7000, n++); - exmap_setup_iomap_page(mmu, OMAP24XX_MAILBOX_BASE, 0x11000, n++); - - if (cpu_is_omap2420()) { - exmap_setup_iomap_page(mmu, OMAP2420_GPT5_BASE, 0xe000, n++); - exmap_setup_iomap_page(mmu, OMAP2420_GPT6_BASE, 0xe800, n++); - exmap_setup_iomap_page(mmu, OMAP2420_GPT7_BASE, 0xf000, n++); - exmap_setup_iomap_page(mmu, OMAP2420_GPT8_BASE, 0xf800, n++); - exmap_setup_iomap_page(mmu, OMAP24XX_EAC_BASE, 0x10000, n++); - exmap_setup_iomap_page(mmu, OMAP24XX_STI_BASE, 0xc800, n++); - for (i = 0; i < 5; i++) - exmap_setup_preserved_mem_page(mmu, - __va(OMAP24XX_STI_CH_BASE + i*SZ_4K), - 0xfb0000 + i*SZ_4K, n++); - } - - return n; -} - -static void exmap_clear_preserved_entries(struct omap_mmu *mmu) -{ - int i; - - exmap_clear_iomap_page(mmu, 0x7000); /* PRCM registers */ - exmap_clear_iomap_page(mmu, 0x11000); /* MAILBOX registers */ - - if (cpu_is_omap2420()) { - exmap_clear_iomap_page(mmu, 0xe000); /* GPT5 */ - exmap_clear_iomap_page(mmu, 0xe800); /* GPT6 */ - exmap_clear_iomap_page(mmu, 0xf000); /* GPT7 */ - exmap_clear_iomap_page(mmu, 0xf800); /* GPT8 */ - exmap_clear_iomap_page(mmu, 0x10000); /* EAC */ - exmap_clear_iomap_page(mmu, 0xc800); /* STI */ - for (i = 0; i < 5; i++) /* STI CH */ - exmap_clear_mem_page(mmu, 0xfb0000 + i*SZ_4K); - } - - exmap_clear_mem_page(mmu, DSP_INIT_PAGE); -} - -#define MMU_IRQ_MASK \ - (OMAP_MMU_IRQ_MULTIHITFAULT | \ - OMAP_MMU_IRQ_TABLEWALKFAULT | \ - OMAP_MMU_IRQ_EMUMISS | \ - OMAP_MMU_IRQ_TRANSLATIONFAULT) - -static int omap2_mmu_startup(struct omap_mmu *mmu) -{ - u32 rev = omap_mmu_read_reg(mmu, OMAP_MMU_REVISION); - - pr_info("MMU: OMAP %s MMU initialized (HW v%d.%d)\n", mmu->name, - (rev >> 4) & 0xf, rev & 0xf); - - dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0); - if (dspvect_page == NULL) { - dev_err(mmu->dev, "MMU %s: failed to allocate memory " - "for vector table\n", mmu->name); - return -ENOMEM; - } - - mmu->nr_exmap_preserved = exmap_setup_preserved_entries(mmu); - - omap_mmu_write_reg(mmu, MMU_IRQ_MASK, OMAP_MMU_IRQENABLE); - - return 0; -} - -static void omap2_mmu_shutdown(struct omap_mmu *mmu) -{ - exmap_clear_preserved_entries(mmu); - - if (dspvect_page != NULL) { - unsigned long virt; - - down_read(&mmu->exmap_sem); - - virt = (unsigned long)omap_mmu_to_virt(mmu, DSP_INIT_PAGE); - flush_tlb_kernel_range(virt, virt + PAGE_SIZE); - free_page((unsigned long)dspvect_page); - dspvect_page = NULL; - - up_read(&mmu->exmap_sem); - } -} - -static ssize_t omap2_mmu_show(struct omap_mmu *mmu, char *buf, - struct omap_mmu_tlb_lock *tlb_lock) -{ - int i, len; - - len = sprintf(buf, "P: preserved, V: valid\n" - "B: big endian, L:little endian, " - "M: mixed page attribute\n" - "ety P V size cam_va ram_pa E ES M\n"); - /* 00: P V 4KB 0x300000 0x10171800 B 16 M */ - - for (i = 0; i < mmu->nr_tlb_entries; i++) { - struct omap_mmu_tlb_entry ent; - struct cam_ram_regset cr; - struct omap_mmu_tlb_lock entry_lock; - char *pgsz_str, *elsz_str; - - /* read a TLB entry */ - entry_lock.base = tlb_lock->base; - entry_lock.victim = i; - omap_mmu_read_tlb(mmu, &entry_lock, &cr); - - ent.pgsz = cr.cam & OMAP_MMU_CAM_PAGESIZE_MASK; - ent.prsvd = cr.cam & OMAP_MMU_CAM_P; - ent.valid = cr.cam & OMAP_MMU_CAM_V; - ent.va = cr.cam & OMAP_MMU_CAM_VATAG_MASK; - ent.endian = cr.ram & OMAP_MMU_RAM_ENDIANNESS; - ent.elsz = cr.ram & OMAP_MMU_RAM_ELEMENTSIZE_MASK; - ent.pa = cr.ram & OMAP_MMU_RAM_PADDR_MASK; - ent.mixed = cr.ram & OMAP_MMU_RAM_MIXED; - - pgsz_str = (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_16MB) ? "64MB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_1MB) ? " 1MB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_64KB) ? "64KB": - (ent.pgsz == OMAP_MMU_CAM_PAGESIZE_4KB) ? " 4KB": - " ???"; - elsz_str = (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_8) ? " 8": - (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_16) ? "16": - (ent.elsz == OMAP_MMU_RAM_ELEMENTSIZE_32) ? "32": - "??"; - - if (i == tlb_lock->base) - len += sprintf(buf + len, "lock base = %d\n", - tlb_lock->base); - if (i == tlb_lock->victim) - len += sprintf(buf + len, "victim = %d\n", - tlb_lock->victim); - - len += sprintf(buf + len, - /* 00: P V 4KB 0x300000 0x10171800 B 16 M */ - "%02d: %c %c %s 0x%06lx 0x%08lx %c %s %c\n", - i, - ent.prsvd ? 'P' : ' ', - ent.valid ? 'V' : ' ', - pgsz_str, ent.va, ent.pa, - ent.endian ? 'B' : 'L', - elsz_str, - ent.mixed ? 'M' : ' '); - } - - return len; -} - -#define get_cam_va_mask(pgsz) \ - (((pgsz) == OMAP_MMU_CAM_PAGESIZE_16MB) ? 0xff000000 : \ - ((pgsz) == OMAP_MMU_CAM_PAGESIZE_1MB) ? 0xfff00000 : \ - ((pgsz) == OMAP_MMU_CAM_PAGESIZE_64KB) ? 0xffff0000 : \ - ((pgsz) == OMAP_MMU_CAM_PAGESIZE_4KB) ? 0xfffff000 : 0) - -static inline unsigned long omap2_mmu_cam_va(struct cam_ram_regset *cr) -{ - unsigned int page_size = cr->cam & OMAP_MMU_CAM_PAGESIZE_MASK; - unsigned int mask = get_cam_va_mask(cr->cam & page_size); - - return cr->cam & mask; -} - -static struct cam_ram_regset * -omap2_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry) -{ - struct cam_ram_regset *cr; - - if (entry->va & ~(get_cam_va_mask(entry->pgsz))) { - dev_err(mmu->dev, "MMU %s: mapping vadr (0x%06lx) is not on" - " an aligned boundary\n", mmu->name, entry->va); - return ERR_PTR(-EINVAL); - } - - cr = kmalloc(sizeof(struct cam_ram_regset), GFP_KERNEL); - - cr->cam = (entry->va & OMAP_MMU_CAM_VATAG_MASK) | - entry->prsvd | entry->pgsz; - cr->ram = entry->pa | entry->endian | entry->elsz; - - return cr; -} - -static inline int omap2_mmu_cam_ram_valid(struct cam_ram_regset *cr) -{ - return cr->cam & OMAP_MMU_CAM_V; -} - -static void omap2_mmu_interrupt(struct omap_mmu *mmu) -{ - unsigned long status, va; - - status = MMU_IRQ_MASK & omap_mmu_read_reg(mmu, OMAP_MMU_IRQSTATUS); - va = omap_mmu_read_reg(mmu, OMAP_MMU_FAULT_AD); - - pr_info("%s\n", (status & OMAP_MMU_IRQ_MULTIHITFAULT)? - "multi hit":""); - pr_info("%s\n", (status & OMAP_MMU_IRQ_TABLEWALKFAULT)? - "table walk fault":""); - pr_info("%s\n", (status & OMAP_MMU_IRQ_EMUMISS)? - "EMU miss":""); - pr_info("%s\n", (status & OMAP_MMU_IRQ_TRANSLATIONFAULT)? - "translation fault":""); - pr_info("%s\n", (status & OMAP_MMU_IRQ_TLBMISS)? - "TLB miss":""); - pr_info("fault address = %#08lx\n", va); - - omap_mmu_disable(mmu); - omap_mmu_write_reg(mmu, status, OMAP_MMU_IRQSTATUS); - - mmu->fault_address = va; - schedule_work(&mmu->irq_work); -} - -static pgprot_t omap2_mmu_pte_get_attr(struct omap_mmu_tlb_entry *entry) -{ - u32 attr; - - attr = entry->mixed << 5; - attr |= entry->endian; - attr |= entry->elsz >> 3; - attr <<= ((entry->pgsz & OMAP_MMU_CAM_PAGESIZE_4KB) ? 0:6); - - return attr; -} - -struct omap_mmu_ops omap2_mmu_ops = { - .startup = omap2_mmu_startup, - .shutdown = omap2_mmu_shutdown, - .read_tlb = omap2_mmu_read_tlb, - .load_tlb = omap2_mmu_load_tlb, - .show = omap2_mmu_show, - .cam_va = omap2_mmu_cam_va, - .cam_ram_alloc = omap2_mmu_cam_ram_alloc, - .cam_ram_valid = omap2_mmu_cam_ram_valid, - .interrupt = omap2_mmu_interrupt, - .pte_get_attr = omap2_mmu_pte_get_attr, -}; -EXPORT_SYMBOL_GPL(omap2_mmu_ops); - -MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-omap2/mmu.h b/arch/arm/mach-omap2/mmu.h deleted file mode 100644 index c9eabf0993f..00000000000 --- a/arch/arm/mach-omap2/mmu.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __MACH_OMAP2_MMU_H -#define __MACH_OMAP2_MMU_H - -#include -#include - -#define MMU_LOCK_BASE_MASK (0x1f << 10) -#define MMU_LOCK_VICTIM_MASK (0x1f << 4) - -#define OMAP_MMU_REVISION 0x00 -#define OMAP_MMU_SYSCONFIG 0x10 -#define OMAP_MMU_SYSSTATUS 0x14 -#define OMAP_MMU_IRQSTATUS 0x18 -#define OMAP_MMU_IRQENABLE 0x1c -#define OMAP_MMU_WALKING_ST 0x40 -#define OMAP_MMU_CNTL 0x44 -#define OMAP_MMU_FAULT_AD 0x48 -#define OMAP_MMU_TTB 0x4c -#define OMAP_MMU_LOCK 0x50 -#define OMAP_MMU_LD_TLB 0x54 -#define OMAP_MMU_CAM 0x58 -#define OMAP_MMU_RAM 0x5c -#define OMAP_MMU_GFLUSH 0x60 -#define OMAP_MMU_FLUSH_ENTRY 0x64 -#define OMAP_MMU_READ_CAM 0x68 -#define OMAP_MMU_READ_RAM 0x6c -#define OMAP_MMU_EMU_FAULT_AD 0x70 - -#define OMAP_MMU_CNTL_BURST_16MNGT_EN 0x0020 -#define OMAP_MMU_CNTL_WTL_EN 0x0004 -#define OMAP_MMU_CNTL_MMU_EN 0x0002 -#define OMAP_MMU_CNTL_RESET_SW 0x0001 - -#define OMAP_MMU_IRQ_MULTIHITFAULT 0x00000010 -#define OMAP_MMU_IRQ_TABLEWALKFAULT 0x00000008 -#define OMAP_MMU_IRQ_EMUMISS 0x00000004 -#define OMAP_MMU_IRQ_TRANSLATIONFAULT 0x00000002 -#define OMAP_MMU_IRQ_TLBMISS 0x00000001 - -#define OMAP_MMU_CAM_VATAG_MASK 0xfffff000 -#define OMAP_MMU_CAM_P 0x00000008 -#define OMAP_MMU_CAM_V 0x00000004 -#define OMAP_MMU_CAM_PAGESIZE_MASK 0x00000003 -#define OMAP_MMU_CAM_PAGESIZE_1MB 0x00000000 -#define OMAP_MMU_CAM_PAGESIZE_64KB 0x00000001 -#define OMAP_MMU_CAM_PAGESIZE_4KB 0x00000002 -#define OMAP_MMU_CAM_PAGESIZE_16MB 0x00000003 - -#define OMAP_MMU_RAM_PADDR_MASK 0xfffff000 -#define OMAP_MMU_RAM_ENDIANNESS 0x00000200 -#define OMAP_MMU_RAM_ENDIANNESS_BIG 0x00000200 -#define OMAP_MMU_RAM_ENDIANNESS_LITTLE 0x00000000 -#define OMAP_MMU_RAM_ELEMENTSIZE_MASK 0x00000180 -#define OMAP_MMU_RAM_ELEMENTSIZE_8 0x00000000 -#define OMAP_MMU_RAM_ELEMENTSIZE_16 0x00000080 -#define OMAP_MMU_RAM_ELEMENTSIZE_32 0x00000100 -#define OMAP_MMU_RAM_ELEMENTSIZE_NONE 0x00000180 -#define OMAP_MMU_RAM_MIXED 0x00000040 - -#define IOMAP_VAL 0x3f - -#define INIT_TLB_ENTRY(ent, v, p, ps) \ -do { \ - (ent)->va = (v); \ - (ent)->pa = (p); \ - (ent)->pgsz = (ps); \ - (ent)->prsvd = 0; \ - (ent)->endian = OMAP_MMU_RAM_ENDIANNESS_LITTLE; \ - (ent)->elsz = OMAP_MMU_RAM_ELEMENTSIZE_16; \ - (ent)->mixed = 0; \ - (ent)->tlb = 1; \ -} while (0) - -#define INIT_TLB_ENTRY_4KB_PRESERVED(ent, v, p) \ -do { \ - (ent)->va = (v); \ - (ent)->pa = (p); \ - (ent)->pgsz = OMAP_MMU_CAM_PAGESIZE_4KB; \ - (ent)->prsvd = OMAP_MMU_CAM_P; \ - (ent)->endian = OMAP_MMU_RAM_ENDIANNESS_LITTLE; \ - (ent)->elsz = OMAP_MMU_RAM_ELEMENTSIZE_16; \ - (ent)->mixed = 0; \ -} while (0) - -#define INIT_TLB_ENTRY_4KB_ES32_PRESERVED(ent, v, p) \ -do { \ - (ent)->va = (v); \ - (ent)->pa = (p); \ - (ent)->pgsz = OMAP_MMU_CAM_PAGESIZE_4KB; \ - (ent)->prsvd = OMAP_MMU_CAM_P; \ - (ent)->endian = OMAP_MMU_RAM_ENDIANNESS_LITTLE; \ - (ent)->elsz = OMAP_MMU_RAM_ELEMENTSIZE_32; \ - (ent)->mixed = 0; \ -} while (0) - -struct omap_mmu_tlb_entry { - unsigned long va; - unsigned long pa; - unsigned int pgsz, prsvd, valid; - - u32 endian, elsz, mixed; - unsigned int tlb; -}; - -static inline unsigned long -omap_mmu_read_reg(struct omap_mmu *mmu, unsigned long reg) -{ - return __raw_readl((void __iomem *)(mmu->base + reg)); -} - -static inline void omap_mmu_write_reg(struct omap_mmu *mmu, - unsigned long val, unsigned long reg) -{ - __raw_writel(val, (void __iomem *)(mmu->base + reg)); -} - -#endif /* __MACH_OMAP2_MMU_H */ diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index df7709849c9..b16ae761d48 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -168,14 +168,6 @@ config OMAP_MCBSP Say Y here if you want support for the OMAP Multichannel Buffered Serial Port. -config OMAP_MMU_FWK - bool "MMU framework support" - depends on ARCH_OMAP - default n - help - Say Y here if you want to use OMAP MMU framework support for - DSP, IVA1.0 and Camera in OMAP1/2. - config OMAP_MBOX_FWK tristate "Mailbox framework support" depends on ARCH_OMAP diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 12598461105..b3f0e6be369 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -23,9 +23,6 @@ obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o obj-$(CONFIG_I2C_OMAP) += i2c.o -# OMAP MMU framework -obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o - # OMAP mailbox framework obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o diff --git a/arch/arm/plat-omap/include/mach/dsp.h b/arch/arm/plat-omap/include/mach/dsp.h deleted file mode 100644 index ae71eb80483..00000000000 --- a/arch/arm/plat-omap/include/mach/dsp.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __ARCH_OMAP_DSP_H -#define __ARCH_OMAP_DSP_H - -/* - * for /dev/dspctl/ctl - */ -#define DSPCTL_IOCTL_RESET 1 -#define DSPCTL_IOCTL_RUN 2 -#define DSPCTL_IOCTL_SETRSTVECT 3 -#ifdef CONFIG_ARCH_OMAP1 -#define DSPCTL_IOCTL_CPU_IDLE 4 -#define DSPCTL_IOCTL_MPUI_WORDSWAP_ON 5 -#define DSPCTL_IOCTL_MPUI_WORDSWAP_OFF 6 -#define DSPCTL_IOCTL_MPUI_BYTESWAP_ON 7 -#define DSPCTL_IOCTL_MPUI_BYTESWAP_OFF 8 -#define DSPCTL_IOCTL_GBL_IDLE 9 -#endif /* CONFIG_ARCH_OMAP1 */ -#define DSPCTL_IOCTL_DSPCFG 10 -#define DSPCTL_IOCTL_DSPUNCFG 11 -#define DSPCTL_IOCTL_TASKCNT 12 -#define DSPCTL_IOCTL_POLL 13 -#define DSPCTL_IOCTL_REGMEMR 40 -#define DSPCTL_IOCTL_REGMEMW 41 -#define DSPCTL_IOCTL_REGIOR 42 -#define DSPCTL_IOCTL_REGIOW 43 -#define DSPCTL_IOCTL_GETVAR 44 -#define DSPCTL_IOCTL_SETVAR 45 -#define DSPCTL_IOCTL_RUNLEVEL 50 -#define DSPCTL_IOCTL_SUSPEND 51 -#define DSPCTL_IOCTL_RESUME 52 -#ifdef CONFIG_OMAP_DSP_FBEXPORT -#define DSPCTL_IOCTL_FBEN 53 -#define DSPCTL_IOCTL_FBDIS 54 -#endif /* CONFIG_OMAP_DSP_FBEXPORT */ -#define DSPCTL_IOCTL_MBSEND 99 - -struct omap_dsp_mailbox_cmd { - __u16 cmd; - __u16 data; -}; - -struct omap_dsp_reginfo { - __u16 adr; - __u16 val; -}; - -struct omap_dsp_varinfo { - __u8 varid; - __u16 val[0]; -}; - -/* - * for taskdev - * (ioctls below should be >= 0x10000) - */ -#define TASK_IOCTL_BFLSH 0x10000 -#define TASK_IOCTL_SETBSZ 0x10001 -#define TASK_IOCTL_LOCK 0x10002 -#define TASK_IOCTL_UNLOCK 0x10003 -#define TASK_IOCTL_GETNAME 0x10004 - -/* - * for /dev/dspctl/mem - */ -#define MEM_IOCTL_EXMAP 1 -#define MEM_IOCTL_EXUNMAP 2 -#define MEM_IOCTL_EXMAP_FLUSH 3 -#define MEM_IOCTL_FBEXPORT 5 -#define MEM_IOCTL_MMUITACK 7 -#define MEM_IOCTL_MMUINIT 9 -#define MEM_IOCTL_KMEM_RESERVE 11 -#define MEM_IOCTL_KMEM_RELEASE 12 - -struct omap_dsp_mapinfo { - __u32 dspadr; - __u32 size; -}; - -/* - * for /dev/dspctl/twch - */ -#define TWCH_IOCTL_MKDEV 1 -#define TWCH_IOCTL_RMDEV 2 -#define TWCH_IOCTL_TADD 11 -#define TWCH_IOCTL_TDEL 12 -#define TWCH_IOCTL_TKILL 13 - -struct omap_dsp_taddinfo { - __u8 minor; - __u32 taskadr; -}; - -#define TADD_ABORTADR 0xffffffff - -#endif /* __ARCH_OMAP_DSP_H */ diff --git a/arch/arm/plat-omap/include/mach/dsp_common.h b/arch/arm/plat-omap/include/mach/dsp_common.h index 0c7565eb6ce..da97736f3ef 100644 --- a/arch/arm/plat-omap/include/mach/dsp_common.h +++ b/arch/arm/plat-omap/include/mach/dsp_common.h @@ -5,50 +5,25 @@ * * Contact: Toshihiro Kobayashi * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * */ #ifndef ASM_ARCH_DSP_COMMON_H #define ASM_ARCH_DSP_COMMON_H -#include - -struct dsp_kfunc_device { - char *name; - struct clk *fck; - struct clk *ick;; - spinlock_t lock; - int enabled; - int type; -#define DSP_KFUNC_DEV_TYPE_COMMON 1 -#define DSP_KFUNC_DEV_TYPE_AUDIO 2 - - struct list_head entry; - - int (*probe)(struct dsp_kfunc_device *, int); - int (*remove)(struct dsp_kfunc_device *, int); - int (*enable)(struct dsp_kfunc_device *, int); - int (*disable)(struct dsp_kfunc_device *, int); -}; - -extern int dsp_kfunc_device_register(struct dsp_kfunc_device *); - -struct dsp_platform_data { - struct list_head kdev_list; -}; - -struct omap_dsp { - struct mutex lock; - int enabled; /* stored peripheral status */ - struct omap_mmu *mmu; - struct omap_mbox *mbox; - struct device *dev; - struct list_head *kdev_list; - int initialized; -}; - #if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK) extern void omap_dsp_request_mpui(void); extern void omap_dsp_release_mpui(void); diff --git a/arch/arm/plat-omap/include/mach/mmu.h b/arch/arm/plat-omap/include/mach/mmu.h deleted file mode 100644 index d970b71a490..00000000000 --- a/arch/arm/plat-omap/include/mach/mmu.h +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef __ARCH_OMAP_MMU_H -#define __ARCH_OMAP_MMU_H - -#include -#include - -enum exmap_type { - EXMAP_TYPE_MEM, - EXMAP_TYPE_FB -}; - -enum omap_mmu_type { - OMAP_MMU_DSP, - OMAP_MMU_IVA1, - OMAP_MMU_CAMERA, -}; - -struct exmap_tbl { - unsigned int valid:1; - unsigned int prsvd:1; - int usecount; /* reference count by mmap */ - enum exmap_type type; - void *buf; /* virtual address of the buffer, - * i.e. 0xc0000000 - */ - void *vadr; /* DSP shadow space, - * i.e. 0xe0000000 - 0xe0ffffff */ - unsigned int order; - struct { - int prev; - int next; - } link; /* grouping */ -}; - -struct cam_ram_regset { - union { - struct { - u16 cam_l; - u16 cam_h; - }; - - u32 cam; - }; - - union { - struct { - u16 ram_l; - u16 ram_h; - }; - - u32 ram; - }; -}; - -struct omap_mmu_tlb_lock { - int base; - int victim; -}; - -struct omap_mmu; -struct omap_mmu_tlb_entry; - -#ifdef CONFIG_ARCH_OMAP1 -extern struct omap_mmu_ops omap1_mmu_ops; -extern void omap_mmu_itack(struct omap_mmu *mmu); -#elif defined(CONFIG_ARCH_OMAP2) -extern struct omap_mmu_ops omap2_mmu_ops; -static inline void omap_mmu_itack(struct omap_mmu *mmu) -{ -} -#endif - -struct omap_mmu_ops { - int (*startup)(struct omap_mmu *mmu); - void (*shutdown)(struct omap_mmu *mmu); - - /* TLB operations */ - void (*read_tlb)(struct omap_mmu *, struct cam_ram_regset *); - void (*load_tlb)(struct omap_mmu *, struct cam_ram_regset *); - ssize_t (*show)(struct omap_mmu *, char *, struct omap_mmu_tlb_lock *); - - /* CAM / RAM operations */ - struct cam_ram_regset *(*cam_ram_alloc)(struct omap_mmu *, - struct omap_mmu_tlb_entry *); - int (*cam_ram_valid)(struct cam_ram_regset *); - unsigned long (*cam_va)(struct cam_ram_regset *); - - /* Memory operations */ - int (*mem_enable)(struct omap_mmu *, void *); - int (*mem_disable)(struct omap_mmu *, void *); - - void (*interrupt)(struct omap_mmu *); - - /* PTE attribute operations */ - pgprot_t (*pte_get_attr)(struct omap_mmu_tlb_entry *); -}; - -struct omap_mmu { - const char *name; - unsigned long base; - struct clk *clk; - - unsigned long membase, memsize; - struct clk *memclk; - - enum omap_mmu_type type; - - struct device *dev; - - struct rw_semaphore exmap_sem; - struct exmap_tbl *exmap_tbl; - - unsigned int nr_tlb_entries; - unsigned int nr_exmap_preserved; - - struct mm_struct *twl_mm; - - /* Size of virtual address space, in bits */ - unsigned int addrspace; - - /* Interrupt */ - unsigned int irq; - unsigned long fault_address; - struct work_struct irq_work; - - struct omap_mmu_ops *ops; -}; - -#define omap_mmu_internal_memory(mmu, addr) \ - (likely(mmu->membase) && (((unsigned long)(addr) >= mmu->membase) && \ - ((unsigned long)(addr) < mmu->membase + mmu->memsize))) - -#define INIT_EXMAP_TBL_ENTRY(ent, b, v, typ, od) \ -do { \ - (ent)->buf = (b); \ - (ent)->vadr = (v); \ - (ent)->valid = 1; \ - (ent)->prsvd = 0; \ - (ent)->usecount = 0; \ - (ent)->type = (typ); \ - (ent)->order = (od); \ - (ent)->link.next = -1; \ - (ent)->link.prev = -1; \ -} while (0) - -#define INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(ent, b, v) \ -do { \ - (ent)->buf = (b); \ - (ent)->vadr = (v); \ - (ent)->valid = 1; \ - (ent)->prsvd = 1; \ - (ent)->usecount = 0; \ - (ent)->type = EXMAP_TYPE_MEM; \ - (ent)->order = 0; \ - (ent)->link.next = -1; \ - (ent)->link.prev = -1; \ -} while (0) - -#define omap_mmu_to_virt(mmu, db) ((void *)((mmu)->membase + (db))) -#define virt_to_omap_mmu(mmu, va) \ - (((unsigned long)(va) - (mmu)->membase)) - -/* arch/arm/plat-omap/mmu.c */ -int omap_mmu_register(struct omap_mmu *mmu); -void omap_mmu_unregister(struct omap_mmu *mmu); - -void omap_mmu_enable(struct omap_mmu *mmu, int reset); -void omap_mmu_disable(struct omap_mmu *mmu); - -int omap_mmu_mem_enable(struct omap_mmu *mmu, void *addr); -void omap_mmu_mem_disable(struct omap_mmu *mmu, void *addr); - -void omap_mmu_read_tlb(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *lock, - struct cam_ram_regset *cr); - -int omap_mmu_load_tlb_entry(struct omap_mmu *, struct omap_mmu_tlb_entry *); -int omap_mmu_clear_tlb_entry(struct omap_mmu *, unsigned long vadr); - -int omap_mmu_load_pte_entry(struct omap_mmu *mmu, - struct omap_mmu_tlb_entry *entry); -int omap_mmu_clear_pte_entry(struct omap_mmu *mmu, unsigned long vadr); - -int omap_mmu_kmem_reserve(struct omap_mmu *mmu, unsigned long size); -void omap_mmu_kmem_release(void); - -unsigned long omap_mmu_virt_to_phys(struct omap_mmu *mmu, void *vadr, - size_t *len); - -int omap_mmu_exmap(struct omap_mmu *mmu, unsigned long dspadr, - unsigned long padr, unsigned long size, - enum exmap_type type); -int omap_mmu_exunmap(struct omap_mmu *mmu, unsigned long dspadr); -void omap_mmu_exmap_flush(struct omap_mmu *mmu); -void omap_mmu_exmap_use(struct omap_mmu *mmu, void *vadr, size_t len); -void omap_mmu_exmap_unuse(struct omap_mmu *mmu, void *vadr, size_t len); - -int exmap_set_armmmu(struct omap_mmu *mmu, unsigned long virt, - unsigned long phys, unsigned long size); -void exmap_clear_armmmu(struct omap_mmu *mmu, unsigned long virt, - unsigned long size); -void exmap_setup_preserved_mem_page(struct omap_mmu *mmu, void *buf, - unsigned long dspadr, int index); -void exmap_clear_mem_page(struct omap_mmu *mmu, unsigned long dspadr); -int exmap_valid(struct omap_mmu *mmu, void *vadr, size_t len); - -/* To be obsolete for backward compatibility */ -ssize_t __omap_mmu_mem_read(struct omap_mmu *mmu, struct bin_attribute *, - char *buf, loff_t offset, size_t count); -ssize_t __omap_mmu_mem_write(struct omap_mmu *mmu, struct bin_attribute *, - char *buf, loff_t offset, size_t count); - -#endif /* __ARCH_OMAP_MMU_H */ diff --git a/arch/arm/plat-omap/mmu.c b/arch/arm/plat-omap/mmu.c deleted file mode 100644 index d81a1488bd9..00000000000 --- a/arch/arm/plat-omap/mmu.c +++ /dev/null @@ -1,1563 +0,0 @@ -/* - * linux/arch/arm/plat-omap/mmu.c - * - * OMAP MMU management framework - * - * Copyright (C) 2002-2006 Nokia Corporation - * - * Written by Toshihiro Kobayashi - * and Paul Mundt - * - * TWL support: Hiroshi DOYU - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_ARCH_OMAP1) -#include "../mach-omap1/mmu.h" -#elif defined(CONFIG_ARCH_OMAP2) -#include "../mach-omap2/mmu.h" -#endif - -/* - * On OMAP2 MMU_LOCK_xxx_MASK only applies to the IVA and DSP, the camera - * MMU has base and victim implemented in different bits in the LOCK - * register (shifts are still the same), all of the other registers are - * the same on all of the MMUs.. - */ -#define MMU_LOCK_BASE_SHIFT 10 -#define MMU_LOCK_VICTIM_SHIFT 4 - -#define CAMERA_MMU_LOCK_BASE_MASK (0x7 << MMU_LOCK_BASE_SHIFT) -#define CAMERA_MMU_LOCK_VICTIM_MASK (0x7 << MMU_LOCK_VICTIM_SHIFT) - -#define is_aligned(adr, align) (!((adr)&((align)-1))) -#define ORDER_1MB (20 - PAGE_SHIFT) -#define ORDER_64KB (16 - PAGE_SHIFT) -#define ORDER_4KB (12 - PAGE_SHIFT) - -#define MMU_CNTL_EMUTLBUPDATE (1<<3) -#define MMU_CNTL_TWLENABLE (1<<2) -#define MMU_CNTL_MMUENABLE (1<<1) - -static mempool_t *mempool_1M; -static mempool_t *mempool_64K; - -#define omap_mmu_for_each_tlb_entry(mmu, entry) \ - for (entry = mmu->exmap_tbl; prefetch(entry + 1), \ - entry < (mmu->exmap_tbl + mmu->nr_tlb_entries); \ - entry++) - -#define to_dev(obj) container_of(obj, struct device, kobj) - -static void *mempool_alloc_from_pool(mempool_t *pool, - unsigned int __nocast gfp_mask) -{ - spin_lock_irq(&pool->lock); - if (likely(pool->curr_nr)) { - void *element = pool->elements[--pool->curr_nr]; - spin_unlock_irq(&pool->lock); - return element; - } - - spin_unlock_irq(&pool->lock); - return mempool_alloc(pool, gfp_mask); -} - -/* - * kmem_reserve(), kmem_release(): - * reserve or release kernel memory for exmap(). - * - * exmap() might request consecutive 1MB or 64kB, - * but it will be difficult after memory pages are fragmented. - * So, user can reserve such memory blocks in the early phase - * through kmem_reserve(). - */ -static void *omap_mmu_pool_alloc(unsigned int __nocast gfp, void *order) -{ - return (void *)__get_dma_pages(gfp, (unsigned int)order); -} - -static void omap_mmu_pool_free(void *buf, void *order) -{ - free_pages((unsigned long)buf, (unsigned int)order); -} - -int omap_mmu_kmem_reserve(struct omap_mmu *mmu, unsigned long size) -{ - unsigned long len = size; - - /* alignment check */ - if (!is_aligned(size, SZ_64K)) { - dev_err(mmu->dev, - "MMU %s: size(0x%lx) is not multiple of 64KB.\n", - mmu->name, size); - return -EINVAL; - } - - if (size > (1 << mmu->addrspace)) { - dev_err(mmu->dev, - "MMU %s: size(0x%lx) is larger than external device " - " memory space size (0x%x.\n", mmu->name, size, - (1 << mmu->addrspace)); - return -EINVAL; - } - - if (size >= SZ_1M) { - int nr = size >> 20; - - if (likely(!mempool_1M)) - mempool_1M = mempool_create(nr, omap_mmu_pool_alloc, - omap_mmu_pool_free, - (void *)ORDER_1MB); - else - mempool_resize(mempool_1M, mempool_1M->min_nr + nr, - GFP_KERNEL); - - size &= ~(0xf << 20); - } - - if (size >= SZ_64K) { - int nr = size >> 16; - - if (likely(!mempool_64K)) - mempool_64K = mempool_create(nr, omap_mmu_pool_alloc, - omap_mmu_pool_free, - (void *)ORDER_64KB); - else - mempool_resize(mempool_64K, mempool_64K->min_nr + nr, - GFP_KERNEL); - - size &= ~(0xf << 16); - } - - if (size) - len -= size; - - return len; -} -EXPORT_SYMBOL_GPL(omap_mmu_kmem_reserve); - -void omap_mmu_kmem_release(void) -{ - if (mempool_64K) { - mempool_destroy(mempool_64K); - mempool_64K = NULL; - } - - if (mempool_1M) { - mempool_destroy(mempool_1M); - mempool_1M = NULL; - } -} -EXPORT_SYMBOL_GPL(omap_mmu_kmem_release); - -static void omap_mmu_free_pages(unsigned long buf, unsigned int order) -{ - struct page *page, *ps, *pe; - - ps = virt_to_page(buf); - pe = virt_to_page(buf + (1 << (PAGE_SHIFT + order))); - - for (page = ps; page < pe; page++) - ClearPageReserved(page); - - if ((order == ORDER_64KB) && likely(mempool_64K)) - mempool_free((void *)buf, mempool_64K); - else if ((order == ORDER_1MB) && likely(mempool_1M)) - mempool_free((void *)buf, mempool_1M); - else - free_pages(buf, order); -} - -/* - * ARM MMU operations - */ -int exmap_set_armmmu(struct omap_mmu *mmu, unsigned long virt, - unsigned long phys, unsigned long size) -{ - long off; - unsigned long sz_left; - pmd_t *pmdp; - pte_t *ptep; - int prot_pmd, prot_pte; - - dev_dbg(mmu->dev, - "MMU %s: mapping in ARM MMU, v=0x%08lx, p=0x%08lx, sz=0x%lx\n", - mmu->name, virt, phys, size); - - prot_pmd = PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_IO); - prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | L_PTE_WRITE; - - pmdp = pmd_offset(pgd_offset_k(virt), virt); - if (pmd_none(*pmdp)) { - ptep = pte_alloc_one_kernel(&init_mm, 0); - if (ptep == NULL) - return -ENOMEM; - /* note: two PMDs will be set */ - pmd_populate_kernel(&init_mm, pmdp, ptep); - } - - off = phys - virt; - for (sz_left = size; - sz_left >= PAGE_SIZE; - sz_left -= PAGE_SIZE, virt += PAGE_SIZE) { - ptep = pte_offset_kernel(pmdp, virt); - set_pte_ext(ptep, __pte((virt + off) | prot_pte), 0); - } - if (sz_left) - BUG(); - - return 0; -} -EXPORT_SYMBOL_GPL(exmap_set_armmmu); - -void exmap_clear_armmmu(struct omap_mmu *mmu, unsigned long virt, - unsigned long size) -{ - unsigned long sz_left; - pmd_t *pmdp; - pte_t *ptep; - - dev_dbg(mmu->dev, - "MMU %s: unmapping in ARM MMU, v=0x%08lx, sz=0x%lx\n", - mmu->name, virt, size); - - for (sz_left = size; - sz_left >= PAGE_SIZE; - sz_left -= PAGE_SIZE, virt += PAGE_SIZE) { - pmdp = pmd_offset(pgd_offset_k(virt), virt); - ptep = pte_offset_kernel(pmdp, virt); - pte_clear(&init_mm, virt, ptep); - } - if (sz_left) - BUG(); -} -EXPORT_SYMBOL_GPL(exmap_clear_armmmu); - -int exmap_valid(struct omap_mmu *mmu, void *vadr, size_t len) -{ - /* exmap_sem should be held before calling this function */ - struct exmap_tbl *ent; - -start: - omap_mmu_for_each_tlb_entry(mmu, ent) { - void *mapadr; - unsigned long mapsize; - - if (!ent->valid) - continue; - mapadr = (void *)ent->vadr; - mapsize = 1 << (ent->order + PAGE_SHIFT); - if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) { - if (vadr + len <= mapadr + mapsize) { - /* this map covers whole address. */ - return 1; - } else { - /* - * this map covers partially. - * check rest portion. - */ - len -= mapadr + mapsize - vadr; - vadr = mapadr + mapsize; - goto start; - } - } - } - - return 0; -} -EXPORT_SYMBOL_GPL(exmap_valid); - -/* - * omap_mmu_exmap_use(), unuse(): - * when the mapped area is exported to user space with mmap, - * the usecount is incremented. - * while the usecount > 0, that area can't be released. - */ -void omap_mmu_exmap_use(struct omap_mmu *mmu, void *vadr, size_t len) -{ - struct exmap_tbl *ent; - - down_write(&mmu->exmap_sem); - omap_mmu_for_each_tlb_entry(mmu, ent) { - void *mapadr; - unsigned long mapsize; - - if (!ent->valid) - continue; - mapadr = (void *)ent->vadr; - mapsize = 1 << (ent->order + PAGE_SHIFT); - if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) - ent->usecount++; - } - up_write(&mmu->exmap_sem); -} -EXPORT_SYMBOL_GPL(omap_mmu_exmap_use); - -void omap_mmu_exmap_unuse(struct omap_mmu *mmu, void *vadr, size_t len) -{ - struct exmap_tbl *ent; - - down_write(&mmu->exmap_sem); - omap_mmu_for_each_tlb_entry(mmu, ent) { - void *mapadr; - unsigned long mapsize; - - if (!ent->valid) - continue; - mapadr = (void *)ent->vadr; - mapsize = 1 << (ent->order + PAGE_SHIFT); - if ((vadr + len > mapadr) && (vadr < mapadr + mapsize)) - ent->usecount--; - } - up_write(&mmu->exmap_sem); -} -EXPORT_SYMBOL_GPL(omap_mmu_exmap_unuse); - -/* - * omap_mmu_virt_to_phys() - * returns physical address, and sets len to valid length - */ -unsigned long -omap_mmu_virt_to_phys(struct omap_mmu *mmu, void *vadr, size_t *len) -{ - struct exmap_tbl *ent; - - if (omap_mmu_internal_memory(mmu, vadr)) { - unsigned long addr = (unsigned long)vadr; - *len = mmu->membase + mmu->memsize - addr; - return addr; - } - - /* EXRAM */ - omap_mmu_for_each_tlb_entry(mmu, ent) { - void *mapadr; - unsigned long mapsize; - - if (!ent->valid) - continue; - mapadr = (void *)ent->vadr; - mapsize = 1 << (ent->order + PAGE_SHIFT); - if ((vadr >= mapadr) && (vadr < mapadr + mapsize)) { - *len = mapadr + mapsize - vadr; - return __pa(ent->buf) + vadr - mapadr; - } - } - - /* valid mapping not found */ - return 0; -} -EXPORT_SYMBOL_GPL(omap_mmu_virt_to_phys); - -/* - * PTE operations - */ -static inline void -omap_mmu_alloc_section(struct mm_struct *mm, unsigned long virt, - unsigned long phys, int prot) -{ - pmd_t *pmdp = pmd_offset(pgd_offset(mm, virt), virt); - if (virt & (1 << SECTION_SHIFT)) - pmdp++; - *pmdp = __pmd((phys & SECTION_MASK) | prot | PMD_TYPE_SECT); - flush_pmd_entry(pmdp); -} - -static inline void -omap_mmu_alloc_supersection(struct mm_struct *mm, unsigned long virt, - unsigned long phys, int prot) -{ - int i; - for (i = 0; i < 16; i += 1) { - omap_mmu_alloc_section(mm, virt, phys, prot | PMD_SECT_SUPER); - virt += (PGDIR_SIZE / 2); - } -} - -static inline int -omap_mmu_alloc_page(struct mm_struct *mm, unsigned long virt, - unsigned long phys, pgprot_t prot) -{ - pte_t *ptep; - pmd_t *pmdp = pmd_offset(pgd_offset(mm, virt), virt); - - if (!(prot & PTE_TYPE_MASK)) - prot |= PTE_TYPE_SMALL; - - if (pmd_none(*pmdp)) { - ptep = pte_alloc_one_kernel(mm, virt); - if (ptep == NULL) - return -ENOMEM; - pmd_populate_kernel(mm, pmdp, ptep); - } - ptep = pte_offset_kernel(pmdp, virt); - ptep -= PTRS_PER_PTE; - *ptep = pfn_pte(phys >> PAGE_SHIFT, prot); - flush_pmd_entry((pmd_t *)ptep); - return 0; -} - -static inline int -omap_mmu_alloc_largepage(struct mm_struct *mm, unsigned long virt, - unsigned long phys, pgprot_t prot) -{ - int i, ret; - for (i = 0; i < 16; i += 1) { - ret = omap_mmu_alloc_page(mm, virt, phys, - prot | PTE_TYPE_LARGE); - if (ret) - return -ENOMEM; /* only 1st time */ - virt += PAGE_SIZE; - } - return 0; -} - -static int omap_mmu_load_pte(struct omap_mmu *mmu, - struct omap_mmu_tlb_entry *e) -{ - int ret = 0; - struct mm_struct *mm = mmu->twl_mm; - const unsigned long va = e->va; - const unsigned long pa = e->pa; - const pgprot_t prot = mmu->ops->pte_get_attr(e); - - spin_lock(&mm->page_table_lock); - - switch (e->pgsz) { - case OMAP_MMU_CAM_PAGESIZE_16MB: - omap_mmu_alloc_supersection(mm, va, pa, prot); - break; - case OMAP_MMU_CAM_PAGESIZE_1MB: - omap_mmu_alloc_section(mm, va, pa, prot); - break; - case OMAP_MMU_CAM_PAGESIZE_64KB: - ret = omap_mmu_alloc_largepage(mm, va, pa, prot); - break; - case OMAP_MMU_CAM_PAGESIZE_4KB: - ret = omap_mmu_alloc_page(mm, va, pa, prot); - break; - default: - BUG(); - break; - } - - spin_unlock(&mm->page_table_lock); - - return ret; -} - -static void omap_mmu_clear_pte(struct omap_mmu *mmu, unsigned long virt) -{ - pte_t *ptep, *end; - pmd_t *pmdp; - struct mm_struct *mm = mmu->twl_mm; - - spin_lock(&mm->page_table_lock); - - pmdp = pmd_offset(pgd_offset(mm, virt), virt); - - if (pmd_none(*pmdp)) - goto out; - - if (!pmd_table(*pmdp)) - goto invalidate_pmd; - - ptep = pte_offset_kernel(pmdp, virt); - pte_clear(mm, virt, ptep); - flush_pmd_entry((pmd_t *)ptep); - - /* zap pte */ - end = pmd_page_vaddr(*pmdp); - ptep = end - PTRS_PER_PTE; - while (ptep < end) { - if (!pte_none(*ptep)) - goto out; - ptep++; - } - pte_free_kernel(mm, pmd_page_vaddr(*pmdp)); - - invalidate_pmd: - pmd_clear(pmdp); - flush_pmd_entry(pmdp); - out: - spin_unlock(&mm->page_table_lock); -} - -/* - * TLB operations - */ -static struct cam_ram_regset * -omap_mmu_cam_ram_alloc(struct omap_mmu *mmu, struct omap_mmu_tlb_entry *entry) -{ - return mmu->ops->cam_ram_alloc(mmu, entry); -} - -static int omap_mmu_cam_ram_valid(struct omap_mmu *mmu, - struct cam_ram_regset *cr) -{ - return mmu->ops->cam_ram_valid(cr); -} - -static inline void -omap_mmu_get_tlb_lock(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *tlb_lock) -{ - unsigned long lock = omap_mmu_read_reg(mmu, OMAP_MMU_LOCK); - int mask; - - mask = (mmu->type == OMAP_MMU_CAMERA) ? - CAMERA_MMU_LOCK_BASE_MASK : MMU_LOCK_BASE_MASK; - tlb_lock->base = (lock & mask) >> MMU_LOCK_BASE_SHIFT; - - mask = (mmu->type == OMAP_MMU_CAMERA) ? - CAMERA_MMU_LOCK_VICTIM_MASK : MMU_LOCK_VICTIM_MASK; - tlb_lock->victim = (lock & mask) >> MMU_LOCK_VICTIM_SHIFT; -} - -static inline void -omap_mmu_set_tlb_lock(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *lock) -{ - omap_mmu_write_reg(mmu, - (lock->base << MMU_LOCK_BASE_SHIFT) | - (lock->victim << MMU_LOCK_VICTIM_SHIFT), - OMAP_MMU_LOCK); -} - -static inline void omap_mmu_flush(struct omap_mmu *mmu) -{ - omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_FLUSH_ENTRY); -} - -static inline void omap_mmu_ldtlb(struct omap_mmu *mmu) -{ - omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_LD_TLB); -} - -void omap_mmu_read_tlb(struct omap_mmu *mmu, struct omap_mmu_tlb_lock *lock, - struct cam_ram_regset *cr) -{ - /* set victim */ - omap_mmu_set_tlb_lock(mmu, lock); - - if (likely(mmu->ops->read_tlb)) - mmu->ops->read_tlb(mmu, cr); -} -EXPORT_SYMBOL_GPL(omap_mmu_read_tlb); - -void omap_mmu_load_tlb(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - if (likely(mmu->ops->load_tlb)) - mmu->ops->load_tlb(mmu, cr); - - /* flush the entry */ - omap_mmu_flush(mmu); - - /* load a TLB entry */ - omap_mmu_ldtlb(mmu); -} - -int omap_mmu_load_tlb_entry(struct omap_mmu *mmu, - struct omap_mmu_tlb_entry *entry) -{ - struct omap_mmu_tlb_lock lock; - struct cam_ram_regset *cr; - int ret; - - clk_enable(mmu->clk); - ret = omap_dsp_request_mem(); - if (ret < 0) - goto out; - - omap_mmu_get_tlb_lock(mmu, &lock); - for (lock.victim = 0; lock.victim < lock.base; lock.victim++) { - struct cam_ram_regset tmp; - - /* read a TLB entry */ - omap_mmu_read_tlb(mmu, &lock, &tmp); - if (!omap_mmu_cam_ram_valid(mmu, &tmp)) - goto found_victim; - } - omap_mmu_set_tlb_lock(mmu, &lock); - -found_victim: - /* The last entry cannot be locked? */ - if (lock.victim == (mmu->nr_tlb_entries - 1)) { - dev_err(mmu->dev, "MMU %s: TLB is full.\n", mmu->name); - return -EBUSY; - } - - cr = omap_mmu_cam_ram_alloc(mmu, entry); - if (IS_ERR(cr)) - return PTR_ERR(cr); - - omap_mmu_load_tlb(mmu, cr); - kfree(cr); - - /* update lock base */ - if (lock.victim == lock.base) - lock.base++; - - omap_mmu_set_tlb_lock(mmu, &lock); - - omap_dsp_release_mem(); -out: - clk_disable(mmu->clk); - return 0; -} -EXPORT_SYMBOL_GPL(omap_mmu_load_tlb_entry); - -static inline unsigned long -omap_mmu_cam_va(struct omap_mmu *mmu, struct cam_ram_regset *cr) -{ - return mmu->ops->cam_va(cr); -} - -int omap_mmu_clear_tlb_entry(struct omap_mmu *mmu, unsigned long vadr) -{ - struct omap_mmu_tlb_lock lock; - int i, ret = 0; - int max_valid = 0; - - clk_enable(mmu->clk); - ret = omap_dsp_request_mem(); - if (ret < 0) - goto out; - - omap_mmu_get_tlb_lock(mmu, &lock); - for (i = 0; i < lock.base; i++) { - struct cam_ram_regset cr; - - /* read a TLB entry */ - lock.victim = i; - omap_mmu_read_tlb(mmu, &lock, &cr); - if (!omap_mmu_cam_ram_valid(mmu, &cr)) - continue; - - if (omap_mmu_cam_va(mmu, &cr) == vadr) - /* flush the entry */ - omap_mmu_flush(mmu); - else - max_valid = i; - } - - /* set new lock base */ - lock.base = lock.victim = max_valid + 1; - omap_mmu_set_tlb_lock(mmu, &lock); - - omap_dsp_release_mem(); -out: - clk_disable(mmu->clk); - return ret; -} -EXPORT_SYMBOL_GPL(omap_mmu_clear_tlb_entry); - -static void omap_mmu_gflush(struct omap_mmu *mmu) -{ - struct omap_mmu_tlb_lock lock; - int ret; - - clk_enable(mmu->clk); - ret = omap_dsp_request_mem(); - if (ret < 0) - goto out; - - omap_mmu_write_reg(mmu, 0x1, OMAP_MMU_GFLUSH); - lock.base = lock.victim = mmu->nr_exmap_preserved; - omap_mmu_set_tlb_lock(mmu, &lock); - - omap_dsp_release_mem(); -out: - clk_disable(mmu->clk); -} - -int omap_mmu_load_pte_entry(struct omap_mmu *mmu, - struct omap_mmu_tlb_entry *entry) -{ - int ret = -1; - /*XXX use PG_flag for prsvd */ - ret = omap_mmu_load_pte(mmu, entry); - if (ret) - return ret; - if (entry->tlb) - ret = omap_mmu_load_tlb_entry(mmu, entry); - return ret; -} -EXPORT_SYMBOL_GPL(omap_mmu_load_pte_entry); - -int omap_mmu_clear_pte_entry(struct omap_mmu *mmu, unsigned long vadr) -{ - int ret = omap_mmu_clear_tlb_entry(mmu, vadr); - if (ret) - return ret; - omap_mmu_clear_pte(mmu, vadr); - return ret; -} -EXPORT_SYMBOL_GPL(omap_mmu_clear_pte_entry); - -/* - * omap_mmu_exmap() - * - * MEM_IOCTL_EXMAP ioctl calls this function with padr=0. - * In this case, the buffer for external device is allocated in this routine, - * then it is mapped. - * On the other hand, for example - frame buffer sharing, calls - * this function with padr set. It means some known address space - * pointed with padr is going to be shared with external device. - */ -int omap_mmu_exmap(struct omap_mmu *mmu, unsigned long devadr, - unsigned long padr, unsigned long size, - enum exmap_type type) -{ - unsigned long pgsz; - void *buf; - unsigned int order = 0; - unsigned long unit; - int prev = -1; - unsigned long _devadr = devadr; - unsigned long _padr = padr; - void *_vadr = omap_mmu_to_virt(mmu, devadr); - unsigned long _size = size; - struct omap_mmu_tlb_entry tlb_ent; - struct exmap_tbl *exmap_ent, *tmp_ent; - int status; - int idx; - -#define MINIMUM_PAGESZ SZ_4K - /* - * alignment check - */ - if (!is_aligned(size, MINIMUM_PAGESZ)) { - dev_err(mmu->dev, - "MMU %s: size(0x%lx) is not multiple of 4KB.\n", - mmu->name, size); - return -EINVAL; - } - if (!is_aligned(devadr, MINIMUM_PAGESZ)) { - dev_err(mmu->dev, - "MMU %s: external device address(0x%lx) is not" - " aligned.\n", mmu->name, devadr); - return -EINVAL; - } - if (!is_aligned(padr, MINIMUM_PAGESZ)) { - dev_err(mmu->dev, - "MMU %s: physical address(0x%lx) is not aligned.\n", - mmu->name, padr); - return -EINVAL; - } - - /* address validity check */ - if ((devadr < mmu->memsize) || - (devadr >= (1 << mmu->addrspace))) { - dev_err(mmu->dev, - "MMU %s: illegal address/size for %s().\n", - mmu->name, __func__); - return -EINVAL; - } - - down_write(&mmu->exmap_sem); - - /* overlap check */ - omap_mmu_for_each_tlb_entry(mmu, tmp_ent) { - unsigned long mapsize; - - if (!tmp_ent->valid) - continue; - mapsize = 1 << (tmp_ent->order + PAGE_SHIFT); - if ((_vadr + size > tmp_ent->vadr) && - (_vadr < tmp_ent->vadr + mapsize)) { - dev_err(mmu->dev, "MMU %s: exmap page overlap!\n", - mmu->name); - up_write(&mmu->exmap_sem); - return -EINVAL; - } - } - -start: - buf = NULL; - /* Are there any free TLB lines? */ - for (idx = 0; idx < mmu->nr_tlb_entries; idx++) - if (!mmu->exmap_tbl[idx].valid) - goto found_free; - - dev_err(mmu->dev, "MMU %s: TLB is full.\n", mmu->name); - status = -EBUSY; - goto fail; - -found_free: - exmap_ent = mmu->exmap_tbl + idx; - - if ((_size >= SZ_1M) && - (is_aligned(_padr, SZ_1M) || (padr == 0)) && - is_aligned(_devadr, SZ_1M)) { - unit = SZ_1M; - pgsz = OMAP_MMU_CAM_PAGESIZE_1MB; - } else if ((_size >= SZ_64K) && - (is_aligned(_padr, SZ_64K) || (padr == 0)) && - is_aligned(_devadr, SZ_64K)) { - unit = SZ_64K; - pgsz = OMAP_MMU_CAM_PAGESIZE_64KB; - } else { - unit = SZ_4K; - pgsz = OMAP_MMU_CAM_PAGESIZE_4KB; - } - - order = get_order(unit); - - /* buffer allocation */ - if (type == EXMAP_TYPE_MEM) { - struct page *page, *ps, *pe; - - if ((order == ORDER_1MB) && likely(mempool_1M)) - buf = mempool_alloc_from_pool(mempool_1M, GFP_KERNEL); - else if ((order == ORDER_64KB) && likely(mempool_64K)) - buf = mempool_alloc_from_pool(mempool_64K, GFP_KERNEL); - else { - buf = (void *)__get_dma_pages(GFP_KERNEL, order); - if (buf == NULL) { - status = -ENOMEM; - goto fail; - } - } - - /* mark the pages as reserved; this is needed for mmap */ - ps = virt_to_page(buf); - pe = virt_to_page(buf + unit); - - for (page = ps; page < pe; page++) - SetPageReserved(page); - - _padr = __pa(buf); - } - - /* - * mapping for ARM MMU: - * we should not access to the allocated memory through 'buf' - * since this area should not be cached. - */ - status = exmap_set_armmmu(mmu, (unsigned long)_vadr, _padr, unit); - if (status < 0) - goto fail; - - /* loading external device PTE entry */ - INIT_TLB_ENTRY(&tlb_ent, _devadr, _padr, pgsz); - status = omap_mmu_load_pte_entry(mmu, &tlb_ent); - if (status < 0) { - exmap_clear_armmmu(mmu, (unsigned long)_vadr, unit); - goto fail; - } - - INIT_EXMAP_TBL_ENTRY(exmap_ent, buf, _vadr, type, order); - exmap_ent->link.prev = prev; - if (prev >= 0) - mmu->exmap_tbl[prev].link.next = idx; - - if ((_size -= unit) == 0) { /* normal completion */ - up_write(&mmu->exmap_sem); - return size; - } - - _devadr += unit; - _vadr += unit; - _padr = padr ? _padr + unit : 0; - prev = idx; - goto start; - -fail: - up_write(&mmu->exmap_sem); - if (buf) - omap_mmu_free_pages((unsigned long)buf, order); - omap_mmu_exunmap(mmu, devadr); - return status; -} -EXPORT_SYMBOL_GPL(omap_mmu_exmap); - -static unsigned long unmap_free_arm(struct omap_mmu *mmu, - struct exmap_tbl *ent) -{ - unsigned long size; - - /* clearing ARM MMU */ - size = 1 << (ent->order + PAGE_SHIFT); - exmap_clear_armmmu(mmu, (unsigned long)ent->vadr, size); - - /* freeing allocated memory */ - if (ent->type == EXMAP_TYPE_MEM) { - omap_mmu_free_pages((unsigned long)ent->buf, ent->order); - dev_dbg(mmu->dev, "MMU %s: freeing 0x%lx bytes @ adr 0x%8p\n", - mmu->name, size, ent->buf); - } - - ent->valid = 0; - return size; -} - -int omap_mmu_exunmap(struct omap_mmu *mmu, unsigned long devadr) -{ - void *vadr; - unsigned long size; - int total = 0; - struct exmap_tbl *ent; - int idx; - - vadr = omap_mmu_to_virt(mmu, devadr); - down_write(&mmu->exmap_sem); - for (idx = 0; idx < mmu->nr_tlb_entries; idx++) { - ent = mmu->exmap_tbl + idx; - if (!ent->valid || ent->prsvd) - continue; - if (ent->vadr == vadr) - goto found_map; - } - up_write(&mmu->exmap_sem); - dev_warn(mmu->dev, "MMU %s: address %06lx not found in exmap_tbl.\n", - mmu->name, devadr); - return -EINVAL; - -found_map: - if (ent->usecount > 0) { - dev_err(mmu->dev, "MMU %s: exmap reference count is not 0.\n" - " idx=%d, vadr=%p, order=%d, usecount=%d\n", - mmu->name, idx, ent->vadr, ent->order, ent->usecount); - up_write(&mmu->exmap_sem); - return -EINVAL; - } - /* clearing external device PTE entry */ - omap_mmu_clear_pte_entry(mmu, devadr); - - /* clear ARM MMU and free buffer */ - size = unmap_free_arm(mmu, ent); - total += size; - - /* we don't free PTEs */ - - /* flush TLB */ - flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size); - - /* check if next mapping is in same group */ - idx = ent->link.next; - if (idx < 0) - goto up_out; /* normal completion */ - ent = mmu->exmap_tbl + idx; - devadr += size; - vadr += size; - if (ent->vadr == vadr) - goto found_map; /* continue */ - - dev_err(mmu->dev, "MMU %s: illegal exmap_tbl grouping!\n" - "expected vadr = %p, exmap_tbl[%d].vadr = %p\n", - mmu->name, vadr, idx, ent->vadr); - up_write(&mmu->exmap_sem); - return -EINVAL; - -up_out: - up_write(&mmu->exmap_sem); - return total; -} -EXPORT_SYMBOL_GPL(omap_mmu_exunmap); - -void omap_mmu_exmap_flush(struct omap_mmu *mmu) -{ - struct exmap_tbl *ent; - - down_write(&mmu->exmap_sem); - - /* clearing TLB entry */ - omap_mmu_gflush(mmu); - - omap_mmu_for_each_tlb_entry(mmu, ent) - if (ent->valid && !ent->prsvd) - unmap_free_arm(mmu, ent); - - /* flush TLB */ - if (likely(mmu->membase)) - flush_tlb_kernel_range(mmu->membase + mmu->memsize, - mmu->membase + (1 << mmu->addrspace)); - - up_write(&mmu->exmap_sem); -} -EXPORT_SYMBOL_GPL(omap_mmu_exmap_flush); - -void exmap_setup_preserved_mem_page(struct omap_mmu *mmu, void *buf, - unsigned long devadr, int index) -{ - unsigned long phys; - void *virt; - struct omap_mmu_tlb_entry tlb_ent; - - phys = __pa(buf); - virt = omap_mmu_to_virt(mmu, devadr); - exmap_set_armmmu(mmu, (unsigned long)virt, phys, PAGE_SIZE); - INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(mmu->exmap_tbl + index, buf, virt); - INIT_TLB_ENTRY_4KB_PRESERVED(&tlb_ent, devadr, phys); - omap_mmu_load_pte_entry(mmu, &tlb_ent); -} -EXPORT_SYMBOL_GPL(exmap_setup_preserved_mem_page); - -void exmap_clear_mem_page(struct omap_mmu *mmu, unsigned long devadr) -{ - void *virt = omap_mmu_to_virt(mmu, devadr); - - exmap_clear_armmmu(mmu, (unsigned long)virt, PAGE_SIZE); - /* DSP MMU is shutting down. not handled here. */ -} -EXPORT_SYMBOL_GPL(exmap_clear_mem_page); - -static void omap_mmu_reset(struct omap_mmu *mmu) -{ -#if defined(CONFIG_ARCH_OMAP2) /* FIXME */ - int i; - - omap_mmu_write_reg(mmu, 0x2, OMAP_MMU_SYSCONFIG); - - for (i = 0; i < 10000; i++) - if (likely(omap_mmu_read_reg(mmu, OMAP_MMU_SYSSTATUS) & 0x1)) - break; -#endif -} - -void omap_mmu_disable(struct omap_mmu *mmu) -{ - omap_mmu_write_reg(mmu, 0x00, OMAP_MMU_CNTL); -} -EXPORT_SYMBOL_GPL(omap_mmu_disable); - -void omap_mmu_enable(struct omap_mmu *mmu, int reset) -{ - u32 val = OMAP_MMU_CNTL_MMU_EN | MMU_CNTL_TWLENABLE; - - if (likely(reset)) - omap_mmu_reset(mmu); -#if defined(CONFIG_ARCH_OMAP2) /* FIXME */ - omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd), - OMAP_MMU_TTB); -#else - omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd) & 0xffff, - OMAP_MMU_TTB_L); - omap_mmu_write_reg(mmu, (u32)virt_to_phys(mmu->twl_mm->pgd) >> 16, - OMAP_MMU_TTB_H); - val |= OMAP_MMU_CNTL_RESET_SW; -#endif - omap_mmu_write_reg(mmu, val, OMAP_MMU_CNTL); -} -EXPORT_SYMBOL_GPL(omap_mmu_enable); - -static irqreturn_t omap_mmu_interrupt(int irq, void *dev_id) -{ - struct omap_mmu *mmu = dev_id; - - if (likely(mmu->ops->interrupt)) - mmu->ops->interrupt(mmu); - - return IRQ_HANDLED; -} - -static int omap_mmu_init(struct omap_mmu *mmu) -{ - struct omap_mmu_tlb_lock tlb_lock; - int ret = 0; - - clk_enable(mmu->clk); - ret = omap_dsp_request_mem(); - if (ret < 0) - goto out; - - down_write(&mmu->exmap_sem); - - ret = request_irq(mmu->irq, omap_mmu_interrupt, IRQF_DISABLED, - mmu->name, mmu); - if (ret < 0) { - dev_err(mmu->dev, "MMU %s: failed to register MMU interrupt:" - " %d\n", mmu->name, ret); - goto fail; - } - - omap_mmu_disable(mmu); /* clear all */ - udelay(100); - omap_mmu_enable(mmu, 1); - - memset(&tlb_lock, 0, sizeof(struct omap_mmu_tlb_lock)); - omap_mmu_set_tlb_lock(mmu, &tlb_lock); - - if (unlikely(mmu->ops->startup)) - ret = mmu->ops->startup(mmu); -fail: - up_write(&mmu->exmap_sem); - omap_dsp_release_mem(); -out: - clk_disable(mmu->clk); - - return ret; -} - -static void omap_mmu_shutdown(struct omap_mmu *mmu) -{ - free_irq(mmu->irq, mmu); - - if (unlikely(mmu->ops->shutdown)) - mmu->ops->shutdown(mmu); - - omap_mmu_exmap_flush(mmu); - omap_mmu_disable(mmu); /* clear all */ -} - -/* - * omap_mmu_mem_enable() / disable() - */ -int omap_mmu_mem_enable(struct omap_mmu *mmu, void *addr) -{ - if (unlikely(mmu->ops->mem_enable)) - return mmu->ops->mem_enable(mmu, addr); - - down_read(&mmu->exmap_sem); - return 0; -} -EXPORT_SYMBOL_GPL(omap_mmu_mem_enable); - -void omap_mmu_mem_disable(struct omap_mmu *mmu, void *addr) -{ - if (unlikely(mmu->ops->mem_disable)) { - mmu->ops->mem_disable(mmu, addr); - return; - } - - up_read(&mmu->exmap_sem); -} -EXPORT_SYMBOL_GPL(omap_mmu_mem_disable); - -/* - * dsp_mem file operations - */ -static ssize_t intmem_read(struct omap_mmu *mmu, char *buf, size_t count, - loff_t *ppos) -{ - unsigned long p = *ppos; - void *vadr = omap_mmu_to_virt(mmu, p); - ssize_t size = mmu->memsize; - ssize_t read; - - if (p >= size) - return 0; - clk_enable(mmu->memclk); - read = count; - if (count > size - p) - read = size - p; - if (copy_to_user(buf, vadr, read)) { - read = -EFAULT; - goto out; - } - *ppos += read; -out: - clk_disable(mmu->memclk); - return read; -} - -static ssize_t exmem_read(struct omap_mmu *mmu, char *buf, size_t count, - loff_t *ppos) -{ - unsigned long p = *ppos; - void *vadr = omap_mmu_to_virt(mmu, p); - - if (!exmap_valid(mmu, vadr, count)) { - dev_err(mmu->dev, "MMU %s: external device address %08lx / " - "size %08x is not valid!\n", mmu->name, p, count); - return -EFAULT; - } - if (count > (1 << mmu->addrspace) - p) - count = (1 << mmu->addrspace) - p; - if (copy_to_user(buf, vadr, count)) - return -EFAULT; - *ppos += count; - - return count; -} - -static ssize_t omap_mmu_mem_read(struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t count) -{ - struct device *dev = to_dev(kobj); - struct omap_mmu *mmu = dev_get_drvdata(dev); - unsigned long p = (unsigned long)offset; - void *vadr = omap_mmu_to_virt(mmu, p); - int ret; - - if (omap_mmu_mem_enable(mmu, vadr) < 0) - return -EBUSY; - - if (p < mmu->memsize) - ret = intmem_read(mmu, buf, count, &offset); - else - ret = exmem_read(mmu, buf, count, &offset); - - omap_mmu_mem_disable(mmu, vadr); - - return ret; -} - -static ssize_t intmem_write(struct omap_mmu *mmu, const char *buf, size_t count, - loff_t *ppos) -{ - unsigned long p = *ppos; - void *vadr = omap_mmu_to_virt(mmu, p); - ssize_t size = mmu->memsize; - ssize_t written; - - if (p >= size) - return 0; - clk_enable(mmu->memclk); - written = count; - if (count > size - p) - written = size - p; - if (copy_from_user(vadr, buf, written)) { - written = -EFAULT; - goto out; - } - *ppos += written; -out: - clk_disable(mmu->memclk); - return written; -} - -static ssize_t exmem_write(struct omap_mmu *mmu, char *buf, size_t count, - loff_t *ppos) -{ - unsigned long p = *ppos; - void *vadr = omap_mmu_to_virt(mmu, p); - - if (!exmap_valid(mmu, vadr, count)) { - dev_err(mmu->dev, "MMU %s: external device address %08lx " - "/ size %08x is not valid!\n", mmu->name, p, count); - return -EFAULT; - } - if (count > (1 << mmu->addrspace) - p) - count = (1 << mmu->addrspace) - p; - if (copy_from_user(vadr, buf, count)) - return -EFAULT; - *ppos += count; - - return count; -} - -static ssize_t omap_mmu_mem_write(struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t count) -{ - struct device *dev = to_dev(kobj); - struct omap_mmu *mmu = dev_get_drvdata(dev); - unsigned long p = (unsigned long)offset; - void *vadr = omap_mmu_to_virt(mmu, p); - int ret; - - if (omap_mmu_mem_enable(mmu, vadr) < 0) - return -EBUSY; - - if (p < mmu->memsize) - ret = intmem_write(mmu, buf, count, &offset); - else - ret = exmem_write(mmu, buf, count, &offset); - - omap_mmu_mem_disable(mmu, vadr); - - return ret; -} - -static struct bin_attribute dev_attr_mem = { - .attr = { - .name = "mem", - .owner = THIS_MODULE, - .mode = S_IRUSR | S_IWUSR | S_IRGRP, - }, - - .read = omap_mmu_mem_read, - .write = omap_mmu_mem_write, -}; - -/* To be obsolete for backward compatibility */ -ssize_t __omap_mmu_mem_read(struct omap_mmu *mmu, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t count) -{ - return omap_mmu_mem_read(&mmu->dev->kobj, attr, buf, offset, count); -} -EXPORT_SYMBOL_GPL(__omap_mmu_mem_read); - -ssize_t __omap_mmu_mem_write(struct omap_mmu *mmu, - struct bin_attribute *attr, - char *buf, loff_t offset, size_t count) -{ - return omap_mmu_mem_write(&mmu->dev->kobj, attr, buf, offset, count); -} -EXPORT_SYMBOL_GPL(__omap_mmu_mem_write); - -/* - * sysfs files - */ -static ssize_t omap_mmu_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct omap_mmu *mmu = dev_get_drvdata(dev); - struct omap_mmu_tlb_lock tlb_lock; - int ret; - - clk_enable(mmu->clk); - ret = omap_dsp_request_mem(); - if (ret < 0) - goto out; - - down_read(&mmu->exmap_sem); - - omap_mmu_get_tlb_lock(mmu, &tlb_lock); - - ret = -EIO; - if (likely(mmu->ops->show)) - ret = mmu->ops->show(mmu, buf, &tlb_lock); - - /* restore victim entry */ - omap_mmu_set_tlb_lock(mmu, &tlb_lock); - - up_read(&mmu->exmap_sem); - omap_dsp_release_mem(); -out: - clk_disable(mmu->clk); - - return ret; -} - -static DEVICE_ATTR(mmu, S_IRUGO, omap_mmu_show, NULL); - -static ssize_t exmap_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct omap_mmu *mmu = dev_get_drvdata(dev); - struct exmap_tbl *ent; - int len; - int i = 0; - - down_read(&mmu->exmap_sem); - len = sprintf(buf, " devadr size buf size uc\n"); - /* 0x300000 0x123000 0xc0171000 0x100000 0*/ - - omap_mmu_for_each_tlb_entry(mmu, ent) { - void *vadr; - unsigned long size; - enum exmap_type type; - int idx; - - /* find a top of link */ - if (!ent->valid || (ent->link.prev >= 0)) - continue; - - vadr = ent->vadr; - type = ent->type; - size = 0; - idx = i; - do { - ent = mmu->exmap_tbl + idx; - size += PAGE_SIZE << ent->order; - } while ((idx = ent->link.next) >= 0); - - len += sprintf(buf + len, "0x%06lx %#8lx", - virt_to_omap_mmu(mmu, vadr), size); - - if (type == EXMAP_TYPE_FB) { - len += sprintf(buf + len, " framebuf\n"); - } else { - len += sprintf(buf + len, "\n"); - idx = i; - do { - ent = mmu->exmap_tbl + idx; - len += sprintf(buf + len, - /* 0xc0171000 0x100000 0*/ - "%19s0x%8p %#8lx %2d\n", - "", ent->buf, - PAGE_SIZE << ent->order, - ent->usecount); - } while ((idx = ent->link.next) >= 0); - } - - i++; - } - - up_read(&mmu->exmap_sem); - return len; -} - -static ssize_t exmap_store(struct device *dev, struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct omap_mmu *mmu = dev_get_drvdata(dev); - unsigned long base = 0, len = 0; - int ret; - - sscanf(buf, "%lx %lx", &base, &len); - - if (!base) - return -EINVAL; - - if (len) { - /* Add the mapping */ - ret = omap_mmu_exmap(mmu, base, 0, len, EXMAP_TYPE_MEM); - if (ret < 0) - return ret; - } else { - /* Remove the mapping */ - ret = omap_mmu_exunmap(mmu, base); - if (ret < 0) - return ret; - } - - return count; -} - -static DEVICE_ATTR(exmap, S_IRUGO | S_IWUSR, exmap_show, exmap_store); - -static ssize_t mempool_show(struct class *class, char *buf) -{ - int min_nr_1M = 0, curr_nr_1M = 0; - int min_nr_64K = 0, curr_nr_64K = 0; - int total = 0; - - if (likely(mempool_1M)) { - min_nr_1M = mempool_1M->min_nr; - curr_nr_1M = mempool_1M->curr_nr; - total += min_nr_1M * SZ_1M; - } - if (likely(mempool_64K)) { - min_nr_64K = mempool_64K->min_nr; - curr_nr_64K = mempool_64K->curr_nr; - total += min_nr_64K * SZ_64K; - } - - return sprintf(buf, - "0x%x\n" - "1M buffer: %d (%d free)\n" - "64K buffer: %d (%d free)\n", - total, min_nr_1M, curr_nr_1M, min_nr_64K, curr_nr_64K); -} - - -static CLASS_ATTR(mempool, S_IRUGO, mempool_show, NULL); - -static struct class omap_mmu_class = { - .name = "mmu", -}; - -int omap_mmu_register(struct omap_mmu *mmu) -{ - int ret; - - mmu->dev = device_create(&omap_mmu_class, NULL, 0, "%s", mmu->name); - if (unlikely(IS_ERR(mmu->dev))) - return PTR_ERR(mmu->dev); - dev_set_drvdata(mmu->dev, mmu); - - mmu->exmap_tbl = kcalloc(mmu->nr_tlb_entries, sizeof(struct exmap_tbl), - GFP_KERNEL); - if (!mmu->exmap_tbl) - return -ENOMEM; - - mmu->twl_mm = mm_alloc(); - if (!mmu->twl_mm) { - ret = -ENOMEM; - goto err_mm_alloc; - } - - init_rwsem(&mmu->exmap_sem); - - ret = omap_mmu_init(mmu); - if (unlikely(ret)) - goto err_mmu_init; - - ret = device_create_file(mmu->dev, &dev_attr_mmu); - if (unlikely(ret)) - goto err_dev_create_mmu; - ret = device_create_file(mmu->dev, &dev_attr_exmap); - if (unlikely(ret)) - goto err_dev_create_exmap; - - if (likely(mmu->membase)) { - dev_attr_mem.size = mmu->memsize; - ret = device_create_bin_file(mmu->dev, - &dev_attr_mem); - if (unlikely(ret)) - goto err_bin_create_mem; - } - return 0; - -err_bin_create_mem: - device_remove_file(mmu->dev, &dev_attr_exmap); -err_dev_create_exmap: - device_remove_file(mmu->dev, &dev_attr_mmu); -err_dev_create_mmu: - omap_mmu_shutdown(mmu); -err_mmu_init: - kfree(mmu->twl_mm); - mmu->twl_mm = NULL; -err_mm_alloc: - kfree(mmu->exmap_tbl); - mmu->exmap_tbl = NULL; - device_unregister(mmu->dev); - return ret; -} -EXPORT_SYMBOL_GPL(omap_mmu_register); - -void omap_mmu_unregister(struct omap_mmu *mmu) -{ - omap_mmu_shutdown(mmu); - omap_mmu_kmem_release(); - - device_remove_file(mmu->dev, &dev_attr_mmu); - device_remove_file(mmu->dev, &dev_attr_exmap); - - if (likely(mmu->membase)) - device_remove_bin_file(mmu->dev, &dev_attr_mem); - - device_unregister(mmu->dev); - - kfree(mmu->exmap_tbl); - mmu->exmap_tbl = NULL; - - if (mmu->twl_mm) { - __mmdrop(mmu->twl_mm); - mmu->twl_mm = NULL; - } -} -EXPORT_SYMBOL_GPL(omap_mmu_unregister); - -static int __init omap_mmu_class_init(void) -{ - int ret = class_register(&omap_mmu_class); - if (!ret) - ret = class_create_file(&omap_mmu_class, &class_attr_mempool); - - return ret; -} - -static void __exit omap_mmu_class_exit(void) -{ - class_remove_file(&omap_mmu_class, &class_attr_mempool); - class_unregister(&omap_mmu_class); -} - -subsys_initcall(omap_mmu_class_init); -module_exit(omap_mmu_class_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/Makefile b/drivers/Makefile index a0f11ed99e7..67de08bb8cd 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -42,7 +42,6 @@ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ mfd/ net/ media/ cbus/ obj-y += i2c/ obj-y += cbus/ -obj-$(CONFIG_ARCH_OMAP) += dsp/dspgateway/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-y += macintosh/ diff --git a/drivers/dsp/dspgateway/Kconfig b/drivers/dsp/dspgateway/Kconfig deleted file mode 100644 index 122164abbf9..00000000000 --- a/drivers/dsp/dspgateway/Kconfig +++ /dev/null @@ -1,24 +0,0 @@ - -config OMAP_DSP - tristate "OMAP DSP driver (DSP Gateway)" - depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP24XX - select OMAP_MMU_FWK - select OMAP_MBOX_FWK - help - This enables OMAP DSP driver, DSP Gateway. - -config OMAP_DSP_MBCMD_VERBOSE - bool "Mailbox Command Verbose LOG" - depends on OMAP_DSP - help - This enables kernel log output in the Mailbox command exchanges - in the DSP Gateway driver. - -config OMAP_DSP_FBEXPORT - bool "Framebuffer export to DSP" - depends on OMAP_DSP && FB - help - This enables to map the frame buffer to DSP. - By doing this, DSP can access the frame buffer directly without - bothering ARM. - diff --git a/drivers/dsp/dspgateway/Makefile b/drivers/dsp/dspgateway/Makefile deleted file mode 100644 index c7d86f358b5..00000000000 --- a/drivers/dsp/dspgateway/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for the OMAP DSP driver. -# - -# The target object and module list name. - -obj-y := dsp_common.o - -obj-$(CONFIG_OMAP_DSP) += dsp.o - -# Declare multi-part drivers - -dsp-objs := dsp_core.o ipbuf.o mblog.o task.o \ - dsp_ctl_core.o dsp_ctl.o taskwatch.o error.o dsp_mem.o \ - uaccess_dsp.o diff --git a/drivers/dsp/dspgateway/dsp.h b/drivers/dsp/dspgateway/dsp.h deleted file mode 100644 index 84e7ceaa037..00000000000 --- a/drivers/dsp/dspgateway/dsp.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __PLAT_OMAP_DSP_DSP_H -#define __PLAT_OMAP_DSP_DSP_H - -#include "hardware_dsp.h" -#include -#include - - -#ifdef CONFIG_ARCH_OMAP2 -#include "../../../arch/arm/mach-omap2/prm.h" -#include "../../../arch/arm/mach-omap2/prm-regbits-24xx.h" -#include "../../../arch/arm/mach-omap2/cm.h" -#include "../../../arch/arm/mach-omap2/cm-regbits-24xx.h" -#endif - -/* - * MAJOR device number: !! allocated arbitrary !! - */ -#define OMAP_DSP_CTL_MAJOR 96 -#define OMAP_DSP_TASK_MAJOR 97 - -#define OLD_BINARY_SUPPORT y - -#ifdef OLD_BINARY_SUPPORT -#define MBREV_3_0 0x0017 -#define MBREV_3_2 0x0018 -#endif - -#define DSP_INIT_PAGE 0xfff000 - -#ifdef CONFIG_ARCH_OMAP1 -/* idle program will be placed at IDLEPG_BASE. */ -#define IDLEPG_BASE 0xfffe00 -#define IDLEPG_SIZE 0x100 -#endif /* CONFIG_ARCH_OMAP1 */ - -/* timeout value for DSP response */ -#define DSP_TIMEOUT (10 * HZ) - -enum dsp_mem_type_e { - MEM_TYPE_CROSSING = -1, - MEM_TYPE_NONE = 0, - MEM_TYPE_DARAM, - MEM_TYPE_SARAM, - MEM_TYPE_EXTERN, -}; - - -typedef int __bitwise arm_dsp_dir_t; -#define DIR_A2D ((__force arm_dsp_dir_t) 1) -#define DIR_D2A ((__force arm_dsp_dir_t) 2) - -enum cfgstat_e { - CFGSTAT_CLEAN = 0, - CFGSTAT_READY, - CFGSTAT_SUSPEND, - CFGSTAT_RESUME, /* request only */ - CFGSTAT_MAX -}; - -enum errcode_e { - ERRCODE_WDT = 0, - ERRCODE_MMU, - ERRCODE_MAX -}; - -/* keep 2 entries for TID_FREE and TID_ANON */ -#define TASKDEV_MAX 254 - -#define MK32(uw,lw) (((u32)(uw)) << 16 | (lw)) -#define MKLONG(uw,lw) (((unsigned long)(uw)) << 16 | (lw)) -#define MKVIRT(uw,lw) dspword_to_virt(MKLONG((uw), (lw))); - -struct sync_seq { - u16 da_dsp; - u16 da_arm; - u16 ad_dsp; - u16 ad_arm; -}; - -struct mem_sync_struct { - struct sync_seq *DARAM; - struct sync_seq *SARAM; - struct sync_seq *SDRAM; -}; - -/* struct mbcmd and union mbcmd_hw must be compatible */ -struct mbcmd { - u32 data:16; - u32 cmd_l:8; - u32 cmd_h:7; - u32 seq:1; -}; - -#define MBCMD_INIT(h, l, d) { \ - .cmd_h = (h), \ - .cmd_l = (l), \ - .data = (d), \ - } - -struct mb_exarg { - u8 tid; - int argc; - u16 *argv; -}; - -typedef u32 dsp_long_t; /* must have ability to carry TADD_ABORTADR */ - -extern void dsp_mbox_start(void); -extern void dsp_mbox_stop(void); -extern int dsp_mbox_config(void *p); -extern int sync_with_dsp(u16 *syncwd, u16 tid, int try_cnt); -extern int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg, - int recovery_flag); -#define dsp_mbcmd_send(mb) __dsp_mbcmd_send_exarg((mb), NULL, 0) -#define dsp_mbcmd_send_exarg(mb, arg) __dsp_mbcmd_send_exarg((mb), (arg), 0) -extern int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg, - wait_queue_head_t *q); -#define dsp_mbcmd_send_and_wait(mb, q) \ - dsp_mbcmd_send_and_wait_exarg((mb), NULL, (q)) - -static inline int __mbcompose_send_exarg(u8 cmd_h, u8 cmd_l, u16 data, - struct mb_exarg *arg, - int recovery_flag) -{ - struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data); - return __dsp_mbcmd_send_exarg(&mb, arg, recovery_flag); -} -#define mbcompose_send(cmd_h, cmd_l, data) \ - __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 0) -#define mbcompose_send_exarg(cmd_h, cmd_l, data, arg) \ - __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), arg, 0) -#define mbcompose_send_recovery(cmd_h, cmd_l, data) \ - __mbcompose_send_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), NULL, 1) - -static inline int __mbcompose_send_and_wait_exarg(u8 cmd_h, u8 cmd_l, - u16 data, - struct mb_exarg *arg, - wait_queue_head_t *q) -{ - struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data); - return dsp_mbcmd_send_and_wait_exarg(&mb, arg, q); -} -#define mbcompose_send_and_wait(cmd_h, cmd_l, data, q) \ - __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \ - NULL, (q)) -#define mbcompose_send_and_wait_exarg(cmd_h, cmd_l, data, arg, q) \ - __mbcompose_send_and_wait_exarg(MBOX_CMD_DSP_##cmd_h, (cmd_l), (data), \ - (arg), (q)) - -extern struct ipbuf_head *bid_to_ipbuf(u16 bid); -extern void ipbuf_start(void); -extern void ipbuf_stop(void); -extern int ipbuf_config(u16 ln, u16 lsz, void *base); -extern int ipbuf_sys_config(void *p, arm_dsp_dir_t dir); -extern int ipbuf_p_validate(void *p, arm_dsp_dir_t dir); -extern struct ipbuf_head *get_free_ipbuf(u8 tid); -extern void release_ipbuf(struct ipbuf_head *ipb_h); -extern void balance_ipbuf(void); -extern void unuse_ipbuf(struct ipbuf_head *ipb_h); -extern void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h); - -#define release_ipbuf_pvt(ipbuf_pvt) \ - do { \ - (ipbuf_pvt)->s = TID_FREE; \ - } while(0) - -extern int mbox_revision; - -extern int dsp_cfgstat_request(enum cfgstat_e st); -extern enum cfgstat_e dsp_cfgstat_get_stat(void); -extern int dsp_set_runlevel(u8 level); - -extern int dsp_task_config_all(u8 n); -extern void dsp_task_unconfig_all(void); -extern u8 dsp_task_count(void); -extern int dsp_taskmod_busy(void); -extern int dsp_mkdev(char *name); -extern int dsp_rmdev(char *name); -extern int dsp_tadd_minor(unsigned char minor, dsp_long_t adr); -extern int dsp_tdel_minor(unsigned char minor); -extern int dsp_tkill_minor(unsigned char minor); -extern long taskdev_state_stale(unsigned char minor); -extern int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz); -extern void dsp_dbg_stop(void); - -extern int ipbuf_is_held(u8 tid, u16 bid); - -extern int dsp_mem_sync_inc(void); -extern int dsp_mem_sync_config(struct mem_sync_struct *sync); -extern enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len); -extern int dsp_address_validate(void *p, size_t len, char *fmt, ...); -#ifdef CONFIG_ARCH_OMAP1 -extern void dsp_mem_usecount_clear(void); -#endif -extern void exmap_use(void *vadr, size_t len); -extern void exmap_unuse(void *vadr, size_t len); -extern unsigned long dsp_virt_to_phys(void *vadr, size_t *len); -extern void dsp_mem_start(void); -extern void dsp_mem_stop(void); - -extern void dsp_twch_start(void); -extern void dsp_twch_stop(void); -extern void dsp_twch_touch(void); - -extern void dsp_err_start(void); -extern void dsp_err_stop(void); -extern void dsp_err_set(enum errcode_e code, unsigned long arg); -extern void dsp_err_clear(enum errcode_e code); -extern int dsp_err_isset(enum errcode_e code); - -enum cmd_l_type_e { - CMD_L_TYPE_NULL, - CMD_L_TYPE_TID, - CMD_L_TYPE_SUBCMD, -}; - -struct cmdinfo { - char *name; - enum cmd_l_type_e cmd_l_type; - void (*handler)(struct mbcmd *mb); -}; - -extern const struct cmdinfo *cmdinfo[]; - -#define cmd_name(mb) (cmdinfo[(mb).cmd_h]->name) -extern char *subcmd_name(struct mbcmd *mb); - -extern void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir); - -extern struct omap_mmu dsp_mmu; - -#define dsp_mem_enable(addr) omap_mmu_mem_enable(&dsp_mmu, (addr)) -#define dsp_mem_disable(addr) omap_mmu_mem_disable(&dsp_mmu, (addr)) - -#define DSPSPACE_SIZE 0x1000000 - -#define omap_set_bit_regw(b,r) \ - do { omap_writew(omap_readw(r) | (b), (r)); } while(0) -#define omap_clr_bit_regw(b,r) \ - do { omap_writew(omap_readw(r) & ~(b), (r)); } while(0) -#define omap_set_bit_regl(b,r) \ - do { omap_writel(omap_readl(r) | (b), (r)); } while(0) -#define omap_clr_bit_regl(b,r) \ - do { omap_writel(omap_readl(r) & ~(b), (r)); } while(0) -#define omap_set_bits_regl(val,mask,r) \ - do { omap_writel((omap_readl(r) & ~(mask)) | (val), (r)); } while(0) - -#define dspword_to_virt(dw) ((void *)(dspmem_base + ((dw) << 1))) -#define dspbyte_to_virt(db) ((void *)(dspmem_base + (db))) -#define virt_to_dspword(va) \ - ((dsp_long_t)(((unsigned long)(va) - dspmem_base) >> 1)) -#define virt_to_dspbyte(va) \ - ((dsp_long_t)((unsigned long)(va) - dspmem_base)) -#define is_dsp_internal_mem(va) \ - (((unsigned long)(va) >= dspmem_base) && \ - ((unsigned long)(va) < dspmem_base + dspmem_size)) -#define is_dspbyte_internal_mem(db) ((db) < dspmem_size) -#define is_dspword_internal_mem(dw) (((dw) << 1) < dspmem_size) - -#ifdef CONFIG_ARCH_OMAP1 -/* - * MPUI byteswap/wordswap on/off - * default setting: wordswap = all, byteswap = APIMEM only - */ -#define mpui_wordswap_on() \ - omap_set_bits_regl(MPUI_CTRL_WORDSWAP_ALL, MPUI_CTRL_WORDSWAP_MASK, \ - MPUI_CTRL) - -#define mpui_wordswap_off() \ - omap_set_bits_regl(MPUI_CTRL_WORDSWAP_NONE, MPUI_CTRL_WORDSWAP_MASK, \ - MPUI_CTRL) - -#define mpui_byteswap_on() \ - omap_set_bits_regl(MPUI_CTRL_BYTESWAP_API, MPUI_CTRL_BYTESWAP_MASK, \ - MPUI_CTRL) - -#define mpui_byteswap_off() \ - omap_set_bits_regl(MPUI_CTRL_BYTESWAP_NONE, MPUI_CTRL_BYTESWAP_MASK, \ - MPUI_CTRL) - -/* - * TC wordswap on / off - */ -#define tc_wordswap() \ - do { \ - omap_writel(TC_ENDIANISM_SWAP_WORD | TC_ENDIANISM_EN, \ - TC_ENDIANISM); \ - } while(0) - -#define tc_noswap() omap_clr_bit_regl(TC_ENDIANISM_EN, TC_ENDIANISM) - -/* - * enable priority registers, EMIF, MPUI control logic - */ -#define __dsp_enable() omap_set_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1) -#define __dsp_disable() omap_clr_bit_regw(ARM_RSTCT1_DSP_RST, ARM_RSTCT1) -#define __dsp_run() omap_set_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1) -#define __dsp_reset() omap_clr_bit_regw(ARM_RSTCT1_DSP_EN, ARM_RSTCT1) -#endif /* CONFIG_ARCH_OMAP1 */ - -#ifdef CONFIG_ARCH_OMAP2 -/* - * PRCM / IPI control logic - * - * REVISIT: these macros should probably be static inline functions - */ -#define __dsp_core_enable() \ - do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \ - & ~OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0) -#define __dsp_core_disable() \ - do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \ - | OMAP24XX_RST1_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0) -#define __dsp_per_enable() \ - do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \ - & ~OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0) -#define __dsp_per_disable() \ - do { prm_write_mod_reg(prm_read_mod_reg(OMAP24XX_DSP_MOD, RM_RSTCTRL) \ - | OMAP24XX_RST2_DSP, OMAP24XX_DSP_MOD, RM_RSTCTRL); } while (0) -#endif /* CONFIG_ARCH_OMAP2 */ - -#if defined(CONFIG_ARCH_OMAP1) -extern struct clk *dsp_ck_handle; -extern struct clk *api_ck_handle; -#elif defined(CONFIG_ARCH_OMAP2) -extern struct clk *dsp_fck_handle; -extern struct clk *dsp_ick_handle; -#endif -extern dsp_long_t dspmem_base, dspmem_size, - daram_base, daram_size, - saram_base, saram_size; - -enum cpustat_e { - CPUSTAT_RESET = 0, -#ifdef CONFIG_ARCH_OMAP1 - CPUSTAT_GBL_IDLE, - CPUSTAT_CPU_IDLE, -#endif - CPUSTAT_RUN, - CPUSTAT_MAX -}; - -int dsp_set_rstvect(dsp_long_t adr); -dsp_long_t dsp_get_rstvect(void); -void dsp_set_idle_boot_base(dsp_long_t adr, size_t size); -void dsp_reset_idle_boot_base(void); -void dsp_cpustat_request(enum cpustat_e req); -enum cpustat_e dsp_cpustat_get_stat(void); -u16 dsp_cpustat_get_icrmask(void); -void dsp_cpustat_set_icrmask(u16 mask); -void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)); -void dsp_unregister_mem_cb(void); - -#if defined(CONFIG_ARCH_OMAP1) -#define command_dvfs_stop(m) (0) -#define command_dvfs_start(m) (0) -#elif defined(CONFIG_ARCH_OMAP2) -#define command_dvfs_stop(m) \ - (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_STOP)) -#define command_dvfs_start(m) \ - (((m)->cmd_l == KFUNC_POWER) && ((m)->data == DVFS_START)) -#endif - -extern struct omap_dsp *omap_dsp; - -extern int dsp_late_init(void); - -#endif /* __PLAT_OMAP_DSP_DSP_H */ diff --git a/drivers/dsp/dspgateway/dsp_common.c b/drivers/dsp/dspgateway/dsp_common.c deleted file mode 100644 index 9dffda2252e..00000000000 --- a/drivers/dsp/dspgateway/dsp_common.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dsp.h" - -#ifdef CONFIG_ARCH_OMAP1 -#include -#endif - -#if defined(CONFIG_ARCH_OMAP1) -#define dsp_boot_config(mode) omap_writew((mode), MPUI_DSP_BOOT_CONFIG) -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -#define dsp_boot_config(mode) writel((mode), DSP_IPI_DSPBOOTCONFIG) -#endif - -struct omap_dsp *omap_dsp; - -#if defined(CONFIG_ARCH_OMAP1) -struct clk *dsp_ck_handle; -struct clk *api_ck_handle; -#elif defined(CONFIG_ARCH_OMAP2) -struct clk *dsp_fck_handle; -struct clk *dsp_ick_handle; -#endif -dsp_long_t dspmem_base, dspmem_size, - daram_base, daram_size, - saram_base, saram_size; - -static struct cpustat { - struct mutex lock; - enum cpustat_e stat; - enum cpustat_e req; - u16 icrmask; -#ifdef CONFIG_ARCH_OMAP1 - struct { - int mpui; - int mem; - int mem_delayed; - } usecount; - int (*mem_req_cb)(void); - void (*mem_rel_cb)(void); -#endif -} cpustat = { - .stat = CPUSTAT_RESET, - .icrmask = 0xffff, -}; - -int dsp_set_rstvect(dsp_long_t adr) -{ - unsigned long *dst_adr; - - if (adr >= DSPSPACE_SIZE) - return -EINVAL; - - dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT); - /* word swap */ - *dst_adr = ((adr & 0xffff) << 16) | (adr >> 16); - /* fill 8 bytes! */ - *(dst_adr + 1) = 0; - /* direct boot */ - dsp_boot_config(DSP_BOOT_CONFIG_DIRECT); - - return 0; -} - -dsp_long_t dsp_get_rstvect(void) -{ - unsigned long *dst_adr; - - dst_adr = dspbyte_to_virt(DSP_BOOT_ADR_DIRECT); - return ((*dst_adr & 0xffff) << 16) | (*dst_adr >> 16); -} - -#ifdef CONFIG_ARCH_OMAP1 -static void simple_load_code(unsigned char *src_c, u16 *dst, int len) -{ - int i; - u16 *src = (u16 *)src_c; - int len_w; - - /* len must be multiple of 2. */ - if (len & 1) - BUG(); - - len_w = len / 2; - for (i = 0; i < len_w; i++) { - /* byte swap copy */ - *dst = ((*src & 0x00ff) << 8) | - ((*src & 0xff00) >> 8); - src++; - dst++; - } -} - -/* program size must be multiple of 2 */ -#define GBL_IDLE_TEXT_SIZE 52 -#define GBL_IDLE_TEXT_INIT { \ - /* SAM */ \ - 0x3c, 0x4a, /* 0x3c4a: MOV 0x4, AR2 */ \ - 0xf4, 0x41, 0xfc, 0xff, /* 0xf441fcff: AND 0xfcff, *AR2 */ \ - /* disable WDT */ \ - 0x76, 0x34, 0x04, 0xb8, /* 0x763404b8: MOV 0x3404, AR3 */ \ - 0xfb, 0x61, 0x00, 0xf5, /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \ - 0x9a, /* 0x9a: PORT */ \ - 0xfb, 0x61, 0x00, 0xa0, /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \ - 0x9a, /* 0x9a: PORT */ \ - /* *IER0 = 0, *IER1 = 0 */ \ - 0x3c, 0x0b, /* 0x3c0b: MOV 0x0, AR3 */ \ - 0xe6, 0x61, 0x00, /* 0xe66100: MOV 0, *AR3 */ \ - 0x76, 0x00, 0x45, 0xb8, /* 0x76004508: MOV 0x45, AR3 */ \ - 0xe6, 0x61, 0x00, /* 0xe66100: MOV 0, *AR3 */ \ - /* *ICR = 0xffff */ \ - 0x3c, 0x1b, /* 0x3c1b: MOV 0x1, AR3 */ \ - 0xfb, 0x61, 0xff, 0xff, /* 0xfb61ffff: MOV 0xffff, *AR3 */ \ - 0x9a, /* 0x9a: PORT */ \ - /* HOM */ \ - 0xf5, 0x41, 0x03, 0x00, /* 0xf5410300: OR 0x0300, *AR2 */ \ - /* idle and loop forever */ \ - 0x7a, 0x00, 0x00, 0x0c, /* 0x7a00000c: IDLE */ \ - 0x4a, 0x7a, /* 0x4a7a: B -6 (infinite loop) */ \ - 0x20, 0x20, 0x20, /* 0x20: NOP */ \ -} - -/* program size must be multiple of 2 */ -#define CPU_IDLE_TEXT_SIZE 48 -#define CPU_IDLE_TEXT_INIT(icrh, icrl) { \ - /* SAM */ \ - 0x3c, 0x4b, /* 0x3c4b: MOV 0x4, AR3 */ \ - 0xf4, 0x61, 0xfc, 0xff, /* 0xf461fcff: AND 0xfcff, *AR3 */ \ - /* disable WDT */ \ - 0x76, 0x34, 0x04, 0xb8, /* 0x763404b8: MOV 0x3404, AR3 */ \ - 0xfb, 0x61, 0x00, 0xf5, /* 0xfb6100f5: MOV 0x00f5, *AR3 */ \ - 0x9a, /* 0x9a: PORT */ \ - 0xfb, 0x61, 0x00, 0xa0, /* 0xfb6100a0: MOV 0x00a0, *AR3 */ \ - 0x9a, /* 0x9a: PORT */ \ - /* *IER0 = 0, *IER1 = 0 */ \ - 0x3c, 0x0b, /* 0x3c0b: MOV 0x0, AR3 */ \ - 0xe6, 0x61, 0x00, /* 0xe66100: MOV 0, *AR3 */ \ - 0x76, 0x00, 0x45, 0xb8, /* 0x76004508: MOV 0x45, AR3 */ \ - 0xe6, 0x61, 0x00, /* 0xe66100: MOV 0, *AR3 */ \ - /* set ICR = icr */ \ - 0x3c, 0x1b, /* 0x3c1b: MOV AR3 0x1 */ \ - 0xfb, 0x61, (icrh), (icrl), /* 0xfb61****: MOV *AR3, icr */ \ - 0x9a, /* 0x9a: PORT */ \ - /* idle and loop forever */ \ - 0x7a, 0x00, 0x00, 0x0c, /* 0x7a00000c: IDLE */ \ - 0x4a, 0x7a, /* 0x4a7a: B -6 (infinite loop) */ \ - 0x20, 0x20, 0x20 /* 0x20: nop */ \ -} - -/* - * idle_boot base: - * Initialized with DSP_BOOT_ADR_MPUI (=0x010000). - * This value is used before DSP Gateway driver is initialized. - * DSP Gateway driver will overwrite this value with other value, - * to avoid confliction with the user program. - */ -static dsp_long_t idle_boot_base = DSP_BOOT_ADR_MPUI; - -static void dsp_gbl_idle(void) -{ - unsigned char idle_text[GBL_IDLE_TEXT_SIZE] = GBL_IDLE_TEXT_INIT; - - __dsp_reset(); - clk_enable(api_ck_handle); - -#if 0 - dsp_boot_config(DSP_BOOT_CONFIG_IDLE); -#endif - simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base), - GBL_IDLE_TEXT_SIZE); - if (idle_boot_base == DSP_BOOT_ADR_MPUI) - dsp_boot_config(DSP_BOOT_CONFIG_MPUI); - else - dsp_set_rstvect(idle_boot_base); - - __dsp_run(); - udelay(100); /* to make things stable */ - clk_disable(api_ck_handle); -} - -static void dsp_cpu_idle(void) -{ - u16 icr_tmp; - unsigned char icrh, icrl; - - __dsp_reset(); - clk_enable(api_ck_handle); - - /* - * icr settings: - * DMA should not sleep for DARAM/SARAM access - * DPLL should not sleep while any other domain is active - */ - icr_tmp = cpustat.icrmask & ~(DSPREG_ICR_DMA | DSPREG_ICR_DPLL); - icrh = icr_tmp >> 8; - icrl = icr_tmp & 0xff; - { - unsigned char idle_text[CPU_IDLE_TEXT_SIZE] = CPU_IDLE_TEXT_INIT(icrh, icrl); - simple_load_code(idle_text, dspbyte_to_virt(idle_boot_base), - CPU_IDLE_TEXT_SIZE); - } - if (idle_boot_base == DSP_BOOT_ADR_MPUI) - dsp_boot_config(DSP_BOOT_CONFIG_MPUI); - else - dsp_set_rstvect(idle_boot_base); - __dsp_run(); - udelay(100); /* to make things stable */ - clk_disable(api_ck_handle); -} - -void dsp_set_idle_boot_base(dsp_long_t adr, size_t size) -{ - if (adr == idle_boot_base) - return; - idle_boot_base = adr; - if ((size < GBL_IDLE_TEXT_SIZE) || - (size < CPU_IDLE_TEXT_SIZE)) { - printk(KERN_ERR - "omapdsp: size for idle program is not enough!\n"); - BUG(); - } - - /* restart idle program with new base address */ - if (cpustat.stat == CPUSTAT_GBL_IDLE) - dsp_gbl_idle(); - if (cpustat.stat == CPUSTAT_CPU_IDLE) - dsp_cpu_idle(); -} - -void dsp_reset_idle_boot_base(void) -{ - idle_boot_base = DSP_BOOT_ADR_MPUI; -} -#else -void dsp_reset_idle_boot_base(void) { } -#endif /* CONFIG_ARCH_OMAP1 */ - -static int init_done; - -static int omap_dsp_init(void) -{ - mutex_init(&cpustat.lock); - - dspmem_size = 0; -#ifdef CONFIG_ARCH_OMAP15XX - if (cpu_is_omap15xx()) { - dspmem_base = OMAP1510_DSP_BASE; - dspmem_size = OMAP1510_DSP_SIZE; - daram_base = OMAP1510_DARAM_BASE; - daram_size = OMAP1510_DARAM_SIZE; - saram_base = OMAP1510_SARAM_BASE; - saram_size = OMAP1510_SARAM_SIZE; - } -#endif -#ifdef CONFIG_ARCH_OMAP16XX - if (cpu_is_omap16xx()) { - dspmem_base = OMAP16XX_DSP_BASE; - dspmem_size = OMAP16XX_DSP_SIZE; - daram_base = OMAP16XX_DARAM_BASE; - daram_size = OMAP16XX_DARAM_SIZE; - saram_base = OMAP16XX_SARAM_BASE; - saram_size = OMAP16XX_SARAM_SIZE; - } -#endif -#ifdef CONFIG_ARCH_OMAP24XX - if (cpu_is_omap24xx()) { - dspmem_base = DSP_MEM_24XX_VIRT; - dspmem_size = DSP_MEM_24XX_SIZE; - daram_base = OMAP24XX_DARAM_BASE; - daram_size = OMAP24XX_DARAM_SIZE; - saram_base = OMAP24XX_SARAM_BASE; - saram_size = OMAP24XX_SARAM_SIZE; - } -#endif -#ifdef CONFIG_ARCH_OMAP34XX - /* To be Revisited for 3430 */ - if (cpu_is_omap34xx()) { - return -ENODEV; - } -#endif - if (dspmem_size == 0) { - printk(KERN_ERR "omapdsp: unsupported omap architecture.\n"); - return -ENODEV; - } - -#if defined(CONFIG_ARCH_OMAP1) - dsp_ck_handle = clk_get(NULL, "dsp_ck"); - if (IS_ERR(dsp_ck_handle)) { - printk(KERN_ERR "omapdsp: could not acquire dsp_ck handle.\n"); - return PTR_ERR(dsp_ck_handle); - } - - api_ck_handle = clk_get(NULL, "api_ck"); - if (IS_ERR(api_ck_handle)) { - printk(KERN_ERR "omapdsp: could not acquire api_ck handle.\n"); - if (dsp_ck_handle != NULL) - clk_put(dsp_ck_handle); - return PTR_ERR(api_ck_handle); - } - - /* This is needed for McBSP init, released in late_initcall */ - clk_enable(api_ck_handle); - - __dsp_enable(); - mpui_byteswap_off(); - mpui_wordswap_on(); - tc_wordswap(); -#elif defined(CONFIG_ARCH_OMAP2) - dsp_fck_handle = clk_get(NULL, "dsp_fck"); - if (IS_ERR(dsp_fck_handle)) { - printk(KERN_ERR "omapdsp: could not acquire dsp_fck handle.\n"); - return PTR_ERR(dsp_fck_handle); - } - -# if defined(CONFIG_ARCH_OMAP2420) - dsp_ick_handle = clk_get(NULL, "dsp_ick"); -# elif defined(CONFIG_ARCH_OMAP2430) - /* - * 2430 has no separate switch for DSP ICLK, but this at least - * involves the minimal change to the rest of the code. - */ - dsp_ick_handle = clk_get(NULL, "iva2_1_ick"); -# endif - if (IS_ERR(dsp_ick_handle)) { - printk(KERN_ERR "omapdsp: could not acquire dsp_ick handle.\n"); - if (dsp_fck_handle != NULL) - clk_put(dsp_fck_handle); - return PTR_ERR(dsp_ick_handle); - } -#endif - - init_done = 1; - pr_info("omap_dsp_init() done\n"); - return 0; -} - -#if defined(CONFIG_ARCH_OMAP1) -static int __dsp_late_init(void) -{ - clk_disable(api_ck_handle); - return 0; -} -late_initcall(__dsp_late_init); -#endif - -static void dsp_cpustat_update(void) -{ - if (!init_done) - omap_dsp_init(); - - if (cpustat.req == CPUSTAT_RUN) { - if (cpustat.stat < CPUSTAT_RUN) { -#if defined(CONFIG_ARCH_OMAP1) - __dsp_reset(); - clk_enable(api_ck_handle); - udelay(10); - __dsp_run(); -#elif defined(CONFIG_ARCH_OMAP2) - __dsp_core_disable(); - udelay(10); - __dsp_core_enable(); -#endif - cpustat.stat = CPUSTAT_RUN; - } - return; - } - - /* cpustat.req < CPUSTAT_RUN */ - - if (cpustat.stat == CPUSTAT_RUN) { -#ifdef CONFIG_ARCH_OMAP1 - clk_disable(api_ck_handle); -#endif - } - -#ifdef CONFIG_ARCH_OMAP1 - /* - * (1) when ARM wants DARAM access, MPUI should be SAM and - * DSP needs to be on. - * (2) if any bits of icr is masked, we can not enter global idle. - */ - if ((cpustat.req == CPUSTAT_CPU_IDLE) || - (cpustat.usecount.mem > 0) || - (cpustat.usecount.mem_delayed > 0) || - ((cpustat.usecount.mpui > 0) && (cpustat.icrmask != 0xffff))) { - if (cpustat.stat != CPUSTAT_CPU_IDLE) { - dsp_cpu_idle(); - cpustat.stat = CPUSTAT_CPU_IDLE; - } - return; - } - - /* - * when ARM only needs MPUI access, MPUI can be HOM and - * DSP can be idling. - */ - if ((cpustat.req == CPUSTAT_GBL_IDLE) || - (cpustat.usecount.mpui > 0)) { - if (cpustat.stat != CPUSTAT_GBL_IDLE) { - dsp_gbl_idle(); - cpustat.stat = CPUSTAT_GBL_IDLE; - } - return; - } -#endif /* CONFIG_ARCH_OMAP1 */ - - /* - * no user, no request - */ - if (cpustat.stat != CPUSTAT_RESET) { -#if defined(CONFIG_ARCH_OMAP1) - __dsp_reset(); -#elif defined(CONFIG_ARCH_OMAP2) - __dsp_core_disable(); -#endif - cpustat.stat = CPUSTAT_RESET; - } -} - -void dsp_cpustat_request(enum cpustat_e req) -{ - mutex_lock(&cpustat.lock); - cpustat.req = req; - dsp_cpustat_update(); - mutex_unlock(&cpustat.lock); -} - -enum cpustat_e dsp_cpustat_get_stat(void) -{ - return cpustat.stat; -} - -u16 dsp_cpustat_get_icrmask(void) -{ - return cpustat.icrmask; -} - -void dsp_cpustat_set_icrmask(u16 mask) -{ - mutex_lock(&cpustat.lock); - cpustat.icrmask = mask; - dsp_cpustat_update(); - mutex_unlock(&cpustat.lock); -} - -#ifdef CONFIG_ARCH_OMAP1 -void omap_dsp_request_mpui(void) -{ - mutex_lock(&cpustat.lock); - if (cpustat.usecount.mpui++ == 0) - dsp_cpustat_update(); - mutex_unlock(&cpustat.lock); -} - -void omap_dsp_release_mpui(void) -{ - mutex_lock(&cpustat.lock); - if (cpustat.usecount.mpui-- == 0) { - printk(KERN_ERR - "omapdsp: unbalanced mpui request/release detected.\n" - " cpustat.usecount.mpui is going to be " - "less than zero! ... fixed to be zero.\n"); - cpustat.usecount.mpui = 0; - } - if (cpustat.usecount.mpui == 0) - dsp_cpustat_update(); - mutex_unlock(&cpustat.lock); -} - -#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK) -int omap_dsp_request_mem(void) -{ - int ret = 0; - - mutex_lock(&cpustat.lock); - if ((cpustat.usecount.mem++ == 0) && - (cpustat.usecount.mem_delayed == 0)) { - if (cpustat.mem_req_cb) { - if ((ret = cpustat.mem_req_cb()) < 0) { - cpustat.usecount.mem--; - goto out; - } - } - dsp_cpustat_update(); - } -out: - mutex_unlock(&cpustat.lock); - - return ret; -} - -/* - * release_mem will be delayed. - */ -static void do_release_mem(struct work_struct *dummy) -{ - mutex_lock(&cpustat.lock); - cpustat.usecount.mem_delayed = 0; - if (cpustat.usecount.mem == 0) { - dsp_cpustat_update(); - if (cpustat.mem_rel_cb) - cpustat.mem_rel_cb(); - } - mutex_unlock(&cpustat.lock); -} - -static DECLARE_DELAYED_WORK(mem_rel_work, do_release_mem); - -int omap_dsp_release_mem(void) -{ - mutex_lock(&cpustat.lock); - - /* cancel previous release work */ - cancel_delayed_work(&mem_rel_work); - cpustat.usecount.mem_delayed = 0; - - if (cpustat.usecount.mem-- == 0) { - printk(KERN_ERR - "omapdsp: unbalanced memory request/release detected.\n" - " cpustat.usecount.mem is going to be " - "less than zero! ... fixed to be zero.\n"); - cpustat.usecount.mem = 0; - } - if (cpustat.usecount.mem == 0) { - cpustat.usecount.mem_delayed = 1; - schedule_delayed_work(&mem_rel_work, HZ); - } - - mutex_unlock(&cpustat.lock); - - return 0; -} -#endif - -void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)) -{ - mutex_lock(&cpustat.lock); - - cpustat.mem_req_cb = req_cb; - cpustat.mem_rel_cb = rel_cb; - - /* - * This function must be called while mem is enabled! - */ - BUG_ON(cpustat.usecount.mem == 0); - - mutex_unlock(&cpustat.lock); -} - -void dsp_unregister_mem_cb(void) -{ - mutex_lock(&cpustat.lock); - cpustat.mem_req_cb = NULL; - cpustat.mem_rel_cb = NULL; - mutex_unlock(&cpustat.lock); -} -#else -void dsp_register_mem_cb(int (*req_cb)(void), void (*rel_cb)(void)) { } -void dsp_unregister_mem_cb(void) { } -#endif /* CONFIG_ARCH_OMAP1 */ - -arch_initcall(omap_dsp_init); - -#ifdef CONFIG_ARCH_OMAP1 -EXPORT_SYMBOL(omap_dsp_request_mpui); -EXPORT_SYMBOL(omap_dsp_release_mpui); -#if defined(CONFIG_ARCH_OMAP1) && defined(CONFIG_OMAP_MMU_FWK) -EXPORT_SYMBOL(omap_dsp_request_mem); -EXPORT_SYMBOL(omap_dsp_release_mem); -#endif -#endif /* CONFIG_ARCH_OMAP1 */ - -#ifdef CONFIG_OMAP_DSP_MODULE -#if defined(CONFIG_ARCH_OMAP1) -EXPORT_SYMBOL(dsp_ck_handle); -EXPORT_SYMBOL(api_ck_handle); -#elif defined(CONFIG_ARCH_OMAP2) -EXPORT_SYMBOL(dsp_fck_handle); -EXPORT_SYMBOL(dsp_ick_handle); -#endif -EXPORT_SYMBOL(omap_dsp); -EXPORT_SYMBOL(dspmem_base); -EXPORT_SYMBOL(dspmem_size); -EXPORT_SYMBOL(daram_base); -EXPORT_SYMBOL(daram_size); -EXPORT_SYMBOL(saram_base); -EXPORT_SYMBOL(saram_size); -EXPORT_SYMBOL(dsp_set_rstvect); -EXPORT_SYMBOL(dsp_get_rstvect); -#ifdef CONFIG_ARCH_OMAP1 -EXPORT_SYMBOL(dsp_set_idle_boot_base); -EXPORT_SYMBOL(dsp_reset_idle_boot_base); -#endif /* CONFIG_ARCH_OMAP1 */ -EXPORT_SYMBOL(dsp_cpustat_request); -EXPORT_SYMBOL(dsp_cpustat_get_stat); -EXPORT_SYMBOL(dsp_cpustat_get_icrmask); -EXPORT_SYMBOL(dsp_cpustat_set_icrmask); -EXPORT_SYMBOL(dsp_register_mem_cb); -EXPORT_SYMBOL(dsp_unregister_mem_cb); - -EXPORT_SYMBOL(__cpu_flush_kern_tlb_range); -EXPORT_SYMBOL(cpu_architecture); -EXPORT_SYMBOL(pmd_clear_bad); -#endif diff --git a/drivers/dsp/dspgateway/dsp_core.c b/drivers/dsp/dspgateway/dsp_core.c deleted file mode 100644 index f2368fb32d8..00000000000 --- a/drivers/dsp/dspgateway/dsp_core.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" -#include "ipbuf.h" - -MODULE_AUTHOR("Toshihiro Kobayashi "); -MODULE_DESCRIPTION("OMAP DSP driver module"); -MODULE_LICENSE("GPL"); - -static struct sync_seq *mbseq; -static u16 mbseq_expect_tmp; -static u16 *mbseq_expect = &mbseq_expect_tmp; - -extern int dsp_mem_late_init(void); - -/* - * mailbox commands - */ -extern void mbox_wdsnd(struct mbcmd *mb); -extern void mbox_wdreq(struct mbcmd *mb); -extern void mbox_bksnd(struct mbcmd *mb); -extern void mbox_bkreq(struct mbcmd *mb); -extern void mbox_bkyld(struct mbcmd *mb); -extern void mbox_bksndp(struct mbcmd *mb); -extern void mbox_bkreqp(struct mbcmd *mb); -extern void mbox_tctl(struct mbcmd *mb); -extern void mbox_poll(struct mbcmd *mb); -#ifdef OLD_BINARY_SUPPORT -/* v3.3 obsolete */ -extern void mbox_wdt(struct mbcmd *mb); -#endif -extern void mbox_suspend(struct mbcmd *mb); -static void mbox_kfunc(struct mbcmd *mb); -extern void mbox_tcfg(struct mbcmd *mb); -extern void mbox_tadd(struct mbcmd *mb); -extern void mbox_tdel(struct mbcmd *mb); -extern void mbox_dspcfg(struct mbcmd *mb); -extern void mbox_regrw(struct mbcmd *mb); -extern void mbox_getvar(struct mbcmd *mb); -extern void mbox_err(struct mbcmd *mb); -extern void mbox_dbg(struct mbcmd *mb); - -static const struct cmdinfo - cif_wdsnd = { "WDSND", CMD_L_TYPE_TID, mbox_wdsnd }, - cif_wdreq = { "WDREQ", CMD_L_TYPE_TID, mbox_wdreq }, - cif_bksnd = { "BKSND", CMD_L_TYPE_TID, mbox_bksnd }, - cif_bkreq = { "BKREQ", CMD_L_TYPE_TID, mbox_bkreq }, - cif_bkyld = { "BKYLD", CMD_L_TYPE_NULL, mbox_bkyld }, - cif_bksndp = { "BKSNDP", CMD_L_TYPE_TID, mbox_bksndp }, - cif_bkreqp = { "BKREQP", CMD_L_TYPE_TID, mbox_bkreqp }, - cif_tctl = { "TCTL", CMD_L_TYPE_TID, mbox_tctl }, - cif_poll = { "POLL", CMD_L_TYPE_NULL, mbox_poll }, -#ifdef OLD_BINARY_SUPPORT - /* v3.3 obsolete */ - cif_wdt = { "WDT", CMD_L_TYPE_NULL, mbox_wdt }, -#endif - cif_runlevel = { "RUNLEVEL", CMD_L_TYPE_SUBCMD, NULL }, - cif_pm = { "PM", CMD_L_TYPE_SUBCMD, NULL }, - cif_suspend = { "SUSPEND", CMD_L_TYPE_NULL, mbox_suspend }, - cif_kfunc = { "KFUNC", CMD_L_TYPE_SUBCMD, mbox_kfunc }, - cif_tcfg = { "TCFG", CMD_L_TYPE_TID, mbox_tcfg }, - cif_tadd = { "TADD", CMD_L_TYPE_TID, mbox_tadd }, - cif_tdel = { "TDEL", CMD_L_TYPE_TID, mbox_tdel }, - cif_tstop = { "TSTOP", CMD_L_TYPE_TID, NULL }, - cif_dspcfg = { "DSPCFG", CMD_L_TYPE_SUBCMD, mbox_dspcfg }, - cif_regrw = { "REGRW", CMD_L_TYPE_SUBCMD, mbox_regrw }, - cif_getvar = { "GETVAR", CMD_L_TYPE_SUBCMD, mbox_getvar }, - cif_setvar = { "SETVAR", CMD_L_TYPE_SUBCMD, NULL }, - cif_err = { "ERR", CMD_L_TYPE_SUBCMD, mbox_err }, - cif_dbg = { "DBG", CMD_L_TYPE_NULL, mbox_dbg }; - -#define MBOX_CMD_MAX 0x80 -const struct cmdinfo *cmdinfo[MBOX_CMD_MAX] = { - [MBOX_CMD_DSP_WDSND] = &cif_wdsnd, - [MBOX_CMD_DSP_WDREQ] = &cif_wdreq, - [MBOX_CMD_DSP_BKSND] = &cif_bksnd, - [MBOX_CMD_DSP_BKREQ] = &cif_bkreq, - [MBOX_CMD_DSP_BKYLD] = &cif_bkyld, - [MBOX_CMD_DSP_BKSNDP] = &cif_bksndp, - [MBOX_CMD_DSP_BKREQP] = &cif_bkreqp, - [MBOX_CMD_DSP_TCTL] = &cif_tctl, - [MBOX_CMD_DSP_POLL] = &cif_poll, -#ifdef OLD_BINARY_SUPPORT - [MBOX_CMD_DSP_WDT] = &cif_wdt, /* v3.3 obsolete */ -#endif - [MBOX_CMD_DSP_RUNLEVEL] = &cif_runlevel, - [MBOX_CMD_DSP_PM] = &cif_pm, - [MBOX_CMD_DSP_SUSPEND] = &cif_suspend, - [MBOX_CMD_DSP_KFUNC] = &cif_kfunc, - [MBOX_CMD_DSP_TCFG] = &cif_tcfg, - [MBOX_CMD_DSP_TADD] = &cif_tadd, - [MBOX_CMD_DSP_TDEL] = &cif_tdel, - [MBOX_CMD_DSP_TSTOP] = &cif_tstop, - [MBOX_CMD_DSP_DSPCFG] = &cif_dspcfg, - [MBOX_CMD_DSP_REGRW] = &cif_regrw, - [MBOX_CMD_DSP_GETVAR] = &cif_getvar, - [MBOX_CMD_DSP_SETVAR] = &cif_setvar, - [MBOX_CMD_DSP_ERR] = &cif_err, - [MBOX_CMD_DSP_DBG] = &cif_dbg, -}; - -#define list_for_each_entry_safe_natural(p,n,h,m) \ - list_for_each_entry_safe(p,n,h,m) -#define __BUILD_KFUNC(fn, dir) \ -static int __dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage)\ -{ \ - struct dsp_kfunc_device *p, *tmp; \ - int ret, fail = 0; \ - \ - list_for_each_entry_safe_##dir(p, tmp, dsp->kdev_list, entry) { \ - if (type && (p->type != type)) \ - continue; \ - if (p->fn == NULL) \ - continue; \ - ret = p->fn(p, stage); \ - if (ret) { \ - printk(KERN_ERR "%s %s failed\n", #fn, p->name); \ - fail++; \ - } \ - } \ - return fail; \ -} -#define BUILD_KFUNC(fn, dir) \ -__BUILD_KFUNC(fn, dir) \ -static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp) \ -{ \ - return __dsp_kfunc_##fn##_devices(dsp, 0, 0); \ -} -#define BUILD_KFUNC_CTL(fn, dir) \ -__BUILD_KFUNC(fn, dir) \ -static inline int dsp_kfunc_##fn##_devices(struct omap_dsp *dsp, int type, int stage) \ -{ \ - return __dsp_kfunc_##fn##_devices(dsp, type, stage); \ -} - -BUILD_KFUNC(probe, natural) -BUILD_KFUNC(remove, reverse) -BUILD_KFUNC_CTL(enable, natural) -BUILD_KFUNC_CTL(disable, reverse) - -int sync_with_dsp(u16 *adr, u16 val, int try_cnt) -{ - int try; - - if (*(volatile u16 *)adr == val) - return 0; - - for (try = 0; try < try_cnt; try++) { - udelay(1); - if (*(volatile u16 *)adr == val) { - /* success! */ - pr_info("omapdsp: sync_with_dsp(): try = %d\n", try); - return 0; - } - } - - /* fail! */ - return -1; -} - -static int mbcmd_sender_prepare(void *data) -{ - struct mb_exarg *arg = data; - int i, ret = 0; - /* - * even if ipbuf_sys_ad is in DSP internal memory, - * dsp_mem_enable() never cause to call PM mailbox command - * because in that case DSP memory should be always enabled. - * (see ipbuf_sys_hold_mem_active in ipbuf.c) - * - * Therefore, we can call this function here safely. - */ - dsp_mem_enable(ipbuf_sys_ad); - if (sync_with_dsp(&ipbuf_sys_ad->s, TID_FREE, 10) < 0) { - printk(KERN_ERR "omapdsp: ipbuf_sys_ad is busy.\n"); - ret = -EBUSY; - goto out; - } - - for (i = 0; i < arg->argc; i++) { - ipbuf_sys_ad->d[i] = arg->argv[i]; - } - ipbuf_sys_ad->s = arg->tid; - out: - dsp_mem_disable(ipbuf_sys_ad); - return ret; -} - -/* - * __dsp_mbcmd_send_exarg(): mailbox dispatcher - */ -int __dsp_mbcmd_send_exarg(struct mbcmd *mb, struct mb_exarg *arg, - int recovery_flag) -{ - int ret = 0; - - if (unlikely(omap_dsp->enabled == 0)) { - ret = dsp_kfunc_enable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_COMMON, 0); - if (ret == 0) - omap_dsp->enabled = 1; - } - - /* - * while MMU fault is set, - * only recovery command can be executed - */ - if (dsp_err_isset(ERRCODE_MMU) && !recovery_flag) { - printk(KERN_ERR - "mbox: mmu interrupt is set. %s is aborting.\n", - cmd_name(*mb)); - goto out; - } - - ret = omap_mbox_msg_send(omap_dsp->mbox, - *(mbox_msg_t *)mb, (void*)arg); - if (ret) - goto out; - - if (mbseq) - mbseq->ad_arm++; - - mblog_add(mb, DIR_A2D); - out: - return ret; -} - -int dsp_mbcmd_send_and_wait_exarg(struct mbcmd *mb, struct mb_exarg *arg, - wait_queue_head_t *q) -{ - int ret; - - DEFINE_WAIT(wait); - prepare_to_wait(q, &wait, TASK_INTERRUPTIBLE); - ret = dsp_mbcmd_send_exarg(mb, arg); - if (ret < 0) - goto out; - schedule_timeout(DSP_TIMEOUT); - out: - finish_wait(q, &wait); - return ret; -} - -/* - * mbcmd receiver - */ -static int mbcmd_receiver(void* msg) -{ - struct mbcmd *mb = (struct mbcmd *)&msg; - - if (cmdinfo[mb->cmd_h] == NULL) { - printk(KERN_ERR - "invalid message (%08x) for mbcmd_receiver().\n", - (mbox_msg_t)msg); - return -1; - } - - (*mbseq_expect)++; - - mblog_add(mb, DIR_D2A); - - /* call handler for the command */ - if (cmdinfo[mb->cmd_h]->handler) - cmdinfo[mb->cmd_h]->handler(mb); - else - printk(KERN_ERR "mbox: %s is not allowed from DSP.\n", - cmd_name(*mb)); - return 0; -} - -static int mbsync_hold_mem_active; - -void dsp_mbox_start(void) -{ - omap_mbox_init_seq(omap_dsp->mbox); - mbseq_expect_tmp = 0; -} - -void dsp_mbox_stop(void) -{ - mbseq = NULL; - mbseq_expect = &mbseq_expect_tmp; -} - -int dsp_mbox_config(void *p) -{ - unsigned long flags; - - if (dsp_address_validate(p, sizeof(struct sync_seq), "mbseq") < 0) - return -1; - if (dsp_mem_type(p, sizeof(struct sync_seq)) != MEM_TYPE_EXTERN) { - printk(KERN_WARNING - "omapdsp: mbseq is placed in DSP internal memory.\n" - " It will prevent DSP from idling.\n"); - mbsync_hold_mem_active = 1; - /* - * dsp_mem_enable() never fails because - * it has been already enabled in dspcfg process and - * this will just increment the usecount. - */ - dsp_mem_enable((void *)daram_base); - } - - local_irq_save(flags); - mbseq = p; - mbseq->da_arm = mbseq_expect_tmp; - mbseq_expect = &mbseq->da_arm; - local_irq_restore(flags); - - return 0; -} - -static int __init dsp_mbox_init(void) -{ - omap_dsp->mbox = omap_mbox_get("dsp"); - if (IS_ERR(omap_dsp->mbox)) { - printk(KERN_ERR "failed to get mailbox handler for DSP.\n"); - return -ENODEV; - } - - omap_dsp->mbox->rxq->callback = mbcmd_receiver; - omap_dsp->mbox->txq->callback = mbcmd_sender_prepare; - - return 0; -} - -static void dsp_mbox_exit(void) -{ - omap_dsp->mbox->txq->callback = NULL; - omap_dsp->mbox->rxq->callback = NULL; - - omap_mbox_put(omap_dsp->mbox); - - if (mbsync_hold_mem_active) { - dsp_mem_disable((void *)daram_base); - mbsync_hold_mem_active = 0; - } -} - -/* - * kernel function dispatcher - */ -extern void mbox_fbctl_upd(void); -extern void mbox_fbctl_disable(struct mbcmd *mb); - -static void mbox_kfunc_fbctl(struct mbcmd *mb) -{ - switch (mb->data) { - case FBCTL_UPD: - mbox_fbctl_upd(); - break; - case FBCTL_DISABLE: - mbox_fbctl_disable(mb); - break; - default: - printk(KERN_ERR - "mbox: Unknown FBCTL from DSP: 0x%04x\n", mb->data); - } -} - -/* - * dspgw: KFUNC message handler - */ -static void mbox_kfunc_power(unsigned short data) -{ - int ret = -1; - - switch (data) { - case DVFS_START: /* ACK from DSP */ - /* TBD */ - break; - case AUDIO_PWR_UP: - ret = dsp_kfunc_enable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_AUDIO, 0); - if (ret == 0) - ret++; - break; - case AUDIO_PWR_DOWN: /* == AUDIO_PWR_DOWN1 */ - ret = dsp_kfunc_disable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_AUDIO, 1); - break; - case AUDIO_PWR_DOWN2: - ret = dsp_kfunc_disable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_AUDIO, 2); - break; - case DSP_PWR_DOWN: - ret = dsp_kfunc_disable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_COMMON, 0); - if (ret == 0) - omap_dsp->enabled = 0; - break; - default: - printk(KERN_ERR - "mailbox: Unknown PWR from DSP: 0x%04x\n", data); - break; - } - - if (unlikely(ret < 0)) { - printk(KERN_ERR "mailbox: PWR(0x%04x) failed\n", data); - return; - } - - if (likely(ret == 0)) - return; - - mbcompose_send(KFUNC, KFUNC_POWER, data); -} - -static void mbox_kfunc(struct mbcmd *mb) -{ - switch (mb->cmd_l) { - case KFUNC_FBCTL: - mbox_kfunc_fbctl(mb); - break; - case KFUNC_POWER: - mbox_kfunc_power(mb->data); - break; - default: - printk(KERN_ERR - "mbox: Unknown KFUNC from DSP: 0x%02x\n", mb->cmd_l); - } -} - -#if defined(CONFIG_ARCH_OMAP1) -static inline void dsp_clk_enable(void) {} -static inline void dsp_clk_disable(void) {} -#elif defined(CONFIG_ARCH_OMAP2) -static inline void dsp_clk_enable(void) -{ - clk_enable(dsp_fck_handle); - clk_enable(dsp_ick_handle); - __dsp_per_enable(); -} -static inline void dsp_clk_disable(void) -{ - __dsp_per_disable(); - clk_disable(dsp_ick_handle); - clk_disable(dsp_fck_handle); -} -#endif - -int dsp_late_init(void) -{ - int ret; - - dsp_clk_enable(); - ret = dsp_mem_late_init(); - if (ret) - return ret; - ret = dsp_mbox_init(); - if (ret) - goto fail_mbox; -#ifdef CONFIG_ARCH_OMAP1 - dsp_set_idle_boot_base(IDLEPG_BASE, IDLEPG_SIZE); -#endif - ret = dsp_kfunc_enable_devices(omap_dsp, - DSP_KFUNC_DEV_TYPE_COMMON, 0); - if (ret) - goto fail_kfunc; - omap_dsp->enabled = 1; - - return 0; - - fail_kfunc: - dsp_mbox_exit(); - fail_mbox: - dsp_clk_disable(); - - return ret; -} - -extern int dsp_ctl_core_init(void); -extern void dsp_ctl_core_exit(void); -extern int dsp_ctl_init(void); -extern void dsp_ctl_exit(void); -extern int dsp_mem_init(void); -extern void dsp_mem_exit(void); -extern void mblog_init(void); -extern void mblog_exit(void); -extern int dsp_taskmod_init(void); -extern void dsp_taskmod_exit(void); - -/* - * driver functions - */ -static int __init dsp_drv_probe(struct platform_device *pdev) -{ - int ret; - struct omap_dsp *info; - struct dsp_platform_data *pdata = pdev->dev.platform_data; - - dev_info(&pdev->dev, "OMAP DSP driver initialization\n"); - - info = kzalloc(sizeof(struct omap_dsp), GFP_KERNEL); - if (unlikely(info == NULL)) { - dev_dbg(&pdev->dev, "no memory for info\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, info); - omap_dsp = info; - - mutex_init(&info->lock); - info->dev = &pdev->dev; - info->kdev_list = &pdata->kdev_list; - - ret = dsp_kfunc_probe_devices(info); - if (ret) { - ret = -ENXIO; - goto fail_kfunc; - } - - ret = dsp_ctl_core_init(); - if (ret) - goto fail_ctl_core; - ret = dsp_mem_init(); - if (ret) - goto fail_mem; - ret = dsp_ctl_init(); - if (unlikely(ret)) - goto fail_ctl_init; - mblog_init(); - ret = dsp_taskmod_init(); - if (ret) - goto fail_taskmod; - - return 0; - - fail_taskmod: - mblog_exit(); - dsp_ctl_exit(); - fail_ctl_init: - dsp_mem_exit(); - fail_mem: - dsp_ctl_core_exit(); - fail_ctl_core: - dsp_kfunc_remove_devices(info); - fail_kfunc: - kfree(info); - - return ret; -} - -static int dsp_drv_remove(struct platform_device *pdev) -{ - struct omap_dsp *info = platform_get_drvdata(pdev); - - dsp_cpustat_request(CPUSTAT_RESET); - - dsp_cfgstat_request(CFGSTAT_CLEAN); - dsp_mbox_exit(); - dsp_taskmod_exit(); - mblog_exit(); - dsp_ctl_exit(); - dsp_mem_exit(); - - dsp_ctl_core_exit(); - -#ifdef CONFIG_ARCH_OMAP2 - __dsp_per_disable(); - clk_disable(dsp_ick_handle); - clk_disable(dsp_fck_handle); -#endif - dsp_kfunc_remove_devices(info); - kfree(info); - - return 0; -} - -#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP1) -static int dsp_drv_suspend(struct platform_device *pdev, pm_message_t state) -{ - dsp_cfgstat_request(CFGSTAT_SUSPEND); - - return 0; -} - -static int dsp_drv_resume(struct platform_device *pdev) -{ - dsp_cfgstat_request(CFGSTAT_RESUME); - - return 0; -} -#else -#define dsp_drv_suspend NULL -#define dsp_drv_resume NULL -#endif /* CONFIG_PM */ - -static struct platform_driver dsp_driver = { - .probe = dsp_drv_probe, - .remove = dsp_drv_remove, - .suspend = dsp_drv_suspend, - .resume = dsp_drv_resume, - .driver = { - .name = "dsp", - }, -}; - -static int __init omap_dsp_mod_init(void) -{ - return platform_driver_register(&dsp_driver); -} - -static void __exit omap_dsp_mod_exit(void) -{ - platform_driver_unregister(&dsp_driver); -} - -/* module dependency: need mailbox module that have mbox_dsp_info */ -extern struct omap_mbox mbox_dsp_info; -struct omap_mbox *mbox_dep = &mbox_dsp_info; - -module_init(omap_dsp_mod_init); -module_exit(omap_dsp_mod_exit); diff --git a/drivers/dsp/dspgateway/dsp_ctl.c b/drivers/dsp/dspgateway/dsp_ctl.c deleted file mode 100644 index 712c3cfad09..00000000000 --- a/drivers/dsp/dspgateway/dsp_ctl.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hardware_dsp.h" -#include "dsp_mbcmd.h" -#include "dsp.h" -#include "ipbuf.h" - -enum dsp_space_e { - SPACE_MEM, - SPACE_IO, -}; - -#ifdef CONFIG_OMAP_DSP_FBEXPORT -static enum fbstat_e { - FBSTAT_DISABLED = 0, - FBSTAT_ENABLED, - FBSTAT_MAX, -} fbstat = FBSTAT_ENABLED; -#endif - -static enum cfgstat_e cfgstat; -int mbox_revision; -static u8 n_stask; - -static ssize_t ifver_show(struct device *dev, struct device_attribute *attr, - char *buf); -static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr, - char *buf); -static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr, - char *buf); -static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); -static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr, - char *buf); - -#define __ATTR_RW(_name, _mode) { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _name##_show, \ - .store = _name##_store, \ -} - -static struct device_attribute dev_attr_ifver = __ATTR_RO(ifver); -static struct device_attribute dev_attr_cpustat = __ATTR_RO(cpustat); -static struct device_attribute dev_attr_icrmask = __ATTR_RW(icrmask, 0644); -static struct device_attribute dev_attr_loadinfo = __ATTR_RO(loadinfo); - -/* - * misc interactive mailbox command operations - */ -static struct misc_mb_wait_struct { - struct mutex lock; - wait_queue_head_t wait_q; - u8 cmd_h; - u8 cmd_l; - u16 *retvp; -} misc_mb_wait = { - .lock = __MUTEX_INITIALIZER(misc_mb_wait.lock), - .wait_q = __WAIT_QUEUE_HEAD_INITIALIZER(misc_mb_wait.wait_q), -}; - -static int __misc_mbcompose_send_and_wait(u8 cmd_h, u8 cmd_l, u16 data, - u16 *retvp) -{ - struct mbcmd mb = MBCMD_INIT(cmd_h, cmd_l, data); - int ret = 0; - - if (mutex_lock_interruptible(&misc_mb_wait.lock)) - return -EINTR; - - misc_mb_wait.cmd_h = mb.cmd_h; - misc_mb_wait.cmd_l = mb.cmd_l; - misc_mb_wait.retvp = retvp; - dsp_mbcmd_send_and_wait(&mb, &misc_mb_wait.wait_q); - - if (misc_mb_wait.cmd_h != 0) - ret = -EINVAL; - - mutex_unlock(&misc_mb_wait.lock); - return ret; -} - -#define misc_mbcompose_send_and_wait(cmd_h, cmd_l, data, retvp) \ - __misc_mbcompose_send_and_wait(MBOX_CMD_DSP_##cmd_h, (cmd_l), \ - (data), (retvp)); - -static int misc_mbcmd_response(struct mbcmd *mb, int argc, int match_cmd_l_flag) -{ - volatile u16 *buf; - int i; - - /* if match_cmd_l_v flag is set, cmd_l needs to be matched as well. */ - if (!waitqueue_active(&misc_mb_wait.wait_q) || - (misc_mb_wait.cmd_h != mb->cmd_h) || - (match_cmd_l_flag && (misc_mb_wait.cmd_l != mb->cmd_l))) { - const struct cmdinfo *ci = cmdinfo[mb->cmd_h]; - char cmdstr[32]; - - if (ci->cmd_l_type == CMD_L_TYPE_SUBCMD) - sprintf(cmdstr, "%s:%s", ci->name, subcmd_name(mb)); - else - strcpy(cmdstr, ci->name); - printk(KERN_WARNING - "mbox: unexpected command %s received!\n", cmdstr); - return -1; - } - - /* - * if argc == 1, receive data through mbox:data register. - * if argc > 1, receive through ipbuf_sys. - */ - if (argc == 1) - misc_mb_wait.retvp[0] = mb->data; - else if (argc > 1) { - if (dsp_mem_enable(ipbuf_sys_da) < 0) { - printk(KERN_ERR "mbox: %s - ipbuf_sys_da read failed!\n", - cmdinfo[mb->cmd_h]->name); - return -1; - } - if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) { - printk(KERN_ERR "mbox: %s - IPBUF sync failed!\n", - cmdinfo[mb->cmd_h]->name); - dsp_mem_disable(ipbuf_sys_da); - return -1; - } - /* need word access. do not use memcpy. */ - buf = ipbuf_sys_da->d; - for (i = 0; i < argc; i++) - misc_mb_wait.retvp[i] = buf[i]; - release_ipbuf_pvt(ipbuf_sys_da); - dsp_mem_disable(ipbuf_sys_da); - } - - misc_mb_wait.cmd_h = 0; - wake_up_interruptible(&misc_mb_wait.wait_q); - return 0; -} - -static int dsp_regread(enum dsp_space_e space, u16 adr, u16 *val) -{ - u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMR : REGRW_IOR; - int ret; - - ret = misc_mbcompose_send_and_wait(REGRW, cmd_l, adr, val); - if ((ret < 0) && (ret != -EINTR)) - printk(KERN_ERR "omapdsp: register read error!\n"); - - return ret; -} - -static int dsp_regwrite(enum dsp_space_e space, u16 adr, u16 val) -{ - u8 cmd_l = (space == SPACE_MEM) ? REGRW_MEMW : REGRW_IOW; - struct mb_exarg arg = { - .tid = TID_ANON, - .argc = 1, - .argv = &val, - }; - - mbcompose_send_exarg(REGRW, cmd_l, adr, &arg); - return 0; -} - -static int dsp_getvar(u8 varid, u16 *val) -{ - int ret; - - ret = misc_mbcompose_send_and_wait(GETVAR, varid, 0, val); - if ((ret < 0) && (ret != -EINTR)) - printk(KERN_ERR "omapdsp: variable read error!\n"); - - return ret; -} - -static int dsp_setvar(u8 varid, u16 val) -{ - mbcompose_send(SETVAR, varid, val); - return 0; -} - -/* - * dsp_cfg() return value - * = 0: OK - * = 1: failed, but state is clear. (DSPCFG command failed) - * < 0: failed. need cleanup. - */ -static int dsp_cfg(void) -{ - int ret = 0; - -#ifdef CONFIG_ARCH_OMAP1 - /* for safety */ - dsp_mem_usecount_clear(); -#endif - - /* - * DSPCFG command and dsp_mem_start() must be called - * while internal mem is on. - */ - dsp_mem_enable((void *)dspmem_base); - - dsp_mbox_start(); - dsp_twch_start(); - dsp_mem_start(); - dsp_err_start(); - - mbox_revision = -1; - - ret = misc_mbcompose_send_and_wait(DSPCFG, DSPCFG_REQ, 0, NULL); - if (ret < 0) { - if (ret != -EINTR) - printk(KERN_ERR "omapdsp: configuration error!\n"); - ret = 1; - goto out; - } - -#if defined(CONFIG_ARCH_OMAP1) && defined(OLD_BINARY_SUPPORT) - /* - * MBREV 3.2 or earlier doesn't assume DMA domain is on - * when DSPCFG command is sent - */ - if ((mbox_revision == MBREV_3_0) || - (mbox_revision == MBREV_3_2)) { - if ((ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA)) < 0) - goto out; - } -#endif - - if ((ret = dsp_task_config_all(n_stask)) < 0) - goto out; - - /* initialization */ -#ifdef CONFIG_OMAP_DSP_FBEXPORT - fbstat = FBSTAT_ENABLED; -#endif - - /* send parameter */ - ret = dsp_setvar(VARID_ICRMASK, dsp_cpustat_get_icrmask()); - if (ret < 0) - goto out; - - /* create runtime sysfs entries */ - ret = device_create_file(omap_dsp->dev, &dev_attr_loadinfo); - if (ret) - printk(KERN_ERR "device_create_file failed: %d\n", ret); - out: - dsp_mem_disable((void *)dspmem_base); - return ret; -} - -static int dsp_uncfg(void) -{ - if (dsp_taskmod_busy()) { - printk(KERN_WARNING "omapdsp: tasks are busy.\n"); - return -EBUSY; - } - - /* FIXME: lock task module */ - - /* remove runtime sysfs entries */ - device_remove_file(omap_dsp->dev, &dev_attr_loadinfo); - - dsp_mbox_stop(); - dsp_twch_stop(); - dsp_mem_stop(); - dsp_err_stop(); - dsp_dbg_stop(); - dsp_task_unconfig_all(); - ipbuf_stop(); - - return 0; -} - -static int dsp_suspend(void) -{ - int ret; - - ret = misc_mbcompose_send_and_wait(SUSPEND, 0, 0, NULL); - if (ret < 0) { - if (ret != -EINVAL) - printk(KERN_ERR "omapdsp: DSP suspend error!\n"); - return ret; - } - - udelay(100); /* wait for DSP-side execution */ - return 0; -} - -int dsp_cfgstat_request(enum cfgstat_e st_req) -{ - static DEFINE_MUTEX(cfgstat_lock); - int ret = 0, ret_override = 0; - - if (mutex_lock_interruptible(&cfgstat_lock)) - return -EINTR; - -again: - switch (st_req) { - - /* cfgstat takes CLEAN, READY or SUSPEND, - while st_req can take SUSPEND in addition. */ - - case CFGSTAT_CLEAN: - if (cfgstat == CFGSTAT_CLEAN) - goto up_out; - if ((ret = dsp_uncfg()) < 0) - goto up_out; - break; - - case CFGSTAT_READY: - if (cfgstat != CFGSTAT_CLEAN) { - printk(KERN_ERR "omapdsp: DSP is ready already!\n"); - ret = -EINVAL; - goto up_out; - } - - ret = dsp_cfg(); - if (ret > 0) { /* failed, but state is clear. */ - ret = -EINVAL; - goto up_out; - } else if (ret < 0) { /* failed, need cleanup. */ - st_req = CFGSTAT_CLEAN; - ret_override = ret; - goto again; - } - break; - - /* - * suspend / resume - * DSP is not reset within this code, but done in omap_pm_suspend. - * so if these functions are called from sysfs, - * DSP should be reset / unreset out of these functions. - */ - case CFGSTAT_SUSPEND: - switch (cfgstat) { - - case CFGSTAT_CLEAN: - if (dsp_cpustat_get_stat() == CPUSTAT_RUN) { - printk(KERN_WARNING - "omapdsp: illegal operation -- trying " - "suspend DSP while it is running but " - "not configured.\n" - " Resetting DSP.\n"); - dsp_cpustat_request(CPUSTAT_RESET); - ret = -EINVAL; - } - goto up_out; - - case CFGSTAT_READY: - if ((ret = dsp_suspend()) < 0) - goto up_out; - break; - - case CFGSTAT_SUSPEND: - goto up_out; - - default: - BUG(); - - } - - break; - - case CFGSTAT_RESUME: - if (cfgstat != CFGSTAT_SUSPEND) { - printk(KERN_WARNING - "omapdsp: DSP resume request, but DSP is not in " - "suspend state.\n"); - ret = -EINVAL; - goto up_out; - } - st_req = CFGSTAT_READY; - break; - - default: - BUG(); - - } - - cfgstat = st_req; -up_out: - mutex_unlock(&cfgstat_lock); - return ret_override ? ret_override : ret; -} - -enum cfgstat_e dsp_cfgstat_get_stat(void) -{ - return cfgstat; -} - -/* - * polls all tasks - */ -static int dsp_poll(void) -{ - int ret; - - ret = misc_mbcompose_send_and_wait(POLL, 0, 0, NULL); - if ((ret < 0) && (ret != -EINTR)) - printk(KERN_ERR "omapdsp: poll error!\n"); - - return ret; -} - -int dsp_set_runlevel(u8 level) -{ - if (level == RUNLEVEL_RECOVERY) { - if (mbcompose_send_recovery(RUNLEVEL, level, 0) < 0) - return -EINVAL; - } else { - if ((level < RUNLEVEL_USER) || - (level > RUNLEVEL_SUPER)) - return -EINVAL; - if (mbcompose_send(RUNLEVEL, level, 0) < 0) - return -EINVAL; - } - - return 0; -} - -#ifdef CONFIG_OMAP_DSP_FBEXPORT -static void dsp_fbctl_enable(void) -{ - mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_ENABLE); -} - -static int dsp_fbctl_disable(void) -{ - int ret; - - ret = misc_mbcompose_send_and_wait(KFUNC, KFUNC_FBCTL, FBCTL_DISABLE, - NULL); - if ((ret < 0) && (ret != -EINTR)) - printk(KERN_ERR "omapdsp: fb disable error!\n"); - - return 0; -} - -static int dsp_fbstat_request(enum fbstat_e st) -{ - static DEFINE_MUTEX(fbstat_lock); - int ret = 0; - - if (mutex_lock_interruptible(&fbstat_lock)) - return -EINTR; - - if (st == fbstat) - goto up_out; - - switch (st) { - case FBSTAT_ENABLED: - dsp_fbctl_enable(); - break; - case FBSTAT_DISABLED: - if ((ret = dsp_fbctl_disable()) < 0) - goto up_out; - break; - default: - BUG(); - } - - fbstat = st; -up_out: - mutex_unlock(&fbstat_lock); - return 0; -} -#endif /* CONFIG_OMAP_DSP_FBEXPORT */ - -/* - * DSP control device file operations - */ -static int dsp_ctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ret = 0; - - switch (cmd) { - /* - * command level 1: commands which don't need lock - */ - case DSPCTL_IOCTL_RUN: - dsp_cpustat_request(CPUSTAT_RUN); - break; - - case DSPCTL_IOCTL_RESET: - dsp_cpustat_request(CPUSTAT_RESET); - break; - - case DSPCTL_IOCTL_SETRSTVECT: - ret = dsp_set_rstvect((dsp_long_t)arg); - break; - -#ifdef CONFIG_ARCH_OMAP1 - case DSPCTL_IOCTL_CPU_IDLE: - dsp_cpustat_request(CPUSTAT_CPU_IDLE); - break; - - case DSPCTL_IOCTL_GBL_IDLE: - dsp_cpustat_request(CPUSTAT_GBL_IDLE); - break; - - case DSPCTL_IOCTL_MPUI_WORDSWAP_ON: - mpui_wordswap_on(); - break; - - case DSPCTL_IOCTL_MPUI_WORDSWAP_OFF: - mpui_wordswap_off(); - break; - - case DSPCTL_IOCTL_MPUI_BYTESWAP_ON: - mpui_byteswap_on(); - break; - - case DSPCTL_IOCTL_MPUI_BYTESWAP_OFF: - mpui_byteswap_off(); - break; -#endif /* CONFIG_ARCH_OMAP1 */ - - case DSPCTL_IOCTL_TASKCNT: - ret = dsp_task_count(); - break; - - case DSPCTL_IOCTL_MBSEND: - { - struct omap_dsp_mailbox_cmd u_cmd; - mbox_msg_t msg; - if (copy_from_user(&u_cmd, (void *)arg, sizeof(u_cmd))) - return -EFAULT; - msg = (u_cmd.cmd << 16) | u_cmd.data; - ret = dsp_mbcmd_send((struct mbcmd *)&msg); - break; - } - - case DSPCTL_IOCTL_SETVAR: - { - struct omap_dsp_varinfo var; - if (copy_from_user(&var, (void *)arg, sizeof(var))) - return -EFAULT; - ret = dsp_setvar(var.varid, var.val[0]); - break; - } - - case DSPCTL_IOCTL_RUNLEVEL: - ret = dsp_set_runlevel(arg); - break; - -#ifdef CONFIG_OMAP_DSP_FBEXPORT - case DSPCTL_IOCTL_FBEN: - ret = dsp_fbstat_request(FBSTAT_ENABLED); - break; -#endif - - /* - * command level 2: commands which need lock - */ - case DSPCTL_IOCTL_DSPCFG: - ret = dsp_cfgstat_request(CFGSTAT_READY); - break; - - case DSPCTL_IOCTL_DSPUNCFG: - ret = dsp_cfgstat_request(CFGSTAT_CLEAN); - break; - - case DSPCTL_IOCTL_POLL: - ret = dsp_poll(); - break; - -#ifdef CONFIG_OMAP_DSP_FBEXPORT - case DSPCTL_IOCTL_FBDIS: - ret = dsp_fbstat_request(FBSTAT_DISABLED); - break; -#endif - - case DSPCTL_IOCTL_SUSPEND: - if ((ret = dsp_cfgstat_request(CFGSTAT_SUSPEND)) < 0) - break; - dsp_cpustat_request(CPUSTAT_RESET); - break; - - case DSPCTL_IOCTL_RESUME: - if ((ret = dsp_cfgstat_request(CFGSTAT_RESUME)) < 0) - break; - dsp_cpustat_request(CPUSTAT_RUN); - break; - - case DSPCTL_IOCTL_REGMEMR: - { - struct omap_dsp_reginfo *u_reg = (void *)arg; - u16 adr, val; - - if (copy_from_user(&adr, &u_reg->adr, sizeof(u16))) - return -EFAULT; - if ((ret = dsp_regread(SPACE_MEM, adr, &val)) < 0) - return ret; - if (copy_to_user(&u_reg->val, &val, sizeof(u16))) - return -EFAULT; - break; - } - - case DSPCTL_IOCTL_REGMEMW: - { - struct omap_dsp_reginfo reg; - - if (copy_from_user(®, (void *)arg, sizeof(reg))) - return -EFAULT; - ret = dsp_regwrite(SPACE_MEM, reg.adr, reg.val); - break; - } - - case DSPCTL_IOCTL_REGIOR: - { - struct omap_dsp_reginfo *u_reg = (void *)arg; - u16 adr, val; - - if (copy_from_user(&adr, &u_reg->adr, sizeof(u16))) - return -EFAULT; - if ((ret = dsp_regread(SPACE_IO, adr, &val)) < 0) - return ret; - if (copy_to_user(&u_reg->val, &val, sizeof(u16))) - return -EFAULT; - break; - } - - case DSPCTL_IOCTL_REGIOW: - { - struct omap_dsp_reginfo reg; - - if (copy_from_user(®, (void *)arg, sizeof(reg))) - return -EFAULT; - ret = dsp_regwrite(SPACE_IO, reg.adr, reg.val); - break; - } - - case DSPCTL_IOCTL_GETVAR: - { - struct omap_dsp_varinfo *u_var = (void *)arg; - u8 varid; - u16 val[5]; /* maximum */ - int argc; - - if (copy_from_user(&varid, &u_var->varid, sizeof(u8))) - return -EFAULT; - switch (varid) { - case VARID_ICRMASK: - argc = 1; - break; - case VARID_LOADINFO: - argc = 5; - break; - default: - return -EINVAL; - } - if ((ret = dsp_getvar(varid, val)) < 0) - return ret; - if (copy_to_user(&u_var->val, val, sizeof(u16) * argc)) - return -EFAULT; - break; - } - - default: - return -ENOIOCTLCMD; - } - - return ret; -} - -/* - * functions called from mailbox interrupt routine - */ -void mbox_suspend(struct mbcmd *mb) -{ - misc_mbcmd_response(mb, 0, 0); -} - -void mbox_dspcfg(struct mbcmd *mb) -{ - u8 last = mb->cmd_l & 0x80; - u8 cfgcmd = mb->cmd_l & 0x7f; - static dsp_long_t tmp_ipb_adr; - - if (!waitqueue_active(&misc_mb_wait.wait_q) || - (misc_mb_wait.cmd_h != MBOX_CMD_DSP_DSPCFG)) { - printk(KERN_WARNING - "mbox: DSPCFG command received, " - "but nobody is waiting for it...\n"); - return; - } - - /* mailbox protocol check */ - if (cfgcmd == DSPCFG_PROTREV) { - mbox_revision = mb->data; - if (mbox_revision == MBPROT_REVISION) - return; -#ifdef OLD_BINARY_SUPPORT - else if ((mbox_revision == MBREV_3_0) || - (mbox_revision == MBREV_3_2)) { - printk(KERN_WARNING - "mbox: ***** old DSP binary *****\n" - " Please update your DSP application.\n"); - return; - } -#endif - else { - printk(KERN_ERR - "mbox: protocol revision check error!\n" - " expected=0x%04x, received=0x%04x\n", - MBPROT_REVISION, mb->data); - mbox_revision = -1; - goto abort1; - } - } - - /* - * following commands are accepted only after - * revision check has been passed. - */ - if (!mbox_revision < 0) { - pr_info("mbox: DSPCFG command received, " - "but revision check has not been passed.\n"); - return; - } - - switch (cfgcmd) { - case DSPCFG_SYSADRH: - tmp_ipb_adr = (u32)mb->data << 16; - break; - - case DSPCFG_SYSADRL: - tmp_ipb_adr |= mb->data; - break; - - case DSPCFG_ABORT: - goto abort1; - - default: - printk(KERN_ERR - "mbox: Unknown CFG command: cmd_l=0x%02x, data=0x%04x\n", - mb->cmd_l, mb->data); - return; - } - - if (last) { - void *badr; - u16 bln; - u16 bsz; - volatile u16 *buf; - void *ipb_sys_da, *ipb_sys_ad; - void *mbseq; /* FIXME: 3.4 obsolete */ - short *dbg_buf; - u16 dbg_buf_sz, dbg_line_sz; - struct mem_sync_struct mem_sync, *mem_syncp; - - ipb_sys_da = dspword_to_virt(tmp_ipb_adr); - if (ipbuf_sys_config(ipb_sys_da, DIR_D2A) < 0) - goto abort1; - - if (dsp_mem_enable(ipbuf_sys_da) < 0) { - printk(KERN_ERR "mbox: DSPCFG - ipbuf_sys_da read failed!\n"); - goto abort1; - } - if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 10) < 0) { - printk(KERN_ERR "mbox: DSPCFG - IPBUF sync failed!\n"); - dsp_mem_disable(ipbuf_sys_da); - goto abort1; - } - /* - * read configuration data on system IPBUF - * we must read with 16bit-access - */ -#ifdef OLD_BINARY_SUPPORT - if (mbox_revision == MBPROT_REVISION) { -#endif - buf = ipbuf_sys_da->d; - n_stask = buf[0]; - bln = buf[1]; - bsz = buf[2]; - badr = MKVIRT(buf[3], buf[4]); - /* ipb_sys_da = MKVIRT(buf[5], buf[6]); */ - ipb_sys_ad = MKVIRT(buf[7], buf[8]); - mbseq = MKVIRT(buf[9], buf[10]); - dbg_buf = MKVIRT(buf[11], buf[12]); - dbg_buf_sz = buf[13]; - dbg_line_sz = buf[14]; - mem_sync.DARAM = MKVIRT(buf[15], buf[16]); - mem_sync.SARAM = MKVIRT(buf[17], buf[18]); - mem_sync.SDRAM = MKVIRT(buf[19], buf[20]); - mem_syncp = &mem_sync; -#ifdef OLD_BINARY_SUPPORT - } else if (mbox_revision == MBREV_3_2) { - buf = ipbuf_sys_da->d; - n_stask = buf[0]; - bln = buf[1]; - bsz = buf[2]; - badr = MKVIRT(buf[3], buf[4]); - /* ipb_sys_da = MKVIRT(buf[5], buf[6]); */ - ipb_sys_ad = MKVIRT(buf[7], buf[8]); - mbseq = MKVIRT(buf[9], buf[10]); - dbg_buf = NULL; - dbg_buf_sz = 0; - dbg_line_sz = 0; - mem_syncp = NULL; - } else if (mbox_revision == MBREV_3_0) { - buf = ipbuf_sys_da->d; - n_stask = buf[0]; - bln = buf[1]; - bsz = buf[2]; - badr = MKVIRT(buf[3], buf[4]); - /* bkeep = buf[5]; */ - /* ipb_sys_da = MKVIRT(buf[6], buf[7]); */ - ipb_sys_ad = MKVIRT(buf[8], buf[9]); - mbseq = MKVIRT(buf[10], buf[11]); - dbg_buf = NULL; - dbg_buf_sz = 0; - dbg_line_sz = 0; - mem_syncp = NULL; - } else { /* should not occur */ - dsp_mem_disable(ipbuf_sys_da); - goto abort1; - } -#endif /* OLD_BINARY_SUPPORT */ - - release_ipbuf_pvt(ipbuf_sys_da); - dsp_mem_disable(ipbuf_sys_da); - - /* - * following configurations need to be done before - * waking up the dspcfg initiator process. - */ - if (ipbuf_sys_config(ipb_sys_ad, DIR_A2D) < 0) - goto abort1; - if (ipbuf_config(bln, bsz, badr) < 0) - goto abort1; - if (dsp_mbox_config(mbseq) < 0) - goto abort2; - if (dsp_dbg_config(dbg_buf, dbg_buf_sz, dbg_line_sz) < 0) - goto abort2; - if (dsp_mem_sync_config(mem_syncp) < 0) - goto abort2; - - misc_mb_wait.cmd_h = 0; - wake_up_interruptible(&misc_mb_wait.wait_q); - } - return; - -abort2: - ipbuf_stop(); -abort1: - wake_up_interruptible(&misc_mb_wait.wait_q); - return; -} - -void mbox_poll(struct mbcmd *mb) -{ - misc_mbcmd_response(mb, 0, 0); -} - -void mbox_regrw(struct mbcmd *mb) -{ - switch (mb->cmd_l) { - case REGRW_DATA: - misc_mbcmd_response(mb, 1, 0); - break; - default: - printk(KERN_ERR - "mbox: Illegal REGRW command: " - "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data); - return; - } -} - -void mbox_getvar(struct mbcmd *mb) -{ - switch (mb->cmd_l) { - case VARID_ICRMASK: - misc_mbcmd_response(mb, 1, 1); - break; - case VARID_LOADINFO: - misc_mbcmd_response(mb, 5, 1); - break; - default: - printk(KERN_ERR - "mbox: Illegal GETVAR command: " - "cmd_l=0x%02x, data=0x%04x\n", mb->cmd_l, mb->data); - return; - } -} - -void mbox_fbctl_disable(struct mbcmd *mb) -{ - misc_mbcmd_response(mb, 0, 0); -} - -struct file_operations dsp_ctl_fops = { - .owner = THIS_MODULE, - .ioctl = dsp_ctl_ioctl, -}; - -/* - * sysfs files - */ - -/* ifver */ -static ssize_t ifver_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int len = 0; - - /* - * I/F VERSION descriptions: - * - * 3.2: sysfs / udev support - * KMEM_RESERVE / KMEM_RELEASE ioctls for mem device - * 3.3: added following ioctls - * DSPCTL_IOCTL_GBL_IDLE - * DSPCTL_IOCTL_CPU_IDLE (instead of DSPCTL_IOCTL_IDLE) - * DSPCTL_IOCTL_POLL - */ - - /* - * print all supporting I/F VERSIONs, like followings. - * - * len += sprintf(buf, "3.2\n"); - * len += sprintf(buf, "3.3\n"); - */ - len += sprintf(buf + len, "3.2\n"); - len += sprintf(buf + len, "3.3\n"); - - return len; -} - -/* cpustat */ -static char *cpustat_name[CPUSTAT_MAX] = { - [CPUSTAT_RESET] = "reset", -#ifdef CONFIG_ARCH_OMAP1 - [CPUSTAT_GBL_IDLE] = "gbl_idle", - [CPUSTAT_CPU_IDLE] = "cpu_idle", -#endif - [CPUSTAT_RUN] = "run", -}; - -static ssize_t cpustat_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", cpustat_name[dsp_cpustat_get_stat()]); -} - -/* icrmask */ -static ssize_t icrmask_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "0x%04x\n", dsp_cpustat_get_icrmask()); -} - -static ssize_t icrmask_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - u16 mask; - int ret; - - mask = simple_strtol(buf, NULL, 16); - dsp_cpustat_set_icrmask(mask); - - if (dsp_cfgstat_get_stat() == CFGSTAT_READY) { - ret = dsp_setvar(VARID_ICRMASK, mask); - if (ret < 0) - return ret; - } - - return count; -} - -/* loadinfo */ -static ssize_t loadinfo_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int len; - int ret; - u16 val[5]; - - if ((ret = dsp_getvar(VARID_LOADINFO, val)) < 0) - return ret; - - /* - * load info value range is 0(free) - 10000(busy): - * if CPU load is not measured on DSP, it sets 0xffff at val[0]. - */ - - if (val[0] == 0xffff) { - len = sprintf(buf, - "currently DSP load info is not available.\n"); - goto out; - } - - len = sprintf(buf, - "DSP load info:\n" - " 10ms average = %3d.%02d%%\n" - " 1sec average = %3d.%02d%% busiest 10ms = %3d.%02d%%\n" - " 1min average = %3d.%02d%% busiest 1s = %3d.%02d%%\n", - val[0]/100, val[0]%100, - val[1]/100, val[1]%100, val[2]/100, val[2]%100, - val[3]/100, val[3]%100, val[4]/100, val[4]%100); -out: - return len; -} - -int __init dsp_ctl_init(void) -{ - int ret; - - ret = device_create_file(omap_dsp->dev, &dev_attr_ifver); - if (unlikely(ret)) - return ret; - ret = device_create_file(omap_dsp->dev, &dev_attr_cpustat); - if (unlikely(ret)) - goto fail_create_cpustat; - ret = device_create_file(omap_dsp->dev, &dev_attr_icrmask); - if (unlikely(ret)) - goto fail_create_icrmask; - - return 0; - -fail_create_icrmask: - device_remove_file(omap_dsp->dev, &dev_attr_cpustat); -fail_create_cpustat: - device_remove_file(omap_dsp->dev, &dev_attr_ifver); - - return ret; -} - -void dsp_ctl_exit(void) -{ - device_remove_file(omap_dsp->dev, &dev_attr_ifver); - device_remove_file(omap_dsp->dev, &dev_attr_cpustat); - device_remove_file(omap_dsp->dev, &dev_attr_icrmask); -} diff --git a/drivers/dsp/dspgateway/dsp_ctl_core.c b/drivers/dsp/dspgateway/dsp_ctl_core.c deleted file mode 100644 index 25954bba9c8..00000000000 --- a/drivers/dsp/dspgateway/dsp_ctl_core.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include "dsp.h" - -#define CTL_MINOR 0 -#define MEM_MINOR 1 -#define TWCH_MINOR 2 -#define ERR_MINOR 3 - -static struct class *dsp_ctl_class; -extern struct file_operations dsp_ctl_fops, - dsp_mem_fops, - dsp_twch_fops, - dsp_err_fops; - -static int dsp_ctl_core_open(struct inode *inode, struct file *file) -{ - static DEFINE_MUTEX(open_lock); - int ret = 0; - - if (mutex_lock_interruptible(&open_lock)) - return -EINTR; - if (omap_dsp->initialized == 0) { - ret = dsp_late_init(); - if (ret != 0) { - mutex_unlock(&open_lock); - return ret; - } - omap_dsp->initialized = 1; - } - mutex_unlock(&open_lock); - - switch (iminor(inode)) { - case CTL_MINOR: - file->f_op = &dsp_ctl_fops; - break; - case MEM_MINOR: - file->f_op = &dsp_mem_fops; - break; - case TWCH_MINOR: - file->f_op = &dsp_twch_fops; - break; - case ERR_MINOR: - file->f_op = &dsp_err_fops; - break; - default: - return -ENXIO; - } - if (file->f_op && file->f_op->open) - return file->f_op->open(inode, file); - return 0; -} - -static struct file_operations dsp_ctl_core_fops = { - .owner = THIS_MODULE, - .open = dsp_ctl_core_open, -}; - -static const struct dev_list { - unsigned int minor; - char *devname; - umode_t mode; -} dev_list[] = { - {CTL_MINOR, "dspctl", S_IRUSR | S_IWUSR}, - {MEM_MINOR, "dspmem", S_IRUSR | S_IWUSR | S_IRGRP}, - {TWCH_MINOR, "dsptwch", S_IRUSR | S_IWUSR | S_IRGRP}, - {ERR_MINOR, "dsperr", S_IRUSR | S_IRGRP}, -}; - -int __init dsp_ctl_core_init(void) -{ - int retval; - int i; - - retval = register_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl", - &dsp_ctl_core_fops); - if (retval < 0) { - printk(KERN_ERR - "omapdsp: failed to register dspctl device: %d\n", - retval); - return retval; - } - - dsp_ctl_class = class_create(THIS_MODULE, "dspctl"); - for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - device_create(dsp_ctl_class, NULL, - MKDEV(OMAP_DSP_CTL_MAJOR, dev_list[i].minor), - NULL, dev_list[i].devname); - } - - return 0; -} - -void dsp_ctl_core_exit(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dev_list); i++) { - device_destroy(dsp_ctl_class, - MKDEV(OMAP_DSP_CTL_MAJOR, - dev_list[i].minor)); - } - class_destroy(dsp_ctl_class); - - unregister_chrdev(OMAP_DSP_CTL_MAJOR, "dspctl"); -} diff --git a/drivers/dsp/dspgateway/dsp_mbcmd.h b/drivers/dsp/dspgateway/dsp_mbcmd.h deleted file mode 100644 index fb357493258..00000000000 --- a/drivers/dsp/dspgateway/dsp_mbcmd.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __PLAT_OMAP_DSP_MBCMD_H -#define __PLAT_OMAP_DSP_MBCMD_H -/* - * mailbox command: 0x00 - 0x7f - * when a driver wants to use mailbox, it must reserve mailbox commands here. - */ -#define MBOX_CMD_DSP_WDSND 0x10 -#define MBOX_CMD_DSP_WDREQ 0x11 -#define MBOX_CMD_DSP_BKSND 0x20 -#define MBOX_CMD_DSP_BKREQ 0x21 -#define MBOX_CMD_DSP_BKYLD 0x23 -#define MBOX_CMD_DSP_BKSNDP 0x24 -#define MBOX_CMD_DSP_BKREQP 0x25 -#define MBOX_CMD_DSP_TCTL 0x30 -#define MBOX_CMD_DSP_TCTLDATA 0x31 -#define MBOX_CMD_DSP_POLL 0x32 -#define MBOX_CMD_DSP_WDT 0x50 -#define MBOX_CMD_DSP_RUNLEVEL 0x51 -#define MBOX_CMD_DSP_PM 0x52 -#define MBOX_CMD_DSP_SUSPEND 0x53 -#define MBOX_CMD_DSP_KFUNC 0x54 -#define MBOX_CMD_DSP_TCFG 0x60 -#define MBOX_CMD_DSP_TADD 0x62 -#define MBOX_CMD_DSP_TDEL 0x63 -#define MBOX_CMD_DSP_TSTOP 0x65 -#define MBOX_CMD_DSP_DSPCFG 0x70 -#define MBOX_CMD_DSP_REGRW 0x72 -#define MBOX_CMD_DSP_GETVAR 0x74 -#define MBOX_CMD_DSP_SETVAR 0x75 -#define MBOX_CMD_DSP_ERR 0x78 -#define MBOX_CMD_DSP_DBG 0x79 - -/* - * DSP mailbox protocol definitions - */ -#define MBPROT_REVISION 0x0019 - -#define TCTL_TINIT 0x0000 -#define TCTL_TEN 0x0001 -#define TCTL_TDIS 0x0002 -#define TCTL_TCLR 0x0003 -#define TCTL_TCLR_FORCE 0x0004 - -#define RUNLEVEL_USER 0x01 -#define RUNLEVEL_SUPER 0x0e -#define RUNLEVEL_RECOVERY 0x10 - -#define PM_DISABLE 0x00 -#define PM_ENABLE 0x01 - -#define KFUNC_FBCTL 0x00 -#define KFUNC_POWER 0x01 - -#define FBCTL_UPD 0x0000 -#define FBCTL_ENABLE 0x0002 -#define FBCTL_DISABLE 0x0003 - -/* KFUNC_POWER */ -#define AUDIO_PWR_UP 0x0000 /* ARM(exe/ack) <-> DSP(req) */ -#define AUDIO_PWR_DOWN 0x0001 /* ARM(exe) <- DSP(req) */ -#define AUDIO_PWR_DOWN1 AUDIO_PWR_DOWN -#define AUDIO_PWR_DOWN2 0x0002 -#define DSP_PWR_UP 0x0003 /* ARM(exe/snd) -> DSP(exe) */ -#define DSP_PWR_DOWN 0x0004 /* ARM(exe) <- DSP(req) */ -#define DVFS_START 0x0006 /* ARM(req) <-> DSP(exe/ack)*/ -#define DVFS_STOP 0x0007 /* ARM(req) -> DSP(exe) */ - -#define TDEL_SAFE 0x0000 -#define TDEL_KILL 0x0001 - -#define DSPCFG_REQ 0x00 -#define DSPCFG_SYSADRH 0x28 -#define DSPCFG_SYSADRL 0x29 -#define DSPCFG_PROTREV 0x70 -#define DSPCFG_ABORT 0x78 -#define DSPCFG_LAST 0x80 - -#define REGRW_MEMR 0x00 -#define REGRW_MEMW 0x01 -#define REGRW_IOR 0x02 -#define REGRW_IOW 0x03 -#define REGRW_DATA 0x04 - -#define VARID_ICRMASK 0x00 -#define VARID_LOADINFO 0x01 - -#define TTYP_ARCV 0x0001 -#define TTYP_ASND 0x0002 -#define TTYP_BKMD 0x0004 -#define TTYP_BKDM 0x0008 -#define TTYP_PVMD 0x0010 -#define TTYP_PVDM 0x0020 - -#define EID_BADTID 0x10 -#define EID_BADTCN 0x11 -#define EID_BADBID 0x20 -#define EID_BADCNT 0x21 -#define EID_NOTLOCKED 0x22 -#define EID_STVBUF 0x23 -#define EID_BADADR 0x24 -#define EID_BADTCTL 0x30 -#define EID_BADPARAM 0x50 -#define EID_FATAL 0x58 -#define EID_NOMEM 0xc0 -#define EID_NORES 0xc1 -#define EID_IPBFULL 0xc2 -#define EID_WDT 0xd0 -#define EID_TASKNOTRDY 0xe0 -#define EID_TASKBSY 0xe1 -#define EID_TASKERR 0xef -#define EID_BADCFGTYP 0xf0 -#define EID_DEBUG 0xf8 -#define EID_BADSEQ 0xfe -#define EID_BADCMD 0xff - -#define TNM_LEN 16 - -#define TID_FREE 0xff -#define TID_ANON 0xfe - -#define BID_NULL 0xffff -#define BID_PVT 0xfffe - -#endif /* __PLAT_OMAP_DSP_MBCMD_H */ diff --git a/drivers/dsp/dspgateway/dsp_mem.c b/drivers/dsp/dspgateway/dsp_mem.c deleted file mode 100644 index e21bd069619..00000000000 --- a/drivers/dsp/dspgateway/dsp_mem.c +++ /dev/null @@ -1,484 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * Conversion to mempool API and ARM MMU section mapping - * by Paul Mundt - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" -#include "ipbuf.h" - -#if 0 -#if defined(CONFIG_ARCH_OMAP1) -#include "../../mach-omap1/mmu.h" -#elif defined(CONFIG_ARCH_OMAP2) -#include "../../mach-omap2/mmu.h" -#endif -#endif - -#include "mmu.h" - -static struct mem_sync_struct mem_sync; - -int dsp_mem_sync_inc(void) -{ - if (dsp_mem_enable((void *)dspmem_base) < 0) - return -1; - if (mem_sync.DARAM) - mem_sync.DARAM->ad_arm++; - if (mem_sync.SARAM) - mem_sync.SARAM->ad_arm++; - if (mem_sync.SDRAM) - mem_sync.SDRAM->ad_arm++; - dsp_mem_disable((void *)dspmem_base); - - return 0; -} - -/* - * dsp_mem_sync_config() is called from mbox1 workqueue - */ -int dsp_mem_sync_config(struct mem_sync_struct *sync) -{ - size_t sync_seq_sz = sizeof(struct sync_seq); - -#ifdef OLD_BINARY_SUPPORT - if (sync == NULL) { - memset(&mem_sync, 0, sizeof(struct mem_sync_struct)); - return 0; - } -#endif - if ((dsp_mem_type(sync->DARAM, sync_seq_sz) != MEM_TYPE_DARAM) || - (dsp_mem_type(sync->SARAM, sync_seq_sz) != MEM_TYPE_SARAM) || - (dsp_mem_type(sync->SDRAM, sync_seq_sz) != MEM_TYPE_EXTERN)) { - printk(KERN_ERR - "omapdsp: mem_sync address validation failure!\n" - " mem_sync.DARAM = 0x%p,\n" - " mem_sync.SARAM = 0x%p,\n" - " mem_sync.SDRAM = 0x%p,\n", - sync->DARAM, sync->SARAM, sync->SDRAM); - return -1; - } - - memcpy(&mem_sync, sync, sizeof(struct mem_sync_struct)); - - return 0; -} - - -enum dsp_mem_type_e dsp_mem_type(void *vadr, size_t len) -{ - void *ds = (void *)daram_base; - void *de = (void *)daram_base + daram_size; - void *ss = (void *)saram_base; - void *se = (void *)saram_base + saram_size; - int ret; - - if ((vadr >= ds) && (vadr < de)) { - if (vadr + len > de) - return MEM_TYPE_CROSSING; - else - return MEM_TYPE_DARAM; - } else if ((vadr >= ss) && (vadr < se)) { - if (vadr + len > se) - return MEM_TYPE_CROSSING; - else - return MEM_TYPE_SARAM; - } else { - down_read(&dsp_mmu.exmap_sem); - if (exmap_valid(&dsp_mmu, vadr, len)) - ret = MEM_TYPE_EXTERN; - else - ret = MEM_TYPE_NONE; - up_read(&dsp_mmu.exmap_sem); - return ret; - } -} - -int dsp_address_validate(void *p, size_t len, char *fmt, ...) -{ - char s[64]; - va_list args; - - if (dsp_mem_type(p, len) > 0) - return 0; - - if (fmt == NULL) - goto out; - - va_start(args, fmt); - vsprintf(s, fmt, args); - va_end(args); - printk(KERN_ERR - "omapdsp: %s address(0x%p) and size(0x%x) is not valid!\n" - "(crossing different type of memories, or external memory\n" - "space where no actual memory is mapped)\n", s, p, len); - out: - return -1; -} - -#ifdef CONFIG_OMAP_DSP_FBEXPORT - -static inline unsigned long lineup_offset(unsigned long adr, - unsigned long ref, - unsigned long mask) -{ - unsigned long newadr; - - newadr = (adr & ~mask) | (ref & mask); - if (newadr < adr) - newadr += mask + 1; - return newadr; -} - -/* - * fb update functions: - * fbupd_response() is executed by the workqueue. - * fbupd_cb() is called when fb update is done, in interrupt context. - * mbox_fbupd() is called when KFUNC:FBCTL:UPD is received from DSP. - */ -static void fbupd_response(struct work_struct *unused) -{ - int status; - - status = mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_UPD); - if (status == 0) - return; - - /* FIXME: DSP is busy !! */ - printk(KERN_ERR - "omapdsp:" - "DSP is busy when trying to send FBCTL:UPD response!\n"); -} - -static DECLARE_WORK(fbupd_response_work, fbupd_response); - -static void fbupd_cb(void *arg) -{ - schedule_work(&fbupd_response_work); -} - -void mbox_fbctl_upd(void) -{ - struct omapfb_update_window win; - volatile unsigned short *buf = ipbuf_sys_da->d; - - if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 5000) < 0) { - printk(KERN_ERR "mbox: FBCTL:UPD - IPBUF sync failed!\n"); - return; - } - win.x = buf[0]; - win.y = buf[1]; - win.width = buf[2]; - win.height = buf[3]; - win.format = buf[4]; - release_ipbuf_pvt(ipbuf_sys_da); - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - if (!omapfb_ready) { - printk(KERN_WARNING - "omapdsp: fbupd() called while HWA742 is not ready!\n"); - return; - } -#endif - omapfb_update_window_async(registered_fb[0], &win, fbupd_cb, NULL); -} - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL -static int omapfb_notifier_cb(struct notifier_block *omapfb_nb, - unsigned long event, void *fbi) -{ - pr_info("omapfb_notifier_cb(): event = %s\n", - (event == OMAPFB_EVENT_READY) ? "READY" : - (event == OMAPFB_EVENT_DISABLED) ? "DISABLED" : "Unknown"); - if (event == OMAPFB_EVENT_READY) - omapfb_ready = 1; - else if (event == OMAPFB_EVENT_DISABLED) - omapfb_ready = 0; - return 0; -} -#endif - -static int dsp_fbexport(dsp_long_t *dspadr) -{ - dsp_long_t dspadr_actual; - unsigned long padr_sys, padr, fbsz_sys, fbsz; - int cnt; -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - int status; -#endif - - pr_debug( "omapdsp: frame buffer export\n"); - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - if (omapfb_nb) { - printk(KERN_WARNING - "omapdsp: frame buffer has been exported already!\n"); - return -EBUSY; - } -#endif - - if (num_registered_fb == 0) { - pr_info("omapdsp: frame buffer not registered.\n"); - return -EINVAL; - } - if (num_registered_fb != 1) { - pr_info("omapdsp: %d frame buffers found. we use first one.\n", - num_registered_fb); - } - padr_sys = registered_fb[0]->fix.smem_start; - fbsz_sys = registered_fb[0]->fix.smem_len; - if (fbsz_sys == 0) { - printk(KERN_ERR - "omapdsp: framebuffer doesn't seem to be configured " - "correctly! (size=0)\n"); - return -EINVAL; - } - - /* - * align padr and fbsz to 4kB boundary - * (should be noted to the user afterwards!) - */ - padr = padr_sys & ~(SZ_4K-1); - fbsz = (fbsz_sys + padr_sys - padr + SZ_4K-1) & ~(SZ_4K-1); - - /* line up dspadr offset with padr */ - dspadr_actual = - (fbsz > SZ_1M) ? lineup_offset(*dspadr, padr, SZ_1M-1) : - (fbsz > SZ_64K) ? lineup_offset(*dspadr, padr, SZ_64K-1) : - /* (fbsz > SZ_4KB) ? */ *dspadr; - if (dspadr_actual != *dspadr) - pr_debug( - "omapdsp: actual dspadr for FBEXPORT = %08x\n", - dspadr_actual); - *dspadr = dspadr_actual; - - cnt = omap_mmu_exmap(&dsp_mmu, dspadr_actual, padr, fbsz, - EXMAP_TYPE_FB); - if (cnt < 0) { - printk(KERN_ERR "omapdsp: exmap failure.\n"); - return cnt; - } - - if ((padr != padr_sys) || (fbsz != fbsz_sys)) { - printk(KERN_WARNING -" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" -" !! screen base address or size is not aligned in 4kB: !!\n" -" !! actual screen adr = %08lx, size = %08lx !!\n" -" !! exporting adr = %08lx, size = %08lx !!\n" -" !! Make sure that the framebuffer is allocated with 4kB-order! !!\n" -" !! Otherwise DSP can corrupt the kernel memory. !!\n" -" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n", - padr_sys, fbsz_sys, padr, fbsz); - } - - /* increase the DMA priority */ - set_emiff_dma_prio(15); - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL - omapfb_nb = kzalloc(sizeof(struct omapfb_notifier_block), GFP_KERNEL); - if (omapfb_nb == NULL) { - printk(KERN_ERR - "omapdsp: failed to allocate memory for omapfb_nb!\n"); - omap_mmu_exunmap(&dsp_mmu, (unsigned long)dspadr); - return -ENOMEM; - } - - status = omapfb_register_client(omapfb_nb, omapfb_notifier_cb, NULL); - if (status) - pr_info("omapfb_register_client(): failure(%d)\n", status); -#endif - - return cnt; -} -#else -void mbox_fbctl_upd(void) { } -#endif - -/* dsp/mem fops: backward compatibility */ -static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct bin_attribute attr; - - return __omap_mmu_mem_read(&dsp_mmu, &attr, - (char __user *)buf, *ppos, count); -} - -static ssize_t dsp_mem_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct bin_attribute attr; - - return __omap_mmu_mem_write(&dsp_mmu, &attr, - (char __user *)buf, *ppos, count); -} - -static int dsp_mem_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct omap_dsp_mapinfo mapinfo; - __u32 size; - - switch (cmd) { - case MEM_IOCTL_MMUINIT: - if (dsp_mmu.exmap_tbl) - omap_mmu_unregister(&dsp_mmu); - dsp_mem_ipi_init(); - return omap_mmu_register(&dsp_mmu); - - case MEM_IOCTL_EXMAP: - if (copy_from_user(&mapinfo, (void __user *)arg, - sizeof(mapinfo))) - return -EFAULT; - return omap_mmu_exmap(&dsp_mmu, mapinfo.dspadr, - 0, mapinfo.size, EXMAP_TYPE_MEM); - - case MEM_IOCTL_EXUNMAP: - return omap_mmu_exunmap(&dsp_mmu, (unsigned long)arg); - - case MEM_IOCTL_EXMAP_FLUSH: - omap_mmu_exmap_flush(&dsp_mmu); - return 0; -#ifdef CONFIG_OMAP_DSP_FBEXPORT - case MEM_IOCTL_FBEXPORT: - { - dsp_long_t dspadr; - int ret; - if (copy_from_user(&dspadr, (void __user *)arg, - sizeof(dsp_long_t))) - return -EFAULT; - ret = dsp_fbexport(&dspadr); - if (copy_to_user((void __user *)arg, &dspadr, - sizeof(dsp_long_t))) - return -EFAULT; - return ret; - } -#endif - case MEM_IOCTL_MMUITACK: - return dsp_mmu_itack(); - - case MEM_IOCTL_KMEM_RESERVE: - - if (copy_from_user(&size, (void __user *)arg, - sizeof(__u32))) - return -EFAULT; - return omap_mmu_kmem_reserve(&dsp_mmu, size); - - - case MEM_IOCTL_KMEM_RELEASE: - omap_mmu_kmem_release(); - return 0; - - default: - return -ENOIOCTLCMD; - } -} - -struct file_operations dsp_mem_fops = { - .owner = THIS_MODULE, - .read = dsp_mem_read, - .write = dsp_mem_write, - .ioctl = dsp_mem_ioctl, -}; - -void dsp_mem_start(void) -{ - dsp_register_mem_cb(intmem_enable, intmem_disable); -} - -void dsp_mem_stop(void) -{ - memset(&mem_sync, 0, sizeof(struct mem_sync_struct)); - dsp_unregister_mem_cb(); -} - -static void dsp_mmu_irq_work(struct work_struct *work) -{ - struct omap_mmu *mmu = container_of(work, struct omap_mmu, irq_work); - - if (dsp_cfgstat_get_stat() == CFGSTAT_READY) { - dsp_err_set(ERRCODE_MMU, mmu->fault_address); - return; - } - omap_mmu_itack(mmu); - pr_info("Resetting DSP...\n"); - dsp_cpustat_request(CPUSTAT_RESET); - omap_mmu_enable(mmu, 0); -} - -/* - * later half of dsp memory initialization - */ -int dsp_mem_late_init(void) -{ - int ret; - - dsp_mem_ipi_init(); - - INIT_WORK(&dsp_mmu.irq_work, dsp_mmu_irq_work); - ret = omap_mmu_register(&dsp_mmu); - if (ret) { - dsp_reset_idle_boot_base(); - goto out; - } - omap_dsp->mmu = &dsp_mmu; - out: - return ret; -} - -int __init dsp_mem_init(void) -{ -#ifdef CONFIG_ARCH_OMAP2 - dsp_mmu.clk = dsp_fck_handle; - dsp_mmu.memclk = dsp_ick_handle; -#elif defined(CONFIG_ARCH_OMAP1) - dsp_mmu.clk = dsp_ck_handle; - dsp_mmu.memclk = api_ck_handle; -#endif - return 0; -} - -void dsp_mem_exit(void) -{ - dsp_reset_idle_boot_base(); - omap_mmu_unregister(&dsp_mmu); -} diff --git a/drivers/dsp/dspgateway/error.c b/drivers/dsp/dspgateway/error.c deleted file mode 100644 index 66d9c8aa51f..00000000000 --- a/drivers/dsp/dspgateway/error.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" - -/* - * value seen through read() - */ -#define DSP_ERR_WDT 0x00000001 -#define DSP_ERR_MMU 0x00000002 -static unsigned long errval; - -static DECLARE_WAIT_QUEUE_HEAD(err_wait_q); -static int errcnt; -static u16 wdtval; /* FIXME: read through ioctl */ -static u32 mmu_fadr; /* FIXME: read through ioctl */ - -/* - * DSP error detection device file operations - */ -static ssize_t dsp_err_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - unsigned long flags; - int status; - DEFINE_WAIT(wait); - - if (count < 4) - return 0; - - prepare_to_wait(&err_wait_q, &wait, TASK_INTERRUPTIBLE); - if (errcnt == 0) - schedule(); - finish_wait(&err_wait_q, &wait); - if (signal_pending(current)) - return -EINTR; - - local_irq_save(flags); - status = copy_to_user(buf, &errval, 4); - if (status) { - local_irq_restore(flags); - return -EFAULT; - } - errcnt = 0; - local_irq_restore(flags); - - return 4; -} - -static unsigned int dsp_err_poll(struct file *file, poll_table *wait) -{ - unsigned int mask = 0; - - poll_wait(file, &err_wait_q, wait); - if (errcnt != 0) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -struct file_operations dsp_err_fops = { - .owner = THIS_MODULE, - .poll = dsp_err_poll, - .read = dsp_err_read, -}; - -/* - * set / clear functions - */ - -/* DSP MMU */ -static void dsp_err_mmu_set(unsigned long arg) -{ - disable_irq(omap_dsp->mmu->irq); - mmu_fadr = (u32)arg; -} - -static void dsp_err_mmu_clr(void) -{ - enable_irq(omap_dsp->mmu->irq); -} - -/* WDT */ -static void dsp_err_wdt_set(unsigned long arg) -{ - wdtval = (u16)arg; -} - -/* - * error code handler - */ -static struct { - unsigned long val; - void (*set)(unsigned long arg); - void (*clr)(void); -} dsp_err_desc[ERRCODE_MAX] = { - [ERRCODE_MMU] = { DSP_ERR_MMU, dsp_err_mmu_set, dsp_err_mmu_clr }, - [ERRCODE_WDT] = { DSP_ERR_WDT, dsp_err_wdt_set, NULL }, -}; - -void dsp_err_set(enum errcode_e code, unsigned long arg) -{ - if (dsp_err_desc[code].set != NULL) - dsp_err_desc[code].set(arg); - - errval |= dsp_err_desc[code].val; - errcnt++; - wake_up_interruptible(&err_wait_q); -} - -void dsp_err_clear(enum errcode_e code) -{ - errval &= ~dsp_err_desc[code].val; - - if (dsp_err_desc[code].clr != NULL) - dsp_err_desc[code].clr(); -} - -int dsp_err_isset(enum errcode_e code) -{ - return (errval & dsp_err_desc[code].val) ? 1 : 0; -} - -void dsp_err_notify(void) -{ - /* new error code should be assigned */ - dsp_err_set(DSP_ERR_WDT, 0); -} - -/* - * functions called from mailbox interrupt routine - */ -static void mbox_err_wdt(u16 data) -{ - dsp_err_set(DSP_ERR_WDT, (unsigned long)data); -} - -#ifdef OLD_BINARY_SUPPORT -/* v3.3 obsolete */ -void mbox_wdt(struct mbcmd *mb) -{ - mbox_err_wdt(mb->data); -} -#endif - -extern void mbox_err_ipbfull(void); -extern void mbox_err_fatal(u8 tid); - -void mbox_err(struct mbcmd *mb) -{ - u8 eid = mb->cmd_l; - char *eidnm = subcmd_name(mb); - u8 tid; - - if (eidnm) { - printk(KERN_WARNING - "mbox: ERR from DSP (%s): 0x%04x\n", eidnm, mb->data); - } else { - printk(KERN_WARNING - "mbox: ERR from DSP (unknown EID=%02x): %04x\n", - eid, mb->data); - } - - switch (eid) { - case EID_IPBFULL: - mbox_err_ipbfull(); - break; - - case EID_FATAL: - tid = mb->data & 0x00ff; - mbox_err_fatal(tid); - break; - - case EID_WDT: - mbox_err_wdt(mb->data); - break; - } -} - -/* - * - */ -void dsp_err_start(void) -{ - enum errcode_e i; - - for (i = 0; i < ERRCODE_MAX; i++) { - if (dsp_err_isset(i)) - dsp_err_clear(i); - } - omap_dsp->mbox->err_notify = dsp_err_notify; - errcnt = 0; -} - -void dsp_err_stop(void) -{ - wake_up_interruptible(&err_wait_q); - omap_dsp->mbox->err_notify = NULL; -} diff --git a/drivers/dsp/dspgateway/hardware_dsp.h b/drivers/dsp/dspgateway/hardware_dsp.h deleted file mode 100644 index 5af46f8b241..00000000000 --- a/drivers/dsp/dspgateway/hardware_dsp.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_DSP_HARDWARE_DSP_H -#define __OMAP_DSP_HARDWARE_DSP_H - -#ifdef CONFIG_ARCH_OMAP1 -#include "omap1_dsp.h" -#endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3430) -#include "omap2_dsp.h" -#endif - -#endif /* __OMAP_DSP_HARDWARE_DSP_H */ diff --git a/drivers/dsp/dspgateway/ipbuf.c b/drivers/dsp/dspgateway/ipbuf.c deleted file mode 100644 index b05ba070777..00000000000 --- a/drivers/dsp/dspgateway/ipbuf.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" -#include "ipbuf.h" - -static struct ipbuf_head *g_ipbuf; -struct ipbcfg ipbcfg; -struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad; -static struct ipblink ipb_free = IPBLINK_INIT; -static int ipbuf_sys_hold_mem_active; - -static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr, - char *buf); -static struct device_attribute dev_attr_ipbuf = __ATTR_RO(ipbuf); - -void ipbuf_stop(void) -{ - int i; - - device_remove_file(omap_dsp->dev, &dev_attr_ipbuf); - - spin_lock(&ipb_free.lock); - RESET_IPBLINK(&ipb_free); - spin_unlock(&ipb_free.lock); - - ipbcfg.ln = 0; - if (g_ipbuf) { - kfree(g_ipbuf); - g_ipbuf = NULL; - } - for (i = 0; i < ipbuf_sys_hold_mem_active; i++) { - dsp_mem_disable((void *)daram_base); - } - ipbuf_sys_hold_mem_active = 0; -} - -int ipbuf_config(u16 ln, u16 lsz, void *base) -{ - size_t lsz_byte = ((size_t)lsz) << 1; - size_t size; - int ret = 0; - int i; - - /* - * global IPBUF - */ - if (((unsigned long)base) & 0x3) { - printk(KERN_ERR - "omapdsp: global ipbuf address(0x%p) is not " - "32-bit aligned!\n", base); - return -EINVAL; - } - size = lsz_byte * ln; - if (dsp_address_validate(base, size, "global ipbuf") < 0) - return -EINVAL; - - g_ipbuf = kmalloc(sizeof(struct ipbuf_head) * ln, GFP_KERNEL); - if (g_ipbuf == NULL) { - printk(KERN_ERR - "omapdsp: memory allocation for ipbuf failed.\n"); - return -ENOMEM; - } - for (i = 0; i < ln; i++) { - void *top, *btm; - - top = base + (sizeof(struct ipbuf) + lsz_byte) * i; - btm = base + (sizeof(struct ipbuf) + lsz_byte) * (i+1) - 1; - g_ipbuf[i].p = (struct ipbuf *)top; - g_ipbuf[i].bid = i; - if (((unsigned long)top & 0xfffe0000) != - ((unsigned long)btm & 0xfffe0000)) { - /* - * an ipbuf line should not cross - * 64k-word boundary. - */ - printk(KERN_ERR - "omapdsp: ipbuf[%d] crosses 64k-word boundary!\n" - " @0x%p, size=0x%08x\n", i, top, lsz_byte); - ret = -EINVAL; - goto free_out; - } - } - ipbcfg.ln = ln; - ipbcfg.lsz = lsz; - ipbcfg.base = base; - ipbcfg.bsycnt = ln; /* DSP holds all ipbufs initially. */ - ipbcfg.cnt_full = 0; - - pr_info("omapdsp: IPBUF configuration\n" - " %d words * %d lines at 0x%p.\n", - ipbcfg.lsz, ipbcfg.ln, ipbcfg.base); - - ret = device_create_file(omap_dsp->dev, &dev_attr_ipbuf); - if (ret) - printk(KERN_ERR "device_create_file failed: %d\n", ret); - - return ret; - - free_out: - kfree(g_ipbuf); - g_ipbuf = NULL; - return ret; -} - -int ipbuf_sys_config(void *p, arm_dsp_dir_t dir) -{ - char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D"; - - if (((unsigned long)p) & 0x3) { - printk(KERN_ERR - "omapdsp: system ipbuf(%s) address(0x%p) is " - "not 32-bit aligned!\n", dir_str, p); - return -1; - } - if (dsp_address_validate(p, sizeof(struct ipbuf_sys), - "system ipbuf(%s)", dir_str) < 0) - return -1; - if (dsp_mem_type(p, sizeof(struct ipbuf_sys)) != MEM_TYPE_EXTERN) { - printk(KERN_WARNING - "omapdsp: system ipbuf(%s) is placed in" - " DSP internal memory.\n" - " It will prevent DSP from idling.\n", dir_str); - ipbuf_sys_hold_mem_active++; - /* - * dsp_mem_enable() never fails because - * it has been already enabled in dspcfg process and - * this will just increment the usecount. - */ - dsp_mem_enable((void *)daram_base); - } - - if (dir == DIR_D2A) - ipbuf_sys_da = p; - else - ipbuf_sys_ad = p; - - return 0; -} - -int ipbuf_p_validate(void *p, arm_dsp_dir_t dir) -{ - char *dir_str = (dir == DIR_D2A) ? "D2A" : "A2D"; - - if (((unsigned long)p) & 0x3) { - printk(KERN_ERR - "omapdsp: private ipbuf(%s) address(0x%p) is " - "not 32-bit aligned!\n", dir_str, p); - return -1; - } - return dsp_address_validate(p, sizeof(struct ipbuf_p), - "private ipbuf(%s)", dir_str); -} - -/* - * Global IPBUF operations - */ -struct ipbuf_head *bid_to_ipbuf(u16 bid) -{ - return &g_ipbuf[bid]; -} - -struct ipbuf_head *get_free_ipbuf(u8 tid) -{ - struct ipbuf_head *ipb_h; - - if (dsp_mem_enable_ipbuf() < 0) - return NULL; - - spin_lock(&ipb_free.lock); - - if (ipblink_empty(&ipb_free)) { - /* FIXME: wait on queue when not available. */ - ipb_h = NULL; - goto out; - } - ipb_h = &g_ipbuf[ipb_free.top]; - ipb_h->p->la = tid; /* lock */ - __ipblink_del_top(&ipb_free); -out: - spin_unlock(&ipb_free.lock); - dsp_mem_disable_ipbuf(); - - return ipb_h; -} - -void release_ipbuf(struct ipbuf_head *ipb_h) -{ - if (ipb_h->p->la == TID_FREE) { - printk(KERN_WARNING - "omapdsp: attempt to release unlocked IPBUF[%d].\n", - ipb_h->bid); - /* - * FIXME: re-calc bsycnt - */ - return; - } - ipb_h->p->la = TID_FREE; - ipb_h->p->sa = TID_FREE; - ipblink_add_tail(&ipb_free, ipb_h->bid); -} - -static int try_yld(struct ipbuf_head *ipb_h) -{ - int status; - - ipb_h->p->sa = TID_ANON; - status = mbcompose_send(BKYLD, 0, ipb_h->bid); - if (status < 0) { - /* DSP is busy and ARM keeps this line. */ - release_ipbuf(ipb_h); - return status; - } - - ipb_bsycnt_inc(&ipbcfg); - return 0; -} - -/* - * balancing ipbuf lines with DSP - */ -static void do_balance_ipbuf(struct work_struct *unused) -{ - while (ipbcfg.bsycnt <= ipbcfg.ln / 4) { - struct ipbuf_head *ipb_h; - - if ((ipb_h = get_free_ipbuf(TID_ANON)) == NULL) - return; - if (try_yld(ipb_h) < 0) - return; - } -} - -static DECLARE_WORK(balance_ipbuf_work, do_balance_ipbuf); - -void balance_ipbuf(void) -{ - schedule_work(&balance_ipbuf_work); -} - -/* for process context */ -void unuse_ipbuf(struct ipbuf_head *ipb_h) -{ - if (ipbcfg.bsycnt > ipbcfg.ln / 4) { - /* we don't have enough IPBUF lines. let's keep it. */ - release_ipbuf(ipb_h); - } else { - /* we have enough IPBUF lines. let's return this line to DSP. */ - ipb_h->p->la = TID_ANON; - try_yld(ipb_h); - balance_ipbuf(); - } -} - -/* for interrupt context */ -void unuse_ipbuf_nowait(struct ipbuf_head *ipb_h) -{ - release_ipbuf(ipb_h); - balance_ipbuf(); -} - -/* - * functions called from mailbox interrupt routine - */ - -void mbox_err_ipbfull(void) -{ - ipbcfg.cnt_full++; -} - -/* - * sysfs files - */ -static ssize_t ipbuf_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int len = 0; - u16 bid; - - for (bid = 0; bid < ipbcfg.ln; bid++) { - struct ipbuf_head *ipb_h = &g_ipbuf[bid]; - u16 la = ipb_h->p->la; - u16 ld = ipb_h->p->ld; - u16 c = ipb_h->p->c; - - if (len > PAGE_SIZE - 100) { - len += sprintf(buf + len, "out of buffer.\n"); - goto finish; - } - - len += sprintf(buf + len, "ipbuf[%d]: adr = 0x%p\n", - bid, ipb_h->p); - if (la == TID_FREE) { - len += sprintf(buf + len, - " DSPtask[%d]->Linux " - "(already read and now free for Linux)\n", - ld); - } else if (ld == TID_FREE) { - len += sprintf(buf + len, - " Linux->DSPtask[%d] " - "(already read and now free for DSP)\n", - la); - } else if (ipbuf_is_held(ld, bid)) { - len += sprintf(buf + len, - " DSPtask[%d]->Linux " - "(waiting to be read)\n" - " count = %d\n", ld, c); - } else { - len += sprintf(buf + len, - " Linux->DSPtask[%d] " - "(waiting to be read)\n" - " count = %d\n", la, c); - } - } - - len += sprintf(buf + len, "\nFree IPBUF link: "); - spin_lock(&ipb_free.lock); - ipblink_for_each(bid, &ipb_free) { - len += sprintf(buf + len, "%d ", bid); - } - spin_unlock(&ipb_free.lock); - len += sprintf(buf + len, "\n"); - len += sprintf(buf + len, "IPBFULL error count: %ld\n", - ipbcfg.cnt_full); - -finish: - return len; -} diff --git a/drivers/dsp/dspgateway/ipbuf.h b/drivers/dsp/dspgateway/ipbuf.h deleted file mode 100644 index 926d3534f59..00000000000 --- a/drivers/dsp/dspgateway/ipbuf.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __PLAT_OMAP_DSP_IPBUF_H -#define __PLAT_OMAP_DSP_IPBUF_H - -struct ipbuf { - u16 c; /* count */ - u16 next; /* link */ - u16 la; /* lock owner (ARM side) */ - u16 sa; /* sync word (ARM->DSP) */ - u16 ld; /* lock owner (DSP side) */ - u16 sd; /* sync word (DSP->ARM) */ - unsigned char d[0]; /* data */ -}; - -struct ipbuf_p { - u16 c; /* count */ - u16 s; /* sync word */ - u16 al; /* data address lower */ - u16 ah; /* data address upper */ -}; - -#define IPBUF_SYS_DLEN 31 - -struct ipbuf_sys { - u16 s; /* sync word */ - u16 d[IPBUF_SYS_DLEN]; /* data */ -}; - -struct ipbcfg { - u16 ln; - u16 lsz; - void *base; - u16 bsycnt; - unsigned long cnt_full; /* count of IPBFULL error */ -}; - -struct ipbuf_head { - u16 bid; - struct ipbuf *p; -}; - -extern struct ipbcfg ipbcfg; -extern struct ipbuf_sys *ipbuf_sys_da, *ipbuf_sys_ad; - -#define ipb_bsycnt_inc(ipbcfg) atomic_inc((atomic_t *)&((ipbcfg)->bsycnt)) -#define ipb_bsycnt_dec(ipbcfg) atomic_dec((atomic_t *)&((ipbcfg)->bsycnt)) - -#define dsp_mem_enable_ipbuf() dsp_mem_enable(ipbcfg.base) -#define dsp_mem_disable_ipbuf() dsp_mem_disable(ipbcfg.base) - -struct ipblink { - spinlock_t lock; - u16 top; - u16 tail; -}; - -#define IPBLINK_INIT { \ - .lock = SPIN_LOCK_UNLOCKED, \ - .top = BID_NULL, \ - .tail = BID_NULL, \ - } - -#define INIT_IPBLINK(link) \ - do { \ - spin_lock_init(&(link)->lock); \ - (link)->top = BID_NULL; \ - (link)->tail = BID_NULL; \ - } while(0) - -#define RESET_IPBLINK(link) \ - do { \ - (link)->top = BID_NULL; \ - (link)->tail = BID_NULL; \ - } while(0) - -#define ipblink_empty(link) ((link)->top == BID_NULL) - -static inline void __ipblink_del_top(struct ipblink *link) -{ - struct ipbuf_head *ipb_h = bid_to_ipbuf(link->top); - - if ((link->top = ipb_h->p->next) == BID_NULL) - link->tail = BID_NULL; - else - ipb_h->p->next = BID_NULL; -} - -static inline void ipblink_del_top(struct ipblink *link) -{ - spin_lock(&link->lock); - __ipblink_del_top(link); - spin_unlock(&link->lock); -} - -static inline void __ipblink_add_tail(struct ipblink *link, u16 bid) -{ - if (ipblink_empty(link)) - link->top = bid; - else - bid_to_ipbuf(link->tail)->p->next = bid; - link->tail = bid; -} - -static inline void ipblink_add_tail(struct ipblink *link, u16 bid) -{ - spin_lock(&link->lock); - __ipblink_add_tail(link, bid); - spin_unlock(&link->lock); -} - -static inline void __ipblink_flush(struct ipblink *link) -{ - u16 bid; - - while (!ipblink_empty(link)) { - bid = link->top; - __ipblink_del_top(link); - unuse_ipbuf(bid_to_ipbuf(bid)); - } -} - -static inline void ipblink_flush(struct ipblink *link) -{ - spin_lock(&link->lock); - __ipblink_flush(link); - spin_unlock(&link->lock); -} - -static inline void __ipblink_add_pvt(struct ipblink *link) -{ - link->top = BID_PVT; - link->tail = BID_PVT; -} - -static inline void ipblink_add_pvt(struct ipblink *link) -{ - spin_lock(&link->lock); - __ipblink_add_pvt(link); - spin_unlock(&link->lock); -} - -static inline void __ipblink_del_pvt(struct ipblink *link) -{ - link->top = BID_NULL; - link->tail = BID_NULL; -} - -static inline void ipblink_del_pvt(struct ipblink *link) -{ - spin_lock(&link->lock); - __ipblink_del_pvt(link); - spin_unlock(&link->lock); -} - -static inline void __ipblink_flush_pvt(struct ipblink *link) -{ - if (!ipblink_empty(link)) - ipblink_del_pvt(link); -} - -static inline void ipblink_flush_pvt(struct ipblink *link) -{ - spin_lock(&link->lock); - __ipblink_flush_pvt(link); - spin_unlock(&link->lock); -} - -#define ipblink_for_each(bid, link) \ - for (bid = (link)->top; bid != BID_NULL; bid = bid_to_ipbuf(bid)->p->next) - -#endif /* __PLAT_OMAP_DSP_IPBUF_H */ diff --git a/drivers/dsp/dspgateway/mblog.c b/drivers/dsp/dspgateway/mblog.c deleted file mode 100644 index 7e008afb6c9..00000000000 --- a/drivers/dsp/dspgateway/mblog.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2003-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" - -char *subcmd_name(struct mbcmd *mb) -{ - u8 cmd_h = mb->cmd_h; - u8 cmd_l = mb->cmd_l; - char *s; - - switch (cmd_h) { - case MBOX_CMD_DSP_RUNLEVEL: - s = (cmd_l == RUNLEVEL_USER) ? "USER": - (cmd_l == RUNLEVEL_SUPER) ? "SUPER": - (cmd_l == RUNLEVEL_RECOVERY) ? "RECOVERY": - NULL; - break; - case MBOX_CMD_DSP_PM: - s = (cmd_l == PM_DISABLE) ? "DISABLE": - (cmd_l == PM_ENABLE) ? "ENABLE": - NULL; - break; - case MBOX_CMD_DSP_KFUNC: - s = (cmd_l == KFUNC_FBCTL) ? "FBCTL": - (cmd_l == KFUNC_POWER) ? - ((mb->data == AUDIO_PWR_UP) ? "PWR AUD /UP": - (mb->data == AUDIO_PWR_DOWN) ? "PWR AUD /DOWN": - (mb->data == AUDIO_PWR_DOWN2) ? "PWR AUD /DOWN(2)": - (mb->data == DSP_PWR_UP) ? "PWR DSP /UP": - (mb->data == DSP_PWR_DOWN) ? "PWR DSP /DOWN": - (mb->data == DVFS_START) ? "PWR DVFS/START": - (mb->data == DVFS_STOP) ? "PWR DVFS/STOP": - NULL): - - NULL; - break; - case MBOX_CMD_DSP_DSPCFG: - { - u8 cfgc = cmd_l & 0x7f; - s = (cfgc == DSPCFG_REQ) ? "REQ": - (cfgc == DSPCFG_SYSADRH) ? "SYSADRH": - (cfgc == DSPCFG_SYSADRL) ? "SYSADRL": - (cfgc == DSPCFG_ABORT) ? "ABORT": - (cfgc == DSPCFG_PROTREV) ? "PROTREV": - NULL; - break; - } - case MBOX_CMD_DSP_REGRW: - s = (cmd_l == REGRW_MEMR) ? "MEMR": - (cmd_l == REGRW_MEMW) ? "MEMW": - (cmd_l == REGRW_IOR) ? "IOR": - (cmd_l == REGRW_IOW) ? "IOW": - (cmd_l == REGRW_DATA) ? "DATA": - NULL; - break; - case MBOX_CMD_DSP_GETVAR: - case MBOX_CMD_DSP_SETVAR: - s = (cmd_l == VARID_ICRMASK) ? "ICRMASK": - (cmd_l == VARID_LOADINFO) ? "LOADINFO": - NULL; - break; - case MBOX_CMD_DSP_ERR: - s = (cmd_l == EID_BADTID) ? "BADTID": - (cmd_l == EID_BADTCN) ? "BADTCN": - (cmd_l == EID_BADBID) ? "BADBID": - (cmd_l == EID_BADCNT) ? "BADCNT": - (cmd_l == EID_NOTLOCKED) ? "NOTLOCKED": - (cmd_l == EID_STVBUF) ? "STVBUF": - (cmd_l == EID_BADADR) ? "BADADR": - (cmd_l == EID_BADTCTL) ? "BADTCTL": - (cmd_l == EID_BADPARAM) ? "BADPARAM": - (cmd_l == EID_FATAL) ? "FATAL": - (cmd_l == EID_WDT) ? "WDT": - (cmd_l == EID_NOMEM) ? "NOMEM": - (cmd_l == EID_NORES) ? "NORES": - (cmd_l == EID_IPBFULL) ? "IPBFULL": - (cmd_l == EID_TASKNOTRDY) ? "TASKNOTRDY": - (cmd_l == EID_TASKBSY) ? "TASKBSY": - (cmd_l == EID_TASKERR) ? "TASKERR": - (cmd_l == EID_BADCFGTYP) ? "BADCFGTYP": - (cmd_l == EID_DEBUG) ? "DEBUG": - (cmd_l == EID_BADSEQ) ? "BADSEQ": - (cmd_l == EID_BADCMD) ? "BADCMD": - NULL; - break; - default: - s = NULL; - } - - return s; -} - -/* output of show() method should fit to PAGE_SIZE */ -#define MBLOG_DEPTH 64 - -struct mblogent { - unsigned long jiffies; - mbox_msg_t msg; - arm_dsp_dir_t dir; -}; - -static struct { - spinlock_t lock; - int wp; - unsigned long cnt, cnt_ad, cnt_da; - struct mblogent ent[MBLOG_DEPTH]; -} mblog = { - .lock = SPIN_LOCK_UNLOCKED, -}; - -#ifdef CONFIG_OMAP_DSP_MBCMD_VERBOSE -static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) -{ - const struct cmdinfo *ci = cmdinfo[mb->cmd_h]; - char *dir_str; - char *subname; - - dir_str = (dir == DIR_A2D) ? "sending " : "receiving"; - switch (ci->cmd_l_type) { - case CMD_L_TYPE_SUBCMD: - subname = subcmd_name(mb); - if (unlikely(!subname)) - subname = "Unknown"; - pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:%s), data=%04x\n", - dir_str, mb->seq, mb->cmd_h, mb->cmd_l, - ci->name, subname, mb->data); - break; - case CMD_L_TYPE_TID: - pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s:task %d), data=%04x\n", - dir_str, mb->seq, mb->cmd_h, mb->cmd_l, - ci->name, mb->cmd_l, mb->data); - break; - case CMD_L_TYPE_NULL: - pr_debug("mbox: %s seq=%d, cmd=%02x:%02x(%s), data=%04x\n", - dir_str, mb->seq, mb->cmd_h, mb->cmd_l, - ci->name, mb->data); - break; - } -} -#else -static inline void mblog_print_cmd(struct mbcmd *mb, arm_dsp_dir_t dir) { } -#endif - -void mblog_add(struct mbcmd *mb, arm_dsp_dir_t dir) -{ - struct mblogent *ent; - - spin_lock(&mblog.lock); - ent = &mblog.ent[mblog.wp]; - ent->jiffies = jiffies; - ent->msg = *(mbox_msg_t *)mb; - ent->dir = dir; - if (mblog.cnt < 0xffffffff) - mblog.cnt++; - switch (dir) { - case DIR_A2D: - if (mblog.cnt_ad < 0xffffffff) - mblog.cnt_ad++; - break; - case DIR_D2A: - if (mblog.cnt_da < 0xffffffff) - mblog.cnt_da++; - break; - } - if (++mblog.wp == MBLOG_DEPTH) - mblog.wp = 0; - spin_unlock(&mblog.lock); - - mblog_print_cmd(mb, dir); -} - -/* - * sysfs file - */ -static ssize_t mblog_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int len = 0; - int wp; - int i; - - spin_lock(&mblog.lock); - - wp = mblog.wp; - len += sprintf(buf + len, - "log count:%ld / ARM->DSP:%ld, DSP->ARM:%ld\n", - mblog.cnt, mblog.cnt_ad, mblog.cnt_da); - if (mblog.cnt == 0) - goto done; - - len += sprintf(buf + len, " ARM->DSP ARM<-DSP\n"); - len += sprintf(buf + len, " jiffies cmd data cmd data\n"); - i = (mblog.cnt >= MBLOG_DEPTH) ? wp : 0; - do { - struct mblogent *ent = &mblog.ent[i]; - struct mbcmd *mb = (struct mbcmd *)&ent->msg; - char *subname; - struct cmdinfo ci_null = { - .name = "Unknown", - .cmd_l_type = CMD_L_TYPE_NULL, - }; - const struct cmdinfo *ci; - - len += sprintf(buf + len, - (ent->dir == DIR_A2D) ? - "%08lx %04x %04x ": - "%08lx %04x %04x ", - ent->jiffies, - (ent->msg >> 16) & 0x7fff, ent->msg & 0xffff); - - if ((ci = cmdinfo[mb->cmd_h]) == NULL) - ci = &ci_null; - - switch (ci->cmd_l_type) { - case CMD_L_TYPE_SUBCMD: - if ((subname = subcmd_name(mb)) == NULL) - subname = "Unknown"; - len += sprintf(buf + len, "%s:%s\n", - ci->name, subname); - break; - case CMD_L_TYPE_TID: - len += sprintf(buf + len, "%s:task %d\n", - ci->name, mb->cmd_l); - break; - case CMD_L_TYPE_NULL: - len += sprintf(buf + len, "%s\n", ci->name); - break; - } - - if (++i == MBLOG_DEPTH) - i = 0; - } while (i != wp); - -done: - spin_unlock(&mblog.lock); - - return len; -} - -static struct device_attribute dev_attr_mblog = __ATTR_RO(mblog); - -void __init mblog_init(void) -{ - int ret; - - ret = device_create_file(omap_dsp->dev, &dev_attr_mblog); - if (ret) - printk(KERN_ERR "device_create_file failed: %d\n", ret); -} - -void mblog_exit(void) -{ - device_remove_file(omap_dsp->dev, &dev_attr_mblog); -} diff --git a/drivers/dsp/dspgateway/mmu.h b/drivers/dsp/dspgateway/mmu.h deleted file mode 100644 index 9d60e9e76b8..00000000000 --- a/drivers/dsp/dspgateway/mmu.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __PLAT_OMAP_DSP_MMU_H -#define __PLAT_OMAP_DSP_MMU_H - -#ifdef CONFIG_ARCH_OMAP1 - -#ifdef CONFIG_ARCH_OMAP15XX -struct omap_mmu dsp_mmu = { - .name = "mmu:dsp", - .type = OMAP_MMU_DSP, - .base = IO_ADDRESS(OMAP1510_DSP_MMU_BASE), - .membase = OMAP1510_DSP_BASE, - .memsize = OMAP1510_DSP_SIZE, - .nr_tlb_entries = 32, - .addrspace = 24, - .irq = INT_1510_DSP_MMU, - .ops = &omap1_mmu_ops, -}; -#endif -#ifdef CONFIG_ARCH_OMAP16XX -struct omap_mmu dsp_mmu = { - .name = "mmu:dsp", - .type = OMAP_MMU_DSP, - .base = IO_ADDRESS(OMAP16XX_DSP_MMU_BASE), - .membase = OMAP16XX_DSP_BASE, - .memsize = OMAP16XX_DSP_SIZE, - .nr_tlb_entries = 32, - .addrspace = 24, - .irq = INT_1610_DSP_MMU, - .ops = &omap1_mmu_ops, -}; -#endif -#else /* OMAP2 */ -struct omap_mmu dsp_mmu = { - .name = "mmu:dsp", - .type = OMAP_MMU_DSP, - .base = DSP_MMU_24XX_VIRT, - .membase = DSP_MEM_24XX_VIRT, - .memsize = DSP_MEM_24XX_SIZE, - .nr_tlb_entries = 32, - .addrspace = 24, - .irq = INT_24XX_DSP_MMU, - .ops = &omap2_mmu_ops, -}; - -#define IOMAP_VAL 0x3f -#endif - -#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL -static struct omapfb_notifier_block *omapfb_nb; -static int omapfb_ready; -#endif - -/* - * OMAP1 EMIFF access - */ -#ifdef CONFIG_ARCH_OMAP1 -#define EMIF_PRIO_LB_MASK 0x0000f000 -#define EMIF_PRIO_LB_SHIFT 12 -#define EMIF_PRIO_DMA_MASK 0x00000f00 -#define EMIF_PRIO_DMA_SHIFT 8 -#define EMIF_PRIO_DSP_MASK 0x00000070 -#define EMIF_PRIO_DSP_SHIFT 4 -#define EMIF_PRIO_MPU_MASK 0x00000007 -#define EMIF_PRIO_MPU_SHIFT 0 -#define set_emiff_dma_prio(prio) \ - do { \ - omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \ - ~EMIF_PRIO_DMA_MASK) | \ - ((prio) << EMIF_PRIO_DMA_SHIFT), \ - OMAP_TC_OCPT1_PRIOR); \ - } while(0) -#else -#define set_emiff_dma_prio(prio) do { } while (0) -#endif /* CONFIG_ARCH_OMAP1 */ - -#ifdef CONFIG_ARCH_OMAP1 -static int dsp_mmu_itack(void) -{ - unsigned long dspadr; - - pr_info("omapdsp: sending DSP MMU interrupt ack.\n"); - if (!dsp_err_isset(ERRCODE_MMU)) { - printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n"); - return -EINVAL; - } - dspadr = dsp_mmu.fault_address & ~(SZ_4K-1); - /* FIXME: reserve TLB entry for this */ - omap_mmu_exmap(&dsp_mmu, dspadr, 0, SZ_4K, EXMAP_TYPE_MEM); - pr_info("omapdsp: falling into recovery runlevel...\n"); - dsp_set_runlevel(RUNLEVEL_RECOVERY); - omap_mmu_itack(&dsp_mmu); - udelay(100); - omap_mmu_exunmap(&dsp_mmu, dspadr); - dsp_err_clear(ERRCODE_MMU); - return 0; -} - -/* - * intmem_enable() / disable(): - * if the address is in DSP internal memories, - * we send PM mailbox commands so that DSP DMA domain won't go in idle - * when ARM is accessing to those memories. - */ -static int intmem_enable(void) -{ - int ret = 0; - - if (dsp_cfgstat_get_stat() == CFGSTAT_READY) - ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA); - - return ret; -} - -static void intmem_disable(void) { - if (dsp_cfgstat_get_stat() == CFGSTAT_READY) - mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA); -} -#else -static int intmem_enable(void) { return 0; } -static void intmem_disable(void) { } -static int dsp_mmu_itack(void) { return 0; } -#endif - -#ifdef CONFIG_ARCH_OMAP2 -static inline void dsp_mem_ipi_init(void) -{ - int i, dspmem_pg_count; - dspmem_pg_count = dspmem_size >> 12; - for (i = 0; i < dspmem_pg_count; i++) { - writel(i, DSP_IPI_INDEX); - writel(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY); - } - writel(1, DSP_IPI_ENABLE); - writel(IOMAP_VAL, DSP_IPI_IOMAP); -} -#else -static inline void dsp_mem_ipi_init(void) { } -#endif - -#endif /* __PLAT_OMAP_DSP_MMU_H */ diff --git a/drivers/dsp/dspgateway/omap1_dsp.h b/drivers/dsp/dspgateway/omap1_dsp.h deleted file mode 100644 index f4ec73eb19a..00000000000 --- a/drivers/dsp/dspgateway/omap1_dsp.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_DSP_OMAP1_DSP_H -#define __OMAP_DSP_OMAP1_DSP_H - -#ifdef CONFIG_ARCH_OMAP15XX -#define OMAP1510_DARAM_BASE (OMAP1510_DSP_BASE + 0x0) -#define OMAP1510_DARAM_SIZE 0x10000 -#define OMAP1510_SARAM_BASE (OMAP1510_DSP_BASE + 0x10000) -#define OMAP1510_SARAM_SIZE 0x18000 -#endif - -#ifdef CONFIG_ARCH_OMAP16XX -#define OMAP16XX_DARAM_BASE (OMAP16XX_DSP_BASE + 0x0) -#define OMAP16XX_DARAM_SIZE 0x10000 -#define OMAP16XX_SARAM_BASE (OMAP16XX_DSP_BASE + 0x10000) -#define OMAP16XX_SARAM_SIZE 0x18000 -#endif - -/* - * Reset Control - */ -#define ARM_RSTCT1_SW_RST 0x0008 -#define ARM_RSTCT1_DSP_RST 0x0004 -#define ARM_RSTCT1_DSP_EN 0x0002 -#define ARM_RSTCT1_ARM_RST 0x0001 - -/* - * MPUI - */ -#define MPUI_CTRL_WORDSWAP_MASK 0x00600000 -#define MPUI_CTRL_WORDSWAP_ALL 0x00000000 -#define MPUI_CTRL_WORDSWAP_NONAPI 0x00200000 -#define MPUI_CTRL_WORDSWAP_API 0x00400000 -#define MPUI_CTRL_WORDSWAP_NONE 0x00600000 -#define MPUI_CTRL_AP_MASK 0x001c0000 -#define MPUI_CTRL_AP_MDH 0x00000000 -#define MPUI_CTRL_AP_MHD 0x00040000 -#define MPUI_CTRL_AP_DMH 0x00080000 -#define MPUI_CTRL_AP_HMD 0x000c0000 -#define MPUI_CTRL_AP_DHM 0x00100000 -#define MPUI_CTRL_AP_HDM 0x00140000 -#define MPUI_CTRL_BYTESWAP_MASK 0x00030000 -#define MPUI_CTRL_BYTESWAP_NONE 0x00000000 -#define MPUI_CTRL_BYTESWAP_NONAPI 0x00010000 -#define MPUI_CTRL_BYTESWAP_ALL 0x00020000 -#define MPUI_CTRL_BYTESWAP_API 0x00030000 -#define MPUI_CTRL_TIMEOUT_MASK 0x0000ff00 -#define MPUI_CTRL_APIF_HNSTB_DIV_MASK 0x000000f0 -#define MPUI_CTRL_S_NABORT_GL 0x00000008 -#define MPUI_CTRL_S_NABORT_32BIT 0x00000004 -#define MPUI_CTRL_EN_TIMEOUT 0x00000002 -#define MPUI_CTRL_HF_MCUCLK 0x00000001 -#define DSP_BOOT_CONFIG_DIRECT 0x00000000 -#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001 -#define DSP_BOOT_CONFIG_IDLE 0x00000002 -#define DSP_BOOT_CONFIG_DL16 0x00000003 -#define DSP_BOOT_CONFIG_DL32 0x00000004 -#define DSP_BOOT_CONFIG_MPUI 0x00000005 -#define DSP_BOOT_CONFIG_INTERNAL 0x00000006 - -/* - * DSP boot mode - * direct: 0xffff00 - * pseudo direct: 0x080000 - * MPUI: branch 0x010000 - * internel: branch 0x024000 - */ -#define DSP_BOOT_ADR_DIRECT 0xffff00 -#define DSP_BOOT_ADR_PSD_DIRECT 0x080000 -#define DSP_BOOT_ADR_MPUI 0x010000 -#define DSP_BOOT_ADR_INTERNAL 0x024000 - -/* - * TC - */ -#define TC_ENDIANISM_SWAP 0x00000002 -#define TC_ENDIANISM_SWAP_WORD 0x00000002 -#define TC_ENDIANISM_SWAP_BYTE 0x00000000 -#define TC_ENDIANISM_EN 0x00000001 - -/* - * DSP ICR - */ -#define DSPREG_ICR_RESERVED_BITS 0xffc0 -#define DSPREG_ICR_EMIF 0x0020 -#define DSPREG_ICR_DPLL 0x0010 -#define DSPREG_ICR_PER 0x0008 -#define DSPREG_ICR_CACHE 0x0004 -#define DSPREG_ICR_DMA 0x0002 -#define DSPREG_ICR_CPU 0x0001 - -#endif /* __OMAP_DSP_OMAP1_DSP_H */ diff --git a/drivers/dsp/dspgateway/omap2_dsp.h b/drivers/dsp/dspgateway/omap2_dsp.h deleted file mode 100644 index 4ac51806eeb..00000000000 --- a/drivers/dsp/dspgateway/omap2_dsp.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __OMAP_DSP_OMAP2_DSP_H -#define __OMAP_DSP_OMAP2_DSP_H - -#ifdef CONFIG_ARCH_OMAP24XX -#define OMAP24XX_DARAM_BASE (DSP_MEM_24XX_VIRT + 0x0) -#define OMAP24XX_DARAM_SIZE 0x10000 -#define OMAP24XX_SARAM_BASE (DSP_MEM_24XX_VIRT + 0x10000) -#define OMAP24XX_SARAM_SIZE 0x18000 -#endif - -#include - -/* - * DSP IPI registers: mapped to 0xe1000000 -- use readX(), writeX() - */ -#ifdef CONFIG_ARCH_OMAP24XX -#define DSP_IPI_BASE DSP_IPI_24XX_VIRT -#endif - -#ifdef CONFIG_ARCH_OMAP34XX -#define DSP_IPI_BASE DSP_IPI_34XX_VIRT -#endif - -#define DSP_IPI_REVISION (DSP_IPI_BASE + 0x00) -#define DSP_IPI_SYSCONFIG (DSP_IPI_BASE + 0x10) -#define DSP_IPI_INDEX (DSP_IPI_BASE + 0x40) -#define DSP_IPI_ENTRY (DSP_IPI_BASE + 0x44) -#define DSP_IPI_ENABLE (DSP_IPI_BASE + 0x48) -#define DSP_IPI_IOMAP (DSP_IPI_BASE + 0x4c) -#define DSP_IPI_DSPBOOTCONFIG (DSP_IPI_BASE + 0x50) - -#define DSP_IPI_ENTRY_ELMSIZEVALUE_MASK 0x00000003 -#define DSP_IPI_ENTRY_ELMSIZEVALUE_8 0x00000000 -#define DSP_IPI_ENTRY_ELMSIZEVALUE_16 0x00000001 -#define DSP_IPI_ENTRY_ELMSIZEVALUE_32 0x00000002 - -#define DSP_BOOT_CONFIG_DIRECT 0x00000000 -#define DSP_BOOT_CONFIG_PSD_DIRECT 0x00000001 -#define DSP_BOOT_CONFIG_IDLE 0x00000002 -#define DSP_BOOT_CONFIG_DL16 0x00000003 -#define DSP_BOOT_CONFIG_DL32 0x00000004 -#define DSP_BOOT_CONFIG_API 0x00000005 -#define DSP_BOOT_CONFIG_INTERNAL 0x00000006 - -/* - * DSP boot mode - * direct: 0xffff00 - * pseudo direct: 0x080000 - * API: branch 0x010000 - * internel: branch 0x024000 - */ -#define DSP_BOOT_ADR_DIRECT 0xffff00 -#define DSP_BOOT_ADR_PSD_DIRECT 0x080000 -#define DSP_BOOT_ADR_API 0x010000 -#define DSP_BOOT_ADR_INTERNAL 0x024000 - -/* - * DSP ICR - */ -#define DSPREG_ICR_RESERVED_BITS 0xfc00 -#define DSPREG_ICR_HWA 0x0200 -#define DSPREG_ICR_IPORT 0x0100 -#define DSPREG_ICR_MPORT 0x0080 -#define DSPREG_ICR_XPORT 0x0040 -#define DSPREG_ICR_DPORT 0x0020 -#define DSPREG_ICR_DPLL 0x0010 -#define DSPREG_ICR_PER 0x0008 -#define DSPREG_ICR_CACHE 0x0004 -#define DSPREG_ICR_DMA 0x0002 -#define DSPREG_ICR_CPU 0x0001 - -#endif /* __OMAP_DSP_OMAP2_DSP_H */ diff --git a/drivers/dsp/dspgateway/proclist.h b/drivers/dsp/dspgateway/proclist.h deleted file mode 100644 index 666ca4dd45d..00000000000 --- a/drivers/dsp/dspgateway/proclist.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __PLAT_OMAP_DSP_PROCLIST_H -#define __PLAT_OMAP_DSP_PROCLIST_H - -struct proc_list { - struct list_head list_head; - pid_t pid; - struct file *file; -}; - -static inline int proc_list_add(spinlock_t *lock, struct list_head *list, - struct task_struct *tsk, struct file *file) -{ - struct proc_list *new; - - new = kmalloc(sizeof(struct proc_list), GFP_KERNEL); - if (new == NULL) - return -ENOMEM; - new->pid = tsk->pid; - new->file = file; - spin_lock(lock); - list_add_tail(&new->list_head, list); - spin_unlock(lock); - - return 0; -} - -static inline void proc_list_del(spinlock_t *lock, struct list_head *list, - struct task_struct *tsk, struct file *file) -{ - struct proc_list *pl; - - spin_lock(lock); - list_for_each_entry(pl, list, list_head) { - if (pl->file == file) { - list_del(&pl->list_head); - kfree(pl); - spin_unlock(lock); - return; - } - } - - /* correspinding file struct isn't found in the list ??? */ - printk(KERN_ERR "proc_list_del(): proc_list is inconsistent!\n" - "struct file (%p) not found\n", file); - printk(KERN_ERR "listing proc_list...\n"); - list_for_each_entry(pl, list, list_head) - printk(KERN_ERR " pid:%d file:%p\n", pl->pid, pl->file); - spin_unlock(lock); -} - -static inline void proc_list_flush(spinlock_t *lock, struct list_head *list) -{ - struct proc_list *pl; - - spin_lock(lock); - while (!list_empty(list)) { - pl = list_entry(list->next, struct proc_list, list_head); - list_del(&pl->list_head); - kfree(pl); - } - spin_unlock(lock); -} - -#endif /* __PLAT_OMAP_DSP_PROCLIST_H */ diff --git a/drivers/dsp/dspgateway/task.c b/drivers/dsp/dspgateway/task.c deleted file mode 100644 index a371911bffa..00000000000 --- a/drivers/dsp/dspgateway/task.c +++ /dev/null @@ -1,3041 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "uaccess_dsp.h" -#include "dsp_mbcmd.h" -#include "dsp.h" -#include "ipbuf.h" -#include "proclist.h" - -/* - * devstate: task device state machine - * NOTASK: task is not attached. - * ATTACHED: task is attached. - * GARBAGE: task is detached. waiting for all processes to close this device. - * ADDREQ: requesting for tadd - * DELREQ: requesting for tdel. no process is opening this device. - * FREEZED: task is attached, but reserved to be killed. - * ADDFAIL: tadd failed. - * ADDING: tadd in process. - * DELING: tdel in process. - * KILLING: tkill in process. - */ -#define TASKDEV_ST_NOTASK 0x00000001 -#define TASKDEV_ST_ATTACHED 0x00000002 -#define TASKDEV_ST_GARBAGE 0x00000004 -#define TASKDEV_ST_INVALID 0x00000008 -#define TASKDEV_ST_ADDREQ 0x00000100 -#define TASKDEV_ST_DELREQ 0x00000200 -#define TASKDEV_ST_FREEZED 0x00000400 -#define TASKDEV_ST_ADDFAIL 0x00001000 -#define TASKDEV_ST_ADDING 0x00010000 -#define TASKDEV_ST_DELING 0x00020000 -#define TASKDEV_ST_KILLING 0x00040000 -#define TASKDEV_ST_STATE_MASK 0x7fffffff -#define TASKDEV_ST_STALE 0x80000000 - -static struct { - long state; - char *name; -} devstate_desc[] = { - { TASKDEV_ST_NOTASK, "notask" }, - { TASKDEV_ST_ATTACHED, "attached" }, - { TASKDEV_ST_GARBAGE, "garbage" }, - { TASKDEV_ST_INVALID, "invalid" }, - { TASKDEV_ST_ADDREQ, "addreq" }, - { TASKDEV_ST_DELREQ, "delreq" }, - { TASKDEV_ST_FREEZED, "freezed" }, - { TASKDEV_ST_ADDFAIL, "addfail" }, - { TASKDEV_ST_ADDING, "adding" }, - { TASKDEV_ST_DELING, "deling" }, - { TASKDEV_ST_KILLING, "killing" }, -}; - -static char *devstate_name(long state) -{ - int i; - int max = ARRAY_SIZE(devstate_desc); - - for (i = 0; i < max; i++) { - if (state & devstate_desc[i].state) - return devstate_desc[i].name; - } - return "unknown"; -} - -struct rcvdt_bk_struct { - struct ipblink link; - unsigned int rp; -}; - -struct taskdev { - struct bus_type *bus; - struct device dev; /* Generic device interface */ - - long state; - struct rw_semaphore state_sem; - wait_queue_head_t state_wait_q; - struct mutex usecount_lock; - unsigned int usecount; - char name[TNM_LEN]; - struct file_operations fops; - spinlock_t proc_list_lock; - struct list_head proc_list; - struct dsptask *task; - - /* read stuff */ - wait_queue_head_t read_wait_q; - struct mutex read_mutex; - spinlock_t read_lock; - union { - struct kfifo *fifo; /* for active word */ - struct rcvdt_bk_struct bk; - } rcvdt; - - /* write stuff */ - wait_queue_head_t write_wait_q; - struct mutex write_mutex; - spinlock_t wsz_lock; - size_t wsz; - - /* tctl stuff */ - wait_queue_head_t tctl_wait_q; - struct mutex tctl_mutex; - int tctl_stat; - int tctl_ret; /* return value for tctl_show() */ - - /* device lock */ - struct mutex lock; - pid_t lock_pid; -}; - -#define to_taskdev(n) container_of(n, struct taskdev, dev) - -struct dsptask { - enum { - TASK_ST_ERR = 0, - TASK_ST_READY, - TASK_ST_CFGREQ - } state; - u8 tid; - char name[TNM_LEN]; - u16 ttyp; - struct taskdev *dev; - - /* read stuff */ - struct ipbuf_p *ipbuf_pvt_r; - - /* write stuff */ - struct ipbuf_p *ipbuf_pvt_w; - - /* mmap stuff */ - void *map_base; - size_t map_length; -}; - -#define sndtyp_acv(ttyp) ((ttyp) & TTYP_ASND) -#define sndtyp_psv(ttyp) (!((ttyp) & TTYP_ASND)) -#define sndtyp_bk(ttyp) ((ttyp) & TTYP_BKDM) -#define sndtyp_wd(ttyp) (!((ttyp) & TTYP_BKDM)) -#define sndtyp_pvt(ttyp) ((ttyp) & TTYP_PVDM) -#define sndtyp_gbl(ttyp) (!((ttyp) & TTYP_PVDM)) -#define rcvtyp_acv(ttyp) ((ttyp) & TTYP_ARCV) -#define rcvtyp_psv(ttyp) (!((ttyp) & TTYP_ARCV)) -#define rcvtyp_bk(ttyp) ((ttyp) & TTYP_BKMD) -#define rcvtyp_wd(ttyp) (!((ttyp) & TTYP_BKMD)) -#define rcvtyp_pvt(ttyp) ((ttyp) & TTYP_PVMD) -#define rcvtyp_gbl(ttyp) (!((ttyp) & TTYP_PVMD)) - -static inline int has_taskdev_lock(struct taskdev *dev); -static int dsp_rmdev_minor(unsigned char minor); -static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor); -static void taskdev_delete(unsigned char minor); -static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task); -static int dsp_tdel_bh(struct taskdev *dev, u16 type); - -static struct bus_type dsptask_bus = { - .name = "dsptask", -}; - -static struct class *dsp_task_class; -static DEFINE_MUTEX(devmgr_lock); -static struct taskdev *taskdev[TASKDEV_MAX]; -static struct dsptask *dsptask[TASKDEV_MAX]; -static DEFINE_MUTEX(cfg_lock); -static u16 cfg_cmd; -static u8 cfg_tid; -static DECLARE_WAIT_QUEUE_HEAD(cfg_wait_q); -static u8 n_task; /* static task count */ -static void *heap; - -#define is_dynamic_task(tid) ((tid) >= n_task) - -#define devstate_read_lock(dev, devstate) \ - devstate_read_lock_timeout(dev, devstate, 0) -#define devstate_read_unlock(dev) up_read(&(dev)->state_sem) -#define devstate_write_lock(dev, devstate) \ - devstate_write_lock_timeout(dev, devstate, 0) -#define devstate_write_unlock(dev) up_write(&(dev)->state_sem) - -static ssize_t devname_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t devstate_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t proc_list_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t taskname_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t ttyp_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t fifosz_show(struct device *d, struct device_attribute *attr, - char *buf); -static int fifosz_store(struct device *d, struct device_attribute *attr, - const char *buf, size_t count); -static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t ipblink_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t wsz_show(struct device *d, struct device_attribute *attr, - char *buf); -static ssize_t mmap_show(struct device *d, struct device_attribute *attr, - char *buf); - -#define __ATTR_RW(_name,_mode) { \ - .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \ - .show = _name##_show, \ - .store = _name##_store, \ -} - -static struct device_attribute dev_attr_devname = __ATTR_RO(devname); -static struct device_attribute dev_attr_devstate = __ATTR_RO(devstate); -static struct device_attribute dev_attr_proc_list = __ATTR_RO(proc_list); -static struct device_attribute dev_attr_taskname = __ATTR_RO(taskname); -static struct device_attribute dev_attr_ttyp = __ATTR_RO(ttyp); -static struct device_attribute dev_attr_fifosz = __ATTR_RW(fifosz, 0666); -static struct device_attribute dev_attr_fifocnt = __ATTR_RO(fifocnt); -static struct device_attribute dev_attr_ipblink = __ATTR_RO(ipblink); -static struct device_attribute dev_attr_wsz = __ATTR_RO(wsz); -static struct device_attribute dev_attr_mmap = __ATTR_RO(mmap); - -static inline void set_taskdev_state(struct taskdev *dev, int state) -{ - pr_debug("omapdsp: devstate: CHANGE %s[%d]:\"%s\"->\"%s\"\n", - dev->name, - (dev->task ? dev->task->tid : -1), - devstate_name(dev->state), - devstate_name(state)); - dev->state = state; -} - -/* - * devstate_read_lock_timeout() - * devstate_write_lock_timeout(): - * timeout != 0: dev->state can be diffeent from what you want. - * timeout == 0: no timeout - */ -#define BUILD_DEVSTATE_LOCK_TIMEOUT(rw) \ -static int devstate_##rw##_lock_timeout(struct taskdev *dev, long devstate, \ - int timeout) \ -{ \ - DEFINE_WAIT(wait); \ - down_##rw(&dev->state_sem); \ - while (!(dev->state & devstate)) { \ - up_##rw(&dev->state_sem); \ - prepare_to_wait(&dev->state_wait_q, &wait, TASK_INTERRUPTIBLE); \ - if (!timeout) \ - timeout = MAX_SCHEDULE_TIMEOUT; \ - timeout = schedule_timeout(timeout); \ - finish_wait(&dev->state_wait_q, &wait); \ - if (timeout == 0) \ - return -ETIME; \ - if (signal_pending(current)) \ - return -EINTR; \ - down_##rw(&dev->state_sem); \ - } \ - return 0; \ -} -BUILD_DEVSTATE_LOCK_TIMEOUT(read) -BUILD_DEVSTATE_LOCK_TIMEOUT(write) - -#define BUILD_DEVSTATE_LOCK_AND_TEST(rw) \ -static int devstate_##rw##_lock_and_test(struct taskdev *dev, long devstate) \ -{ \ - down_##rw(&dev->state_sem); \ - if (dev->state & devstate) \ - return 1; /* success */ \ - /* failure */ \ - up_##rw(&dev->state_sem); \ - return 0; \ -} -BUILD_DEVSTATE_LOCK_AND_TEST(read) -BUILD_DEVSTATE_LOCK_AND_TEST(write) - -static int taskdev_lock_interruptible(struct taskdev *dev, - struct mutex *lock) -{ - int ret; - - if (has_taskdev_lock(dev)) - ret = mutex_lock_interruptible(lock); - else { - if ((ret = mutex_lock_interruptible(&dev->lock)) != 0) - return ret; - ret = mutex_lock_interruptible(lock); - mutex_unlock(&dev->lock); - } - - return ret; -} - -static int taskdev_lock_and_statelock_attached(struct taskdev *dev, - struct mutex *lock) -{ - int ret; - - if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED)) - return -ENODEV; - - if ((ret = taskdev_lock_interruptible(dev, lock)) != 0) - devstate_read_unlock(dev); - - return ret; -} - -static inline void taskdev_unlock_and_stateunlock(struct taskdev *dev, - struct mutex *lock) -{ - mutex_unlock(lock); - devstate_read_unlock(dev); -} - -/* - * taskdev_flush_buf() - * must be called under state_lock(ATTACHED) and dev->read_mutex. - */ -static int taskdev_flush_buf(struct taskdev *dev) -{ - u16 ttyp = dev->task->ttyp; - - if (sndtyp_wd(ttyp)) { - /* word receiving */ - kfifo_reset(dev->rcvdt.fifo); - } else { - /* block receiving */ - struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk; - - if (sndtyp_gbl(ttyp)) - ipblink_flush(&rcvdt->link); - else { - ipblink_flush_pvt(&rcvdt->link); - release_ipbuf_pvt(dev->task->ipbuf_pvt_r); - } - } - - return 0; -} - -/* - * taskdev_set_fifosz() - * must be called under dev->read_mutex. - */ -static int taskdev_set_fifosz(struct taskdev *dev, unsigned long sz) -{ - u16 ttyp = dev->task->ttyp; - - if (!(sndtyp_wd(ttyp) && sndtyp_acv(ttyp))) { - printk(KERN_ERR - "omapdsp: buffer size can be changed only for " - "active word sending task.\n"); - return -EINVAL; - } - if ((sz == 0) || (sz & 1)) { - printk(KERN_ERR "omapdsp: illegal buffer size! (%ld)\n" - "it must be even and non-zero value.\n", sz); - return -EINVAL; - } - - if (kfifo_len(dev->rcvdt.fifo)) { - printk(KERN_ERR "omapdsp: buffer is not empty!\n"); - return -EIO; - } - - kfifo_free(dev->rcvdt.fifo); - dev->rcvdt.fifo = kfifo_alloc(sz, GFP_KERNEL, &dev->read_lock); - if (IS_ERR(dev->rcvdt.fifo)) { - printk(KERN_ERR - "omapdsp: unable to change receive buffer size. " - "(%ld bytes for %s)\n", sz, dev->name); - return -ENOMEM; - } - - return 0; -} - -static inline int has_taskdev_lock(struct taskdev *dev) -{ - return (dev->lock_pid == current->pid); -} - -static int taskdev_lock(struct taskdev *dev) -{ - if (mutex_lock_interruptible(&dev->lock)) - return -EINTR; - dev->lock_pid = current->pid; - return 0; -} - -static int taskdev_unlock(struct taskdev *dev) -{ - if (!has_taskdev_lock(dev)) { - printk(KERN_ERR - "omapdsp: an illegal process attempted to " - "unlock the dsptask lock!\n"); - return -EINVAL; - } - dev->lock_pid = 0; - mutex_unlock(&dev->lock); - return 0; -} - -static int dsp_task_config(struct dsptask *task, u8 tid) -{ - u16 ttyp; - int ret; - - task->tid = tid; - dsptask[tid] = task; - - /* TCFG request */ - task->state = TASK_ST_CFGREQ; - if (mutex_lock_interruptible(&cfg_lock)) { - ret = -EINTR; - goto fail_out; - } - cfg_cmd = MBOX_CMD_DSP_TCFG; - mbcompose_send_and_wait(TCFG, tid, 0, &cfg_wait_q); - cfg_cmd = 0; - mutex_unlock(&cfg_lock); - - if (task->state != TASK_ST_READY) { - printk(KERN_ERR "omapdsp: task %d configuration error!\n", tid); - ret = -EINVAL; - goto fail_out; - } - - if (strlen(task->name) <= 1) - sprintf(task->name, "%d", tid); - pr_info("omapdsp: task %d: name %s\n", tid, task->name); - - ttyp = task->ttyp; - - /* - * task info sanity check - */ - - /* task type check */ - if (rcvtyp_psv(ttyp) && rcvtyp_pvt(ttyp)) { - printk(KERN_ERR "omapdsp: illegal task type(0x%04x), tid=%d\n", - tid, ttyp); - ret = -EINVAL; - goto fail_out; - } - - /* private buffer address check */ - if (sndtyp_pvt(ttyp) && - (ipbuf_p_validate(task->ipbuf_pvt_r, DIR_D2A) < 0)) { - ret = -EINVAL; - goto fail_out; - } - if (rcvtyp_pvt(ttyp) && - (ipbuf_p_validate(task->ipbuf_pvt_w, DIR_A2D) < 0)) { - ret = -EINVAL; - goto fail_out; - } - - /* mmap buffer configuration check */ - if ((task->map_length > 0) && - ((!ALIGN((unsigned long)task->map_base, PAGE_SIZE)) || - (!ALIGN(task->map_length, PAGE_SIZE)) || - (dsp_mem_type(task->map_base, task->map_length) != MEM_TYPE_EXTERN))) { - printk(KERN_ERR - "omapdsp: illegal mmap buffer address(0x%p) or " - "length(0x%x).\n" - " It needs to be page-aligned and located at " - "external memory.\n", - task->map_base, task->map_length); - ret = -EINVAL; - goto fail_out; - } - - return 0; - -fail_out: - dsptask[tid] = NULL; - return ret; -} - -static void dsp_task_init(struct dsptask *task) -{ - mbcompose_send(TCTL, task->tid, TCTL_TINIT); -} - -int dsp_task_config_all(u8 n) -{ - int i, ret; - struct taskdev *devheap; - struct dsptask *taskheap; - size_t devheapsz, taskheapsz; - - pr_info("omapdsp: found %d task(s)\n", n); - if (n == 0) - return 0; - - /* - * reducing kmalloc! - */ - devheapsz = sizeof(struct taskdev) * n; - taskheapsz = sizeof(struct dsptask) * n; - heap = kzalloc(devheapsz + taskheapsz, GFP_KERNEL); - if (heap == NULL) - return -ENOMEM; - devheap = heap; - taskheap = heap + devheapsz; - - n_task = n; - for (i = 0; i < n; i++) { - struct taskdev *dev = &devheap[i]; - struct dsptask *task = &taskheap[i]; - - if ((ret = dsp_task_config(task, i)) < 0) - return ret; - if ((ret = taskdev_init(dev, task->name, i)) < 0) - return ret; - if ((ret = taskdev_attach_task(dev, task)) < 0) - return ret; - dsp_task_init(task); - pr_info("omapdsp: taskdev %s enabled.\n", dev->name); - } - - return 0; -} - -static void dsp_task_unconfig(struct dsptask *task) -{ - dsptask[task->tid] = NULL; -} - -void dsp_task_unconfig_all(void) -{ - unsigned char minor; - u8 tid; - struct dsptask *task; - - for (minor = 0; minor < n_task; minor++) { - /* - * taskdev[minor] can be NULL in case of - * configuration failure - */ - if (taskdev[minor]) - taskdev_delete(minor); - } - for (; minor < TASKDEV_MAX; minor++) { - if (taskdev[minor]) - dsp_rmdev_minor(minor); - } - - for (tid = 0; tid < n_task; tid++) { - /* - * dsptask[tid] can be NULL in case of - * configuration failure - */ - task = dsptask[tid]; - if (task) - dsp_task_unconfig(task); - } - for (; tid < TASKDEV_MAX; tid++) { - task = dsptask[tid]; - if (task) { - /* - * on-demand tasks should be deleted in - * rmdev_minor(), but just in case. - */ - dsp_task_unconfig(task); - kfree(task); - } - } - - if (heap) { - kfree(heap); - heap = NULL; - } - - n_task = 0; -} - -static struct device_driver dsptask_driver = { - .name = "dsptask", - .bus = &dsptask_bus, -}; - -u8 dsp_task_count(void) -{ - return n_task; -} - -int dsp_taskmod_busy(void) -{ - struct taskdev *dev; - unsigned char minor; - unsigned int usecount; - - for (minor = 0; minor < TASKDEV_MAX; minor++) { - dev = taskdev[minor]; - if (dev == NULL) - continue; - if ((usecount = dev->usecount) > 0) { - printk("dsp_taskmod_busy(): %s: usecount=%d\n", - dev->name, usecount); - return 1; - } -/* - if ((dev->state & (TASKDEV_ST_ADDREQ | - TASKDEV_ST_DELREQ)) { -*/ - if (dev->state & TASKDEV_ST_ADDREQ) { - printk("dsp_taskmod_busy(): %s is in %s\n", - dev->name, devstate_name(dev->state)); - return 1; - } - } - return 0; -} - -/* - * DSP task device file operations - */ -static ssize_t dsp_task_read_wd_acv(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - int ret = 0; - DEFINE_WAIT(wait); - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - - - prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE); - if (kfifo_len(dev->rcvdt.fifo) == 0) - schedule(); - finish_wait(&dev->read_wait_q, &wait); - if (kfifo_len(dev->rcvdt.fifo) == 0) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - - ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count); - - up_out: - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - return ret; -} - -static ssize_t dsp_task_read_bk_acv(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk; - ssize_t ret = 0; - DEFINE_WAIT(wait); - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } else if ((int)buf & 0x1) { - printk(KERN_ERR - "omapdsp: buf should be word aligned for " - "dsp_task_read().\n"); - return -EINVAL; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - - prepare_to_wait(&dev->read_wait_q, &wait, TASK_INTERRUPTIBLE); - if (ipblink_empty(&rcvdt->link)) - schedule(); - finish_wait(&dev->read_wait_q, &wait); - if (ipblink_empty(&rcvdt->link)) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - /* copy from delayed IPBUF */ - if (sndtyp_pvt(dev->task->ttyp)) { - /* private */ - if (!ipblink_empty(&rcvdt->link)) { - struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r; - unsigned char *base, *src; - size_t bkcnt; - - if (dsp_mem_enable(ipbp) < 0) { - ret = -EBUSY; - goto up_out; - } - base = MKVIRT(ipbp->ah, ipbp->al); - bkcnt = ((unsigned long)ipbp->c) * 2 - rcvdt->rp; - if (dsp_address_validate(base, bkcnt, - "task %s read buffer", - dev->task->name) < 0) { - ret = -EINVAL; - goto pv_out1; - } - if (dsp_mem_enable(base) < 0) { - ret = -EBUSY; - goto pv_out1; - } - src = base + rcvdt->rp; - if (bkcnt > count) { - if (copy_to_user_dsp(buf, src, count)) { - ret = -EFAULT; - goto pv_out2; - } - ret = count; - rcvdt->rp += count; - } else { - if (copy_to_user_dsp(buf, src, bkcnt)) { - ret = -EFAULT; - goto pv_out2; - } - ret = bkcnt; - ipblink_del_pvt(&rcvdt->link); - release_ipbuf_pvt(ipbp); - rcvdt->rp = 0; - } - pv_out2: - dsp_mem_disable(src); - pv_out1: - dsp_mem_disable(ipbp); - } - } else { - /* global */ - if (dsp_mem_enable_ipbuf() < 0) { - ret = -EBUSY; - goto up_out; - } - while (!ipblink_empty(&rcvdt->link)) { - unsigned char *src; - size_t bkcnt; - struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top); - - src = ipb_h->p->d + rcvdt->rp; - bkcnt = ((unsigned long)ipb_h->p->c) * 2 - rcvdt->rp; - if (bkcnt > count) { - if (copy_to_user_dsp(buf, src, count)) { - ret = -EFAULT; - goto gb_out; - } - ret += count; - rcvdt->rp += count; - break; - } else { - if (copy_to_user_dsp(buf, src, bkcnt)) { - ret = -EFAULT; - goto gb_out; - } - ret += bkcnt; - buf += bkcnt; - count -= bkcnt; - ipblink_del_top(&rcvdt->link); - unuse_ipbuf(ipb_h); - rcvdt->rp = 0; - } - } - gb_out: - dsp_mem_disable_ipbuf(); - } - - up_out: - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - return ret; -} - -static ssize_t dsp_task_read_wd_psv(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - int ret = 0; - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } else { - /* force! */ - count = 2; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - - mbcompose_send_and_wait(WDREQ, dev->task->tid, 0, &dev->read_wait_q); - - if (kfifo_len(dev->rcvdt.fifo) == 0) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - ret = kfifo_get_to_user(dev->rcvdt.fifo, buf, count); - -up_out: - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - return ret; -} - -static ssize_t dsp_task_read_bk_psv(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - struct rcvdt_bk_struct *rcvdt = &dev->rcvdt.bk; - int ret = 0; - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } else if ((int)buf & 0x1) { - printk(KERN_ERR - "omapdsp: buf should be word aligned for " - "dsp_task_read().\n"); - return -EINVAL; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - - mbcompose_send_and_wait(BKREQ, dev->task->tid, count/2, - &dev->read_wait_q); - - if (ipblink_empty(&rcvdt->link)) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - /* - * We will not receive more than requested count. - */ - if (sndtyp_pvt(dev->task->ttyp)) { - /* private */ - struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_r; - size_t rcvcnt; - void *src; - - if (dsp_mem_enable(ipbp) < 0) { - ret = -EBUSY; - goto up_out; - } - src = MKVIRT(ipbp->ah, ipbp->al); - rcvcnt = ((unsigned long)ipbp->c) * 2; - if (dsp_address_validate(src, rcvcnt, "task %s read buffer", - dev->task->name) < 0) { - ret = -EINVAL; - goto pv_out1; - } - if (dsp_mem_enable(src) < 0) { - ret = -EBUSY; - goto pv_out1; - } - if (count > rcvcnt) - count = rcvcnt; - if (copy_to_user_dsp(buf, src, count)) { - ret = -EFAULT; - goto pv_out2; - } - ipblink_del_pvt(&rcvdt->link); - release_ipbuf_pvt(ipbp); - ret = count; -pv_out2: - dsp_mem_disable(src); -pv_out1: - dsp_mem_disable(ipbp); - } else { - /* global */ - struct ipbuf_head *ipb_h = bid_to_ipbuf(rcvdt->link.top); - size_t rcvcnt; - - if (dsp_mem_enable_ipbuf() < 0) { - ret = -EBUSY; - goto up_out; - } - rcvcnt = ((unsigned long)ipb_h->p->c) * 2; - if (count > rcvcnt) - count = rcvcnt; - if (copy_to_user_dsp(buf, ipb_h->p->d, count)) { - ret = -EFAULT; - goto gb_out; - } - ipblink_del_top(&rcvdt->link); - unuse_ipbuf(ipb_h); - ret = count; -gb_out: - dsp_mem_disable_ipbuf(); - } - -up_out: - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - return ret; -} - -static ssize_t dsp_task_write_wd(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - u16 wd; - int ret = 0; - DEFINE_WAIT(wait); - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } else { - /* force! */ - count = 2; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex)) - return -ENODEV; - - prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE); - if (dev->wsz == 0) - schedule(); - finish_wait(&dev->write_wait_q, &wait); - if (dev->wsz == 0) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - if (copy_from_user(&wd, buf, count)) { - ret = -EFAULT; - goto up_out; - } - - spin_lock(&dev->wsz_lock); - if (mbcompose_send(WDSND, dev->task->tid, wd) < 0) { - spin_unlock(&dev->wsz_lock); - goto up_out; - } - ret = count; - if (rcvtyp_acv(dev->task->ttyp)) - dev->wsz = 0; - spin_unlock(&dev->wsz_lock); - - up_out: - taskdev_unlock_and_stateunlock(dev, &dev->write_mutex); - return ret; -} - -static ssize_t dsp_task_write_bk(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - int ret = 0; - DEFINE_WAIT(wait); - - if (count == 0) { - return 0; - } else if (count & 0x1) { - printk(KERN_ERR - "omapdsp: odd count is illegal for DSP task device.\n"); - return -EINVAL; - } else if ((int)buf & 0x1) { - printk(KERN_ERR - "omapdsp: buf should be word aligned for " - "dsp_task_write().\n"); - return -EINVAL; - } - - if (taskdev_lock_and_statelock_attached(dev, &dev->write_mutex)) - return -ENODEV; - - prepare_to_wait(&dev->write_wait_q, &wait, TASK_INTERRUPTIBLE); - if (dev->wsz == 0) - schedule(); - finish_wait(&dev->write_wait_q, &wait); - if (dev->wsz == 0) { - /* failure */ - if (signal_pending(current)) - ret = -EINTR; - goto up_out; - } - - if (count > dev->wsz) - count = dev->wsz; - - if (rcvtyp_pvt(dev->task->ttyp)) { - /* private */ - struct ipbuf_p *ipbp = dev->task->ipbuf_pvt_w; - unsigned char *dst; - - if (dsp_mem_enable(ipbp) < 0) { - ret = -EBUSY; - goto up_out; - } - dst = MKVIRT(ipbp->ah, ipbp->al); - if (dsp_address_validate(dst, count, "task %s write buffer", - dev->task->name) < 0) { - ret = -EINVAL; - goto pv_out1; - } - if (dsp_mem_enable(dst) < 0) { - ret = -EBUSY; - goto pv_out1; - } - if (copy_from_user_dsp(dst, buf, count)) { - ret = -EFAULT; - goto pv_out2; - } - ipbp->c = count/2; - ipbp->s = dev->task->tid; - spin_lock(&dev->wsz_lock); - if (mbcompose_send(BKSNDP, dev->task->tid, 0) == 0) { - if (rcvtyp_acv(dev->task->ttyp)) - dev->wsz = 0; - ret = count; - } - spin_unlock(&dev->wsz_lock); - pv_out2: - dsp_mem_disable(dst); - pv_out1: - dsp_mem_disable(ipbp); - } else { - /* global */ - struct ipbuf_head *ipb_h; - - if (dsp_mem_enable_ipbuf() < 0) { - ret = -EBUSY; - goto up_out; - } - if ((ipb_h = get_free_ipbuf(dev->task->tid)) == NULL) - goto gb_out; - if (copy_from_user_dsp(ipb_h->p->d, buf, count)) { - release_ipbuf(ipb_h); - ret = -EFAULT; - goto gb_out; - } - ipb_h->p->c = count/2; - ipb_h->p->sa = dev->task->tid; - spin_lock(&dev->wsz_lock); - if (mbcompose_send(BKSND, dev->task->tid, ipb_h->bid) == 0) { - if (rcvtyp_acv(dev->task->ttyp)) - dev->wsz = 0; - ret = count; - ipb_bsycnt_inc(&ipbcfg); - } else - release_ipbuf(ipb_h); - spin_unlock(&dev->wsz_lock); - gb_out: - dsp_mem_disable_ipbuf(); - } - - up_out: - taskdev_unlock_and_stateunlock(dev, &dev->write_mutex); - return ret; -} - -static unsigned int dsp_task_poll(struct file * file, poll_table * wait) -{ - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - struct dsptask *task = dev->task; - unsigned int mask = 0; - - if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED)) - return 0; - poll_wait(file, &dev->read_wait_q, wait); - poll_wait(file, &dev->write_wait_q, wait); - if (sndtyp_psv(task->ttyp) || - (sndtyp_wd(task->ttyp) && kfifo_len(dev->rcvdt.fifo)) || - (sndtyp_bk(task->ttyp) && !ipblink_empty(&dev->rcvdt.bk.link))) - mask |= POLLIN | POLLRDNORM; - if (dev->wsz) - mask |= POLLOUT | POLLWRNORM; - devstate_read_unlock(dev); - - return mask; -} - -static int dsp_tctl_issue(struct taskdev *dev, u16 cmd, int argc, u16 argv[]) -{ - int tctl_argc; - struct mb_exarg mbarg, *mbargp; - int interactive; - u8 tid; - int ret = 0; - - if (cmd < 0x8000) { - /* - * 0x0000 - 0x7fff - * system reserved TCTL commands - */ - switch (cmd) { - case TCTL_TEN: - case TCTL_TDIS: - tctl_argc = 0; - interactive = 0; - break; - default: - return -EINVAL; - } - } - /* - * 0x8000 - 0xffff - * user-defined TCTL commands - */ - else if (cmd < 0x8100) { - /* 0x8000-0x80ff: no arg, non-interactive */ - tctl_argc = 0; - interactive = 0; - } else if (cmd < 0x8200) { - /* 0x8100-0x81ff: 1 arg, non-interactive */ - tctl_argc = 1; - interactive = 0; - } else if (cmd < 0x9000) { - /* 0x8200-0x8fff: reserved */ - return -EINVAL; - } else if (cmd < 0x9100) { - /* 0x9000-0x90ff: no arg, interactive */ - tctl_argc = 0; - interactive = 1; - } else if (cmd < 0x9200) { - /* 0x9100-0x91ff: 1 arg, interactive */ - tctl_argc = 1; - interactive = 1; - } else { - /* 0x9200-0xffff: reserved */ - return -EINVAL; - } - - /* - * if argc < 0, use tctl_argc as is. - * if argc >= 0, check arg count. - */ - if ((argc >= 0) && (argc != tctl_argc)) - return -EINVAL; - - /* - * issue TCTL - */ - if (taskdev_lock_interruptible(dev, &dev->tctl_mutex)) - return -EINTR; - - tid = dev->task->tid; - if (tctl_argc > 0) { - mbarg.argc = tctl_argc; - mbarg.tid = tid; - mbarg.argv = argv; - mbargp = &mbarg; - } else - mbargp = NULL; - - if (interactive) { - dev->tctl_stat = -EINVAL; - - mbcompose_send_and_wait_exarg(TCTL, tid, cmd, mbargp, - &dev->tctl_wait_q); - if (signal_pending(current)) { - ret = -EINTR; - goto up_out; - } - if ((ret = dev->tctl_stat) < 0) { - printk(KERN_ERR "omapdsp: TCTL not responding.\n"); - goto up_out; - } - } else - mbcompose_send_exarg(TCTL, tid, cmd, mbargp); - -up_out: - mutex_unlock(&dev->tctl_mutex); - return ret; -} - -static int dsp_task_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - int ret; - - if (cmd < 0x10000) { - /* issue TCTL */ - u16 mbargv[1]; - - mbargv[0] = arg & 0xffff; - return dsp_tctl_issue(dev, cmd, -1, mbargv); - } - - /* non TCTL ioctls */ - switch (cmd) { - - case TASK_IOCTL_LOCK: - ret = taskdev_lock(dev); - break; - - case TASK_IOCTL_UNLOCK: - ret = taskdev_unlock(dev); - break; - - case TASK_IOCTL_BFLSH: - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - ret = taskdev_flush_buf(dev); - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - break; - - case TASK_IOCTL_SETBSZ: - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - ret = taskdev_set_fifosz(dev, arg); - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - break; - - case TASK_IOCTL_GETNAME: - ret = 0; - if (copy_to_user((void __user *)arg, dev->name, - strlen(dev->name) + 1)) - ret = -EFAULT; - break; - - default: - ret = -ENOIOCTLCMD; - - } - - return ret; -} - -static void dsp_task_mmap_open(struct vm_area_struct *vma) -{ - struct taskdev *dev = (struct taskdev *)vma->vm_private_data; - struct dsptask *task; - size_t len = vma->vm_end - vma->vm_start; - - BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED)); - task = dev->task; - omap_mmu_exmap_use(&dsp_mmu, task->map_base, len); -} - -static void dsp_task_mmap_close(struct vm_area_struct *vma) -{ - struct taskdev *dev = (struct taskdev *)vma->vm_private_data; - struct dsptask *task; - size_t len = vma->vm_end - vma->vm_start; - - BUG_ON(!(dev->state & TASKDEV_ST_ATTACHED)); - task = dev->task; - omap_mmu_exmap_unuse(&dsp_mmu, task->map_base, len); -} - -/** - * On demand page allocation is not allowed. The mapping area is defined by - * corresponding DSP tasks. - */ -static int dsp_task_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - return VM_FAULT_NOPAGE; -} - -static struct vm_operations_struct dsp_task_vm_ops = { - .open = dsp_task_mmap_open, - .close = dsp_task_mmap_close, - .fault = dsp_task_mmap_fault, -}; - -static int dsp_task_mmap(struct file *filp, struct vm_area_struct *vma) -{ - void *tmp_vadr; - unsigned long tmp_padr, tmp_vmadr, off; - size_t req_len, tmp_len; - unsigned int minor = MINOR(filp->f_dentry->d_inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - struct dsptask *task; - int ret = 0; - - if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED)) - return -ENODEV; - task = dev->task; - - /* - * Don't swap this area out - * Don't dump this area to a core file - */ - vma->vm_flags |= VM_RESERVED | VM_IO; - - /* Do not cache this area */ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - req_len = vma->vm_end - vma->vm_start; - off = vma->vm_pgoff << PAGE_SHIFT; - tmp_vmadr = vma->vm_start; - tmp_vadr = task->map_base + off; - do { - tmp_padr = omap_mmu_virt_to_phys(&dsp_mmu, tmp_vadr, &tmp_len); - if (tmp_padr == 0) { - printk(KERN_ERR - "omapdsp: task %s: illegal address " - "for mmap: %p", task->name, tmp_vadr); - /* partial mapping will be cleared in upper layer */ - ret = -EINVAL; - goto unlock_out; - } - if (tmp_len > req_len) - tmp_len = req_len; - - pr_debug("omapdsp: mmap info: " - "vmadr = %08lx, padr = %08lx, len = %x\n", - tmp_vmadr, tmp_padr, tmp_len); - if (remap_pfn_range(vma, tmp_vmadr, tmp_padr >> PAGE_SHIFT, - tmp_len, vma->vm_page_prot) != 0) { - printk(KERN_ERR - "omapdsp: task %s: remap_page_range() failed.\n", - task->name); - /* partial mapping will be cleared in upper layer */ - ret = -EINVAL; - goto unlock_out; - } - - req_len -= tmp_len; - tmp_vmadr += tmp_len; - tmp_vadr += tmp_len; - } while (req_len); - - vma->vm_ops = &dsp_task_vm_ops; - vma->vm_private_data = dev; - omap_mmu_exmap_use(&dsp_mmu, task->map_base, vma->vm_end - vma->vm_start); - -unlock_out: - devstate_read_unlock(dev); - return ret; -} - -static int dsp_task_open(struct inode *inode, struct file *file) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct taskdev *dev; - int ret = 0; - - if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) - return -ENODEV; - - restart: - mutex_lock(&dev->usecount_lock); - down_write(&dev->state_sem); - - /* state can be NOTASK, ATTACHED/FREEZED, KILLING, GARBAGE or INVALID here. */ - switch (dev->state & TASKDEV_ST_STATE_MASK) { - case TASKDEV_ST_NOTASK: - break; - case TASKDEV_ST_ATTACHED: - goto attached; - - case TASKDEV_ST_INVALID: - up_write(&dev->state_sem); - mutex_unlock(&dev->usecount_lock); - return -ENODEV; - - case TASKDEV_ST_FREEZED: - case TASKDEV_ST_KILLING: - case TASKDEV_ST_GARBAGE: - case TASKDEV_ST_DELREQ: - /* on the kill process. wait until it becomes NOTASK. */ - up_write(&dev->state_sem); - mutex_unlock(&dev->usecount_lock); - if (devstate_write_lock(dev, TASKDEV_ST_NOTASK) < 0) - return -EINTR; - devstate_write_unlock(dev); - goto restart; - } - - /* NOTASK */ - set_taskdev_state(dev, TASKDEV_ST_ADDREQ); - /* wake up twch daemon for tadd */ - dsp_twch_touch(); - up_write(&dev->state_sem); - if (devstate_write_lock(dev, TASKDEV_ST_ATTACHED | - TASKDEV_ST_ADDFAIL) < 0) { - /* cancelled */ - if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) { - mutex_unlock(&dev->usecount_lock); - /* out of control ??? */ - return -EINTR; - } - set_taskdev_state(dev, TASKDEV_ST_NOTASK); - ret = -EINTR; - goto change_out; - } - if (dev->state & TASKDEV_ST_ADDFAIL) { - printk(KERN_ERR "omapdsp: task attach failed for %s!\n", - dev->name); - ret = -EBUSY; - set_taskdev_state(dev, TASKDEV_ST_NOTASK); - goto change_out; - } - - attached: - ret = proc_list_add(&dev->proc_list_lock, - &dev->proc_list, current, file); - if (ret) - goto out; - - dev->usecount++; - file->f_op = &dev->fops; - up_write(&dev->state_sem); - mutex_unlock(&dev->usecount_lock); - -#ifdef DSP_PTE_FREE /* not used currently. */ - dsp_map_update(current); - dsp_cur_users_add(current); -#endif /* DSP_PTE_FREE */ - return 0; - - change_out: - wake_up_interruptible_all(&dev->state_wait_q); - out: - up_write(&dev->state_sem); - mutex_unlock(&dev->usecount_lock); - return ret; -} - -static int dsp_task_release(struct inode *inode, struct file *file) -{ - unsigned int minor = MINOR(inode->i_rdev); - struct taskdev *dev = taskdev[minor]; - -#ifdef DSP_PTE_FREE /* not used currently. */ - dsp_cur_users_del(current); -#endif /* DSP_PTE_FREE */ - - if (has_taskdev_lock(dev)) - taskdev_unlock(dev); - - proc_list_del(&dev->proc_list_lock, &dev->proc_list, current, file); - mutex_lock(&dev->usecount_lock); - if (--dev->usecount > 0) { - /* other processes are using this device. no state change. */ - mutex_unlock(&dev->usecount_lock); - return 0; - } - - /* usecount == 0 */ - down_write(&dev->state_sem); - - /* state can be ATTACHED/FREEZED, KILLING or GARBAGE here. */ - switch (dev->state & TASKDEV_ST_STATE_MASK) { - - case TASKDEV_ST_KILLING: - break; - - case TASKDEV_ST_GARBAGE: - set_taskdev_state(dev, TASKDEV_ST_NOTASK); - wake_up_interruptible_all(&dev->state_wait_q); - break; - - case TASKDEV_ST_ATTACHED: - case TASKDEV_ST_FREEZED: - if (is_dynamic_task(minor)) { - set_taskdev_state(dev, TASKDEV_ST_DELREQ); - /* wake up twch daemon for tdel */ - dsp_twch_touch(); - } - break; - - } - - up_write(&dev->state_sem); - mutex_unlock(&dev->usecount_lock); - return 0; -} - -/* - * mkdev / rmdev - */ -int dsp_mkdev(char *name) -{ - struct taskdev *dev; - int status; - unsigned char minor; - int ret; - - if (dsp_cfgstat_get_stat() != CFGSTAT_READY) { - printk(KERN_ERR "omapdsp: dsp has not been configured.\n"); - return -EINVAL; - } - - if (mutex_lock_interruptible(&devmgr_lock)) - return -EINTR; - - /* naming check */ - for (minor = 0; minor < TASKDEV_MAX; minor++) { - if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) { - printk(KERN_ERR - "omapdsp: task device name %s is already " - "in use.\n", name); - ret = -EINVAL; - goto out; - } - } - - /* find free minor number */ - for (minor = n_task; minor < TASKDEV_MAX; minor++) { - if (taskdev[minor] == NULL) - goto do_make; - } - printk(KERN_ERR "omapdsp: Too many task devices.\n"); - ret = -EBUSY; - goto out; - -do_make: - if ((dev = kzalloc(sizeof(struct taskdev), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto out; - } - if ((status = taskdev_init(dev, name, minor)) < 0) { - kfree(dev); - ret = status; - goto out; - } - ret = minor; - -out: - mutex_unlock(&devmgr_lock); - return ret; -} - -int dsp_rmdev(char *name) -{ - unsigned char minor; - int status; - int ret; - - if (dsp_cfgstat_get_stat() != CFGSTAT_READY) { - printk(KERN_ERR "omapdsp: dsp has not been configured.\n"); - return -EINVAL; - } - - if (mutex_lock_interruptible(&devmgr_lock)) - return -EINTR; - - /* find in dynamic devices */ - for (minor = n_task; minor < TASKDEV_MAX; minor++) { - if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) - goto do_remove; - } - - /* find in static devices */ - for (minor = 0; minor < n_task; minor++) { - if (taskdev[minor] && !strcmp(taskdev[minor]->name, name)) { - printk(KERN_ERR - "omapdsp: task device %s is static.\n", name); - ret = -EINVAL; - goto out; - } - } - - printk(KERN_ERR "omapdsp: task device %s not found.\n", name); - return -EINVAL; - -do_remove: - ret = minor; - if ((status = dsp_rmdev_minor(minor)) < 0) - ret = status; -out: - mutex_unlock(&devmgr_lock); - return ret; -} - -static int dsp_rmdev_minor(unsigned char minor) -{ - struct taskdev *dev = taskdev[minor]; - - while (!down_write_trylock(&dev->state_sem)) { - down_read(&dev->state_sem); - if (dev->state & (TASKDEV_ST_ATTACHED | - TASKDEV_ST_FREEZED)) { - /* - * task is working. kill it. - * ATTACHED -> FREEZED can be changed under - * down_read of state_sem.. - */ - set_taskdev_state(dev, TASKDEV_ST_FREEZED); - wake_up_interruptible_all(&dev->read_wait_q); - wake_up_interruptible_all(&dev->write_wait_q); - wake_up_interruptible_all(&dev->tctl_wait_q); - } - up_read(&dev->state_sem); - schedule(); - } - - switch (dev->state & TASKDEV_ST_STATE_MASK) { - - case TASKDEV_ST_NOTASK: - case TASKDEV_ST_INVALID: - /* fine */ - goto notask; - - case TASKDEV_ST_ATTACHED: - case TASKDEV_ST_FREEZED: - /* task is working. kill it. */ - set_taskdev_state(dev, TASKDEV_ST_KILLING); - up_write(&dev->state_sem); - dsp_tdel_bh(dev, TDEL_KILL); - goto invalidate; - - case TASKDEV_ST_ADDREQ: - /* open() is waiting. drain it. */ - set_taskdev_state(dev, TASKDEV_ST_ADDFAIL); - wake_up_interruptible_all(&dev->state_wait_q); - break; - - case TASKDEV_ST_DELREQ: - /* nobody is waiting. */ - set_taskdev_state(dev, TASKDEV_ST_NOTASK); - wake_up_interruptible_all(&dev->state_wait_q); - break; - - case TASKDEV_ST_ADDING: - case TASKDEV_ST_DELING: - case TASKDEV_ST_KILLING: - case TASKDEV_ST_GARBAGE: - case TASKDEV_ST_ADDFAIL: - /* transient state. wait for a moment. */ - break; - - } - - up_write(&dev->state_sem); - -invalidate: - /* wait for some time and hope the state is settled */ - devstate_read_lock_timeout(dev, TASKDEV_ST_NOTASK, 5 * HZ); - if (!(dev->state & TASKDEV_ST_NOTASK)) { - printk(KERN_WARNING - "omapdsp: illegal device state (%s) on rmdev %s.\n", - devstate_name(dev->state), dev->name); - } -notask: - set_taskdev_state(dev, TASKDEV_ST_INVALID); - devstate_read_unlock(dev); - - taskdev_delete(minor); - kfree(dev); - - return 0; -} - -static struct file_operations dsp_task_fops = { - .owner = THIS_MODULE, - .poll = dsp_task_poll, - .ioctl = dsp_task_ioctl, - .open = dsp_task_open, - .release = dsp_task_release, -}; - -static void dsptask_dev_release(struct device *dev) -{ -} - -static int taskdev_init(struct taskdev *dev, char *name, unsigned char minor) -{ - int ret; - struct device *task_dev; - - taskdev[minor] = dev; - - spin_lock_init(&dev->proc_list_lock); - INIT_LIST_HEAD(&dev->proc_list); - init_waitqueue_head(&dev->read_wait_q); - init_waitqueue_head(&dev->write_wait_q); - init_waitqueue_head(&dev->tctl_wait_q); - mutex_init(&dev->read_mutex); - mutex_init(&dev->write_mutex); - mutex_init(&dev->tctl_mutex); - mutex_init(&dev->lock); - spin_lock_init(&dev->wsz_lock); - dev->tctl_ret = -EINVAL; - dev->lock_pid = 0; - - strncpy(dev->name, name, TNM_LEN); - dev->name[TNM_LEN-1] = '\0'; - set_taskdev_state(dev, (minor < n_task) ? TASKDEV_ST_ATTACHED : TASKDEV_ST_NOTASK); - dev->usecount = 0; - mutex_init(&dev->usecount_lock); - memcpy(&dev->fops, &dsp_task_fops, sizeof(struct file_operations)); - - dev->dev.parent = omap_dsp->dev; - dev->dev.bus = &dsptask_bus; - sprintf(dev->dev.bus_id, "dsptask%d", minor); - dev->dev.release = dsptask_dev_release; - ret = device_register(&dev->dev); - if (ret) { - printk(KERN_ERR "device_register failed: %d\n", ret); - return ret; - } - ret = device_create_file(&dev->dev, &dev_attr_devname); - if (ret) - goto fail_create_devname; - ret = device_create_file(&dev->dev, &dev_attr_devstate); - if (ret) - goto fail_create_devstate; - ret = device_create_file(&dev->dev, &dev_attr_proc_list); - if (ret) - goto fail_create_proclist; - - task_dev = device_create(dsp_task_class, NULL, - MKDEV(OMAP_DSP_TASK_MAJOR, minor), NULL, - "dsptask%d", (int)minor); - - if (unlikely(IS_ERR(task_dev))) { - ret = -EINVAL; - goto fail_create_taskclass; - } - - init_waitqueue_head(&dev->state_wait_q); - init_rwsem(&dev->state_sem); - - return 0; - - fail_create_taskclass: - device_remove_file(&dev->dev, &dev_attr_proc_list); - fail_create_proclist: - device_remove_file(&dev->dev, &dev_attr_devstate); - fail_create_devstate: - device_remove_file(&dev->dev, &dev_attr_devname); - fail_create_devname: - device_unregister(&dev->dev); - return ret; -} - -static void taskdev_delete(unsigned char minor) -{ - struct taskdev *dev = taskdev[minor]; - - if (!dev) - return; - device_remove_file(&dev->dev, &dev_attr_devname); - device_remove_file(&dev->dev, &dev_attr_devstate); - device_remove_file(&dev->dev, &dev_attr_proc_list); - device_destroy(dsp_task_class, MKDEV(OMAP_DSP_TASK_MAJOR, minor)); - device_unregister(&dev->dev); - proc_list_flush(&dev->proc_list_lock, &dev->proc_list); - taskdev[minor] = NULL; -} - -static int taskdev_attach_task(struct taskdev *dev, struct dsptask *task) -{ - u16 ttyp = task->ttyp; - int ret; - - dev->fops.read = - sndtyp_acv(ttyp) ? - sndtyp_wd(ttyp) ? dsp_task_read_wd_acv: - /* sndtyp_bk */ dsp_task_read_bk_acv: - /* sndtyp_psv */ - sndtyp_wd(ttyp) ? dsp_task_read_wd_psv: - /* sndtyp_bk */ dsp_task_read_bk_psv; - if (sndtyp_wd(ttyp)) { - /* word */ - size_t fifosz = sndtyp_psv(ttyp) ? 2:32; /* passive:active */ - - dev->rcvdt.fifo = kfifo_alloc(fifosz, GFP_KERNEL, - &dev->read_lock); - if (IS_ERR(dev->rcvdt.fifo)) { - printk(KERN_ERR - "omapdsp: unable to allocate receive buffer. " - "(%d bytes for %s)\n", fifosz, dev->name); - return -ENOMEM; - } - } else { - /* block */ - INIT_IPBLINK(&dev->rcvdt.bk.link); - dev->rcvdt.bk.rp = 0; - } - - dev->fops.write = - rcvtyp_wd(ttyp) ? dsp_task_write_wd: - /* rcvbyp_bk */ dsp_task_write_bk; - dev->wsz = rcvtyp_acv(ttyp) ? 0 : /* active */ - rcvtyp_wd(ttyp) ? 2 : /* passive word */ - ipbcfg.lsz*2; /* passive block */ - - if (task->map_length) - dev->fops.mmap = dsp_task_mmap; - - ret = device_create_file(&dev->dev, &dev_attr_taskname); - if (unlikely(ret)) - goto fail_create_taskname; - ret = device_create_file(&dev->dev, &dev_attr_ttyp); - if (unlikely(ret)) - goto fail_create_ttyp; - ret = device_create_file(&dev->dev, &dev_attr_wsz); - if (unlikely(ret)) - goto fail_create_wsz; - if (task->map_length) { - ret = device_create_file(&dev->dev, &dev_attr_mmap); - if (unlikely(ret)) - goto fail_create_mmap; - } - if (sndtyp_wd(ttyp)) { - ret = device_create_file(&dev->dev, &dev_attr_fifosz); - if (unlikely(ret)) - goto fail_create_fifosz; - ret = device_create_file(&dev->dev, &dev_attr_fifocnt); - if (unlikely(ret)) - goto fail_create_fifocnt; - } else { - ret = device_create_file(&dev->dev, &dev_attr_ipblink); - if (unlikely(ret)) - goto fail_create_ipblink; - } - - dev->task = task; - task->dev = dev; - - return 0; - - fail_create_fifocnt: - device_remove_file(&dev->dev, &dev_attr_fifosz); - fail_create_ipblink: - fail_create_fifosz: - if (task->map_length) - device_remove_file(&dev->dev, &dev_attr_mmap); - fail_create_mmap: - device_remove_file(&dev->dev, &dev_attr_wsz); - fail_create_wsz: - device_remove_file(&dev->dev, &dev_attr_ttyp); - fail_create_ttyp: - device_remove_file(&dev->dev, &dev_attr_taskname); - fail_create_taskname: - if (task->map_length) - dev->fops.mmap = NULL; - - dev->fops.write = NULL; - dev->wsz = 0; - - dev->fops.read = NULL; - taskdev_flush_buf(dev); - - if (sndtyp_wd(ttyp)) - kfifo_free(dev->rcvdt.fifo); - - dev->task = NULL; - - return ret; -} - -static void taskdev_detach_task(struct taskdev *dev) -{ - u16 ttyp = dev->task->ttyp; - - device_remove_file(&dev->dev, &dev_attr_taskname); - device_remove_file(&dev->dev, &dev_attr_ttyp); - if (sndtyp_wd(ttyp)) { - device_remove_file(&dev->dev, &dev_attr_fifosz); - device_remove_file(&dev->dev, &dev_attr_fifocnt); - } else - device_remove_file(&dev->dev, &dev_attr_ipblink); - device_remove_file(&dev->dev, &dev_attr_wsz); - if (dev->task->map_length) { - device_remove_file(&dev->dev, &dev_attr_mmap); - dev->fops.mmap = NULL; - } - - dev->fops.read = NULL; - taskdev_flush_buf(dev); - if (sndtyp_wd(ttyp)) - kfifo_free(dev->rcvdt.fifo); - - dev->fops.write = NULL; - dev->wsz = 0; - - pr_info("omapdsp: taskdev %s disabled.\n", dev->name); - dev->task = NULL; -} - -/* - * tadd / tdel / tkill - */ -static int dsp_tadd(struct taskdev *dev, dsp_long_t adr) -{ - struct dsptask *task; - struct mb_exarg arg; - u8 tid, tid_response; - u16 argv[2]; - int ret = 0; - - if (!devstate_write_lock_and_test(dev, TASKDEV_ST_ADDREQ)) { - printk(KERN_ERR - "omapdsp: taskdev %s is not requesting for tadd. " - "(state is %s)\n", dev->name, devstate_name(dev->state)); - return -EINVAL; - } - set_taskdev_state(dev, TASKDEV_ST_ADDING); - devstate_write_unlock(dev); - - if (adr == TADD_ABORTADR) { - /* aborting tadd intentionally */ - pr_info("omapdsp: tadd address is ABORTADR.\n"); - goto fail_out; - } - if (adr >= DSPSPACE_SIZE) { - printk(KERN_ERR - "omapdsp: illegal address 0x%08x for tadd\n", adr); - ret = -EINVAL; - goto fail_out; - } - - adr >>= 1; /* word address */ - argv[0] = adr >> 16; /* addrh */ - argv[1] = adr & 0xffff; /* addrl */ - - if (mutex_lock_interruptible(&cfg_lock)) { - ret = -EINTR; - goto fail_out; - } - cfg_tid = TID_ANON; - cfg_cmd = MBOX_CMD_DSP_TADD; - arg.tid = TID_ANON; - arg.argc = 2; - arg.argv = argv; - - if (dsp_mem_sync_inc() < 0) { - printk(KERN_ERR "omapdsp: memory sync failed!\n"); - ret = -EBUSY; - goto fail_out; - } - mbcompose_send_and_wait_exarg(TADD, 0, 0, &arg, &cfg_wait_q); - - tid = cfg_tid; - cfg_tid = TID_ANON; - cfg_cmd = 0; - mutex_unlock(&cfg_lock); - - if (tid == TID_ANON) { - printk(KERN_ERR "omapdsp: tadd failed!\n"); - ret = -EINVAL; - goto fail_out; - } - if ((tid < n_task) || dsptask[tid]) { - printk(KERN_ERR "omapdsp: illegal tid (%d)!\n", tid); - ret = -EINVAL; - goto fail_out; - } - if ((task = kzalloc(sizeof(struct dsptask), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto del_out; - } - - if ((ret = dsp_task_config(task, tid)) < 0) - goto free_out; - - if (strcmp(dev->name, task->name)) { - printk(KERN_ERR - "omapdsp: task name (%s) doesn't match with " - "device name (%s).\n", task->name, dev->name); - ret = -EINVAL; - goto free_out; - } - - if ((ret = taskdev_attach_task(dev, task)) < 0) - goto free_out; - - dsp_task_init(task); - pr_info("omapdsp: taskdev %s enabled.\n", dev->name); - set_taskdev_state(dev, TASKDEV_ST_ATTACHED); - wake_up_interruptible_all(&dev->state_wait_q); - return 0; - -free_out: - kfree(task); - -del_out: - printk(KERN_ERR "omapdsp: deleting the task...\n"); - - set_taskdev_state(dev, TASKDEV_ST_DELING); - - if (mutex_lock_interruptible(&cfg_lock)) { - printk(KERN_ERR "omapdsp: aborting tdel process. " - "DSP side could be corrupted.\n"); - goto fail_out; - } - cfg_tid = TID_ANON; - cfg_cmd = MBOX_CMD_DSP_TDEL; - mbcompose_send_and_wait(TDEL, tid, TDEL_KILL, &cfg_wait_q); - tid_response = cfg_tid; - cfg_tid = TID_ANON; - cfg_cmd = 0; - mutex_unlock(&cfg_lock); - - if (tid_response != tid) - printk(KERN_ERR "omapdsp: tdel failed. " - "DSP side could be corrupted.\n"); - -fail_out: - set_taskdev_state(dev, TASKDEV_ST_ADDFAIL); - wake_up_interruptible_all(&dev->state_wait_q); - return ret; -} - -int dsp_tadd_minor(unsigned char minor, dsp_long_t adr) -{ - struct taskdev *dev; - int status; - int ret; - - if (mutex_lock_interruptible(&devmgr_lock)) - return -EINTR; - - if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) { - printk(KERN_ERR - "omapdsp: no task device with minor %d\n", minor); - ret = -EINVAL; - goto out; - } - ret = minor; - if ((status = dsp_tadd(dev, adr)) < 0) - ret = status; - -out: - mutex_unlock(&devmgr_lock); - return ret; -} - -static int dsp_tdel(struct taskdev *dev) -{ - if (!devstate_write_lock_and_test(dev, TASKDEV_ST_DELREQ)) { - printk(KERN_ERR - "omapdsp: taskdev %s is not requesting for tdel. " - "(state is %s)\n", dev->name, devstate_name(dev->state)); - return -EINVAL; - } - set_taskdev_state(dev, TASKDEV_ST_DELING); - devstate_write_unlock(dev); - - return dsp_tdel_bh(dev, TDEL_SAFE); -} - -int dsp_tdel_minor(unsigned char minor) -{ - struct taskdev *dev; - int status; - int ret; - - if (mutex_lock_interruptible(&devmgr_lock)) - return -EINTR; - - if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) { - printk(KERN_ERR - "omapdsp: no task device with minor %d\n", minor); - ret = -EINVAL; - goto out; - } - - ret = minor; - if ((status = dsp_tdel(dev)) < 0) - ret = status; - -out: - mutex_unlock(&devmgr_lock); - return ret; -} - -static int dsp_tkill(struct taskdev *dev) -{ - while (!down_write_trylock(&dev->state_sem)) { - if (!devstate_read_lock_and_test(dev, (TASKDEV_ST_ATTACHED | - TASKDEV_ST_FREEZED))) { - printk(KERN_ERR - "omapdsp: task has not been attached for " - "taskdev %s\n", dev->name); - return -EINVAL; - } - /* ATTACHED -> FREEZED can be changed under read semaphore. */ - set_taskdev_state(dev, TASKDEV_ST_FREEZED); - wake_up_interruptible_all(&dev->read_wait_q); - wake_up_interruptible_all(&dev->write_wait_q); - wake_up_interruptible_all(&dev->tctl_wait_q); - devstate_read_unlock(dev); - schedule(); - } - - if (!(dev->state & (TASKDEV_ST_ATTACHED | - TASKDEV_ST_FREEZED))) { - printk(KERN_ERR - "omapdsp: task has not been attached for taskdev %s\n", - dev->name); - devstate_write_unlock(dev); - return -EINVAL; - } - if (!is_dynamic_task(dev->task->tid)) { - printk(KERN_ERR "omapdsp: task %s is not a dynamic task.\n", - dev->name); - devstate_write_unlock(dev); - return -EINVAL; - } - set_taskdev_state(dev, TASKDEV_ST_KILLING); - devstate_write_unlock(dev); - - return dsp_tdel_bh(dev, TDEL_KILL); -} - -int dsp_tkill_minor(unsigned char minor) -{ - struct taskdev *dev; - int status; - int ret; - - if (mutex_lock_interruptible(&devmgr_lock)) - return -EINTR; - - if ((minor >= TASKDEV_MAX) || ((dev = taskdev[minor]) == NULL)) { - printk(KERN_ERR - "omapdsp: no task device with minor %d\n", minor); - ret = -EINVAL; - goto out; - } - - ret = minor; - if ((status = dsp_tkill(dev)) < 0) - ret = status; - -out: - mutex_unlock(&devmgr_lock); - return ret; -} - -static int dsp_tdel_bh(struct taskdev *dev, u16 type) -{ - struct dsptask *task; - u8 tid, tid_response; - int ret = 0; - - task = dev->task; - tid = task->tid; - if (mutex_lock_interruptible(&cfg_lock)) { - if (type == TDEL_SAFE) { - set_taskdev_state(dev, TASKDEV_ST_DELREQ); - return -EINTR; - } else { - tid_response = TID_ANON; - ret = -EINTR; - goto detach_out; - } - } - cfg_tid = TID_ANON; - cfg_cmd = MBOX_CMD_DSP_TDEL; - mbcompose_send_and_wait(TDEL, tid, type, &cfg_wait_q); - tid_response = cfg_tid; - cfg_tid = TID_ANON; - cfg_cmd = 0; - mutex_unlock(&cfg_lock); - -detach_out: - taskdev_detach_task(dev); - dsp_task_unconfig(task); - kfree(task); - - if (tid_response != tid) { - printk(KERN_ERR "omapdsp: %s failed!\n", - (type == TDEL_SAFE) ? "tdel" : "tkill"); - ret = -EINVAL; - } - down_write(&dev->state_sem); - set_taskdev_state(dev, (dev->usecount > 0) ? TASKDEV_ST_GARBAGE : - TASKDEV_ST_NOTASK); - wake_up_interruptible_all(&dev->state_wait_q); - up_write(&dev->state_sem); - - return ret; -} - -/* - * state inquiry - */ -long taskdev_state_stale(unsigned char minor) -{ - if (taskdev[minor]) { - long state = taskdev[minor]->state; - taskdev[minor]->state |= TASKDEV_ST_STALE; - return state; - } else - return TASKDEV_ST_NOTASK; -} - -/* - * functions called from mailbox interrupt routine - */ -void mbox_wdsnd(struct mbcmd *mb) -{ - unsigned int n; - u8 tid = mb->cmd_l; - u16 data = mb->data; - struct dsptask *task = dsptask[tid]; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: WDSND with illegal tid! %d\n", tid); - return; - } - if (sndtyp_bk(task->ttyp)) { - printk(KERN_ERR - "mbox: WDSND from block sending task! (task%d)\n", tid); - return; - } - if (sndtyp_psv(task->ttyp) && - !waitqueue_active(&task->dev->read_wait_q)) { - printk(KERN_WARNING - "mbox: WDSND from passive sending task (task%d) " - "without request!\n", tid); - return; - } - - n = kfifo_put(task->dev->rcvdt.fifo, (unsigned char *)&data, - sizeof(data)); - if (n != sizeof(data)) - printk(KERN_WARNING "Receive FIFO(%d) is full\n", tid); - - wake_up_interruptible(&task->dev->read_wait_q); -} - -void mbox_wdreq(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - struct dsptask *task = dsptask[tid]; - struct taskdev *dev; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: WDREQ with illegal tid! %d\n", tid); - return; - } - if (rcvtyp_psv(task->ttyp)) { - printk(KERN_ERR - "mbox: WDREQ from passive receiving task! (task%d)\n", - tid); - return; - } - - dev = task->dev; - spin_lock(&dev->wsz_lock); - dev->wsz = 2; - spin_unlock(&dev->wsz_lock); - wake_up_interruptible(&dev->write_wait_q); -} - -void mbox_bksnd(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - u16 bid = mb->data; - struct dsptask *task = dsptask[tid]; - struct ipbuf_head *ipb_h; - u16 cnt; - - if (bid >= ipbcfg.ln) { - printk(KERN_ERR "mbox: BKSND with illegal bid! %d\n", bid); - return; - } - ipb_h = bid_to_ipbuf(bid); - ipb_bsycnt_dec(&ipbcfg); - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: BKSND with illegal tid! %d\n", tid); - goto unuse_ipbuf_out; - } - if (sndtyp_wd(task->ttyp)) { - printk(KERN_ERR - "mbox: BKSND from word sending task! (task%d)\n", tid); - goto unuse_ipbuf_out; - } - if (sndtyp_pvt(task->ttyp)) { - printk(KERN_ERR - "mbox: BKSND from private sending task! (task%d)\n", tid); - goto unuse_ipbuf_out; - } - if (sync_with_dsp(&ipb_h->p->sd, tid, 10) < 0) { - printk(KERN_ERR "mbox: BKSND - IPBUF sync failed!\n"); - return; - } - - /* should be done in DSP, but just in case. */ - ipb_h->p->next = BID_NULL; - - cnt = ipb_h->p->c; - if (cnt > ipbcfg.lsz) { - printk(KERN_ERR "mbox: BKSND cnt(%d) > ipbuf line size(%d)!\n", - cnt, ipbcfg.lsz); - goto unuse_ipbuf_out; - } - - if (cnt == 0) { - /* 0-byte send from DSP */ - unuse_ipbuf_nowait(ipb_h); - goto done; - } - ipblink_add_tail(&task->dev->rcvdt.bk.link, bid); - /* we keep coming bid and return alternative line to DSP. */ - balance_ipbuf(); - -done: - wake_up_interruptible(&task->dev->read_wait_q); - return; - -unuse_ipbuf_out: - unuse_ipbuf_nowait(ipb_h); - return; -} - -void mbox_bkreq(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - u16 cnt = mb->data; - struct dsptask *task = dsptask[tid]; - struct taskdev *dev; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: BKREQ with illegal tid! %d\n", tid); - return; - } - if (rcvtyp_wd(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQ from word receiving task! (task%d)\n", tid); - return; - } - if (rcvtyp_pvt(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQ from private receiving task! (task%d)\n", - tid); - return; - } - if (rcvtyp_psv(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQ from passive receiving task! (task%d)\n", - tid); - return; - } - - dev = task->dev; - spin_lock(&dev->wsz_lock); - dev->wsz = cnt*2; - spin_unlock(&dev->wsz_lock); - wake_up_interruptible(&dev->write_wait_q); -} - -void mbox_bkyld(struct mbcmd *mb) -{ - u16 bid = mb->data; - struct ipbuf_head *ipb_h; - - if (bid >= ipbcfg.ln) { - printk(KERN_ERR "mbox: BKYLD with illegal bid! %d\n", bid); - return; - } - ipb_h = bid_to_ipbuf(bid); - - /* should be done in DSP, but just in case. */ - ipb_h->p->next = BID_NULL; - - /* we don't need to sync with DSP */ - ipb_bsycnt_dec(&ipbcfg); - release_ipbuf(ipb_h); -} - -void mbox_bksndp(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - struct dsptask *task = dsptask[tid]; - struct ipbuf_p *ipbp; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: BKSNDP with illegal tid! %d\n", tid); - return; - } - if (sndtyp_wd(task->ttyp)) { - printk(KERN_ERR - "mbox: BKSNDP from word sending task! (task%d)\n", tid); - return; - } - if (sndtyp_gbl(task->ttyp)) { - printk(KERN_ERR - "mbox: BKSNDP from non-private sending task! (task%d)\n", - tid); - return; - } - - /* - * we should not have delayed block at this point - * because read() routine releases the lock of the buffer and - * until then DSP can't send next data. - */ - - ipbp = task->ipbuf_pvt_r; - if (sync_with_dsp(&ipbp->s, tid, 10) < 0) { - printk(KERN_ERR "mbox: BKSNDP - IPBUF sync failed!\n"); - return; - } - pr_debug("mbox: ipbuf_pvt_r->a = 0x%08lx\n", - MKLONG(ipbp->ah, ipbp->al)); - ipblink_add_pvt(&task->dev->rcvdt.bk.link); - wake_up_interruptible(&task->dev->read_wait_q); -} - -void mbox_bkreqp(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - struct dsptask *task = dsptask[tid]; - struct taskdev *dev; - struct ipbuf_p *ipbp; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: BKREQP with illegal tid! %d\n", tid); - return; - } - if (rcvtyp_wd(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQP from word receiving task! (task%d)\n", tid); - return; - } - if (rcvtyp_gbl(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQP from non-private receiving task! (task%d)\n", tid); - return; - } - if (rcvtyp_psv(task->ttyp)) { - printk(KERN_ERR - "mbox: BKREQP from passive receiving task! (task%d)\n", tid); - return; - } - - ipbp = task->ipbuf_pvt_w; - if (sync_with_dsp(&ipbp->s, TID_FREE, 10) < 0) { - printk(KERN_ERR "mbox: BKREQP - IPBUF sync failed!\n"); - return; - } - pr_debug("mbox: ipbuf_pvt_w->a = 0x%08lx\n", - MKLONG(ipbp->ah, ipbp->al)); - dev = task->dev; - spin_lock(&dev->wsz_lock); - dev->wsz = ipbp->c*2; - spin_unlock(&dev->wsz_lock); - wake_up_interruptible(&dev->write_wait_q); -} - -void mbox_tctl(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - struct dsptask *task = dsptask[tid]; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: TCTL with illegal tid! %d\n", tid); - return; - } - - if (!waitqueue_active(&task->dev->tctl_wait_q)) { - printk(KERN_WARNING "mbox: unexpected TCTL from DSP!\n"); - return; - } - - task->dev->tctl_stat = mb->data; - wake_up_interruptible(&task->dev->tctl_wait_q); -} - -void mbox_tcfg(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - struct dsptask *task = dsptask[tid]; - u16 *tnm; - volatile u16 *buf; - int i; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: TCFG with illegal tid! %d\n", tid); - return; - } - if ((task->state != TASK_ST_CFGREQ) || (cfg_cmd != MBOX_CMD_DSP_TCFG)) { - printk(KERN_WARNING "mbox: unexpected TCFG from DSP!\n"); - return; - } - - if (dsp_mem_enable(ipbuf_sys_da) < 0) { - printk(KERN_ERR "mbox: TCFG - ipbuf_sys_da read failed!\n"); - dsp_mem_disable(ipbuf_sys_da); - goto out; - } - if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) { - printk(KERN_ERR "mbox: TCFG - IPBUF sync failed!\n"); - dsp_mem_disable(ipbuf_sys_da); - goto out; - } - - /* - * read configuration data on system IPBUF - */ - buf = ipbuf_sys_da->d; - task->ttyp = buf[0]; - task->ipbuf_pvt_r = MKVIRT(buf[1], buf[2]); - task->ipbuf_pvt_w = MKVIRT(buf[3], buf[4]); - task->map_base = MKVIRT(buf[5], buf[6]); - task->map_length = MKLONG(buf[7], buf[8]) << 1; /* word -> byte */ - tnm = MKVIRT(buf[9], buf[10]); - release_ipbuf_pvt(ipbuf_sys_da); - dsp_mem_disable(ipbuf_sys_da); - - /* - * copy task name string - */ - if (dsp_address_validate(tnm, TNM_LEN, "task name buffer") < 0) { - task->name[0] = '\0'; - goto out; - } - - for (i = 0; i < TNM_LEN-1; i++) { - /* avoiding byte access */ - u16 tmp = tnm[i]; - task->name[i] = tmp & 0x00ff; - if (!tmp) - break; - } - task->name[TNM_LEN-1] = '\0'; - - task->state = TASK_ST_READY; -out: - wake_up_interruptible(&cfg_wait_q); -} - -void mbox_tadd(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - - if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TADD)) { - printk(KERN_WARNING "mbox: unexpected TADD from DSP!\n"); - return; - } - cfg_tid = tid; - wake_up_interruptible(&cfg_wait_q); -} - -void mbox_tdel(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - - if ((!waitqueue_active(&cfg_wait_q)) || (cfg_cmd != MBOX_CMD_DSP_TDEL)) { - printk(KERN_WARNING "mbox: unexpected TDEL from DSP!\n"); - return; - } - cfg_tid = tid; - wake_up_interruptible(&cfg_wait_q); -} - -void mbox_err_fatal(u8 tid) -{ - struct dsptask *task = dsptask[tid]; - struct taskdev *dev; - - if ((tid >= TASKDEV_MAX) || (task == NULL)) { - printk(KERN_ERR "mbox: FATAL ERR with illegal tid! %d\n", tid); - return; - } - - /* wake up waiting processes */ - dev = task->dev; - wake_up_interruptible_all(&dev->read_wait_q); - wake_up_interruptible_all(&dev->write_wait_q); - wake_up_interruptible_all(&dev->tctl_wait_q); -} - -static u16 *dbg_buf; -static u16 dbg_buf_sz, dbg_line_sz; -static int dbg_rp; - -int dsp_dbg_config(u16 *buf, u16 sz, u16 lsz) -{ -#ifdef OLD_BINARY_SUPPORT - if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) { - dbg_buf = NULL; - dbg_buf_sz = 0; - dbg_line_sz = 0; - dbg_rp = 0; - return 0; - } -#endif - - if (dsp_address_validate(buf, sz, "debug buffer") < 0) - return -1; - - if (lsz > sz) { - printk(KERN_ERR - "omapdsp: dbg_buf lsz (%d) is greater than its " - "buffer size (%d)\n", lsz, sz); - return -1; - } - - dbg_buf = buf; - dbg_buf_sz = sz; - dbg_line_sz = lsz; - dbg_rp = 0; - - return 0; -} - -void dsp_dbg_stop(void) -{ - dbg_buf = NULL; -} - -#ifdef OLD_BINARY_SUPPORT -static void mbox_dbg_old(struct mbcmd *mb); -#endif - -void mbox_dbg(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - int cnt = mb->data; - char s[80], *s_end = &s[79], *p; - u16 *src; - int i; - -#ifdef OLD_BINARY_SUPPORT - if ((mbox_revision == MBREV_3_0) || (mbox_revision == MBREV_3_2)) { - mbox_dbg_old(mb); - return; - } -#endif - - if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) && - (tid != TID_ANON)) { - printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid); - return; - } - if (dbg_buf == NULL) { - printk(KERN_ERR "mbox: DBG command received, but " - "dbg_buf has not been configured yet.\n"); - return; - } - - if (dsp_mem_enable(dbg_buf) < 0) - return; - - src = &dbg_buf[dbg_rp]; - p = s; - for (i = 0; i < cnt; i++) { - u16 tmp; - /* - * Be carefull that dbg_buf should not be read with - * 1-byte access since it might be placed in DARAM/SARAM - * and it can cause unexpected byteswap. - * For example, - * *(p++) = *(src++) & 0xff; - * causes 1-byte access! - */ - tmp = *src++; - *(p++) = tmp & 0xff; - if (*(p-1) == '\n') { - *p = '\0'; - pr_info("%s", s); - p = s; - continue; - } - if (p == s_end) { - *p = '\0'; - pr_info("%s\n", s); - p = s; - continue; - } - } - if (p > s) { - *p = '\0'; - pr_info("%s\n", s); - } - if ((dbg_rp += cnt + 1) > dbg_buf_sz - dbg_line_sz) - dbg_rp = 0; - - dsp_mem_disable(dbg_buf); -} - -#ifdef OLD_BINARY_SUPPORT -static void mbox_dbg_old(struct mbcmd *mb) -{ - u8 tid = mb->cmd_l; - char s[80], *s_end = &s[79], *p; - u16 *src; - volatile u16 *buf; - int cnt; - int i; - - if (((tid >= TASKDEV_MAX) || (dsptask[tid] == NULL)) && - (tid != TID_ANON)) { - printk(KERN_ERR "mbox: DBG with illegal tid! %d\n", tid); - return; - } - if (dsp_mem_enable(ipbuf_sys_da) < 0) { - printk(KERN_ERR "mbox: DBG - ipbuf_sys_da read failed!\n"); - return; - } - if (sync_with_dsp(&ipbuf_sys_da->s, tid, 10) < 0) { - printk(KERN_ERR "mbox: DBG - IPBUF sync failed!\n"); - goto out1; - } - buf = ipbuf_sys_da->d; - cnt = buf[0]; - src = MKVIRT(buf[1], buf[2]); - if (dsp_address_validate(src, cnt, "dbg buffer") < 0) - goto out2; - - if (dsp_mem_enable(src) < 0) - goto out2; - - p = s; - for (i = 0; i < cnt; i++) { - u16 tmp; - /* - * Be carefull that ipbuf should not be read with - * 1-byte access since it might be placed in DARAM/SARAM - * and it can cause unexpected byteswap. - * For example, - * *(p++) = *(src++) & 0xff; - * causes 1-byte access! - */ - tmp = *src++; - *(p++) = tmp & 0xff; - if (*(p-1) == '\n') { - *p = '\0'; - pr_info("%s", s); - p = s; - continue; - } - if (p == s_end) { - *p = '\0'; - pr_info("%s\n", s); - p = s; - continue; - } - } - if (p > s) { - *p = '\0'; - pr_info("%s\n", s); - } - - dsp_mem_disable(src); -out2: - release_ipbuf_pvt(ipbuf_sys_da); -out1: - dsp_mem_disable(ipbuf_sys_da); -} -#endif /* OLD_BINARY_SUPPORT */ - -/* - * sysfs files: for each device - */ - -/* devname */ -static ssize_t devname_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", to_taskdev(d)->name); -} - -/* devstate */ -static ssize_t devstate_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%s\n", devstate_name(to_taskdev(d)->state)); -} - -/* proc_list */ -static ssize_t proc_list_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct taskdev *dev; - struct proc_list *pl; - int len = 0; - - dev = to_taskdev(d); - spin_lock(&dev->proc_list_lock); - list_for_each_entry(pl, &dev->proc_list, list_head) { - /* need to lock tasklist_lock before calling - * find_task_by_pid_type. */ - if (find_task_by_pid_type_ns(PIDTYPE_PID, pl->pid, &init_pid_ns) != NULL) - len += sprintf(buf + len, "%d\n", pl->pid); - read_unlock(&tasklist_lock); - } - spin_unlock(&dev->proc_list_lock); - - return len; -} - -/* taskname */ -static ssize_t taskname_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct taskdev *dev = to_taskdev(d); - int len; - - if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED)) - return -ENODEV; - - len = sprintf(buf, "%s\n", dev->task->name); - - devstate_read_unlock(dev); - return len; -} - -/* ttyp */ -static ssize_t ttyp_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct taskdev *dev = to_taskdev(d); - u16 ttyp; - int len = 0; - - if (!devstate_read_lock_and_test(dev, TASKDEV_ST_ATTACHED)) - return -ENODEV; - - ttyp = dev->task->ttyp; - len += sprintf(buf + len, "0x%04x\n", ttyp); - len += sprintf(buf + len, "%s %s send\n", - (sndtyp_acv(ttyp)) ? "active" : - "passive", - (sndtyp_wd(ttyp)) ? "word" : - (sndtyp_pvt(ttyp)) ? "private block" : - "global block"); - len += sprintf(buf + len, "%s %s receive\n", - (rcvtyp_acv(ttyp)) ? "active" : - "passive", - (rcvtyp_wd(ttyp)) ? "word" : - (rcvtyp_pvt(ttyp)) ? "private block" : - "global block"); - - devstate_read_unlock(dev); - return len; -} - -/* fifosz */ -static ssize_t fifosz_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo; - return sprintf(buf, "%d\n", fifo->size); -} - -static int fifosz_store(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct taskdev *dev = to_taskdev(d); - unsigned long fifosz; - int ret; - - fifosz = simple_strtol(buf, NULL, 10); - if (taskdev_lock_and_statelock_attached(dev, &dev->read_mutex)) - return -ENODEV; - ret = taskdev_set_fifosz(dev, fifosz); - taskdev_unlock_and_stateunlock(dev, &dev->read_mutex); - - return (ret < 0) ? ret : strlen(buf); -} - -/* fifocnt */ -static ssize_t fifocnt_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct kfifo *fifo = to_taskdev(d)->rcvdt.fifo; - return sprintf(buf, "%d\n", fifo->size); -} - -/* ipblink */ -static inline char *bid_name(u16 bid) -{ - static char s[6]; - - switch (bid) { - case BID_NULL: - return "NULL"; - case BID_PVT: - return "PRIVATE"; - default: - sprintf(s, "%d", bid); - return s; - } -} - -static ssize_t ipblink_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct rcvdt_bk_struct *rcvdt = &to_taskdev(d)->rcvdt.bk; - int len; - - spin_lock(&rcvdt->link.lock); - len = sprintf(buf, "top %s\ntail %s\n", - bid_name(rcvdt->link.top), bid_name(rcvdt->link.tail)); - spin_unlock(&rcvdt->link.lock); - - return len; -} - -/* wsz */ -static ssize_t wsz_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", to_taskdev(d)->wsz); -} - -/* mmap */ -static ssize_t mmap_show(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct dsptask *task = to_taskdev(d)->task; - return sprintf(buf, "0x%p 0x%x\n", task->map_base, task->map_length); -} - -/* - * called from ipbuf_show() - */ -int ipbuf_is_held(u8 tid, u16 bid) -{ - struct dsptask *task = dsptask[tid]; - struct ipblink *link; - u16 b; - int ret = 0; - - if (task == NULL) - return 0; - - link = &task->dev->rcvdt.bk.link; - spin_lock(&link->lock); - ipblink_for_each(b, link) { - if (b == bid) { /* found */ - ret = 1; - break; - } - } - spin_unlock(&link->lock); - - return ret; -} - -int __init dsp_taskmod_init(void) -{ - int retval; - - memset(taskdev, 0, sizeof(void *) * TASKDEV_MAX); - memset(dsptask, 0, sizeof(void *) * TASKDEV_MAX); - - retval = register_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask", - &dsp_task_fops); - if (retval < 0) { - printk(KERN_ERR - "omapdsp: failed to register task device: %d\n", retval); - return retval; - } - - retval = bus_register(&dsptask_bus); - if (retval) { - printk(KERN_ERR - "omapdsp: failed to register DSP task bus: %d\n", - retval); - unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask"); - return -EINVAL; - } - retval = driver_register(&dsptask_driver); - if (retval) { - printk(KERN_ERR - "omapdsp: failed to register DSP task driver: %d\n", - retval); - bus_unregister(&dsptask_bus); - unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask"); - return -EINVAL; - } - dsp_task_class = class_create(THIS_MODULE, "dsptask"); - if (IS_ERR(dsp_task_class)) { - printk(KERN_ERR "omapdsp: failed to create DSP task class\n"); - driver_unregister(&dsptask_driver); - bus_unregister(&dsptask_bus); - unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask"); - return -EINVAL; - } - - return 0; -} - -void dsp_taskmod_exit(void) -{ - class_destroy(dsp_task_class); - driver_unregister(&dsptask_driver); - bus_unregister(&dsptask_bus); - unregister_chrdev(OMAP_DSP_TASK_MAJOR, "dsptask"); -} diff --git a/drivers/dsp/dspgateway/taskwatch.c b/drivers/dsp/dspgateway/taskwatch.c deleted file mode 100644 index a5fea3df1a1..00000000000 --- a/drivers/dsp/dspgateway/taskwatch.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "dsp_mbcmd.h" -#include "dsp.h" - -static DECLARE_WAIT_QUEUE_HEAD(read_wait_q); -static unsigned int change_cnt; - -void dsp_twch_touch(void) -{ - change_cnt++; - wake_up_interruptible(&read_wait_q); -} - -/* - * @count: represents the device counts of the user's interst - */ -static ssize_t dsp_twch_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - long taskstat[TASKDEV_MAX]; - int devcount = count / sizeof(long); - int i; - DEFINE_WAIT(wait); - - if (dsp_cfgstat_get_stat() != CFGSTAT_READY) { - printk(KERN_ERR "omapdsp: dsp has not been configured.\n"); - return -EINVAL; - } - - prepare_to_wait(&read_wait_q, &wait, TASK_INTERRUPTIBLE); - if (change_cnt == 0) /* last check */ - schedule(); - finish_wait(&read_wait_q, &wait); - - /* unconfigured while waiting ;-( */ - if ((change_cnt == 0) && (dsp_cfgstat_get_stat() != CFGSTAT_READY)) - return -EINVAL; - - if (devcount > TASKDEV_MAX) - devcount = TASKDEV_MAX; - - count = devcount * sizeof(long); - change_cnt = 0; - for (i = 0; i < devcount; i++) { - /* - * once the device state is read, the 'STALE' bit will be set - * so that the Dynamic Loader can distinguish the new request - * from the old one. - */ - taskstat[i] = taskdev_state_stale(i); - } - - if (copy_to_user(buf, taskstat, count)) - return -EFAULT; - - return count; -} - -static unsigned int dsp_twch_poll(struct file *file, poll_table *wait) -{ - unsigned int mask = 0; - - poll_wait(file, &read_wait_q, wait); - if (change_cnt) - mask |= POLLIN | POLLRDNORM; - - return mask; -} - -static int dsp_twch_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int ret; - - switch (cmd) { - case TWCH_IOCTL_MKDEV: - { - char name[TNM_LEN]; - if (copy_from_user(name, (void __user *)arg, TNM_LEN)) - return -EFAULT; - name[TNM_LEN-1] = '\0'; - ret = dsp_mkdev(name); - break; - } - - case TWCH_IOCTL_RMDEV: - { - char name[TNM_LEN]; - if (copy_from_user(name, (void __user *)arg, TNM_LEN)) - return -EFAULT; - name[TNM_LEN-1] = '\0'; - ret = dsp_rmdev(name); - break; - } - - case TWCH_IOCTL_TADD: - { - struct omap_dsp_taddinfo ti; - if (copy_from_user(&ti, (void __user *)arg, sizeof(ti))) - return -EFAULT; - ret = dsp_tadd_minor(ti.minor, ti.taskadr); - break; - } - - case TWCH_IOCTL_TDEL: - ret = dsp_tdel_minor(arg); - break; - - case TWCH_IOCTL_TKILL: - ret = dsp_tkill_minor(arg); - break; - - default: - return -ENOIOCTLCMD; - } - - return ret; -} - -struct file_operations dsp_twch_fops = { - .owner = THIS_MODULE, - .read = dsp_twch_read, - .poll = dsp_twch_poll, - .ioctl = dsp_twch_ioctl, -}; - -void dsp_twch_start(void) -{ - change_cnt = 1; /* first read will not wait */ -} - -void dsp_twch_stop(void) -{ - wake_up_interruptible(&read_wait_q); -} diff --git a/drivers/dsp/dspgateway/uaccess_dsp.S b/drivers/dsp/dspgateway/uaccess_dsp.S deleted file mode 100644 index bcf4a547499..00000000000 --- a/drivers/dsp/dspgateway/uaccess_dsp.S +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2004-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - - .text - -/* Prototype: int __copy_to_user_dsp_2b(void *to, const char *from) - * Purpose : copy 2 bytes to user memory from kernel(DSP) memory - * escaping from unexpected byte swap using __copy_to_user() - * in OMAP architecture. - * Params : to - user memory - * : from - kernel(DSP) memory - * Returns : success = 0, failure = 2 - */ - -ENTRY(__copy_to_user_dsp_2b) - stmfd sp!, {r4, lr} - ldrb r3, [r1], #1 - ldrb r4, [r1], #1 -USER( strbt r4, [r0], #1) @ May fault -USER( strbt r3, [r0], #1) @ May fault - mov r0, #0 - ldmfd sp!, {r4, pc} - - .section .fixup,"ax" - .align 0 -9001: mov r0, #2 - ldmfd sp!, {r4, pc} - .previous - -/* Prototype: unsigned long __copy_from_user_dsp_2b(void *to, const void *from); - * Purpose : copy 2 bytes from user memory to kernel(DSP) memory - * escaping from unexpected byte swap using __copy_to_user() - * in OMAP architecture. - * Params : to - kernel (DSP) memory - * : from - user memory - * Returns : success = 0, failure = 2 - */ - -ENTRY(__copy_from_user_dsp_2b) - stmfd sp!, {r4, lr} -USER( ldrbt r3, [r1], #1) @ May fault -USER( ldrbt r4, [r1], #1) @ May fault - strb r4, [r0], #1 - strb r3, [r0], #1 - mov r0, #0 - ldmfd sp!, {r4, pc} - - .section .fixup,"ax" - .align 0 -9001: mov r3, #0 - strh r3, [r0], #2 - mov r0, #2 - ldmfd sp!, {r4, pc} - .previous diff --git a/drivers/dsp/dspgateway/uaccess_dsp.h b/drivers/dsp/dspgateway/uaccess_dsp.h deleted file mode 100644 index 839a51aa071..00000000000 --- a/drivers/dsp/dspgateway/uaccess_dsp.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of OMAP DSP driver (DSP Gateway version 3.3.1) - * - * Copyright (C) 2002-2006 Nokia Corporation. All rights reserved. - * - * Contact: Toshihiro Kobayashi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef _OMAP_DSP_UACCESS_DSP_H -#define _OMAP_DSP_UACCESS_DSP_H - -#include -#include -#include "dsp.h" - -#define HAVE_ASM_COPY_FROM_USER_DSP_2B - -#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B -extern unsigned long __copy_from_user_dsp_2b(void *to, - const void __user *from); -extern unsigned long __copy_to_user_dsp_2b(void __user *to, - const void *from); -#endif - -#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B -static inline unsigned long copy_from_user_dsp_2b(void *to, - const void *from) -{ - unsigned short tmp; - - if (__copy_from_user(&tmp, from, 2)) - return 2; - /* expecting compiler to generate "strh" instruction */ - *((unsigned short *)to) = tmp; - return 0; -} -#endif - -/* - * @n must be multiple of 2 - */ -static inline unsigned long copy_from_user_dsp(void *to, const void *from, - unsigned long n) -{ - if (access_ok(VERIFY_READ, from, n)) { - if ((is_dsp_internal_mem(to)) && - (((unsigned long)to & 2) || (n & 2))) { - /* - * DARAM/SARAM with odd word alignment - */ - unsigned long n4; - unsigned long last_n; - - /* dest not aligned -- copy 2 bytes */ - if (((unsigned long)to & 2) && (n >= 2)) { -#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B - if (__copy_from_user_dsp_2b(to, from)) -#else - if (copy_from_user_dsp_2b(to, from)) -#endif - return n; - to += 2; - from += 2; - n -= 2; - } - /* middle 4*n bytes */ - last_n = n & 2; - n4 = n - last_n; - if ((n = __copy_from_user(to, from, n4)) != 0) - return n + last_n; - /* last 2 bytes */ - if (last_n) { - to += n4; - from += n4; -#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B - if (__copy_from_user_dsp_2b(to, from)) -#else - if (copy_from_user_dsp_2b(to, from)) -#endif - return 2; - n = 0; - } - } else { - /* - * DARAM/SARAM with 4-byte alignment or - * external memory - */ - n = __copy_from_user(to, from, n); - } - } - else /* security hole - plug it */ - memzero(to, n); - return n; -} - -#ifndef HAVE_ASM_COPY_FROM_USER_DSP_2B -static inline unsigned long copy_to_user_dsp_2b(void *to, const void *from) -{ - /* expecting compiler to generate "strh" instruction */ - unsigned short tmp = *(unsigned short *)from; - - return __copy_to_user(to, &tmp, 2); -} -#endif - -/* - * @n must be multiple of 2 - */ -static inline unsigned long copy_to_user_dsp(void *to, const void *from, - unsigned long n) -{ - if (access_ok(VERIFY_WRITE, to, n)) { - if ((is_dsp_internal_mem(from)) && - (((unsigned long)to & 2) || (n & 2))) { - /* - * DARAM/SARAM with odd word alignment - */ - unsigned long n4; - unsigned long last_n; - - /* dest not aligned -- copy 2 bytes */ - if (((unsigned long)to & 2) && (n >= 2)) { -#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B - if (__copy_to_user_dsp_2b(to, from)) -#else - if (copy_to_user_dsp_2b(to, from)) -#endif - return n; - to += 2; - from += 2; - n -= 2; - } - /* middle 4*n bytes */ - last_n = n & 2; - n4 = n - last_n; - if ((n = __copy_to_user(to, from, n4)) != 0) - return n + last_n; - /* last 2 bytes */ - if (last_n) { - to += n4; - from += n4; -#ifdef HAVE_ASM_COPY_FROM_USER_DSP_2B - if (__copy_to_user_dsp_2b(to, from)) -#else - if (copy_to_user_dsp_2b(to, from)) -#endif - return 2; - n = 0; - } - } else { - /* - * DARAM/SARAM with 4-byte alignment or - * external memory - */ - n = __copy_to_user(to, from, n); - } - } - return n; -} - -#endif /* _OMAP_DSP_UACCESS_DSP_H */ diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index 17065f7681a..29f62e1733f 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -41,9 +41,6 @@ extern unsigned int __kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len); extern unsigned int __kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len); -extern unsigned int __kfifo_get_to_user(struct kfifo *fifo, - unsigned char __user *buffer, - unsigned int len); /** * __kfifo_reset - removes the entire FIFO contents, no locking version @@ -152,36 +149,4 @@ static inline unsigned int kfifo_len(struct kfifo *fifo) return ret; } -/** - * kfifo_get_to_user - gets some data from the FIFO - * @fifo: the fifo to be used. - * @buffer: where the data must be copied. user buffer - * @len: the size of the destination buffer. - * - * This function copies at most @len bytes from the FIFO into the - * user @buffer and returns the number of copied bytes. - */ -static inline unsigned int kfifo_get_to_user(struct kfifo *fifo, - unsigned char __user *buffer, - unsigned int len) -{ - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(fifo->lock, flags); - - ret = __kfifo_get_to_user(fifo, buffer, len); - - /* - * optimization: if the FIFO is empty, set the indices to 0 - * so we don't wrap the next time - */ - if (fifo->in == fifo->out) - fifo->in = fifo->out = 0; - - spin_unlock_irqrestore(fifo->lock, flags); - - return ret; -} - #endif diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 6d3e9999cf7..bc41ad0f24f 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -25,7 +25,6 @@ #include #include #include -#include /** * kfifo_init - allocates a new FIFO using a preallocated buffer @@ -196,59 +195,3 @@ unsigned int __kfifo_get(struct kfifo *fifo, return len; } EXPORT_SYMBOL(__kfifo_get); - -/** - * __kfifo_get_to_user - gets some data from the FIFO, no locking version - * @fifo: the fifo to be used. - * @buffer: where the data must be copied. user buffer. - * @len: the size of the destination buffer. - * - * This function copies at most @len bytes from the FIFO into the - * user @buffer and returns the number of copied bytes. - * - * Note that with only one concurrent reader and one concurrent - * writer, you don't need extra locking to use these functions. - */ -unsigned int __kfifo_get_to_user(struct kfifo *fifo, - unsigned char __user *buffer, - unsigned int len) -{ - unsigned int n1, n2; - int ret; - - len = min(len, fifo->in - fifo->out); - - /* - * Ensure that we sample the fifo->in index -before- we - * start removing bytes from the kfifo. - */ - - smp_rmb(); - - /* first get the data from fifo->out until the end of the buffer */ - n1 = min(len, fifo->size - (fifo->out & (fifo->size - 1))); - n2 = len -n1; - ret = copy_to_user(buffer, - fifo->buffer + (fifo->out & (fifo->size - 1)), n1); - if (ret) { - len = n1 - ret; - goto out; - } - - /* then get the rest (if any) from the beginning of the buffer */ - ret = copy_to_user(buffer + n1, fifo->buffer, n2); - if (ret) - len = n1 + n2 - ret; - - /* - * Ensure that we remove the bytes from the kfifo -before- - * we update the fifo->out index. - */ -out: - smp_mb(); - - fifo->out += len; - - return len; -} -EXPORT_SYMBOL(__kfifo_get_to_user); -- 2.41.0