|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
|
#include <linux/workqueue.h>
|
|
|
|
|
#include <linux/spi/spi.h>
|
|
|
|
|
|
|
|
|
|
#define FRAME_SIZE (24)
|
|
|
|
@ -19,6 +20,7 @@
|
|
|
|
|
|
|
|
|
|
struct ads1278
|
|
|
|
|
{
|
|
|
|
|
struct workqueue_struct *wq;
|
|
|
|
|
unsigned char *rx;
|
|
|
|
|
unsigned char *tx;
|
|
|
|
|
dma_addr_t rx_dma_handle;
|
|
|
|
@ -29,26 +31,43 @@ struct ads1278
|
|
|
|
|
int running[2];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void ads1278_transfer_callback1(void *context)
|
|
|
|
|
static struct spi_device *spip = NULL;
|
|
|
|
|
static void ads1278_work_handler(struct work_struct *w)
|
|
|
|
|
{
|
|
|
|
|
struct spi_device *spi = (struct spi_device *)context;
|
|
|
|
|
struct ads1278 *ads = spi_get_drvdata(spi);
|
|
|
|
|
struct ads1278 *ads;
|
|
|
|
|
|
|
|
|
|
if (!spip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
ads = spi_get_drvdata(spip);
|
|
|
|
|
|
|
|
|
|
if (!ads->stop_requested)
|
|
|
|
|
spi_async(spi, &ads->msg[0]);
|
|
|
|
|
else
|
|
|
|
|
ads->running[0] = 0;
|
|
|
|
|
while (!ads->stop_requested) {
|
|
|
|
|
spi_sync_locked(spip, &ads->msg[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
static DECLARE_WORK(ads1278_work, ads1278_work_handler);
|
|
|
|
|
|
|
|
|
|
static void ads1278_transfer_callback2(void *context)
|
|
|
|
|
static void ads1278_transfer_callback1(void *context)
|
|
|
|
|
{
|
|
|
|
|
struct spi_device *spi = (struct spi_device *)context;
|
|
|
|
|
struct ads1278 *ads = spi_get_drvdata(spi);
|
|
|
|
|
// struct spi_device *spi = (struct spi_device *)context;
|
|
|
|
|
// struct ads1278 *ads = spi_get_drvdata(spi);
|
|
|
|
|
//
|
|
|
|
|
// if (!ads->stop_requested)
|
|
|
|
|
// queue_work(ads->wq, &ads1278_work);
|
|
|
|
|
// //spi_async(spi, &ads->msg[0]);
|
|
|
|
|
// else
|
|
|
|
|
// ads->running[0] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ads->stop_requested)
|
|
|
|
|
spi_async(spi, &ads->msg[1]);
|
|
|
|
|
else
|
|
|
|
|
ads->running[1] = 0;
|
|
|
|
|
static void ads1278_transfer_callback2(void *context)
|
|
|
|
|
{
|
|
|
|
|
// struct spi_device *spi = (struct spi_device *)context;
|
|
|
|
|
// struct ads1278 *ads = spi_get_drvdata(spi);
|
|
|
|
|
//
|
|
|
|
|
// if (!ads->stop_requested)
|
|
|
|
|
// spi_async(spi, &ads->msg[1]);
|
|
|
|
|
// else
|
|
|
|
|
// ads->running[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -119,8 +138,16 @@ static int ads1278_begin_transfer(struct spi_device *spi)
|
|
|
|
|
ads->running[0] = 1;
|
|
|
|
|
ads->running[1] = 1;
|
|
|
|
|
|
|
|
|
|
/* TODO ret = */ spi_async(spi, &ads->msg[0]);
|
|
|
|
|
return spi_async(spi, &ads->msg[1]);
|
|
|
|
|
// /* TODO ret = */ spi_async(spi, &ads->msg[0]);
|
|
|
|
|
// return spi_async(spi, &ads->msg[1]);
|
|
|
|
|
|
|
|
|
|
ads->wq = create_singlethread_workqueue("ads1278");
|
|
|
|
|
if (ads->wq) {
|
|
|
|
|
spip = spi;
|
|
|
|
|
queue_work(ads->wq, &ads1278_work);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ads1278_probe(struct spi_device *spi)
|
|
|
|
@ -149,6 +176,7 @@ static int ads1278_probe(struct spi_device *spi)
|
|
|
|
|
|
|
|
|
|
dev_info(&spi->dev, "ready to go!");
|
|
|
|
|
|
|
|
|
|
spi_bus_lock(spi->controller);
|
|
|
|
|
if (ads1278_begin_transfer(spi)) {
|
|
|
|
|
dev_err(&spi->dev, "error with initial transfer!");
|
|
|
|
|
goto end_free_ads;
|
|
|
|
@ -184,9 +212,14 @@ static void ads1278_remove(struct spi_device *spi)
|
|
|
|
|
dma_free_coherent(&spi->dev, TRANSFER_SIZE * 2, ads->tx, ads->tx_dma_handle);
|
|
|
|
|
dma_free_coherent(&spi->dev, TRANSFER_SIZE * 2, ads->rx, ads->rx_dma_handle);
|
|
|
|
|
|
|
|
|
|
flush_scheduled_work();
|
|
|
|
|
if (ads->wq)
|
|
|
|
|
destroy_workqueue(ads->wq);
|
|
|
|
|
|
|
|
|
|
kfree(ads);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
spi_bus_unlock(spi->controller);
|
|
|
|
|
dev_info(&spi->dev, "done.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|