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

📄 s3c2410-kbd.c

📁 这个程序为嵌入式linux系统下的键盘驱动程序
💻 C
字号:
#include <linux/config.h>
#include <linux/input.h>
#include <linux/interrupt.h> /* irqreturn_t */ /*包含了 linux/kernel.h*/
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-spi.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/arch/regs-clock.h>

#define S3C2410_KBD_DEBUG
/* Debug tool */
/*capital!*/
#ifdef S3C2410_KBD_DEBUG
#define DPRINTK(fmt, args...) printk(KERN_INFO fmt, ##args)
#else
#define DPRINTK(fmt, args...) do {} while(0)
#endif

#define PFX "s3c2410-kbd: "

static struct resource * s3c2410_spi_mem;
static void __iomem *s3c2410_spi_base;
struct clk *spi_clk;


/* Write cmd to zlg7289 */
static int zlg7289_write(unsigned char c)
{
     unsigned int ret;KDBy/
     s3c2410_gpio_setpin(S3C2410_GPG2, 0);
     /* Master out */
     s3c2410_gpio_setpin(S3C2410_GPB0, 0);
     udelay(60);
     while((ioread8(s3c2410_spi_base + S3C2410_SPSTA) & 0x1) == 0);
     iowrite8(c, s3c2410_spi_base + S3C2410_SPTDAT);
     /* Master in */
     s3c2410_gpio_setpin(S3C2410_GPB0, 1);
     while((ioread8(s3c2410_spi_base + S3C2410_SPSTA) & 0x1) == 0);
     ret = ioread32(s3c2410_spi_base + S3C2410_SPRDAT);
     /* Disable CS */KDB
     s3c2410_gpio_setpin(S3C2410_GPG2, 1);
     /* Master out */
     s3c2410_gpio_setpin(S3C2410_GPB0, 0);
     return ret;
}

/* Read key value of zlg7289 */
static unsigned char zlg7289_read_key(void)
{
     unsigned char ret;
     /* Enable CS */
     s3c2410_gpio_setpin(S3C2410_GPG2, 0);
     /* Master out */
     s3c2410_gpio_setpin(S3C2410_GPB0, 0);
     udelay(60);
     /* Send read key cmd to zlg7289 */
     while((ioread8(s3c2410_spi_base + S3C2410_SPSTA) & 0x1) == 0);
     iowrite8(0x15, s3c2410_spi_base + S3C2410_SPTDAT);
     while((ioread8(s3c2410_spi_base + S3C2410_SPSTA) & 0x1) == 0);
     udelay(30);
     /* Master in */
     s3c2410_gpio_setpin(S3C2410_GPB0, 1);
     /* Write 0xff to start tx & rx procedure */
     iowrite8(0xff, s3c2410_spi_base + S3C2410_SPTDAT);
     while((ioread8(s3c2410_spi_base + S3C2410_SPSTA) & 0x1) == 0);
     ret = ioread8(s3c2410_spi_base + S3C2410_SPRDAT);
     /* Disable CS */
     s3c2410_gpio_setpin(S3C2410_GPG2, 1);
     /* Master out */
     s3c2410_gpio_setpin(S3C2410_GPB0, 0);
     return ret;
}

/*interrupt handle*/
static irqreturn_t s3c2410kbd_keyevent(int irq, void *dev_id, struct pt_regs *reg)
{
	unsigned char data;
	/*read key*/
	data=zlg7289_read_key();

	printk(PFX "key data is 0x%x\n",data);
	 return IRQ_HANDLED;
}


/*spi config*/
	
static void s3c2410_spi_enable(void)
{ 
	unsigned char tmp;
	if(s3c2410_spi_base==NULL)
		return;
	 /*SETUP DIR*/
	 s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
	 s3c2410_gpio_setpin(S3C2410_GPB0, 0);
     /*SETUP SPIMIS00*/
	 s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE2_SPIMIS00);

	 /*SETUP NSS0*/
	 s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_OUTP);
	 s3c2410_gpio_setpin(S3C2410_GPG2, 1);

	 /*SETUP SPICLK0*/
	 s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_SPICLK0);

	  /*SETUP SPIMOSI0*/
	 s3c2410_gpio_cfgpin(S3C2410_GPE12, S3C2410_GPE12_SPIMOSI0);

	  /*SETUP BAND RATE REG SPPRE0*/
	 iowrite8(255,s3c2410_spi_base+S3C2410_SPPRE);

	  /*SETUP SPCON0*/
	 tmp=ioread8(s3c2410_spi_base+S3C2410_SPCON);
	 tmp&=~S3C2410_SPCON_SMOD_INT;
	 tmp|=S3C2410_SPCON_ENSCK;
	 tmp|=S3C2410_SPCON_MSTR;
	 tmp&=~S3C2410_SPCON_CPOL_HIGH;
     tmp|=S3C2410_SPCON_CPHA_FMTA;
	 tmp&=~S3C2410_SPCON_TAGD;
	 iowrite8(tmp,s3c2410_spi_base+S3C2410_SPCON);
	 dprintk(PFX"after setting SPICON,SPICON=0x%x\n",ioread8(s3c2410_spi_base+S3C2410_SPCON));

	 /*SET UP EINT*/
	 s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_EINT1);

	 /*RESET ZLG7289*/
	 zlg7219_write(0xa4);

}


/*probe */
static int _init s3c2410kbd_probe(struct platform_device *pdev)
{ 
  int ret;
  struct resource *res;
  /*enable clk*/
  spi_clk=clk_get(&pdev->dev, "spi");
  if(IS_ERR(spi_clk)){
	  printk(KERN_ERR PFX "failed to get clk\n");
     ret=-ENOENT;
     goto err1;
  }
   clk_enable(spi_clk);

  /*get the mem region for the spi*/
  res=platform_get_resource(pdev, IORESOURCE_MEM,0);
  if(res==NULL){
    printk(KERN_ERR PFX "failed to get MEM region resource\n");
    ret=-EN0ENT;
    goto err2;
  }

  size=(res->end - res->start)+1;/*right?*/
  s3c2410_spi_mem=request_mem_region(res->start,size,pdev->name);
  if(s3c2410_spi_mem==NULL){
     printk(KERN_ERR PFX "failed to get men region\n");
     ret=-ENXI0;
     goto err3;
   }

  s3c2410_spi_base=ioremap(res->start,size);
   if(spi_base==NULL){
     printk(KERN_ERR PFX "failed to ioremap\n");
     ret=-ENXI0;
     goto err4;
   }

  s3c2410_spi_enable();
  ret=request_irq(IRQ_EINT1,s3c2410kbd_keyevent,SA_SAMPLE_RANDOM,pdev->name,NULL);

  if (ret != 0)
  {
	 printk(KERN_ERR PFX"faild\n");
	 goto err5;
  }
  set_irq_type(IRQ_EINT1, IRQT_FALLING);
  printk(PFX"irq=%d\n",IRQ_EINT1);
  printk("%s driver initialed\n", pdev->name);
  return 0;
  
  err5:
  err4:
  err3:
       iounmap(s3c2410_spi_base);
  err2:
       release_mem_region(res->start, size+1);
  err1:
	   printk(PFX "erro",ret);
	   return ret;
}


static int s3c2410kbd_remove(struct platform_device *pdev)
{
	struct resource *res = pdev->resource;
	disable_irq(IRQ_EINT1);
	free_irq(IRQ_EINT1,NULL);

	iounmap(s3c2410_spi_base);
	release_mem_region(res->start, (res->end - res->start) + 1);
	return 0;
}

static struct platform_driver s3c2410kbd_driver = {
.probe = s3c2410kbd_probe,
.remove = s3c2410kbd_remove,
.suspend = NULL,
.resume = NULL,
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-kbd",
}
};


static int __init s3c2410kbd_init(void)
{
return platform_driver_register(&s3c2410kbd_driver);
}

static void __exit s3c2410kbd_exit(void)
{
platform_driver_unregister(&s3c2410kbd_driver);
}

module_init(s3c2410kbd_init);
module_exit(s3c2410kbd_exit);

MODULE_DESCRIPTION("S3C2410 KBD Driver");
MODULE_AUTHOR("yuandaode&yianxi");
MODULE_LICENSE("Dual/GPL");

⌨️ 快捷键说明

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