#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/mempool.h>
-#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/arch/tc.h>
#include <asm/arch/omapfb.h>
+#include <asm/arch/dsp.h>
#include <asm/arch/mailbox.h>
-#include <asm/arch/dsp_common.h>
-#include "uaccess_dsp.h"
+#include <asm/arch/mmu.h>
#include "dsp_mbcmd.h"
#include "dsp.h"
-#include "ioctl.h"
#include "ipbuf.h"
-#ifdef CONFIG_ARCH_OMAP2
-#define IOMAP_VAL 0x3f
-#endif
-
-#define SZ_1KB 0x400
-#define SZ_4KB 0x1000
-#define SZ_64KB 0x10000
-#define SZ_1MB 0x100000
-#define SZ_16MB 0x1000000
-#define is_aligned(adr,align) (!((adr)&((align)-1)))
-#define ORDER_4KB (12 - PAGE_SHIFT)
-#define ORDER_64KB (16 - PAGE_SHIFT)
-#define ORDER_1MB (20 - PAGE_SHIFT)
-
-/*
- * absorb DSP MMU register size and location difference
- */
-#if defined(CONFIG_ARCH_OMAP1)
-typedef u16 dsp_mmu_reg_t;
-#define dsp_mmu_read_reg(a) omap_readw(a)
-#define dsp_mmu_write_reg(v,a) omap_writew(v,a)
-#elif defined(CONFIG_ARCH_OMAP2)
-typedef u32 dsp_mmu_reg_t;
-#define dsp_mmu_read_reg(a) readl(a)
-#define dsp_mmu_write_reg(v,a) writel(v,a)
-#define dsp_ipi_read_reg(a) readl(a)
-#define dsp_ipi_write_reg(v,a) writel(v,a)
-#endif
-
-#if defined(CONFIG_ARCH_OMAP1)
-
-#define dsp_mmu_enable() \
- do { \
- dsp_mmu_write_reg(DSP_MMU_CNTL_MMU_EN | DSP_MMU_CNTL_RESET_SW, \
- DSP_MMU_CNTL); \
- } while(0)
-#define dsp_mmu_disable() \
- do { \
- dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
- } while(0)
-#define __dsp_mmu_itack() \
- do { \
- dsp_mmu_write_reg(DSP_MMU_IT_ACK_IT_ACK, DSP_MMU_IT_ACK); \
- } while(0)
-
-#elif defined(CONFIG_ARCH_OMAP2)
-
-#define dsp_mmu_enable() \
- do { \
- dsp_mmu_write_reg(DSP_MMU_CNTL_MMUENABLE, DSP_MMU_CNTL); \
- } while(0)
-#define dsp_mmu_disable() \
- do { \
- dsp_mmu_write_reg(0, DSP_MMU_CNTL); \
- } while(0)
-#define dsp_mmu_reset() \
- do { \
- dsp_mmu_write_reg(dsp_mmu_read_reg(DSP_MMU_SYSCONFIG) | \
- DSP_MMU_SYSCONFIG_SOFTRESET, \
- DSP_MMU_SYSCONFIG); \
- } while(0)
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
-#define dsp_mmu_flush() \
- do { \
- dsp_mmu_write_reg(DSP_MMU_FLUSH_ENTRY_FLUSH_ENTRY, \
- DSP_MMU_FLUSH_ENTRY); \
- } while(0)
-#define __dsp_mmu_gflush() \
- do { \
- dsp_mmu_write_reg(DSP_MMU_GFLUSH_GFLUSH, DSP_MMU_GFLUSH); \
- } while(0)
-
-/*
- * absorb register name difference
- */
-#ifdef CONFIG_ARCH_OMAP1
-#define DSP_MMU_CAM_P DSP_MMU_CAM_L_P
-#define DSP_MMU_CAM_V DSP_MMU_CAM_L_V
-#define DSP_MMU_CAM_PAGESIZE_MASK DSP_MMU_CAM_L_PAGESIZE_MASK
-#define DSP_MMU_CAM_PAGESIZE_1MB DSP_MMU_CAM_L_PAGESIZE_1MB
-#define DSP_MMU_CAM_PAGESIZE_64KB DSP_MMU_CAM_L_PAGESIZE_64KB
-#define DSP_MMU_CAM_PAGESIZE_4KB DSP_MMU_CAM_L_PAGESIZE_4KB
-#define DSP_MMU_CAM_PAGESIZE_1KB DSP_MMU_CAM_L_PAGESIZE_1KB
-#endif /* CONFIG_ARCH_OMAP1 */
-
-/*
- * 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)
-#endif /* CONFIG_ARCH_OMAP1 */
-
-enum exmap_type_e {
- EXMAP_TYPE_MEM,
- EXMAP_TYPE_FB
-};
-
-struct exmap_tbl_entry {
- unsigned int valid:1;
- unsigned int prsvd:1; /* preserved */
- int usecount; /* reference count by mmap */
- enum exmap_type_e 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 */
-};
-
-#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 DSP_MMU_TLB_LINES 32
-static struct exmap_tbl_entry exmap_tbl[DSP_MMU_TLB_LINES];
-static int exmap_preserved_cnt;
-static DECLARE_RWSEM(exmap_sem);
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-static struct omapfb_notifier_block *omapfb_nb;
-static int omapfb_ready;
-#endif
-
-struct cam_ram_regset {
-#if defined(CONFIG_ARCH_OMAP1)
- dsp_mmu_reg_t cam_h;
- dsp_mmu_reg_t cam_l;
- dsp_mmu_reg_t ram_h;
- dsp_mmu_reg_t ram_l;
-#elif defined(CONFIG_ARCH_OMAP2)
- dsp_mmu_reg_t cam;
- dsp_mmu_reg_t ram;
-#endif
-};
-
-struct tlb_entry {
- dsp_long_t va;
- unsigned long pa;
- dsp_mmu_reg_t pgsz, prsvd, valid;
-#if defined(CONFIG_ARCH_OMAP1)
- dsp_mmu_reg_t ap;
-#elif defined(CONFIG_ARCH_OMAP2)
- dsp_mmu_reg_t endian, elsz, mixed;
-#endif
-};
-
-#if defined(CONFIG_ARCH_OMAP1)
-#define INIT_TLB_ENTRY(ent,v,p,ps) \
- do { \
- (ent)->va = (v); \
- (ent)->pa = (p); \
- (ent)->pgsz = (ps); \
- (ent)->prsvd = 0; \
- (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
- } while (0)
-#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
- do { \
- (ent)->va = (v); \
- (ent)->pa = (p); \
- (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
- (ent)->prsvd = DSP_MMU_CAM_P; \
- (ent)->ap = DSP_MMU_RAM_L_AP_FA; \
- } while (0)
-#elif defined(CONFIG_ARCH_OMAP2)
-#define INIT_TLB_ENTRY(ent,v,p,ps) \
- do { \
- (ent)->va = (v); \
- (ent)->pa = (p); \
- (ent)->pgsz = (ps); \
- (ent)->prsvd = 0; \
- (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
- (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_16; \
- (ent)->mixed = 0; \
- } while (0)
-#define INIT_TLB_ENTRY_4KB_PRESERVED(ent,v,p) \
- do { \
- (ent)->va = (v); \
- (ent)->pa = (p); \
- (ent)->pgsz = DSP_MMU_CAM_PAGESIZE_4KB; \
- (ent)->prsvd = DSP_MMU_CAM_P; \
- (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
- (ent)->elsz = DSP_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 = DSP_MMU_CAM_PAGESIZE_4KB; \
- (ent)->prsvd = DSP_MMU_CAM_P; \
- (ent)->endian = DSP_MMU_RAM_ENDIANNESS_LITTLE; \
- (ent)->elsz = DSP_MMU_RAM_ELEMENTSIZE_32; \
- (ent)->mixed = 0; \
- } while (0)
-#endif
-
#if defined(CONFIG_ARCH_OMAP1)
-#define cam_ram_valid(cr) ((cr).cam_l & DSP_MMU_CAM_V)
+#include "../../mach-omap1/mmu.h"
#elif defined(CONFIG_ARCH_OMAP2)
-#define cam_ram_valid(cr) ((cr).cam & DSP_MMU_CAM_V)
+#include "../../mach-omap2/mmu.h"
#endif
-struct tlb_lock {
- int base;
- int victim;
-};
-
-static int dsp_exunmap(dsp_long_t dspadr);
+#include "mmu.h"
-static void *dspvect_page;
-static u32 dsp_fault_adr;
static struct mem_sync_struct mem_sync;
-static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
- char *buf);
-
-static struct device_attribute dev_attr_mmu = __ATTR_RO(mmu);
-static struct device_attribute dev_attr_exmap = __ATTR_RO(exmap);
-static struct device_attribute dev_attr_mempool = __ATTR_RO(mempool);
-
-/*
- * special mempool function:
- * hope this goes to mm/mempool.c
- */
-static void *mempool_alloc_from_pool(mempool_t *pool, gfp_t gfp_mask)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&pool->lock, flags);
- if (likely(pool->curr_nr)) {
- void *element = pool->elements[--pool->curr_nr];
- spin_unlock_irqrestore(&pool->lock, flags);
- return element;
- }
- spin_unlock_irqrestore(&pool->lock, flags);
-
- return mempool_alloc(pool, gfp_mask);
-}
-
-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;
-}
-
int dsp_mem_sync_inc(void)
{
if (dsp_mem_enable((void *)dspmem_base) < 0)
if (mem_sync.SDRAM)
mem_sync.SDRAM->ad_arm++;
dsp_mem_disable((void *)dspmem_base);
+
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;
-}
-
-static mempool_t *kmem_pool_1M;
-static mempool_t *kmem_pool_64K;
-
-static void *dsp_pool_alloc(unsigned int __nocast gfp, void *order)
-{
- return (void *)__get_dma_pages(gfp, (unsigned int)order);
-}
-
-static void dsp_pool_free(void *buf, void *order)
-{
- free_pages((unsigned long)buf, (unsigned int)order);
-}
-
-static void dsp_kmem_release(void)
-{
- if (kmem_pool_64K) {
- mempool_destroy(kmem_pool_64K);
- kmem_pool_64K = NULL;
- }
-
- if (kmem_pool_1M) {
- mempool_destroy(kmem_pool_1M);
- kmem_pool_1M = NULL;
- }
-}
-
-static int dsp_kmem_reserve(unsigned long size)
-{
- unsigned long len = size;
-
- /* alignment check */
- if (!is_aligned(size, SZ_64KB)) {
- printk(KERN_ERR
- "omapdsp: size(0x%lx) is not multiple of 64KB.\n", size);
- return -EINVAL;
- }
-
- if (size > DSPSPACE_SIZE) {
- printk(KERN_ERR
- "omapdsp: size(0x%lx) is larger than DSP memory space "
- "size (0x%x.\n", size, DSPSPACE_SIZE);
- return -EINVAL;
- }
-
- if (size >= SZ_1MB) {
- int nr = size >> 20;
-
- if (likely(!kmem_pool_1M))
- kmem_pool_1M = mempool_create(nr,
- dsp_pool_alloc,
- dsp_pool_free,
- (void *)ORDER_1MB);
- else
- mempool_resize(kmem_pool_1M, kmem_pool_1M->min_nr + nr,
- GFP_KERNEL);
-
- size &= ~(0xf << 20);
- }
-
- if (size >= SZ_64KB) {
- int nr = size >> 16;
-
- if (likely(!kmem_pool_64K))
- kmem_pool_64K = mempool_create(nr,
- dsp_pool_alloc,
- dsp_pool_free,
- (void *)ORDER_64KB);
- else
- mempool_resize(kmem_pool_64K,
- kmem_pool_64K->min_nr + nr, GFP_KERNEL);
-
- size &= ~(0xf << 16);
- }
-
- if (size)
- len -= size;
-
- return len;
-}
-
-static void dsp_mem_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(kmem_pool_64K))
- mempool_free((void *)buf, kmem_pool_64K);
- else if ((order == ORDER_1MB) && likely(kmem_pool_1M))
- mempool_free((void *)buf, kmem_pool_1M);
- else
- free_pages(buf, order);
-}
-
-static inline void
-exmap_alloc_pte(unsigned long virt, unsigned long phys, pgprot_t prot)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgd_offset_k(virt);
- pud = pud_offset(pgd, virt);
- pmd = pmd_offset(pud, virt);
-
- if (pmd_none(*pmd)) {
- pte = pte_alloc_one_kernel(&init_mm, 0);
- if (!pte)
- return;
-
- /* note: two PMDs will be set */
- pmd_populate_kernel(&init_mm, pmd, pte);
- }
-
- pte = pte_offset_kernel(pmd, virt);
- set_pte_ext(pte, pfn_pte(phys >> PAGE_SHIFT, prot), 0);
-}
-
-#if 0
-static inline int
-exmap_alloc_sect(unsigned long virt, unsigned long phys, int prot)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
-
- pgd = pgd_offset_k(virt);
- pud = pud_alloc(&init_mm, pgd, virt);
- pmd = pmd_alloc(&init_mm, pud, virt);
-
- if (virt & (1 << 20))
- pmd++;
-
- if (!pmd_none(*pmd))
- /* No good, fall back on smaller mappings. */
- return -EINVAL;
-
- *pmd = __pmd(phys | prot);
- flush_pmd_entry(pmd);
-
- return 0;
-}
-#endif
-
-/*
- * ARM MMU operations
- */
-static int exmap_set_armmmu(unsigned long virt, unsigned long phys,
- unsigned long size)
-{
- long off;
- pgprot_t prot_pte;
- int prot_sect;
-
- printk(KERN_DEBUG
- "omapdsp: mapping in ARM MMU, v=0x%08lx, p=0x%08lx, sz=0x%lx\n",
- virt, phys, size);
-
- prot_pte = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
- L_PTE_DIRTY | L_PTE_WRITE);
-
- prot_sect = PMD_TYPE_SECT | PMD_SECT_UNCACHED |
- PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
-
- if (cpu_architecture() <= CPU_ARCH_ARMv5)
- prot_sect |= PMD_BIT4;
-
- off = phys - virt;
-
- while ((virt & 0xfffff || (virt + off) & 0xfffff) && size >= PAGE_SIZE) {
- exmap_alloc_pte(virt, virt + off, prot_pte);
-
- virt += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- /* XXX: Not yet.. confuses dspfb -- PFM. */
-#if 0
- while (size >= (PGDIR_SIZE / 2)) {
- if (exmap_alloc_sect(virt, virt + off, prot_sect) < 0)
- break;
-
- virt += (PGDIR_SIZE / 2);
- size -= (PGDIR_SIZE / 2);
- }
-#endif
-
- while (size >= PAGE_SIZE) {
- exmap_alloc_pte(virt, virt + off, prot_pte);
-
- virt += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- BUG_ON(size);
-
- return 0;
-}
-
- /* XXX: T.Kobayashi
- * A process can have old mappings. if we want to clear a pmd,
- * we need to do it for all proceeses that use the old mapping.
- */
-#if 0
-static inline void
-exmap_clear_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
-{
- pte_t *pte;
-
- pte = pte_offset_map(pmd, addr);
- do {
- if (pte_none(*pte))
- continue;
-
- pte_clear(&init_mm, addr, pte);
- } while (pte++, addr += PAGE_SIZE, addr != end);
-
- pte_unmap(pte - 1);
-}
-
-static inline void
-exmap_clear_pmd_range(pud_t *pud, unsigned long addr, unsigned long end)
-{
- pmd_t *pmd;
- unsigned long next;
-
- pmd = pmd_offset(pud, addr);
- do {
- next = pmd_addr_end(addr, end);
-
- if (addr & (1 << 20))
- pmd++;
-
- if ((pmd_val(*pmd) & PMD_TYPE_MASK) == PMD_TYPE_SECT) {
- *pmd = __pmd(0);
- clean_pmd_entry(pmd);
- continue;
- }
-
- if (pmd_none_or_clear_bad(pmd))
- continue;
-
- exmap_clear_pte_range(pmd, addr, next);
- } while (pmd++, addr = next, addr != end);
-}
-
-static inline void
-exmap_clear_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end)
-{
- pud_t *pud;
- unsigned long next;
-
- pud = pud_offset(pgd, addr);
- do {
- next = pud_addr_end(addr, end);
- if (pud_none_or_clear_bad(pud))
- continue;
-
- exmap_clear_pmd_range(pud, addr, next);
- } while (pud++, addr = next, addr != end);
-}
-#endif
-
-static void exmap_clear_armmmu(unsigned long virt, unsigned long size)
-{
-#if 0
- unsigned long next, end;
- pgd_t *pgd;
-
- printk(KERN_DEBUG
- "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
- virt, size);
-
- pgd = pgd_offset_k(virt);
- end = virt + size;
- do {
- next = pgd_addr_end(virt, end);
- if (pgd_none_or_clear_bad(pgd))
- continue;
-
- exmap_clear_pud_range(pgd, virt, next);
- } while (pgd++, virt = next, virt != end);
-#else
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
-
- printk(KERN_DEBUG
- "omapdsp: unmapping in ARM MMU, v=%#010lx, sz=%#lx\n",
- virt, size);
-
- while (size >= PAGE_SIZE) {
- pgd = pgd_offset_k(virt);
- pud = pud_offset(pgd, virt);
- pmd = pmd_offset(pud, virt);
- pte = pte_offset_kernel(pmd, virt);
-
- pte_clear(&init_mm, virt, pte);
- size -= PAGE_SIZE;
- virt += PAGE_SIZE;
- }
-
- BUG_ON(size);
-#endif
-}
-
-static int exmap_valid(void *vadr, size_t len)
-{
- /* exmap_sem should be held before calling this function */
- int i;
-
-start:
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- void *mapadr;
- unsigned long mapsize;
- struct exmap_tbl_entry *ent = &exmap_tbl[i];
-
- 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;
-}
-
-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(&exmap_sem);
- if (exmap_valid(vadr, len))
- ret = MEM_TYPE_EXTERN;
- else
- ret = MEM_TYPE_NONE;
- up_read(&exmap_sem);
- return ret;
- }
-}
-
-int dsp_address_validate(void *p, size_t len, char *fmt, ...)
-{
- if (dsp_mem_type(p, len) <= 0) {
- if (fmt != NULL) {
- char s[64];
- va_list args;
-
- 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 \n"
- " external memory space where no "
- "actual memory is mapped)\n",
- s, p, len);
- }
- return -1;
- }
-
- return 0;
-}
-
-/*
- * 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 exmap_use(void *vadr, size_t len)
-{
- int i;
-
- down_write(&exmap_sem);
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- void *mapadr;
- unsigned long mapsize;
- struct exmap_tbl_entry *ent = &exmap_tbl[i];
-
- 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(&exmap_sem);
-}
-
-void exmap_unuse(void *vadr, size_t len)
-{
- int i;
-
- down_write(&exmap_sem);
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- void *mapadr;
- unsigned long mapsize;
- struct exmap_tbl_entry *ent = &exmap_tbl[i];
-
- 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(&exmap_sem);
-}
-
-/*
- * dsp_virt_to_phys()
- * returns physical address, and sets len to valid length
- */
-unsigned long dsp_virt_to_phys(void *vadr, size_t *len)
-{
- int i;
-
- if (is_dsp_internal_mem(vadr)) {
- /* DSRAM or SARAM */
- *len = dspmem_base + dspmem_size - (unsigned long)vadr;
- return (unsigned long)vadr;
- }
-
- /* EXRAM */
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- void *mapadr;
- unsigned long mapsize;
- struct exmap_tbl_entry *ent = &exmap_tbl[i];
-
- 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;
-}
-
-/*
- * DSP MMU operations
- */
-#ifdef CONFIG_ARCH_OMAP1
-static dsp_mmu_reg_t get_cam_l_va_mask(dsp_mmu_reg_t pgsz)
-{
- switch (pgsz) {
- case DSP_MMU_CAM_PAGESIZE_1MB:
- return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
- DSP_MMU_CAM_L_VA_TAG_L2_MASK_1MB;
- case DSP_MMU_CAM_PAGESIZE_64KB:
- return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
- DSP_MMU_CAM_L_VA_TAG_L2_MASK_64KB;
- case DSP_MMU_CAM_PAGESIZE_4KB:
- return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
- DSP_MMU_CAM_L_VA_TAG_L2_MASK_4KB;
- case DSP_MMU_CAM_PAGESIZE_1KB:
- return DSP_MMU_CAM_L_VA_TAG_L1_MASK |
- DSP_MMU_CAM_L_VA_TAG_L2_MASK_1KB;
- }
- return 0;
-}
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#if defined(CONFIG_ARCH_OMAP1)
-#define get_cam_va_mask(pgsz) \
- ((u32)DSP_MMU_CAM_H_VA_TAG_H_MASK << 22 | \
- (u32)get_cam_l_va_mask(pgsz) << 6)
-#elif defined(CONFIG_ARCH_OMAP2)
-#define get_cam_va_mask(pgsz) \
- ((pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? 0xff000000 : \
- (pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? 0xfff00000 : \
- (pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? 0xffff0000 : \
- (pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? 0xfffff000 : 0)
-#endif /* CONFIG_ARCH_OMAP2 */
-
-static void get_tlb_lock(struct tlb_lock *tlb_lock)
-{
- dsp_mmu_reg_t lock = dsp_mmu_read_reg(DSP_MMU_LOCK);
-
- tlb_lock->base = (lock & DSP_MMU_LOCK_BASE_MASK) >>
- DSP_MMU_LOCK_BASE_SHIFT;
- tlb_lock->victim = (lock & DSP_MMU_LOCK_VICTIM_MASK) >>
- DSP_MMU_LOCK_VICTIM_SHIFT;
-}
-
-static void set_tlb_lock(struct tlb_lock *tlb_lock)
-{
- dsp_mmu_write_reg((tlb_lock->base << DSP_MMU_LOCK_BASE_SHIFT) |
- (tlb_lock->victim << DSP_MMU_LOCK_VICTIM_SHIFT),
- DSP_MMU_LOCK);
-}
-
-static void __read_tlb(struct tlb_lock *tlb_lock, struct cam_ram_regset *cr)
-{
- /* set victim */
- set_tlb_lock(tlb_lock);
-
-#if defined(CONFIG_ARCH_OMAP1)
- /* read a TLB entry */
- dsp_mmu_write_reg(DSP_MMU_LD_TLB_RD, DSP_MMU_LD_TLB);
-
- cr->cam_h = dsp_mmu_read_reg(DSP_MMU_READ_CAM_H);
- cr->cam_l = dsp_mmu_read_reg(DSP_MMU_READ_CAM_L);
- cr->ram_h = dsp_mmu_read_reg(DSP_MMU_READ_RAM_H);
- cr->ram_l = dsp_mmu_read_reg(DSP_MMU_READ_RAM_L);
-#elif defined(CONFIG_ARCH_OMAP2)
- cr->cam = dsp_mmu_read_reg(DSP_MMU_READ_CAM);
- cr->ram = dsp_mmu_read_reg(DSP_MMU_READ_RAM);
-#endif
-}
-
-static void __load_tlb(struct cam_ram_regset *cr)
-{
-#if defined(CONFIG_ARCH_OMAP1)
- dsp_mmu_write_reg(cr->cam_h, DSP_MMU_CAM_H);
- dsp_mmu_write_reg(cr->cam_l, DSP_MMU_CAM_L);
- dsp_mmu_write_reg(cr->ram_h, DSP_MMU_RAM_H);
- dsp_mmu_write_reg(cr->ram_l, DSP_MMU_RAM_L);
-#elif defined(CONFIG_ARCH_OMAP2)
- dsp_mmu_write_reg(cr->cam | DSP_MMU_CAM_V, DSP_MMU_CAM);
- dsp_mmu_write_reg(cr->ram, DSP_MMU_RAM);
-#endif
-
- /* flush the entry */
- dsp_mmu_flush();
-
- /* load a TLB entry */
- dsp_mmu_write_reg(DSP_MMU_LD_TLB_LD, DSP_MMU_LD_TLB);
-}
-
-static int dsp_mmu_load_tlb(struct tlb_entry *tlb_ent)
-{
- struct tlb_lock tlb_lock;
- struct cam_ram_regset cr;
-
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(dsp_ck_handle);
- omap_dsp_request_mem();
-#endif
-
- get_tlb_lock(&tlb_lock);
- for (tlb_lock.victim = 0;
- tlb_lock.victim < tlb_lock.base;
- tlb_lock.victim++) {
- struct cam_ram_regset tmp_cr;
-
- /* read a TLB entry */
- __read_tlb(&tlb_lock, &tmp_cr);
- if (!cam_ram_valid(tmp_cr))
- goto found_victim;
- }
- set_tlb_lock(&tlb_lock);
-
-found_victim:
- /* The last (31st) entry cannot be locked? */
- if (tlb_lock.victim == 31) {
- printk(KERN_ERR "omapdsp: TLB is full.\n");
- return -EBUSY;
- }
-
- if (tlb_ent->va & ~get_cam_va_mask(tlb_ent->pgsz)) {
- printk(KERN_ERR
- "omapdsp: mapping vadr (0x%06x) is not "
- "aligned boundary\n", tlb_ent->va);
- return -EINVAL;
- }
-
-#if defined(CONFIG_ARCH_OMAP1)
- cr.cam_h = tlb_ent->va >> 22;
- cr.cam_l = (tlb_ent->va >> 6 & get_cam_l_va_mask(tlb_ent->pgsz)) |
- tlb_ent->prsvd | tlb_ent->pgsz;
- cr.ram_h = tlb_ent->pa >> 16;
- cr.ram_l = (tlb_ent->pa & DSP_MMU_RAM_L_RAM_LSB_MASK) | tlb_ent->ap;
-#elif defined(CONFIG_ARCH_OMAP2)
- cr.cam = (tlb_ent->va & DSP_MMU_CAM_VATAG_MASK) |
- tlb_ent->prsvd | tlb_ent->pgsz;
- cr.ram = tlb_ent->pa | tlb_ent->endian | tlb_ent->elsz;
-#endif
- __load_tlb(&cr);
-
- /* update lock base */
- if (tlb_lock.victim == tlb_lock.base)
- tlb_lock.base++;
- tlb_lock.victim = tlb_lock.base;
- set_tlb_lock(&tlb_lock);
-
-#ifdef CONFIG_ARCH_OMAP1
- omap_dsp_release_mem();
- clk_disable(dsp_ck_handle);
-#endif
- return 0;
-}
-
-static int dsp_mmu_clear_tlb(dsp_long_t vadr)
-{
- struct tlb_lock tlb_lock;
- int i;
- int max_valid = 0;
-
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(dsp_ck_handle);
- omap_dsp_request_mem();
-#endif
-
- get_tlb_lock(&tlb_lock);
- for (i = 0; i < tlb_lock.base; i++) {
- struct cam_ram_regset cr;
- dsp_long_t cam_va;
- dsp_mmu_reg_t pgsz;
-
- /* read a TLB entry */
- tlb_lock.victim = i;
- __read_tlb(&tlb_lock, &cr);
- if (!cam_ram_valid(cr))
- continue;
-
-#if defined(CONFIG_ARCH_OMAP1)
- pgsz = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
- cam_va = (u32)(cr.cam_h & DSP_MMU_CAM_H_VA_TAG_H_MASK) << 22 |
- (u32)(cr.cam_l & get_cam_l_va_mask(pgsz)) << 6;
-#elif defined(CONFIG_ARCH_OMAP2)
- pgsz = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
- cam_va = cr.cam & get_cam_va_mask(pgsz);
-#endif
-
- if (cam_va == vadr)
- /* flush the entry */
- dsp_mmu_flush();
- else
- max_valid = i;
- }
-
- /* set new lock base */
- tlb_lock.base = max_valid + 1;
- tlb_lock.victim = max_valid + 1;
- set_tlb_lock(&tlb_lock);
-
-#ifdef CONFIG_ARCH_OMAP1
- omap_dsp_release_mem();
- clk_disable(dsp_ck_handle);
-#endif
- return 0;
-}
-
-static void dsp_mmu_gflush(void)
-{
- struct tlb_lock tlb_lock;
-
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(dsp_ck_handle);
- omap_dsp_request_mem();
-#endif
-
- __dsp_mmu_gflush();
- tlb_lock.base = exmap_preserved_cnt;
- tlb_lock.victim = exmap_preserved_cnt;
- set_tlb_lock(&tlb_lock);
-
-#ifdef CONFIG_ARCH_OMAP1
- omap_dsp_release_mem();
- clk_disable(dsp_ck_handle);
-#endif
-}
-
-/*
- * dsp_exmap()
- *
- * MEM_IOCTL_EXMAP ioctl calls this function with padr=0.
- * In this case, the buffer for DSP 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 DSP.
- */
-static int dsp_exmap(dsp_long_t dspadr, unsigned long padr, unsigned long size,
- enum exmap_type_e type)
-{
- dsp_mmu_reg_t pgsz;
- void *buf;
- unsigned int order = 0;
- unsigned long unit;
- int prev = -1;
- dsp_long_t _dspadr = dspadr;
- unsigned long _padr = padr;
- void *_vadr = dspbyte_to_virt(dspadr);
- unsigned long _size = size;
- struct tlb_entry tlb_ent;
- struct exmap_tbl_entry *exmap_ent;
- int status;
- int idx;
- int i;
-
-#define MINIMUM_PAGESZ SZ_4KB
- /*
- * alignment check
- */
- if (!is_aligned(size, MINIMUM_PAGESZ)) {
- printk(KERN_ERR
- "omapdsp: size(0x%lx) is not multiple of 4KB.\n", size);
- return -EINVAL;
- }
- if (!is_aligned(dspadr, MINIMUM_PAGESZ)) {
- printk(KERN_ERR
- "omapdsp: DSP address(0x%x) is not aligned.\n", dspadr);
- return -EINVAL;
- }
- if (!is_aligned(padr, MINIMUM_PAGESZ)) {
- printk(KERN_ERR
- "omapdsp: physical address(0x%lx) is not aligned.\n",
- padr);
- return -EINVAL;
- }
-
- /* address validity check */
- if ((dspadr < dspmem_size) ||
- (dspadr >= DSPSPACE_SIZE) ||
- ((dspadr + size > DSP_INIT_PAGE) &&
- (dspadr < DSP_INIT_PAGE + PAGE_SIZE))) {
- printk(KERN_ERR
- "omapdsp: illegal address/size for dsp_exmap().\n");
- return -EINVAL;
- }
-
- down_write(&exmap_sem);
-
- /* overlap check */
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- unsigned long mapsize;
- struct exmap_tbl_entry *tmp_ent = &exmap_tbl[i];
-
- if (!tmp_ent->valid)
- continue;
- mapsize = 1 << (tmp_ent->order + PAGE_SHIFT);
- if ((_vadr + size > tmp_ent->vadr) &&
- (_vadr < tmp_ent->vadr + mapsize)) {
- printk(KERN_ERR "omapdsp: exmap page overlap!\n");
- up_write(&exmap_sem);
- return -EINVAL;
- }
- }
-
-start:
- buf = NULL;
- /* Are there any free TLB lines? */
- for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
- if (!exmap_tbl[idx].valid)
- goto found_free;
- }
- printk(KERN_ERR "omapdsp: DSP TLB is full.\n");
- status = -EBUSY;
- goto fail;
-
-found_free:
- exmap_ent = &exmap_tbl[idx];
-
- /*
- * we don't use
- * 1KB mapping in OMAP1,
- * 16MB mapping in OMAP2.
- */
- if ((_size >= SZ_1MB) &&
- (is_aligned(_padr, SZ_1MB) || (padr == 0)) &&
- is_aligned(_dspadr, SZ_1MB)) {
- unit = SZ_1MB;
- pgsz = DSP_MMU_CAM_PAGESIZE_1MB;
- } else if ((_size >= SZ_64KB) &&
- (is_aligned(_padr, SZ_64KB) || (padr == 0)) &&
- is_aligned(_dspadr, SZ_64KB)) {
- unit = SZ_64KB;
- pgsz = DSP_MMU_CAM_PAGESIZE_64KB;
- } else {
- unit = SZ_4KB;
- pgsz = DSP_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(kmem_pool_1M))
- buf = mempool_alloc_from_pool(kmem_pool_1M, GFP_KERNEL);
- else if ((order == ORDER_64KB) && likely(kmem_pool_64K))
- buf = mempool_alloc_from_pool(kmem_pool_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 cashed.
- */
- status = exmap_set_armmmu((unsigned long)_vadr, _padr, unit);
- if (status < 0)
- goto fail;
-
- /* loading DSP TLB entry */
- INIT_TLB_ENTRY(&tlb_ent, _dspadr, _padr, pgsz);
- status = dsp_mmu_load_tlb(&tlb_ent);
- if (status < 0) {
- exmap_clear_armmmu((unsigned long)_vadr, unit);
- goto fail;
- }
-
- INIT_EXMAP_TBL_ENTRY(exmap_ent, buf, _vadr, type, order);
- exmap_ent->link.prev = prev;
- if (prev >= 0)
- exmap_tbl[prev].link.next = idx;
-
- if ((_size -= unit) == 0) { /* normal completion */
- up_write(&exmap_sem);
- return size;
- }
-
- _dspadr += unit;
- _vadr += unit;
- _padr = padr ? _padr + unit : 0;
- prev = idx;
- goto start;
-
-fail:
- up_write(&exmap_sem);
- if (buf)
- dsp_mem_free_pages((unsigned long)buf, order);
- dsp_exunmap(dspadr);
- return status;
-}
-
-static unsigned long unmap_free_arm(struct exmap_tbl_entry *ent)
-{
- unsigned long size;
-
- /* clearing ARM MMU */
- size = 1 << (ent->order + PAGE_SHIFT);
- exmap_clear_armmmu((unsigned long)ent->vadr, size);
-
- /* freeing allocated memory */
- if (ent->type == EXMAP_TYPE_MEM) {
- dsp_mem_free_pages((unsigned long)ent->buf, ent->order);
- printk(KERN_DEBUG
- "omapdsp: freeing 0x%lx bytes @ adr 0x%8p\n",
- size, ent->buf);
- }
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
- else if (ent->type == EXMAP_TYPE_FB) {
- int status;
- if (omapfb_nb) {
- status = omapfb_unregister_client(omapfb_nb);
- if (!status)
- printk("omapfb_unregister_client(): "
- "success\n");
- else
- printk("omapfb_runegister_client(): "
- "failure(%d)\n", status);
- kfree(omapfb_nb);
- omapfb_nb = NULL;
- omapfb_ready = 0;
- }
- }
-#endif
-
- return size;
-}
-
-static int dsp_exunmap(dsp_long_t dspadr)
-{
- void *vadr;
- unsigned long size;
- int total = 0;
- struct exmap_tbl_entry *ent;
- int idx;
-
- vadr = dspbyte_to_virt(dspadr);
- down_write(&exmap_sem);
- for (idx = 0; idx < DSP_MMU_TLB_LINES; idx++) {
- ent = &exmap_tbl[idx];
- if ((!ent->valid) || ent->prsvd)
- continue;
- if (ent->vadr == vadr)
- goto found_map;
- }
- up_write(&exmap_sem);
- printk(KERN_WARNING
- "omapdsp: address %06x not found in exmap_tbl.\n", dspadr);
- return -EINVAL;
-
-found_map:
- if (ent->usecount > 0) {
- printk(KERN_ERR
- "omapdsp: exmap reference count is not 0.\n"
- " idx=%d, vadr=%p, order=%d, usecount=%d\n",
- idx, ent->vadr, ent->order, ent->usecount);
- up_write(&exmap_sem);
- return -EINVAL;
- }
- /* clearing DSP TLB entry */
- dsp_mmu_clear_tlb(dspadr);
-
- /* clear ARM MMU and free buffer */
- size = unmap_free_arm(ent);
- ent->valid = 0;
- total += size;
-
- /* we don't free PTEs */
-
- /* flush TLB */
- flush_tlb_kernel_range((unsigned long)vadr, (unsigned long)vadr + size);
-
- if ((idx = ent->link.next) < 0)
- goto up_out; /* normal completion */
- ent = &exmap_tbl[idx];
- dspadr += size;
- vadr += size;
- if (ent->vadr == vadr)
- goto found_map; /* continue */
-
- printk(KERN_ERR
- "omapdsp: illegal exmap_tbl grouping!\n"
- "expected vadr = %p, exmap_tbl[%d].vadr = %p\n",
- vadr, idx, ent->vadr);
- up_write(&exmap_sem);
- return -EINVAL;
-
-up_out:
- up_write(&exmap_sem);
- return total;
-}
-
-static void exmap_flush(void)
-{
- struct exmap_tbl_entry *ent;
- int i;
-
- down_write(&exmap_sem);
-
- /* clearing DSP TLB entry */
- dsp_mmu_gflush();
-
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- ent = &exmap_tbl[i];
- if (ent->valid && (!ent->prsvd)) {
- unmap_free_arm(ent);
- ent->valid = 0;
- }
- }
-
- /* flush TLB */
- flush_tlb_kernel_range(dspmem_base + dspmem_size,
- dspmem_base + DSPSPACE_SIZE);
- up_write(&exmap_sem);
-}
-
-#ifdef CONFIG_OMAP_DSP_FBEXPORT
-#ifndef CONFIG_FB
-#error You configured OMAP_DSP_FBEXPORT, but FB was not configured!
-#endif /* CONFIG_FB */
-
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
-static int omapfb_notifier_cb(struct notifier_block *omapfb_nb,
- unsigned long event, void *fbi)
-{
- /* XXX */
- printk("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
-
- printk(KERN_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) {
- printk(KERN_INFO "omapdsp: frame buffer not registered.\n");
- return -EINVAL;
- }
- if (num_registered_fb != 1) {
- printk(KERN_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_4KB-1);
- fbsz = (fbsz_sys + padr_sys - padr + SZ_4KB-1) & ~(SZ_4KB-1);
-
- /* line up dspadr offset with padr */
- dspadr_actual =
- (fbsz > SZ_1MB) ? lineup_offset(*dspadr, padr, SZ_1MB-1) :
- (fbsz > SZ_64KB) ? lineup_offset(*dspadr, padr, SZ_64KB-1) :
- /* (fbsz > SZ_4KB) ? */ *dspadr;
- if (dspadr_actual != *dspadr)
- printk(KERN_DEBUG
- "omapdsp: actual dspadr for FBEXPORT = %08x\n",
- dspadr_actual);
- *dspadr = dspadr_actual;
-
- cnt = dsp_exmap(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);
- }
-
-#ifdef CONFIG_ARCH_OMAP1
- /* increase the DMA priority */
- set_emiff_dma_prio(15);
-#endif
-
-#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");
- dsp_exunmap(dspadr_actual);
- return -ENOMEM;
- }
- status = omapfb_register_client(omapfb_nb, omapfb_notifier_cb, NULL);
- if (!status)
- printk("omapfb_register_client(): success\n");
- else
- printk("omapfb_register_client(): failure(%d)\n", status);
-#endif
-
- return cnt;
-}
-
-#else /* CONFIG_OMAP_DSP_FBEXPORT */
-
-static int dsp_fbexport(dsp_long_t *dspadr)
-{
- printk(KERN_ERR "omapdsp: FBEXPORT function is not enabled.\n");
- return -EINVAL;
-}
-
-#endif /* CONFIG_OMAP_DSP_FBEXPORT */
-
-static void exmap_setup_preserved_mem_page(void *buf, dsp_long_t dspadr,
- int exmap_idx)
-{
- unsigned long phys;
- void *virt;
- struct tlb_entry tlb_ent;
-
- phys = __pa(buf);
- virt = dspbyte_to_virt(dspadr);
- exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
- INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], buf, virt);
- INIT_TLB_ENTRY_4KB_PRESERVED(&tlb_ent, dspadr, phys);
- dsp_mmu_load_tlb(&tlb_ent);
-}
-
-static void exmap_clear_mem_page(dsp_long_t dspadr)
-{
- void *virt;
-
- virt = dspbyte_to_virt(dspadr);
- exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
- /* DSP MMU is shutting down. not handled here. */
-}
-
-#ifdef CONFIG_ARCH_OMAP2
-static void exmap_setup_iomap_page(unsigned long phys, unsigned long dsp_io_adr,
- int exmap_idx)
-{
- dsp_long_t dspadr;
- void *virt;
- struct tlb_entry tlb_ent;
-
- dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
- virt = dspbyte_to_virt(dspadr);
- exmap_set_armmmu((unsigned long)virt, phys, PAGE_SIZE);
- INIT_EXMAP_TBL_ENTRY_4KB_PRESERVED(&exmap_tbl[exmap_idx], NULL, virt);
- INIT_TLB_ENTRY_4KB_ES32_PRESERVED(&tlb_ent, dspadr, phys);
- dsp_mmu_load_tlb(&tlb_ent);
-}
-
-static void exmap_clear_iomap_page(unsigned long dsp_io_adr)
-{
- dsp_long_t dspadr;
- void *virt;
-
- dspadr = (IOMAP_VAL << 18) + (dsp_io_adr << 1);
- virt = dspbyte_to_virt(dspadr);
- exmap_clear_armmmu((unsigned long)virt, PAGE_SIZE);
- /* DSP MMU is shutting down. not handled here. */
-}
-#endif /* CONFIG_ARCH_OMAP2 */
-
-#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)
-
-static int exmap_setup_preserved_entries(void)
-{
- int n = 0;
-
- exmap_setup_preserved_mem_page(dspvect_page, DSP_INIT_PAGE, n++);
-#ifdef CONFIG_ARCH_OMAP2
- exmap_setup_iomap_page(OMAP24XX_PRCM_BASE, 0x7000, n++);
-#ifdef CONFIG_ARCH_OMAP2420
- exmap_setup_iomap_page(OMAP2420_GPT5_BASE, 0xe000, n++);
- exmap_setup_iomap_page(OMAP2420_GPT6_BASE, 0xe800, n++);
- exmap_setup_iomap_page(OMAP2420_GPT7_BASE, 0xf000, n++);
- exmap_setup_iomap_page(OMAP2420_GPT8_BASE, 0xf800, n++);
-#endif /* CONFIG_ARCH_OMAP2420 */
- exmap_setup_iomap_page(OMAP24XX_EAC_BASE, 0x10000, n++);
- exmap_setup_iomap_page(OMAP24XX_MAILBOX_BASE, 0x11000, n++);
-#endif /* CONFIG_ARCH_OMAP2 */
-
- return n;
-}
-
-static void exmap_clear_preserved_entries(void)
-{
- exmap_clear_mem_page(DSP_INIT_PAGE);
-#ifdef CONFIG_ARCH_OMAP2
- exmap_clear_iomap_page(0x7000); /* PRCM */
-#ifdef CONFIG_ARCH_OMAP2420
- exmap_clear_iomap_page(0xe000); /* GPT5 */
- exmap_clear_iomap_page(0xe800); /* GPT6 */
- exmap_clear_iomap_page(0xf000); /* GPT7 */
- exmap_clear_iomap_page(0xf800); /* GPT8 */
-#endif /* CONFIG_ARCH_OMAP2420 */
- exmap_clear_iomap_page(0x10000); /* EAC */
- exmap_clear_iomap_page(0x11000); /* MAILBOX */
-#endif /* CONFIG_ARCH_OMAP2 */
-}
-
-#ifdef CONFIG_ARCH_OMAP1
-static int dsp_mmu_itack(void)
-{
- unsigned long dspadr;
-
- printk(KERN_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_fault_adr & ~(SZ_4K-1);
- dsp_exmap(dspadr, 0, SZ_4K, EXMAP_TYPE_MEM); /* FIXME: reserve TLB entry for this */
- printk(KERN_INFO "omapdsp: falling into recovery runlevel...\n");
- dsp_set_runlevel(RUNLEVEL_RECOVERY);
- __dsp_mmu_itack();
- udelay(100);
- dsp_exunmap(dspadr);
- dsp_err_clear(ERRCODE_MMU);
- return 0;
-}
-#endif /* CONFIG_ARCH_OMAP1 */
-
-#ifdef CONFIG_ARCH_OMAP2
-#define MMU_IRQ_MASK \
- (DSP_MMU_IRQ_MULTIHITFAULT | \
- DSP_MMU_IRQ_TABLEWALKFAULT | \
- DSP_MMU_IRQ_EMUMISS | \
- DSP_MMU_IRQ_TRANSLATIONFAULT | \
- DSP_MMU_IRQ_TLBMISS)
-#endif
-
-static int is_mmu_init;
-
-static void dsp_mmu_init(void)
-{
- struct tlb_lock tlb_lock;
-
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(dsp_ck_handle);
- omap_dsp_request_mem();
-#endif
- down_write(&exmap_sem);
-
-#if defined(CONFIG_ARCH_OMAP1)
- dsp_mmu_disable(); /* clear all */
- udelay(100);
-#elif defined(CONFIG_ARCH_OMAP2)
- dsp_mmu_reset();
-#endif
- dsp_mmu_enable();
-
- /* DSP TLB initialization */
- tlb_lock.base = 0;
- tlb_lock.victim = 0;
- set_tlb_lock(&tlb_lock);
-
- exmap_preserved_cnt = exmap_setup_preserved_entries();
-
-#ifdef CONFIG_ARCH_OMAP2
- /* MMU IRQ mask setup */
- dsp_mmu_write_reg(MMU_IRQ_MASK, DSP_MMU_IRQENABLE);
-#endif
-
- up_write(&exmap_sem);
-#ifdef CONFIG_ARCH_OMAP1
- omap_dsp_release_mem();
- clk_disable(dsp_ck_handle);
-#endif
-
- is_mmu_init = 1;
-}
-
-static void dsp_mmu_shutdown(void)
-{
- if (is_mmu_init) {
- exmap_flush();
- exmap_clear_preserved_entries();
- dsp_mmu_disable();
- }
-}
-
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * 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);
-}
-#endif /* CONFIG_ARCH_OMAP1 */
-
-/*
- * dsp_mem_enable() / disable()
- */
-#ifdef CONFIG_ARCH_OMAP1
-int intmem_usecount;
-#endif
-
-int dsp_mem_enable(void *adr)
-{
- int ret = 0;
-
- if (is_dsp_internal_mem(adr)) {
-#ifdef CONFIG_ARCH_OMAP1
- if (intmem_usecount++ == 0)
- ret = omap_dsp_request_mem();
-#endif
- } else
- down_read(&exmap_sem);
-
- return ret;
-}
-
-void dsp_mem_disable(void *adr)
-{
- if (is_dsp_internal_mem(adr)) {
-#ifdef CONFIG_ARCH_OMAP1
- if (--intmem_usecount == 0)
- omap_dsp_release_mem();
-#endif
- } else
- up_read(&exmap_sem);
-}
-
-/* for safety */
-#ifdef CONFIG_ARCH_OMAP1
-void dsp_mem_usecount_clear(void)
-{
- if (intmem_usecount != 0) {
- printk(KERN_WARNING
- "omapdsp: 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();
- }
-}
-#endif /* CONFIG_ARCH_OMAP1 */
-
-/*
- * dsp_mem file operations
- */
-static loff_t dsp_mem_lseek(struct file *file, loff_t offset, int orig)
-{
- loff_t ret;
-
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
- switch (orig) {
- case 0:
- file->f_pos = offset;
- ret = file->f_pos;
- break;
- case 1:
- file->f_pos += offset;
- ret = file->f_pos;
- break;
- default:
- ret = -EINVAL;
- }
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
- return ret;
-}
-
-static ssize_t intmem_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- unsigned long p = *ppos;
- void *vadr = dspbyte_to_virt(p);
- ssize_t size = dspmem_size;
- ssize_t read;
-
- if (p >= size)
- return 0;
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(api_ck_handle);
-#endif
- read = count;
- if (count > size - p)
- read = size - p;
- if (copy_to_user(buf, vadr, read)) {
- read = -EFAULT;
- goto out;
- }
- *ppos += read;
-out:
-#ifdef CONFIG_ARCH_OMAP1
- clk_disable(api_ck_handle);
-#endif
- return read;
-}
-
-static ssize_t exmem_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- unsigned long p = *ppos;
- void *vadr = dspbyte_to_virt(p);
-
- if (!exmap_valid(vadr, count)) {
- printk(KERN_ERR
- "omapdsp: DSP address %08lx / size %08x "
- "is not valid!\n", p, count);
- return -EFAULT;
- }
- if (count > DSPSPACE_SIZE - p)
- count = DSPSPACE_SIZE - p;
- if (copy_to_user(buf, vadr, count))
- return -EFAULT;
- *ppos += count;
-
- return count;
-}
-
-static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- int ret;
- void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
-
- if (dsp_mem_enable(vadr) < 0)
- return -EBUSY;
- if (is_dspbyte_internal_mem(*ppos))
- ret = intmem_read(file, buf, count, ppos);
- else
- ret = exmem_read(file, buf, count, ppos);
- dsp_mem_disable(vadr);
-
- return ret;
-}
-
-static ssize_t intmem_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long p = *ppos;
- void *vadr = dspbyte_to_virt(p);
- ssize_t size = dspmem_size;
- ssize_t written;
-
- if (p >= size)
- return 0;
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(api_ck_handle);
-#endif
- written = count;
- if (count > size - p)
- written = size - p;
- if (copy_from_user(vadr, buf, written)) {
- written = -EFAULT;
- goto out;
- }
- *ppos += written;
-out:
-#ifdef CONFIG_ARCH_OMAP1
- clk_disable(api_ck_handle);
-#endif
- return written;
-}
-
-static ssize_t exmem_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long p = *ppos;
- void *vadr = dspbyte_to_virt(p);
-
- if (!exmap_valid(vadr, count)) {
+ (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: DSP address %08lx / size %08x "
- "is not valid!\n", p, count);
- return -EFAULT;
+ "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;
}
- if (count > DSPSPACE_SIZE - p)
- count = DSPSPACE_SIZE - p;
- if (copy_from_user(vadr, buf, count))
- return -EFAULT;
- *ppos += count;
- return count;
+ memcpy(&mem_sync, sync, sizeof(struct mem_sync_struct));
+
+ return 0;
}
-static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+
+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;
- void *vadr = dspbyte_to_virt(*(unsigned long *)ppos);
-
- if (dsp_mem_enable(vadr) < 0)
- return -EBUSY;
- if (is_dspbyte_internal_mem(*ppos))
- ret = intmem_write(file, buf, count, ppos);
- else
- ret = exmem_write(file, buf, count, ppos);
- dsp_mem_disable(vadr);
- return 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;
+ }
}
-static int dsp_mem_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+int dsp_address_validate(void *p, size_t len, char *fmt, ...)
{
- switch (cmd) {
- case MEM_IOCTL_MMUINIT:
- dsp_mmu_init();
- return 0;
-
- case MEM_IOCTL_EXMAP:
- {
- struct omap_dsp_mapinfo mapinfo;
- if (copy_from_user(&mapinfo, (void __user *)arg,
- sizeof(mapinfo)))
- return -EFAULT;
- return dsp_exmap(mapinfo.dspadr, 0, mapinfo.size,
- EXMAP_TYPE_MEM);
- }
-
- case MEM_IOCTL_EXUNMAP:
- return dsp_exunmap((unsigned long)arg);
+ char s[64];
+ va_list args;
- case MEM_IOCTL_EXMAP_FLUSH:
- exmap_flush();
+ if (dsp_mem_type(p, len) > 0)
return 0;
- 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;
- }
-
-#ifdef CONFIG_ARCH_OMAP1
- case MEM_IOCTL_MMUITACK:
- return dsp_mmu_itack();
-#endif
-
- case MEM_IOCTL_KMEM_RESERVE:
- {
- __u32 size;
- if (copy_from_user(&size, (void __user *)arg,
- sizeof(__u32)))
- return -EFAULT;
- return dsp_kmem_reserve(size);
- }
-
- case MEM_IOCTL_KMEM_RELEASE:
- dsp_kmem_release();
- return 0;
+ if (fmt == NULL)
+ goto out;
- default:
- return -ENOIOCTLCMD;
- }
+ 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;
}
-static int dsp_mem_mmap(struct file *file, struct vm_area_struct *vma)
-{
- /*
- * FIXME
- */
- return -ENOSYS;
-}
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
-static int dsp_mem_open(struct inode *inode, struct file *file)
+static inline unsigned long lineup_offset(unsigned long adr,
+ unsigned long ref,
+ unsigned long mask)
{
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
+ unsigned long newadr;
- return 0;
+ newadr = (adr & ~mask) | (ref & mask);
+ if (newadr < adr)
+ newadr += mask + 1;
+ return newadr;
}
-#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
/*
* fb update functions:
* fbupd_response() is executed by the workqueue.
int status;
status = mbcompose_send(KFUNC, KFUNC_FBCTL, FBCTL_UPD);
- if (status < 0) {
- /* FIXME: DSP is busy !! */
- printk(KERN_ERR
- "omapdsp: DSP is busy when trying to send FBCTL:UPD "
- "response!\n");
- }
+ 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);
struct omapfb_update_window win;
volatile unsigned short *buf = ipbuf_sys_da->d;
- /* FIXME: try count sometimes exceeds 1000. */
if (sync_with_dsp(&ipbuf_sys_da->s, TID_ANON, 5000) < 0) {
printk(KERN_ERR "mbox: FBCTL:UPD - IPBUF sync failed!\n");
return;
"omapdsp: fbupd() called while HWA742 is not ready!\n");
return;
}
- //printk("calling omapfb_update_window_async()\n");
omapfb_update_window_async(registered_fb[0], &win, fbupd_cb, NULL);
}
-#else /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
-
-void mbox_fbctl_upd(void)
+#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 /* CONFIG_FB_OMAP_LCDC_EXTERNAL */
-
-/*
- * sysfs files
- */
+#endif
-/* mmu */
-static ssize_t mmu_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static int dsp_fbexport(dsp_long_t *dspadr)
{
- int len;
- struct tlb_lock tlb_lock_org;
- int i;
-
-#ifdef CONFIG_ARCH_OMAP1
- clk_enable(dsp_ck_handle);
- omap_dsp_request_mem();
-#endif
- down_read(&exmap_sem);
+ dsp_long_t dspadr_actual;
+ unsigned long padr_sys, padr, fbsz_sys, fbsz;
+ int cnt, status;
- get_tlb_lock(&tlb_lock_org);
+ pr_debug( "omapdsp: frame buffer export\n");
-#if defined(CONFIG_ARCH_OMAP1)
- 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 */
-#elif defined(CONFIG_ARCH_OMAP2)
- 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 */
+#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
+ if (omapfb_nb) {
+ printk(KERN_WARNING
+ "omapdsp: frame buffer has been exported already!\n");
+ return -EBUSY;
+ }
#endif
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- struct cam_ram_regset cr;
- struct tlb_lock tlb_lock_tmp;
- struct tlb_entry ent;
-#if defined(CONFIG_ARCH_OMAP1)
- char *pgsz_str, *ap_str;
-#elif defined(CONFIG_ARCH_OMAP2)
- char *pgsz_str, *elsz_str;
-#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);
- /* read a TLB entry */
- tlb_lock_tmp.base = tlb_lock_org.base;
- tlb_lock_tmp.victim = i;
- __read_tlb(&tlb_lock_tmp, &cr);
+ /* 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;
-#if defined(CONFIG_ARCH_OMAP1)
- ent.pgsz = cr.cam_l & DSP_MMU_CAM_PAGESIZE_MASK;
- ent.prsvd = cr.cam_l & DSP_MMU_CAM_P;
- ent.valid = cr.cam_l & DSP_MMU_CAM_V;
- ent.ap = cr.ram_l & DSP_MMU_RAM_L_AP_MASK;
- ent.va = (u32)(cr.cam_h & DSP_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 & DSP_MMU_RAM_L_RAM_LSB_MASK);
-
- pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? " 1MB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? " 4KB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1KB) ? " 1KB":
- " ???";
- ap_str = (ent.ap == DSP_MMU_RAM_L_AP_RO) ? "RO":
- (ent.ap == DSP_MMU_RAM_L_AP_FA) ? "FA":
- (ent.ap == DSP_MMU_RAM_L_AP_NA) ? "NA":
- "??";
-#elif defined(CONFIG_ARCH_OMAP2)
- ent.pgsz = cr.cam & DSP_MMU_CAM_PAGESIZE_MASK;
- ent.prsvd = cr.cam & DSP_MMU_CAM_P;
- ent.valid = cr.cam & DSP_MMU_CAM_V;
- ent.va = cr.cam & DSP_MMU_CAM_VATAG_MASK;
- ent.endian = cr.ram & DSP_MMU_RAM_ENDIANNESS;
- ent.elsz = cr.ram & DSP_MMU_RAM_ELEMENTSIZE_MASK;
- ent.pa = cr.ram & DSP_MMU_RAM_PADDR_MASK;
- ent.mixed = cr.ram & DSP_MMU_RAM_MIXED;
-
- pgsz_str = (ent.pgsz == DSP_MMU_CAM_PAGESIZE_16MB) ? "64MB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_1MB) ? " 1MB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_64KB) ? "64KB":
- (ent.pgsz == DSP_MMU_CAM_PAGESIZE_4KB) ? " 4KB":
- " ???";
- elsz_str = (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_8) ? " 8":
- (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_16) ? "16":
- (ent.elsz == DSP_MMU_RAM_ELEMENTSIZE_32) ? "32":
- "??";
-#endif
+ 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 (i == tlb_lock_org.base)
- len += sprintf(buf + len, "lock base = %d\n",
- tlb_lock_org.base);
- if (i == tlb_lock_org.victim)
- len += sprintf(buf + len, "victim = %d\n",
- tlb_lock_org.victim);
-#if defined(CONFIG_ARCH_OMAP1)
- len += sprintf(buf + len,
- /* 00: P V 4KB 0x300000 0x10171800 FA */
- "%02d: %c %c %s 0x%06x 0x%08lx %s\n",
- i,
- ent.prsvd ? 'P' : ' ',
- ent.valid ? 'V' : ' ',
- pgsz_str, ent.va, ent.pa, ap_str);
-#elif defined(CONFIG_ARCH_OMAP2)
- len += sprintf(buf + len,
- /* 00: P V 4KB 0x300000 0x10171800 B 16 M */
- "%02d: %c %c %s 0x%06x 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' : ' ');
-#endif /* CONFIG_ARCH_OMAP2 */
+ 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);
}
- /* restore victim entry */
- set_tlb_lock(&tlb_lock_org);
+ /* increase the DMA priority */
+ set_emiff_dma_prio(15);
- up_read(&exmap_sem);
-#ifdef CONFIG_ARCH_OMAP1
- omap_dsp_release_mem();
- clk_disable(dsp_ck_handle);
+#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 len;
+
+ return cnt;
}
+#else
+void mbox_fbctl_upd(void) { }
+#endif
-/* exmap */
-static ssize_t exmap_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+/* dsp/mem fops: backward compatibility */
+static ssize_t dsp_mem_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
{
- int len;
- int i;
-
- down_read(&exmap_sem);
- len = sprintf(buf, " dspadr size buf size uc\n");
- /* 0x300000 0x123000 0xc0171000 0x100000 0*/
- for (i = 0; i < DSP_MMU_TLB_LINES; i++) {
- struct exmap_tbl_entry *ent = &exmap_tbl[i];
- void *vadr;
- unsigned long size;
- enum exmap_type_e 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 = &exmap_tbl[idx];
- size += PAGE_SIZE << ent->order;
- } while ((idx = ent->link.next) >= 0);
-
- len += sprintf(buf + len, "0x%06x %#8lx",
- virt_to_dspbyte(vadr), size);
-
- if (type == EXMAP_TYPE_FB) {
- len += sprintf(buf + len, " framebuf\n");
- } else {
- len += sprintf(buf + len, "\n");
- idx = i;
- do {
- ent = &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);
- }
- }
-
- up_read(&exmap_sem);
- return len;
+ return __omap_mmu_mem_read(&dsp_mmu, buf, *ppos, count);
}
-/* mempool */
-static ssize_t mempool_show(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t dsp_mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- int min_nr_1M = 0, curr_nr_1M = 0;
- int min_nr_64K = 0, curr_nr_64K = 0;
- int total = 0;
-
- if (likely(kmem_pool_1M)) {
- min_nr_1M = kmem_pool_1M->min_nr;
- curr_nr_1M = kmem_pool_1M->curr_nr;
- total += min_nr_1M * SZ_1MB;
- }
- if (likely(kmem_pool_64K)) {
- min_nr_64K = kmem_pool_64K->min_nr;
- curr_nr_64K = kmem_pool_64K->curr_nr;
- total += min_nr_64K * SZ_64KB;
- }
-
- 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);
+ return __omap_mmu_mem_write(&dsp_mmu,
+ (char __user *)buf, *ppos, count);
}
-/*
- * workqueue for mmu int
- */
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * MMU fault mask:
- * We ignore prefetch err.
- */
-#define MMUFAULT_MASK \
- (DSP_MMU_FAULT_ST_PERM |\
- DSP_MMU_FAULT_ST_TLB_MISS |\
- DSP_MMU_FAULT_ST_TRANS)
-#endif /* CONFIG_ARCH_OMAP1 */
-
-static void do_mmu_int(struct work_struct *unused)
+static int dsp_mem_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
{
-#if defined(CONFIG_ARCH_OMAP1)
-
- dsp_mmu_reg_t status;
- dsp_mmu_reg_t adh, adl;
- dsp_mmu_reg_t dp;
-
- status = dsp_mmu_read_reg(DSP_MMU_FAULT_ST);
- adh = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_H);
- adl = dsp_mmu_read_reg(DSP_MMU_FAULT_AD_L);
- dp = adh & DSP_MMU_FAULT_AD_H_DP;
- dsp_fault_adr = MK32(adh & DSP_MMU_FAULT_AD_H_ADR_MASK, adl);
-
- /* if the fault is masked, nothing to do */
- if ((status & MMUFAULT_MASK) == 0) {
- printk(KERN_DEBUG "DSP MMU interrupt, but ignoring.\n");
- /*
- * note: in OMAP1710,
- * when CACHE + DMA domain gets out of idle in DSP,
- * MMU interrupt occurs but DSP_MMU_FAULT_ST is not set.
- * in this case, we just ignore the interrupt.
- */
- if (status) {
- printk(KERN_DEBUG "%s%s%s%s\n",
- (status & DSP_MMU_FAULT_ST_PREF)?
- " (prefetch err)" : "",
- (status & DSP_MMU_FAULT_ST_PERM)?
- " (permission fault)" : "",
- (status & DSP_MMU_FAULT_ST_TLB_MISS)?
- " (TLB miss)" : "",
- (status & DSP_MMU_FAULT_ST_TRANS) ?
- " (translation fault)": "");
- printk(KERN_DEBUG "fault address = %#08x\n",
- dsp_fault_adr);
- }
- enable_irq(omap_dsp->mmu_irq);
- return;
- }
+ struct omap_dsp_mapinfo mapinfo;
+ dsp_long_t dspadr;
+ int ret;
+ __u32 size;
-#elif defined(CONFIG_ARCH_OMAP2)
+ switch (cmd) {
+ case MEM_IOCTL_MMUINIT:
+ if (dsp_mmu.exmap_tbl)
+ omap_mmu_unregister(&dsp_mmu);
+ return omap_mmu_register(&dsp_mmu);
- dsp_mmu_reg_t status;
+ 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);
- status = dsp_mmu_read_reg(DSP_MMU_IRQSTATUS);
- dsp_fault_adr = dsp_mmu_read_reg(DSP_MMU_FAULT_AD);
+ case MEM_IOCTL_EXUNMAP:
+ return omap_mmu_exunmap(&dsp_mmu, (unsigned long)arg);
-#endif /* CONFIG_ARCH_OMAP2 */
+ case MEM_IOCTL_EXMAP_FLUSH:
+ omap_mmu_exmap_flush(&dsp_mmu);
+ return 0;
+#ifdef CONFIG_OMAP_DSP_FBEXPORT
+ case MEM_IOCTL_FBEXPORT:
+ 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();
- printk(KERN_INFO "DSP MMU interrupt!\n");
+ case MEM_IOCTL_KMEM_RESERVE:
-#if defined(CONFIG_ARCH_OMAP1)
+ if (copy_from_user(&size, (void __user *)arg,
+ sizeof(__u32)))
+ return -EFAULT;
+ return omap_mmu_kmem_reserve(&dsp_mmu, size);
- printk(KERN_INFO "%s%s%s%s\n",
- (status & DSP_MMU_FAULT_ST_PREF)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PREF)?
- " prefetch err":
- " (prefetch err)":
- "",
- (status & DSP_MMU_FAULT_ST_PERM)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PERM)?
- " permission fault":
- " (permission fault)":
- "",
- (status & DSP_MMU_FAULT_ST_TLB_MISS)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TLB_MISS)?
- " TLB miss":
- " (TLB miss)":
- "",
- (status & DSP_MMU_FAULT_ST_TRANS)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TRANS)?
- " translation fault":
- " (translation fault)":
- "");
-#elif defined(CONFIG_ARCH_OMAP2)
+ case MEM_IOCTL_KMEM_RELEASE:
+ omap_mmu_kmem_release();
+ return 0;
- printk(KERN_INFO "%s%s%s%s%s\n",
- (status & DSP_MMU_IRQ_MULTIHITFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_MULTIHITFAULT)?
- " multi hit":
- " (multi hit)":
- "",
- (status & DSP_MMU_IRQ_TABLEWALKFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TABLEWALKFAULT)?
- " table walk fault":
- " (table walk fault)":
- "",
- (status & DSP_MMU_IRQ_EMUMISS)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_EMUMISS)?
- " EMU miss":
- " (EMU miss)":
- "",
- (status & DSP_MMU_IRQ_TRANSLATIONFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TRANSLATIONFAULT)?
- " translation fault":
- " (translation fault)":
- "",
- (status & DSP_MMU_IRQ_TLBMISS)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TLBMISS)?
- " TLB miss":
- " (TLB miss)":
- "");
-
-#endif /* CONFIG_ARCH_OMAP2 */
-
- printk(KERN_INFO "fault address = %#08x\n", dsp_fault_adr);
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
- dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
- else {
-#ifdef CONFIG_ARCH_OMAP1
- __dsp_mmu_itack();
-#endif
- printk(KERN_INFO "Resetting DSP...\n");
- dsp_cpustat_request(CPUSTAT_RESET);
- /*
- * if we enable followings, semaphore lock should be avoided.
- *
- printk(KERN_INFO "Flushing DSP MMU...\n");
- exmap_flush();
- dsp_mmu_init();
- */
+ default:
+ return -ENOIOCTLCMD;
}
-
-#ifdef CONFIG_ARCH_OMAP2
- dsp_mmu_disable();
- dsp_mmu_write_reg(status, DSP_MMU_IRQSTATUS);
- dsp_mmu_enable();
-#endif
-
- enable_irq(omap_dsp->mmu_irq);
}
-static DECLARE_WORK(mmu_int_work, do_mmu_int);
+struct file_operations dsp_mem_fops = {
+ .owner = THIS_MODULE,
+ .read = dsp_mem_read,
+ .write = dsp_mem_write,
+ .ioctl = dsp_mem_ioctl,
+};
/*
* DSP MMU interrupt handler
*/
-
static irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id)
{
disable_irq(omap_dsp->mmu_irq);
return IRQ_HANDLED;
}
-/*
- *
- */
-struct file_operations dsp_mem_fops = {
- .owner = THIS_MODULE,
- .llseek = dsp_mem_lseek,
- .read = dsp_mem_read,
- .write = dsp_mem_write,
- .ioctl = dsp_mem_ioctl,
- .mmap = dsp_mem_mmap,
- .open = dsp_mem_open,
-};
-
void dsp_mem_start(void)
{
-#ifdef CONFIG_ARCH_OMAP1
dsp_register_mem_cb(intmem_enable, intmem_disable);
-#endif
}
void dsp_mem_stop(void)
{
memset(&mem_sync, 0, sizeof(struct mem_sync_struct));
-#ifdef CONFIG_ARCH_OMAP1
dsp_unregister_mem_cb();
-#endif
}
/*
*/
void dsp_mem_late_init(void)
{
+ int ret = 0;
#ifdef CONFIG_ARCH_OMAP2
- int i;
- int dspmem_pg_count;
+ int i, dspmem_pg_count;
dspmem_pg_count = dspmem_size >> 12;
for (i = 0; i < dspmem_pg_count; i++) {
- dsp_ipi_write_reg(i, DSP_IPI_INDEX);
- dsp_ipi_write_reg(DSP_IPI_ENTRY_ELMSIZEVALUE_16,
- DSP_IPI_ENTRY);
+ writel(i, DSP_IPI_INDEX);
+ writel(DSP_IPI_ENTRY_ELMSIZEVALUE_16, DSP_IPI_ENTRY);
}
- dsp_ipi_write_reg(1, DSP_IPI_ENABLE);
- dsp_ipi_write_reg(IOMAP_VAL, DSP_IPI_IOMAP);
+ writel(1, DSP_IPI_ENABLE);
+ writel(IOMAP_VAL, DSP_IPI_IOMAP);
+
+ 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
- dsp_mmu_init();
+ ret = omap_mmu_register(&dsp_mmu);
}
-static char devid_mmu;
-
int __init dsp_mem_init(void)
{
- int i, ret;
-
- for (i = 0; i < DSP_MMU_TLB_LINES; i++)
- exmap_tbl[i].valid = 0;
-
- dspvect_page = (void *)__get_dma_pages(GFP_KERNEL, 0);
- if (dspvect_page == NULL) {
- printk(KERN_ERR
- "omapdsp: failed to allocate memory "
- "for dsp vector table\n");
- return -ENOMEM;
- }
-
+ int ret;
/*
* DSP MMU interrupt setup
*/
ret = request_irq(omap_dsp->mmu_irq, dsp_mmu_interrupt, IRQF_DISABLED,
- "dsp_mmu", &devid_mmu);
+ "dsp_mmu", NULL);
if (ret) {
printk(KERN_ERR
"failed to register DSP MMU interrupt: %d\n", ret);
- return ret;
+ goto fail;
}
/* MMU interrupt is not enabled until DSP runs */
disable_irq(omap_dsp->mmu_irq);
- ret = device_create_file(omap_dsp->dev, &dev_attr_mmu);
- ret |= device_create_file(omap_dsp->dev, &dev_attr_exmap);
- ret |= device_create_file(omap_dsp->dev, &dev_attr_mempool);
- if (ret)
- printk(KERN_ERR "device_create_file failed: %d\n", ret);
-
return 0;
+ fail:
+#ifdef CONFIG_ARCH_OMAP1
+ dsp_reset_idle_boot_base();
+#endif
+ return ret;
}
void dsp_mem_exit(void)
{
- free_irq(omap_dsp->mmu_irq, &devid_mmu);
+ free_irq(omap_dsp->mmu_irq, NULL);
/* recover disable_depth */
enable_irq(omap_dsp->mmu_irq);
#ifdef CONFIG_ARCH_OMAP1
dsp_reset_idle_boot_base();
#endif
- dsp_mmu_shutdown();
- dsp_kmem_release();
-
- if (dspvect_page != NULL) {
- free_page((unsigned long)dspvect_page);
- dspvect_page = NULL;
- }
-
- device_remove_file(omap_dsp->dev, &dev_attr_mmu);
- device_remove_file(omap_dsp->dev, &dev_attr_exmap);
- device_remove_file(omap_dsp->dev, &dev_attr_mempool);
+ omap_mmu_unregister(&dsp_mmu);
}