I am using dm357' s SPI port to communicate with fpga.dm357 is master,i can write data to spidata1 register,but i cannot detect clock at th spi_clk pin.Also,when i config spi pins as gpio,i wrtie data to spi_clk(mux with gpio40) pin ,no signal out put,but other gpio work good.
anybody is using spi port on the dm357 or dm644x platform?
my program is as follows:
///////////////////////////
// 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 LPSoC
#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 1
// 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 standard
// phase as described by the motorola architecture. I.E. phase 0 = sample on rising edge of clock
// 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(local power system on chip)
// 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 the
clock
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 IOCTL commands
// 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 %d bytes\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 have
just 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 have
just 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);