⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tffsarch.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** *                                                                            * * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3  family  * * of devices under Linux kernel 2.6.                                         * *                                                                            * *   Version: 1.0                                                             * *   Email questions to: oemsupport@sandisk.com                               * *   Copyright (C) SanDisk IL Ltd. 1995 - 2007                                * *   SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel             * *                                                                            * ****************************************************************************** *                                                                            * * This program is free software; you can redistribute it and/or modify it    * * under the terms of the GNU General Public License as published by the Free * * Software Foundation; either version 2 of the License, or any later version.* * 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, which is set forth in the readme.txt file.                   * * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA                    * *                                                                            * * This License does not grant you any right to use the trademarks, service   * * marks or logos of SanDisk IL Ltd. or SanDisk Corporation.                  * * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * * licensors, hereby reserves all intellectual property rights in the program,* * except for the rights expressly granted in this License.                   * *                                                                            * ******************************************************************************//* * $Log$ */#include "tffsdrv.h"#include "flbase.h"#include "doch_sys.h"/* * macro */#define Align(ptr,alignment)  (((unsigned long)(ptr)) & (~((alignment) - 1)))#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && !defined(virt_addr_valid)#  define virt_addr_valid(vaddr)  (((vaddr) >= PAGE_OFFSET) && ((vaddr) < (unsigned long)high_memory))#endif/* * static routines */static void __dmasw_bread  (int off, void *vbuf, unsigned int bytes);static void __dmasw_bwrite (int off, void *vbuf, unsigned int bytes);/*-----------------------------------------------------------------------* *                                                                       * *                           t f f s _ d m a s w                         * *                                                                       * * Transfer data between DiskOnChip's and RAM buffer.                    * * This routines handles any kind of virtual buffer (linearly mapped or  * * vmalloc() allocated, spanning multiple memory pages, containing       * * multiple sectors).                                                    * *                                                                       * * Parameters:                                                           * *      win            pointer to DiskOnChip's I/O window                * *      off            offset of DiskOnChip's I/O register from the base * *                     of DiskOnChip window                              * *      vbuf           virtual address of RAM buffer                     * *      bytes          bytes to transfer                                 * *      read           DMA direction: '1' for DiskOnChip->RAM, or zero   * *                     for RAM->DiskOnChip                               * *                                                                       * *-----------------------------------------------------------------------*/void tffs_dmasw ( char         * win,                  int            off,                  void         * vbuf,                   unsigned int   bytes,                  int            read ){    /* We check if 'vbuf' is linearly mapped kernel virtual address (and     * is therefore laid out in consecutive physical pages). If 'vbuf'      * is  not linearly mapped (i.e. came from user space or allocated      * via vmalloc()), we check if it entirely fits into a single memory     * page.     */    if ((virt_addr_valid((unsigned long)vbuf)) /* linearly mapped kernel virtual address */            ||        (Align(vbuf,PAGE_SIZE) == Align((unsigned long)vbuf + bytes,PAGE_SIZE)))    {        if (read == 1)            __dmasw_bread (off, vbuf, bytes);        else            __dmasw_bwrite (off, vbuf, bytes);    }    else  /* 'vbuf' crosses memory page boundary */    {        if (bytes >= (FL_SECTOR_SIZE * 2))  /* two or more sectors */        {            register unsigned long  bytes_on_this_page;            /* Do multiple DMA transfers, each one fitting into a single             * memory page.             */            do             {                bytes_on_this_page = PAGE_SIZE - ((unsigned long)vbuf & (PAGE_SIZE - 1));                if (bytes_on_this_page > bytes)                    bytes_on_this_page = bytes;                if (read == 1)                    __dmasw_bread (off, vbuf, bytes_on_this_page);                else                    __dmasw_bwrite (off, vbuf, bytes);                bytes -= bytes_on_this_page;                vbuf   = (char *)vbuf + bytes_on_this_page;            } while (bytes > 0);        }        else  /* single sector; don't bother with DMA ... */        {            if (read == 1)                tffs_readw  ((unsigned long)(win + off), vbuf, (bytes / sizeof(short)));            else                tffs_writew ((unsigned long)(win + off), vbuf, (bytes / sizeof(short)));        }    }}#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE)/*_____________________________________________________________________________ |                                                                            | |                                                                            | |                Intel PXA27x ("Mainstone") board                            | |                                                                            | |____________________________________________________________________________| */# include <asm/dma.h># include <linux/pci.h># include <asm/arch/pxa-regs.h>/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears * to be buggy: it seems to constantly shoot past the end of the address * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some * bogus data into this RAM address range while invalidating it in D-cache.  */# define PXA27X_DCACHE_BUG_WORKAROUND/* * static routines for PXA27x */static void tffs_dma_init (int resume);static void tffs_dma_release (void);static void tffs_dma_intr (int dma, void *dummy, struct pt_regs *regs);/*-----------------------------------------------------------------------* *                                                                       * *                    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 ){    /* chip select that DiskOnChip is connected to */#define PXA27X_CS  5          /* Value to write to chip select's conf register. Possible values are:     *     *     0x099C   VLIO DiskOnChip adapter and DiskOnChip G4/G3/H3 device     *     0x0AAC   VLIO DiskOnChip adapter and DiskOnChip H1 device      *     0xA998   sync DiskOnChip adapter and DiskOnChip G4/G3/H3 device     *     0xAAA8   sync DiskOnChip adapter and DiskOnChip H1 device     *     * Register description:     *     *     31     0 - slow device (VLIO); 1 - fast device     *     30:28  The value of this bit is half the number of memory clock cycles     *            from the time that chip select is de-asserted after a read or     *            write until the next chip select (of a different static memory     *            bank) or nSDCS is asserted     *     27:24  ROM Delay Next Access The RDN field is encoded as follows:     *            ENCODED (Programmed) Value -----> DECODED (Actual) Value     *                                  0-11 -----> 0-11     *                                    12 -----> 15     *                                    13 -----> 20     *                                    14 -----> 26     *                                    15 -----> 30     *            RDNx * 2 = amount of time nOE or nPWE is deasserted to address     *            hold and address setup to nOE or nPWE assertion time     *     23:20  This determines the minimum number of memory clock cycles     *            (minus 1) of nOE (nPWE) assert time for each beat of read (write)     *        19  ROM Bus Width (1 = 16 bits)     *     16-18  0 - Synchronous flash; 2 - burst 4; 3 - burst 8; 4 - Variable-latency     *            I/O (VLIO)     */#define PXA27X_CS_VAL  0x026C /* andrayk Nov 242 006: originally was 0x044C */    int            cs  = PXA27X_CS;    unsigned long  val;    if (resume == FALSE)        { PrintkInfo ("use Chip Select %d", cs); }    /* Line below configures GPIO33 as output.      * Without this line, DiskOnChip driver fails to detect DiskOnChip G4.     */    GPDR1 |= 0x2; /* was: GPDR1 = 0xfc3fab83 */    /* read chip select config reg */    val = __REG(0x48000008 + ((cs / 2) * sizeof(long)));    if (cs & 1)        val = ((PXA27X_CS_VAL << 16) | (val & 0xffff));    else        val = ((val & 0xffff0000) | PXA27X_CS_VAL);    /* write chip select config reg */    __REG(0x48000008 + ((cs / 2) * sizeof(long))) = val;    /* 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){    if (resume == FALSE)     {        /* We use single DMA channel for both 'read' and         * 'write' operations, so we allocate it here.         */        if ((tffsInfo.channel = pxa_request_dma(TFFS_DEVICE_NAME,                                                 DMA_PRIO_LOW, tffs_dma_intr, NULL)) < 0)        {            /* failed to allocate DMA channel, won't use DMA */            tffs_dma_mode = 0;            PrintkError ("can't get DMA chan");            return;        }        PrintkInfo ("use DMA channel %d", tffsInfo.channel);    }    DRCMR(tffsInfo.channel) = (DRCMR_MAPVLD | (tffsInfo.channel & 0x1f));    __REG(0x400000a0) |= (1 << tffsInfo.channel);    /* clear any pending DMA errors/interrupts */    DCSR(tffsInfo.channel) = (DCSR_NODESC | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR);    if (resume == FALSE)    {        tffsInfo.dma_buf_vptr = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -