最新日志

发表于:2007-6-19 13:31:13
标签:psram  

1

psram 会取代 sram 吗?

PSRAM

来自EEWiki.

跳转到: 导航, 搜索

PSRAM,假静态随机存储器。

PSRAM

背景:

PSRAM具有一个单晶体管的DRAM储存格,与传统具有六个晶体管的SRAM储存格或是四个晶体管与two-load resistor SRAM 储存格大不相同,但它具有类似SRAM的稳定接口,内部的DRAM架构给予PSRAM一些比low-power 6T SRAM优异的长处,例如体积更为轻巧,售价更具竞争力。目前在整体SRAM市场中,有90%的制造商都在生产PSRAM组件。在过去两年,市场上重要的SRAM/PSRAM供货商有Samsung、Cypress、Renesas、Micron与Toshiba等。

基本原理:

PSRAM就是伪SRAM,内部的内存颗粒跟SDRAM的颗粒相似,但外部的接口跟SRAM相似,不需要SDRAM那样复杂的控制器和刷新机制,PSRAM的接口跟SRAM的接口是一样的。

PSRAM容量有8Mbit,16Mbit,32Mbit等等,容量没有SDRAM那样密度高,但肯定是比SRAM的容量要高很多的,速度支持突发模式,并不是很慢,Hynix,Coremagic, WINBOND .MICRON. CY 等厂家都有供应,价格只比相同容量的SDRAM稍贵一点点,比SRAM便宜很多。

PSRAM主要应用于手机,电子词典,掌上电脑,PDA,PMP.MP3/4,GPS接收器等消费电子产品与SRAM(采用6T的技术)相比,PSRAM采用的是1T+1C的技术,所以在体积上更小,同时,PSRAM的I/O接口与SRAM相同.在容量上,目前有4MB,8MB,16MB,32MB,64MB和128MB。比较于SDRAM,PSRAM的功耗要低很多。所以对于要求有一定缓存容量的很多便携式产品是一个理想的选择。

目前发展现状:

东芝(Toshiba)、NEC Electronics和富士通(Fujitsu)三家公司日前共同提出PSRAM (Pseudo Static Random Access Memory)第四版的标准接口规范,也称之为CSOMORAM Rev. 4 (COmmon Specifications for MObile RAM)是用于移动RAM的通用规范。三家公司将各自生产与销售自家产品,产品最快可在2007年3月推出。上述三家公司在1998年9月首次提出通用规范,将堆栈多芯片封装(MCP)通用接口规范共享给包括闪存和SRAM在内的移动设备。随后,他们在2002、2003和2004年分别对其进行了修订,增加了页面模式和突发模式等规格。COSMORAM Rev. 4为Pseudo SRAM增加了双速率突发(DDR突发)模式。

点击此处查看原文 >>

系统分类: 嵌入式   |    用户分类:    |    来源: 转贴

评论(0) | 阅读(1286)
发表于:2007-3-30 12:41:59
标签:sd  驱动  

3

关于linux2.6的mmc/sd驱动

 关于linux 2.6 mmc/sd驱动

    linux 2.6 中的mmc/sd驱动分为以下几方面的内容
        1. sysfs 层的总线类型处理: 注册一组 mmc 类型处理函数, 标志为 "mmc"
        2. mmc/sd 快设备管理:注册一个块设备和一组 mmc 总线类型的 driver 子函数, 实现块设备的队列管理等
        3. mmc/sd host管理: 实现 host 的管理
        4. 针对特定的mcu实现一个host驱动实例:主要是注册一个 host实体,中断处理函数,io设置函数,请求处理函数等
     
    以上1.2.3基本是不需要修改的,需要处理的就是 4.要做的工作.当有卡插入时,由4中实现的插卡中断激活卡初始化程序和总线探测函数. 由mmc总线探测函数会调用块设备的探测函数,在卡设备探测函数中会初始化块设备的请求队列和注册一个gendisk实体(以后文件系统会通过gendisk实体访问 mmc 块设备),同时在sysfs中建立真正的 mmc/sd 设备.块设备通过具体的 host 注册的io设置函数和请求函数与具体的host通讯.

点击此处查看原文 >>

系统分类: 嵌入式   |    用户分类:    |    来源: 无分类

评论(0) | 阅读(1925)
发表于:2007-3-29 15:35:16
标签:sd  卡驱动  linux  26  

1

s3c2440linux2.6mmc/sd驱动程序

这几天要做SD卡方面的事情了,看了看相关资料,从网上得到了 s3c2440 在2.6下的驱动,经过修改,目前可以工作了,现拿出与大家分享.希望共同学习讨论.

     1 /*
      2  *  linux/drivers/mmc/s3c2410mci.h - Samsung S3C2410 SDI Interface driver
      3  *
      4  *  Copyright (C) 2004 Thomas Kleffel, All Rights Reserved.
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License version 2 as
      8  * published by the Free Software Foundation.
      9  */
     10 #include <linux/config.h>
     11 #include <linux/module.h>
     12 #include <linux/moduleparam.h>
     13 #include <linux/init.h>
     14 #include <linux/ioport.h>
     15 #include <linux/device.h>
     16 #include <linux/platform_device.h>
     17 #include <linux/interrupt.h>
     18 #include <linux/blkdev.h>
     19 #include <linux/delay.h>
     20 #include <linux/err.h>
     21 #include <linux/dma-mapping.h>
     22 #include <linux/mmc/host.h>
     23 #include <linux/mmc/protocol.h>
     24 #include <linux/clk.h>
     25 #include <linux/irq.h>
     26
     27 #include <asm/dma.h>
     28 #include <asm/dma-mapping.h>
     29 #include <asm/arch/dma.h>
     30
     31 #include <asm/io.h>
     32 #include <asm/irq.h>
     33 #include <asm/mach/mmc.h>
     34
     35 #include <asm/arch/regs-sdi.h>
     36 #include <asm/arch/regs-gpio.h>
     37 #include <asm/arch/mmc.h>
     38
     39 //#define CONFIG_MMC_DEBUG
#ifdef CONFIG_MMC_DEBUG
     42 #define DBG(x...)       printk(KERN_INFO x)
     43 #else
     44 #define DBG(x...)       do { } while (0)
     45 #endif
     46
     47 #include "s3c2440mci.h"
     48
     49 #define DRIVER_NAME "mmci-s3c2410"
     50 #define PFX DRIVER_NAME ": "
     51
     52 #define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
     53
     54 static struct s3c2410_dma_client s3c2410sdi_dma_client = {
     55     .name       = "s3c2410-sdi",
     56 };
 static irqreturn_t s3c2410sdi_irq(int irq, void *dev_id, struct pt_regs *regs)
     82 {
     83     struct s3c2410sdi_host *host;
     84     u32 sdi_csta, sdi_dsta, sdi_dcnt;
     85     u32 sdi_cclear, sdi_dclear;
     86     unsigned long iflags;
     87
     88     host = (struct s3c2410sdi_host *)dev_id;
     89
     90     /* Check for things not supposed to happen */
     91     if(!host) return IRQ_HANDLED;
     92
     93     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
     94     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
     95     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
     96
     97     DBG(PFX "IRQ csta=0x%08x dsta=0x%08x dcnt:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt);
     98
     99     spin_lock_irqsave( &host->complete_lock, iflags);
    100
    101     if( host->complete_what == COMPLETION_NONE ) {
    102         goto clear_imask;
    103     }
    104
    105     if(!host->mrq) {
    106         goto clear_imask;
    107     }
    108
    109     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    110     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    111     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    112     sdi_cclear  = 0;
    113     sdi_dclear  = 0;
    if(sdi_csta & S3C2410_SDICMDSTAT_CMDTIMEOUT) {
    117         DBG(PFX "CMD TIMEOUT\n");
    118         host->mrq->cmd->error = MMC_ERR_TIMEOUT;
    119         goto transfer_closed;
    120     }
    121
    122     if(sdi_csta & S3C2410_SDICMDSTAT_CMDSENT) {
    123         if(host->complete_what == COMPLETION_CMDSENT) {
    124             DBG(PFX "COMPLETION_CMDSENT\n");
    125             host->mrq->cmd->error = MMC_ERR_NONE;
    126             goto transfer_closed;
    127         }
    128
    129         sdi_cclear |= S3C2410_SDICMDSTAT_CMDSENT;
    130     }
    131
    132     if(sdi_csta & S3C2410_SDICMDSTAT_CRCFAIL) {
    133
    134             DBG(PFX "S3C2410_SDICMDSTAT_CRCFAIL\n");
    135
    136         if ((host->mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
    137             DBG(PFX "s3c2410 fixup : ignore CRC fail with long rsp\n");
    138             DBG(PFX "host->mrq->cmd->flags = %x\n", host->mrq->cmd->flags);
    139         }
    140         else {
    141             if(host->mrq->cmd->flags & MMC_RSP_CRC) {
    142                 DBG(PFX "COMMAND CRC FAILED %x\n", sdi_csta);
    143                 host->mrq->cmd->error = MMC_ERR_BADCRC;
    144                 goto transfer_closed;
    145             }
    146         }
    147         sdi_cclear |= S3C2410_SDICMDSTAT_CRCFAIL;
    148     }
     if(sdi_csta & S3C2410_SDICMDSTAT_RSPFIN) {
    151
    152             DBG(PFX "S3C2410_SDICMDSTAT_RSPFIN\n");
    153         if(host->complete_what == COMPLETION_RSPFIN) {
    154             host->mrq->cmd->error = MMC_ERR_NONE;
    155             goto transfer_closed;
    156         }
    157
    158         if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
    159             host->mrq->cmd->error = MMC_ERR_NONE;
    160             host->complete_what = COMPLETION_XFERFINISH;
    161         }
    162
    163         sdi_cclear |= S3C2410_SDICMDSTAT_RSPFIN;
    164     }
    165
    166     if(sdi_dsta & S3C2410_SDIDSTA_FIFOFAIL) {
    167             DBG(PFX "S3C2410_SDIDSTA_FIFOFAIL\n");
    168         host->mrq->cmd->error = MMC_ERR_NONE;
    169         host->mrq->data->error = MMC_ERR_FIFO;
    170         goto transfer_closed;
    171     }
    172
    173     if(sdi_dsta & S3C2410_SDIDSTA_RXCRCFAIL) {
    174         DBG(PFX "S3C2410_SDIDSTA_RXCRCFAIL\n");
    175         host->mrq->cmd->error = MMC_ERR_NONE;
    176         host->mrq->data->error = MMC_ERR_BADCRC;
    177         goto transfer_closed;
    178     }
    179
    180     if(sdi_dsta & S3C2410_SDIDSTA_CRCFAIL) {
    181         DBG(PFX "DATA CRC FAILED %u\n", sdi_csta);
    182         host->mrq->cmd->error = MMC_ERR_NONE;
    183         host->mrq->data->error = MMC_ERR_BADCRC;
    184         goto transfer_closed;
    185     }

     if(sdi_dsta & S3C2410_SDIDSTA_DATATIMEOUT) {
    188         DBG(PFX "S3C2410_SDIDSTA_DATATIMEOUT\n");
    189         host->mrq->cmd->error = MMC_ERR_NONE;
    190         host->mrq->data->error = MMC_ERR_TIMEOUT;
    191         goto transfer_closed;
    192     }
    193
    194     if(sdi_dsta & S3C2410_SDIDSTA_XFERFINISH) {
    195         DBG(PFX "S3C2410_SDIDSTA_XFERFINISH\n");
    196         if(host->complete_what == COMPLETION_XFERFINISH) {
    197             DBG(PFX "COMPLETION_XFERFINISH\n");
    198             host->mrq->cmd->error = MMC_ERR_NONE;
    199             host->mrq->data->error = MMC_ERR_NONE;
    200             goto transfer_closed;
    201         }
    202
    203         if(host->complete_what == COMPLETION_XFERFINISH_RSPFIN) {
    204             DBG(PFX "COMPLETION_XFERFINISH_RSPFIN\n");
    205             host->mrq->data->error = MMC_ERR_NONE;
    206             host->complete_what = COMPLETION_RSPFIN;
    207         }
    208
    209         sdi_dclear |= S3C2410_SDIDSTA_XFERFINISH;
    210     }
    211
    212     writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
    213     writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
    214
    215     spin_unlock_irqrestore( &host->complete_lock, iflags);
    216     DBG(PFX "IRQ still waiting.\n");
    217     return IRQ_HANDLED;

 transfer_closed:
    221     writel(sdi_cclear, host->base + S3C2410_SDICMDSTAT);
    222     writel(sdi_dclear, host->base + S3C2410_SDIDSTA);
    223     host->complete_what = COMPLETION_NONE;
    224     complete(&host->complete_request);
    225     writel(0, host->base + S3C2440_SDIIMSK);
    226     spin_unlock_irqrestore( &host->complete_lock, iflags);
    227     DBG(PFX "IRQ transfer closed.\n");
    228     return IRQ_HANDLED;
    229
    230 clear_imask:
    231     writel(0, host->base + S3C2440_SDIIMSK);
    232     spin_unlock_irqrestore( &host->complete_lock, iflags);
    233     DBG(PFX "IRQ clear imask.\n");
    234     return IRQ_HANDLED;
    235
    236 }
    237
    238
    239 /*
    240  * ISR for the CardDetect Pin
    241 */
    242
    243 static irqreturn_t s3c2410sdi_irq_cd(int irq, void *dev_id, struct pt_regs *regs)
    244 {
    245     struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)dev_id;
    246
    247     //DBG(" %s : %s :%s\n", __FUNCTION__, __FILE__, __LINE__);
    248
    249     mmc_detect_change(host->mmc, S3C2410SDI_CDLATENCY);
    250
    251     return IRQ_HANDLED;
    252 }
    253
 void s3c2410sdi_dma_done_callback(struct s3c2410_dma_chan *dma_ch, void *buf_id,
    257     int size, enum s3c2410_dma_buffresult result)
    258 {   unsigned long iflags;
    259     u32 sdi_csta, sdi_dsta,sdi_dcnt;
    260     struct s3c2410sdi_host *host = (struct s3c2410sdi_host *)buf_id;
    261
    262     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    263     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    264     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    265
    266     DBG(PFX "DMAD csta=0x%08x dsta=0x%08x dcnt:0x%08x result:0x%08x\n", sdi_csta, sdi_dsta, sdi_dcnt, result);
    267
    268     spin_lock_irqsave( &host->complete_lock, iflags);
    269
    270     if(!host->mrq) goto out;
    271     if(!host->mrq->data) goto out;
    272
    273
    274     sdi_csta    = readl(host->base + S3C2410_SDICMDSTAT);
    275     sdi_dsta    = readl(host->base + S3C2410_SDIDSTA);
    276     sdi_dcnt    = readl(host->base + S3C2410_SDIDCNT);
    277
    278     if( result!=S3C2410_RES_OK ) {
    279         goto fail_request;
    280     }
    281
    282
    283     if(host->mrq->data->flags & MMC_DATA_READ) {
    284         if( sdi_dcnt>0 ) {
    285             goto fail_request;
    286         }
    287     }
    288
    289 out:
    290     complete(&host->complete_dma);
    291     spin_unlock_irqrestore( &host->complete_lock, iflags);
    292     return;
    293
 fail_request:
    296     host->mrq->data->error = MMC_ERR_FAILED;
    297     host->complete_what = COMPLETION_NONE;
    298     complete(&host->complete_request);
    299     writel(0, host->base + S3C2440_SDIIMSK);
    300     goto out;
    301
    302 }
    303
    304
    305 void s3c2410sdi_dma_setup(struct s3c2410sdi_host *host, enum s3c2410_dmasrc source) {
    306
    307     s3c2410_dma_devconfig(host->dma, source, 3, host->mem->start + S3C2440_SDIDATA);
    308     s3c2410_dma_config(host->dma, 4, (1<<23) | (2<<24));
    309     s3c2410_dma_set_buffdone_fn(host->dma, s3c2410sdi_dma_done_callback);
    310     s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
    311 }
    312
    313 static void s3c2410sdi_request(struct mmc_host *mmc, struct mmc_request *mrq) {
    314     struct s3c2410sdi_host *host = mmc_priv(mmc);
    315     struct device *dev = mmc_dev(host->mmc);
    316     struct platform_device *pdev = to_platform_device(dev);
    317     u32 sdi_carg, sdi_ccon, sdi_timer;
    318     u32 sdi_bsize, sdi_dcon, sdi_imsk;
    319     u32 sdi_fsta;
    320
    321     int dma_len = 0;
    322
    323     DBG(KERN_DEBUG PFX "request: [CMD] opcode:0x%02x arg:0x%08x flags:%x retries:%u\n",
    324         mrq->cmd->opcode, mrq->cmd->arg, mrq->cmd->flags, mrq->cmd->retries);
    325
    326     DBG(PFX "request : %s mode\n",mmc->mode == MMC_MODE_MMC ? "mmc" : "sd");
 328     sdi_ccon = mrq->cmd->opcode & S3C2410_SDICMDCON_INDEX;
    329     sdi_ccon |= S3C2410_SDICMDCON_SENDERHOST;
    330     sdi_ccon |= S3C2410_SDICMDCON_CMDSTART;
    331
    332     //sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    333     sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    334
    335     sdi_carg = mrq->cmd->arg;
    336
    337     //sdi_timer= 0xF000;
    338     sdi_timer= 0x7fffff;
    339
    340     sdi_bsize= 0;
    341     sdi_dcon = 0;
    342     sdi_imsk = 0;
    343
    344     /* enable interrupts for transmission errors */
    345     sdi_imsk |= S3C2410_SDIIMSK_RESPONSEND;
    346     sdi_imsk |= S3C2410_SDIIMSK_CRCSTATUS;
    347
    348     host->complete_what = COMPLETION_CMDSENT;
    349
    350     if ((mrq->cmd->flags & MMC_RSP_MASK) != MMC_RSP_NONE) {
    351         host->complete_what = COMPLETION_RSPFIN;
    352
    353         sdi_ccon |= S3C2410_SDICMDCON_WAITRSP;
    354         sdi_imsk |= S3C2410_SDIIMSK_CMDTIMEOUT;
    355
    356     } else {
    357         /* We need the CMDSENT-Interrupt only if we want are not waiting
    358          * for a response
    359          */
    360         sdi_imsk |= S3C2410_SDIIMSK_CMDSENT;
    361     }
    362
    363     //if(mrq->cmd->flags & MMC_RSP_LONG) {
    364     if((mrq->cmd->flags & MMC_RSP_MASK) == MMC_RSP_LONG) {
    365         sdi_ccon |= S3C2410_SDICMDCON_LONGRSP;
    366     }
  367
    368     if(mrq->cmd->flags & MMC_RSP_CRC) {
    369         sdi_imsk |= S3C2410_SDIIMSK_RESPONSECRC;
    370     }
    371
    372     if (mrq->data) {
    373         host->complete_what = COMPLETION_XFERFINISH_RSPFIN;
    374
    375         sdi_bsize = (1 << mrq->data->blksz_bits);
    376         host->size = mrq->data->blocks << mrq->data->blksz_bits;
    377
    378         sdi_dcon  = (mrq->data->blocks & S3C2410_SDIDCON_BLKNUM_MASK);
    379         sdi_dcon |= S3C2410_SDIDCON_DMAEN;
    380
    381         sdi_dcon |= S3C2410_SDIDCON_DATA_WORD;
    382         sdi_dcon |= S3C2410_SDIDCON_DTST;
    383
    384         sdi_imsk |= S3C2410_SDIIMSK_FIFOFAIL;
    385         sdi_imsk |= S3C2410_SDIIMSK_DATACRC;
    386         sdi_imsk |= S3C2410_SDIIMSK_DATATIMEOUT;
    387         sdi_imsk |= S3C2410_SDIIMSK_DATAFINISH;
    388         sdi_imsk |= 0xFFFFFFE0;
    389
    390         sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
    391
    392         DBG(PFX "request: [DAT] bsize:%u blocks:%u bytes:%u\n",
    393             sdi_bsize, mrq->data->blocks, mrq->data->blocks * sdi_bsize);
    394
    395
    396         if (host->bus_width == MMC_BUS_WIDTH_4) {
    397             sdi_dcon |= S3C2410_SDIDCON_WIDEBUS;
    398         }
    399
    400         if(!(mrq->data->flags & MMC_DATA_STREAM)) {
    401             sdi_dcon |= S3C2410_SDIDCON_BLOCKMODE;
    402         }
    403
    404         if(mrq->data->flags & MMC_DATA_WRITE) {
    405             sdi_dcon |= S3C2410_SDIDCON_TXAFTERRESP;
    406             sdi_dcon |= S3C2410_SDIDCON_XFER_TXSTART;
    407         }
    408
    409         if(mrq->data->flags & MMC_DATA_READ) {
    410             sdi_dcon |= S3C2410_SDIDCON_RXAFTERCMD;
    411             sdi_dcon |= S3C2410_SDIDCON_XFER_RXSTART;
    412         }
    413
    414         s3c2410sdi_dma_setup(host, mrq->data->flags & MMC_DATA_WRITE ? S3C2410_DMASRC_MEM : S3C2410_DMASRC_HW);
    415
    416         /* see DMA-API.txt */
    417         dma_len = dma_map_sg(&pdev->dev, mrq->data->sg, \
    418                 mrq->data->sg_len, \
    419                 mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
    420
    421         /* start DMA */
    422         s3c2410_dma_enqueue(host->dma, (void *) host,
    423             sg_dma_address(&mrq->data->sg[0]),
    424             (mrq->data->blocks << mrq->data->blksz_bits) );
    425     }
    426
    427     host->mrq = mrq;
    428
    429     init_completion(&host->complete_request);
    430     init_completion(&host->complete_dma);
    431
    432     /* Clear command and data status registers */
    433     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    434     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
    435
    436     writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
    437
    438     /* Setup SDI controller */
    439     writel(sdi_bsize, host->base + S3C2410_SDIBSIZE);
    440     writel(sdi_timer, host->base + S3C2410_SDITIMER);
    441     writel(sdi_imsk, host->base + S3C2440_SDIIMSK);
    442
    443     /* Setup SDI command argument and data control */
    444     writel(sdi_carg, host->base + S3C2410_SDICMDARG);
    445     writel(sdi_dcon, host->base + S3C2410_SDIDCON);
    446
    447     /* This initiates transfer */
    448     writel(sdi_ccon, host->base + S3C2410_SDICMDCON);
    449
    450
    451     /* Wait for transfer to complete */
    452     wait_for_completion(&host->complete_request);
    453
    454     DBG(PFX "[CMD] request complete.\n");
    455
    456     if(mrq->data) {
    457         wait_for_completion(&host->complete_dma);
    458         DBG(PFX "[DAT] DMA complete.\n");
    459     }
    460
    461     /* Cleanup controller */
    462     writel(0, host->base + S3C2410_SDICMDARG);
    463     writel(0, host->base + S3C2410_SDIDCON);
    464     writel(0, host->base + S3C2410_SDICMDCON);
    465     writel(0, host->base + S3C2440_SDIIMSK);
    466
    467     /*  Read response */
    468     mrq->cmd->resp[0] = readl(host->base + S3C2410_SDIRSP0);
    469     mrq->cmd->resp[1] = readl(host->base + S3C2410_SDIRSP1);
    470     mrq->cmd->resp[2] = readl(host->base + S3C2410_SDIRSP2);
    471     mrq->cmd->resp[3] = readl(host->base + S3C2410_SDIRSP3);
    472
    473     host->mrq = NULL;
    474
    475     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    476     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
    477
    478     DBG(PFX "request done.\n");
    479
    480     /* If we have no data transfer we are finished here */
    481     if (!mrq->data) goto request_done;
 482
    483     dma_unmap_sg(&pdev->dev, mrq->data->sg, dma_len, \
    484                  mrq->data->flags & MMC_DATA_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
    485
    486     /* Calulate the amout of bytes transfer, but only if there was
    487      * no error
    488      */
    489     if(mrq->data->error == MMC_ERR_NONE) {
    490         mrq->data->bytes_xfered = (mrq->data->blocks << mrq->data->blksz_bits);
    491     } else {
    492         mrq->data->bytes_xfered = 0;
    493     }
    494
    495     /* If we had an error while transfering data we flush the
    496      * DMA channel to clear out any garbage
    497      */
    498     if(mrq->data->error != MMC_ERR_NONE) {
    499         s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
    500         DBG(PFX "flushing DMA.\n");
    501     }
    502
    503     if(mrq->data->stop) mmc_wait_for_cmd(mmc, mrq->data->stop, 3);
    504
    505 request_done:
    506
    507     mrq->done(mrq);
    508 }
  510 static void s3c2410sdi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) {
    511     struct s3c2410sdi_host *host = mmc_priv(mmc);
    512     u32 sdi_psc, sdi_con, sdi_fsta;
    513
    514     DBG(" %s: %s: line = %d\n", __FUNCTION__, __FILE__, __LINE__);
    515
    516     /* Set power */
    517     sdi_con = readl(host->base + S3C2410_SDICON);
    518     sdi_fsta = readl(host->base + S3C2410_SDIFSTA);
    519
    520     switch(ios->power_mode) {
    521         case MMC_POWER_ON:
    522         case MMC_POWER_UP:
    523             DBG(PFX "power on\n");
    524             s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
    525             s3c2410_gpio_pullup(S3C2410_GPE5, 0);
    526             s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
    527             s3c2410_gpio_pullup(S3C2410_GPE6, 0);
    528             s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
    529             s3c2410_gpio_pullup(S3C2410_GPE7, 0);
    530             s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
    531             s3c2410_gpio_pullup(S3C2410_GPE8, 0);
    532             s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
    533             s3c2410_gpio_pullup(S3C2410_GPE9, 0);
    534             s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
    535             s3c2410_gpio_pullup(S3C2410_GPE10, 0);
    536
    537             if (host->pdata->set_power)
    538                 (host->pdata->set_power)(1);
    539
    540             #ifdef CONFIG_CPU_S3C2440
    541                 sdi_fsta |= S3C2440_SDIFSTA_FIFORESET;
    542             #else
    543                 sdi_con |= S3C2410_SDICON_FIFORESET;
    544             #endif
    545
    546             //sdi_con |= S3C2410_SDICON_BYTEORDER;
    547
    548             break;
  550         case MMC_POWER_OFF:
    551         default:
    552             if (host->pdata->set_power)
    553                 (host->pdata->set_power)(0);
    554             break;
    555     }
    556
    557     /* Set clock */
    558     for(sdi_psc = 0; sdi_psc < 255; sdi_psc++) {
    559         #ifdef CONFIG_CPU_S3C2440
    560         if( (clk_get_rate(host->clk) / ((sdi_psc + 1))) <= ios->clock) break;
    561         #else
    562         if( (clk_get_rate(host->clk) / (2 * (sdi_psc + 1))) <= ios->clock) break;
    563         #endif
    564     }
    565
    566     DBG("\n  ios->clock = %u \n", ios->clock);
    567
    568     if(sdi_psc > 255) sdi_psc = 255;
    569
    570     writel(sdi_psc, host->base + S3C2410_SDIPRE);
    571
    572     /* Set CLOCK_ENABLE */
    573     #ifdef CONFIG_CPU_S3C2440
    574     if(ios->clock)  sdi_con |= S3C2440_SDICON_CLOCK_OUTE;
    575     else        sdi_con &= ~S3C2440_SDICON_CLOCK_OUTE;
    576     #else
    577     if(ios->clock)  sdi_con |= S3C2410_SDICON_CLOCKTYPE;
    578     else        sdi_con &=~S3C2410_SDICON_CLOCKTYPE;
    579     #endif
    580
    581     #ifdef CONFIG_CPU_S3C2440
    582     writel(sdi_fsta, host->base + S3C2410_SDIFSTA);
    583     #endif
    584
    585     writel(0xFFFFFFFF, host->base + S3C2410_SDICMDSTAT);
    586     writel(0xFFFFFFFF, host->base + S3C2410_SDIDSTA);
  587
    588     //writel(0x0FFF, host->base + S3C2410_SDIDSTA);
    589
    590     writel(sdi_con, host->base + S3C2410_SDICON);
    591
    592     host->bus_width = ios->bus_width;
    593
    594     DBG("\n host->bus_width = %u \n", host->bus_width);
    595
    596 }
    597
    598 static struct mmc_host_ops s3c2410sdi_ops = {
    599     .request    = s3c2410sdi_request,
    600     .set_ios    = s3c2410sdi_set_ios,
    601 };

  611 static struct s3c24xx_mmc_platdata s3c2410_mmc_defplat = {
    612     .gpio_detect    = S3C2410_GPG10,
    613     //.set_power    = s3c2410_mmc_def_setpower,
    614     .set_power  = NULL,
    615     .f_max      = 3000000,
    616     .ocr_avail  = MMC_VDD_32_33,
    617 };
    618
    619 static int s3c2410sdi_probe(struct device *dev)
    620 {
    621     struct platform_device  *pdev = to_platform_device(dev);
    622     struct mmc_host     *mmc;
    623     s3c24xx_mmc_pdata_t *pdata;
    624     struct s3c2410sdi_host  *host;
    625
    626     int ret;
    627
    628     mmc = mmc_alloc_host(sizeof(struct s3c2410sdi_host), dev);
    629     if (!mmc) {
    630         ret = -ENOMEM;
    631         goto probe_out;
    632     }
    633
    634     host = mmc_priv(mmc);
    635
    636     spin_lock_init( &host->complete_lock );
    637     host->complete_what     = COMPLETION_NONE;
    638     host->mmc       = mmc;
    639     host->dma       = S3C2410SDI_DMA;
    640
    641     pdata = dev->platform_data;
    642     if (!pdata) {
    643         dev->platform_data = &s3c2410_mmc_defplat;
    644         pdata = &s3c2410_mmc_defplat;
    645     }
    646
    647     host->pdata = pdata;

 649     host->irq_cd = s3c2410_gpio_getirq(pdata->gpio_detect);
    650     s3c2410_gpio_cfgpin(pdata->gpio_detect, S3C2410_GPIO_IRQ);
    651
    652     host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    653     if (!host->mem) {
    654         printk(KERN_ERR PFX "failed to get io memory region resouce.\n");
    655         ret = -ENOENT;
    656         goto probe_free_host;
    657     }
    658
    659     host->mem = request_mem_region(host->mem->start,
    660         RESSIZE(host->mem), pdev->name);
    661
    662     if (!host->mem) {
    663         printk(KERN_ERR PFX "failed to request io memory region.\n");
    664         ret = -ENOENT;
    665         goto probe_free_host;
    666     }
    667
    668     host->base = ioremap(host->mem->start, RESSIZE(host->mem));
    669     if (host->base == 0) {
    670         printk(KERN_ERR PFX "failed to ioremap() io memory region.\n");
    671         ret = -EINVAL;
    672         goto probe_free_mem_region;
    673     }
    674
    675     host->irq = platform_get_irq(pdev, 0);
    676     if (host->irq == 0) {
    677         printk(KERN_ERR PFX "failed to get interrupt resouce.\n");
    678         ret = -EINVAL;
    679         goto probe_iounmap;
    680     }
    681
    682     if(request_irq(host->irq, s3c2410sdi_irq, 0, DRIVER_NAME, host)) {
    683         printk(KERN_ERR PFX "failed to request sdi interrupt.\n");
    684         ret = -ENOENT;
    685         goto probe_iounmap;
    686     }

  689     s3c2410_gpio_cfgpin(S3C2410_GPG10, S3C2410_GPG10_EINT18);
    690
    691     set_irq_type(host->irq_cd, IRQT_BOTHEDGE);
    692
    693     if(request_irq(host->irq_cd, s3c2410sdi_irq_cd, 0, DRIVER_NAME, host)) {
    694         printk(KERN_ERR PFX "failed to request card detect interrupt.\n" );
    695         ret = -ENOENT;
    696         goto probe_free_irq;
    697     }
    698
    699     if(s3c2410_dma_request(S3C2410SDI_DMA, &s3c2410sdi_dma_client, NULL)) {
    700         printk(KERN_ERR PFX "unable to get DMA channel.\n" );
    701         ret = -EBUSY;
    702         goto probe_free_irq_cd;
    703     }
    704
    705     host->clk = clk_get(dev, "sdi");
    706     if (IS_ERR(host->clk)) {
    707         printk(KERN_ERR PFX "failed to find clock source.\n");
    708         ret = PTR_ERR(host->clk);
    709         host->clk = NULL;
    710         goto probe_free_host;
    711     }
    712
    713     if((ret = clk_enable(host->clk))) {
    714         printk(KERN_ERR PFX "failed to enable clock source.\n");
    715         goto clk_free;
    716     }
    717
    718
    719     mmc->ops    = &s3c2410sdi_ops;
    720     mmc->ocr_avail  = MMC_VDD_32_33;
    721
    722     mmc->f_min  = clk_get_rate(host->clk) / 512;
    723     mmc->f_max  = clk_get_rate(host->clk) / 2;
    724
    725     mmc->caps   = MMC_CAP_4_BIT_DATA;
 736     mmc->max_sectors = 64;
    737
    738     /*
    739      * Set the maximum segment size.  Since we aren't doing DMA
    740      * (yet) we are only limited by the data length register.
    741      */
    742
    743     mmc->max_seg_size = mmc->max_sectors << 9;
    744
    745     printk(KERN_INFO PFX "probe: mapped sdi_base=%p irq=%u irq_cd=%u \n", host->base, host->irq, host->irq_cd);
    746
    747     if((ret = mmc_add_host(mmc))) {
    748         printk(KERN_ERR PFX "failed to add mmc host.\n");
    749         goto clk_disable;
    750     }
    751
    752     dev_set_drvdata(dev, mmc);
    753
    754     printk(KERN_INFO PFX "initialisation done.\n");
    755     return 0;
    756
    757  clk_disable:
    758     clk_disable(host->clk);
    759
    760  clk_free:
    761     clk_put(host->clk);
    762
    763  probe_free_irq_cd:
    764     free_irq(host->irq_cd, host);
    765
    766  probe_free_irq:
    767     free_irq(host->irq, host);
    768
    769  probe_iounmap:
    770     iounmap(host->base);
    771
    772  probe_free_mem_region:
    773     release_mem_region(host->mem->start, RESSIZE(host->mem));
                                                                                                                     
    775  probe_free_host:
    776     mmc_free_host(mmc);
    777  probe_out:
    778     return ret;
    779 }
    780
    781 static int s3c2410sdi_remove(struct device *dev)
    782 {
    783     struct mmc_host     *mmc  = dev_get_drvdata(dev);
    784     struct s3c2410sdi_host  *host = mmc_priv(mmc);
    785
    786     mmc_remove_host(mmc);
    787     clk_disable(host->clk);
    788     clk_put(host->clk);
    789     free_irq(host->irq_cd, host);
    790     free_irq(host->irq, host);
    791     iounmap(host->base);
    792     release_mem_region(host->mem->start, RESSIZE(host->mem));
    793     mmc_free_host(mmc);
    794
    795     return 0;
    796 }
    797
    798 static struct device_driver s3c2410sdi_driver =
    799 {
    800         .name           = "s3c2410-sdi",
    801         .bus            = &platform_bus_type,
    802         .probe          = s3c2410sdi_probe,
    803         .remove         = s3c2410sdi_remove,
    804 };
 static int __init s3c2410sdi_init(void)
    807 {
    808     return driver_register(&s3c2410sdi_driver);
    809 }
    810
    811 static void __exit s3c2410sdi_exit(void)
    812 {
    813     driver_unregister(&s3c2410sdi_driver);
    814 }
    815
    816 module_init(s3c2410sdi_init);
    817 module_exit(s3c2410sdi_exit);
    818
    819 MODULE_DESCRIPTION("Samsung S3C2410 Multimedia Card Interface driver");
    820 MODULE_LICENSE("GPL");
                                                                    




点击此处查看原文 >>

系统分类: 嵌入式   |    用户分类:    |    来源: 无分类

评论(7) | 阅读(2284)
发表于:2007-1-16 16:04:49
标签:gpio  button  key  

0

s3c2440-gpio-button(keyboard)驱动

/*
  *  Keyboard driver for s3c2440 gpio button, Borzoi and Akita (SL-Cxx00 series)
  *
  *  Copyright (c) 2005 Richard Purdie
  *
  *  Based on corgikbd.c
  *
   *  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.
  *
  */
     13
     14 #include <linux/delay.h>
     15 #include <linux/platform_device.h>
     16 #include <linux/init.h>
     17 #include <linux/input.h>
     18 #include <linux/interrupt.h>
     19 #include <linux/jiffies.h>
     20 #include <linux/module.h>
     21 #include <linux/slab.h>
     22 #include <linux/irq.h>
     23
     24 #include <asm/io.h>
     25 #include <asm/irq.h>
     26 #include <asm/arch/regs-gpio.h>
     27 #include <asm/arch/hardware.h>
     28
     29 #define KB_ROWS         3
     30 #define KB_COLS         8
     31
     32 #define SCAN_INTERVAL       (50) /* ms */
     33 #define KB_DELAY            10
     34 #define KB_ACTIVATE_DELAY   10
     35
     36 static const unsigned int s3c2440_kbd_keycode[KB_COLS * KB_ROWS] = {
     37     KEY_PLAYPAUSE, KEY_STOPCD, KEY_BACK,KEY_FORWARD,  KEY_RECORD, 0, 0, 0,
     38     KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_F1, KEY_F2, KEY_F3, KEY_F4,
     39     KEY_ESC, KEY_SOUND, KEY_ENTER, KEY_PAGEUP, KEY_PAGEDOWN, 0, KEY_HELP, KEY_F5,
 };
     41
     42 struct s3c2440_kbd {
     43     unsigned int keycode[ARRAY_SIZE(s3c2440_kbd_keycode)];
     44     struct input_dev *input;
     45     char phys[32];
     46
     47     spinlock_t lock;
     48     struct timer_list timers[KB_COLS];
     49
     50     unsigned int suspended;
     51     unsigned long suspend_jiffies;
     52 };
     53
     54 static struct s3c2440_kbd g_s3c2440_kbd;
     55
     56 struct s3c2440_kbd_row{
     57     unsigned int pin;
     58     unsigned int pin_out;
     59     unsigned int pin_val;
     60     unsigned int pin_in;
     61     unsigned int irq;
     62     unsigned int irq_type;
     63     unsigned int irq_flag;
     64 };
     65
     66 static const struct s3c2440_kbd_row c_s3c2440_row[KB_ROWS]=
     67 {
     68     {S3C2410_GPG5, S3C2410_GPG5_OUTP, 0, S3C2410_GPG5_INP, 0, 0, 0},
     69     {S3C2410_GPG6, S3C2410_GPG6_OUTP, 0, S3C2410_GPG6_INP, 0, 0, 0},
     70     {S3C2410_GPG7, S3C2410_GPG7_OUTP, 0, S3C2410_GPG7_INP, 0, 0, 0},
     71 /*
     72     {S3C2410_GPG2, S3C2410_GPG2_OUTP, 0, S3C2410_GPG2_INP, 0, 0, 0},
     73     {S3C2410_GPG3, S3C2410_GPG3_OUTP, 0, S3C2410_GPG3_INP, 0, 0, 0},
     74     {S3C2410_GPG1, S3C2410_GPG1_OUTP, 0, S3C2410_GPG1_INP, 0, 0, 0},
     75     {S3C2410_GPG12, S3C2410_GPG12_OUTP, 0, S3C2410_GPG12_INP, 0, 0, 0},*/
     76 };
 static unsigned int s3c2440_kbd_states[KB_ROWS];
     91
     92
     93 static inline void s3c2440_kbd_set_row_status(int col, int flag)
     94 {
     95     int i;
     96
     97     if (!flag) {
     98         for (i = 0; i < KB_ROWS; i++)
     99             s3c2410_gpio_setpin(c_s3c2440_row[i].pin, 1 - c_s3c2440_row[i].pin_val);
    100     } else {
    101         for (i = 0; i < KB_ROWS; i++)
    102             s3c2410_gpio_setpin(c_s3c2440_row[i].pin, c_s3c2440_row[i].pin_val);
    103     }
    104     return ;
    105 }
static void s3c2440_kbd_scankeyboard(struct s3c2440_kbd *kbd_data, struct pt_regs *regs, int timer_id)
    108 {
    109     unsigned int row;
    110     unsigned long flags;
    111     unsigned int num_pressed;
    112
    113     //printk("\n %s timer_id = %d\n", __FUNCTION__, timer_id);
    114
    115     if (kbd_data->suspended)
    116         return;
    117
    118     spin_lock_irqsave(&kbd_data->lock, flags);
    119
    120     input_regs(kbd_data->input, regs);
    121
    122     num_pressed = 0;
    123
    124     s3c2440_kbd_set_row_status(timer_id, 0);
    125
    126     for (row = 0; row < KB_ROWS; row++) {
    127         unsigned int pin1, pin2, pin3;
    128
    129         s3c2410_gpio_setpin(c_s3c2440_row[row].pin, c_s3c2440_row[row].pin_val);
    130
    131         udelay(KB_ACTIVATE_DELAY);
    132         pin1 = s3c2410_gpio_getpin(c_s3c2440_col[timer_id].pin);
    133
    134         udelay(KB_DELAY);
    135         pin2 = s3c2410_gpio_getpin(c_s3c2440_col[timer_id].pin);
    136
    137         udelay(KB_DELAY);
    138         pin3 = s3c2410_gpio_getpin(c_s3c2440_col[timer_id].pin);
    139
    140         if (pin2 == pin3)
    141             pin1 = pin3;
    142
    143         if (pin1 == pin2 ) {
    144             if (pin1 == c_s3c2440_col[timer_id].pin_val) {
5                 num_pressed++;
    146                 if (s3c2440_kbd_states[row] & (1 << timer_id)) {
    147                     s3c2440_kbd_states[row] &= ~(1 << timer_id);
    148                     input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + timer_id], 1);
    149                     printk("\n keycode = %d pressed = 1 \n", kbd_data->keycode[row * KB_COLS + timer_id]);
    150                     //printk("\n row = %d col = %d \n", row, timer_id);
    151
    152                 }
    153             }else {
    154                 if ( !(s3c2440_kbd_states[row] & (1 << timer_id)) ) {
    155                     s3c2440_kbd_states[row] |= (1 << timer_id);
    156                     input_report_key(kbd_data->input, kbd_data->keycode[row * KB_COLS + timer_id], 0);
    157                     printk("\n keycode = %d pressed = 0 \n", kbd_data->keycode[row * KB_COLS + timer_id]);
    158                 }
    159             }
    160         }
    161
    162         s3c2410_gpio_setpin(c_s3c2440_row[row].pin, 1 - c_s3c2440_row[row].pin_val);
    163     }
    164
    165     s3c2440_kbd_set_row_status(timer_id, 1);
    166
    167     input_sync(kbd_data->input);
    168
    169     /* if any keys are pressed, enable the timer */
    170     if (num_pressed) {
    171         mod_timer(&kbd_data->timers[timer_id], jiffies + msecs_to_jiffies(SCAN_INTERVAL));
    172     }else {
    173         set_irq_type(c_s3c2440_col[timer_id].irq, c_s3c2440_col[timer_id].irq_type);
    174         enable_irq(c_s3c2440_col[timer_id].irq);
    175     }
    176     spin_unlock_irqrestore(&kbd_data->lock, flags);
    177 }


static irqreturn_t s3c2440_kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    180 {
    181     int i = (int)dev_id;
    182
    183     //printk("\n %s : IRQ = %d \n", __FUNCTION__, i);
    184
    185     if (i >= 0 && i < KB_COLS) {
    186
    187         if (!timer_pending(&g_s3c2440_kbd.timers[i])) {
    188             /** wait chattering delay **/
    189             //udelay(20);
    190             //s3c2440_kbd_scankeyboard(&g_s3c2440_kbd, regs);
    191             disable_irq(c_s3c2440_col[i].irq);
    192             s3c2410_gpio_cfgpin(c_s3c2440_col[i].pin, c_s3c2440_col[i].pin_in);
    193             mod_timer(&g_s3c2440_kbd.timers[i], jiffies + msecs_to_jiffies(SCAN_INTERVAL));
    194         }
    195     }
    196
    197     return IRQ_HANDLED;
    198 }

 static void s3c2440_kbd_timer_callback(unsigned long data)
    201 {
    202     int timer_id = (int)data;
    203
    204     //printk("\n %s: timer id = %d\n", __FUNCTION__, timer_id);
    205
    206     if (timer_id >= 0 && timer_id < KB_COLS) {
    207         s3c2440_kbd_scankeyboard(&g_s3c2440_kbd, NULL, timer_id);
    208     #if 0
    209         set_irq_type(c_s3c2440_col[timer_id].irq, c_s3c2440_col[timer_id].irq_type);
    210         enable_irq(c_s3c2440_col[timer_id].irq);
    211     #endif
    212     }
    213 }
    214
6 #ifdef CONFIG_PM
    217 static int s3c2440_kbd_suspend(struct platform_device *dev, pm_message_t state)
    218 {
    219     struct s3c2440_kbd *s3c2440_kbd = platform_get_drvdata(dev);
    220     s3c2440_kbd->suspended = 1;
    221
    222     #if 0
    223     /* Set Strobe lines as inputs - *except* strobe line 0 leave this
    224        enabled so we can detect a power button press for resume */
    225     for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
    226         pxa_gpio_mode(s3c2440_kbd_strobes[i] | GPIO_IN);
    227     #endif
    228
    229     return 0;
    230 }
    231
    232 static int s3c2440_kbd_resume(struct platform_device *dev)
    233 {
    234     struct s3c2440_kbd *s3c2440_kbd = platform_get_drvdata(dev);
    235
    236     #if 0
    237     for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
    238         pxa_gpio_mode(s3c2440_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
    239     #endif
    240
    241     /* Upon resume, ignore the suspend key for a short while */
    242     s3c2440_kbd->suspend_jiffies = jiffies;
    243     s3c2440_kbd->suspended = 0;
    244
    245     return 0;
    246 }
    247 #else
    248 #define s3c2440_kbd_suspend NULL
    249 #define s3c2440_kbd_resume      NULL
    250 #endif

 static int __init s3c2440_kbd_probe(struct platform_device *dev)
    253 {
    254     struct input_dev *input_dev;
    255     int i;
    256
    257     input_dev = input_allocate_device();
    258     if (!input_dev) {
    259         return -ENOMEM;
    260     }
    261
    262     platform_set_drvdata(dev, &g_s3c2440_kbd);
    263
    264     strcpy(g_s3c2440_kbd.phys, "input/kbd0");
    265
    266     spin_lock_init(&g_s3c2440_kbd.lock);
    267
    268     /* Init Keyboard rescan timer */
    269     //init_timer(&g_s3c2440_kbd.timer);
    270     //g_s3c2440_kbd.timer.function = s3c2440_kbd_timer_callback;
    271     //g_s3c2440_kbd.timer.data = (unsigned long)&g_s3c2440_kbd;
    272
    273     g_s3c2440_kbd.suspend_jiffies = jiffies;
    274
    275     g_s3c2440_kbd.input = input_dev;
    276
    277     input_dev->private = &g_s3c2440_kbd;
    278     input_dev->name = "S3c2440 Keyboard";
    279     input_dev->phys = g_s3c2440_kbd.phys;
    280     input_dev->cdev.dev = &dev->dev;
    281
    282     input_dev->id.bustype = BUS_PARPORT;
    283     input_dev->id.vendor = 0x0001;
    284     input_dev->id.product = 0x0001;
    285     input_dev->id.version = 0x0100;
    286
    287     input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_SYN);
    288     input_dev->keycode = g_s3c2440_kbd.keycode;
    289     input_dev->keycodesize = sizeof(unsigned int);
    290     input_dev->keycodemax = ARRAY_SIZE(s3c2440_kbd_keycode);
    292     memcpy(g_s3c2440_kbd.keycode, s3c2440_kbd_keycode, sizeof(g_s3c2440_kbd.keycode));
    293     for (i = 0; i < ARRAY_SIZE(s3c2440_kbd_keycode); i++)
    294         set_bit(g_s3c2440_kbd.keycode[i], input_dev->keybit);
    295
    296     //clear_bit(0, input_dev->keybit);
    297
    298     for (i = 0; i < KB_ROWS; i++) {
    299         s3c2410_gpio_cfgpin(c_s3c2440_row[i].pin, c_s3c2440_row[i].pin_out);
    300         s3c2410_gpio_pullup(c_s3c2440_row[i].pin, 1);
    301         s3c2410_gpio_setpin(c_s3c2440_row[i].pin, c_s3c2440_row[i].pin_val);
    302         s3c2440_kbd_states[i] = -1;
    303     }
    304
    305     for (i = 0; i < KB_COLS; i++) {
    306         init_timer(&g_s3c2440_kbd.timers[i]);
    307         g_s3c2440_kbd.timers[i].function = s3c2440_kbd_timer_callback;
    308         g_s3c2440_kbd.timers[i].data = (unsigned long)i;
    309
    310         s3c2410_gpio_pullup(c_s3c2440_col[i].pin, 0);
    311
    312         set_irq_type(c_s3c2440_col[i].irq, c_s3c2440_col[i].irq_type);
    313         if (request_irq(c_s3c2440_col[i].irq, s3c2440_kbd_interrupt, c_s3c2440_col[i].irq_flag,"kbd_irq",(void*)i)){
    314             while ( i >= 0 ){
    315                 disable_irq(c_s3c2440_col[i].irq);
    316                 free_irq(c_s3c2440_col[i].irq, (void*)i);
    317                 s3c2410_gpio_cfgpin(c_s3c2440_col[i].pin, c_s3c2440_col[i].pin_in);
    318             }
    319             printk(KERN_ERR "s3c2440_gpio_kbd.c: Could not allocate irq !\n");
    320             return -EIO;
    321         }
    322
    323     }

    354     input_register_device(input_dev);
    355
    356     printk(KERN_INFO "input: S3c2440  Keyboard Registered\n");
    357
    358     return 0;
    359 }
 static int s3c2440_kbd_remove(struct platform_device *dev)
    362 {
    363     int i;
    364     struct s3c2440_kbd *s3c2440_kbd = platform_get_drvdata(dev);
    365
    366     #if 0
    367     disable_irq(IRQ_EINT0);
    368     disable_irq(IRQ_EINT2);
    369
    370     free_irq(IRQ_EINT0, (void*)IRQ_EINT0);
    371     free_irq(IRQ_EINT2, (void*)IRQ_EINT2);
    372     #endif
    373
    374     for (i = 0; i < KB_COLS; i++)
    375     {
    376         del_timer_sync(&s3c2440_kbd->timers[i]);
    377         disable_irq(c_s3c2440_col[i].irq);
    378         free_irq(c_s3c2440_col[i].irq, (void*)i);
    379         s3c2410_gpio_cfgpin(c_s3c2440_col[i].pin, c_s3c2440_col[i].pin_in);
    380     }
    381
    382     input_unregister_device(s3c2440_kbd->input);
    383
    384     return 0;
    385 }
    386
    387 static struct platform_driver s3c2440_kbd_driver = {
    388     .probe      = s3c2440_kbd_probe,
    389     .remove     = s3c2440_kbd_remove,
    390     .suspend    = s3c2440_kbd_suspend,
    391     .resume     = s3c2440_kbd_resume,
    392     .driver     = {
    393         .name   = "s3c2440-gpio-kbd",
    394     },
    395 };
    396

 static int __init s3c2440_kbd_init(void)
    398 {
    399     return platform_driver_register(&s3c2440_kbd_driver);
    400 }
    401
    402 static void __exit s3c2440_kbd_exit(void)
    403 {
    404     platform_driver_unregister(&s3c2440_kbd_driver);
    405 }
    406
    407 module_init(s3c2440_kbd_init);
    408 module_exit(s3c2440_kbd_exit);
           MODULE_AUTHOR("s3c2440");
           MODULE_DESCRIPTION("smdk s3c2440 Keyboard Driver");
           MODULE_LICENSE("GPLv2");





                                                                                                         

<