📄 w90n745_ebi2.c
字号:
/****************************************************************************
* *
* Copyright (c) 2006 - 2007 Gtm Electronics Corp. All rights reserved. *
* *
***************************************************************************/
/****************************************************************************
*
* FILENAME
* w90n745_ebi2.c
*
* VERSION
* 1.0
*
* DESCRIPTION
* This file is the driver of ebi 2 Module driver
* 8-16 Bit Bus Control
* DATA STRUCTURES
* NONE
*
* FUNCTIONS
* static int ebi2ledc_init(void);
* static int ebi2ledc_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);
* static int ebi2ledc_open(struct inode *inode,struct file *filp); * static int ebi2ledc_close(struct inode *inode,struct file *filp);
* static int ebi2ledc_write(struct file *filp, const char *buff, size_t count, loff_t *f_pos);
* static int ebi2ledc_read(struct file *flip,char * buff,size_t count, loff_t * f_pos);
*
* HISTORY
* 2007/12/12 Ver 1.0 Created by gtm ymy
* 2007/12/24 Modified ymy * REMARK
* None
**************************************************************************/
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/hardware.h>
#include <asm/errno.h>#include <asm/uaccess.h>
#include <asm/delay.h>
#include <gpio/gpio_interface.h>
#include "w90n745_ebi2.h"
#define EBI2_MEM_SIZE 2//buffsize
#define ebi2drv_major 232
#define DEVICE_NAME "led" /*name */
#define BIT_FF(x) ((x)&0xff)
//Modified 2007/12/20
//file operation
static struct file_operations ebi2ledc_fops =
{ owner: THIS_MODULE,
open: ebi2ledc_open,
//close: ebi2ledc_close,
write: ebi2ledc_write, read: ebi2ledc_read,
ioctl: ebi2ledc_ioctl,
release: ebi2ledc_close,
};
/****************************************************************************************
*
* FUNCTION
*
* WB_SetExternalIO
*
* DESCRIPTION
*
* To set base address, address size , and bus width for external I/O device.
*
* INPUTS
* extNo External I/O bank number.
* extBaseAddr External I/O bank base address.
* extSize External I/O size.
* extBusWidth External I/O bus width.
*
* OUTPUTS
* none
*
*****************************************************************************************/
static void GTM_SetExternalIO(int extNo, unsigned int extBaseAddr, unsigned int extSize, int extBusWidth)
{
unsigned int reg;
switch (extNo)
{
case EXT0:
reg = DWORD_READ(EXT0CON);
// Set Bus width
switch (extBusWidth)
{
case BUS_BIT_8:
reg = (reg & 0xfffffffc) | 0x01;
break;
case BUS_BIT_16:
reg = (reg & 0xfffffffc) | 0x02;
break;
case BUS_BIT_32:
reg = (reg & 0xfffffffc) | 0x03;
break;
case BUS_DISABLE:
reg = reg & 0xfffffffc;
break;
}
// Set size
switch (extSize)
{
case SIZE_256K:
reg = reg & 0xfff8ffff;
break;
case SIZE_512K:
reg = (reg & 0xfff8ffff)|0x00010000;
break;
case SIZE_1M:
reg = (reg & 0xfff8ffff)|0x00020000;
break;
case SIZE_2M:
reg = (reg & 0xfff8ffff)|0x00030000;
break;
case SIZE_4M:
reg = (reg & 0xfff8ffff)|0x00040000;
break;
case SIZE_8M:
reg = (reg & 0xfff8ffff)|0x00050000;
break;
case SIZE_16M:
reg = (reg & 0xfff8ffff)|0x00060000;
break;
case SIZE_32M:
reg = (reg & 0xfff8ffff)|0x00070000;
break;
}
// Set Base address
extBaseAddr = (extBaseAddr << 1) & 0xfff80000;
reg = reg | extBaseAddr;
// set the reg value into register
reg = reg |0x7870; // CYH tACC
DWORD_WRITE(EXT0CON, reg);
break;
case EXT1:
reg = DWORD_READ(EXT1CON);
// Set Bus width
switch (extBusWidth)
{
case BUS_BIT_8:
reg = (reg & 0xfffffffc) | 0x01;
break;
case BUS_BIT_16:
reg = (reg & 0xfffffffc) | 0x02;
break;
case BUS_BIT_32:
reg = (reg & 0xfffffffc) | 0x03;
break;
case BUS_DISABLE:
reg = reg & 0xfffffffc;
break;
}
// Set size
switch (extSize)
{
case SIZE_256K:
reg = reg & 0xfff8ffff;
break;
case SIZE_512K:
reg = (reg & 0xfff8ffff)|0x00010000;
break;
case SIZE_1M:
reg = (reg & 0xfff8ffff)|0x00020000;
break;
case SIZE_2M:
reg = (reg & 0xfff8ffff)|0x00030000;
break;
case SIZE_4M:
reg = (reg & 0xfff8ffff)|0x00040000;
break;
case SIZE_8M:
reg = (reg & 0xfff8ffff)|0x00050000;
break;
case SIZE_16M:
reg = (reg & 0xfff8ffff)|0x00060000;
break;
case SIZE_32M:
reg = (reg & 0xfff8ffff)|0x00070000;
break;
}
// Set Base address
extBaseAddr = (extBaseAddr << 1) & 0xfff80000;
reg = reg | extBaseAddr;
// set the reg value into register
DWORD_WRITE(EXT1CON, reg);
break;
case EXT2:
reg = DWORD_READ(EXT2CON);
// Set Bus width
switch (extBusWidth)
{
case BUS_BIT_8:
reg = (reg & 0xfffffffc) | 0x01;
break;
case BUS_BIT_16:
reg = (reg & 0xfffffffc) | 0x02;
break;
case BUS_BIT_32:
reg = (reg & 0xfffffffc) | 0x03;
break;
case BUS_DISABLE:
reg = reg & 0xfffffffc;
break;
}
// Set size
switch (extSize)
{
case SIZE_256K:
reg = reg & 0xfff8ffff;
break;
case SIZE_512K:
reg = (reg & 0xfff8ffff)|0x00010000;
break;
case SIZE_1M:
reg = (reg & 0xfff8ffff)|0x00020000;
break;
case SIZE_2M:
reg = (reg & 0xfff8ffff)|0x00030000;
break;
case SIZE_4M:
reg = (reg & 0xfff8ffff)|0x00040000;
break;
case SIZE_8M:
reg = (reg & 0xfff8ffff)|0x00050000;
break;
case SIZE_16M:
reg = (reg & 0xfff8ffff)|0x00060000;
break;
case SIZE_32M:
reg = (reg & 0xfff8ffff)|0x00070000;
break;
}
// Set Base address
extBaseAddr = (extBaseAddr << 1) & 0xfff80000;
reg = reg | extBaseAddr;
// set the reg value into register
DWORD_WRITE(EXT2CON, reg);
break;
case EXT3:
reg = DWORD_READ(EXT3CON);
// Set Bus width
switch (extBusWidth)
{
case BUS_BIT_8:
reg = (reg & 0xfffffffc) | 0x01;
break;
case BUS_BIT_16:
reg = (reg & 0xfffffffc) | 0x02;
break;
case BUS_BIT_32:
reg = (reg & 0xfffffffc) | 0x03;
break;
case BUS_DISABLE:
reg = reg & 0xfffffffc;
break;
}
// Set size
switch (extSize)
{
case SIZE_256K:
reg = reg & 0xfff8ffff;
break;
case SIZE_512K:
reg = (reg & 0xfff8ffff)|0x00010000;
break;
case SIZE_1M:
reg = (reg & 0xfff8ffff)|0x00020000;
break;
case SIZE_2M:
reg = (reg & 0xfff8ffff)|0x00030000;
break;
case SIZE_4M:
reg = (reg & 0xfff8ffff)|0x00040000;
break;
case SIZE_8M:
reg = (reg & 0xfff8ffff)|0x00050000;
break;
case SIZE_16M:
reg = (reg & 0xfff8ffff)|0x00060000;
break;
case SIZE_32M:
reg = (reg & 0xfff8ffff)|0x00070000;
break;
}
// Set Base address
extBaseAddr = (extBaseAddr << 1) & 0xfff80000;
reg = reg | extBaseAddr;
// set the reg value into register
DWORD_WRITE(EXT3CON, reg);
break;
default:
;
}
} /* end WB_SetExternalIO */
/****************************************************************************************
*
* FUNCTION
*
* WB_SetExternalIOTiming1
*
* DESCRIPTION
*
* To set access cycles & address set-up before nECS for the specified External I/O bank.
*
* INPUTS
* extNo External I/O bank number.
* tACC Access cycle for the specified External I/O bank.
* tACS Address set-up before nECS for the specified External I/O bank.
*
* OUTPUTS
* none
*
*****************************************************************************************/
void GTM_SetExternalIOTiming1(int extNo, int a, int b)
{
UINT32 reg;
switch (extNo)
{
case EXT0:
reg = DWORD_READ(EXT0CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xffff78ff) | (a << 11);
else if ((a > 0x8) && (a <= 0x17))
reg = (reg & 0xffff78ff) | (((a - 0x8)/2 + 0x8) << 11);
else
reg = (reg & 0xffff78ff);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffff1f) | (b << 5);
DWORD_WRITE(EXT0CON, reg);
break;
case EXT1:
reg = DWORD_READ(EXT1CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xffff78ff) | (a << 11);
else if ((a > 0x8) && (a <= 0x17))
reg = (reg & 0xffff78ff) | (((a - 0x8)/2 + 0x8) << 11);
else
reg = (reg & 0xffff78ff);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffff1f) | (b << 5);
DWORD_WRITE(EXT1CON, reg);
break;
case EXT2:
reg = DWORD_READ(EXT2CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xffff78ff) | (a << 11);
else if ((a > 0x8) && (a <= 0x17))
reg = (reg & 0xffff78ff) | (((a - 0x8)/2 + 0x8) << 11);
else
reg = (reg & 0xffff78ff);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffff1f) | (b << 5);
DWORD_WRITE(EXT2CON, reg);
break;
case EXT3:
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xffff78ff) | (a << 11);
else if ((a > 0x8) && (a <= 0x17))
reg = (reg & 0xffff78ff) | (((a - 0x8)/2 + 0x8) << 11);
else
reg = (reg & 0xffff78ff);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffff1f) | (b << 5);
reg = DWORD_READ(EXT3CON);
DWORD_WRITE(EXT3CON, reg);
break;
}
} /* end WB_SetExternalIOTiming1 */
/****************************************************************************************
*
* FUNCTION
*
* WB_SetExternalIOTiming2
*
* DESCRIPTION
*
* To set chip select hold-on time & chip select set-up time for the specified External I/O bank.
*
* INPUTS
* extNo External I/O bank number.
* tCOH Chip select hold-on time on nOE or nWBE for the specified External I/O bank.
* tCOS Chip select set-up time on nOE or nWBE for the specified External I/O bank.
*
* OUTPUTS
* none
*
*****************************************************************************************/
void GTM_SetExternalIOTiming2(int extNo, int a, int b)
{
unsigned int reg;
switch (extNo)
{
case EXT0:
reg = DWORD_READ(EXT0CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xfffff8ff) | (a << 8);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffffe3) | (b << 2);
DWORD_WRITE(EXT0CON, reg);
break;
case EXT1:
reg = DWORD_READ(EXT1CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xfffff8ff) | (a << 8);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffffe3) | (b << 2);
DWORD_WRITE(EXT1CON, reg);
break;
case EXT2:
reg = DWORD_READ(EXT2CON);
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xfffff8ff) | (a << 8);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffffe3) | (b << 2);
DWORD_WRITE(EXT2CON, reg);
break;
case EXT3:
if ((a >= 0) && (a <= 0x7))
reg = (reg & 0xfffff8ff) | (a << 8);
if ((b >= 0) && (b <= 0x7))
reg = (reg & 0xffffffe3) | (b << 2);
reg = DWORD_READ(EXT3CON);
DWORD_WRITE(EXT3CON, reg);
break;
}
} /* end WB_SetExternalIOTiming2 */
//setup ebi
void ebi_Init(void)
{ /*for bank2 0x74000000->LED Use it*/
int t_ACC =23, t_ACS = 0;
int t_COH = 0, t_COS = 0;
GTM_SetExternalIO(2, EXT2_BASS, SIZE_256K, BUS_BIT_8);
GTM_SetExternalIOTiming1(2, t_ACC, t_ACS);
GTM_SetExternalIOTiming2(2, t_COH, t_COS);
}
//NULL
static int ebi2ledc_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)
{
unsigned char* buffer = NULL;
//memset(buffer, 0, EBI2_MEM_SIZE);
printk("CMD=%d\n",cmd);//test
switch (cmd)
{
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
default:
//printk("default\n");
return -EINVAL;
}
return 0;
}
//read data from ebi2
static int ebi2ledc_read(struct file *flip,char * buff,size_t count, loff_t *f_pos)
{
unsigned char* buffer = NULL;
int total_count=0;
total_count=count; // memset(buffer, 0, EBI2_MEM_SIZE);
buffer[0] = BYTE_READ(LED_BASE_ADDR); //buffer[0] =98;
copy_to_user(buff, buffer, total_count);
return total_count;
}
//write
static int ebi2ledc_write(struct file *filp, const char *buff, size_t count, loff_t *f_pos)
{
unsigned char *buffer = NULL;
unsigned long wr_count = 0, total_wr_count = 0;
total_wr_count=count;
//memset(buffer, 0, EBI2_MEM_SIZE);
if (total_wr_count > EBI2_MEM_SIZE)
{
return -EFAULT;
}
//if(buff==NULL)
//return -EFAULT;
if (copy_from_user(buffer, buff, count))
{
printk("copy_from_user failed!\n");
return -EFAULT;
}
BYTE_WRITE(LED_BASE_ADDR,*buffer);
/*test No123*/ //printk("buff=%x",*buff); //printk("buffer[0]=%d\n",*buffer);
return total_wr_count;
}
//open fd
static int ebi2ledc_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
ebi_Init();
//printk("ebi2 open !\n");
return 0;
}
//close fd
static int ebi2ledc_close(struct inode *inode,struct file *filp)
{
//printk("ebi2 close !\n");
MOD_DEC_USE_COUNT;
return 0;
}
//init register device
static int __init ebi2ledc_init(void)
{
int error;
error = register_chrdev(ebi2drv_major, DEVICE_NAME,&ebi2ledc_fops);
if (error)
{ unregister_chrdev(ebi2drv_major, DEVICE_NAME);
printk("Register ebi2 device error!\n");
return error;
} else
printk("EBI2 for LED has been registered!\n");
return 0;
}
static __exit void ebi2ledc_cleanup(void)
{
unregister_chrdev(ebi2drv_major, DEVICE_NAME);
printk("unregister device succeed!\n");
printk("88!\n");
// return ;
}
module_init(ebi2ledc_init);
module_exit(ebi2ledc_cleanup);
//end!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -