📄 tffsarch.c
字号:
* t f f s _ d m a _ i n t r * * * * Handle DMA interrupt on Intel PXA27x (Mainstone) board. * * * * Parameters: * * dma interrupting DMA channel * * dummy not used * * regs not used * * * *-----------------------------------------------------------------------*/static void tffs_dma_intr ( int dma, void * dummy, /* not used */ struct pt_regs * regs ) /* not used */{ register u_int tmp; profiling[4]++; /* check if interrupt came from our DMA channel */ if (dma == tffsInfo.channel) { /* check if DMA transfer was successful */ if ((tmp = DCSR(dma)) & DCSR_BUSERR) { /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ PrintkError ("Bus error, DMA transfer failed"); } /* clear DMA interrupt from this channel */ DCSR(dma) = (tmp | (DCSR_BUSERR | DCSR_ENDINTR)); } else { PrintkError ("received DMA interrupt on wrong channel"); }}#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2)/*_____________________________________________________________________________ | | | | | Texas Instruments OMAP-1610 (H2) board | | | |____________________________________________________________________________| */# include <asm/arch/hardware.h># include <asm/arch/dma.h> /* EMIFS: Extended Memory Interface Slow. This 16-bit wide bus can interface with and handle all transactions to flash memory, ROM, asynchronous memories, and synchronous burst flash. The EMIFS can support 16-bit interface width only. TC: traffic controller The EMIFS supports 8-,16-, or 32-bit asynchronous and synchronous read, 4- x 32-bit synchronous burst read and 8-, 16-, or 32-bit asynchronous write. EMIFS_PRIOR EMIFS LRU priority register FFFECC04 EMIFS_CONFIG EMIFS configuration register FFFECC0C EMIFS_CCS2 EMIFS chip-select configuration CS2 FFFECC18 7:4 RDWST Controls the wait states cycle number for asynchronous read operation and the initial idle time for asynchronous read page mode and synchronous read mode. 15:12 PGWST/WELEN Controls the wait states cycle number between accesses in a page for asynchronous page mode. Controls the WE pulse length during a write access. When PGWSTEN is 0, this bit specifies both PGWST/WELEN. When PGWSTEN is 1, this bit specifies only WELEN EMIFS_PTOR1 EMIFS dynamic priority time-out 1 FFFECC28 EMIFS_PTOR2 EMIFS dynamic priority time-out 2 FFFECC2C EMIFS_PTOR3 EMIFS dynamic priority time-out 3 FFFECC30 EMIFS_DWS EMIFS dynamic wait states FFFECC40 EMIFS_AADDR EMIFS abort address FFFECC44 EMIFS_ATYPER EMIFS abort type FFFECC48 EMIFS_ATOR EMIFS abort time-out FFFECC4C EMIFS_ACS2 Advanced EMIFS chip-select configuration nCS2 FFFECC58 EMIFS_CS2_CONFIG 0xFFFECC18 BSP sets the reg val 0xf800f22a, but the val after kernel starts is 0xff80fff3 *//* * static routines for OMAP1610 */static void tffs_dma_init (int resume);static void tffs_dma_release (void);/* * static vars */static dma_regs_t * dma_regs = NULL;/*-----------------------------------------------------------------------* * * * t f f s a r c h _ i n i t * * * * This routine is called during module initialization time with 'resume'* * argument set to FALSE, and from Power Manager's 'resume' routine with * * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * * allocates and initializes all required board resources; if 'resume' * * is TRUE, this routine does minimal required re-initialization of * * these resources after power suspend. * * * * Parameters: * * suspend FALSE (module initialization) or TRUE (power resume) * * * * Returns: * * always '1' (success) * * * *-----------------------------------------------------------------------*/unsigned char tffsarch_init (int resume){ register unsigned short tmp16; register unsigned long tmp32; /* Configure Chip Select that DiskOnChip is connected to. * * NOTE. Code below configures Chip Select to set duration of * DiskOnChip access cycle to 70 nanosecond, which is * appropriate for the case when DiskOnChip is connected to * OMAP1610 board via M-Systems' adapters. If you solder * DiskOnChip into your board, consider changing Chip Select * settings to significantly shorten DiskOnChip acecss cycle. * This should have significant positive efefct on * DiskOnChip's 'read' performance. */ tmp32 = (1 << 27) | /* wait states between accesses in a page for async. page mode */ (1 << 23) | /* idle cycles for bus turn around */ (0 << 16) | /* asynchronous read */ (1 << 12) | /* WE length */ (0 << 8) | /* wait states in write operation */ (0 << 4) | /* wait states in read operation */ 2; /* REF_CLK = TC_CK / 2 */ #define OMAP1610_H2_CS 2 /* chip select that DiskOnChip is connected to */ outl (tmp32, (EMIFS_CS0_CONFIG + (OMAP1610_H2_CS * sizeof(unsigned long)))); if (tffs_irq >= 0) { /* Configure GPIO-9 as input. This is actually a default state * after reset, but just to be sure ... */ tmp16 = inw (GPIO_DIRECTION_REG); outw ((tmp16 | (1 << (tffs_irq - IH_GPIO_BASE))), GPIO_DIRECTION_REG); /* configure DiskOnChip IRQ as GPIO-9, disable PullDown */ outl( (inl(PULL_DWN_CTRL_2) | (1 << 23)), PULL_DWN_CTRL_2); /* select function W8 pin as GPIO-9 */ outl( (inl(FUNC_MUX_CTRL_B) & 0xFF1FFFFF), FUNC_MUX_CTRL_B); }# if 0 volatile unsigned long*reg; unsigned long ulTemp; /* configure DMAREQ# as MPUIO4, disable PullDown */ ulTemp = *(volatile unsigned long*) 0xFFFE1044; ulTemp |= 0x00002000; /* 0x1<<13; */ *(volatile unsigned long *)0xFFFE1044 = (unsigned long)ulTemp; /* select function DMA_REQ tffsInfo.channel 6 */ ulTemp = *(volatile unsigned long*) 0xFFFE1020; ulTemp |= 0x8000; /* 0x1<<15; */ *(volatile unsigned long *)0xFFFE1020 = (unsigned long)ulTemp; /* configure mDoc IRQ# as GPIO-9, disable PullDown */ /* TH: For H2 Platform */ ulTemp = *(volatile unsigned long*) 0xFFFE1048; ulTemp |= 0x800000; /* 0x1<<23; */ *(volatile unsigned long *)0xFFFE1048 = (unsigned long)ulTemp; /* select function W8 pin as GPIO-9 */ ulTemp = *(volatile unsigned long*) (0xFFFE1030); ulTemp &= 0xFF1FFFFF; *(volatile unsigned long *)(0xFFFE1030) = (unsigned long)ulTemp; reg=(unsigned long*)EMIFS_CONFIG_REG; PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); *reg=0x0c; reg=(unsigned long*)EMIFS_CONFIG_REG; PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); reg=(unsigned long*)EMIFS_CS2_CONFIG2; PrintkInfo("EMIFS_CS2_CONFIG2=0x%lx",*reg); reg=(unsigned long*)EMIFS_CS2_CONFIG; PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg); *reg=0x8070; reg=(unsigned long*)EMIFS_CS2_CONFIG; PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg);# endif /* if DMA is requested, configure it */ if (tffs_dma_mode > 0) { tffs_dma_init (resume); } return 1;}void TffsHWRelease(void){ /* if DMA was actually used, release all DMA resources */ if (tffs_dma_mode > 0) { tffs_dma_release (); }}/*-----------------------------------------------------------------------* * * * t f f s _ d m a _ i n i t * * * * This routine is called during module initialization time with 'resume'* * argument set to FALSE, and from Power Manager's 'resume' routine with * * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * * allocates and initializes all required DMA resources; if 'resume' is * * TRUE, this routine does minimal required re-initialization of DMA * * channel after power suspend. * * * * Parameters: * * resume FALSE (module initialization) or TRUE (power resume) * * * *-----------------------------------------------------------------------*/static void tffs_dma_init (int resume){ u32 tmp; if (resume == FALSE) { /* We use single DMA channel for both 'read' and 'write' operations, * so we allocate it here. We don't use DMA interrupts, so we won't * need DMA callback. */ tffsInfo.channel = omap_request_dma (eDMANotSync, /* not connected to any DMA line */ TFFS_DEVICE_NAME, NULL, /* no callback when DMA completes */ NULL, /* data to pass to DMA callback */ &dma_regs); if ((tffsInfo.channel != 0) || (dma_regs == NULL)) { /* failed to allocate DMA channel, won't use DMA */ tffs_dma_mode = 0; PrintkError ("can't get DMA chan"); return; } } /* Logical Channel Control Register. * Specify peripheral DMA transfer. */ dma_regs->lch_ctrl = LCH_TYPE_P; /* Channel Element Number Register. * Specify single element (16-bit word) per DMA frame. */ dma_regs->cen = 1; /* Channel Control Register 2. * Specify block synchronization. */ dma_regs->ccr2 = (1 << 2); /* Channel Interrupt Control Register. * Enable time-out interrupt, disable all others. */ dma_regs->cicr = /* (1 << 5) | */ /* end-of-block interrupt */ 1; /* timeout interrupt */ /* read Channel Status register to clear it */ tmp = dma_regs->csr; if (resume == FALSE) { tffsInfo.dma_buf_vptr = NULL; tffsInfo.dma_buf_size = 0; if ((tffs_dma_mode >= 1) && (tffs_dma_mode <= 3)) { /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ tffsInfo.dma_buf_size = PAGE_SIZE; tffsInfo.dma_buf_vptr = #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, &tffsInfo.dma_buf_paddr);#else dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA));#endif if (tffsInfo.dma_buf_vptr == NULL) { /* failed to allocate intermediate DMA buffer, won't use DMA */ tffs_dma_mode = 0; omap_free_dma (dma_regs); dma_regs = NULL; tffsInfo.dma_buf_size = 0; PrintkError ("can't alloc DMA buffer"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -