if ARCH_OMAP
source "drivers/cbus/Kconfig"
-source "drivers/dsp/dspgateway/Kconfig"
endif
endmenu
#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 { \
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
+++ /dev/null
-/*
- * linux/arch/arm/mach-omap1/mmu.c
- *
- * Support for non-MPU OMAP1 MMUs.
- *
- * Copyright (C) 2002-2005 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * and Paul Mundt <paul.mundt@nokia.com>
- *
- * 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 <linux/types.h>
-#include <linux/init.h>
-#include <linux/rwsem.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include "mmu.h"
-#include <asm/tlbflush.h>
-#include <mach/dsp_common.h>
-
-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);
+++ /dev/null
-#ifndef __MACH_OMAP1_MMU_H
-#define __MACH_OMAP1_MMU_H
-
-#include <linux/io.h>
-#include <mach/mmu.h>
-
-#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 */
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
+++ /dev/null
-/*
- * linux/arch/arm/mach-omap2/mmu.c
- *
- * Support for non-MPU OMAP2 MMUs.
- *
- * Copyright (C) 2002-2007 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * and Paul Mundt <paul.mundt@nokia.com>
- *
- * TWL support: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * 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 <linux/types.h>
-#include <linux/init.h>
-#include <linux/rwsem.h>
-#include <linux/device.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include "mmu.h"
-#include <mach/mmu.h>
-#include <asm/tlbflush.h>
-#include <asm/sizes.h>
-
-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");
+++ /dev/null
-#ifndef __MACH_OMAP2_MMU_H
-#define __MACH_OMAP2_MMU_H
-
-#include <linux/io.h>
-#include <mach/mmu.h>
-
-#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 */
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
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
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
*
* Contact: Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
*
- * 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 <linux/clk.h>
-
-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);
+++ /dev/null
-#ifndef __ARCH_OMAP_MMU_H
-#define __ARCH_OMAP_MMU_H
-
-#include <linux/device.h>
-#include <linux/workqueue.h>
-
-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 */
+++ /dev/null
-/*
- * linux/arch/arm/plat-omap/mmu.c
- *
- * OMAP MMU management framework
- *
- * Copyright (C) 2002-2006 Nokia Corporation
- *
- * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>
- * and Paul Mundt <lethal@linux-sh.org>
- *
- * TWL support: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/mempool.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <mach/mmu.h>
-#include <asm/sizes.h>
-#include <mach/dsp_common.h>
-
-#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");
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/
+++ /dev/null
-
-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.
-
+++ /dev/null
-#
-# 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
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <mach/dsp_common.h>
-#include <mach/mmu.h>
-
-
-#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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/tlbflush.h>
-#include <asm/irq.h>
-#include <mach/dsp_common.h>
-#include "dsp.h"
-
-#ifdef CONFIG_ARCH_OMAP1
-#include <mach/tc.h>
-#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
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <asm/delay.h>
-#include <mach/mailbox.h>
-#include <mach/dsp.h>
-#include <mach/dsp_common.h>
-#include "dsp_mbcmd.h"
-#include "dsp.h"
-#include "ipbuf.h"
-
-MODULE_AUTHOR("Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com>");
-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);
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/ioctls.h>
-#include <mach/mailbox.h>
-#include <mach/dsp.h>
-#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);
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/major.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#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");
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * Conversion to mempool API and ARM MMU section mapping
- * by Paul Mundt <paul.mundt@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/fb.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mempool.h>
-#include <linux/clk.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <mach/tc.h>
-#include <mach/omapfb.h>
-#include <mach/dsp.h>
-#include <mach/mailbox.h>
-#include <mach/mmu.h>
-#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);
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <mach/mailbox.h>
-#include <asm/uaccess.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/sched.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <mach/mailbox.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/platform_device.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <mach/mailbox.h>
-#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);
-}
+++ /dev/null
-#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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <mach/hardware.h>
-
-/*
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 */
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/kfifo.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <mach/mailbox.h>
-#include <mach/dsp.h>
-#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");
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/module.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <asm/uaccess.h>
-#include <mach/dsp.h>
-#include <asm/io.h>
-#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);
-}
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <linux/linkage.h>
-#include <asm/assembler.h>
-
- .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
+++ /dev/null
-/*
- * 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 <toshihiro.kobayashi@nokia.com>
- *
- * 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 <asm/uaccess.h>
-#include <mach/dsp_common.h>
-#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 */
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
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
#include <linux/err.h>
#include <linux/kfifo.h>
#include <linux/log2.h>
-#include <linux/uaccess.h>
/**
* kfifo_init - allocates a new FIFO using a preallocated buffer
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);