diff --git a/.gitignore b/.gitignore index 2be0d54..b7d8491 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.cmd *.ko.cmd *.mod.c *.mod.o diff --git a/README.md b/README.md index b1f8cd4..db18c6c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To compile you'll need an ARM cross compiler and the source tree of a compiled ARM kernel. Update the Makefile to point to your kernel source, and run the following command: -make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- Please note that we're cross-compiling from an x86 machine. diff --git a/cc2520.ko b/cc2520.ko index a312ca3..58bb9e3 100644 Binary files a/cc2520.ko and b/cc2520.ko differ diff --git a/debug.h b/debug.h index 3743a20..59e3a69 100644 --- a/debug.h +++ b/debug.h @@ -9,7 +9,7 @@ #define DEBUG_PRINT_ERR 1 // print occasional messages about interesting things #define DEBUG_PRINT_INFO 2 -// print a good amount of debuging output +// print a good amount of debugging output #define DEBUG_PRINT_DBG 3 // Defines the level of debug output diff --git a/module.c b/module.c index 69f8f03..8f55119 100644 --- a/module.c +++ b/module.c @@ -20,7 +20,7 @@ #include "debug.h" #define DRIVER_AUTHOR "Andrew Robinson " -#define DRIVER_DESC "A driver for the CC2520 radio. Be afraid." +#define DRIVER_DESC "A driver for the CC2520 radio." #define DRIVER_VERSION "0.5" uint8_t debug_print; @@ -58,7 +58,7 @@ int init_module() memset(&state, 0, sizeof(struct cc2520_state)); - INFO((KERN_INFO "loading CC2520 Kernel Module v%s...\n", DRIVER_VERSION)); + INFO((KERN_INFO "[CC2520] - Loading kernel module v%s\n", DRIVER_VERSION)); err = cc2520_plat_gpio_init(); if (err) { @@ -127,7 +127,7 @@ int init_module() error6: cc2520_plat_gpio_free(); error7: - return 1; + return -1; } void cleanup_module() @@ -136,7 +136,7 @@ void cleanup_module() cc2520_interface_free(); cc2520_plat_gpio_free(); cc2520_plat_spi_free(); - INFO((KERN_INFO "Unloading CC2520 Kernel Module...\n")); + INFO((KERN_INFO "[cc2520] - Unloading kernel module\n")); } MODULE_LICENSE("GPL"); diff --git a/patches/bcm2708.patch b/patches/bcm2708.patch index 5ae2fb2..33468ed 100644 --- a/patches/bcm2708.patch +++ b/patches/bcm2708.patch @@ -1,5 +1,5 @@ diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c -index 7fe7283..32f1fdf 100644 +index 9a5632f..6f39d36 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -584,6 +584,9 @@ static struct platform_device bcm2708_spi_device = { @@ -11,4 +11,4 @@ index 7fe7283..32f1fdf 100644 + }, }; - #ifdef CONFIG_SPI + #ifdef CONFIG_BCM2708_SPIDEV diff --git a/patches/spi-bcm2708.patch b/patches/spi-bcm2708.patch index 54a4d07..0fe1d79 100644 --- a/patches/spi-bcm2708.patch +++ b/patches/spi-bcm2708.patch @@ -1,5 +1,5 @@ diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c -index 088cbaa..661a4cb 100644 +index 1744c1e..b648ab4 100644 --- a/drivers/spi/spi-bcm2708.c +++ b/drivers/spi/spi-bcm2708.c @@ -1,7 +1,7 @@ @@ -11,7 +11,7 @@ index 088cbaa..661a4cb 100644 * * This driver is inspired by: * spi-ath79.c, Copyright (C) 2009-2011 Gabor Juhos -@@ -35,6 +35,14 @@ +@@ -35,6 +35,15 @@ #include #include #include @@ -23,10 +23,11 @@ index 088cbaa..661a4cb 100644 +static short processmode=1; +module_param(processmode,short,0); +MODULE_PARM_DESC(processmode,"Processing mode: 0=polling, 1=interrupt driven, 2=dma"); ++ /* SPI register offsets */ #define SPI_CS 0x00 -@@ -74,6 +82,37 @@ +@@ -74,6 +83,37 @@ #define DRV_NAME "bcm2708_spi" @@ -64,7 +65,7 @@ index 088cbaa..661a4cb 100644 struct bcm2708_spi { spinlock_t lock; void __iomem *base; -@@ -81,14 +120,24 @@ struct bcm2708_spi { +@@ -81,14 +121,24 @@ struct bcm2708_spi { struct clk *clk; bool stopping; @@ -95,7 +96,7 @@ index 088cbaa..661a4cb 100644 }; struct bcm2708_spi_state { -@@ -132,75 +181,9 @@ static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val) +@@ -132,96 +182,9 @@ static inline void bcm2708_wr(struct bcm2708_spi *bs, unsigned reg, u32 val) writel(val, bs->base + reg); } @@ -113,10 +114,31 @@ index 088cbaa..661a4cb 100644 -static inline void bcm2708_wr_fifo(struct bcm2708_spi *bs, int len) -{ - u8 byte; +- u16 val; - - if (len > bs->len) - len = bs->len; - +- if (unlikely(bcm2708_rd(bs, SPI_CS) & SPI_CS_LEN)) { +- /* LoSSI mode */ +- if (unlikely(len % 2)) { +- printk(KERN_ERR"bcm2708_wr_fifo: length must be even, skipping.\n"); +- bs->len = 0; +- return; +- } +- while (len) { +- if (bs->tx_buf) { +- val = *(const u16 *)bs->tx_buf; +- bs->tx_buf += 2; +- } else +- val = 0; +- bcm2708_wr(bs, SPI_FIFO, val); +- bs->len -= 2; +- len -= 2; +- } +- return; +- } +- - while (len--) { - byte = bs->tx_buf ? *bs->tx_buf++ : 0; - bcm2708_wr(bs, SPI_FIFO, byte); @@ -173,7 +195,7 @@ index 088cbaa..661a4cb 100644 { struct bcm2708_spi *bs = spi_master_get_devdata(master); int cdiv; -@@ -259,96 +242,468 @@ static int bcm2708_setup_state(struct spi_master *master, +@@ -284,97 +247,468 @@ static int bcm2708_setup_state(struct spi_master *master, if (state) { state->cs = cs; state->cdiv = cdiv; @@ -228,7 +250,8 @@ index 088cbaa..661a4cb 100644 - ret = bcm2708_setup_state(spi->master, &spi->dev, &state, - xfer->speed_hz ? xfer->speed_hz : spi->max_speed_hz, - spi->chip_select, spi->mode, -- spi->bits_per_word); +- xfer->bits_per_word ? xfer->bits_per_word : +- spi->bits_per_word); - if (ret) - return ret; +static int bcm2708_register_dmabuffer(struct platform_device *pdev, @@ -286,8 +309,7 @@ index 088cbaa..661a4cb 100644 + /* return IRQ handled */ + return IRQ_HANDLED; +} - -- cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA; ++ +/* We could improve on DMA options, by chaining individual xfer messages + into a more complex CB chain that takes care of all the transfers in one "go" + resulting in only one interrupt getting delivered at the end of the sequence. @@ -344,7 +366,8 @@ index 088cbaa..661a4cb 100644 + } + /* auto deselect CS if it is the last */ + if (flags&FLAGS_LAST_TRANSFER) { cs|=SPI_CS_ADCS; } -+ + +- cs = stp->cs | SPI_CS_INTR | SPI_CS_INTD | SPI_CS_TA; + /* store data for interrupts and more */ + bs->rx_buf=xfer->rx_buf; + bs->tx_buf=xfer->tx_buf; @@ -461,7 +484,9 @@ index 088cbaa..661a4cb 100644 + (bs->rx_len)--; + } + spin_unlock(&bs->lock); -+ + +- if (xfer->delay_usecs) +- udelay(xfer->delay_usecs); + /* and if we have rx_len as 0 then wakeup the process */ + if (bs->rx_len==0) { + /* clean the transfers including all interrupts */ @@ -470,9 +495,7 @@ index 088cbaa..661a4cb 100644 + /* and wake up the thread to continue its work */ + complete(&bs->done); + } - -- if (xfer->delay_usecs) -- udelay(xfer->delay_usecs); ++ + /* return IRQ handled */ + return IRQ_HANDLED; +} @@ -566,7 +589,10 @@ index 088cbaa..661a4cb 100644 - spin_unlock_irqrestore(&bs->lock, flags); + /* increment type counter */ + bs->transfers_polling++; -+ + +- list_for_each_entry(xfer, &msg->transfers, transfer_list) { +- status = bcm2708_process_transfer(bs, msg, xfer); +- if (status) + /* start by setting up the SPI controller */ + cs=stp->cs|SPI_CS_TA; + bcm2708_wr(bs, SPI_CLK, stp->cdiv); @@ -597,10 +623,7 @@ index 088cbaa..661a4cb 100644 + /* and return OK */ + return 0; +} - -- list_for_each_entry(xfer, &msg->transfers, transfer_list) { -- status = bcm2708_process_transfer(bs, msg, xfer); -- if (status) ++ +/* this one sends a message */ +static int bcm2708_transfer_one_message(struct spi_master *master, + struct spi_message* msg) { @@ -701,7 +724,7 @@ index 088cbaa..661a4cb 100644 } static int bcm2708_spi_setup(struct spi_device *spi) -@@ -357,11 +712,13 @@ static int bcm2708_spi_setup(struct spi_device *spi) +@@ -383,11 +717,13 @@ static int bcm2708_spi_setup(struct spi_device *spi) struct bcm2708_spi_state *state; int ret; @@ -716,7 +739,7 @@ index 088cbaa..661a4cb 100644 dev_dbg(&spi->dev, "setup: invalid chipselect %u (%u defined)\n", spi->chip_select, spi->master->num_chipselect); -@@ -378,12 +735,11 @@ static int bcm2708_spi_setup(struct spi_device *spi) +@@ -404,12 +740,11 @@ static int bcm2708_spi_setup(struct spi_device *spi) } ret = bcm2708_setup_state(spi->master, &spi->dev, state, @@ -731,7 +754,7 @@ index 088cbaa..661a4cb 100644 } dev_dbg(&spi->dev, -@@ -394,48 +750,6 @@ static int bcm2708_spi_setup(struct spi_device *spi) +@@ -420,48 +755,6 @@ static int bcm2708_spi_setup(struct spi_device *spi) return 0; } @@ -780,7 +803,7 @@ index 088cbaa..661a4cb 100644 static void bcm2708_spi_cleanup(struct spi_device *spi) { if (spi->controller_state) { -@@ -451,6 +765,7 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) +@@ -477,6 +770,7 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) struct clk *clk; struct spi_master *master; struct bcm2708_spi *bs; @@ -788,7 +811,7 @@ index 088cbaa..661a4cb 100644 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) { -@@ -484,40 +799,75 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) +@@ -510,16 +804,25 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) master->bus_num = pdev->id; master->num_chipselect = 3; master->setup = bcm2708_spi_setup; @@ -802,23 +825,23 @@ index 088cbaa..661a4cb 100644 + platform_set_drvdata(pdev, master); -- bs = spi_master_get_devdata(master); - -+ bs = spi_master_get_devdata(master); + bs = spi_master_get_devdata(master); +- spin_lock_init(&bs->lock); - INIT_LIST_HEAD(&bs->queue); init_completion(&bs->done); - INIT_WORK(&bs->work, bcm2708_work); - ++ + /* set counters */ + bs->transfers_polling=0; + bs->transfers_irqdriven=0; + bs->transfers_dmadriven=0; + + /* get Register Map */ + bs->base = ioremap(regs->start, resource_size(regs)); if (!bs->base) { - dev_err(&pdev->dev, "could not remap memory\n"); +@@ -527,21 +830,46 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) goto out_master_put; } @@ -872,11 +895,8 @@ index 088cbaa..661a4cb 100644 + goto out_free_dma_tx; } -+ /* initialise the hardware */ - clk_enable(clk); - bcm2708_wr(bs, SPI_CS, SPI_CS_REN | SPI_CS_CLEAR_RX | SPI_CS_CLEAR_TX); -@@ -525,18 +875,35 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) +@@ -551,18 +879,36 @@ static int __devinit bcm2708_spi_probe(struct platform_device *pdev) err = spi_register_master(master); if (err) { dev_err(&pdev->dev, "could not register SPI master: %d\n", err); @@ -900,7 +920,7 @@ index 088cbaa..661a4cb 100644 + } + dev_info(&pdev->dev, "SPI Controller running in %s mode\n",mode); return 0; -- + +out_free_dma_irq: + free_irq(bs->dma_rx.irq, master); +out_free_dma_tx: @@ -916,7 +936,7 @@ index 088cbaa..661a4cb 100644 out_iounmap: iounmap(bs->base); out_master_put: -@@ -551,19 +918,29 @@ static int __devexit bcm2708_spi_remove(struct platform_device *pdev) +@@ -577,19 +923,29 @@ static int __devexit bcm2708_spi_remove(struct platform_device *pdev) struct spi_master *master = platform_get_drvdata(pdev); struct bcm2708_spi *bs = spi_master_get_devdata(master); @@ -950,18 +970,18 @@ index 088cbaa..661a4cb 100644 spi_unregister_master(master); return 0; -@@ -581,6 +958,10 @@ static struct platform_driver bcm2708_spi_driver = { +@@ -607,6 +963,10 @@ static struct platform_driver bcm2708_spi_driver = { static int __init bcm2708_spi_init(void) { -+ /* range check for processmode */ -+ if ((processmode<0) || (processmode>3)) { -+ processmode=1; ++ /* range check for processmode */ ++ if ((processmode<0) || (processmode>3)) { ++ processmode=1; + } return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe); } module_init(bcm2708_spi_init); -@@ -591,10 +972,9 @@ static void __exit bcm2708_spi_exit(void) +@@ -617,10 +977,9 @@ static void __exit bcm2708_spi_exit(void) } module_exit(bcm2708_spi_exit);