This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to call SPI protocol driver?

Hi guys!

I'm writing SPI Protocol driver for my SPI device. My driver uses "spi_davinci" driver as SPI Master Controller driver.

I see that my driver in the system (/sys/bus/spi/drivers/ and /sys/bus/spi/devices/ directories) after "insmod" my module.

/ # grep devxxx /proc/kallsyms
bf000248 t devxxx_remove       [mydev]
bf000264 t devxxx_probe        [mydev]
bf00007c t devxxx_spi_read     [mydev]
bf000000 t devxxx_spi_write    [mydev]
bf0002f0 t devxxx_exit [mydev]
bf0001a4 t devxxx_cmd_read     [mydev]
bf0000f8 t devxxx_cmd_write    [mydev]
/ #

How can I call my SPI protocol driver in the kernel space? Do I need some file to use for?

What is default way to call external module (driver) functions?

My code:

 

#include <linux/init.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>

#include <linux/spi/spi.h>


struct devxxx {
	struct spi_device	*spi;
	struct device       *dev;
	struct mutex		lock;

	int (*read)(struct devxxx *mydev, void *buf, int len);
	int (*write)(struct devxxx *mydev, void *buf, int len);
};


int devxxx_cmd_read(struct devxxx *mydev, u16 cmd, u8 len, u16 *buf);
int devxxx_cmd_write(struct devxxx *mydev, u16 cmd, u8 len, u16 *buf);

/****************************************************************************/

int devxxx_cmd_read(struct devxxx *mydev, u16 cmd, u8 len, u16 *buf)
{
	int err, data;

	mutex_lock(&mydev->lock);

	err = mydev->write(mydev, &cmd, 1);
	if (err < 0)
		dev_err(mydev->dev, "Write cmd 0x%04X failed\n", cmd);

	data = mydev->read(mydev, buf, len);
	if (data < 0)
		dev_err(mydev->dev, "Read cmd 0x%04X failed\n", cmd);

	mutex_unlock(&mydev->lock);
	return data;
}
EXPORT_SYMBOL_GPL(devxxx_cmd_read);

static int devxxx_spi_read(struct devxxx *mydev, void *buf, int len)
{
	struct spi_device *spi = mydev->spi;
	struct spi_transfer	t = {
			.rx_buf		= buf,
			.len		= len << 1,
			.bits_per_word = 16,
	};
	struct spi_message	m;

	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	return spi_sync(spi, &m);

//	struct spi_device *spi = mydev->spi;
//	return spi_read(spi, buf, len);
}

int devxxx_cmd_write(struct devxxx *mydev, u16 cmd, u8 len, u16 *buf)
{
	int err;
	u8 wlen;
	u16 wbuf[33];

	wbuf[0] = cmd;
	wlen = 1;
	if (len != 0) {
		if (len > 32) {
			printk(KERN_ALERT "devxxx_cmd_write(): cmd 0x%04X: too big size", cmd);
			len = 32;
		}
		memcpy(&wbuf[1], buf, len << 1);
		wlen += len;
	}
	mutex_lock(&mydev->lock);

	err = mydev->write(mydev, wbuf, wlen);
	if (err < 0)
		dev_err(mydev->dev, "Write cmd 0x%04X failed\n", cmd);

	mutex_unlock(&mydev->lock);
	return err;
}
EXPORT_SYMBOL_GPL(devxxx_cmd_write);


static int devxxx_spi_write(struct devxxx *mydev, void *buf, int len)
{
	struct spi_device *spi = mydev->spi;
	struct spi_transfer	t = {
			.tx_buf		= buf,
			.len		= len << 1,
			.bits_per_word = 16,
	};
	struct spi_message	m;

	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	return spi_sync(spi, &m);

//	struct spi_device *spi = mydev->spi;
//	return spi_write(spi, buf, len);
}

/****************************************************************************/

static int __devinit devxxx_probe(struct spi_device *spi)
{
	struct devxxx *mydev;

	/* get memory for driver's per-chip state */
	mydev = kzalloc(sizeof *mydev, GFP_KERNEL);
	if (!mydev)
		return -ENOMEM;
	
	mydev->spi = spi;
	mydev->dev = &spi->dev;

	mutex_init(&mydev->lock);

	mydev->read = devxxx_spi_read;
	mydev->write = devxxx_spi_write;
	
	spi_set_drvdata(spi, mydev);

	return 0;
}


static int __devexit devxxx_remove(struct spi_device *spi)
{
	struct devxxx *mydev = spi_get_drvdata(spi);

	kfree(mydev);

	return 0;
}


static struct spi_driver devxxx_driver = {
	.driver = {
		.name	= "devxxx",
		.owner	= THIS_MODULE,
	},
	.probe	= devxxx_probe,
	.remove	= __devexit_p(devxxx_remove),
};


static int __init devxxx_init(void)
{
	return spi_register_driver(&devxxx_driver);
}


static void __exit devxxx_exit(void)
{
	spi_unregister_driver(&devxxx_driver);
}


module_init(devxxx_init);
module_exit(devxxx_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Bakir Khaybullin");
MODULE_DESCRIPTION("SPI driver for devxxx devices");