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");