📄 leon3ps2.c
字号:
/* * linux/drivers/input/serio/leon3ps2.c * * Copyright (C) 2000-2003 Deep Blue Solutions Ltd. * Copyright (C) 2002 Russell King. * Copyright (C) 2005 Gaisler Research, Marcus.hellquist@gmail.com * * 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 * (at your option) any later version. */ ///////////// modify by hawk tan 2060208 //////////#include <linux/module.h>#include <linux/init.h>#include <linux/serio.h>#include <linux/errno.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/device.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/err.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/leon.h>struct leon3ps2_port { struct serio *io; struct clk *clk; void *base; unsigned int irq; unsigned int open;};#define PORT(kmi) ((LEON3_APBPS2_REGS_Map*)(kmi->base))#define GET_STATUS(kmi) (LEON_BYPASS_LOAD_PA(&(PORT(kmi)->status)))#define GET_CTRL(kmi) (LEON_BYPASS_LOAD_PA(&(PORT(kmi)->ctrl)))#define GET_DATA(kmi) (LEON_BYPASS_LOAD_PA(&(PORT(kmi)->data)))#define SET_CTRL(kmi,v) (LEON_BYPASS_STORE_PA(&(PORT(kmi)->ctrl),v))#define SET_DATA(kmi,v) (LEON_BYPASS_STORE_PA(&(PORT(kmi)->data),v))//////////////////////////////////////////////* IDs returned by GSC_ID port register */#define GSC_ID_KEYBOARD 0x4 /* device ID values */#define GSC_ID_MOUSE 0x1#define BUFFER_SIZE 0x0f// author hawk/* * gscps2_write() - send a byte out through the aux interface. */// author hawk// author hawktanstruct ps2dataregister{ unsigned long reserve24 :24 ; unsigned long ps2data:8 ;};// author hawktanstruct ps2statusregister{ unsigned long rcnt :5 ; unsigned long tcnt :5 ; unsigned long reserver17:17; unsigned long ps2if :1 ; unsigned long ps2of :1; unsigned long ps2ki :1 ; unsigned long ps2fe :1 ; unsigned long ps2pe :1 ; unsigned long ps2dr :1;};// author hawktanstruct ps2ctrregister{ unsigned long reserve24 :24 ; unsigned long ps2ti :1; unsigned long ps2ri :1; unsigned long ps2te :1; unsigned long ps2re :1;};// author hawktanstruct ps2timeregister{ unsigned long reserve24 :24 ; unsigned long timedata:8 ;};struct ps2dataregister * keydataregister;struct ps2statusregister * keystatusregister ;struct ps2ctrregister * keyctrregister;struct ps2timeregister * keytimeregister;struct ps2dataregister * mousedataregister;struct ps2statusregister * mousestatusregister ;struct ps2ctrregister * mousectrregister;struct ps2timeregister * mousetimeregister;/////////////////////////////////////////////static irqreturn_t leon3ps2_int(int irq, void *dev_id, struct pt_regs *regs){ struct leon3ps2_port *kmi = dev_id; unsigned long status, ctrl, scan; int handled = IRQ_NONE; // HARDDBG_FUNC status = GET_STATUS(kmi); do { // printk(" GET_STATUS ===0x%08x======\n",status); scan = GET_DATA(kmi); ctrl = GET_CTRL(kmi); if ((status & LEON_REG_PS2_STATUS_DR) && (ctrl & LEON_REG_PS2_CTRL_RE)) { serio_interrupt(kmi->io, scan, 0, regs); } status = GET_STATUS(kmi); handled = IRQ_HANDLED; } while (status & LEON_REG_PS2_STATUS_DR); // printk("data = %08x \n", GET_DATA(kmi)); return handled;}// author hawktanstatic int leon3ps2_write(struct serio *io, unsigned char val) { unsigned long flags; struct leon3ps2_port * kmi = io->port_data; spinlock_t lockq; // printk("%x \n",val); // printk(" leon3ps2_write ==enter into==========\n"); // HARDDBG_FUNC //HARDDBG_OUT("data: 0x%02x\n",val); SET_DATA(kmi,val); SET_CTRL(kmi,LEON_REG_PS2_CTRL_TE); /* printk("data = %08x \n", &(PORT(kmi)->data)); printk("status = %08x \n", &(PORT(kmi)->status)); printk("status val = %08x \n",GET_STATUS(kmi)); printk("ctrl = %08x \n", &(PORT(kmi)->ctrl)); printk("ctrl val= %08x \n",GET_CTRL(kmi)); printk("=======gscps2_write======================\n"); */ // mdelay(6); return 0;}static int leon3ps2_open(struct serio *io){ //printk("===========leon3ps2_open\n"); struct leon3ps2_port *kmi = io->port_data; int ret; // HARDDBG_FUNC // printk("===========irq=%d\n",kmi->irq); ret = request_irq(kmi->irq, leon3ps2_int, 0, "PS/2irq", kmi); if (ret) { printk(KERN_ERR "leon3ps2: failed to claim IRQ%d\n", kmi->irq); return ret; } SET_CTRL(kmi,LEON_REG_PS2_CTRL_RE); printk("data = %08x \n", &(PORT(kmi)->data)); return 0;}static void leon3ps2_close(struct serio *io){ struct leon3ps2_port *kmi = io->port_data; HARDDBG_FUNC SET_CTRL(kmi,0);}extern volatile LEON3_GpTimer_Regs_Map *LEON3_GpTimer_Regs;static int __init leon3ps2_probe() { // printk("leon3ps2_probe===========\n"); struct leon3ps2_port *kmi; struct serio *io; int ret = 0; int i, leon_ports_nr; unsigned long clk; HARDDBG_FUNC amba_apb_device dev[8]; clk = ((unsigned long)(((LEON3_BYPASS_LOAD_PA (&LEON3_GpTimer_Regs->scalar_reload)) + 1))); leon_ports_nr = amba_get_free_apbslv_devices(VENDOR_GAISLER, GAISLER_KBD, dev, 8); for (i = 0; i < leon_ports_nr; i++) { kmi = kmalloc(sizeof(struct leon3ps2_port), GFP_KERNEL); io = kmalloc(sizeof(struct serio), GFP_KERNEL); if (!kmi || !io) { ret = -ENOMEM; break; } memset(kmi, 0, sizeof(struct leon3ps2_port)); memset(io, 0, sizeof(struct serio)); // // io->idproduct = 0x0001; // io->idversion = 0x0010; // // io->write = leon3ps2_write ; // if( dev[i].irq == 0x4 ) io->open = leon3ps2_open; io->close = leon3ps2_close; strlcpy(io->name, "Leon PS/2 keyboard", sizeof(io->name)); strlcpy(io->phys, "Leon PS/2 keyboard", sizeof(io->phys)); io->port_data = kmi; kmi->io = io; kmi->base = (void *)dev[i].start; kmi->clk = clk; kmi->irq = dev[i].irq; io->write = leon3ps2_write; if(kmi->irq==GSC_ID_KEYBOARD) { // io->write=0 ; io->type=SERIO_LEON3PS2; } else { io->type = SERIO_PS_PSTHRU; } serio_register_port(kmi->io); // printk("-------data = %08x \n", &(PORT(kmi)->data)); // printk("Attaching grlib ps2 keyboard drivers (clk:%ihz) at 0x%08x, irq: %d ,dev[i].bus_id=0x%08x\n", // (int)clk, kmi->base, kmi->irq,dev[i].bus_id); // printk("leon3ps2_probe==out======\n"); #if 0 if(kmi->irq==GSC_ID_MOUSE) { mousedataregister=(struct ps2dataregister *)ioremap((unsigned long)(&(PORT(kmi)->data)),4); mousestatusregister= (struct ps2statusregister * )ioremap((unsigned long)(&(PORT(kmi)->status)),4); mousectrregister=(struct ps2ctrregister * )ioremap((unsigned long)(&(PORT(kmi)->ctrl)),4); //struct ps2timeregister * mousetimeregister(struct ps2timeregister * ); if(mousedataregister==NULL) { printk("mousedataregister==null \n"); } else { printk("=====mousedataregister init========= \n"); } // memset(mousedataregister,0x0,sizeof(struct ps2dataregister)); // memset(mousestatusregister,0x0,sizeof(struct ps2statusregister)); // memset(mousectrregister,0x0,sizeof(struct ps2dataregister)); } else if (kmi->irq==GSC_ID_KEYBOARD) { keydataregister=(struct ps2dataregister *)ioremap((unsigned long)(&(PORT(kmi)->data)),4); keystatusregister =(struct ps2statusregister * )ioremap((unsigned long)(&(PORT(kmi)->status)),4); keyctrregister=(struct ps2ctrregister *)ioremap((unsigned long)(&(PORT(kmi)->ctrl)),4); // struct ps2timeregister * keytimeregister=(struct ps2timeregister *)ioremap(&(PORT(kmi)->data),4);; if(mousedataregister==NULL) { printk("mousedataregister==null \n"); } else { printk("=====keydataregister init========= \n"); } // memset(keydataregister,0x0,sizeof(struct ps2dataregister)); // memset(keystatusregister,0x0,sizeof(struct ps2statusregister)); // memset(keyctrregister,0x0,sizeof(struct ps2ctrregister)); } #endif } return ret;}static int __init leon3ps2_init(void){ leon3ps2_probe();}static void __exit leon3ps2_exit(void){}module_init(leon3ps2_init);module_exit(leon3ps2_exit);MODULE_AUTHOR("Gaisler Research, Marcus.hellquist@gmail.com");MODULE_DESCRIPTION("grlib PS2 serial i/o");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -