Created
July 5, 2015 22:38
-
-
Save primiano/1355a300807880627e29 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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