123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767 |
- /*
- * Driver for Microchip MRF24J40 802.15.4 Wireless-PAN Networking controller
- *
- * Copyright (C) 2012 Alan Ott <alan@signal11.us>
- * Signal 11 Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <linux/spi/spi.h>
- #include <linux/interrupt.h>
- #include <linux/module.h>
- #include <net/wpan-phy.h>
- #include <net/mac802154.h>
- /* MRF24J40 Short Address Registers */
- #define REG_RXMCR 0x00 /* Receive MAC control */
- #define REG_PANIDL 0x01 /* PAN ID (low) */
- #define REG_PANIDH 0x02 /* PAN ID (high) */
- #define REG_SADRL 0x03 /* Short address (low) */
- #define REG_SADRH 0x04 /* Short address (high) */
- #define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */
- #define REG_TXMCR 0x11 /* Transmit MAC control */
- #define REG_PACON0 0x16 /* Power Amplifier Control */
- #define REG_PACON1 0x17 /* Power Amplifier Control */
- #define REG_PACON2 0x18 /* Power Amplifier Control */
- #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
- #define REG_TXSTAT 0x24 /* TX MAC Status Register */
- #define REG_SOFTRST 0x2A /* Soft Reset */
- #define REG_TXSTBL 0x2E /* TX Stabilization */
- #define REG_INTSTAT 0x31 /* Interrupt Status */
- #define REG_INTCON 0x32 /* Interrupt Control */
- #define REG_RFCTL 0x36 /* RF Control Mode Register */
- #define REG_BBREG1 0x39 /* Baseband Registers */
- #define REG_BBREG2 0x3A /* */
- #define REG_BBREG6 0x3E /* */
- #define REG_CCAEDTH 0x3F /* Energy Detection Threshold */
- /* MRF24J40 Long Address Registers */
- #define REG_RFCON0 0x200 /* RF Control Registers */
- #define REG_RFCON1 0x201
- #define REG_RFCON2 0x202
- #define REG_RFCON3 0x203
- #define REG_RFCON5 0x205
- #define REG_RFCON6 0x206
- #define REG_RFCON7 0x207
- #define REG_RFCON8 0x208
- #define REG_RSSI 0x210
- #define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */
- #define REG_SLPCON1 0x220
- #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
- #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
- #define REG_RX_FIFO 0x300 /* Receive FIFO */
- /* Device configuration: Only channels 11-26 on page 0 are supported. */
- #define MRF24J40_CHAN_MIN 11
- #define MRF24J40_CHAN_MAX 26
- #define CHANNEL_MASK (((u32)1 << (MRF24J40_CHAN_MAX + 1)) \
- - ((u32)1 << MRF24J40_CHAN_MIN))
- #define TX_FIFO_SIZE 128 /* From datasheet */
- #define RX_FIFO_SIZE 144 /* From datasheet */
- #define SET_CHANNEL_DELAY_US 192 /* From datasheet */
- /* Device Private Data */
- struct mrf24j40 {
- struct spi_device *spi;
- struct ieee802154_dev *dev;
- struct mutex buffer_mutex; /* only used to protect buf */
- struct completion tx_complete;
- struct work_struct irqwork;
- u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */
- };
- /* Read/Write SPI Commands for Short and Long Address registers. */
- #define MRF24J40_READSHORT(reg) ((reg) << 1)
- #define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1)
- #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
- #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
- /* Maximum speed to run the device at. TODO: Get the real max value from
- * someone at Microchip since it isn't in the datasheet. */
- #define MAX_SPI_SPEED_HZ 1000000
- #define printdev(X) (&X->spi->dev)
- static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value)
- {
- int ret;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = MRF24J40_WRITESHORT(reg);
- devrec->buf[1] = value;
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI write Failed for short register 0x%hhx\n", reg);
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
- }
- static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val)
- {
- int ret = -1;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = MRF24J40_READSHORT(reg);
- devrec->buf[1] = 0;
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI read Failed for short register 0x%hhx\n", reg);
- else
- *val = devrec->buf[1];
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
- }
- static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
- {
- int ret;
- u16 cmd;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 3,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- cmd = MRF24J40_READLONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- devrec->buf[2] = 0;
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI read Failed for long register 0x%hx\n", reg);
- else
- *value = devrec->buf[2];
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
- }
- static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
- {
- int ret;
- u16 cmd;
- struct spi_message msg;
- struct spi_transfer xfer = {
- .len = 3,
- .tx_buf = devrec->buf,
- .rx_buf = devrec->buf,
- };
- spi_message_init(&msg);
- spi_message_add_tail(&xfer, &msg);
- cmd = MRF24J40_WRITELONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- devrec->buf[2] = val;
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec),
- "SPI write Failed for long register 0x%hx\n", reg);
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
- }
- /* This function relies on an undocumented write method. Once a write command
- and address is set, as many bytes of data as desired can be clocked into
- the device. The datasheet only shows setting one byte at a time. */
- static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
- const u8 *data, size_t length)
- {
- int ret;
- u16 cmd;
- u8 lengths[2];
- struct spi_message msg;
- struct spi_transfer addr_xfer = {
- .len = 2,
- .tx_buf = devrec->buf,
- };
- struct spi_transfer lengths_xfer = {
- .len = 2,
- .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */
- };
- struct spi_transfer data_xfer = {
- .len = length,
- .tx_buf = data,
- };
- /* Range check the length. 2 bytes are used for the length fields.*/
- if (length > TX_FIFO_SIZE-2) {
- dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n");
- length = TX_FIFO_SIZE-2;
- }
- spi_message_init(&msg);
- spi_message_add_tail(&addr_xfer, &msg);
- spi_message_add_tail(&lengths_xfer, &msg);
- spi_message_add_tail(&data_xfer, &msg);
- cmd = MRF24J40_WRITELONG(reg);
- mutex_lock(&devrec->buffer_mutex);
- devrec->buf[0] = cmd >> 8 & 0xff;
- devrec->buf[1] = cmd & 0xff;
- lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
- lengths[1] = length; /* Total length */
- ret = spi_sync(devrec->spi, &msg);
- if (ret)
- dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
- mutex_unlock(&devrec->buffer_mutex);
- return ret;
- }
- static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
- u8 *data, u8 *len, u8 *lqi)
- {
- u8 rx_len;
- u8 addr[2];
- u8 lqi_rssi[2];
- u16 cmd;
- int ret;
- struct spi_message msg;
- struct spi_transfer addr_xfer = {
- .len = 2,
- .tx_buf = &addr,
- };
- struct spi_transfer data_xfer = {
- .len = 0x0, /* set below */
- .rx_buf = data,
- };
- struct spi_transfer status_xfer = {
- .len = 2,
- .rx_buf = &lqi_rssi,
- };
- /* Get the length of the data in the RX FIFO. The length in this
- * register exclues the 1-byte length field at the beginning. */
- ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len);
- if (ret)
- goto out;
- /* Range check the RX FIFO length, accounting for the one-byte
- * length field at the begining. */
- if (rx_len > RX_FIFO_SIZE-1) {
- dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n");
- rx_len = RX_FIFO_SIZE-1;
- }
- if (rx_len > *len) {
- /* Passed in buffer wasn't big enough. Should never happen. */
- dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n");
- rx_len = *len;
- }
- /* Set up the commands to read the data. */
- cmd = MRF24J40_READLONG(REG_RX_FIFO+1);
- addr[0] = cmd >> 8 & 0xff;
- addr[1] = cmd & 0xff;
- data_xfer.len = rx_len;
- spi_message_init(&msg);
- spi_message_add_tail(&addr_xfer, &msg);
- spi_message_add_tail(&data_xfer, &msg);
- spi_message_add_tail(&status_xfer, &msg);
- ret = spi_sync(devrec->spi, &msg);
- if (ret) {
- dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n");
- goto out;
- }
- *lqi = lqi_rssi[0];
- *len = rx_len;
- #ifdef DEBUG
- print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
- DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
- printk(KERN_DEBUG "mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
- lqi_rssi[0], lqi_rssi[1]);
- #endif
- out:
- return ret;
- }
- static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
- {
- struct mrf24j40 *devrec = dev->priv;
- u8 val;
- int ret = 0;
- dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
- ret = write_tx_buf(devrec, 0x000, skb->data, skb->len);
- if (ret)
- goto err;
- /* Set TXNTRIG bit of TXNCON to send packet */
- ret = read_short_reg(devrec, REG_TXNCON, &val);
- if (ret)
- goto err;
- val |= 0x1;
- val &= ~0x4;
- write_short_reg(devrec, REG_TXNCON, val);
- INIT_COMPLETION(devrec->tx_complete);
- /* Wait for the device to send the TX complete interrupt. */
- ret = wait_for_completion_interruptible_timeout(
- &devrec->tx_complete,
- 5 * HZ);
- if (ret == -ERESTARTSYS)
- goto err;
- if (ret == 0) {
- ret = -ETIMEDOUT;
- goto err;
- }
- /* Check for send error from the device. */
- ret = read_short_reg(devrec, REG_TXSTAT, &val);
- if (ret)
- goto err;
- if (val & 0x1) {
- dev_err(printdev(devrec), "Error Sending. Retry count exceeded\n");
- ret = -ECOMM; /* TODO: Better error code ? */
- } else
- dev_dbg(printdev(devrec), "Packet Sent\n");
- err:
- return ret;
- }
- static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
- {
- /* TODO: */
- printk(KERN_WARNING "mrf24j40: ed not implemented\n");
- *level = 0;
- return 0;
- }
- static int mrf24j40_start(struct ieee802154_dev *dev)
- {
- struct mrf24j40 *devrec = dev->priv;
- u8 val;
- int ret;
- dev_dbg(printdev(devrec), "start\n");
- ret = read_short_reg(devrec, REG_INTCON, &val);
- if (ret)
- return ret;
- val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */
- write_short_reg(devrec, REG_INTCON, val);
- return 0;
- }
- static void mrf24j40_stop(struct ieee802154_dev *dev)
- {
- struct mrf24j40 *devrec = dev->priv;
- u8 val;
- int ret;
- dev_dbg(printdev(devrec), "stop\n");
- ret = read_short_reg(devrec, REG_INTCON, &val);
- if (ret)
- return;
- val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
- write_short_reg(devrec, REG_INTCON, val);
- return;
- }
- static int mrf24j40_set_channel(struct ieee802154_dev *dev,
- int page, int channel)
- {
- struct mrf24j40 *devrec = dev->priv;
- u8 val;
- int ret;
- dev_dbg(printdev(devrec), "Set Channel %d\n", channel);
- WARN_ON(page != 0);
- WARN_ON(channel < MRF24J40_CHAN_MIN);
- WARN_ON(channel > MRF24J40_CHAN_MAX);
- /* Set Channel TODO */
- val = (channel-11) << 4 | 0x03;
- write_long_reg(devrec, REG_RFCON0, val);
- /* RF Reset */
- ret = read_short_reg(devrec, REG_RFCTL, &val);
- if (ret)
- return ret;
- val |= 0x04;
- write_short_reg(devrec, REG_RFCTL, val);
- val &= ~0x04;
- write_short_reg(devrec, REG_RFCTL, val);
- udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
- return 0;
- }
- static int mrf24j40_filter(struct ieee802154_dev *dev,
- struct ieee802154_hw_addr_filt *filt,
- unsigned long changed)
- {
- struct mrf24j40 *devrec = dev->priv;
- dev_dbg(printdev(devrec), "filter\n");
- if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
- /* Short Addr */
- u8 addrh, addrl;
- addrh = filt->short_addr >> 8 & 0xff;
- addrl = filt->short_addr & 0xff;
- write_short_reg(devrec, REG_SADRH, addrh);
- write_short_reg(devrec, REG_SADRL, addrl);
- dev_dbg(printdev(devrec),
- "Set short addr to %04hx\n", filt->short_addr);
- }
- if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
- /* Device Address */
- int i;
- for (i = 0; i < 8; i++)
- write_short_reg(devrec, REG_EADR0+i,
- filt->ieee_addr[i]);
- #ifdef DEBUG
- printk(KERN_DEBUG "Set long addr to: ");
- for (i = 0; i < 8; i++)
- printk("%02hhx ", filt->ieee_addr[i]);
- printk(KERN_DEBUG "\n");
- #endif
- }
- if (changed & IEEE802515_AFILT_PANID_CHANGED) {
- /* PAN ID */
- u8 panidl, panidh;
- panidh = filt->pan_id >> 8 & 0xff;
- panidl = filt->pan_id & 0xff;
- write_short_reg(devrec, REG_PANIDH, panidh);
- write_short_reg(devrec, REG_PANIDL, panidl);
- dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
- }
- if (changed & IEEE802515_AFILT_PANC_CHANGED) {
- /* Pan Coordinator */
- u8 val;
- int ret;
- ret = read_short_reg(devrec, REG_RXMCR, &val);
- if (ret)
- return ret;
- if (filt->pan_coord)
- val |= 0x8;
- else
- val &= ~0x8;
- write_short_reg(devrec, REG_RXMCR, val);
- /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
- * REG_ORDER is maintained as default (no beacon/superframe).
- */
- dev_dbg(printdev(devrec), "Set Pan Coord to %s\n",
- filt->pan_coord ? "on" : "off");
- }
- return 0;
- }
- static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
- {
- u8 len = RX_FIFO_SIZE;
- u8 lqi = 0;
- u8 val;
- int ret = 0;
- struct sk_buff *skb;
- /* Turn off reception of packets off the air. This prevents the
- * device from overwriting the buffer while we're reading it. */
- ret = read_short_reg(devrec, REG_BBREG1, &val);
- if (ret)
- goto out;
- val |= 4; /* SET RXDECINV */
- write_short_reg(devrec, REG_BBREG1, val);
- skb = alloc_skb(len, GFP_KERNEL);
- if (!skb) {
- ret = -ENOMEM;
- goto out;
- }
- ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi);
- if (ret < 0) {
- dev_err(printdev(devrec), "Failure reading RX FIFO\n");
- kfree_skb(skb);
- ret = -EINVAL;
- goto out;
- }
- /* Cut off the checksum */
- skb_trim(skb, len-2);
- /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
- * also from a workqueue). I think irqsafe is not necessary here.
- * Can someone confirm? */
- ieee802154_rx_irqsafe(devrec->dev, skb, lqi);
- dev_dbg(printdev(devrec), "RX Handled\n");
- out:
- /* Turn back on reception of packets off the air. */
- ret = read_short_reg(devrec, REG_BBREG1, &val);
- if (ret)
- return ret;
- val &= ~0x4; /* Clear RXDECINV */
- write_short_reg(devrec, REG_BBREG1, val);
- return ret;
- }
- static struct ieee802154_ops mrf24j40_ops = {
- .owner = THIS_MODULE,
- .xmit = mrf24j40_tx,
- .ed = mrf24j40_ed,
- .start = mrf24j40_start,
- .stop = mrf24j40_stop,
- .set_channel = mrf24j40_set_channel,
- .set_hw_addr_filt = mrf24j40_filter,
- };
- static irqreturn_t mrf24j40_isr(int irq, void *data)
- {
- struct mrf24j40 *devrec = data;
- disable_irq_nosync(irq);
- schedule_work(&devrec->irqwork);
- return IRQ_HANDLED;
- }
- static void mrf24j40_isrwork(struct work_struct *work)
- {
- struct mrf24j40 *devrec = container_of(work, struct mrf24j40, irqwork);
- u8 intstat;
- int ret;
- /* Read the interrupt status */
- ret = read_short_reg(devrec, REG_INTSTAT, &intstat);
- if (ret)
- goto out;
- /* Check for TX complete */
- if (intstat & 0x1)
- complete(&devrec->tx_complete);
- /* Check for Rx */
- if (intstat & 0x8)
- mrf24j40_handle_rx(devrec);
- out:
- enable_irq(devrec->spi->irq);
- }
- static int mrf24j40_probe(struct spi_device *spi)
- {
- int ret = -ENOMEM;
- u8 val;
- struct mrf24j40 *devrec;
- printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq);
- devrec = kzalloc(sizeof(struct mrf24j40), GFP_KERNEL);
- if (!devrec)
- goto err_devrec;
- devrec->buf = kzalloc(3, GFP_KERNEL);
- if (!devrec->buf)
- goto err_buf;
- spi->mode = SPI_MODE_0; /* TODO: Is this appropriate for right here? */
- if (spi->max_speed_hz > MAX_SPI_SPEED_HZ)
- spi->max_speed_hz = MAX_SPI_SPEED_HZ;
- mutex_init(&devrec->buffer_mutex);
- init_completion(&devrec->tx_complete);
- INIT_WORK(&devrec->irqwork, mrf24j40_isrwork);
- devrec->spi = spi;
- dev_set_drvdata(&spi->dev, devrec);
- /* Register with the 802154 subsystem */
- devrec->dev = ieee802154_alloc_device(0, &mrf24j40_ops);
- if (!devrec->dev)
- goto err_alloc_dev;
- devrec->dev->priv = devrec;
- devrec->dev->parent = &devrec->spi->dev;
- devrec->dev->phy->channels_supported[0] = CHANNEL_MASK;
- devrec->dev->flags = IEEE802154_HW_OMIT_CKSUM|IEEE802154_HW_AACK;
- dev_dbg(printdev(devrec), "registered mrf24j40\n");
- ret = ieee802154_register_device(devrec->dev);
- if (ret)
- goto err_register_device;
- /* Initialize the device.
- From datasheet section 3.2: Initialization. */
- write_short_reg(devrec, REG_SOFTRST, 0x07);
- write_short_reg(devrec, REG_PACON2, 0x98);
- write_short_reg(devrec, REG_TXSTBL, 0x95);
- write_long_reg(devrec, REG_RFCON0, 0x03);
- write_long_reg(devrec, REG_RFCON1, 0x01);
- write_long_reg(devrec, REG_RFCON2, 0x80);
- write_long_reg(devrec, REG_RFCON6, 0x90);
- write_long_reg(devrec, REG_RFCON7, 0x80);
- write_long_reg(devrec, REG_RFCON8, 0x10);
- write_long_reg(devrec, REG_SLPCON1, 0x21);
- write_short_reg(devrec, REG_BBREG2, 0x80);
- write_short_reg(devrec, REG_CCAEDTH, 0x60);
- write_short_reg(devrec, REG_BBREG6, 0x40);
- write_short_reg(devrec, REG_RFCTL, 0x04);
- write_short_reg(devrec, REG_RFCTL, 0x0);
- udelay(192);
- /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
- ret = read_short_reg(devrec, REG_RXMCR, &val);
- if (ret)
- goto err_read_reg;
- val &= ~0x3; /* Clear RX mode (normal) */
- write_short_reg(devrec, REG_RXMCR, val);
- ret = request_irq(spi->irq,
- mrf24j40_isr,
- IRQF_TRIGGER_FALLING,
- dev_name(&spi->dev),
- devrec);
- if (ret) {
- dev_err(printdev(devrec), "Unable to get IRQ");
- goto err_irq;
- }
- return 0;
- err_irq:
- err_read_reg:
- ieee802154_unregister_device(devrec->dev);
- err_register_device:
- ieee802154_free_device(devrec->dev);
- err_alloc_dev:
- kfree(devrec->buf);
- err_buf:
- kfree(devrec);
- err_devrec:
- return ret;
- }
- static int mrf24j40_remove(struct spi_device *spi)
- {
- struct mrf24j40 *devrec = dev_get_drvdata(&spi->dev);
- dev_dbg(printdev(devrec), "remove\n");
- free_irq(spi->irq, devrec);
- flush_work(&devrec->irqwork); /* TODO: Is this the right call? */
- ieee802154_unregister_device(devrec->dev);
- ieee802154_free_device(devrec->dev);
- /* TODO: Will ieee802154_free_device() wait until ->xmit() is
- * complete? */
- /* Clean up the SPI stuff. */
- dev_set_drvdata(&spi->dev, NULL);
- kfree(devrec->buf);
- kfree(devrec);
- return 0;
- }
- static const struct spi_device_id mrf24j40_ids[] = {
- { "mrf24j40", 0 },
- { "mrf24j40ma", 0 },
- { },
- };
- MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
- static struct spi_driver mrf24j40_driver = {
- .driver = {
- .name = "mrf24j40",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
- .id_table = mrf24j40_ids,
- .probe = mrf24j40_probe,
- .remove = mrf24j40_remove,
- };
- static int __init mrf24j40_init(void)
- {
- return spi_register_driver(&mrf24j40_driver);
- }
- static void __exit mrf24j40_exit(void)
- {
- spi_unregister_driver(&mrf24j40_driver);
- }
- module_init(mrf24j40_init);
- module_exit(mrf24j40_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Alan Ott");
- MODULE_DESCRIPTION("MRF24J40 SPI 802.15.4 Controller Driver");
|