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