Hi all,
I am trying to use the spi1 port on my custom DM368 board, and I have porting a spi driver for it. the following is my spi driver demo( master, and use only SCLK, SIMO, SOMI three pins):
/*-----------------------driver code begin---------------------------------------------*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <mach/io.h>
#include <mach/cputype.h>
#include <mach/hardware.h>
#include <linux/clk.h>
#include <mach/dm365.h>
#include <mach/mux.h>
#define DEV_IRQ_NAME "FPGA_SPI"
#define DEV_IRQ_ID "FPGA_SPI"
#define MODULE_NAME "davinci_spi"
///////////////////////////
// DEFINITIONS & GLOBALS
//////////////////////////
// Register definitions to control the SPI,refer to dm368 spi referrence guide.pdf & dm368 ARM subsystem.pdf
#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
#define PINMUX3 0x01c4000c
#define PINMUX4 0x01c40010
// 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 0
// Set these values to whatever you need
#define SPI_POLARITY 0
#define SPI_WORDLENGTH 0x10
#define SPI_WORDLENGTH8 0x8
#define TXFULL_NEWDATA_HERE 0x1
#define TXFULL_NO_NEWDATA_HERE 0x0
#define CSSELECT_ACTIVE 0x1
#define CSSELECT_DEACTIVE 0x0
#define SPIEN0_SEL_ONLY 0x2
#define SPIEN1_SEL_ONLY 0x1
#define SPIEN_SEL_BOTH 0x0
#define RXEMPTY_DATA 0x0
#define RXEMPTY_NO_DATA 0x1
#define SPIGCR1_LOOPBACK 0X1
#define SPIGCR1_NO_LOOPBACK 0X1
#define DFSEL 0x0
#define DMAREQEN 0x1
#define TXINTENA 0x1
#define RXINTENA 0x1
#define TXINTLVL 0x0
#define RXINTLVL 0x0
// We will use a 100K buffer to store data
#define DATABUFFER_ALLOC 5000
#define TXBUFFER 5000
// PRESCALE in bit 15-8 set to whatever you need, SPI_CLK = SYSCLK4 / (Prescale + 1) // 26 => 4MHz, 107 => 1MHz, SYSCLK4=108MHz?
#define PRESCALE_SPICLK4M 26
#define PRESCALE_SPICLK2M 53
#define PRESCALE_SPICLK1M 107
#define PRESCALE_SPICLK500K 215
#define CIF_FRAME_SIZE 76800
#define MAX_FRAME_SIZE 8192
#define MAX_FRAME_NUM 100
#define GPIO_PIN6 GPIO(6)
#define GPIO_PIN16 16
#define GPIO_PIN17 17
#define GPIO_PIN18 18
#define FPGA_BUF 4096
// Macro for accessing a memory location such as a register
//#define SPI_REG(reg) (*(int *__iomem) IO_ADDRESS(reg))
#define SPI_REG(reg) (*(volatile unsigned int *) IO_ADDRESS(reg))
#define __REG(addr) (*(volatile unsigned int *)IO_ADDRESS(addr))
#define REG_PINMUX2 __REG(0x01c40008)
// Version numbers
#define MAJOR_VERSION 245
#define MINOR_VERSION 01
///////////////////////////
// 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);
// 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;
static struct cdev cdev;
// Structure that declares the usual file access functions
static struct file_operations dv_spi_fops = {
.owner = THIS_MODULE,
.read = dv_spi_read,
.write = dv_spi_write,
.open = dv_spi_open,
.release = dv_spi_release
};
// We will use a 1K buffer to store data
static unsigned char * g_buf;
static unsigned int g_bufcount = 0;
struct FS
{
unsigned char FrameBuffer[MAX_FRAME_NUM][MAX_FRAME_SIZE];
long FrameLen[MAX_FRAME_NUM];
long FrameNum;
};
long FindFrame = 0;
long FrameLen = 0;
int Translate = 0;
//////////////////////////////////////////////////////////////
// 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 SPI1
// --------------------------------
// Enable the SPI pins on the GPIO
SPI_REG(PINMUX3) |= 0x80000000;//SPI1_SIMO
SPI_REG(PINMUX4) |= 0x00000015;//SPI1_SCLK, SPI1_SOMI
printk("0000000 = %x -----%x .\n", SPI_REG(PINMUX3), SPI_REG(PINMUX4));
// --------------------------------
// Reset SPI
// --------------------------------
control = 0x00000000;
SPI_REG(SPIGCR0) = control; // Place SPI peripheral in reset
printk("11111111 = %x ------ control = %x.\n", SPI_REG(SPIGCR0) , control);
mdelay(1); // Delay for a bit
control=0x00000001;
SPI_REG(SPIGCR0)=control; // Remove from reset
printk("2222222 = %x ------ control = %x.\n", SPI_REG(SPIGCR0) , control );
// --------------------------------
// Enable SPI CLK & Master
// --------------------------------
control=0x00000003;
SPI_REG(SPIGCR1)=control;
printk("3333333 = %x ------ control = %x.\n", SPI_REG(SPIGCR1) , control );
// -------------------------------
// Enable loopback mode
// -------------------------------
//control = SPI_REG(SPIGCR1);
//control=control | ( SPIGCR1_LOOPBACK << 16 );
//SPI_REG(SPIGCR1) = control;
// --------------------------------
// Enable pins : DI,DO,CLK
// --------------------------------
control=0x00000E00;
SPI_REG(SPIPC0)=control;
printk("4444444 = %x ------ control = %x.\n", 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) // 26 => 4MHz, 107 => 1MHz, SYSCLK5=108MHz
// CHARLEN in bit 4-0 set to 16 : 16 bit characters
-------------------------------- */
control=0x00000000 | (SPI_POLARITY << 17) | (SPI_PHASE << 16) | (0 << 8) | SPI_WORDLENGTH8;
// control=0x00000000 | (SPI_POLARITY << 17) | (SPI_PHASE << 16) | (PRESCALE_SPICLK500K << 8) | SPI_WORDLENGTH8;
// control=0x00000000 | (SPI_POLARITY << 17) | (SPI_PHASE << 16) | (PRESCALE_SPICLK2M << 8) | SPI_WORDLENGTH8;
// control=0x00000000 | (SPI_POLARITY << 17) | (SPI_PHASE << 16) | (PRESCALE_SPICLK1M << 8) | SPI_WORDLENGTH8;
SPI_REG(SPIFMT0)=control;
printk("5555555 = %x ------ control = %x.\n", SPI_REG(SPIFMT0) , control);
// --------------------------------
// Set data format for used -> SPIFMT0
// --------------------------------
control=0x00000000 | (DFSEL << 24);
SPI_REG(SPIDAT1)=control;
printk("6666666 = %x ------ control = %x.\n", SPI_REG(SPIDAT1) , control);
//--------------------------------
// Set interrupt
// -------------------------------
control=0x00000000 | (DMAREQEN << 16) | (TXINTENA<< 9) | (RXINTENA<< 8);
SPI_REG(SPIINT)=control;
printk("7777777 = %x ------ control = %x.\n", SPI_REG(SPIINT) , control);
control=0x00000000 | (TXINTLVL<< 9) | (RXINTLVL<< 8);
SPI_REG(SPILVL)=control;
printk("8888888 = %x ------ control = %x.\n", SPI_REG(SPILVL) , control);
// Set hold time and setup time
// --------------------------------
control=0x00000000 | (0x1F << 16) | (0x1F << 24);
SPI_REG(SPIDELAY)=control;
printk("9999999 = %x ------ control = %x.\n", SPI_REG(SPIDELAY) , control);
// --------------------------------
// Set Chip Select Default
// CSHOLD -> 0 -> release SPI_EN0 state after transmission -> bit 28
// CSNR -> 2 -> Only use SPI_EN0
//********do you really need this part?********
// --------------------------------
control = SPI_REG(SPIDAT1);
control |= (0x2 << 16);
SPI_REG(SPIDAT1)=control;
printk("aaaaaaa = %x ------ control = %x.\n", SPI_REG(SPIDAT1) , control );
// --------------------------------
// Enable for transmitting
// --------------------------------
control=SPI_REG(SPIGCR1);
control=control | 1 << 24; // enable SPIENA
SPI_REG(SPIGCR1)=control;
printk("bbbbbbb = %x ------ control = %x.\n", SPI_REG(SPIGCR1) , control);
// Zero out our read buffer
memset(g_buf, 0, DATABUFFER_ALLOC);
g_bufcount = 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(PINMUX3) &= ~0xB800000;
// 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)
{
return 0;
}
void sendchar(unsigned char ch)
{
return 0;
}
static int dv_spi_init(void)
{
int result;
result = register_chrdev (MAJOR_VERSION, MODULE_NAME, &dv_spi_fops);
if (result)
{
printk ("davinci_spi : can't get major number \n");
return result;
}
// Allocate space for the read buffer
g_buf = kmalloc(DATABUFFER_ALLOC, GFP_KERNEL);
if (!g_buf)
{
result = -ENOMEM;
dv_spi_exit();
return result;
}
printk("<1>Inserting %s module\n", MODULE_NAME);
return 0;
}
static void dv_spi_exit(void)
{
/* Freeing the major number */
unregister_chrdev(MAJOR_VERSION, MODULE_NAME);
/* Freeing buffer memory */
if(g_buf)
kfree(g_buf);
if (g_clkptr)
dv_spi_release(0,0);
printk("<1>Removing %s module.\n", MODULE_NAME);
}
MODULE_AUTHOR("serdar/Jammy Dane");
MODULE_DESCRIPTION("DaVinci SPI driver for XiGongDa");
MODULE_LICENSE("Dual BSD/GPL");
module_init(dv_spi_init);
module_exit(dv_spi_exit);
/*---------------------driver code end------------------------------------------*/
but when i insmod the spi.ko and when i open the spi device, the printk message is as follows:
00000000 = e15affff - - - - - 5155c555.
11111111 = 0 - - - - - control = 0.
22222222 = 0 - - - - - control = 1.
33333333 = 0 - - - - - control = 3.
44444444 = 0 - - - - - control = e00.
55555555 = 0 - - - - - control = 8.
66666666 = 0 - - - - - control = 0.
77777777 = 0 - - - - - control = 1f1f0000.
88888888 = 0 - - - - - control = 0.
99999999 = 0 - - - - - control = 1.
aaaaaaaa = 0 - - - - - control = 20000.
bbbbbbbb = 0 - - - - - control = 1000000.
It seems that I can not write value to the spi registers, such as SPIGCR0 and so on. can you help me to check it. How to fix it ?