How to write SPI driver.

Jon
Hello,
I do u know about how to write the SPI driver for MINI2440.I am newbin for
embedded linux.I have done character driver on Linux PC,paraller driver for
PC & serial port driver also write.
tell mi how to write basic SPI driver for read write only.
Thanx in advacne .

Juergen
SPI access as a 'master' or 'slave'? The SPI master driver is already
present in the kernel. A slave driver is up to you and your attached SPI
device.

Mosfet Killer
This code works on mini210s:

static uint8_t spimode;
static uint8_t spibits = 8;
static uint32_t spispeed = 16000*1000; //(16MHz)
static uint16_t spidelay;
uint16_t delay;

static void spi_transfer(int fd, uint8_t *tx, uint8_t *rx)
{
    struct spi_ioc_transfer tr;
    tr.tx_buf = (unsigned long)tx;
    tr.rx_buf = (unsigned long)rx;
    tr.len = 3;
    tr.delay_usecs = spidelay;
    tr.speed_hz = spispeed;
    tr.bits_per_word = 8;

    ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
}

void *adc_thd(void *id){
    int fd;

    spimode = 3;
    spispeed = 16000*1000;
    spibits = 8;

    fd = open("/dev/spidev1.0", O_RDWR);
    if (fd < 0){
        print_error(2,"can't open SPI device");
        pthread_exit(NULL);
    }
    bool spiinit = true;
    ret = ioctl(fd, SPI_IOC_WR_MODE, &spimode);
    if(ret < 0)spiinit = false;
    ret = ioctl(fd, SPI_IOC_RD_MODE, &spimode);
    if(ret < 0)spiinit = false;
    ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spibits);
    if(ret < 0)spiinit = false;
    ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &spibits);
    if(ret < 0)spiinit = false;
    ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spispeed);
    if(ret < 0)spiinit = false;
    ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &spispeed);
    if(ret < 0)spiinit = false;
    if(spiinit){
        printf("spi mode: %d\n", spimode);
        printf("bits per word: %d\n", spibits);
        printf("max speed:%d KHz)\n", spispeed/1000);
    }else{
        print_error(2,"SPI critical initialization ERRORS -- closing");
        pthread_exit(NULL);
    }
.
.
.
.
.

to write i used:

uint8_t tx[3], rx[3];
// write something into tx
spi_transfer(fd, tx, rx);
//read rx

Mosfet Killer
Ah, forgot that you have to include
#include <linux/spi/spidev.h>

jon
Hello,
thanx for replay please tell mi how to use slave & master in user level

Rofique Anowar
Hi,
   I am also new to write the driver in the kernel. I have to write driver
for slave device RC-632. Hardware connection as follows.I have connected
Connector4 of Friendly ARM(Mini2440) Board.

Connector4->pin25(SPIMISO)--RC632-pin22(MOSI)

Rofique Anowar
Connector4->pin25(SPIMISO)--RC632-pin22(MOSI)
          ->pin27(SPICLK) --RC632-pin24(CLK)
          ->pin26(SPIMOSI)--RC632-pin13(MISO)
          ->pin28(nSS_SPI)--RC632-pin21(CS)
          ->pin5          --RC632-pin2(IRQ)
          ->pin7          --RC632-pin31(RST)

I have connected the basic hardware connection. Now want to make a driver
in kernel side and one program to access the data from user space.

I have to write the following finction:

1.void cs_632(unsigned char );
2.void rst_632(unsigned char );
3.unsigned char irq_632(void);
4.void spi_init(void);
5.unsigned char spi_read_write (unsigned char  );

I know to how to write SPI driver with Non OS based controller. 
But I have no clue how to the same thing in kernel space and user space.

Please guide me.
Thanks in advance.
Rofique Anowar

Juergen
There are many drivers in the kernel for devices which are connected via
SPI bus. Take a look into them and get an idea how to create the
communication bit stream, and/or take a look into kernel's
"Documentation/spi/spi-summary"

Rofique Anowar
Hi Juergen,
    Thanks for your reply. I have written the following function

1.static int spi_dev_open(struct inode *inode,struct file *filp);
2.static int spi_dev_release(struct inode *inode,struct file *filp);
3.static void spi_writebyte(const char data);  
4.static char spi_readbyte(const char data);
5.static ssize_t spi_dev_read(struct file *filp,char __user *buf,size_t
count,loff_t *f_ops); 
6.static ssize_t spidev__write(struct file *filp,const char __user *buf,  
size_t count,loff_t *f_ops);
7.static int __init spi_dev_init(void); 
8.static void __exit spi_dev_exit(void); 

I have written this as character module driver. I have loop-back the MISO
and MOSI pin. I am writing some byte to my driver, then reading byte. I am
getting the same thing. That means my driver SPI driver working perfectly.

Now, I need to implement the 
1.Chip-select as OUTPUT_PIN 
2.Set and Clear the the chip-select PIN.
3.One IRQ as INPUT_PIN.
4.Detect the IRQ_PIN whether it is low or high.

Please, guide me how can I achieve this.
Thanks in advance.

Rofique

Rofique Anowar
Could you Please tell me How to do I/O Initialization and read write in
kernel side coding.

Juergen
The kernel's SPI framework uses classes of SPI master driver (which are
responsible to transfer data between the SPI master and an attached SPI
device) and SPI devices. SPI devices get registered to their corresponding
SPI master drivers (to form a bus). This is plain configuration (via
platform code or devicetree).

After that SPI device drivers start to communicate in a generic manner to
their SPI devices. "Generic" means, there is no need for you to handle the
CS line. Its handled for you automatically inside the SPI master driver
your SPI device is connected to.
If you have additional requirements like an interrupt its up to your SPI
device driver to register this channel as well. I'm sure, there are many
SPI device drivers in the kernel where you can see how it works.

BTW: do not use a character driver. Use the nice and powerful sysfs
features instead to communicate from your application in userspace with
your SPI device driver in kernelspace.

Rofique Anowar
Anyone have worked on direct register setting of s3c2440 chip?
I need three I/O pin what will be the register value for that?

Rofique Anowar
Hi Juergen,
   Thanks for your reply. Ok! I will do it what you have suggested.
But beside the ChipSelect I have to control two more I/O. How can I do
that?
   1.Some time I need to Reset the SPI device.
   2.Some time need to check state of an input pin.

In chapter 9 (I/O PORTS) of "S3C2440.pdf" there are detailed description
about the I/O. But, what set of register is need to set?

Do you have any Non-OS based source code for Input/Output?  

Thanks

Juergen
I always wonder why everybody wants to program registers itself. With Linux
you are running an operating system, not a kitchen sync selfmade somehow
software. Why everybody wants to re-invent the wheel over and over again?

If you want to control GPIOs within your driver use the gpiolib, a
framework inside the Linux kernel. It provides registering and changing
GPIOs in a generic and architecture and hardware independent manner.

Read all in Documentation/gpio, especially gpio-legacy.txt and gpio.txt

Rofique Anowar
Hi Juergen,
    Thanks for your valuable suggestion. I will definitely follow your
suggestion. Basically I am familiar to write the device driver in non-OS
based system and novice in writing device 
driver in kernel space.
    Anyway, I have solved my previously asked question. We need to
implement this ->

s3c2410_gpio_setpin(S3C2410_GPG(2),0)-> for Clear.
s3c2410_gpio_setpin(S3C2410_GPG(2),1)-> for Set.

Thanks.

rahul
Hi,
I want to write SPI device driver for MCP3008 ADC on BEAGLE BONE BLACK.
How can I write this driver.

please guide me.

davef
rahul,

I think you would stand a better chance posting on the BeagleBone forums.

davef
http://exploringbeaglebone.com/chapter8/

Gwtham
In device tree i am adding my device and also default spi device it self
not binding with my driver i am writing driver in beaglebone balck 
and also i tried ovaerlay concept but what ever i am passing into the slots
in bonecape manger it is telling  no such overlay is present in firmware
directory what i will do.

davef
> I think you would stand a better chance posting on the BeagleBone forums.

Kushal Parmar
I am accessing max7219 LED display using userspace interface provided by
spidev using the spi_ioc_transfer structure and the spi_ioc_message(n)
ioctl to send the address and value to set.
I am facing a problem, as I am not able to display anything on the led.
I followed the setup using th efollowing ioctls:
SPI_IOC_WR_MODE
SPI_IOC_WR_MAX_SPEED_HZ
SPI_IOC_WR_LSB_FIRST //set to MSb first by giving 0
SPI_IOC_WR_BITS_PER_WORD

I observed that my initial setup ioctl's return successful even when the
LED device is not connected to the board.

What is the explanation for this? OR is this normal?

Thank you