📄 s3c2410-kbd.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 + -