Skip to content

Instantly share code, notes, and snippets.

@primiano
Created July 5, 2015 22:38
Show Gist options
  • Save primiano/1355a300807880627e29 to your computer and use it in GitHub Desktop.
Save primiano/1355a300807880627e29 to your computer and use it in GitHub Desktop.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/spi/spi.h>
struct task_struct* worker;
static struct spi_device* spi_dev = NULL;
#define BUF_SIZE 512
static DECLARE_WAIT_QUEUE_HEAD(wait_queue);
static DECLARE_COMPLETION(xfer_done);
static void spi_async_callback(void* unused ) {
complete(&xfer_done);
}
static int worker_main(void* unused) {
int res;
unsigned long num_xfers_completed = 0;
static void* buffer;
struct spi_message msg;
struct spi_transfer xfer = {
.tx_buf = buffer,
.bits_per_word = 32,
.len = BUF_SIZE,
};
buffer = kmalloc(BUF_SIZE, GFP_DMA);
memset((char*)buffer, 0xA0, BUF_SIZE);
// Wait before entering the loop.
while(!kthread_should_stop()){
interruptible_sleep_on_timeout(&wait_queue, HZ/10);
if (!spi_dev)
continue;
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
msg.complete = spi_async_callback;
res = spi_async_locked(spi_dev, &msg);
if (res) {
printk(KERN_ERR "spi_async_locked FAILED %d\n", res);
continue;
}
if(!wait_for_completion_interruptible_timeout(&xfer_done, 5 * HZ)) {
printk(KERN_ERR "wait_for_completion_interruptible_timeout TIMED OUT");
break;
}
++num_xfers_completed;
printk(KERN_INFO "Completed xfer %lu\n", num_xfers_completed);
}
kfree(buffer);
return 0;
}
static int test_spi_probe(struct spi_device *spi) {
spi->max_speed_hz = 5000000;
spi->bits_per_word = 32;
spi_setup(spi);
spi_dev = spi;
printk(KERN_INFO "SPI probed, starting pump thread.\n");
worker = kthread_run(worker_main, NULL, "spi_writer_thread");
return 0;
}
static int test_spi_remove(struct spi_device *spi) {
spi_dev = NULL;
return 0;
}
static const struct spi_device_id idtable[] = {
{"ads7955", 0}, // ads7955 is just a hack to avoid changing the board config.
{}
};
static struct spi_driver test_spi_driver = {
.driver = {
.name = "ads7955", // ads7955 is just a hack to avoid changing the board config.
.owner = THIS_MODULE,
},
.probe = test_spi_probe,
.remove = test_spi_remove,
.id_table = idtable,
};
static int __init test_spi_init(void)
{
int res;
init_waitqueue_head(&wait_queue);
res = spi_register_driver(&test_spi_driver);
if (res)
return res;
printk(KERN_INFO "test spi intialized\n");
return 0;
}
static void __exit test_spi_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
if (worker)
kthread_stop(worker);
return spi_unregister_driver(&test_spi_driver);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Primiano Tucci");
MODULE_DESCRIPTION("Test");
module_init(test_spi_init);
module_exit(test_spi_cleanup);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment