linux/drivers/net/ieee802154/cc2520.c
<<
>>
Prefs
   1/* Driver for TI CC2520 802.15.4 Wireless-PAN Networking controller
   2 *
   3 * Copyright (C) 2014 Varka Bhadram <varkab@cdac.in>
   4 *                    Md.Jamal Mohiuddin <mjmohiuddin@cdac.in>
   5 *                    P Sowjanya <sowjanyap@cdac.in>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License as published by
   9 * the Free Software Foundation; either version 2 of the License, or
  10 * (at your option) any later version.
  11 *
  12 */
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/gpio.h>
  16#include <linux/delay.h>
  17#include <linux/spi/spi.h>
  18#include <linux/spi/cc2520.h>
  19#include <linux/workqueue.h>
  20#include <linux/interrupt.h>
  21#include <linux/skbuff.h>
  22#include <linux/of_gpio.h>
  23#include <linux/ieee802154.h>
  24#include <linux/crc-ccitt.h>
  25#include <asm/unaligned.h>
  26
  27#include <net/mac802154.h>
  28#include <net/cfg802154.h>
  29
  30#define SPI_COMMAND_BUFFER      3
  31#define HIGH                    1
  32#define LOW                     0
  33#define STATE_IDLE              0
  34#define RSSI_VALID              0
  35#define RSSI_OFFSET             78
  36
  37#define CC2520_RAM_SIZE         640
  38#define CC2520_FIFO_SIZE        128
  39
  40#define CC2520RAM_TXFIFO        0x100
  41#define CC2520RAM_RXFIFO        0x180
  42#define CC2520RAM_IEEEADDR      0x3EA
  43#define CC2520RAM_PANID         0x3F2
  44#define CC2520RAM_SHORTADDR     0x3F4
  45
  46#define CC2520_FREG_MASK        0x3F
  47
  48/* status byte values */
  49#define CC2520_STATUS_XOSC32M_STABLE    BIT(7)
  50#define CC2520_STATUS_RSSI_VALID        BIT(6)
  51#define CC2520_STATUS_TX_UNDERFLOW      BIT(3)
  52
  53/* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
  54#define CC2520_MINCHANNEL               11
  55#define CC2520_MAXCHANNEL               26
  56#define CC2520_CHANNEL_SPACING          5
  57
  58/* command strobes */
  59#define CC2520_CMD_SNOP                 0x00
  60#define CC2520_CMD_IBUFLD               0x02
  61#define CC2520_CMD_SIBUFEX              0x03
  62#define CC2520_CMD_SSAMPLECCA           0x04
  63#define CC2520_CMD_SRES                 0x0f
  64#define CC2520_CMD_MEMORY_MASK          0x0f
  65#define CC2520_CMD_MEMORY_READ          0x10
  66#define CC2520_CMD_MEMORY_WRITE         0x20
  67#define CC2520_CMD_RXBUF                0x30
  68#define CC2520_CMD_RXBUFCP              0x38
  69#define CC2520_CMD_RXBUFMOV             0x32
  70#define CC2520_CMD_TXBUF                0x3A
  71#define CC2520_CMD_TXBUFCP              0x3E
  72#define CC2520_CMD_RANDOM               0x3C
  73#define CC2520_CMD_SXOSCON              0x40
  74#define CC2520_CMD_STXCAL               0x41
  75#define CC2520_CMD_SRXON                0x42
  76#define CC2520_CMD_STXON                0x43
  77#define CC2520_CMD_STXONCCA             0x44
  78#define CC2520_CMD_SRFOFF               0x45
  79#define CC2520_CMD_SXOSCOFF             0x46
  80#define CC2520_CMD_SFLUSHRX             0x47
  81#define CC2520_CMD_SFLUSHTX             0x48
  82#define CC2520_CMD_SACK                 0x49
  83#define CC2520_CMD_SACKPEND             0x4A
  84#define CC2520_CMD_SNACK                0x4B
  85#define CC2520_CMD_SRXMASKBITSET        0x4C
  86#define CC2520_CMD_SRXMASKBITCLR        0x4D
  87#define CC2520_CMD_RXMASKAND            0x4E
  88#define CC2520_CMD_RXMASKOR             0x4F
  89#define CC2520_CMD_MEMCP                0x50
  90#define CC2520_CMD_MEMCPR               0x52
  91#define CC2520_CMD_MEMXCP               0x54
  92#define CC2520_CMD_MEMXWR               0x56
  93#define CC2520_CMD_BCLR                 0x58
  94#define CC2520_CMD_BSET                 0x59
  95#define CC2520_CMD_CTR_UCTR             0x60
  96#define CC2520_CMD_CBCMAC               0x64
  97#define CC2520_CMD_UCBCMAC              0x66
  98#define CC2520_CMD_CCM                  0x68
  99#define CC2520_CMD_UCCM                 0x6A
 100#define CC2520_CMD_ECB                  0x70
 101#define CC2520_CMD_ECBO                 0x72
 102#define CC2520_CMD_ECBX                 0x74
 103#define CC2520_CMD_INC                  0x78
 104#define CC2520_CMD_ABORT                0x7F
 105#define CC2520_CMD_REGISTER_READ        0x80
 106#define CC2520_CMD_REGISTER_WRITE       0xC0
 107
 108/* status registers */
 109#define CC2520_CHIPID                   0x40
 110#define CC2520_VERSION                  0x42
 111#define CC2520_EXTCLOCK                 0x44
 112#define CC2520_MDMCTRL0                 0x46
 113#define CC2520_MDMCTRL1                 0x47
 114#define CC2520_FREQEST                  0x48
 115#define CC2520_RXCTRL                   0x4A
 116#define CC2520_FSCTRL                   0x4C
 117#define CC2520_FSCAL0                   0x4E
 118#define CC2520_FSCAL1                   0x4F
 119#define CC2520_FSCAL2                   0x50
 120#define CC2520_FSCAL3                   0x51
 121#define CC2520_AGCCTRL0                 0x52
 122#define CC2520_AGCCTRL1                 0x53
 123#define CC2520_AGCCTRL2                 0x54
 124#define CC2520_AGCCTRL3                 0x55
 125#define CC2520_ADCTEST0                 0x56
 126#define CC2520_ADCTEST1                 0x57
 127#define CC2520_ADCTEST2                 0x58
 128#define CC2520_MDMTEST0                 0x5A
 129#define CC2520_MDMTEST1                 0x5B
 130#define CC2520_DACTEST0                 0x5C
 131#define CC2520_DACTEST1                 0x5D
 132#define CC2520_ATEST                    0x5E
 133#define CC2520_DACTEST2                 0x5F
 134#define CC2520_PTEST0                   0x60
 135#define CC2520_PTEST1                   0x61
 136#define CC2520_RESERVED                 0x62
 137#define CC2520_DPUBIST                  0x7A
 138#define CC2520_ACTBIST                  0x7C
 139#define CC2520_RAMBIST                  0x7E
 140
 141/* frame registers */
 142#define CC2520_FRMFILT0                 0x00
 143#define CC2520_FRMFILT1                 0x01
 144#define CC2520_SRCMATCH                 0x02
 145#define CC2520_SRCSHORTEN0              0x04
 146#define CC2520_SRCSHORTEN1              0x05
 147#define CC2520_SRCSHORTEN2              0x06
 148#define CC2520_SRCEXTEN0                0x08
 149#define CC2520_SRCEXTEN1                0x09
 150#define CC2520_SRCEXTEN2                0x0A
 151#define CC2520_FRMCTRL0                 0x0C
 152#define CC2520_FRMCTRL1                 0x0D
 153#define CC2520_RXENABLE0                0x0E
 154#define CC2520_RXENABLE1                0x0F
 155#define CC2520_EXCFLAG0                 0x10
 156#define CC2520_EXCFLAG1                 0x11
 157#define CC2520_EXCFLAG2                 0x12
 158#define CC2520_EXCMASKA0                0x14
 159#define CC2520_EXCMASKA1                0x15
 160#define CC2520_EXCMASKA2                0x16
 161#define CC2520_EXCMASKB0                0x18
 162#define CC2520_EXCMASKB1                0x19
 163#define CC2520_EXCMASKB2                0x1A
 164#define CC2520_EXCBINDX0                0x1C
 165#define CC2520_EXCBINDX1                0x1D
 166#define CC2520_EXCBINDY0                0x1E
 167#define CC2520_EXCBINDY1                0x1F
 168#define CC2520_GPIOCTRL0                0x20
 169#define CC2520_GPIOCTRL1                0x21
 170#define CC2520_GPIOCTRL2                0x22
 171#define CC2520_GPIOCTRL3                0x23
 172#define CC2520_GPIOCTRL4                0x24
 173#define CC2520_GPIOCTRL5                0x25
 174#define CC2520_GPIOPOLARITY             0x26
 175#define CC2520_GPIOCTRL                 0x28
 176#define CC2520_DPUCON                   0x2A
 177#define CC2520_DPUSTAT                  0x2C
 178#define CC2520_FREQCTRL                 0x2E
 179#define CC2520_FREQTUNE                 0x2F
 180#define CC2520_TXPOWER                  0x30
 181#define CC2520_TXCTRL                   0x31
 182#define CC2520_FSMSTAT0                 0x32
 183#define CC2520_FSMSTAT1                 0x33
 184#define CC2520_FIFOPCTRL                0x34
 185#define CC2520_FSMCTRL                  0x35
 186#define CC2520_CCACTRL0                 0x36
 187#define CC2520_CCACTRL1                 0x37
 188#define CC2520_RSSI                     0x38
 189#define CC2520_RSSISTAT                 0x39
 190#define CC2520_RXFIRST                  0x3C
 191#define CC2520_RXFIFOCNT                0x3E
 192#define CC2520_TXFIFOCNT                0x3F
 193
 194/* CC2520_FRMFILT0 */
 195#define FRMFILT0_FRAME_FILTER_EN        BIT(0)
 196#define FRMFILT0_PAN_COORDINATOR        BIT(1)
 197
 198/* CC2520_FRMCTRL0 */
 199#define FRMCTRL0_AUTOACK                BIT(5)
 200#define FRMCTRL0_AUTOCRC                BIT(6)
 201
 202/* CC2520_FRMCTRL1 */
 203#define FRMCTRL1_SET_RXENMASK_ON_TX     BIT(0)
 204#define FRMCTRL1_IGNORE_TX_UNDERF       BIT(1)
 205
 206/* Driver private information */
 207struct cc2520_private {
 208        struct spi_device *spi;         /* SPI device structure */
 209        struct ieee802154_hw *hw;       /* IEEE-802.15.4 device */
 210        u8 *buf;                        /* SPI TX/Rx data buffer */
 211        struct mutex buffer_mutex;      /* SPI buffer mutex */
 212        bool is_tx;                     /* Flag for sync b/w Tx and Rx */
 213        bool amplified;                 /* Flag for CC2591 */
 214        int fifo_pin;                   /* FIFO GPIO pin number */
 215        struct work_struct fifop_irqwork;/* Workqueue for FIFOP */
 216        spinlock_t lock;                /* Lock for is_tx*/
 217        struct completion tx_complete;  /* Work completion for Tx */
 218        bool promiscuous;               /* Flag for promiscuous mode */
 219};
 220
 221/* Generic Functions */
 222static int
 223cc2520_cmd_strobe(struct cc2520_private *priv, u8 cmd)
 224{
 225        int ret;
 226        u8 status = 0xff;
 227        struct spi_message msg;
 228        struct spi_transfer xfer = {
 229                .len = 0,
 230                .tx_buf = priv->buf,
 231                .rx_buf = priv->buf,
 232        };
 233
 234        spi_message_init(&msg);
 235        spi_message_add_tail(&xfer, &msg);
 236
 237        mutex_lock(&priv->buffer_mutex);
 238        priv->buf[xfer.len++] = cmd;
 239        dev_vdbg(&priv->spi->dev,
 240                 "command strobe buf[0] = %02x\n",
 241                 priv->buf[0]);
 242
 243        ret = spi_sync(priv->spi, &msg);
 244        if (!ret)
 245                status = priv->buf[0];
 246        dev_vdbg(&priv->spi->dev,
 247                 "buf[0] = %02x\n", priv->buf[0]);
 248        mutex_unlock(&priv->buffer_mutex);
 249
 250        return ret;
 251}
 252
 253static int
 254cc2520_get_status(struct cc2520_private *priv, u8 *status)
 255{
 256        int ret;
 257        struct spi_message msg;
 258        struct spi_transfer xfer = {
 259                .len = 0,
 260                .tx_buf = priv->buf,
 261                .rx_buf = priv->buf,
 262        };
 263
 264        spi_message_init(&msg);
 265        spi_message_add_tail(&xfer, &msg);
 266
 267        mutex_lock(&priv->buffer_mutex);
 268        priv->buf[xfer.len++] = CC2520_CMD_SNOP;
 269        dev_vdbg(&priv->spi->dev,
 270                 "get status command buf[0] = %02x\n", priv->buf[0]);
 271
 272        ret = spi_sync(priv->spi, &msg);
 273        if (!ret)
 274                *status = priv->buf[0];
 275        dev_vdbg(&priv->spi->dev,
 276                 "buf[0] = %02x\n", priv->buf[0]);
 277        mutex_unlock(&priv->buffer_mutex);
 278
 279        return ret;
 280}
 281
 282static int
 283cc2520_write_register(struct cc2520_private *priv, u8 reg, u8 value)
 284{
 285        int status;
 286        struct spi_message msg;
 287        struct spi_transfer xfer = {
 288                .len = 0,
 289                .tx_buf = priv->buf,
 290                .rx_buf = priv->buf,
 291        };
 292
 293        spi_message_init(&msg);
 294        spi_message_add_tail(&xfer, &msg);
 295
 296        mutex_lock(&priv->buffer_mutex);
 297
 298        if (reg <= CC2520_FREG_MASK) {
 299                priv->buf[xfer.len++] = CC2520_CMD_REGISTER_WRITE | reg;
 300                priv->buf[xfer.len++] = value;
 301        } else {
 302                priv->buf[xfer.len++] = CC2520_CMD_MEMORY_WRITE;
 303                priv->buf[xfer.len++] = reg;
 304                priv->buf[xfer.len++] = value;
 305        }
 306        status = spi_sync(priv->spi, &msg);
 307        if (msg.status)
 308                status = msg.status;
 309
 310        mutex_unlock(&priv->buffer_mutex);
 311
 312        return status;
 313}
 314
 315static int
 316cc2520_write_ram(struct cc2520_private *priv, u16 reg, u8 len, u8 *data)
 317{
 318        int status;
 319        struct spi_message msg;
 320        struct spi_transfer xfer_head = {
 321                .len        = 0,
 322                .tx_buf        = priv->buf,
 323                .rx_buf        = priv->buf,
 324        };
 325
 326        struct spi_transfer xfer_buf = {
 327                .len = len,
 328                .tx_buf = data,
 329        };
 330
 331        mutex_lock(&priv->buffer_mutex);
 332        priv->buf[xfer_head.len++] = (CC2520_CMD_MEMORY_WRITE |
 333                                                ((reg >> 8) & 0xff));
 334        priv->buf[xfer_head.len++] = reg & 0xff;
 335
 336        spi_message_init(&msg);
 337        spi_message_add_tail(&xfer_head, &msg);
 338        spi_message_add_tail(&xfer_buf, &msg);
 339
 340        status = spi_sync(priv->spi, &msg);
 341        dev_dbg(&priv->spi->dev, "spi status = %d\n", status);
 342        if (msg.status)
 343                status = msg.status;
 344
 345        mutex_unlock(&priv->buffer_mutex);
 346        return status;
 347}
 348
 349static int
 350cc2520_read_register(struct cc2520_private *priv, u8 reg, u8 *data)
 351{
 352        int status;
 353        struct spi_message msg;
 354        struct spi_transfer xfer1 = {
 355                .len = 0,
 356                .tx_buf = priv->buf,
 357                .rx_buf = priv->buf,
 358        };
 359
 360        struct spi_transfer xfer2 = {
 361                .len = 1,
 362                .rx_buf = data,
 363        };
 364
 365        spi_message_init(&msg);
 366        spi_message_add_tail(&xfer1, &msg);
 367        spi_message_add_tail(&xfer2, &msg);
 368
 369        mutex_lock(&priv->buffer_mutex);
 370        priv->buf[xfer1.len++] = CC2520_CMD_MEMORY_READ;
 371        priv->buf[xfer1.len++] = reg;
 372
 373        status = spi_sync(priv->spi, &msg);
 374        dev_dbg(&priv->spi->dev,
 375                "spi status = %d\n", status);
 376        if (msg.status)
 377                status = msg.status;
 378
 379        mutex_unlock(&priv->buffer_mutex);
 380
 381        return status;
 382}
 383
 384static int
 385cc2520_write_txfifo(struct cc2520_private *priv, u8 pkt_len, u8 *data, u8 len)
 386{
 387        int status;
 388
 389        /* length byte must include FCS even
 390         * if it is calculated in the hardware
 391         */
 392        int len_byte = pkt_len;
 393
 394        struct spi_message msg;
 395
 396        struct spi_transfer xfer_head = {
 397                .len = 0,
 398                .tx_buf = priv->buf,
 399                .rx_buf = priv->buf,
 400        };
 401        struct spi_transfer xfer_len = {
 402                .len = 1,
 403                .tx_buf = &len_byte,
 404        };
 405        struct spi_transfer xfer_buf = {
 406                .len = len,
 407                .tx_buf = data,
 408        };
 409
 410        spi_message_init(&msg);
 411        spi_message_add_tail(&xfer_head, &msg);
 412        spi_message_add_tail(&xfer_len, &msg);
 413        spi_message_add_tail(&xfer_buf, &msg);
 414
 415        mutex_lock(&priv->buffer_mutex);
 416        priv->buf[xfer_head.len++] = CC2520_CMD_TXBUF;
 417        dev_vdbg(&priv->spi->dev,
 418                 "TX_FIFO cmd buf[0] = %02x\n", priv->buf[0]);
 419
 420        status = spi_sync(priv->spi, &msg);
 421        dev_vdbg(&priv->spi->dev, "status = %d\n", status);
 422        if (msg.status)
 423                status = msg.status;
 424        dev_vdbg(&priv->spi->dev, "status = %d\n", status);
 425        dev_vdbg(&priv->spi->dev, "buf[0] = %02x\n", priv->buf[0]);
 426        mutex_unlock(&priv->buffer_mutex);
 427
 428        return status;
 429}
 430
 431static int
 432cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len)
 433{
 434        int status;
 435        struct spi_message msg;
 436
 437        struct spi_transfer xfer_head = {
 438                .len = 0,
 439                .tx_buf = priv->buf,
 440                .rx_buf = priv->buf,
 441        };
 442        struct spi_transfer xfer_buf = {
 443                .len = len,
 444                .rx_buf = data,
 445        };
 446
 447        spi_message_init(&msg);
 448        spi_message_add_tail(&xfer_head, &msg);
 449        spi_message_add_tail(&xfer_buf, &msg);
 450
 451        mutex_lock(&priv->buffer_mutex);
 452        priv->buf[xfer_head.len++] = CC2520_CMD_RXBUF;
 453
 454        dev_vdbg(&priv->spi->dev, "read rxfifo buf[0] = %02x\n", priv->buf[0]);
 455        dev_vdbg(&priv->spi->dev, "buf[1] = %02x\n", priv->buf[1]);
 456
 457        status = spi_sync(priv->spi, &msg);
 458        dev_vdbg(&priv->spi->dev, "status = %d\n", status);
 459        if (msg.status)
 460                status = msg.status;
 461        dev_vdbg(&priv->spi->dev, "status = %d\n", status);
 462        dev_vdbg(&priv->spi->dev,
 463                 "return status buf[0] = %02x\n", priv->buf[0]);
 464        dev_vdbg(&priv->spi->dev, "length buf[1] = %02x\n", priv->buf[1]);
 465
 466        mutex_unlock(&priv->buffer_mutex);
 467
 468        return status;
 469}
 470
 471static int cc2520_start(struct ieee802154_hw *hw)
 472{
 473        return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON);
 474}
 475
 476static void cc2520_stop(struct ieee802154_hw *hw)
 477{
 478        cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF);
 479}
 480
 481static int
 482cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
 483{
 484        struct cc2520_private *priv = hw->priv;
 485        unsigned long flags;
 486        int rc;
 487        u8 status = 0;
 488        u8 pkt_len;
 489
 490        /* In promiscuous mode we disable AUTOCRC so we can get the raw CRC
 491         * values on RX. This means we need to manually add the CRC on TX.
 492         */
 493        if (priv->promiscuous) {
 494                u16 crc = crc_ccitt(0, skb->data, skb->len);
 495
 496                put_unaligned_le16(crc, skb_put(skb, 2));
 497                pkt_len = skb->len;
 498        } else {
 499                pkt_len = skb->len + 2;
 500        }
 501
 502        rc = cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
 503        if (rc)
 504                goto err_tx;
 505
 506        rc = cc2520_write_txfifo(priv, pkt_len, skb->data, skb->len);
 507        if (rc)
 508                goto err_tx;
 509
 510        rc = cc2520_get_status(priv, &status);
 511        if (rc)
 512                goto err_tx;
 513
 514        if (status & CC2520_STATUS_TX_UNDERFLOW) {
 515                dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
 516                goto err_tx;
 517        }
 518
 519        spin_lock_irqsave(&priv->lock, flags);
 520        WARN_ON(priv->is_tx);
 521        priv->is_tx = 1;
 522        spin_unlock_irqrestore(&priv->lock, flags);
 523
 524        rc = cc2520_cmd_strobe(priv, CC2520_CMD_STXONCCA);
 525        if (rc)
 526                goto err;
 527
 528        rc = wait_for_completion_interruptible(&priv->tx_complete);
 529        if (rc < 0)
 530                goto err;
 531
 532        cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
 533        cc2520_cmd_strobe(priv, CC2520_CMD_SRXON);
 534
 535        return rc;
 536err:
 537        spin_lock_irqsave(&priv->lock, flags);
 538        priv->is_tx = 0;
 539        spin_unlock_irqrestore(&priv->lock, flags);
 540err_tx:
 541        return rc;
 542}
 543
 544static int cc2520_rx(struct cc2520_private *priv)
 545{
 546        u8 len = 0, lqi = 0, bytes = 1;
 547        struct sk_buff *skb;
 548
 549        /* Read single length byte from the radio. */
 550        cc2520_read_rxfifo(priv, &len, bytes);
 551
 552        if (!ieee802154_is_valid_psdu_len(len)) {
 553                /* Corrupted frame received, clear frame buffer by
 554                 * reading entire buffer.
 555                 */
 556                dev_dbg(&priv->spi->dev, "corrupted frame received\n");
 557                len = IEEE802154_MTU;
 558        }
 559
 560        skb = dev_alloc_skb(len);
 561        if (!skb)
 562                return -ENOMEM;
 563
 564        if (cc2520_read_rxfifo(priv, skb_put(skb, len), len)) {
 565                dev_dbg(&priv->spi->dev, "frame reception failed\n");
 566                kfree_skb(skb);
 567                return -EINVAL;
 568        }
 569
 570        /* In promiscuous mode, we configure the radio to include the
 571         * CRC (AUTOCRC==0) and we pass on the packet unconditionally. If not
 572         * in promiscuous mode, we check the CRC here, but leave the
 573         * RSSI/LQI/CRC_OK bytes as they will get removed in the mac layer.
 574         */
 575        if (!priv->promiscuous) {
 576                bool crc_ok;
 577
 578                /* Check if the CRC is valid. With AUTOCRC set, the most
 579                 * significant bit of the last byte returned from the CC2520
 580                 * is CRC_OK flag. See section 20.3.4 of the datasheet.
 581                 */
 582                crc_ok = skb->data[len - 1] & BIT(7);
 583
 584                /* If we failed CRC drop the packet in the driver layer. */
 585                if (!crc_ok) {
 586                        dev_dbg(&priv->spi->dev, "CRC check failed\n");
 587                        kfree_skb(skb);
 588                        return -EINVAL;
 589                }
 590
 591                /* To calculate LQI, the lower 7 bits of the last byte (the
 592                 * correlation value provided by the radio) must be scaled to
 593                 * the range 0-255. According to section 20.6, the correlation
 594                 * value ranges from 50-110. Ideally this would be calibrated
 595                 * per hardware design, but we use roughly the datasheet values
 596                 * to get close enough while avoiding floating point.
 597                 */
 598                lqi = skb->data[len - 1] & 0x7f;
 599                if (lqi < 50)
 600                        lqi = 50;
 601                else if (lqi > 113)
 602                        lqi = 113;
 603                lqi = (lqi - 50) * 4;
 604        }
 605
 606        ieee802154_rx_irqsafe(priv->hw, skb, lqi);
 607
 608        dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
 609
 610        return 0;
 611}
 612
 613static int
 614cc2520_ed(struct ieee802154_hw *hw, u8 *level)
 615{
 616        struct cc2520_private *priv = hw->priv;
 617        u8 status = 0xff;
 618        u8 rssi;
 619        int ret;
 620
 621        ret = cc2520_read_register(priv, CC2520_RSSISTAT, &status);
 622        if (ret)
 623                return ret;
 624
 625        if (status != RSSI_VALID)
 626                return -EINVAL;
 627
 628        ret = cc2520_read_register(priv, CC2520_RSSI, &rssi);
 629        if (ret)
 630                return ret;
 631
 632        /* level = RSSI(rssi) - OFFSET [dBm] : offset is 76dBm */
 633        *level = rssi - RSSI_OFFSET;
 634
 635        return 0;
 636}
 637
 638static int
 639cc2520_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 640{
 641        struct cc2520_private *priv = hw->priv;
 642        int ret;
 643
 644        dev_dbg(&priv->spi->dev, "trying to set channel\n");
 645
 646        WARN_ON(page != 0);
 647        WARN_ON(channel < CC2520_MINCHANNEL);
 648        WARN_ON(channel > CC2520_MAXCHANNEL);
 649
 650        ret = cc2520_write_register(priv, CC2520_FREQCTRL,
 651                                    11 + 5 * (channel - 11));
 652
 653        return ret;
 654}
 655
 656static int
 657cc2520_filter(struct ieee802154_hw *hw,
 658              struct ieee802154_hw_addr_filt *filt, unsigned long changed)
 659{
 660        struct cc2520_private *priv = hw->priv;
 661        int ret = 0;
 662
 663        if (changed & IEEE802154_AFILT_PANID_CHANGED) {
 664                u16 panid = le16_to_cpu(filt->pan_id);
 665
 666                dev_vdbg(&priv->spi->dev, "%s called for pan id\n", __func__);
 667                ret = cc2520_write_ram(priv, CC2520RAM_PANID,
 668                                       sizeof(panid), (u8 *)&panid);
 669        }
 670
 671        if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
 672                dev_vdbg(&priv->spi->dev,
 673                         "%s called for IEEE addr\n", __func__);
 674                ret = cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
 675                                       sizeof(filt->ieee_addr),
 676                                       (u8 *)&filt->ieee_addr);
 677        }
 678
 679        if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
 680                u16 addr = le16_to_cpu(filt->short_addr);
 681
 682                dev_vdbg(&priv->spi->dev, "%s called for saddr\n", __func__);
 683                ret = cc2520_write_ram(priv, CC2520RAM_SHORTADDR,
 684                                       sizeof(addr), (u8 *)&addr);
 685        }
 686
 687        if (changed & IEEE802154_AFILT_PANC_CHANGED) {
 688                u8 frmfilt0;
 689
 690                dev_vdbg(&priv->spi->dev,
 691                         "%s called for panc change\n", __func__);
 692
 693                cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
 694
 695                if (filt->pan_coord)
 696                        frmfilt0 |= FRMFILT0_PAN_COORDINATOR;
 697                else
 698                        frmfilt0 &= ~FRMFILT0_PAN_COORDINATOR;
 699
 700                ret = cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
 701        }
 702
 703        return ret;
 704}
 705
 706static inline int cc2520_set_tx_power(struct cc2520_private *priv, s32 mbm)
 707{
 708        u8 power;
 709
 710        switch (mbm) {
 711        case 500:
 712                power = 0xF7;
 713                break;
 714        case 300:
 715                power = 0xF2;
 716                break;
 717        case 200:
 718                power = 0xAB;
 719                break;
 720        case 100:
 721                power = 0x13;
 722                break;
 723        case 0:
 724                power = 0x32;
 725                break;
 726        case -200:
 727                power = 0x81;
 728                break;
 729        case -400:
 730                power = 0x88;
 731                break;
 732        case -700:
 733                power = 0x2C;
 734                break;
 735        case -1800:
 736                power = 0x03;
 737                break;
 738        default:
 739                return -EINVAL;
 740        }
 741
 742        return cc2520_write_register(priv, CC2520_TXPOWER, power);
 743}
 744
 745static inline int cc2520_cc2591_set_tx_power(struct cc2520_private *priv,
 746                                             s32 mbm)
 747{
 748        u8 power;
 749
 750        switch (mbm) {
 751        case 1700:
 752                power = 0xF9;
 753                break;
 754        case 1600:
 755                power = 0xF0;
 756                break;
 757        case 1400:
 758                power = 0xA0;
 759                break;
 760        case 1100:
 761                power = 0x2C;
 762                break;
 763        case -100:
 764                power = 0x03;
 765                break;
 766        case -800:
 767                power = 0x01;
 768                break;
 769        default:
 770                return -EINVAL;
 771        }
 772
 773        return cc2520_write_register(priv, CC2520_TXPOWER, power);
 774}
 775
 776#define CC2520_MAX_TX_POWERS 0x8
 777static const s32 cc2520_powers[CC2520_MAX_TX_POWERS + 1] = {
 778        500, 300, 200, 100, 0, -200, -400, -700, -1800,
 779};
 780
 781#define CC2520_CC2591_MAX_TX_POWERS 0x5
 782static const s32 cc2520_cc2591_powers[CC2520_CC2591_MAX_TX_POWERS + 1] = {
 783        1700, 1600, 1400, 1100, -100, -800,
 784};
 785
 786static int
 787cc2520_set_txpower(struct ieee802154_hw *hw, s32 mbm)
 788{
 789        struct cc2520_private *priv = hw->priv;
 790
 791        if (!priv->amplified)
 792                return cc2520_set_tx_power(priv, mbm);
 793
 794        return cc2520_cc2591_set_tx_power(priv, mbm);
 795}
 796
 797static int
 798cc2520_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
 799{
 800        struct cc2520_private *priv = hw->priv;
 801        u8 frmfilt0;
 802
 803        dev_dbg(&priv->spi->dev, "%s : mode %d\n", __func__, on);
 804
 805        priv->promiscuous = on;
 806
 807        cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
 808
 809        if (on) {
 810                /* Disable automatic ACK, automatic CRC, and frame filtering. */
 811                cc2520_write_register(priv, CC2520_FRMCTRL0, 0);
 812                frmfilt0 &= ~FRMFILT0_FRAME_FILTER_EN;
 813        } else {
 814                cc2520_write_register(priv, CC2520_FRMCTRL0, FRMCTRL0_AUTOACK |
 815                                                             FRMCTRL0_AUTOCRC);
 816                frmfilt0 |= FRMFILT0_FRAME_FILTER_EN;
 817        }
 818        return cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
 819}
 820
 821static const struct ieee802154_ops cc2520_ops = {
 822        .owner = THIS_MODULE,
 823        .start = cc2520_start,
 824        .stop = cc2520_stop,
 825        .xmit_sync = cc2520_tx,
 826        .ed = cc2520_ed,
 827        .set_channel = cc2520_set_channel,
 828        .set_hw_addr_filt = cc2520_filter,
 829        .set_txpower = cc2520_set_txpower,
 830        .set_promiscuous_mode = cc2520_set_promiscuous_mode,
 831};
 832
 833static int cc2520_register(struct cc2520_private *priv)
 834{
 835        int ret = -ENOMEM;
 836
 837        priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops);
 838        if (!priv->hw)
 839                goto err_ret;
 840
 841        priv->hw->priv = priv;
 842        priv->hw->parent = &priv->spi->dev;
 843        priv->hw->extra_tx_headroom = 0;
 844        ieee802154_random_extended_addr(&priv->hw->phy->perm_extended_addr);
 845
 846        /* We do support only 2.4 Ghz */
 847        priv->hw->phy->supported.channels[0] = 0x7FFF800;
 848        priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
 849                          IEEE802154_HW_PROMISCUOUS;
 850
 851        priv->hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
 852
 853        if (!priv->amplified) {
 854                priv->hw->phy->supported.tx_powers = cc2520_powers;
 855                priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_powers);
 856                priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[4];
 857        } else {
 858                priv->hw->phy->supported.tx_powers = cc2520_cc2591_powers;
 859                priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_cc2591_powers);
 860                priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[0];
 861        }
 862
 863        priv->hw->phy->current_channel = 11;
 864
 865        dev_vdbg(&priv->spi->dev, "registered cc2520\n");
 866        ret = ieee802154_register_hw(priv->hw);
 867        if (ret)
 868                goto err_free_device;
 869
 870        return 0;
 871
 872err_free_device:
 873        ieee802154_free_hw(priv->hw);
 874err_ret:
 875        return ret;
 876}
 877
 878static void cc2520_fifop_irqwork(struct work_struct *work)
 879{
 880        struct cc2520_private *priv
 881                = container_of(work, struct cc2520_private, fifop_irqwork);
 882
 883        dev_dbg(&priv->spi->dev, "fifop interrupt received\n");
 884
 885        if (gpio_get_value(priv->fifo_pin))
 886                cc2520_rx(priv);
 887        else
 888                dev_dbg(&priv->spi->dev, "rxfifo overflow\n");
 889
 890        cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
 891        cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
 892}
 893
 894static irqreturn_t cc2520_fifop_isr(int irq, void *data)
 895{
 896        struct cc2520_private *priv = data;
 897
 898        schedule_work(&priv->fifop_irqwork);
 899
 900        return IRQ_HANDLED;
 901}
 902
 903static irqreturn_t cc2520_sfd_isr(int irq, void *data)
 904{
 905        struct cc2520_private *priv = data;
 906        unsigned long flags;
 907
 908        spin_lock_irqsave(&priv->lock, flags);
 909        if (priv->is_tx) {
 910                priv->is_tx = 0;
 911                spin_unlock_irqrestore(&priv->lock, flags);
 912                dev_dbg(&priv->spi->dev, "SFD for TX\n");
 913                complete(&priv->tx_complete);
 914        } else {
 915                spin_unlock_irqrestore(&priv->lock, flags);
 916                dev_dbg(&priv->spi->dev, "SFD for RX\n");
 917        }
 918
 919        return IRQ_HANDLED;
 920}
 921
 922static int cc2520_get_platform_data(struct spi_device *spi,
 923                                    struct cc2520_platform_data *pdata)
 924{
 925        struct device_node *np = spi->dev.of_node;
 926        struct cc2520_private *priv = spi_get_drvdata(spi);
 927
 928        if (!np) {
 929                struct cc2520_platform_data *spi_pdata = spi->dev.platform_data;
 930
 931                if (!spi_pdata)
 932                        return -ENOENT;
 933                *pdata = *spi_pdata;
 934                priv->fifo_pin = pdata->fifo;
 935                return 0;
 936        }
 937
 938        pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0);
 939        priv->fifo_pin = pdata->fifo;
 940
 941        pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0);
 942
 943        pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0);
 944        pdata->cca = of_get_named_gpio(np, "cca-gpio", 0);
 945        pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0);
 946        pdata->reset = of_get_named_gpio(np, "reset-gpio", 0);
 947
 948        /* CC2591 front end for CC2520 */
 949        if (of_property_read_bool(np, "amplified"))
 950                priv->amplified = true;
 951
 952        return 0;
 953}
 954
 955static int cc2520_hw_init(struct cc2520_private *priv)
 956{
 957        u8 status = 0, state = 0xff;
 958        int ret;
 959        int timeout = 100;
 960        struct cc2520_platform_data pdata;
 961
 962        ret = cc2520_get_platform_data(priv->spi, &pdata);
 963        if (ret)
 964                goto err_ret;
 965
 966        ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state);
 967        if (ret)
 968                goto err_ret;
 969
 970        if (state != STATE_IDLE)
 971                return -EINVAL;
 972
 973        do {
 974                ret = cc2520_get_status(priv, &status);
 975                if (ret)
 976                        goto err_ret;
 977
 978                if (timeout-- <= 0) {
 979                        dev_err(&priv->spi->dev, "oscillator start failed!\n");
 980                        return ret;
 981                }
 982                udelay(1);
 983        } while (!(status & CC2520_STATUS_XOSC32M_STABLE));
 984
 985        dev_vdbg(&priv->spi->dev, "oscillator brought up\n");
 986
 987        /* If the CC2520 is connected to a CC2591 amplifier, we must both
 988         * configure GPIOs on the CC2520 to correctly configure the CC2591
 989         * and change a couple settings of the CC2520 to work with the
 990         * amplifier. See section 8 page 17 of TI application note AN065.
 991         * http://www.ti.com/lit/an/swra229a/swra229a.pdf
 992         */
 993        if (priv->amplified) {
 994                ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x16);
 995                if (ret)
 996                        goto err_ret;
 997
 998                ret = cc2520_write_register(priv, CC2520_GPIOCTRL0, 0x46);
 999                if (ret)
1000                        goto err_ret;
1001
1002                ret = cc2520_write_register(priv, CC2520_GPIOCTRL5, 0x47);
1003                if (ret)
1004                        goto err_ret;
1005
1006                ret = cc2520_write_register(priv, CC2520_GPIOPOLARITY, 0x1e);
1007                if (ret)
1008                        goto err_ret;
1009
1010                ret = cc2520_write_register(priv, CC2520_TXCTRL, 0xc1);
1011                if (ret)
1012                        goto err_ret;
1013        } else {
1014                ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11);
1015                if (ret)
1016                        goto err_ret;
1017        }
1018
1019        /* Registers default value: section 28.1 in Datasheet */
1020
1021        /* Set the CCA threshold to -50 dBm. This seems to have been copied
1022         * from the TinyOS CC2520 driver and is much higher than the -84 dBm
1023         * threshold suggested in the datasheet.
1024         */
1025        ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
1026        if (ret)
1027                goto err_ret;
1028
1029        ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85);
1030        if (ret)
1031                goto err_ret;
1032
1033        ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14);
1034        if (ret)
1035                goto err_ret;
1036
1037        ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f);
1038        if (ret)
1039                goto err_ret;
1040
1041        ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a);
1042        if (ret)
1043                goto err_ret;
1044
1045        ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b);
1046        if (ret)
1047                goto err_ret;
1048
1049        ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10);
1050        if (ret)
1051                goto err_ret;
1052
1053        ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e);
1054        if (ret)
1055                goto err_ret;
1056
1057        ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03);
1058        if (ret)
1059                goto err_ret;
1060
1061        /* Configure registers correctly for this driver. */
1062        ret = cc2520_write_register(priv, CC2520_FRMCTRL1,
1063                                    FRMCTRL1_SET_RXENMASK_ON_TX |
1064                                    FRMCTRL1_IGNORE_TX_UNDERF);
1065        if (ret)
1066                goto err_ret;
1067
1068        ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127);
1069        if (ret)
1070                goto err_ret;
1071
1072        return 0;
1073
1074err_ret:
1075        return ret;
1076}
1077
1078static int cc2520_probe(struct spi_device *spi)
1079{
1080        struct cc2520_private *priv;
1081        struct cc2520_platform_data pdata;
1082        int ret;
1083
1084        priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
1085        if (!priv)
1086                return -ENOMEM;
1087
1088        spi_set_drvdata(spi, priv);
1089
1090        ret = cc2520_get_platform_data(spi, &pdata);
1091        if (ret < 0) {
1092                dev_err(&spi->dev, "no platform data\n");
1093                return -EINVAL;
1094        }
1095
1096        priv->spi = spi;
1097
1098        priv->buf = devm_kzalloc(&spi->dev,
1099                                 SPI_COMMAND_BUFFER, GFP_KERNEL);
1100        if (!priv->buf)
1101                return -ENOMEM;
1102
1103        mutex_init(&priv->buffer_mutex);
1104        INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork);
1105        spin_lock_init(&priv->lock);
1106        init_completion(&priv->tx_complete);
1107
1108        /* Assumption that CC2591 is not connected */
1109        priv->amplified = false;
1110
1111        /* Request all the gpio's */
1112        if (!gpio_is_valid(pdata.fifo)) {
1113                dev_err(&spi->dev, "fifo gpio is not valid\n");
1114                ret = -EINVAL;
1115                goto err_hw_init;
1116        }
1117
1118        ret = devm_gpio_request_one(&spi->dev, pdata.fifo,
1119                                    GPIOF_IN, "fifo");
1120        if (ret)
1121                goto err_hw_init;
1122
1123        if (!gpio_is_valid(pdata.cca)) {
1124                dev_err(&spi->dev, "cca gpio is not valid\n");
1125                ret = -EINVAL;
1126                goto err_hw_init;
1127        }
1128
1129        ret = devm_gpio_request_one(&spi->dev, pdata.cca,
1130                                    GPIOF_IN, "cca");
1131        if (ret)
1132                goto err_hw_init;
1133
1134        if (!gpio_is_valid(pdata.fifop)) {
1135                dev_err(&spi->dev, "fifop gpio is not valid\n");
1136                ret = -EINVAL;
1137                goto err_hw_init;
1138        }
1139
1140        ret = devm_gpio_request_one(&spi->dev, pdata.fifop,
1141                                    GPIOF_IN, "fifop");
1142        if (ret)
1143                goto err_hw_init;
1144
1145        if (!gpio_is_valid(pdata.sfd)) {
1146                dev_err(&spi->dev, "sfd gpio is not valid\n");
1147                ret = -EINVAL;
1148                goto err_hw_init;
1149        }
1150
1151        ret = devm_gpio_request_one(&spi->dev, pdata.sfd,
1152                                    GPIOF_IN, "sfd");
1153        if (ret)
1154                goto err_hw_init;
1155
1156        if (!gpio_is_valid(pdata.reset)) {
1157                dev_err(&spi->dev, "reset gpio is not valid\n");
1158                ret = -EINVAL;
1159                goto err_hw_init;
1160        }
1161
1162        ret = devm_gpio_request_one(&spi->dev, pdata.reset,
1163                                    GPIOF_OUT_INIT_LOW, "reset");
1164        if (ret)
1165                goto err_hw_init;
1166
1167        if (!gpio_is_valid(pdata.vreg)) {
1168                dev_err(&spi->dev, "vreg gpio is not valid\n");
1169                ret = -EINVAL;
1170                goto err_hw_init;
1171        }
1172
1173        ret = devm_gpio_request_one(&spi->dev, pdata.vreg,
1174                                    GPIOF_OUT_INIT_LOW, "vreg");
1175        if (ret)
1176                goto err_hw_init;
1177
1178        gpio_set_value(pdata.vreg, HIGH);
1179        usleep_range(100, 150);
1180
1181        gpio_set_value(pdata.reset, HIGH);
1182        usleep_range(200, 250);
1183
1184        ret = cc2520_hw_init(priv);
1185        if (ret)
1186                goto err_hw_init;
1187
1188        /* Set up fifop interrupt */
1189        ret = devm_request_irq(&spi->dev,
1190                               gpio_to_irq(pdata.fifop),
1191                               cc2520_fifop_isr,
1192                               IRQF_TRIGGER_RISING,
1193                               dev_name(&spi->dev),
1194                               priv);
1195        if (ret) {
1196                dev_err(&spi->dev, "could not get fifop irq\n");
1197                goto err_hw_init;
1198        }
1199
1200        /* Set up sfd interrupt */
1201        ret = devm_request_irq(&spi->dev,
1202                               gpio_to_irq(pdata.sfd),
1203                               cc2520_sfd_isr,
1204                               IRQF_TRIGGER_FALLING,
1205                               dev_name(&spi->dev),
1206                               priv);
1207        if (ret) {
1208                dev_err(&spi->dev, "could not get sfd irq\n");
1209                goto err_hw_init;
1210        }
1211
1212        ret = cc2520_register(priv);
1213        if (ret)
1214                goto err_hw_init;
1215
1216        return 0;
1217
1218err_hw_init:
1219        mutex_destroy(&priv->buffer_mutex);
1220        flush_work(&priv->fifop_irqwork);
1221        return ret;
1222}
1223
1224static int cc2520_remove(struct spi_device *spi)
1225{
1226        struct cc2520_private *priv = spi_get_drvdata(spi);
1227
1228        mutex_destroy(&priv->buffer_mutex);
1229        flush_work(&priv->fifop_irqwork);
1230
1231        ieee802154_unregister_hw(priv->hw);
1232        ieee802154_free_hw(priv->hw);
1233
1234        return 0;
1235}
1236
1237static const struct spi_device_id cc2520_ids[] = {
1238        {"cc2520", },
1239        {},
1240};
1241MODULE_DEVICE_TABLE(spi, cc2520_ids);
1242
1243static const struct of_device_id cc2520_of_ids[] = {
1244        {.compatible = "ti,cc2520", },
1245        {},
1246};
1247MODULE_DEVICE_TABLE(of, cc2520_of_ids);
1248
1249/* SPI driver structure */
1250static struct spi_driver cc2520_driver = {
1251        .driver = {
1252                .name = "cc2520",
1253                .of_match_table = of_match_ptr(cc2520_of_ids),
1254        },
1255        .id_table = cc2520_ids,
1256        .probe = cc2520_probe,
1257        .remove = cc2520_remove,
1258};
1259module_spi_driver(cc2520_driver);
1260
1261MODULE_AUTHOR("Varka Bhadram <varkab@cdac.in>");
1262MODULE_DESCRIPTION("CC2520 Transceiver Driver");
1263MODULE_LICENSE("GPL v2");
1264