?? ppc_dpram.c
字號:
/* * drivers/char/ppc_dpram.c * Demo driver for DPRAM of PowerPC 405EP PKU. * * Copyright (C) 2006 LingFang Micro System. * * add IRQ support * Tomxue <gbe.tao.xue@gmail.com> 2006.11.15 ZhanChunYuan BeiJing * Tom Xue <gbe.tao.xue@gmail.com> 2006.10.10 BeiJing * Tom Xue <fpslic@sina.com> 2006.05.10 BeiJing * Tom Xue <fpslic@sina.com> 2006.03.13 BeiJing * Tom Xue <fpslic@sina.com> 2003.12.13 Geneve * * 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. See * the file "COPYING" in the main directory of this archive * for more details. * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/slab.h>#include <platforms/ibm405ep.h>#include <linux/list.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include <asm/delay.h>#define DPRAM_IRQ_1 29 //EIRQ4 of PPC405EP#define DPRAM_IRQ_2 30 //EIRQ5 of PPC405EP#define DPRAM_PHY_ADDRESS 0xF0100000#define COMMAND_CHANGE_PID 0xAA#define DPRAM_SIGNAL_1 46#define DPRAM_SIGNAL_2 47static int app_pid;static struct task_struct *ptask; static unsigned long dpram_virtual_address;static int ppc_dpram_open(struct inode *, struct file *);static int ppc_dpram_close(struct inode *, struct file *);static ssize_t ppc_dpram_read(struct file *, char *, size_t, loff_t *);static ssize_t ppc_dpram_write(struct file *, const char *, size_t, loff_t *);static int ppc_dpram_ioctl(struct inode *, struct file *, unsigned int, unsigned long);static void ppc_dpram_interrupt(int irq, void *dev_id, struct pt_regs *regs);struct ppc_dpram_dev_struct { int opened; char *name; void *private;} ppc_dpram_dev;ppc_dpram_dev_minor = 189; //Here are the same number in the /dev/dpram nods./*************************************************************************** ** define driver struct. ** ***************************************************************************/static struct file_operations ppc_dpram_fops ={ open: ppc_dpram_open, release:ppc_dpram_close, read: ppc_dpram_read, write: ppc_dpram_write, ioctl: ppc_dpram_ioctl,};static struct miscdevice ppc_dpram_miscdev = { minor: 189, name: "dpram", fops: &ppc_dpram_fops,};/*************************************************************************** ** driver open process. ** ***************************************************************************/static int ppc_dpram_open(struct inode *inode, struct file *filp){ unsigned long i; if (ppc_dpram_dev.opened) { printk(KERN_INFO "DPRAM driver: the device is busy\n"); return -EBUSY; } //You can add some printk information here. //printk("This is the ppc_dpram driver.\n"); MOD_INC_USE_COUNT; ppc_dpram_dev.opened = 1; return 0;}/*************************************************************************** ** driver close process. ** ***************************************************************************/static int ppc_dpram_close(struct inode *inode, struct file *filp){ MOD_DEC_USE_COUNT; ppc_dpram_dev.opened = 0; return 0;}/*************************************************************************** ** Read PORTA status. ** ***************************************************************************/static ssize_t ppc_dpram_read(struct file *filp, char *buf, size_t count, loff_t *ppos){ unsigned long offset; unsigned long i; offset = *ppos; //printk("read offset is %08X.\n", offset);//debug count = count >> 1; //printk("count is %08X 16bit word.\n",count); for(i=0;i<count;i++) { *((unsigned short *)(buf + 2*i)) = *((volatile unsigned short *)(dpram_virtual_address + offset + 2*i)); } return 0xAA; }/*************************************************************************** ** Write data to PORTA. ** ***************************************************************************/static ssize_t ppc_dpram_write(struct file *filp, const char *buf, size_t count, loff_t *ppos){ unsigned long offset; unsigned long i; offset = *ppos; //printk("write offset is %08X.\n", offset);//debug count = count >> 1; //printk("count is %08X 16bit word.\n",count); for(i=0;i<count;i++) { *((volatile unsigned short *)(dpram_virtual_address + offset + 2*i)) = *((unsigned short *)(buf + 2*i)); } return 0xAA; }/*************************************************************************** ** ioctl function. ** ***************************************************************************/#define PPC_DPRAM_BIT_1 0x01000000#define PPC_DPRAM_BIT_2 0x00800000static int ppc_dpram_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ unsigned long i; switch (cmd) { case 0: /* set the led on, output 0 on GPIO7 */ i = in_be32((volatile unsigned*)GPIO0_OR);//*(volatile unsigned long *)(0xef60071c);//read the GPIO0_OR register i = i &(~PPC_DPRAM_BIT_1); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register break; case 1: /* set the led off, output 1 on GPIO7 */ i = in_be32((volatile unsigned*)GPIO0_OR);//read the GPIO0_OR register i = i |(PPC_DPRAM_BIT_1); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register break; case 3: /* set the led on, output 0 on GPIO8 */ i = in_be32((volatile unsigned*)GPIO0_OR);//*(volatile unsigned long *)(0xef60071c);//read the GPIO0_OR register i = i &(~PPC_DPRAM_BIT_2); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register break; case 4: /* set the led off, output 1 on GPIO8 */ i = in_be32((volatile unsigned*)GPIO0_OR);//read the GPIO0_OR register i = i |(PPC_DPRAM_BIT_2); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register break; case COMMAND_CHANGE_PID: app_pid = arg; break; default: return -ENOIOCTLCMD; } return -EINVAL;}/*************************************************************************** ** interrupt process routine. ** ***************************************************************************/static void ppc_dpram_interrupt_1(int irq, void *dev_id, struct pt_regs *regs){ //printk("EIRQ 4 of PPC405EP\n");//for debug //send a signal to application, tell it that a eirq4 received. ptask = find_task_by_pid(app_pid); if (ptask != NULL) { send_sig(DPRAM_SIGNAL_1, ptask, 1);//send signal DPRAM_SIGNAL_1 to application by EIRQ4 }}static void ppc_dpram_interrupt_2(int irq, void *dev_id, struct pt_regs *regs){ //printk("EIRQ 5 of PPC405EP\n");//for debug //send a signal to application, tell it that a eirq4 received. ptask = find_task_by_pid(app_pid); if (ptask != NULL) { send_sig(DPRAM_SIGNAL_2, ptask, 1);//send signal DPRAM_SIGNAL_2 to application by EIRQ5 }}/*************************************************************************** ** Init routine ** ***************************************************************************/static int __init ppc_dpram_init(void){ int result; int i; unsigned long value=0; printk(KERN_INFO "DPRAM driver launched. By Tom Xue 2006.10.10 <gbe.tao.xue@gmail.com>.\n"); result = misc_register(&ppc_dpram_miscdev); //get the virtual address dpram_virtual_address = ioremap(DPRAM_PHY_ADDRESS, 1024*1024); printk(KERN_INFO "DPRAM virtual address is 0x%08X .\n", dpram_virtual_address); //register the IRQ for DPRAM system result = request_irq(DPRAM_IRQ_1, ppc_dpram_interrupt_1, SA_INTERRUPT, "dpram_irq_1", NULL); if (0 != result) { printk(KERN_INFO "PPC DPRAM driver interrupt handler 1 install failed.\n"); } //for test,we only register one irq, the following one will be enable in real production test /* result = request_irq(DPRAM_IRQ_2, ppc_dpram_interrupt_2, SA_INTERRUPT, "dpram_irq_2", NULL); if (0 != result) { printk(KERN_INFO "PPC DPRAM driver interrupt handler 2 install failed.\n"); } */ //setup the default GPIO value to 1 /* output 1 on GPIO7 */ i = in_be32((volatile unsigned*)GPIO0_OR);//read the GPIO0_OR register i = i |(PPC_DPRAM_BIT_1); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register /* output 1 on GPIO7 */ i = in_be32((volatile unsigned*)GPIO0_OR);//read the GPIO0_OR register i = i |(PPC_DPRAM_BIT_2); out_be32((volatile unsigned*)GPIO0_OR, i);//send out to GPIO0_OR register return result;}/*************************************************************************** ** exit routine. ** ***************************************************************************/static void __exit ppc_dpram_exit(void){ misc_deregister(&ppc_dpram_miscdev); printk(KERN_INFO "DPRAM driver exit.\n");}MODULE_AUTHOR ("Tom Xue <gbe.tao.xue@gmail.com>");MODULE_DESCRIPTION ("DPRAM driver");MODULE_LICENSE("GPL");module_init(ppc_dpram_init);module_exit(ppc_dpram_exit);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -