自己写的DM6446中uart1驱动来实现485通信。在linux-2.6.18_pro500中uart驱动在8250.c中。这里贴出自己的实现的驱动。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include<linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include<linux/mtd/partitions.h>
#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
#include <linux/mtd/physmap.h>
#endif
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <asm/setup.h>
#include <asm/io.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/flash.h>
#include <asm/arch/common.h>
#include <asm/arch/gpio.h>
#include <asm/arch/mux.h>
#include <asm/arch/clock.h>
#include <asm/arch/nand.h>
#include <asm/arch/mmc.h>
#include <asm/arch/edma.h>
#include <asm/arch/i2c-client.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/sysrq.h>
#include <linux/delay.h>
#include<linux/platform_device.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_reg.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_8250.h>
#include <linux/nmi.h>
#include <linux/mutex.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/videodev.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#define davinci_readb(a) (*(volatile unsignedchar *)IO_ADDRESS(a))
#define davinci_readw(a) (*(volatile unsignedshort *)IO_ADDRESS(a))
#define davinci_readl(a) (*(volatile unsignedint *)IO_ADDRESS(a))
#define davinci_writeb(v,a) (*(volatileunsigned char *)IO_ADDRESS(a) = (v))
#define davinci_writew(v,a) (*(volatile unsignedshort *)IO_ADDRESS(a) = (v))
#define davinci_writel(v,a) (*(volatile unsignedint *)IO_ADDRESS(a) = (v))
#undef DEV_485_BUG
#define DEV_485_BUG
#ifdef DEV_485_BUG
#define debug_print3(fmt, args...) printk( "dev_485: " fmt, ##args)
#else
#define debug_print3(x...)
#endif
static int Opened=0;
static int Major=0;
#define DRIVER_NAME "max485"
struct max485_chip_info {
struct cdevcdev;
struct mutexupdate_lock;
};
struct class *max485_class;
//static unsigned int kuart1_base;
//static unsigned int kpsc_epcpr;
//static unsigned int kpsc_ptcmd;
//static unsigned int kpsc_ptstat;
//static unsigned int kpsc_pdstat;
//static unsigned int kpsc_pdctl;
//static unsigned int kpsc_mdctl_uart1;
//static unsigned int kgpio_base;
//static unsigned int kpinmux_base;
//static unsigned int kpsc_mdstat_uart1;
//static unsigned int kpsc_mdctl_gpio;
//static unsigned int kpsc_mdstat_gpio;
#define UART1_BASE_ (0x01c00000 +0x20400)//
#define PSC_EPCPR (0x01C40000 +0x1070)
#define PSC_PTCMD (0x01C40000 +0x1120)
#define PSC_PTSTAT (0x01C40000 +0x1128)
#define PSC_PDSTAT (0x01C40000 +0x1200)
#define PSC_PDCTL (0x01C40000 +0x1300)
#define PSC_MDCTL_UART1 (0x01C40000 +0x1200)
#define GPIO_BASE (0x01C67000)
#define PINMUX_BASE (0x01C40000)
#define PSC_MDSTAT_UART1 (0x01C41850)
#define PSC_MDCTL_GPIO (0x01C41A68)
#define PSC_MDSTAT_GPIO (0x01C41868)
#define kuart1_base UART1_BASE_
#define kpsc_epcpr PSC_EPCPR
#define kpsc_ptcmd PSC_PTCMD
#define kpsc_ptstat PSC_PTSTAT
#define kpsc_pdstat PSC_PDSTAT
#define kpsc_pdctl PSC_PDCTL
#define kpsc_mdctl_uart1 PSC_MDCTL_UART1
#define kpsc_mdstat_uart1 PSC_MDSTAT_UART1
#define kpsc_mdctl_gpio PSC_MDCTL_GPIO
#define kpsc_mdstat_gpio PSC_MDSTAT_GPIO
#define kpinmux_base PINMUX_BASE
//static inline void
static void
serial_out(unsigned int value, unsigned int reg)
{
davinci_writel(value, reg );
}
//static inline unsigned int
static unsigned int
serial_in(unsigned int reg)
{
unsigned int value;
value = davinci_readl(reg);
return value;
}
unsigned int serial_in_pwr (unsigned int offset)
{
// FIXME read procedure to set
return davinci_readl(offset);
}
unsigned int serial_out_pwr (unsigned int value, unsigned intoffset)
{
return davinci_writel(value, offset);
}
#if 0
void phy_to_kern (void)
{
kuart1_base =(unsigned int)(ioremap(UART1_BASE_ , 0x22)); //34bytes
kpsc_epcpr =(unsigned int)(ioremap(PSC_EPCPR , 0x04));//new
kpsc_ptcmd =(unsigned int)(ioremap(PSC_PTCMD , 0x04));
kpsc_ptstat =(unsigned int)(ioremap(PSC_PTSTAT , 0x04));
kpsc_pdstat =(unsigned int)(ioremap(PSC_PDSTAT , 0x04));//new
kpsc_pdctl =(unsigned int)(ioremap(PSC_PDCTL , 0x04));//new
kpsc_mdctl_uart1 = (unsignedint)(ioremap(PSC_MDCTL_UART1, 0x04));
kgpio_base =(unsigned int)(ioremap(GPIO_BASE , 0x20)); //32bytes
kpinmux_base = (unsignedint)(ioremap(PINMUX_BASE , 0x08)); //8bytes
kpsc_mdstat_uart1 = (unsignedint)(ioremap(PSC_MDSTAT_UART1, 0x04)); //for
kpsc_mdctl_gpio = (unsignedint)(ioremap(PSC_MDCTL_GPIO , 0x04)); //forgpio
kpsc_mdstat_gpio = (unsignedint)(ioremap(PSC_MDSTAT_GPIO , 0x04)); //for gpio
debug_print3("kuart1_base 0x%x\n",kuart1_base );
debug_print3("kpsc_ptcmd 0x%x\n",kpsc_ptcmd );
debug_print3("kpsc_ptsta 0x%x\n",kpsc_ptstat );
debug_print3("kpsc_mdctl_uart1 0x%x\n",kpsc_mdctl_uart1);
debug_print3("kgpio_base 0x%x\n",kgpio_base );
debug_print3("kpinmux_base 0x%x\n",kpinmux_base );
debug_print3("kpsc_mdctl_gpio 0x%x\n",kpsc_mdctl_gpio );
debug_print3("kpsc_epcpr 0x%x\n",kpsc_epcpr );
debug_print3("kpsc_pdstat 0x%x\n",kpsc_pdstat );
debug_print3("kpsc_pdctl 0x%x\n",kpsc_pdctl );
}
#endif
void poweron_uart1(void)
{
unsigned int reg_mdctl_uart1, reg_ptcmd,reg_ptstat;
unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
unsigned int reg_mdstat_uart1;
//reg_epcpr =serial_in(reg_epcpr ); //new
//reg_pdstat =serial_in(reg_pdstat); //new
//reg_pdctl =serial_in(reg_pdctl ); //new
//22Aug updated after finding that uartPWREMU_MGMT is still 0x3 and following values
//RS485: kpsc_epcpr 0xc4860070
//RS485: kpsc_pdstat 0xc4866200
//RS485: kpsc_pdctl 0xc4868300
//already there
reg_mdctl_uart1 =serial_in(kpsc_mdctl_uart1);
debug_print3("Before powering on reg_mdctl_uart1= 0x%x\n", reg_mdctl_uart1);
reg_mdctl_uart1 |=0x03; //Module Powerenabled
serial_out(reg_mdctl_uart1,kpsc_mdctl_uart1);
//22Aug
reg_pdstat = serial_in(kpsc_pdstat);
debug_print3("reg_pdstat in poweron_uart1()s =0x%x\n", reg_pdstat);
if (!(reg_pdstat & 0x01))
{
debug_print3("pdstat- off. Powering on...\n");
reg_pdctl =serial_in(kpsc_pdstat);
reg_pdctl |=0x01;
serial_out(reg_pdctl,kpsc_pdctl);
reg_ptcmd = serial_in(kpsc_ptcmd);
reg_ptcmd =0x01;
serial_out(reg_ptcmd,kpsc_ptcmd);
do
{
reg_epcpr =serial_in(kpsc_epcpr);
}
while (!((reg_epcpr & 0x01) == 0));
debug_print3("reg_epcpr done...\n");
reg_pdctl= serial_in(kpsc_pdctl);
reg_pdctl|= 0x100;
serial_out(reg_pdctl, kpsc_pdctl);
do
{
reg_ptstat =serial_in(kpsc_ptstat);
}
while (!((reg_ptstat & 0x01) == 0));
debug_print3("reg_ptstatdone...\n");
}
else
{
reg_ptcmd =serial_in(kpsc_ptcmd);
reg_ptcmd =0x01;
serial_out(reg_ptcmd,kpsc_ptcmd);
do
{
reg_ptstat =serial_in(kpsc_ptstat);
}
while (!((reg_ptstat & 0x01) == 0));
debug_print3("reg_ptstatdone...\n");
}
do
{
reg_mdstat_uart1= serial_in(kpsc_mdstat_uart1);
}
while (! ((reg_mdstat_uart1& 0x1F) == 0x03));
debug_print3("reg_mdstat_uart1...\n");
//alreadythere
// reg_ptcmd = serial_in(kpsc_ptcmd);
// reg_ptcmd =0x01;
// serial_out(reg_ptcmd,kpsc_ptcmd);
// do
// {
// reg_ptstat =serial_in(kpsc_ptstat);
// }
// while (!((reg_ptstat & 0x01) ==0));
debug_print3("Powering ON theUART1 moduleDone........\n");
}
#if 0
static int enable_tranciver(DIR dir)
{
unsigned int reg_outdata01;
unsigned int one = 0x01;
if (dir == TX)
{
reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
debug_print3("TX:: OUT_DATA01= %x\n",reg_outdata01);
reg_outdata01|= (one<< TXRX_CTL_PIN);
serial_out(reg_outdata01,kgpio_base + OUT_DATA01);
reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
debug_print3("TX:: OUT_DATA01= %x\n",reg_outdata01);
}
else if (dir == RX)
{
reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
debug_print3("RX:: OUT_DATA01= %x\n",reg_outdata01);
reg_outdata01&= 0xFDFFFFFF;
//reg_outdata01&= ~(one<< TXRX_CTL_PIN);
debug_print3("RX:: regoutdata= %x\n",reg_outdata01);
serial_out(reg_outdata01,kgpio_base + OUT_DATA01);
reg_outdata01 =serial_in(kgpio_base + OUT_DATA01);
debug_print3("RX:: OUT_DATA01= %x\n",reg_outdata01);
}
else
{
debug_print3("ERROR: wrongdirection %d", dir);
return -1;
}
return 0;
}
#endif
static int poweron_gpio(void)
{
unsigned int reg_mdctl_gpio, reg_ptcmd,reg_ptstat;
unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
unsigned int reg_mdstat_gpio;
reg_mdctl_gpio =serial_in_pwr(kpsc_mdctl_gpio);
reg_mdctl_gpio =0x03; //Module Powerenabled
serial_out_pwr(reg_mdctl_gpio,kpsc_mdctl_gpio);
//22Aug
reg_pdstat = serial_in(kpsc_pdstat);
debug_print3("reg_pdstat in poweron_gpio()s =0x%x\n", reg_pdstat);
if (!(reg_pdstat & 0x01))
{
debug_print3("pdstat- off. Powering on...\n");
reg_pdctl =serial_in(kpsc_pdstat);
reg_pdctl |=0x01;
serial_out(reg_pdctl,kpsc_pdctl);
reg_ptcmd = serial_in(kpsc_ptcmd);
reg_ptcmd =0x01;
serial_out(reg_ptcmd,kpsc_ptcmd);
do
{
reg_epcpr =serial_in(kpsc_epcpr);
}
while (!((reg_epcpr & 0x01) == 0));
debug_print3("reg_epcpr done...\n");
reg_pdctl= serial_in(kpsc_pdctl);
reg_pdctl|= 0x100;
serial_out(reg_pdctl, kpsc_pdctl);
do
{
reg_ptstat =serial_in(kpsc_ptstat);
}
while (!((reg_ptstat & 0x01) == 0));
debug_print3("reg_ptstatdone...\n");
}
else
{
reg_ptcmd =serial_in(kpsc_ptcmd);
reg_ptcmd =0x01;
serial_out(reg_ptcmd,kpsc_ptcmd);
do
{
reg_ptstat =serial_in(kpsc_ptstat);
}
while (!((reg_ptstat & 0x01) == 0));
debug_print3("reg_ptstatdone...\n");
}
do
{
reg_mdstat_gpio= serial_in(kpsc_mdstat_gpio);
}
while (! ((reg_mdstat_gpio& 0x1F) == 0x03));
debug_print3("reg_mdstat_gpio...\n");
debug_print3("Powering ON the GPIO moduleDone........\n");
return 0;
}
#definePINMUX0 ( 0x00)
#define PINMUX1 ( 0x04)
void config_gpio (void)
{
unsigned int reg_pinmux0,reg_pinmux1;//reg_dir01, reg_outdata01;
debug_print3("Config GPIOEntered....\n");
reg_pinmux0 = serial_in(kpinmux_base +PINMUX0); //PINMUX 0
debug_print3("PINMUX0 =%x\n",reg_pinmux0);
reg_pinmux0 &=0xFFFCFFFF; //Disable ATA and HDIREN
serial_out(reg_pinmux0,kpinmux_base +PINMUX0);
reg_pinmux0 = serial_in(kpinmux_base +PINMUX0);
debug_print3("set PINMUX0 =%x\n",reg_pinmux0);
reg_pinmux1 = serial_in(kpinmux_base +PINMUX1);
debug_print3("PINMUX1 =%x\n",reg_pinmux1);// PINMUX 1
reg_pinmux1 |= 0x00000063; //Enable I2C, UART1 and UART0
serial_out(reg_pinmux1, kpinmux_base +PINMUX1);
reg_pinmux1 =serial_in(kpinmux_base + PINMUX1);
debug_print3("set PINMUX1 =%x\n",reg_pinmux1);// PINMUX 1
#if 0
reg_dir01 = serial_in(kgpio_base +DIR01);
debug_print2("DIR01 = %x\n",reg_dir01);
reg_dir01 &=0xF9FFFFFF;
serial_out(reg_dir01, kgpio_base + DIR01);
reg_dir01 = serial_in(kgpio_base +DIR01);
debug_print2("DIR01 = %x\n",reg_dir01);
reg_outdata01 = serial_in(kgpio_base +OUT_DATA01);
debug_print2("OUT_DATA01 =%x\n",reg_outdata01);
reg_outdata01&= 0xFBFFFFFF;
reg_outdata01|= 0x02000000;
serial_out(reg_outdata01 ,kgpio_base +OUT_DATA01);
reg_outdata01 = serial_in(kgpio_base +OUT_DATA01);
debug_print2("OUT_DATA01 =%x\n",reg_outdata01);
debug_print1("Configuring GPIODone........\n");
#endif
}
void reset_dlab (void)
{
unsigned int reg_lcr;
//reg_lcr = 0x00;
//serial_out(reg_lcr, kuart1_base + LCR);
reg_lcr = serial_in(kuart1_base +0xc); // For R/W of IERregister
debug_print3("LCR = %x\n",reg_lcr);
reg_lcr &= 0x7F;
serial_out(reg_lcr, kuart1_base +0xc);
reg_lcr = serial_in(kuart1_base +0xc); // For R/W of IERregister
debug_print3("LCR = %x\n",reg_lcr);
}
void disable_interrupt (void)
{
unsigned int reg_IER;
reset_dlab();
reg_IER = 0x0;
serial_out(reg_IER , kuart1_base + 0x4);
}
void set_dlab (void)
{
unsigned int reg_lcr;
//reg_lcr = 0x80;
//serial_out(reg_lcr, kuart1_base + LCR);
reg_lcr = serial_in(kuart1_base +0xc); // For R/W of DLL...registers
debug_print3("LCR = %x\n",reg_lcr);
reg_lcr |=(1<<7);
serial_out(reg_lcr, kuart1_base + 0xc);
reg_lcr = serial_in(kuart1_base +0xc); // For R/W of DLL...registers
debug_print3("LCR = %x\n",reg_lcr);
}
void set_baud_rate (void)
{
unsigned int reg_dll, reg_dlh;
set_dlab();
reg_dll =0x0F;
serial_out(reg_dll, kuart1_base + 0x20);
reg_dlh = 0x00;
serial_out(reg_dlh , kuart1_base +0x24);
}
void config_fifo(unsigned int enable)
{
//FCR (RO) and IIR (WO) share address : DLAB =x
unsigned int reg_fcr;
reg_fcr = serial_in(kuart1_base + 0x8);
if(enable)
reg_fcr |=0x00000001; // Enable FIFO
else
reg_fcr &=0xFFFFFFFE; // DisableFIFO
serial_out(reg_fcr, kuart1_base + 0x8);
}
void set_protocol(void)
{
unsigned int reg_lcr, reg_mcr;
//If loopback is enabled TX,RX data can beverified
#ifdef LOOPBACK
reg_mcr = 0x00000010;
serial_out(reg_mcr, kuart1_base + 0x10);
#else
reg_mcr = 0x00000000;
serial_out(reg_mcr, kuart1_base + 0x10);
#endif
reg_lcr =0x00000003; // No Parity, 1 stopbit, 8-bit data.
serial_out(reg_lcr, kuart1_base + 0xc);
}
void reset_uart1(void)
{
unsigned int reg_pwremu_mgmt;//, delay;
reg_pwremu_mgmt = 0x0001; //Reset
serial_out(reg_pwremu_mgmt, kuart1_base +0x30); //UTRST = 1 - tx is active
reg_pwremu_mgmt |=(1<<14 |1<<13 |1<<0); // Enable txand rx and FREE
serial_out(reg_pwremu_mgmt, kuart1_base +0x30); //UTRST = 1 - tx is active
}
void enable_interrupt(void)
{
unsigned int reg_IER;
reset_dlab();
reg_IER = 0x3;
serial_out(reg_IER , kuart1_base + 0x4);
debug_print3("Enabling InterruptDone...\n");
}
void check_reg(void)
{
unsigned intreg_mdctl_uart1,reg_ptstat,reg_mdctl_gpio,reg_ptcmd,reg_pinmux0,reg_pinmux1,reg_dir01,reg_outdata01,reg_dll;
unsigned int reg_dlh,reg_mcr,reg_lcr,reg_pwremu_mgmt,reg_mdstat_uart1,reg_mdstat_gpio,reg_lsr;//reg_fcr,
unsigned int reg_epcpr, reg_pdstat, reg_pdctl;
reg_mdctl_uart1 =serial_in(kpsc_mdctl_uart1);
reg_epcpr =serial_in(kpsc_epcpr ); //new
reg_pdstat =serial_in(kpsc_pdstat); //new
reg_pdctl =serial_in(kpsc_pdctl ); //new
reg_ptstat =serial_in(kpsc_ptstat);
reg_mdctl_gpio = serial_in_pwr(kpsc_mdctl_gpio);
reg_ptcmd =serial_in_pwr(kpsc_ptcmd);
reg_ptstat =serial_in_pwr(kpsc_ptstat);
reg_pinmux0 =serial_in(kpinmux_base +0); // PINMUX0
reg_pinmux1 =serial_in(kpinmux_base +0x04); //PINMUX 1
//reg_dir01 =serial_in(kgpio_base + 0x10);
//reg_outdata01 = serial_in(kgpio_base +0x14);
reg_mdstat_uart1 =serial_in(kpsc_mdstat_uart1);
reg_mdstat_gpio =serial_in(kpsc_mdstat_gpio);
//reg_fcr = serial_in(kuart1_base + FCR);
reg_mcr = serial_in(kuart1_base + 0x10);
reg_lcr = serial_in(kuart1_base + 0xc);
reg_pwremu_mgmt =serial_in(kuart1_base + 0x30);
//set_dlab();
reg_dll = serial_in(kuart1_base +0x20); // Low byte
reg_dlh = serial_in(kuart1_base +0x24); // High byte
reg_lsr = serial_in((volatile unsignedint)kuart1_base + 0x14);
debug_print3("reg_mdctl_uart1 =0x%x\n",reg_mdctl_uart1 );
debug_print3("reg_epcpr =0x%x\n",reg_epcpr );
debug_print3("reg_pdstat =0x%x\n",reg_pdstat );
debug_print3("reg_pdctl =0x%x\n",reg_pdctl );
debug_print3("reg_ptstat =0x%x\n",reg_ptstat );
debug_print3("reg_mdctl_gpio = 0x%x\n",reg_mdctl_gpio );
debug_print3("reg_ptcmd =0x%x\n",reg_ptcmd );
debug_print3("reg_pinmux0 =0x%x\n",reg_pinmux0 );
debug_print3("reg_pinmux1 =0x%x\n",reg_pinmux1 );
debug_print3("reg_dir01 = 0x%x\n",reg_dir01 );
debug_print3("reg_outdata01 = 0x%x\n",reg_outdata01 );
debug_print3("reg_dll = 0x%x\n", reg_dll);
debug_print3("reg_dlh = 0x%x\n", reg_dlh);
//debug_print1("reg_fcr = 0x%x\n",reg_fcr);
debug_print3("reg_mcr = 0x%x\n", reg_mcr);
debug_print3("reg_lcr = 0x%x\n", reg_lcr);
debug_print3(" reg_pwremu_mgmt =0x%x\n", reg_pwremu_mgmt);
debug_print3(" reg_mdstat_uart1= 0x%x\n", reg_mdstat_uart1);
debug_print3(" reg_mdstat_gpio =0x%x\n", reg_mdstat_gpio);
debug_print3(" LSR = 0x%x\n",reg_lsr);
}
static ssize_t device_read(struct file *fp, char *buffer, size_tlen, loff_t *offset)
{
unsigned int reg_lsr,reg_iir, reg_ier;
unsigned char byte = 0x42;//=*(int*)buffer;
unsigned int count = 0;
int retval;
//TODO: get no. of byte to be read from user dorelated stuffs.
reset_dlab();
#ifdef BOARD_DVPB
enable_tranciver(RX);
#endif
//do
//{
// reg_iir =serial_in(kuart1_base + IIR);
// //mdelay(1000);
//}
//while (((reg_iir & 0x0000000E)!= 0x04));
//while (((reg_iir & 0x0000000E)!= 0x02));
// Wait till the transmit FIFO isempty
do
{
// Read the Status Register tocheck if the Transmit FIFO isempty
reg_lsr = serial_in((volatileunsigned int)kuart1_base + 0x14);
//debug_print3("Kernellsr...0x%x\n",reg_lsr);
reg_lsr =reg_lsr & 0x01;
count++;
}
while((reg_lsr != 0x01) || (count< 10000));
reg_ier = serial_in(kuart1_base + 0x04);
reg_iir = serial_in(kuart1_base + 0x08);
debug_print3("IIR 0x%x, IER0x%x\n",reg_iir,reg_ier);
byte = serial_in(kuart1_base + 0);
debug_print3("KERNEL: byte read =%x\n\n\n",byte);
if ( ( retval = copy_to_user ( (void __user*)buffer,&byte, sizeof(char) ) ) == -1)
debug_print3("ERROR: incopy_to_user inside device_write\n" );
return 1;
}
static ssize_t device_write(struct file *file, const char __user*buff,size_t count, loff_t *offp)
{
unsigned char byte,reg_lsr ;//=*(int*)buffer;
unsigned int count1 = 0;
int retval;
reset_dlab();
#ifdef BOARD_DVPB
//enable_tranciver(TX);
#endif
if(( retval = copy_from_user (&byte, (void __user *) buff, count ) ) == -1)
debug_print3("ERROR: in copy_from_user insidedevice_write\n" );
//unsigned long copy_from_user(void *to,constvoid __user *from,unsigned long count);
debug_print3("anger To be sentbyte:%c\n",byte);
// Wait till the transmit FIFO isempty
do
{
// Read the Status Registerto check if the Transmit FIFO isempty
reg_lsr = serial_in((volatile unsignedint)kuart1_base + 0x14);
//debug_print3("Kernellsr...0x%x\n",reg_lsr);
reg_lsr = reg_lsr & 0x20;
count1++;
}
while(reg_lsr!=0x20);
debug_print3("Count afterlsr!=0x20...0x%x\n",count1);
serial_out(byte, kuart1_base + 0);
return 1;
}
static int device_open(struct inode *inod, struct file *fp)
{
printk("device_openentered...\n" );
// If devie is opened returnbusy status
// if (Opened)
// return-EBUSY;
//else
{
Opened=1;
// Remapping physical adress tokernel space
//phy_to_kern();
poweron_gpio();
poweron_uart1();
config_gpio();
disable_interrupt ();
set_baud_rate();
//in fops...
config_fifo(0);//DISABLE
set_protocol();
reset_uart1();
enable_interrupt();
check_reg();
}
return 0;
}
static struct file_operations uart1_fops = {
.owner = THIS_MODULE,
.read =device_read,
.write = device_write,
.open =device_open,
.release = NULL,
};
static void max485_setup_cdev(struct max485_chip_info *dev,intindex)
{
int err,max485_dev=MKDEV(Major,index);
cdev_init(&dev->cdev,&uart1_fops);
dev->cdev.owner=THIS_MODULE;
err=cdev_add(&dev->cdev,max485_dev,1);
if(err)
printk(KERN_NOTICE "error %d adding max485 %d/n",err,index);
}
int __init init_module(void)
{
//Registering device
int err=0;
int result;
dev_t max485_dev;
struct max485_chip_info*chip;
if(!(chip = kzalloc(sizeof(struct max485_chip_info), GFP_KERNEL))){
err = -ENOMEM;
return err;
}
if(Major)
{
result=register_chrdev_region(max485_dev,1,DRIVER_NAME);
}
else{
result=alloc_chrdev_region(&max485_dev,0,1,DRIVER_NAME);
Major=MAJOR(max485_dev);
debug_print3( "Major %d\n", Major);
}
if (result < 0) {
debug_print3( "Unable to get Major region, error %d\n",result);
err=result;
}
max485_setup_cdev(chip,0);
max485_class =class_create(THIS_MODULE, "max485");
if(IS_ERR(max485_class))
{
printk("Err: failed in creating max485_class\n");
kfree(chip);
return -1;
}
debug_print3("start device_class for max485\n");
class_device_create( max485_class, NULL, max485_dev, 0,"max485""%d",0);
debug_print3 (KERN_INFO "Registered character driverpcf8574a sensor\n");
return err;
}
void __exit cleanup_module(void)
{
//int ret;
//iounmap((void *)kuart1_base );
//iounmap((void *) kpsc_ptcmd );
//iounmap((void *) kpsc_ptstat );
//iounmap((void *)kpsc_mdctl_uart1 );
//iounmap((void *) kgpio_base );
//iounmap((void *) kpinmux_base );
//iounmap((void *) kpsc_mdctl_gpio);
// Unregister device
device_destroy(max485_class, MKDEV(Major, 0));
class_destroy(max485_class);
unregister_chrdev_region(MKDEV(Major, 0), 1);
}
module_init(init_module);
module_exit(cleanup_module);
MODULE_DESCRIPTION("PCF8574A erternal IO");
MODULE_AUTHOR("Wang, <@.com>");
MODULE_LICENSE("GPL");
应用程序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include "ioport-pcf8574a.h"
#include <sys/ioctl.h>
static int set_opt(int fd,int nSpeed, int nBits, char nEvent,int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0)//取属性(termios结构);
{
perror("SetupSerial1\n\r");
return -1;
}
bzero( &newtio, sizeof( newtio ));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK |ISTRIP);
break;
case 'E':
newtio.c_iflag |= (INPCK |ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag&= ~PARODD;
break;
case 'N':
newtio.c_cflag&= ~PARENB;
break;
}
switch( nSpeed )
{
case 1200:
cfsetispeed(&newtio,B1200);
cfsetospeed(&newtio,B1200);
break;
case 2400:
cfsetispeed(&newtio,B2400);//设置输入速度
cfsetospeed(&newtio,B2400);//设置输出速度
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
case 19200:
cfsetispeed(&newtio,B19200);
cfsetospeed(&newtio,B19200);
break;
case 38400:
cfsetispeed(&newtio,B38400);
cfsetospeed(&newtio,B38400);
break;
case 57600:
cfsetispeed(&newtio,B57600);
cfsetospeed(&newtio,B57600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
default:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
if( nStop== 1 )
newtio.c_cflag&= ~CSTOPB;
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);//刷清未决输入和/或输出;
if((tcsetattr(fd,TCSANOW,&newtio))!=0)//设置属性(termios结构);
{
printf("com set error=%d\n\r",(tcsetattr(fd,TCSANOW,&newtio)));
return -1;
}
printf("set done!\n");
return 0;
}
static int open_port(int fd,int comport)
{
char*dev[]={"/dev/tts/0","/dev/tts/1","/dev/ttyS2"};
long vdisable;
if (comport==1)
{
fd = open( "/dev/ttyS0",O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open SerialPort");
return(-1);
}
else
printf("open ttyS0.....\n");
}
else if(comport==2)
{
fd = open( "/dev/ttyS1",O_RDWR|O_NOCTTY|O_NDELAY);
//fd = open( "/dev/ttyS1",O_RDWR);
if (-1 == fd){
perror("Can't Open SerialPort");
return(-1);
}
else
printf("open ttyS1.....\n");
}
else if (comport==3)
{
fd = open( "/dev/ttyS2",O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd){
perror("Can't Open SerialPort");
return(-1);
}
else
printf("open ttyS2.....\n");
}
//
if(fcntl(fd, F_SETFL, 0)<0)
printf("fcntlfailed!\n");
else
printf("fcntl=%d\n",fcntl(fd,F_SETFL,0));
if(isatty(STDIN_FILENO)==0)
printf("standard input is not aterminal device\n");
else
printf("isattysuccess!\n");
printf("fd-open=%d\n",fd);
return fd;
}
int main(int argc, char *argv[])
{
int fd;
int fdio;
int nread,i;
unsigned char iord;
char buff[]="Hello anger\n";
char rbuff[128];
int rs485_dev;
printf("test uart\n\r");
if((fd=open_port(fd,2))<0)
{
printf("open_porterror\n\r");
return -1;
}
printf("start set\n\r");
if((i=set_opt(fd,57600,8,'N',1))<0)
{
printf("set_opterror\n\r");
return;
}
printf("fd=%d\n\r",fd);
fdio = open("/dev/exioport0",O_RDWR);
if (-1 == fdio){
perror("Can't Open ioPort");
return(-1);
}
ioctl(fdio,EX_GPIO_CONTROL_MAX485_HIGH);
ioctl(fdio,EX_GPIO_READ_PORT,&iord);
printf("ioctl read data=0x%x\n\r",iord);
ioctl(fdio,EX_GPIO_CONTROL_MAX485_LOW);
ioctl(fdio,EX_GPIO_READ_PORT,&iord);
printf("ioctl read data=0x%x\n\r",iord);
while(1)
{
nread =0;
nread=read(fd,rbuff,128);
if(nread)
{
printf("read=%d,%s\n\r",nread,rbuff);
ioctl(fdio,EX_GPIO_CONTROL_MAX485_HIGH);
write(fd,buff,12);
usleep(100000);
usleep(100000);
usleep(100000);
ioctl(fdio,EX_GPIO_CONTROL_MAX485_LOW);
}
}
//close(fd);
//close(fdio);
return;
}