SPI driver for davinci,SPI裸驱,达芬奇

本人口号:只贴精品:

转帖注明出处:【blog.csdn.net/lanmanck】

 

/////////////////////////// // INCLUDES ////////////////////////// #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> // udelay() #include <linux/fs.h> // everything... #include <asm/uaccess.h> // copy_from/to_user // Definition for SPI Base Address and the local Power or Sleep Controller #include <asm/arch/hardware.h> #include <asm/hardware/clock.h> /////////////////////////// // PROTOTYPES ////////////////////////// /* Declaration of dv_spi.c functions */ int dv_spi_open(struct inode *inode, struct file *filp); int dv_spi_release(struct inode *inode, struct file *filp); ssize_t dv_spi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos); ssize_t dv_spi_write(struct file *filp, const char *buf, size_t count,loff_t *f_pos); static void dv_spi_exit(void); static int dv_spi_init(void); /////////////////////////// // DEFINITIONS & GLOBALS ////////////////////////// // Register definitions to control the SPI #define SPIGCR0 0x01c66800 #define SPIGCR1 0x01c66804 #define SPIINT 0x01c66808 #define SPILVL 0x01c6680c #define SPIFLG 0x01C66810 // SPI Flag Status Register #define SPIPC0 0x01C66814 // SPI Pin Control Register 0 #define SPIPC2 0x01C6681C // SPI Pin Control Register 2 #define SPIDAT1 0x01C6683C // SPI Shift Register 1 #define SPIBUF 0x01C66840 // SPI Buffer Register #define SPIEMU 0x01C66844 // SPI Emulation Register #define SPIDELAY 0x01C66848 // SPI Delay Register #define SPIDEF 0x01C6684C // SPI Default Chip Select Register #define SPIFMT0 0x01C66850 // SPI Data Format Register 0 #define SPIFMT1 0x01C66854 // SPI Data Format Register 1 #define SPIFMT2 0x01C66858 // SPI Data Format Register 2 #define SPIFMT3 0x01C6685C // SPI Data Format Register 3 #define INTVEC0 0x01C66860 // SPI Interrupt Vector Register 0 #define INTVEC1 0x01C66864 // SPI Interrupt Vector Register // Definition for GPIO Pin Multiplexing #define PINMUX1 0x01c40004 // SPI format - Polarity and Phase // ***NOTE*** It doesn't seem like the SPI Phase for the davinci follows the // In the davinci it seems this is opposite. #define SPI_PHASE 1 // Set these values to whatever you need #define SPI_POLARITY 0 // Macro for accessing a memory location such as a register #define SPI_REG(reg) (*(int *__iomem) IO_ADDRESS(reg)) // Version numbers #define MAJOR_VERSION 60 #define MINOR_VERSION 01 // Global pointer to the clock struct. We use this to start up the LPSoC // so our SPI peripheral has power going to it. static struct clk *g_clkptr = 0; // Structure that declares the usual file access functions static struct file_operations dv_spi_fops = { read: dv_spi_read, write: dv_spi_write, open: dv_spi_open, release: dv_spi_release }; // We will use a 1K read buffer to store data static unsigned char *g_readbuf = 0; static unsigned int g_readbufcount = 0; static int dv_spi_init(void) { int result; /* Registering device */ result = register_chrdev(MAJOR_VERSION, "spi",&dv_spi_fops); if (result < 0) { printk("<1>dv_spi: cannot obtain major number %d/n", MAJOR_VERSION); return result; } // Allocate space for the read buffer g_readbuf = kmalloc(1024, GFP_KERNEL); if (!g_readbuf) { result = -ENOMEM; dv_spi_exit(); return result; } printk("<1>Inserting SPI module/n"); return 0; } static void dv_spi_exit(void) { /* Freeing the major number */ unregister_chrdev(MAJOR_VERSION, "spi"); /* Freeing buffer memory */ if(g_readbuf) kfree(g_readbuf); if (g_clkptr) dv_spi_release(0,0); printk("<1>Removing SPI module/n"); } // Called when a userspace program opens the file int dv_spi_open(struct inode *inode, struct file *filp) { unsigned int control; // Power up the SPI hardware by requesting and enabling theclock g_clkptr = clk_get(NULL, "SPICLK"); if(g_clkptr <= 0) printk("<l>Error could not get the clock/n"); else clk_enable(g_clkptr); // -------------------------------- // Configure GPIO Pins for SPI // -------------------------------- // Enable the SPI pins on the GPIO SPI_REG(PINMUX1) |= 0x100; // -------------------------------- // Reset SPI // -------------------------------- control=0x00000000; SPI_REG(SPIGCR0)=control; // Place SPI peripheral in reset mdelay(1); // Delay for a bit control=0x00000001; SPI_REG(SPIGCR0)=control; // Remove from reset // -------------------------------- // Enable SPI CLK & Master // -------------------------------- control=0x00000003; SPI_REG(SPIGCR1)=control; // -------------------------------- // Enable pins : DI,DO,CLK,EN0 // -------------------------------- control=0x00000E01; SPI_REG(SPIPC0)=control; /* -------------------------------- // Set data format in SPIFMT0 - THIS CAN BE CHANGED BY IOCTLcommands // SHIFTDIR in bit 20 set to 1 : MSB first // POLARITY and PHASE in bit 17, 16 set to 0, 0 // PRESCALE in bit 15-8 set to whatever you need, SPI_CLK =SYSCLK5 / (Prescale + 1) // CHARLEN in bit 4-0 set to 08 : 8 bit characters -------------------------------- */ control=0x00000000 | (SPI_POLARITY << 17) | (SPI_PHASE <<16) | (0x7 << 8) | 0x8; SPI_REG(SPIFMT0)=control; // -------------------------------- // Set data format for used -> SPIFMT0 // -------------------------------- control=0x00000000 | (0x00 << 24); SPI_REG(SPIDAT1)=control; // -------------------------------- // Set hold time and setup time // -------------------------------- control=0x00000000 | (0x03 << 16) | (0x06 << 24); SPI_REG(SPIDELAY)=control; // -------------------------------- // Set Chip Select Default // CSHOLD -> 0 -> release SPI_EN0 state after transmission-> bit 28 // CSNR -> 2 -> Only use SPI_EN0 // -------------------------------- control=SPI_REG(SPIDAT1); control|= (0x2 << 16); SPI_REG(SPIDAT1)=control; // -------------------------------- // Enable for transmitting // -------------------------------- control=SPI_REG(SPIGCR1); control=control | 1 << 24; // enable SPIENA SPI_REG(SPIGCR1)=control; // Zero out our read buffer memset(g_readbuf, 0, 1024); g_readbufcount = 0; return 0; } // Called when a userspace program closes the file int dv_spi_release(struct inode *inode, struct file *filp) { // Place SPI peripheral into reset SPI_REG(SPIGCR0)=0; // Remove the SPI output on the GPIO SPI_REG(PINMUX1) &= ~0x100; // Disable the clock thus removing power from the peripheral if(g_clkptr) clk_disable(g_clkptr); g_clkptr = 0; return 0; } // Reading from the SPI device ssize_t dv_spi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos) { //printk("<1>Attempting to read %d bytes and we only have %dbytes/n",count,g_readbufcount); if(g_readbufcount == 0) return 0; // No data // See if there is enough available if(count > g_readbufcount) count = g_readbufcount; // Transferring data to user space copy_to_user(buf,g_readbuf,count); // Now shift the memory down memmove(&g_readbuf[0],&g_readbuf[count],g_readbufcount-count); g_readbufcount -= count; // Advance the file pointer *f_pos += count; return count; } // Writing to the SPI device ssize_t dv_spi_write(struct file *filp, const char *buf, size_t count,loff_t *f_pos) { unsigned char spiData; size_t i; unsigned int control; unsigned int ReadByte; // Wait until the TX buffer is clear control = SPI_REG(SPIBUF); while(control & (1 << 29)) //Wait until the TX data has been transmitted control = SPI_REG(SPIBUF); // Write out data one byte at a time for(i=0; i < count; i++) { ReadByte = 0; // Send the data copy_from_user(&spiData,buf+i,1); control = 0x00000000 | (0x1 << 28) | (0x2 <<16) | spiData; // Hold the chip select line between multibytes SPI_REG(SPIDAT1) = control; if(i == (count -1)) SPI_REG(SPIDAT1) =0x00000000 | (0x2 << 16) | spiData; // Remove the chip select hold control = SPI_REG(SPIBUF); while(control & (1 << 29))// Wait until the TX data has been transmitted { // Check for data received if(!(control & (1 << 31))) { // We havejust read a byte of data, store it. if(g_readbufcount < 1024) { // printk("<1>Read in byte value = %d!/n",count); g_readbuf[g_readbufcount] = control & 0xFF; g_readbufcount++; ReadByte = 1; } } control = SPI_REG(SPIBUF); } // Make sure we have always read in a byte while(!ReadByte) { // Check for data received if(!(control & (1 << 31))) { // printk("<1>we received a byte with value %d/n",control & 0xFF);// We havejut read a byte of data, store it. if(g_readbufcount < 1024) {// printk("<1>Read in byte value = %d/n",control); g_readbuf[g_readbufcount] = control & 0xFF; g_readbufcount++; ReadByte = 1; } } control = SPI_REG(SPIBUF); } } return count; } MODULE_LICENSE("Dual BSD/GPL"); module_init(dv_spi_init); module_exit(dv_spi_exit);  

你可能感兴趣的:(struct,vector,File,Module,buffer,byte)