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