📄 hpi.c
字号:
/*************************************************************************** HPI Drivers --------------------------------- begin : March 10th,2008 copyright : wangpingan email : wang8y8y@163.com QQ : 276708824 ***************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//* this program is a driver for S3c2410 and TMS50x,which is a interface driver connecting S3c2410 and TMS54X DSP with *HPI-8, *hardware connection showed as follows: * ARM S3c2410 DSP TMS5416 * PIN PIN * DATA[0-7] <------------------------------> HD[0-7] * ADDR[1] -------------------------------> HCNTL0 * ADDR[2] -------------------------------> HCNTL1 * ADDR[3] -------------------------------> HBIL * ADDR[4] -------------------------------> HR/W * EINT[19] <------------------------------- HINT * nCS3 -------------------------------> HCS * nEXT_OE -------------------------------> HDS1 * nEXT_WD -------------------------------> HDS2 * EXPRDY <------------------------------- HRDY * ************************************************************************ * SYSTEM ADDRESS MAPPING ************************************************************************ * HardWare Map *--------------------------------------------------------------------------------- * chip select size&width * nGCS0 0X0000.0000-0X0800.0000 128MB 16/32bits * nGCS1 0X0800.0000-0X1000.0000 128MB 8/16/32bits * nGCS2 0X1000.0000-0X1800.0000 128MB 8/16/32bits * nGCS3 0X1800.0000-0X2000.0000 128MB 8/16/32bits * nGCS4 0X2000.0000-0X2800.0000 128MB 8/16/32bits * nGCS5 0X2800.0000-0X3000.0000 128MB 8/16/32bits * nGCS6 0X3000.0000-0X3800.0000 2/4/8/16/32/64/128MB 8/16/32bits * nGCS7 0X3800.0000-0X4000.0000 2/4/8/16/32/64/128MB 8/16/32bits * 0x4000.0000-0x4000.0fff Reserved * 0x4800.0000-0x6000.0000 SFR * 0x6000.0000-0xffff.ffff Reserved ************************************************************************* * SoftWare Map *---------------------------------------------------------------------------------- * Address Usage * 0x0000.0000-0x0002.0000 Nboot * 0x0002.0000-0x000c.0000 Eboot * 0x000c.0000-0x0200.0000 wince Kernel * * 0x0200.0000-0x0203.0000 UBoot * 0x0203.0000-0x0220.0000 Linux Kernel * 0x0220.0000-0x0400.0000 Linux file system * ****************************************************************************************** * * * HPI Address Map * *--------------------------------------------------------------------------------------------------------------------------- * OFFSET USAGE * HR/W HBIL HCNTL1 HCNTL0 (ADDR[0-3]) (ADDR[1-4]) * 1 0 0 1 b 0X09 0X12 HPI Data Register First Byte Read (MODE :continuous read) * 0 0 0 1 b 0X01 0X02 HPI Data Register First Byte Write( MODE :continuous write) * 1 1 0 1 b 0X0d 0X1a HPI Data Register Second Byte Read (MODE :continuous read) * 0 1 0 1 b 0X05 0X0a HPI Data Register Second Byte Write (MODE :continuous write) * * * 1 0 0 0 b 0X08 0X10 HPI Control Register First Byte Read (MODE :continuous read) * 0 0 0 0 b 0X00 0X00 HPI Control Register First Byte Write (MODE :continuous write) * 1 1 0 0 b 0X0C 0X18 HPI Control Register Second Byte Read (MODE :continuous read) * 0 1 0 0 b 0X04 0X08 HPI Control Register Second Byte Write (MODE :continuous write) * * 0 0 1 0 b 0X02 0X04 HPI Address Register Fisrt Byte Write * 0 1 1 0 b 0X06 0X0c HPI Address Register Second Byte Write * ***************************************************************************************************** * frame protocol * ********************************************************************* * READ FRAME | WRITE FRAME *_____________________________________________________________________________ * HPI ADDRESS(offset) | FUNCTION | HPI ADDRESS(offset) |FUNCTION *------------------------------------------------------------------------------------------- * 0X0001 (low)value=0x55 indicate DSP ready | 0x0001 (low)value=0x55 indicate ARM ready * 0x0001 (high)value=0x55 indicate read frame | 0x0001 (high) value=0x55 indicate write frame * effective | effective * 0x0002 read frame length (16bit) | 0x0002 write frame length *------------------------------------------------------------------------------------------------- * 0X0003 (low)value=0x55 dsp read interrupt | 0x0003 (low)value=0x55 arm read interrupt * (high)value=0x55 dsp write interrupt | (high)value=0x55 arm write interrupt *------------------------------------------------------------------------------------------------- * 0x0004 | 0x0004 * | read frame data | | write frame data * 0x03FF | 0x03FF ***********************************************************************/#ifndef __KERNEL__ /* Kernel compile */#define __KERNEL__#endif#ifndef MODULE /* Module compile */#define MODULE#endif//Define HPI Register Address #define HPI_BASE 0x10000300 /* bank2 */ #define HPI_LENGTH 0x0FFF #define HPD_READ_LOW 0x000012 #define HPD_READ_HIGH 0x00001a #define HPD_WRITE_LOW 0x000002 #define HPD_WRITE_HIGH 0x00000a #define HPC_READ_LOW 0x000010 #define HPC_READ_HIGH 0x000018 #define HPC_WRITE_LOW 0x000000 #define HPC_WRITE_HIGH 0x000008 #define HPA_WRITE_LOW 0x000004 #define HPA_WRITE_HIGH 0x00000c //Define HPI major number (dynamic) #define HPI_MAJOR 0 //Irq number #define IRQ_NUM IRQ_EINT3 //read buffer base adderess #define HPI_READ_BASE_LOW 0x00 #define HPI_READ_BASE_HIGH 0x10 //write buffer base address #define HPI_WRITE_BASE_LOW 0x00 #define HPI_WRITE_BASE_HIGH 0x14 //*******I/O Configure and interrupt cofigure******* #define GPIO_BASE 0x56000050 #define rGPFCON 0x0000 #define rEXTINT0 0x0038 #define rEINTMASK 0x0054 #define INT_BASE 0x4A000000 #define rINTMOD 0x0004 #define rINTMSK 0x0008 //port lenghth #define IO_SIZE 0x100 //INT lenghth #define INT_SIZE 0x10 //Notes: include files must specify the linux source path rather than the system include path when you complile // please see the makefile#include <linux/module.h>#include <linux/config.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/delay.h> /* udelay */#include <linux/slab.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/interrupt.h>#include <linux/tqueue.h>#include <linux/poll.h>#include <asm/io.h>#include <asm/system.h>#include <linux/spinlock.h>#include <asm/irq.h> //***************************************************** //Global varialbe definition static u32 phys_address = 0x1000; static u32 io_base_address; static u32 int_base_address; static int major=0; static int read_event=0; static int write_event=0; static spinlock_t hpi_lock=SPIN_LOCK_UNLOCKED; static unsigned long flags; DECLARE_WAIT_QUEUE_HEAD(hpi_read_queue); DECLARE_WAIT_QUEUE_HEAD(hpi_write_queue); //**************************************************** //set io portG and interrupt registervoid io_port_configure(void) { u32 tmp_reg; //set GPFCON; tmp_reg=readl(rGPFCON+io_base_address); udelay(5); printk(KERN_INFO"Read GPFCON :0x%x\n",tmp_reg); writel((tmp_reg&0xffbf)|(1<<9),rGPFCON+io_base_address); udelay(5); tmp_reg=readl(rGPFCON+io_base_address); udelay(5); printk(KERN_INFO"Read Changed GPFCON :0x%x\n",tmp_reg); //set EXTINT0; tmp_reg=readl(rEXTINT0+io_base_address); printk(KERN_INFO"Read EXTINT0 :0x%x\n",tmp_reg); udelay(5); writel((tmp_reg&0xffff8fff),rEXTINT0+io_base_address); udelay(5); tmp_reg=readl(rEXTINT0+io_base_address); udelay(5); printk(KERN_INFO"Read Changed EXTINT0 :0x%x\n",tmp_reg); /* //set EINTMASK; tmp_reg=readl(rEINTMASK+io_base_address); printk(KERN_INFO"Read EINTMASK :0x%x\n",tmp_reg); udelay(5); writel(tmp_reg&0xf7ffff,rEINTMASK+io_base_address); udelay(5); tmp_reg=readl(rEINTMASK+io_base_address); udelay(5); printk(KERN_INFO"Read Changed EINTMASK :0x%x\n",tmp_reg); */ //set INTMOD; tmp_reg=readl(rINTMOD+int_base_address); printk(KERN_INFO"Read INTMOD :0x%x\n",tmp_reg); udelay(5); writel(tmp_reg&0xfffffff7,rINTMOD+int_base_address); udelay(5); tmp_reg=readl(rINTMOD+int_base_address); udelay(5); printk(KERN_INFO"Read Changed INTMOD :0x%x\n",tmp_reg); //set INTMSK; tmp_reg=readl(rINTMSK+int_base_address); printk(KERN_INFO"Read INTMSK :0x%x\n",tmp_reg); udelay(5); writel(tmp_reg&0xfffffff7,rINTMSK+int_base_address); udelay(5); tmp_reg=readl(rINTMSK+int_base_address); udelay(5); printk(KERN_INFO"Read Changed INTMSK :0x%x\n",tmp_reg); } void set_arm_ready(void) { //set ARM ready writeb(0x00+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); udelay(5); writeb(0x55,HPD_WRITE_LOW+phys_address); } void set_arm_not_ready(void) { //set ARM not ready writeb(0x00+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); udelay(5); writeb(0x00,HPD_WRITE_LOW+phys_address); } void frame_init(void) { //set write frame writeb(0x00+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); udelay(5); //set arm ready writeb(0x55,HPD_WRITE_LOW+phys_address); //set write frame inactive udelay(5); writeb(0x00,HPD_WRITE_HIGH+phys_address); udelay(5); //set write frame length writeb(0x00,HPD_WRITE_LOW+phys_address); udelay(5); writeb(0x00,HPD_WRITE_HIGH+phys_address); udelay(5); //set read & write interrupt flag 0 writeb(0x00,HPD_WRITE_LOW+phys_address); udelay(5); writeb(0x00,HPD_WRITE_HIGH+phys_address); } //open file int hpi_open(struct inode *inode,struct file *file) { MOD_INC_USE_COUNT; //set hpi control register as address auto increase //clear dsp interrupt spin_lock_irqsave(&hpi_lock,flags); writeb(0x09,HPC_WRITE_LOW+phys_address); udelay(5); writeb(0x09,HPC_WRITE_HIGH+phys_address); udelay(5); frame_init(); spin_unlock_irqrestore(&hpi_lock,flags); return 0; /* success */ } //close file int hpi_release(struct inode *inode,struct file *file) { //set ARM NOT ready writeb(0x00+HPI_WRITE_BASE_LOW,HPA_WRITE_LOW+phys_address); udelay(5); writeb(0x00+HPI_WRITE_BASE_HIGH,HPA_WRITE_HIGH+phys_address); udelay(5); writeb(0x00,HPD_WRITE_LOW+phys_address); MOD_DEC_USE_COUNT; return 0; /* success */ } // hpi read ssize_t hpi_read(struct file *file, char *buffer, size_t count, loff_t *pos) { unsigned char *kbuf ; unsigned char dsp_ready=0; unsigned char frame_active=0; u16 frame_length=0; unsigned char tempt; int i; // printk(KERN_INFO"READ :%d \n",count); spin_lock_irqsave(&hpi_lock,flags); writeb(0x01+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); dsp_ready=readb(HPD_READ_LOW+phys_address); // udelay(5); frame_active=readb(HPD_READ_HIGH+phys_address); spin_unlock_irqrestore(&hpi_lock,flags); // printk(KERN_INFO"dsp_ready:0x%x frame_active:0x%x\n",dsp_ready,frame_active); if(dsp_ready!=0x55) { //DSP NOT READY printk( "\nHPI:DSP not ready\n"); return -EINVAL; /* Invalid argument */ } if(frame_active!=0x55) { //FRAME inactive if(file->f_flags&O_NONBLOCK) return 0; /* success */ read_event=1; while(frame_active!=0x55) { interruptible_sleep_on(&hpi_read_queue); if(signal_pending(current)) return -ERESTARTSYS; spin_lock_irqsave(&hpi_lock,flags); writeb(0x01+HPI_READ_BASE_LOW,HPA_WRITE_LOW+phys_address); // udelay(5); writeb(HPI_READ_BASE_HIGH,HPA_WRITE_HIGH+phys_address); // udelay(5); dsp_ready=readb(HPD_READ_LOW+phys_address); // udelay(5); rmb(); frame_active=readb(HPD_READ_HIGH+phys_address); spin_unlock_irqrestore(&hpi_lock,flags); } } //READ FRAME LENGTH tempt=readb(HPD_READ_LOW+phys_address); // udelay(5);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -