linux/drivers/net/ieee802154/ca8210.c
<<
>>
Prefs
   1/*
   2 * http://www.cascoda.com/products/ca-821x/
   3 * Copyright (c) 2016, Cascoda, Ltd.
   4 * All rights reserved.
   5 *
   6 * This code is dual-licensed under both GPLv2 and 3-clause BSD. What follows is
   7 * the license notice for both respectively.
   8 *
   9 *******************************************************************************
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License
  13 * as published by the Free Software Foundation; either version 2
  14 * of the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 *******************************************************************************
  22 *
  23 * Redistribution and use in source and binary forms, with or without
  24 * modification, are permitted provided that the following conditions are met:
  25 *
  26 * 1. Redistributions of source code must retain the above copyright notice,
  27 * this list of conditions and the following disclaimer.
  28 *
  29 * 2. Redistributions in binary form must reproduce the above copyright notice,
  30 * this list of conditions and the following disclaimer in the documentation
  31 * and/or other materials provided with the distribution.
  32 *
  33 * 3. Neither the name of the copyright holder nor the names of its contributors
  34 * may be used to endorse or promote products derived from this software without
  35 * specific prior written permission.
  36 *
  37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  38 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  40 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  41 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  44 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  45 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  47 * POSSIBILITY OF SUCH DAMAGE.
  48 */
  49
  50#include <linux/cdev.h>
  51#include <linux/clk-provider.h>
  52#include <linux/debugfs.h>
  53#include <linux/delay.h>
  54#include <linux/gpio.h>
  55#include <linux/ieee802154.h>
  56#include <linux/io.h>
  57#include <linux/kfifo.h>
  58#include <linux/of.h>
  59#include <linux/of_device.h>
  60#include <linux/of_gpio.h>
  61#include <linux/module.h>
  62#include <linux/mutex.h>
  63#include <linux/poll.h>
  64#include <linux/skbuff.h>
  65#include <linux/slab.h>
  66#include <linux/spi/spi.h>
  67#include <linux/spinlock.h>
  68#include <linux/string.h>
  69#include <linux/workqueue.h>
  70#include <linux/interrupt.h>
  71
  72#include <net/ieee802154_netdev.h>
  73#include <net/mac802154.h>
  74
  75#define DRIVER_NAME "ca8210"
  76
  77/* external clock frequencies */
  78#define ONE_MHZ      1000000
  79#define TWO_MHZ      (2 * ONE_MHZ)
  80#define FOUR_MHZ     (4 * ONE_MHZ)
  81#define EIGHT_MHZ    (8 * ONE_MHZ)
  82#define SIXTEEN_MHZ  (16 * ONE_MHZ)
  83
  84/* spi constants */
  85#define CA8210_SPI_BUF_SIZE 256
  86#define CA8210_SYNC_TIMEOUT 1000     /* Timeout for synchronous commands [ms] */
  87
  88/* test interface constants */
  89#define CA8210_TEST_INT_FILE_NAME "ca8210_test"
  90#define CA8210_TEST_INT_FIFO_SIZE 256
  91
  92/* MAC status enumerations */
  93#define MAC_SUCCESS                     (0x00)
  94#define MAC_ERROR                       (0x01)
  95#define MAC_CANCELLED                   (0x02)
  96#define MAC_READY_FOR_POLL              (0x03)
  97#define MAC_COUNTER_ERROR               (0xDB)
  98#define MAC_IMPROPER_KEY_TYPE           (0xDC)
  99#define MAC_IMPROPER_SECURITY_LEVEL     (0xDD)
 100#define MAC_UNSUPPORTED_LEGACY          (0xDE)
 101#define MAC_UNSUPPORTED_SECURITY        (0xDF)
 102#define MAC_BEACON_LOST                 (0xE0)
 103#define MAC_CHANNEL_ACCESS_FAILURE      (0xE1)
 104#define MAC_DENIED                      (0xE2)
 105#define MAC_DISABLE_TRX_FAILURE         (0xE3)
 106#define MAC_SECURITY_ERROR              (0xE4)
 107#define MAC_FRAME_TOO_LONG              (0xE5)
 108#define MAC_INVALID_GTS                 (0xE6)
 109#define MAC_INVALID_HANDLE              (0xE7)
 110#define MAC_INVALID_PARAMETER           (0xE8)
 111#define MAC_NO_ACK                      (0xE9)
 112#define MAC_NO_BEACON                   (0xEA)
 113#define MAC_NO_DATA                     (0xEB)
 114#define MAC_NO_SHORT_ADDRESS            (0xEC)
 115#define MAC_OUT_OF_CAP                  (0xED)
 116#define MAC_PAN_ID_CONFLICT             (0xEE)
 117#define MAC_REALIGNMENT                 (0xEF)
 118#define MAC_TRANSACTION_EXPIRED         (0xF0)
 119#define MAC_TRANSACTION_OVERFLOW        (0xF1)
 120#define MAC_TX_ACTIVE                   (0xF2)
 121#define MAC_UNAVAILABLE_KEY             (0xF3)
 122#define MAC_UNSUPPORTED_ATTRIBUTE       (0xF4)
 123#define MAC_INVALID_ADDRESS             (0xF5)
 124#define MAC_ON_TIME_TOO_LONG            (0xF6)
 125#define MAC_PAST_TIME                   (0xF7)
 126#define MAC_TRACKING_OFF                (0xF8)
 127#define MAC_INVALID_INDEX               (0xF9)
 128#define MAC_LIMIT_REACHED               (0xFA)
 129#define MAC_READ_ONLY                   (0xFB)
 130#define MAC_SCAN_IN_PROGRESS            (0xFC)
 131#define MAC_SUPERFRAME_OVERLAP          (0xFD)
 132#define MAC_SYSTEM_ERROR                (0xFF)
 133
 134/* HWME attribute IDs */
 135#define HWME_EDTHRESHOLD       (0x04)
 136#define HWME_EDVALUE           (0x06)
 137#define HWME_SYSCLKOUT         (0x0F)
 138#define HWME_LQILIMIT          (0x11)
 139
 140/* TDME attribute IDs */
 141#define TDME_CHANNEL          (0x00)
 142#define TDME_ATM_CONFIG       (0x06)
 143
 144#define MAX_HWME_ATTRIBUTE_SIZE  16
 145#define MAX_TDME_ATTRIBUTE_SIZE  2
 146
 147/* PHY/MAC PIB Attribute Enumerations */
 148#define PHY_CURRENT_CHANNEL               (0x00)
 149#define PHY_TRANSMIT_POWER                (0x02)
 150#define PHY_CCA_MODE                      (0x03)
 151#define MAC_ASSOCIATION_PERMIT            (0x41)
 152#define MAC_AUTO_REQUEST                  (0x42)
 153#define MAC_BATT_LIFE_EXT                 (0x43)
 154#define MAC_BATT_LIFE_EXT_PERIODS         (0x44)
 155#define MAC_BEACON_PAYLOAD                (0x45)
 156#define MAC_BEACON_PAYLOAD_LENGTH         (0x46)
 157#define MAC_BEACON_ORDER                  (0x47)
 158#define MAC_GTS_PERMIT                    (0x4d)
 159#define MAC_MAX_CSMA_BACKOFFS             (0x4e)
 160#define MAC_MIN_BE                        (0x4f)
 161#define MAC_PAN_ID                        (0x50)
 162#define MAC_PROMISCUOUS_MODE              (0x51)
 163#define MAC_RX_ON_WHEN_IDLE               (0x52)
 164#define MAC_SHORT_ADDRESS                 (0x53)
 165#define MAC_SUPERFRAME_ORDER              (0x54)
 166#define MAC_ASSOCIATED_PAN_COORD          (0x56)
 167#define MAC_MAX_BE                        (0x57)
 168#define MAC_MAX_FRAME_RETRIES             (0x59)
 169#define MAC_RESPONSE_WAIT_TIME            (0x5A)
 170#define MAC_SECURITY_ENABLED              (0x5D)
 171
 172#define MAC_AUTO_REQUEST_SECURITY_LEVEL   (0x78)
 173#define MAC_AUTO_REQUEST_KEY_ID_MODE      (0x79)
 174
 175#define NS_IEEE_ADDRESS                   (0xFF) /* Non-standard IEEE address */
 176
 177/* MAC Address Mode Definitions */
 178#define MAC_MODE_NO_ADDR                (0x00)
 179#define MAC_MODE_SHORT_ADDR             (0x02)
 180#define MAC_MODE_LONG_ADDR              (0x03)
 181
 182/* MAC constants */
 183#define MAX_BEACON_OVERHEAD        (75)
 184#define MAX_BEACON_PAYLOAD_LENGTH  (IEEE802154_MTU - MAX_BEACON_OVERHEAD)
 185
 186#define MAX_ATTRIBUTE_SIZE              (122)
 187#define MAX_DATA_SIZE                   (114)
 188
 189#define CA8210_VALID_CHANNELS                 (0x07FFF800)
 190
 191/* MAC workarounds for V1.1 and MPW silicon (V0.x) */
 192#define CA8210_MAC_WORKAROUNDS (0)
 193#define CA8210_MAC_MPW         (0)
 194
 195/* memory manipulation macros */
 196#define LS_BYTE(x)     ((u8)((x) & 0xFF))
 197#define MS_BYTE(x)     ((u8)(((x) >> 8) & 0xFF))
 198
 199/* message ID codes in SPI commands */
 200/* downstream */
 201#define MCPS_DATA_REQUEST                     (0x00)
 202#define MLME_ASSOCIATE_REQUEST                (0x02)
 203#define MLME_ASSOCIATE_RESPONSE               (0x03)
 204#define MLME_DISASSOCIATE_REQUEST             (0x04)
 205#define MLME_GET_REQUEST                      (0x05)
 206#define MLME_ORPHAN_RESPONSE                  (0x06)
 207#define MLME_RESET_REQUEST                    (0x07)
 208#define MLME_RX_ENABLE_REQUEST                (0x08)
 209#define MLME_SCAN_REQUEST                     (0x09)
 210#define MLME_SET_REQUEST                      (0x0A)
 211#define MLME_START_REQUEST                    (0x0B)
 212#define MLME_POLL_REQUEST                     (0x0D)
 213#define HWME_SET_REQUEST                      (0x0E)
 214#define HWME_GET_REQUEST                      (0x0F)
 215#define TDME_SETSFR_REQUEST                   (0x11)
 216#define TDME_GETSFR_REQUEST                   (0x12)
 217#define TDME_SET_REQUEST                      (0x14)
 218/* upstream */
 219#define MCPS_DATA_INDICATION                  (0x00)
 220#define MCPS_DATA_CONFIRM                     (0x01)
 221#define MLME_RESET_CONFIRM                    (0x0A)
 222#define MLME_SET_CONFIRM                      (0x0E)
 223#define MLME_START_CONFIRM                    (0x0F)
 224#define HWME_SET_CONFIRM                      (0x12)
 225#define HWME_GET_CONFIRM                      (0x13)
 226#define HWME_WAKEUP_INDICATION                (0x15)
 227#define TDME_SETSFR_CONFIRM                   (0x17)
 228
 229/* SPI command IDs */
 230/* bit indicating a confirm or indication from slave to master */
 231#define SPI_S2M                            (0x20)
 232/* bit indicating a synchronous message */
 233#define SPI_SYN                            (0x40)
 234
 235/* SPI command definitions */
 236#define SPI_IDLE                           (0xFF)
 237#define SPI_NACK                           (0xF0)
 238
 239#define SPI_MCPS_DATA_REQUEST          (MCPS_DATA_REQUEST)
 240#define SPI_MCPS_DATA_INDICATION       (MCPS_DATA_INDICATION + SPI_S2M)
 241#define SPI_MCPS_DATA_CONFIRM          (MCPS_DATA_CONFIRM + SPI_S2M)
 242
 243#define SPI_MLME_ASSOCIATE_REQUEST     (MLME_ASSOCIATE_REQUEST)
 244#define SPI_MLME_RESET_REQUEST         (MLME_RESET_REQUEST + SPI_SYN)
 245#define SPI_MLME_SET_REQUEST           (MLME_SET_REQUEST + SPI_SYN)
 246#define SPI_MLME_START_REQUEST         (MLME_START_REQUEST + SPI_SYN)
 247#define SPI_MLME_RESET_CONFIRM         (MLME_RESET_CONFIRM + SPI_S2M + SPI_SYN)
 248#define SPI_MLME_SET_CONFIRM           (MLME_SET_CONFIRM + SPI_S2M + SPI_SYN)
 249#define SPI_MLME_START_CONFIRM         (MLME_START_CONFIRM + SPI_S2M + SPI_SYN)
 250
 251#define SPI_HWME_SET_REQUEST           (HWME_SET_REQUEST + SPI_SYN)
 252#define SPI_HWME_GET_REQUEST           (HWME_GET_REQUEST + SPI_SYN)
 253#define SPI_HWME_SET_CONFIRM           (HWME_SET_CONFIRM + SPI_S2M + SPI_SYN)
 254#define SPI_HWME_GET_CONFIRM           (HWME_GET_CONFIRM + SPI_S2M + SPI_SYN)
 255#define SPI_HWME_WAKEUP_INDICATION     (HWME_WAKEUP_INDICATION + SPI_S2M)
 256
 257#define SPI_TDME_SETSFR_REQUEST        (TDME_SETSFR_REQUEST + SPI_SYN)
 258#define SPI_TDME_SET_REQUEST           (TDME_SET_REQUEST + SPI_SYN)
 259#define SPI_TDME_SETSFR_CONFIRM        (TDME_SETSFR_CONFIRM + SPI_S2M + SPI_SYN)
 260
 261/* TDME SFR addresses */
 262/* Page 0 */
 263#define CA8210_SFR_PACFG                   (0xB1)
 264#define CA8210_SFR_MACCON                  (0xD8)
 265#define CA8210_SFR_PACFGIB                 (0xFE)
 266/* Page 1 */
 267#define CA8210_SFR_LOTXCAL                 (0xBF)
 268#define CA8210_SFR_PTHRH                   (0xD1)
 269#define CA8210_SFR_PRECFG                  (0xD3)
 270#define CA8210_SFR_LNAGX40                 (0xE1)
 271#define CA8210_SFR_LNAGX41                 (0xE2)
 272#define CA8210_SFR_LNAGX42                 (0xE3)
 273#define CA8210_SFR_LNAGX43                 (0xE4)
 274#define CA8210_SFR_LNAGX44                 (0xE5)
 275#define CA8210_SFR_LNAGX45                 (0xE6)
 276#define CA8210_SFR_LNAGX46                 (0xE7)
 277#define CA8210_SFR_LNAGX47                 (0xE9)
 278
 279#define PACFGIB_DEFAULT_CURRENT            (0x3F)
 280#define PTHRH_DEFAULT_THRESHOLD            (0x5A)
 281#define LNAGX40_DEFAULT_GAIN               (0x29) /* 10dB */
 282#define LNAGX41_DEFAULT_GAIN               (0x54) /* 21dB */
 283#define LNAGX42_DEFAULT_GAIN               (0x6C) /* 27dB */
 284#define LNAGX43_DEFAULT_GAIN               (0x7A) /* 30dB */
 285#define LNAGX44_DEFAULT_GAIN               (0x84) /* 33dB */
 286#define LNAGX45_DEFAULT_GAIN               (0x8B) /* 34dB */
 287#define LNAGX46_DEFAULT_GAIN               (0x92) /* 36dB */
 288#define LNAGX47_DEFAULT_GAIN               (0x96) /* 37dB */
 289
 290#define CA8210_IOCTL_HARD_RESET            (0x00)
 291
 292/* Structs/Enums */
 293
 294/**
 295 * struct cas_control - spi transfer structure
 296 * @msg:                  spi_message for each exchange
 297 * @transfer:             spi_transfer for each exchange
 298 * @tx_buf:               source array for transmission
 299 * @tx_in_buf:            array storing bytes received during transmission
 300 * @priv:                 pointer to private data
 301 *
 302 * This structure stores all the necessary data passed around during a single
 303 * spi exchange.
 304 */
 305struct cas_control {
 306        struct spi_message msg;
 307        struct spi_transfer transfer;
 308
 309        u8 tx_buf[CA8210_SPI_BUF_SIZE];
 310        u8 tx_in_buf[CA8210_SPI_BUF_SIZE];
 311
 312        struct ca8210_priv *priv;
 313};
 314
 315/**
 316 * struct ca8210_test - ca8210 test interface structure
 317 * @ca8210_dfs_spi_int: pointer to the entry in the debug fs for this device
 318 * @up_fifo:            fifo for upstream messages
 319 * @readq:              read wait queue
 320 *
 321 * This structure stores all the data pertaining to the debug interface
 322 */
 323struct ca8210_test {
 324        struct dentry *ca8210_dfs_spi_int;
 325        struct kfifo up_fifo;
 326        wait_queue_head_t readq;
 327};
 328
 329/**
 330 * struct ca8210_priv - ca8210 private data structure
 331 * @spi:                    pointer to the ca8210 spi device object
 332 * @hw:                     pointer to the ca8210 ieee802154_hw object
 333 * @hw_registered:          true if hw has been registered with ieee802154
 334 * @lock:                   spinlock protecting the private data area
 335 * @mlme_workqueue:           workqueue for triggering MLME Reset
 336 * @irq_workqueue:          workqueue for irq processing
 337 * @tx_skb:                 current socket buffer to transmit
 338 * @nextmsduhandle:         msdu handle to pass to the 15.4 MAC layer for the
 339 *                           next transmission
 340 * @clk:                    external clock provided by the ca8210
 341 * @last_dsn:               sequence number of last data packet received, for
 342 *                           resend detection
 343 * @test:                   test interface data section for this instance
 344 * @async_tx_pending:       true if an asynchronous transmission was started and
 345 *                           is not complete
 346 * @sync_command_response:  pointer to buffer to fill with sync response
 347 * @ca8210_is_awake:        nonzero if ca8210 is initialised, ready for comms
 348 * @sync_down:              counts number of downstream synchronous commands
 349 * @sync_up:                counts number of upstream synchronous commands
 350 * @spi_transfer_complete:  completion object for a single spi_transfer
 351 * @sync_exchange_complete: completion object for a complete synchronous API
 352 *                          exchange
 353 * @promiscuous:            whether the ca8210 is in promiscuous mode or not
 354 * @retries:                records how many times the current pending spi
 355 *                          transfer has been retried
 356 */
 357struct ca8210_priv {
 358        struct spi_device *spi;
 359        struct ieee802154_hw *hw;
 360        bool hw_registered;
 361        spinlock_t lock;
 362        struct workqueue_struct *mlme_workqueue;
 363        struct workqueue_struct *irq_workqueue;
 364        struct sk_buff *tx_skb;
 365        u8 nextmsduhandle;
 366        struct clk *clk;
 367        int last_dsn;
 368        struct ca8210_test test;
 369        bool async_tx_pending;
 370        u8 *sync_command_response;
 371        struct completion ca8210_is_awake;
 372        int sync_down, sync_up;
 373        struct completion spi_transfer_complete, sync_exchange_complete;
 374        bool promiscuous;
 375        int retries;
 376};
 377
 378/**
 379 * struct work_priv_container - link between a work object and the relevant
 380 *                              device's private data
 381 * @work: work object being executed
 382 * @priv: device's private data section
 383 *
 384 */
 385struct work_priv_container {
 386        struct work_struct work;
 387        struct ca8210_priv *priv;
 388};
 389
 390/**
 391 * struct ca8210_platform_data - ca8210 platform data structure
 392 * @extclockenable: true if the external clock is to be enabled
 393 * @extclockfreq:   frequency of the external clock
 394 * @extclockgpio:   ca8210 output gpio of the external clock
 395 * @gpio_reset:     gpio number of ca8210 reset line
 396 * @gpio_irq:       gpio number of ca8210 interrupt line
 397 * @irq_id:         identifier for the ca8210 irq
 398 *
 399 */
 400struct ca8210_platform_data {
 401        bool extclockenable;
 402        unsigned int extclockfreq;
 403        unsigned int extclockgpio;
 404        int gpio_reset;
 405        int gpio_irq;
 406        int irq_id;
 407};
 408
 409/**
 410 * struct fulladdr - full MAC addressing information structure
 411 * @mode:    address mode (none, short, extended)
 412 * @pan_id:  16-bit LE pan id
 413 * @address: LE address, variable length as specified by mode
 414 *
 415 */
 416struct fulladdr {
 417        u8         mode;
 418        u8         pan_id[2];
 419        u8         address[8];
 420};
 421
 422/**
 423 * union macaddr: generic MAC address container
 424 * @short_address: 16-bit short address
 425 * @ieee_address:  64-bit extended address as LE byte array
 426 *
 427 */
 428union macaddr {
 429        u16        short_address;
 430        u8         ieee_address[8];
 431};
 432
 433/**
 434 * struct secspec: security specification for SAP commands
 435 * @security_level: 0-7, controls level of authentication & encryption
 436 * @key_id_mode:    0-3, specifies how to obtain key
 437 * @key_source:     extended key retrieval data
 438 * @key_index:      single-byte key identifier
 439 *
 440 */
 441struct secspec {
 442        u8         security_level;
 443        u8         key_id_mode;
 444        u8         key_source[8];
 445        u8         key_index;
 446};
 447
 448/* downlink functions parameter set definitions */
 449struct mcps_data_request_pset {
 450        u8              src_addr_mode;
 451        struct fulladdr dst;
 452        u8              msdu_length;
 453        u8              msdu_handle;
 454        u8              tx_options;
 455        u8              msdu[MAX_DATA_SIZE];
 456};
 457
 458struct mlme_set_request_pset {
 459        u8         pib_attribute;
 460        u8         pib_attribute_index;
 461        u8         pib_attribute_length;
 462        u8         pib_attribute_value[MAX_ATTRIBUTE_SIZE];
 463};
 464
 465struct hwme_set_request_pset {
 466        u8         hw_attribute;
 467        u8         hw_attribute_length;
 468        u8         hw_attribute_value[MAX_HWME_ATTRIBUTE_SIZE];
 469};
 470
 471struct hwme_get_request_pset {
 472        u8         hw_attribute;
 473};
 474
 475struct tdme_setsfr_request_pset {
 476        u8         sfr_page;
 477        u8         sfr_address;
 478        u8         sfr_value;
 479};
 480
 481/* uplink functions parameter set definitions */
 482struct hwme_set_confirm_pset {
 483        u8         status;
 484        u8         hw_attribute;
 485};
 486
 487struct hwme_get_confirm_pset {
 488        u8         status;
 489        u8         hw_attribute;
 490        u8         hw_attribute_length;
 491        u8         hw_attribute_value[MAX_HWME_ATTRIBUTE_SIZE];
 492};
 493
 494struct tdme_setsfr_confirm_pset {
 495        u8         status;
 496        u8         sfr_page;
 497        u8         sfr_address;
 498};
 499
 500struct mac_message {
 501        u8      command_id;
 502        u8      length;
 503        union {
 504                struct mcps_data_request_pset       data_req;
 505                struct mlme_set_request_pset        set_req;
 506                struct hwme_set_request_pset        hwme_set_req;
 507                struct hwme_get_request_pset        hwme_get_req;
 508                struct tdme_setsfr_request_pset     tdme_set_sfr_req;
 509                struct hwme_set_confirm_pset        hwme_set_cnf;
 510                struct hwme_get_confirm_pset        hwme_get_cnf;
 511                struct tdme_setsfr_confirm_pset     tdme_set_sfr_cnf;
 512                u8                                  u8param;
 513                u8                                  status;
 514                u8                                  payload[148];
 515        } pdata;
 516};
 517
 518union pa_cfg_sfr {
 519        struct {
 520                u8 bias_current_trim     : 3;
 521                u8 /* reserved */        : 1;
 522                u8 buffer_capacitor_trim : 3;
 523                u8 boost                 : 1;
 524        };
 525        u8 paib;
 526};
 527
 528struct preamble_cfg_sfr {
 529        u8 timeout_symbols      : 3;
 530        u8 acquisition_symbols  : 3;
 531        u8 search_symbols       : 2;
 532};
 533
 534static int (*cascoda_api_upstream)(
 535        const u8 *buf,
 536        size_t len,
 537        void *device_ref
 538);
 539
 540/**
 541 * link_to_linux_err() - Translates an 802.15.4 return code into the closest
 542 *                       linux error
 543 * @link_status:  802.15.4 status code
 544 *
 545 * Return: 0 or Linux error code
 546 */
 547static int link_to_linux_err(int link_status)
 548{
 549        if (link_status < 0) {
 550                /* status is already a Linux code */
 551                return link_status;
 552        }
 553        switch (link_status) {
 554        case MAC_SUCCESS:
 555        case MAC_REALIGNMENT:
 556                return 0;
 557        case MAC_IMPROPER_KEY_TYPE:
 558                return -EKEYREJECTED;
 559        case MAC_IMPROPER_SECURITY_LEVEL:
 560        case MAC_UNSUPPORTED_LEGACY:
 561        case MAC_DENIED:
 562                return -EACCES;
 563        case MAC_BEACON_LOST:
 564        case MAC_NO_ACK:
 565        case MAC_NO_BEACON:
 566                return -ENETUNREACH;
 567        case MAC_CHANNEL_ACCESS_FAILURE:
 568        case MAC_TX_ACTIVE:
 569        case MAC_SCAN_IN_PROGRESS:
 570                return -EBUSY;
 571        case MAC_DISABLE_TRX_FAILURE:
 572        case MAC_OUT_OF_CAP:
 573                return -EAGAIN;
 574        case MAC_FRAME_TOO_LONG:
 575                return -EMSGSIZE;
 576        case MAC_INVALID_GTS:
 577        case MAC_PAST_TIME:
 578                return -EBADSLT;
 579        case MAC_INVALID_HANDLE:
 580                return -EBADMSG;
 581        case MAC_INVALID_PARAMETER:
 582        case MAC_UNSUPPORTED_ATTRIBUTE:
 583        case MAC_ON_TIME_TOO_LONG:
 584        case MAC_INVALID_INDEX:
 585                return -EINVAL;
 586        case MAC_NO_DATA:
 587                return -ENODATA;
 588        case MAC_NO_SHORT_ADDRESS:
 589                return -EFAULT;
 590        case MAC_PAN_ID_CONFLICT:
 591                return -EADDRINUSE;
 592        case MAC_TRANSACTION_EXPIRED:
 593                return -ETIME;
 594        case MAC_TRANSACTION_OVERFLOW:
 595                return -ENOBUFS;
 596        case MAC_UNAVAILABLE_KEY:
 597                return -ENOKEY;
 598        case MAC_INVALID_ADDRESS:
 599                return -ENXIO;
 600        case MAC_TRACKING_OFF:
 601        case MAC_SUPERFRAME_OVERLAP:
 602                return -EREMOTEIO;
 603        case MAC_LIMIT_REACHED:
 604                return -EDQUOT;
 605        case MAC_READ_ONLY:
 606                return -EROFS;
 607        default:
 608                return -EPROTO;
 609        }
 610}
 611
 612/**
 613 * ca8210_test_int_driver_write() - Writes a message to the test interface to be
 614 *                                  read by the userspace
 615 * @buf:  Buffer containing upstream message
 616 * @len:  length of message to write
 617 * @spi:  SPI device of message originator
 618 *
 619 * Return: 0 or linux error code
 620 */
 621static int ca8210_test_int_driver_write(
 622        const u8       *buf,
 623        size_t          len,
 624        void           *spi
 625)
 626{
 627        struct ca8210_priv *priv = spi_get_drvdata(spi);
 628        struct ca8210_test *test = &priv->test;
 629        char *fifo_buffer;
 630        int i;
 631
 632        dev_dbg(
 633                &priv->spi->dev,
 634                "test_interface: Buffering upstream message:\n"
 635        );
 636        for (i = 0; i < len; i++)
 637                dev_dbg(&priv->spi->dev, "%#03x\n", buf[i]);
 638
 639        fifo_buffer = kmemdup(buf, len, GFP_KERNEL);
 640        if (!fifo_buffer)
 641                return -ENOMEM;
 642        kfifo_in(&test->up_fifo, &fifo_buffer, 4);
 643        wake_up_interruptible(&priv->test.readq);
 644
 645        return 0;
 646}
 647
 648/* SPI Operation */
 649
 650static int ca8210_net_rx(
 651        struct ieee802154_hw  *hw,
 652        u8                    *command,
 653        size_t                 len
 654);
 655static u8 mlme_reset_request_sync(
 656        u8       set_default_pib,
 657        void    *device_ref
 658);
 659static int ca8210_spi_transfer(
 660        struct spi_device *spi,
 661        const u8          *buf,
 662        size_t             len
 663);
 664
 665/**
 666 * ca8210_reset_send() - Hard resets the ca8210 for a given time
 667 * @spi:  Pointer to target ca8210 spi device
 668 * @ms:   Milliseconds to hold the reset line low for
 669 */
 670static void ca8210_reset_send(struct spi_device *spi, unsigned int ms)
 671{
 672        struct ca8210_platform_data *pdata = spi->dev.platform_data;
 673        struct ca8210_priv *priv = spi_get_drvdata(spi);
 674        long status;
 675
 676        gpio_set_value(pdata->gpio_reset, 0);
 677        reinit_completion(&priv->ca8210_is_awake);
 678        msleep(ms);
 679        gpio_set_value(pdata->gpio_reset, 1);
 680        priv->promiscuous = false;
 681
 682        /* Wait until wakeup indication seen */
 683        status = wait_for_completion_interruptible_timeout(
 684                &priv->ca8210_is_awake,
 685                msecs_to_jiffies(CA8210_SYNC_TIMEOUT)
 686        );
 687        if (status == 0) {
 688                dev_crit(
 689                        &spi->dev,
 690                        "Fatal: No wakeup from ca8210 after reset!\n"
 691                );
 692        }
 693
 694        dev_dbg(&spi->dev, "Reset the device\n");
 695}
 696
 697/**
 698 * ca8210_mlme_reset_worker() - Resets the MLME, Called when the MAC OVERFLOW
 699 *                              condition happens.
 700 * @work:  Pointer to work being executed
 701 */
 702static void ca8210_mlme_reset_worker(struct work_struct *work)
 703{
 704        struct work_priv_container *wpc = container_of(
 705                work,
 706                struct work_priv_container,
 707                work
 708        );
 709        struct ca8210_priv *priv = wpc->priv;
 710
 711        mlme_reset_request_sync(0, priv->spi);
 712        kfree(wpc);
 713}
 714
 715/**
 716 * ca8210_rx_done() - Calls various message dispatches responding to a received
 717 *                    command
 718 * @cas_ctl: Pointer to the cas_control object for the relevant spi transfer
 719 *
 720 * Presents a received SAP command from the ca8210 to the Cascoda EVBME, test
 721 * interface and network driver.
 722 */
 723static void ca8210_rx_done(struct cas_control *cas_ctl)
 724{
 725        u8 *buf;
 726        unsigned int len;
 727        struct work_priv_container *mlme_reset_wpc;
 728        struct ca8210_priv *priv = cas_ctl->priv;
 729
 730        buf = cas_ctl->tx_in_buf;
 731        len = buf[1] + 2;
 732        if (len > CA8210_SPI_BUF_SIZE) {
 733                dev_crit(
 734                        &priv->spi->dev,
 735                        "Received packet len (%u) erroneously long\n",
 736                        len
 737                );
 738                goto finish;
 739        }
 740
 741        if (buf[0] & SPI_SYN) {
 742                if (priv->sync_command_response) {
 743                        memcpy(priv->sync_command_response, buf, len);
 744                        complete(&priv->sync_exchange_complete);
 745                } else {
 746                        if (cascoda_api_upstream)
 747                                cascoda_api_upstream(buf, len, priv->spi);
 748                        priv->sync_up++;
 749                }
 750        } else {
 751                if (cascoda_api_upstream)
 752                        cascoda_api_upstream(buf, len, priv->spi);
 753        }
 754
 755        ca8210_net_rx(priv->hw, buf, len);
 756        if (buf[0] == SPI_MCPS_DATA_CONFIRM) {
 757                if (buf[3] == MAC_TRANSACTION_OVERFLOW) {
 758                        dev_info(
 759                                &priv->spi->dev,
 760                                "Waiting for transaction overflow to stabilise...\n");
 761                        msleep(2000);
 762                        dev_info(
 763                                &priv->spi->dev,
 764                                "Resetting MAC...\n");
 765
 766                        mlme_reset_wpc = kmalloc(sizeof(*mlme_reset_wpc),
 767                                                 GFP_KERNEL);
 768                        if (!mlme_reset_wpc)
 769                                goto finish;
 770                        INIT_WORK(
 771                                &mlme_reset_wpc->work,
 772                                ca8210_mlme_reset_worker
 773                        );
 774                        mlme_reset_wpc->priv = priv;
 775                        queue_work(priv->mlme_workqueue, &mlme_reset_wpc->work);
 776                }
 777        } else if (buf[0] == SPI_HWME_WAKEUP_INDICATION) {
 778                dev_notice(
 779                        &priv->spi->dev,
 780                        "Wakeup indication received, reason:\n"
 781                );
 782                switch (buf[2]) {
 783                case 0:
 784                        dev_notice(
 785                                &priv->spi->dev,
 786                                "Transceiver woken up from Power Up / System Reset\n"
 787                        );
 788                        break;
 789                case 1:
 790                        dev_notice(
 791                                &priv->spi->dev,
 792                                "Watchdog Timer Time-Out\n"
 793                        );
 794                        break;
 795                case 2:
 796                        dev_notice(
 797                                &priv->spi->dev,
 798                                "Transceiver woken up from Power-Off by Sleep Timer Time-Out\n");
 799                        break;
 800                case 3:
 801                        dev_notice(
 802                                &priv->spi->dev,
 803                                "Transceiver woken up from Power-Off by GPIO Activity\n"
 804                        );
 805                        break;
 806                case 4:
 807                        dev_notice(
 808                                &priv->spi->dev,
 809                                "Transceiver woken up from Standby by Sleep Timer Time-Out\n"
 810                        );
 811                        break;
 812                case 5:
 813                        dev_notice(
 814                                &priv->spi->dev,
 815                                "Transceiver woken up from Standby by GPIO Activity\n"
 816                        );
 817                        break;
 818                case 6:
 819                        dev_notice(
 820                                &priv->spi->dev,
 821                                "Sleep-Timer Time-Out in Active Mode\n"
 822                        );
 823                        break;
 824                default:
 825                        dev_warn(&priv->spi->dev, "Wakeup reason unknown\n");
 826                        break;
 827                }
 828                complete(&priv->ca8210_is_awake);
 829        }
 830
 831finish:;
 832}
 833
 834static int ca8210_remove(struct spi_device *spi_device);
 835
 836/**
 837 * ca8210_spi_transfer_complete() - Called when a single spi transfer has
 838 *                                  completed
 839 * @context:  Pointer to the cas_control object for the finished transfer
 840 */
 841static void ca8210_spi_transfer_complete(void *context)
 842{
 843        struct cas_control *cas_ctl = context;
 844        struct ca8210_priv *priv = cas_ctl->priv;
 845        bool duplex_rx = false;
 846        int i;
 847        u8 retry_buffer[CA8210_SPI_BUF_SIZE];
 848
 849        if (
 850                cas_ctl->tx_in_buf[0] == SPI_NACK ||
 851                (cas_ctl->tx_in_buf[0] == SPI_IDLE &&
 852                cas_ctl->tx_in_buf[1] == SPI_NACK)
 853        ) {
 854                /* ca8210 is busy */
 855                dev_info(&priv->spi->dev, "ca8210 was busy during attempted write\n");
 856                if (cas_ctl->tx_buf[0] == SPI_IDLE) {
 857                        dev_warn(
 858                                &priv->spi->dev,
 859                                "IRQ servicing NACKd, dropping transfer\n"
 860                        );
 861                        kfree(cas_ctl);
 862                        return;
 863                }
 864                if (priv->retries > 3) {
 865                        dev_err(&priv->spi->dev, "too many retries!\n");
 866                        kfree(cas_ctl);
 867                        ca8210_remove(priv->spi);
 868                        return;
 869                }
 870                memcpy(retry_buffer, cas_ctl->tx_buf, CA8210_SPI_BUF_SIZE);
 871                kfree(cas_ctl);
 872                ca8210_spi_transfer(
 873                        priv->spi,
 874                        retry_buffer,
 875                        CA8210_SPI_BUF_SIZE
 876                );
 877                priv->retries++;
 878                dev_info(&priv->spi->dev, "retried spi write\n");
 879                return;
 880        } else if (
 881                        cas_ctl->tx_in_buf[0] != SPI_IDLE &&
 882                        cas_ctl->tx_in_buf[0] != SPI_NACK
 883                ) {
 884                duplex_rx = true;
 885        }
 886
 887        if (duplex_rx) {
 888                dev_dbg(&priv->spi->dev, "READ CMD DURING TX\n");
 889                for (i = 0; i < cas_ctl->tx_in_buf[1] + 2; i++)
 890                        dev_dbg(
 891                                &priv->spi->dev,
 892                                "%#03x\n",
 893                                cas_ctl->tx_in_buf[i]
 894                        );
 895                ca8210_rx_done(cas_ctl);
 896        }
 897        complete(&priv->spi_transfer_complete);
 898        kfree(cas_ctl);
 899        priv->retries = 0;
 900}
 901
 902/**
 903 * ca8210_spi_transfer() - Initiate duplex spi transfer with ca8210
 904 * @spi: Pointer to spi device for transfer
 905 * @buf: Octet array to send
 906 * @len: length of the buffer being sent
 907 *
 908 * Return: 0 or linux error code
 909 */
 910static int ca8210_spi_transfer(
 911        struct spi_device  *spi,
 912        const u8           *buf,
 913        size_t              len
 914)
 915{
 916        int i, status = 0;
 917        struct ca8210_priv *priv;
 918        struct cas_control *cas_ctl;
 919
 920        if (!spi) {
 921                pr_crit("NULL spi device passed to %s\n", __func__);
 922                return -ENODEV;
 923        }
 924
 925        priv = spi_get_drvdata(spi);
 926        reinit_completion(&priv->spi_transfer_complete);
 927
 928        dev_dbg(&spi->dev, "%s called\n", __func__);
 929
 930        cas_ctl = kmalloc(sizeof(*cas_ctl), GFP_ATOMIC);
 931        if (!cas_ctl)
 932                return -ENOMEM;
 933
 934        cas_ctl->priv = priv;
 935        memset(cas_ctl->tx_buf, SPI_IDLE, CA8210_SPI_BUF_SIZE);
 936        memset(cas_ctl->tx_in_buf, SPI_IDLE, CA8210_SPI_BUF_SIZE);
 937        memcpy(cas_ctl->tx_buf, buf, len);
 938
 939        for (i = 0; i < len; i++)
 940                dev_dbg(&spi->dev, "%#03x\n", cas_ctl->tx_buf[i]);
 941
 942        spi_message_init(&cas_ctl->msg);
 943
 944        cas_ctl->transfer.tx_nbits = 1; /* 1 MOSI line */
 945        cas_ctl->transfer.rx_nbits = 1; /* 1 MISO line */
 946        cas_ctl->transfer.speed_hz = 0; /* Use device setting */
 947        cas_ctl->transfer.bits_per_word = 0; /* Use device setting */
 948        cas_ctl->transfer.tx_buf = cas_ctl->tx_buf;
 949        cas_ctl->transfer.rx_buf = cas_ctl->tx_in_buf;
 950        cas_ctl->transfer.delay.value = 0;
 951        cas_ctl->transfer.delay.unit = SPI_DELAY_UNIT_USECS;
 952        cas_ctl->transfer.cs_change = 0;
 953        cas_ctl->transfer.len = sizeof(struct mac_message);
 954        cas_ctl->msg.complete = ca8210_spi_transfer_complete;
 955        cas_ctl->msg.context = cas_ctl;
 956
 957        spi_message_add_tail(
 958                &cas_ctl->transfer,
 959                &cas_ctl->msg
 960        );
 961
 962        status = spi_async(spi, &cas_ctl->msg);
 963        if (status < 0) {
 964                dev_crit(
 965                        &spi->dev,
 966                        "status %d from spi_sync in write\n",
 967                        status
 968                );
 969        }
 970
 971        return status;
 972}
 973
 974/**
 975 * ca8210_spi_exchange() - Exchange API/SAP commands with the radio
 976 * @buf:         Octet array of command being sent downstream
 977 * @len:         length of buf
 978 * @response:    buffer for storing synchronous response
 979 * @device_ref:  spi_device pointer for ca8210
 980 *
 981 * Effectively calls ca8210_spi_transfer to write buf[] to the spi, then for
 982 * synchronous commands waits for the corresponding response to be read from
 983 * the spi before returning. The response is written to the response parameter.
 984 *
 985 * Return: 0 or linux error code
 986 */
 987static int ca8210_spi_exchange(
 988        const u8 *buf,
 989        size_t len,
 990        u8 *response,
 991        void *device_ref
 992)
 993{
 994        int status = 0;
 995        struct spi_device *spi = device_ref;
 996        struct ca8210_priv *priv = spi->dev.driver_data;
 997        long wait_remaining;
 998
 999        if ((buf[0] & SPI_SYN) && response) { /* if sync wait for confirm */
1000                reinit_completion(&priv->sync_exchange_complete);
1001                priv->sync_command_response = response;
1002        }
1003
1004        do {
1005                reinit_completion(&priv->spi_transfer_complete);
1006                status = ca8210_spi_transfer(priv->spi, buf, len);
1007                if (status) {
1008                        dev_warn(
1009                                &spi->dev,
1010                                "spi write failed, returned %d\n",
1011                                status
1012                        );
1013                        if (status == -EBUSY)
1014                                continue;
1015                        if (((buf[0] & SPI_SYN) && response))
1016                                complete(&priv->sync_exchange_complete);
1017                        goto cleanup;
1018                }
1019
1020                wait_remaining = wait_for_completion_interruptible_timeout(
1021                        &priv->spi_transfer_complete,
1022                        msecs_to_jiffies(1000)
1023                );
1024                if (wait_remaining == -ERESTARTSYS) {
1025                        status = -ERESTARTSYS;
1026                } else if (wait_remaining == 0) {
1027                        dev_err(
1028                                &spi->dev,
1029                                "SPI downstream transfer timed out!\n"
1030                        );
1031                        status = -ETIME;
1032                        goto cleanup;
1033                }
1034        } while (status < 0);
1035
1036        if (!((buf[0] & SPI_SYN) && response))
1037                goto cleanup;
1038
1039        wait_remaining = wait_for_completion_interruptible_timeout(
1040                &priv->sync_exchange_complete,
1041                msecs_to_jiffies(CA8210_SYNC_TIMEOUT)
1042        );
1043        if (wait_remaining == -ERESTARTSYS) {
1044                status = -ERESTARTSYS;
1045        } else if (wait_remaining == 0) {
1046                dev_err(
1047                        &spi->dev,
1048                        "Synchronous confirm timeout\n"
1049                );
1050                status = -ETIME;
1051        }
1052
1053cleanup:
1054        priv->sync_command_response = NULL;
1055        return status;
1056}
1057
1058/**
1059 * ca8210_interrupt_handler() - Called when an irq is received from the ca8210
1060 * @irq:     Id of the irq being handled
1061 * @dev_id:  Pointer passed by the system, pointing to the ca8210's private data
1062 *
1063 * This function is called when the irq line from the ca8210 is asserted,
1064 * signifying that the ca8210 has a message to send upstream to us. Starts the
1065 * asynchronous spi read.
1066 *
1067 * Return: irq return code
1068 */
1069static irqreturn_t ca8210_interrupt_handler(int irq, void *dev_id)
1070{
1071        struct ca8210_priv *priv = dev_id;
1072        int status;
1073
1074        dev_dbg(&priv->spi->dev, "irq: Interrupt occurred\n");
1075        do {
1076                status = ca8210_spi_transfer(priv->spi, NULL, 0);
1077                if (status && (status != -EBUSY)) {
1078                        dev_warn(
1079                                &priv->spi->dev,
1080                                "spi read failed, returned %d\n",
1081                                status
1082                        );
1083                }
1084        } while (status == -EBUSY);
1085        return IRQ_HANDLED;
1086}
1087
1088static int (*cascoda_api_downstream)(
1089        const u8 *buf,
1090        size_t len,
1091        u8 *response,
1092        void *device_ref
1093) = ca8210_spi_exchange;
1094
1095/* Cascoda API / 15.4 SAP Primitives */
1096
1097/**
1098 * tdme_setsfr_request_sync() - TDME_SETSFR_request/confirm according to API
1099 * @sfr_page:    SFR Page
1100 * @sfr_address: SFR Address
1101 * @sfr_value:   SFR Value
1102 * @device_ref:  Nondescript pointer to target device
1103 *
1104 * Return: 802.15.4 status code of TDME-SETSFR.confirm
1105 */
1106static u8 tdme_setsfr_request_sync(
1107        u8            sfr_page,
1108        u8            sfr_address,
1109        u8            sfr_value,
1110        void         *device_ref
1111)
1112{
1113        int ret;
1114        struct mac_message command, response;
1115        struct spi_device *spi = device_ref;
1116
1117        command.command_id = SPI_TDME_SETSFR_REQUEST;
1118        command.length = 3;
1119        command.pdata.tdme_set_sfr_req.sfr_page    = sfr_page;
1120        command.pdata.tdme_set_sfr_req.sfr_address = sfr_address;
1121        command.pdata.tdme_set_sfr_req.sfr_value   = sfr_value;
1122        response.command_id = SPI_IDLE;
1123        ret = cascoda_api_downstream(
1124                &command.command_id,
1125                command.length + 2,
1126                &response.command_id,
1127                device_ref
1128        );
1129        if (ret) {
1130                dev_crit(&spi->dev, "cascoda_api_downstream returned %d", ret);
1131                return MAC_SYSTEM_ERROR;
1132        }
1133
1134        if (response.command_id != SPI_TDME_SETSFR_CONFIRM) {
1135                dev_crit(
1136                        &spi->dev,
1137                        "sync response to SPI_TDME_SETSFR_REQUEST was not SPI_TDME_SETSFR_CONFIRM, it was %d\n",
1138                        response.command_id
1139                );
1140                return MAC_SYSTEM_ERROR;
1141        }
1142
1143        return response.pdata.tdme_set_sfr_cnf.status;
1144}
1145
1146/**
1147 * tdme_chipinit() - TDME Chip Register Default Initialisation Macro
1148 * @device_ref: Nondescript pointer to target device
1149 *
1150 * Return: 802.15.4 status code of API calls
1151 */
1152static u8 tdme_chipinit(void *device_ref)
1153{
1154        u8 status = MAC_SUCCESS;
1155        u8 sfr_address;
1156        struct spi_device *spi = device_ref;
1157        struct preamble_cfg_sfr pre_cfg_value = {
1158                .timeout_symbols     = 3,
1159                .acquisition_symbols = 3,
1160                .search_symbols      = 1,
1161        };
1162        /* LNA Gain Settings */
1163        status = tdme_setsfr_request_sync(
1164                1, (sfr_address = CA8210_SFR_LNAGX40),
1165                LNAGX40_DEFAULT_GAIN, device_ref);
1166        if (status)
1167                goto finish;
1168        status = tdme_setsfr_request_sync(
1169                1, (sfr_address = CA8210_SFR_LNAGX41),
1170                LNAGX41_DEFAULT_GAIN, device_ref);
1171        if (status)
1172                goto finish;
1173        status = tdme_setsfr_request_sync(
1174                1, (sfr_address = CA8210_SFR_LNAGX42),
1175                LNAGX42_DEFAULT_GAIN, device_ref);
1176        if (status)
1177                goto finish;
1178        status = tdme_setsfr_request_sync(
1179                1, (sfr_address = CA8210_SFR_LNAGX43),
1180                LNAGX43_DEFAULT_GAIN, device_ref);
1181        if (status)
1182                goto finish;
1183        status = tdme_setsfr_request_sync(
1184                1, (sfr_address = CA8210_SFR_LNAGX44),
1185                LNAGX44_DEFAULT_GAIN, device_ref);
1186        if (status)
1187                goto finish;
1188        status = tdme_setsfr_request_sync(
1189                1, (sfr_address = CA8210_SFR_LNAGX45),
1190                LNAGX45_DEFAULT_GAIN, device_ref);
1191        if (status)
1192                goto finish;
1193        status = tdme_setsfr_request_sync(
1194                1, (sfr_address = CA8210_SFR_LNAGX46),
1195                LNAGX46_DEFAULT_GAIN, device_ref);
1196        if (status)
1197                goto finish;
1198        status = tdme_setsfr_request_sync(
1199                1, (sfr_address = CA8210_SFR_LNAGX47),
1200                LNAGX47_DEFAULT_GAIN, device_ref);
1201        if (status)
1202                goto finish;
1203        /* Preamble Timing Config */
1204        status = tdme_setsfr_request_sync(
1205                1, (sfr_address = CA8210_SFR_PRECFG),
1206                *((u8 *)&pre_cfg_value), device_ref);
1207        if (status)
1208                goto finish;
1209        /* Preamble Threshold High */
1210        status = tdme_setsfr_request_sync(
1211                1, (sfr_address = CA8210_SFR_PTHRH),
1212                PTHRH_DEFAULT_THRESHOLD, device_ref);
1213        if (status)
1214                goto finish;
1215        /* Tx Output Power 8 dBm */
1216        status = tdme_setsfr_request_sync(
1217                0, (sfr_address = CA8210_SFR_PACFGIB),
1218                PACFGIB_DEFAULT_CURRENT, device_ref);
1219        if (status)
1220                goto finish;
1221
1222finish:
1223        if (status != MAC_SUCCESS) {
1224                dev_err(
1225                        &spi->dev,
1226                        "failed to set sfr at %#03x, status = %#03x\n",
1227                        sfr_address,
1228                        status
1229                );
1230        }
1231        return status;
1232}
1233
1234/**
1235 * tdme_channelinit() - TDME Channel Register Default Initialisation Macro (Tx)
1236 * @channel:    802.15.4 channel to initialise chip for
1237 * @device_ref: Nondescript pointer to target device
1238 *
1239 * Return: 802.15.4 status code of API calls
1240 */
1241static u8 tdme_channelinit(u8 channel, void *device_ref)
1242{
1243        /* Transceiver front-end local oscillator tx two-point calibration
1244         * value. Tuned for the hardware.
1245         */
1246        u8 txcalval;
1247
1248        if (channel >= 25)
1249                txcalval = 0xA7;
1250        else if (channel >= 23)
1251                txcalval = 0xA8;
1252        else if (channel >= 22)
1253                txcalval = 0xA9;
1254        else if (channel >= 20)
1255                txcalval = 0xAA;
1256        else if (channel >= 17)
1257                txcalval = 0xAB;
1258        else if (channel >= 16)
1259                txcalval = 0xAC;
1260        else if (channel >= 14)
1261                txcalval = 0xAD;
1262        else if (channel >= 12)
1263                txcalval = 0xAE;
1264        else
1265                txcalval = 0xAF;
1266
1267        return tdme_setsfr_request_sync(
1268                1,
1269                CA8210_SFR_LOTXCAL,
1270                txcalval,
1271                device_ref
1272        );  /* LO Tx Cal */
1273}
1274
1275/**
1276 * tdme_checkpibattribute() - Checks Attribute Values that are not checked in
1277 *                            MAC
1278 * @pib_attribute:        Attribute Number
1279 * @pib_attribute_length: Attribute length
1280 * @pib_attribute_value:  Pointer to Attribute Value
1281 *
1282 * Return: 802.15.4 status code of checks
1283 */
1284static u8 tdme_checkpibattribute(
1285        u8            pib_attribute,
1286        u8            pib_attribute_length,
1287        const void   *pib_attribute_value
1288)
1289{
1290        u8 status = MAC_SUCCESS;
1291        u8 value;
1292
1293        value  = *((u8 *)pib_attribute_value);
1294
1295        switch (pib_attribute) {
1296        /* PHY */
1297        case PHY_TRANSMIT_POWER:
1298                if (value > 0x3F)
1299                        status = MAC_INVALID_PARAMETER;
1300                break;
1301        case PHY_CCA_MODE:
1302                if (value > 0x03)
1303                        status = MAC_INVALID_PARAMETER;
1304                break;
1305        /* MAC */
1306        case MAC_BATT_LIFE_EXT_PERIODS:
1307                if (value < 6 || value > 41)
1308                        status = MAC_INVALID_PARAMETER;
1309                break;
1310        case MAC_BEACON_PAYLOAD:
1311                if (pib_attribute_length > MAX_BEACON_PAYLOAD_LENGTH)
1312                        status = MAC_INVALID_PARAMETER;
1313                break;
1314        case MAC_BEACON_PAYLOAD_LENGTH:
1315                if (value > MAX_BEACON_PAYLOAD_LENGTH)
1316                        status = MAC_INVALID_PARAMETER;
1317                break;
1318        case MAC_BEACON_ORDER:
1319                if (value > 15)
1320                        status = MAC_INVALID_PARAMETER;
1321                break;
1322        case MAC_MAX_BE:
1323                if (value < 3 || value > 8)
1324                        status = MAC_INVALID_PARAMETER;
1325                break;
1326        case MAC_MAX_CSMA_BACKOFFS:
1327                if (value > 5)
1328                        status = MAC_INVALID_PARAMETER;
1329                break;
1330        case MAC_MAX_FRAME_RETRIES:
1331                if (value > 7)
1332                        status = MAC_INVALID_PARAMETER;
1333                break;
1334        case MAC_MIN_BE:
1335                if (value > 8)
1336                        status = MAC_INVALID_PARAMETER;
1337                break;
1338        case MAC_RESPONSE_WAIT_TIME:
1339                if (value < 2 || value > 64)
1340                        status = MAC_INVALID_PARAMETER;
1341                break;
1342        case MAC_SUPERFRAME_ORDER:
1343                if (value > 15)
1344                        status = MAC_INVALID_PARAMETER;
1345                break;
1346        /* boolean */
1347        case MAC_ASSOCIATED_PAN_COORD:
1348        case MAC_ASSOCIATION_PERMIT:
1349        case MAC_AUTO_REQUEST:
1350        case MAC_BATT_LIFE_EXT:
1351        case MAC_GTS_PERMIT:
1352        case MAC_PROMISCUOUS_MODE:
1353        case MAC_RX_ON_WHEN_IDLE:
1354        case MAC_SECURITY_ENABLED:
1355                if (value > 1)
1356                        status = MAC_INVALID_PARAMETER;
1357                break;
1358        /* MAC SEC */
1359        case MAC_AUTO_REQUEST_SECURITY_LEVEL:
1360                if (value > 7)
1361                        status = MAC_INVALID_PARAMETER;
1362                break;
1363        case MAC_AUTO_REQUEST_KEY_ID_MODE:
1364                if (value > 3)
1365                        status = MAC_INVALID_PARAMETER;
1366                break;
1367        default:
1368                break;
1369        }
1370
1371        return status;
1372}
1373
1374/**
1375 * tdme_settxpower() - Sets the tx power for MLME_SET phyTransmitPower
1376 * @txp:        Transmit Power
1377 * @device_ref: Nondescript pointer to target device
1378 *
1379 * Normalised to 802.15.4 Definition (6-bit, signed):
1380 * Bit 7-6: not used
1381 * Bit 5-0: tx power (-32 - +31 dB)
1382 *
1383 * Return: 802.15.4 status code of api calls
1384 */
1385static u8 tdme_settxpower(u8 txp, void *device_ref)
1386{
1387        u8 status;
1388        s8 txp_val;
1389        u8 txp_ext;
1390        union pa_cfg_sfr pa_cfg_val;
1391
1392        /* extend from 6 to 8 bit */
1393        txp_ext = 0x3F & txp;
1394        if (txp_ext & 0x20)
1395                txp_ext += 0xC0;
1396        txp_val = (s8)txp_ext;
1397
1398        if (CA8210_MAC_MPW) {
1399                if (txp_val > 0) {
1400                        /* 8 dBm: ptrim = 5, itrim = +3 => +4 dBm */
1401                        pa_cfg_val.bias_current_trim     = 3;
1402                        pa_cfg_val.buffer_capacitor_trim = 5;
1403                        pa_cfg_val.boost                 = 1;
1404                } else {
1405                        /* 0 dBm: ptrim = 7, itrim = +3 => -6 dBm */
1406                        pa_cfg_val.bias_current_trim     = 3;
1407                        pa_cfg_val.buffer_capacitor_trim = 7;
1408                        pa_cfg_val.boost                 = 0;
1409                }
1410                /* write PACFG */
1411                status = tdme_setsfr_request_sync(
1412                        0,
1413                        CA8210_SFR_PACFG,
1414                        pa_cfg_val.paib,
1415                        device_ref
1416                );
1417        } else {
1418                /* Look-Up Table for Setting Current and Frequency Trim values
1419                 * for desired Output Power
1420                 */
1421                if (txp_val > 8) {
1422                        pa_cfg_val.paib = 0x3F;
1423                } else if (txp_val == 8) {
1424                        pa_cfg_val.paib = 0x32;
1425                } else if (txp_val == 7) {
1426                        pa_cfg_val.paib = 0x22;
1427                } else if (txp_val == 6) {
1428                        pa_cfg_val.paib = 0x18;
1429                } else if (txp_val == 5) {
1430                        pa_cfg_val.paib = 0x10;
1431                } else if (txp_val == 4) {
1432                        pa_cfg_val.paib = 0x0C;
1433                } else if (txp_val == 3) {
1434                        pa_cfg_val.paib = 0x08;
1435                } else if (txp_val == 2) {
1436                        pa_cfg_val.paib = 0x05;
1437                } else if (txp_val == 1) {
1438                        pa_cfg_val.paib = 0x03;
1439                } else if (txp_val == 0) {
1440                        pa_cfg_val.paib = 0x01;
1441                } else { /* < 0 */
1442                        pa_cfg_val.paib = 0x00;
1443                }
1444                /* write PACFGIB */
1445                status = tdme_setsfr_request_sync(
1446                        0,
1447                        CA8210_SFR_PACFGIB,
1448                        pa_cfg_val.paib,
1449                        device_ref
1450                );
1451        }
1452
1453        return status;
1454}
1455
1456/**
1457 * mcps_data_request() - mcps_data_request (Send Data) according to API Spec
1458 * @src_addr_mode:    Source Addressing Mode
1459 * @dst_address_mode: Destination Addressing Mode
1460 * @dst_pan_id:       Destination PAN ID
1461 * @dst_addr:         Pointer to Destination Address
1462 * @msdu_length:      length of Data
1463 * @msdu:             Pointer to Data
1464 * @msdu_handle:      Handle of Data
1465 * @tx_options:       Tx Options Bit Field
1466 * @security:         Pointer to Security Structure or NULL
1467 * @device_ref:       Nondescript pointer to target device
1468 *
1469 * Return: 802.15.4 status code of action
1470 */
1471static u8 mcps_data_request(
1472        u8               src_addr_mode,
1473        u8               dst_address_mode,
1474        u16              dst_pan_id,
1475        union macaddr   *dst_addr,
1476        u8               msdu_length,
1477        u8              *msdu,
1478        u8               msdu_handle,
1479        u8               tx_options,
1480        struct secspec  *security,
1481        void            *device_ref
1482)
1483{
1484        struct secspec *psec;
1485        struct mac_message command;
1486
1487        command.command_id = SPI_MCPS_DATA_REQUEST;
1488        command.pdata.data_req.src_addr_mode = src_addr_mode;
1489        command.pdata.data_req.dst.mode = dst_address_mode;
1490        if (dst_address_mode != MAC_MODE_NO_ADDR) {
1491                command.pdata.data_req.dst.pan_id[0] = LS_BYTE(dst_pan_id);
1492                command.pdata.data_req.dst.pan_id[1] = MS_BYTE(dst_pan_id);
1493                if (dst_address_mode == MAC_MODE_SHORT_ADDR) {
1494                        command.pdata.data_req.dst.address[0] = LS_BYTE(
1495                                dst_addr->short_address
1496                        );
1497                        command.pdata.data_req.dst.address[1] = MS_BYTE(
1498                                dst_addr->short_address
1499                        );
1500                } else {   /* MAC_MODE_LONG_ADDR*/
1501                        memcpy(
1502                                command.pdata.data_req.dst.address,
1503                                dst_addr->ieee_address,
1504                                8
1505                        );
1506                }
1507        }
1508        command.pdata.data_req.msdu_length = msdu_length;
1509        command.pdata.data_req.msdu_handle = msdu_handle;
1510        command.pdata.data_req.tx_options = tx_options;
1511        memcpy(command.pdata.data_req.msdu, msdu, msdu_length);
1512        psec = (struct secspec *)(command.pdata.data_req.msdu + msdu_length);
1513        command.length = sizeof(struct mcps_data_request_pset) -
1514                MAX_DATA_SIZE + msdu_length;
1515        if (!security || security->security_level == 0) {
1516                psec->security_level = 0;
1517                command.length += 1;
1518        } else {
1519                *psec = *security;
1520                command.length += sizeof(struct secspec);
1521        }
1522
1523        if (ca8210_spi_transfer(device_ref, &command.command_id,
1524                                command.length + 2))
1525                return MAC_SYSTEM_ERROR;
1526
1527        return MAC_SUCCESS;
1528}
1529
1530/**
1531 * mlme_reset_request_sync() - MLME_RESET_request/confirm according to API Spec
1532 * @set_default_pib: Set defaults in PIB
1533 * @device_ref:      Nondescript pointer to target device
1534 *
1535 * Return: 802.15.4 status code of MLME-RESET.confirm
1536 */
1537static u8 mlme_reset_request_sync(
1538        u8    set_default_pib,
1539        void *device_ref
1540)
1541{
1542        u8 status;
1543        struct mac_message command, response;
1544        struct spi_device *spi = device_ref;
1545
1546        command.command_id = SPI_MLME_RESET_REQUEST;
1547        command.length = 1;
1548        command.pdata.u8param = set_default_pib;
1549
1550        if (cascoda_api_downstream(
1551                &command.command_id,
1552                command.length + 2,
1553                &response.command_id,
1554                device_ref)) {
1555                dev_err(&spi->dev, "cascoda_api_downstream failed\n");
1556                return MAC_SYSTEM_ERROR;
1557        }
1558
1559        if (response.command_id != SPI_MLME_RESET_CONFIRM)
1560                return MAC_SYSTEM_ERROR;
1561
1562        status = response.pdata.status;
1563
1564        /* reset COORD Bit for Channel Filtering as Coordinator */
1565        if (CA8210_MAC_WORKAROUNDS && set_default_pib && !status) {
1566                status = tdme_setsfr_request_sync(
1567                        0,
1568                        CA8210_SFR_MACCON,
1569                        0,
1570                        device_ref
1571                );
1572        }
1573
1574        return status;
1575}
1576
1577/**
1578 * mlme_set_request_sync() - MLME_SET_request/confirm according to API Spec
1579 * @pib_attribute:        Attribute Number
1580 * @pib_attribute_index:  Index within Attribute if an Array
1581 * @pib_attribute_length: Attribute length
1582 * @pib_attribute_value:  Pointer to Attribute Value
1583 * @device_ref:           Nondescript pointer to target device
1584 *
1585 * Return: 802.15.4 status code of MLME-SET.confirm
1586 */
1587static u8 mlme_set_request_sync(
1588        u8            pib_attribute,
1589        u8            pib_attribute_index,
1590        u8            pib_attribute_length,
1591        const void   *pib_attribute_value,
1592        void         *device_ref
1593)
1594{
1595        u8 status;
1596        struct mac_message command, response;
1597
1598        /* pre-check the validity of pib_attribute values that are not checked
1599         * in MAC
1600         */
1601        if (tdme_checkpibattribute(
1602                pib_attribute, pib_attribute_length, pib_attribute_value)) {
1603                return MAC_INVALID_PARAMETER;
1604        }
1605
1606        if (pib_attribute == PHY_CURRENT_CHANNEL) {
1607                status = tdme_channelinit(
1608                        *((u8 *)pib_attribute_value),
1609                        device_ref
1610                );
1611                if (status)
1612                        return status;
1613        }
1614
1615        if (pib_attribute == PHY_TRANSMIT_POWER) {
1616                return tdme_settxpower(
1617                        *((u8 *)pib_attribute_value),
1618                        device_ref
1619                );
1620        }
1621
1622        command.command_id = SPI_MLME_SET_REQUEST;
1623        command.length = sizeof(struct mlme_set_request_pset) -
1624                MAX_ATTRIBUTE_SIZE + pib_attribute_length;
1625        command.pdata.set_req.pib_attribute = pib_attribute;
1626        command.pdata.set_req.pib_attribute_index = pib_attribute_index;
1627        command.pdata.set_req.pib_attribute_length = pib_attribute_length;
1628        memcpy(
1629                command.pdata.set_req.pib_attribute_value,
1630                pib_attribute_value,
1631                pib_attribute_length
1632        );
1633
1634        if (cascoda_api_downstream(
1635                &command.command_id,
1636                command.length + 2,
1637                &response.command_id,
1638                device_ref)) {
1639                return MAC_SYSTEM_ERROR;
1640        }
1641
1642        if (response.command_id != SPI_MLME_SET_CONFIRM)
1643                return MAC_SYSTEM_ERROR;
1644
1645        return response.pdata.status;
1646}
1647
1648/**
1649 * hwme_set_request_sync() - HWME_SET_request/confirm according to API Spec
1650 * @hw_attribute:        Attribute Number
1651 * @hw_attribute_length: Attribute length
1652 * @hw_attribute_value:  Pointer to Attribute Value
1653 * @device_ref:          Nondescript pointer to target device
1654 *
1655 * Return: 802.15.4 status code of HWME-SET.confirm
1656 */
1657static u8 hwme_set_request_sync(
1658        u8           hw_attribute,
1659        u8           hw_attribute_length,
1660        u8          *hw_attribute_value,
1661        void        *device_ref
1662)
1663{
1664        struct mac_message command, response;
1665
1666        command.command_id = SPI_HWME_SET_REQUEST;
1667        command.length = 2 + hw_attribute_length;
1668        command.pdata.hwme_set_req.hw_attribute = hw_attribute;
1669        command.pdata.hwme_set_req.hw_attribute_length = hw_attribute_length;
1670        memcpy(
1671                command.pdata.hwme_set_req.hw_attribute_value,
1672                hw_attribute_value,
1673                hw_attribute_length
1674        );
1675
1676        if (cascoda_api_downstream(
1677                &command.command_id,
1678                command.length + 2,
1679                &response.command_id,
1680                device_ref)) {
1681                return MAC_SYSTEM_ERROR;
1682        }
1683
1684        if (response.command_id != SPI_HWME_SET_CONFIRM)
1685                return MAC_SYSTEM_ERROR;
1686
1687        return response.pdata.hwme_set_cnf.status;
1688}
1689
1690/**
1691 * hwme_get_request_sync() - HWME_GET_request/confirm according to API Spec
1692 * @hw_attribute:        Attribute Number
1693 * @hw_attribute_length: Attribute length
1694 * @hw_attribute_value:  Pointer to Attribute Value
1695 * @device_ref:          Nondescript pointer to target device
1696 *
1697 * Return: 802.15.4 status code of HWME-GET.confirm
1698 */
1699static u8 hwme_get_request_sync(
1700        u8           hw_attribute,
1701        u8          *hw_attribute_length,
1702        u8          *hw_attribute_value,
1703        void        *device_ref
1704)
1705{
1706        struct mac_message command, response;
1707
1708        command.command_id = SPI_HWME_GET_REQUEST;
1709        command.length = 1;
1710        command.pdata.hwme_get_req.hw_attribute = hw_attribute;
1711
1712        if (cascoda_api_downstream(
1713                &command.command_id,
1714                command.length + 2,
1715                &response.command_id,
1716                device_ref)) {
1717                return MAC_SYSTEM_ERROR;
1718        }
1719
1720        if (response.command_id != SPI_HWME_GET_CONFIRM)
1721                return MAC_SYSTEM_ERROR;
1722
1723        if (response.pdata.hwme_get_cnf.status == MAC_SUCCESS) {
1724                *hw_attribute_length =
1725                        response.pdata.hwme_get_cnf.hw_attribute_length;
1726                memcpy(
1727                        hw_attribute_value,
1728                        response.pdata.hwme_get_cnf.hw_attribute_value,
1729                        *hw_attribute_length
1730                );
1731        }
1732
1733        return response.pdata.hwme_get_cnf.status;
1734}
1735
1736/* Network driver operation */
1737
1738/**
1739 * ca8210_async_xmit_complete() - Called to announce that an asynchronous
1740 *                                transmission has finished
1741 * @hw:          ieee802154_hw of ca8210 that has finished exchange
1742 * @msduhandle:  Identifier of transmission that has completed
1743 * @status:      Returned 802.15.4 status code of the transmission
1744 *
1745 * Return: 0 or linux error code
1746 */
1747static int ca8210_async_xmit_complete(
1748        struct ieee802154_hw  *hw,
1749        u8                     msduhandle,
1750        u8                     status)
1751{
1752        struct ca8210_priv *priv = hw->priv;
1753
1754        if (priv->nextmsduhandle != msduhandle) {
1755                dev_err(
1756                        &priv->spi->dev,
1757                        "Unexpected msdu_handle on data confirm, Expected %d, got %d\n",
1758                        priv->nextmsduhandle,
1759                        msduhandle
1760                );
1761                return -EIO;
1762        }
1763
1764        priv->async_tx_pending = false;
1765        priv->nextmsduhandle++;
1766
1767        if (status) {
1768                dev_err(
1769                        &priv->spi->dev,
1770                        "Link transmission unsuccessful, status = %d\n",
1771                        status
1772                );
1773                if (status != MAC_TRANSACTION_OVERFLOW) {
1774                        ieee802154_wake_queue(priv->hw);
1775                        return 0;
1776                }
1777        }
1778        ieee802154_xmit_complete(priv->hw, priv->tx_skb, true);
1779
1780        return 0;
1781}
1782
1783/**
1784 * ca8210_skb_rx() - Contructs a properly framed socket buffer from a received
1785 *                   MCPS_DATA_indication
1786 * @hw:        ieee802154_hw that MCPS_DATA_indication was received by
1787 * @len:       length of MCPS_DATA_indication
1788 * @data_ind:  Octet array of MCPS_DATA_indication
1789 *
1790 * Called by the spi driver whenever a SAP command is received, this function
1791 * will ascertain whether the command is of interest to the network driver and
1792 * take necessary action.
1793 *
1794 * Return: 0 or linux error code
1795 */
1796static int ca8210_skb_rx(
1797        struct ieee802154_hw  *hw,
1798        size_t                 len,
1799        u8                    *data_ind
1800)
1801{
1802        struct ieee802154_hdr hdr;
1803        int msdulen;
1804        int hlen;
1805        u8 mpdulinkquality = data_ind[23];
1806        struct sk_buff *skb;
1807        struct ca8210_priv *priv = hw->priv;
1808
1809        /* Allocate mtu size buffer for every rx packet */
1810        skb = dev_alloc_skb(IEEE802154_MTU + sizeof(hdr));
1811        if (!skb)
1812                return -ENOMEM;
1813
1814        skb_reserve(skb, sizeof(hdr));
1815
1816        msdulen = data_ind[22]; /* msdu_length */
1817        if (msdulen > IEEE802154_MTU) {
1818                dev_err(
1819                        &priv->spi->dev,
1820                        "received erroneously large msdu length!\n"
1821                );
1822                kfree_skb(skb);
1823                return -EMSGSIZE;
1824        }
1825        dev_dbg(&priv->spi->dev, "skb buffer length = %d\n", msdulen);
1826
1827        if (priv->promiscuous)
1828                goto copy_payload;
1829
1830        /* Populate hdr */
1831        hdr.sec.level = data_ind[29 + msdulen];
1832        dev_dbg(&priv->spi->dev, "security level: %#03x\n", hdr.sec.level);
1833        if (hdr.sec.level > 0) {
1834                hdr.sec.key_id_mode = data_ind[30 + msdulen];
1835                memcpy(&hdr.sec.extended_src, &data_ind[31 + msdulen], 8);
1836                hdr.sec.key_id = data_ind[39 + msdulen];
1837        }
1838        hdr.source.mode = data_ind[0];
1839        dev_dbg(&priv->spi->dev, "srcAddrMode: %#03x\n", hdr.source.mode);
1840        hdr.source.pan_id = *(u16 *)&data_ind[1];
1841        dev_dbg(&priv->spi->dev, "srcPanId: %#06x\n", hdr.source.pan_id);
1842        memcpy(&hdr.source.extended_addr, &data_ind[3], 8);
1843        hdr.dest.mode = data_ind[11];
1844        dev_dbg(&priv->spi->dev, "dstAddrMode: %#03x\n", hdr.dest.mode);
1845        hdr.dest.pan_id = *(u16 *)&data_ind[12];
1846        dev_dbg(&priv->spi->dev, "dstPanId: %#06x\n", hdr.dest.pan_id);
1847        memcpy(&hdr.dest.extended_addr, &data_ind[14], 8);
1848
1849        /* Fill in FC implicitly */
1850        hdr.fc.type = 1; /* Data frame */
1851        if (hdr.sec.level)
1852                hdr.fc.security_enabled = 1;
1853        else
1854                hdr.fc.security_enabled = 0;
1855        if (data_ind[1] != data_ind[12] || data_ind[2] != data_ind[13])
1856                hdr.fc.intra_pan = 1;
1857        else
1858                hdr.fc.intra_pan = 0;
1859        hdr.fc.dest_addr_mode = hdr.dest.mode;
1860        hdr.fc.source_addr_mode = hdr.source.mode;
1861
1862        /* Add hdr to front of buffer */
1863        hlen = ieee802154_hdr_push(skb, &hdr);
1864
1865        if (hlen < 0) {
1866                dev_crit(&priv->spi->dev, "failed to push mac hdr onto skb!\n");
1867                kfree_skb(skb);
1868                return hlen;
1869        }
1870
1871        skb_reset_mac_header(skb);
1872        skb->mac_len = hlen;
1873
1874copy_payload:
1875        /* Add <msdulen> bytes of space to the back of the buffer */
1876        /* Copy msdu to skb */
1877        skb_put_data(skb, &data_ind[29], msdulen);
1878
1879        ieee802154_rx_irqsafe(hw, skb, mpdulinkquality);
1880        return 0;
1881}
1882
1883/**
1884 * ca8210_net_rx() - Acts upon received SAP commands relevant to the network
1885 *                   driver
1886 * @hw:       ieee802154_hw that command was received by
1887 * @command:  Octet array of received command
1888 * @len:      length of the received command
1889 *
1890 * Called by the spi driver whenever a SAP command is received, this function
1891 * will ascertain whether the command is of interest to the network driver and
1892 * take necessary action.
1893 *
1894 * Return: 0 or linux error code
1895 */
1896static int ca8210_net_rx(struct ieee802154_hw *hw, u8 *command, size_t len)
1897{
1898        struct ca8210_priv *priv = hw->priv;
1899        unsigned long flags;
1900        u8 status;
1901
1902        dev_dbg(&priv->spi->dev, "%s: CmdID = %d\n", __func__, command[0]);
1903
1904        if (command[0] == SPI_MCPS_DATA_INDICATION) {
1905                /* Received data */
1906                spin_lock_irqsave(&priv->lock, flags);
1907                if (command[26] == priv->last_dsn) {
1908                        dev_dbg(
1909                                &priv->spi->dev,
1910                                "DSN %d resend received, ignoring...\n",
1911                                command[26]
1912                        );
1913                        spin_unlock_irqrestore(&priv->lock, flags);
1914                        return 0;
1915                }
1916                priv->last_dsn = command[26];
1917                spin_unlock_irqrestore(&priv->lock, flags);
1918                return ca8210_skb_rx(hw, len - 2, command + 2);
1919        } else if (command[0] == SPI_MCPS_DATA_CONFIRM) {
1920                status = command[3];
1921                if (priv->async_tx_pending) {
1922                        return ca8210_async_xmit_complete(
1923                                hw,
1924                                command[2],
1925                                status
1926                        );
1927                }
1928        }
1929
1930        return 0;
1931}
1932
1933/**
1934 * ca8210_skb_tx() - Transmits a given socket buffer using the ca8210
1935 * @skb:         Socket buffer to transmit
1936 * @msduhandle:  Data identifier to pass to the 802.15.4 MAC
1937 * @priv:        Pointer to private data section of target ca8210
1938 *
1939 * Return: 0 or linux error code
1940 */
1941static int ca8210_skb_tx(
1942        struct sk_buff      *skb,
1943        u8                   msduhandle,
1944        struct ca8210_priv  *priv
1945)
1946{
1947        int status;
1948        struct ieee802154_hdr header = { };
1949        struct secspec secspec;
1950        unsigned int mac_len;
1951
1952        dev_dbg(&priv->spi->dev, "%s called\n", __func__);
1953
1954        /* Get addressing info from skb - ieee802154 layer creates a full
1955         * packet
1956         */
1957        mac_len = ieee802154_hdr_peek_addrs(skb, &header);
1958
1959        secspec.security_level = header.sec.level;
1960        secspec.key_id_mode = header.sec.key_id_mode;
1961        if (secspec.key_id_mode == 2)
1962                memcpy(secspec.key_source, &header.sec.short_src, 4);
1963        else if (secspec.key_id_mode == 3)
1964                memcpy(secspec.key_source, &header.sec.extended_src, 8);
1965        secspec.key_index = header.sec.key_id;
1966
1967        /* Pass to Cascoda API */
1968        status =  mcps_data_request(
1969                header.source.mode,
1970                header.dest.mode,
1971                header.dest.pan_id,
1972                (union macaddr *)&header.dest.extended_addr,
1973                skb->len - mac_len,
1974                &skb->data[mac_len],
1975                msduhandle,
1976                header.fc.ack_request,
1977                &secspec,
1978                priv->spi
1979        );
1980        return link_to_linux_err(status);
1981}
1982
1983/**
1984 * ca8210_start() - Starts the network driver
1985 * @hw:  ieee802154_hw of ca8210 being started
1986 *
1987 * Return: 0 or linux error code
1988 */
1989static int ca8210_start(struct ieee802154_hw *hw)
1990{
1991        int status;
1992        u8 rx_on_when_idle;
1993        u8 lqi_threshold = 0;
1994        struct ca8210_priv *priv = hw->priv;
1995
1996        priv->last_dsn = -1;
1997        /* Turn receiver on when idle for now just to test rx */
1998        rx_on_when_idle = 1;
1999        status = mlme_set_request_sync(
2000                MAC_RX_ON_WHEN_IDLE,
2001                0,
2002                1,
2003                &rx_on_when_idle,
2004                priv->spi
2005        );
2006        if (status) {
2007                dev_crit(
2008                        &priv->spi->dev,
2009                        "Setting rx_on_when_idle failed, status = %d\n",
2010                        status
2011                );
2012                return link_to_linux_err(status);
2013        }
2014        status = hwme_set_request_sync(
2015                HWME_LQILIMIT,
2016                1,
2017                &lqi_threshold,
2018                priv->spi
2019        );
2020        if (status) {
2021                dev_crit(
2022                        &priv->spi->dev,
2023                        "Setting lqilimit failed, status = %d\n",
2024                        status
2025                );
2026                return link_to_linux_err(status);
2027        }
2028
2029        return 0;
2030}
2031
2032/**
2033 * ca8210_stop() - Stops the network driver
2034 * @hw:  ieee802154_hw of ca8210 being stopped
2035 *
2036 * Return: 0 or linux error code
2037 */
2038static void ca8210_stop(struct ieee802154_hw *hw)
2039{
2040}
2041
2042/**
2043 * ca8210_xmit_async() - Asynchronously transmits a given socket buffer using
2044 *                       the ca8210
2045 * @hw:   ieee802154_hw of ca8210 to transmit from
2046 * @skb:  Socket buffer to transmit
2047 *
2048 * Return: 0 or linux error code
2049 */
2050static int ca8210_xmit_async(struct ieee802154_hw *hw, struct sk_buff *skb)
2051{
2052        struct ca8210_priv *priv = hw->priv;
2053        int status;
2054
2055        dev_dbg(&priv->spi->dev, "calling %s\n", __func__);
2056
2057        priv->tx_skb = skb;
2058        priv->async_tx_pending = true;
2059        status = ca8210_skb_tx(skb, priv->nextmsduhandle, priv);
2060        return status;
2061}
2062
2063/**
2064 * ca8210_get_ed() - Returns the measured energy on the current channel at this
2065 *                   instant in time
2066 * @hw:     ieee802154_hw of target ca8210
2067 * @level:  Measured Energy Detect level
2068 *
2069 * Return: 0 or linux error code
2070 */
2071static int ca8210_get_ed(struct ieee802154_hw *hw, u8 *level)
2072{
2073        u8 lenvar;
2074        struct ca8210_priv *priv = hw->priv;
2075
2076        return link_to_linux_err(
2077                hwme_get_request_sync(HWME_EDVALUE, &lenvar, level, priv->spi)
2078        );
2079}
2080
2081/**
2082 * ca8210_set_channel() - Sets the current operating 802.15.4 channel of the
2083 *                        ca8210
2084 * @hw:       ieee802154_hw of target ca8210
2085 * @page:     Channel page to set
2086 * @channel:  Channel number to set
2087 *
2088 * Return: 0 or linux error code
2089 */
2090static int ca8210_set_channel(
2091        struct ieee802154_hw  *hw,
2092        u8                     page,
2093        u8                     channel
2094)
2095{
2096        u8 status;
2097        struct ca8210_priv *priv = hw->priv;
2098
2099        status = mlme_set_request_sync(
2100                PHY_CURRENT_CHANNEL,
2101                0,
2102                1,
2103                &channel,
2104                priv->spi
2105        );
2106        if (status) {
2107                dev_err(
2108                        &priv->spi->dev,
2109                        "error setting channel, MLME-SET.confirm status = %d\n",
2110                        status
2111                );
2112        }
2113        return link_to_linux_err(status);
2114}
2115
2116/**
2117 * ca8210_set_hw_addr_filt() - Sets the address filtering parameters of the
2118 *                             ca8210
2119 * @hw:       ieee802154_hw of target ca8210
2120 * @filt:     Filtering parameters
2121 * @changed:  Bitmap representing which parameters to change
2122 *
2123 * Effectively just sets the actual addressing information identifying this node
2124 * as all filtering is performed by the ca8210 as detailed in the IEEE 802.15.4
2125 * 2006 specification.
2126 *
2127 * Return: 0 or linux error code
2128 */
2129static int ca8210_set_hw_addr_filt(
2130        struct ieee802154_hw            *hw,
2131        struct ieee802154_hw_addr_filt  *filt,
2132        unsigned long                    changed
2133)
2134{
2135        u8 status = 0;
2136        struct ca8210_priv *priv = hw->priv;
2137
2138        if (changed & IEEE802154_AFILT_PANID_CHANGED) {
2139                status = mlme_set_request_sync(
2140                        MAC_PAN_ID,
2141                        0,
2142                        2,
2143                        &filt->pan_id, priv->spi
2144                );
2145                if (status) {
2146                        dev_err(
2147                                &priv->spi->dev,
2148                                "error setting pan id, MLME-SET.confirm status = %d",
2149                                status
2150                        );
2151                        return link_to_linux_err(status);
2152                }
2153        }
2154        if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
2155                status = mlme_set_request_sync(
2156                        MAC_SHORT_ADDRESS,
2157                        0,
2158                        2,
2159                        &filt->short_addr, priv->spi
2160                );
2161                if (status) {
2162                        dev_err(
2163                                &priv->spi->dev,
2164                                "error setting short address, MLME-SET.confirm status = %d",
2165                                status
2166                        );
2167                        return link_to_linux_err(status);
2168                }
2169        }
2170        if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
2171                status = mlme_set_request_sync(
2172                        NS_IEEE_ADDRESS,
2173                        0,
2174                        8,
2175                        &filt->ieee_addr,
2176                        priv->spi
2177                );
2178                if (status) {
2179                        dev_err(
2180                                &priv->spi->dev,
2181                                "error setting ieee address, MLME-SET.confirm status = %d",
2182                                status
2183                        );
2184                        return link_to_linux_err(status);
2185                }
2186        }
2187        /* TODO: Should use MLME_START to set coord bit? */
2188        return 0;
2189}
2190
2191/**
2192 * ca8210_set_tx_power() - Sets the transmit power of the ca8210
2193 * @hw:   ieee802154_hw of target ca8210
2194 * @mbm:  Transmit power in mBm (dBm*100)
2195 *
2196 * Return: 0 or linux error code
2197 */
2198static int ca8210_set_tx_power(struct ieee802154_hw *hw, s32 mbm)
2199{
2200        struct ca8210_priv *priv = hw->priv;
2201
2202        mbm /= 100;
2203        return link_to_linux_err(
2204                mlme_set_request_sync(PHY_TRANSMIT_POWER, 0, 1, &mbm, priv->spi)
2205        );
2206}
2207
2208/**
2209 * ca8210_set_cca_mode() - Sets the clear channel assessment mode of the ca8210
2210 * @hw:   ieee802154_hw of target ca8210
2211 * @cca:  CCA mode to set
2212 *
2213 * Return: 0 or linux error code
2214 */
2215static int ca8210_set_cca_mode(
2216        struct ieee802154_hw       *hw,
2217        const struct wpan_phy_cca  *cca
2218)
2219{
2220        u8 status;
2221        u8 cca_mode;
2222        struct ca8210_priv *priv = hw->priv;
2223
2224        cca_mode = cca->mode & 3;
2225        if (cca_mode == 3 && cca->opt == NL802154_CCA_OPT_ENERGY_CARRIER_OR) {
2226                /* cca_mode 0 == CS OR ED, 3 == CS AND ED */
2227                cca_mode = 0;
2228        }
2229        status = mlme_set_request_sync(
2230                PHY_CCA_MODE,
2231                0,
2232                1,
2233                &cca_mode,
2234                priv->spi
2235        );
2236        if (status) {
2237                dev_err(
2238                        &priv->spi->dev,
2239                        "error setting cca mode, MLME-SET.confirm status = %d",
2240                        status
2241                );
2242        }
2243        return link_to_linux_err(status);
2244}
2245
2246/**
2247 * ca8210_set_cca_ed_level() - Sets the CCA ED level of the ca8210
2248 * @hw:     ieee802154_hw of target ca8210
2249 * @level:  ED level to set (in mbm)
2250 *
2251 * Sets the minimum threshold of measured energy above which the ca8210 will
2252 * back off and retry a transmission.
2253 *
2254 * Return: 0 or linux error code
2255 */
2256static int ca8210_set_cca_ed_level(struct ieee802154_hw *hw, s32 level)
2257{
2258        u8 status;
2259        u8 ed_threshold = (level / 100) * 2 + 256;
2260        struct ca8210_priv *priv = hw->priv;
2261
2262        status = hwme_set_request_sync(
2263                HWME_EDTHRESHOLD,
2264                1,
2265                &ed_threshold,
2266                priv->spi
2267        );
2268        if (status) {
2269                dev_err(
2270                        &priv->spi->dev,
2271                        "error setting ed threshold, HWME-SET.confirm status = %d",
2272                        status
2273                );
2274        }
2275        return link_to_linux_err(status);
2276}
2277
2278/**
2279 * ca8210_set_csma_params() - Sets the CSMA parameters of the ca8210
2280 * @hw:       ieee802154_hw of target ca8210
2281 * @min_be:   Minimum backoff exponent when backing off a transmission
2282 * @max_be:   Maximum backoff exponent when backing off a transmission
2283 * @retries:  Number of times to retry after backing off
2284 *
2285 * Return: 0 or linux error code
2286 */
2287static int ca8210_set_csma_params(
2288        struct ieee802154_hw  *hw,
2289        u8                     min_be,
2290        u8                     max_be,
2291        u8                     retries
2292)
2293{
2294        u8 status;
2295        struct ca8210_priv *priv = hw->priv;
2296
2297        status = mlme_set_request_sync(MAC_MIN_BE, 0, 1, &min_be, priv->spi);
2298        if (status) {
2299                dev_err(
2300                        &priv->spi->dev,
2301                        "error setting min be, MLME-SET.confirm status = %d",
2302                        status
2303                );
2304                return link_to_linux_err(status);
2305        }
2306        status = mlme_set_request_sync(MAC_MAX_BE, 0, 1, &max_be, priv->spi);
2307        if (status) {
2308                dev_err(
2309                        &priv->spi->dev,
2310                        "error setting max be, MLME-SET.confirm status = %d",
2311                        status
2312                );
2313                return link_to_linux_err(status);
2314        }
2315        status = mlme_set_request_sync(
2316                MAC_MAX_CSMA_BACKOFFS,
2317                0,
2318                1,
2319                &retries,
2320                priv->spi
2321        );
2322        if (status) {
2323                dev_err(
2324                        &priv->spi->dev,
2325                        "error setting max csma backoffs, MLME-SET.confirm status = %d",
2326                        status
2327                );
2328        }
2329        return link_to_linux_err(status);
2330}
2331
2332/**
2333 * ca8210_set_frame_retries() - Sets the maximum frame retries of the ca8210
2334 * @hw:       ieee802154_hw of target ca8210
2335 * @retries:  Number of retries
2336 *
2337 * Sets the number of times to retry a transmission if no acknowledgment was
2338 * was received from the other end when one was requested.
2339 *
2340 * Return: 0 or linux error code
2341 */
2342static int ca8210_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
2343{
2344        u8 status;
2345        struct ca8210_priv *priv = hw->priv;
2346
2347        status = mlme_set_request_sync(
2348                MAC_MAX_FRAME_RETRIES,
2349                0,
2350                1,
2351                &retries,
2352                priv->spi
2353        );
2354        if (status) {
2355                dev_err(
2356                        &priv->spi->dev,
2357                        "error setting frame retries, MLME-SET.confirm status = %d",
2358                        status
2359                );
2360        }
2361        return link_to_linux_err(status);
2362}
2363
2364static int ca8210_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
2365{
2366        u8 status;
2367        struct ca8210_priv *priv = hw->priv;
2368
2369        status = mlme_set_request_sync(
2370                MAC_PROMISCUOUS_MODE,
2371                0,
2372                1,
2373                (const void *)&on,
2374                priv->spi
2375        );
2376        if (status) {
2377                dev_err(
2378                        &priv->spi->dev,
2379                        "error setting promiscuous mode, MLME-SET.confirm status = %d",
2380                        status
2381                );
2382        } else {
2383                priv->promiscuous = on;
2384        }
2385        return link_to_linux_err(status);
2386}
2387
2388static const struct ieee802154_ops ca8210_phy_ops = {
2389        .start = ca8210_start,
2390        .stop = ca8210_stop,
2391        .xmit_async = ca8210_xmit_async,
2392        .ed = ca8210_get_ed,
2393        .set_channel = ca8210_set_channel,
2394        .set_hw_addr_filt = ca8210_set_hw_addr_filt,
2395        .set_txpower = ca8210_set_tx_power,
2396        .set_cca_mode = ca8210_set_cca_mode,
2397        .set_cca_ed_level = ca8210_set_cca_ed_level,
2398        .set_csma_params = ca8210_set_csma_params,
2399        .set_frame_retries = ca8210_set_frame_retries,
2400        .set_promiscuous_mode = ca8210_set_promiscuous_mode
2401};
2402
2403/* Test/EVBME Interface */
2404
2405/**
2406 * ca8210_test_int_open() - Opens the test interface to the userspace
2407 * @inodp:  inode representation of file interface
2408 * @filp:   file interface
2409 *
2410 * Return: 0 or linux error code
2411 */
2412static int ca8210_test_int_open(struct inode *inodp, struct file *filp)
2413{
2414        struct ca8210_priv *priv = inodp->i_private;
2415
2416        filp->private_data = priv;
2417        return 0;
2418}
2419
2420/**
2421 * ca8210_test_check_upstream() - Checks a command received from the upstream
2422 *                                testing interface for required action
2423 * @buf:        Buffer containing command to check
2424 * @device_ref: Nondescript pointer to target device
2425 *
2426 * Return: 0 or linux error code
2427 */
2428static int ca8210_test_check_upstream(u8 *buf, void *device_ref)
2429{
2430        int ret;
2431        u8 response[CA8210_SPI_BUF_SIZE];
2432
2433        if (buf[0] == SPI_MLME_SET_REQUEST) {
2434                ret = tdme_checkpibattribute(buf[2], buf[4], buf + 5);
2435                if (ret) {
2436                        response[0]  = SPI_MLME_SET_CONFIRM;
2437                        response[1] = 3;
2438                        response[2] = MAC_INVALID_PARAMETER;
2439                        response[3] = buf[2];
2440                        response[4] = buf[3];
2441                        if (cascoda_api_upstream)
2442                                cascoda_api_upstream(response, 5, device_ref);
2443                        return ret;
2444                }
2445        }
2446        if (buf[0] == SPI_MLME_ASSOCIATE_REQUEST) {
2447                return tdme_channelinit(buf[2], device_ref);
2448        } else if (buf[0] == SPI_MLME_START_REQUEST) {
2449                return tdme_channelinit(buf[4], device_ref);
2450        } else if (
2451                (buf[0] == SPI_MLME_SET_REQUEST) &&
2452                (buf[2] == PHY_CURRENT_CHANNEL)
2453        ) {
2454                return tdme_channelinit(buf[5], device_ref);
2455        } else if (
2456                (buf[0] == SPI_TDME_SET_REQUEST) &&
2457                (buf[2] == TDME_CHANNEL)
2458        ) {
2459                return tdme_channelinit(buf[4], device_ref);
2460        } else if (
2461                (CA8210_MAC_WORKAROUNDS) &&
2462                (buf[0] == SPI_MLME_RESET_REQUEST) &&
2463                (buf[2] == 1)
2464        ) {
2465                /* reset COORD Bit for Channel Filtering as Coordinator */
2466                return tdme_setsfr_request_sync(
2467                        0,
2468                        CA8210_SFR_MACCON,
2469                        0,
2470                        device_ref
2471                );
2472        }
2473        return 0;
2474} /* End of EVBMECheckSerialCommand() */
2475
2476/**
2477 * ca8210_test_int_user_write() - Called by a process in userspace to send a
2478 *                                message to the ca8210 drivers
2479 * @filp:    file interface
2480 * @in_buf:  Buffer containing message to write
2481 * @len:     length of message
2482 * @off:     file offset
2483 *
2484 * Return: 0 or linux error code
2485 */
2486static ssize_t ca8210_test_int_user_write(
2487        struct file        *filp,
2488        const char __user  *in_buf,
2489        size_t              len,
2490        loff_t             *off
2491)
2492{
2493        int ret;
2494        struct ca8210_priv *priv = filp->private_data;
2495        u8 command[CA8210_SPI_BUF_SIZE];
2496
2497        memset(command, SPI_IDLE, 6);
2498        if (len > CA8210_SPI_BUF_SIZE || len < 2) {
2499                dev_warn(
2500                        &priv->spi->dev,
2501                        "userspace requested erroneous write length (%zu)\n",
2502                        len
2503                );
2504                return -EBADE;
2505        }
2506
2507        ret = copy_from_user(command, in_buf, len);
2508        if (ret) {
2509                dev_err(
2510                        &priv->spi->dev,
2511                        "%d bytes could not be copied from userspace\n",
2512                        ret
2513                );
2514                return -EIO;
2515        }
2516        if (len != command[1] + 2) {
2517                dev_err(
2518                        &priv->spi->dev,
2519                        "write len does not match packet length field\n"
2520                );
2521                return -EBADE;
2522        }
2523
2524        ret = ca8210_test_check_upstream(command, priv->spi);
2525        if (ret == 0) {
2526                ret = ca8210_spi_exchange(
2527                        command,
2528                        command[1] + 2,
2529                        NULL,
2530                        priv->spi
2531                );
2532                if (ret < 0) {
2533                        /* effectively 0 bytes were written successfully */
2534                        dev_err(
2535                                &priv->spi->dev,
2536                                "spi exchange failed\n"
2537                        );
2538                        return ret;
2539                }
2540                if (command[0] & SPI_SYN)
2541                        priv->sync_down++;
2542        }
2543
2544        return len;
2545}
2546
2547/**
2548 * ca8210_test_int_user_read() - Called by a process in userspace to read a
2549 *                               message from the ca8210 drivers
2550 * @filp:  file interface
2551 * @buf:   Buffer to write message to
2552 * @len:   length of message to read (ignored)
2553 * @offp:  file offset
2554 *
2555 * If the O_NONBLOCK flag was set when opening the file then this function will
2556 * not block, i.e. it will return if the fifo is empty. Otherwise the function
2557 * will block, i.e. wait until new data arrives.
2558 *
2559 * Return: number of bytes read
2560 */
2561static ssize_t ca8210_test_int_user_read(
2562        struct file  *filp,
2563        char __user  *buf,
2564        size_t        len,
2565        loff_t       *offp
2566)
2567{
2568        int i, cmdlen;
2569        struct ca8210_priv *priv = filp->private_data;
2570        unsigned char *fifo_buffer;
2571        unsigned long bytes_not_copied;
2572
2573        if (filp->f_flags & O_NONBLOCK) {
2574                /* Non-blocking mode */
2575                if (kfifo_is_empty(&priv->test.up_fifo))
2576                        return 0;
2577        } else {
2578                /* Blocking mode */
2579                wait_event_interruptible(
2580                        priv->test.readq,
2581                        !kfifo_is_empty(&priv->test.up_fifo)
2582                );
2583        }
2584
2585        if (kfifo_out(&priv->test.up_fifo, &fifo_buffer, 4) != 4) {
2586                dev_err(
2587                        &priv->spi->dev,
2588                        "test_interface: Wrong number of elements popped from upstream fifo\n"
2589                );
2590                return 0;
2591        }
2592        cmdlen = fifo_buffer[1];
2593        bytes_not_copied = cmdlen + 2;
2594
2595        bytes_not_copied = copy_to_user(buf, fifo_buffer, bytes_not_copied);
2596        if (bytes_not_copied > 0) {
2597                dev_err(
2598                        &priv->spi->dev,
2599                        "%lu bytes could not be copied to user space!\n",
2600                        bytes_not_copied
2601                );
2602        }
2603
2604        dev_dbg(&priv->spi->dev, "test_interface: Cmd len = %d\n", cmdlen);
2605
2606        dev_dbg(&priv->spi->dev, "test_interface: Read\n");
2607        for (i = 0; i < cmdlen + 2; i++)
2608                dev_dbg(&priv->spi->dev, "%#03x\n", fifo_buffer[i]);
2609
2610        kfree(fifo_buffer);
2611
2612        return cmdlen + 2;
2613}
2614
2615/**
2616 * ca8210_test_int_ioctl() - Called by a process in userspace to enact an
2617 *                           arbitrary action
2618 * @filp:        file interface
2619 * @ioctl_num:   which action to enact
2620 * @ioctl_param: arbitrary parameter for the action
2621 *
2622 * Return: status
2623 */
2624static long ca8210_test_int_ioctl(
2625        struct file *filp,
2626        unsigned int ioctl_num,
2627        unsigned long ioctl_param
2628)
2629{
2630        struct ca8210_priv *priv = filp->private_data;
2631
2632        switch (ioctl_num) {
2633        case CA8210_IOCTL_HARD_RESET:
2634                ca8210_reset_send(priv->spi, ioctl_param);
2635                break;
2636        default:
2637                break;
2638        }
2639        return 0;
2640}
2641
2642/**
2643 * ca8210_test_int_poll() - Called by a process in userspace to determine which
2644 *                          actions are currently possible for the file
2645 * @filp:   file interface
2646 * @ptable: poll table
2647 *
2648 * Return: set of poll return flags
2649 */
2650static __poll_t ca8210_test_int_poll(
2651        struct file *filp,
2652        struct poll_table_struct *ptable
2653)
2654{
2655        __poll_t return_flags = 0;
2656        struct ca8210_priv *priv = filp->private_data;
2657
2658        poll_wait(filp, &priv->test.readq, ptable);
2659        if (!kfifo_is_empty(&priv->test.up_fifo))
2660                return_flags |= (EPOLLIN | EPOLLRDNORM);
2661        if (wait_event_interruptible(
2662                priv->test.readq,
2663                !kfifo_is_empty(&priv->test.up_fifo))) {
2664                return EPOLLERR;
2665        }
2666        return return_flags;
2667}
2668
2669static const struct file_operations test_int_fops = {
2670        .read =           ca8210_test_int_user_read,
2671        .write =          ca8210_test_int_user_write,
2672        .open =           ca8210_test_int_open,
2673        .release =        NULL,
2674        .unlocked_ioctl = ca8210_test_int_ioctl,
2675        .poll =           ca8210_test_int_poll
2676};
2677
2678/* Init/Deinit */
2679
2680/**
2681 * ca8210_get_platform_data() - Populate a ca8210_platform_data object
2682 * @spi_device:  Pointer to ca8210 spi device object to get data for
2683 * @pdata:       Pointer to ca8210_platform_data object to populate
2684 *
2685 * Return: 0 or linux error code
2686 */
2687static int ca8210_get_platform_data(
2688        struct spi_device *spi_device,
2689        struct ca8210_platform_data *pdata
2690)
2691{
2692        int ret = 0;
2693
2694        if (!spi_device->dev.of_node)
2695                return -EINVAL;
2696
2697        pdata->extclockenable = of_property_read_bool(
2698                spi_device->dev.of_node,
2699                "extclock-enable"
2700        );
2701        if (pdata->extclockenable) {
2702                ret = of_property_read_u32(
2703                        spi_device->dev.of_node,
2704                        "extclock-freq",
2705                        &pdata->extclockfreq
2706                );
2707                if (ret < 0)
2708                        return ret;
2709
2710                ret = of_property_read_u32(
2711                        spi_device->dev.of_node,
2712                        "extclock-gpio",
2713                        &pdata->extclockgpio
2714                );
2715        }
2716
2717        return ret;
2718}
2719
2720/**
2721 * ca8210_config_extern_clk() - Configure the external clock provided by the
2722 *                              ca8210
2723 * @pdata:  Pointer to ca8210_platform_data containing clock parameters
2724 * @spi:    Pointer to target ca8210 spi device
2725 * @on:     True to turn the clock on, false to turn off
2726 *
2727 * The external clock is configured with a frequency and output pin taken from
2728 * the platform data.
2729 *
2730 * Return: 0 or linux error code
2731 */
2732static int ca8210_config_extern_clk(
2733        struct ca8210_platform_data *pdata,
2734        struct spi_device *spi,
2735        bool on
2736)
2737{
2738        u8 clkparam[2];
2739
2740        if (on) {
2741                dev_info(&spi->dev, "Switching external clock on\n");
2742                switch (pdata->extclockfreq) {
2743                case SIXTEEN_MHZ:
2744                        clkparam[0] = 1;
2745                        break;
2746                case EIGHT_MHZ:
2747                        clkparam[0] = 2;
2748                        break;
2749                case FOUR_MHZ:
2750                        clkparam[0] = 3;
2751                        break;
2752                case TWO_MHZ:
2753                        clkparam[0] = 4;
2754                        break;
2755                case ONE_MHZ:
2756                        clkparam[0] = 5;
2757                        break;
2758                default:
2759                        dev_crit(&spi->dev, "Invalid extclock-freq\n");
2760                        return -EINVAL;
2761                }
2762                clkparam[1] = pdata->extclockgpio;
2763        } else {
2764                dev_info(&spi->dev, "Switching external clock off\n");
2765                clkparam[0] = 0; /* off */
2766                clkparam[1] = 0;
2767        }
2768        return link_to_linux_err(
2769                hwme_set_request_sync(HWME_SYSCLKOUT, 2, clkparam, spi)
2770        );
2771}
2772
2773/**
2774 * ca8210_register_ext_clock() - Register ca8210's external clock with kernel
2775 * @spi:  Pointer to target ca8210 spi device
2776 *
2777 * Return: 0 or linux error code
2778 */
2779static int ca8210_register_ext_clock(struct spi_device *spi)
2780{
2781        struct device_node *np = spi->dev.of_node;
2782        struct ca8210_priv *priv = spi_get_drvdata(spi);
2783        struct ca8210_platform_data *pdata = spi->dev.platform_data;
2784        int ret = 0;
2785
2786        if (!np)
2787                return -EFAULT;
2788
2789        priv->clk = clk_register_fixed_rate(
2790                &spi->dev,
2791                np->name,
2792                NULL,
2793                0,
2794                pdata->extclockfreq
2795        );
2796
2797        if (IS_ERR(priv->clk)) {
2798                dev_crit(&spi->dev, "Failed to register external clk\n");
2799                return PTR_ERR(priv->clk);
2800        }
2801        ret = of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
2802        if (ret) {
2803                clk_unregister(priv->clk);
2804                dev_crit(
2805                        &spi->dev,
2806                        "Failed to register external clock as clock provider\n"
2807                );
2808        } else {
2809                dev_info(&spi->dev, "External clock set as clock provider\n");
2810        }
2811
2812        return ret;
2813}
2814
2815/**
2816 * ca8210_unregister_ext_clock() - Unregister ca8210's external clock with
2817 *                                 kernel
2818 * @spi:  Pointer to target ca8210 spi device
2819 */
2820static void ca8210_unregister_ext_clock(struct spi_device *spi)
2821{
2822        struct ca8210_priv *priv = spi_get_drvdata(spi);
2823
2824        if (!priv->clk)
2825                return
2826
2827        of_clk_del_provider(spi->dev.of_node);
2828        clk_unregister(priv->clk);
2829        dev_info(&spi->dev, "External clock unregistered\n");
2830}
2831
2832/**
2833 * ca8210_reset_init() - Initialise the reset input to the ca8210
2834 * @spi:  Pointer to target ca8210 spi device
2835 *
2836 * Return: 0 or linux error code
2837 */
2838static int ca8210_reset_init(struct spi_device *spi)
2839{
2840        int ret;
2841        struct ca8210_platform_data *pdata = spi->dev.platform_data;
2842
2843        pdata->gpio_reset = of_get_named_gpio(
2844                spi->dev.of_node,
2845                "reset-gpio",
2846                0
2847        );
2848
2849        ret = gpio_direction_output(pdata->gpio_reset, 1);
2850        if (ret < 0) {
2851                dev_crit(
2852                        &spi->dev,
2853                        "Reset GPIO %d did not set to output mode\n",
2854                        pdata->gpio_reset
2855                );
2856        }
2857
2858        return ret;
2859}
2860
2861/**
2862 * ca8210_interrupt_init() - Initialise the irq output from the ca8210
2863 * @spi:  Pointer to target ca8210 spi device
2864 *
2865 * Return: 0 or linux error code
2866 */
2867static int ca8210_interrupt_init(struct spi_device *spi)
2868{
2869        int ret;
2870        struct ca8210_platform_data *pdata = spi->dev.platform_data;
2871
2872        pdata->gpio_irq = of_get_named_gpio(
2873                spi->dev.of_node,
2874                "irq-gpio",
2875                0
2876        );
2877
2878        pdata->irq_id = gpio_to_irq(pdata->gpio_irq);
2879        if (pdata->irq_id < 0) {
2880                dev_crit(
2881                        &spi->dev,
2882                        "Could not get irq for gpio pin %d\n",
2883                        pdata->gpio_irq
2884                );
2885                gpio_free(pdata->gpio_irq);
2886                return pdata->irq_id;
2887        }
2888
2889        ret = request_irq(
2890                pdata->irq_id,
2891                ca8210_interrupt_handler,
2892                IRQF_TRIGGER_FALLING,
2893                "ca8210-irq",
2894                spi_get_drvdata(spi)
2895        );
2896        if (ret) {
2897                dev_crit(&spi->dev, "request_irq %d failed\n", pdata->irq_id);
2898                gpio_unexport(pdata->gpio_irq);
2899                gpio_free(pdata->gpio_irq);
2900        }
2901
2902        return ret;
2903}
2904
2905/**
2906 * ca8210_dev_com_init() - Initialise the spi communication component
2907 * @priv:  Pointer to private data structure
2908 *
2909 * Return: 0 or linux error code
2910 */
2911static int ca8210_dev_com_init(struct ca8210_priv *priv)
2912{
2913        priv->mlme_workqueue = alloc_ordered_workqueue(
2914                "MLME work queue",
2915                WQ_UNBOUND
2916        );
2917        if (!priv->mlme_workqueue) {
2918                dev_crit(&priv->spi->dev, "alloc of mlme_workqueue failed!\n");
2919                return -ENOMEM;
2920        }
2921
2922        priv->irq_workqueue = alloc_ordered_workqueue(
2923                "ca8210 irq worker",
2924                WQ_UNBOUND
2925        );
2926        if (!priv->irq_workqueue) {
2927                dev_crit(&priv->spi->dev, "alloc of irq_workqueue failed!\n");
2928                destroy_workqueue(priv->mlme_workqueue);
2929                return -ENOMEM;
2930        }
2931
2932        return 0;
2933}
2934
2935/**
2936 * ca8210_dev_com_clear() - Deinitialise the spi communication component
2937 * @priv:  Pointer to private data structure
2938 */
2939static void ca8210_dev_com_clear(struct ca8210_priv *priv)
2940{
2941        flush_workqueue(priv->mlme_workqueue);
2942        destroy_workqueue(priv->mlme_workqueue);
2943        flush_workqueue(priv->irq_workqueue);
2944        destroy_workqueue(priv->irq_workqueue);
2945}
2946
2947#define CA8210_MAX_TX_POWERS (9)
2948static const s32 ca8210_tx_powers[CA8210_MAX_TX_POWERS] = {
2949        800, 700, 600, 500, 400, 300, 200, 100, 0
2950};
2951
2952#define CA8210_MAX_ED_LEVELS (21)
2953static const s32 ca8210_ed_levels[CA8210_MAX_ED_LEVELS] = {
2954        -10300, -10250, -10200, -10150, -10100, -10050, -10000, -9950, -9900,
2955        -9850, -9800, -9750, -9700, -9650, -9600, -9550, -9500, -9450, -9400,
2956        -9350, -9300
2957};
2958
2959/**
2960 * ca8210_hw_setup() - Populate the ieee802154_hw phy attributes with the
2961 *                     ca8210's defaults
2962 * @ca8210_hw:  Pointer to ieee802154_hw to populate
2963 */
2964static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw)
2965{
2966        /* Support channels 11-26 */
2967        ca8210_hw->phy->supported.channels[0] = CA8210_VALID_CHANNELS;
2968        ca8210_hw->phy->supported.tx_powers_size = CA8210_MAX_TX_POWERS;
2969        ca8210_hw->phy->supported.tx_powers = ca8210_tx_powers;
2970        ca8210_hw->phy->supported.cca_ed_levels_size = CA8210_MAX_ED_LEVELS;
2971        ca8210_hw->phy->supported.cca_ed_levels = ca8210_ed_levels;
2972        ca8210_hw->phy->current_channel = 18;
2973        ca8210_hw->phy->current_page = 0;
2974        ca8210_hw->phy->transmit_power = 800;
2975        ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER;
2976        ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND;
2977        ca8210_hw->phy->cca_ed_level = -9800;
2978        ca8210_hw->phy->symbol_duration = 16;
2979        ca8210_hw->phy->lifs_period = 40;
2980        ca8210_hw->phy->sifs_period = 12;
2981        ca8210_hw->flags =
2982                IEEE802154_HW_AFILT |
2983                IEEE802154_HW_OMIT_CKSUM |
2984                IEEE802154_HW_FRAME_RETRIES |
2985                IEEE802154_HW_PROMISCUOUS |
2986                IEEE802154_HW_CSMA_PARAMS;
2987        ca8210_hw->phy->flags =
2988                WPAN_PHY_FLAG_TXPOWER |
2989                WPAN_PHY_FLAG_CCA_ED_LEVEL |
2990                WPAN_PHY_FLAG_CCA_MODE;
2991}
2992
2993/**
2994 * ca8210_test_interface_init() - Initialise the test file interface
2995 * @priv:  Pointer to private data structure
2996 *
2997 * Provided as an alternative to the standard linux network interface, the test
2998 * interface exposes a file in the filesystem (ca8210_test) that allows
2999 * 802.15.4 SAP Commands and Cascoda EVBME commands to be sent directly to
3000 * the stack.
3001 *
3002 * Return: 0 or linux error code
3003 */
3004static int ca8210_test_interface_init(struct ca8210_priv *priv)
3005{
3006        struct ca8210_test *test = &priv->test;
3007        char node_name[32];
3008
3009        snprintf(
3010                node_name,
3011                sizeof(node_name),
3012                "ca8210@%d_%d",
3013                priv->spi->master->bus_num,
3014                priv->spi->chip_select
3015        );
3016
3017        test->ca8210_dfs_spi_int = debugfs_create_file(
3018                node_name,
3019                0600, /* S_IRUSR | S_IWUSR */
3020                NULL,
3021                priv,
3022                &test_int_fops
3023        );
3024
3025        debugfs_create_symlink("ca8210", NULL, node_name);
3026        init_waitqueue_head(&test->readq);
3027        return kfifo_alloc(
3028                &test->up_fifo,
3029                CA8210_TEST_INT_FIFO_SIZE,
3030                GFP_KERNEL
3031        );
3032}
3033
3034/**
3035 * ca8210_test_interface_clear() - Deinitialise the test file interface
3036 * @priv:  Pointer to private data structure
3037 */
3038static void ca8210_test_interface_clear(struct ca8210_priv *priv)
3039{
3040        struct ca8210_test *test = &priv->test;
3041
3042        debugfs_remove(test->ca8210_dfs_spi_int);
3043        kfifo_free(&test->up_fifo);
3044        dev_info(&priv->spi->dev, "Test interface removed\n");
3045}
3046
3047/**
3048 * ca8210_remove() - Shut down a ca8210 upon being disconnected
3049 * @spi_device:  Pointer to spi device data structure
3050 *
3051 * Return: 0 or linux error code
3052 */
3053static int ca8210_remove(struct spi_device *spi_device)
3054{
3055        struct ca8210_priv *priv;
3056        struct ca8210_platform_data *pdata;
3057
3058        dev_info(&spi_device->dev, "Removing ca8210\n");
3059
3060        pdata = spi_device->dev.platform_data;
3061        if (pdata) {
3062                if (pdata->extclockenable) {
3063                        ca8210_unregister_ext_clock(spi_device);
3064                        ca8210_config_extern_clk(pdata, spi_device, 0);
3065                }
3066                free_irq(pdata->irq_id, spi_device->dev.driver_data);
3067                kfree(pdata);
3068                spi_device->dev.platform_data = NULL;
3069        }
3070        /* get spi_device private data */
3071        priv = spi_get_drvdata(spi_device);
3072        if (priv) {
3073                dev_info(
3074                        &spi_device->dev,
3075                        "sync_down = %d, sync_up = %d\n",
3076                        priv->sync_down,
3077                        priv->sync_up
3078                );
3079                ca8210_dev_com_clear(spi_device->dev.driver_data);
3080                if (priv->hw) {
3081                        if (priv->hw_registered)
3082                                ieee802154_unregister_hw(priv->hw);
3083                        ieee802154_free_hw(priv->hw);
3084                        priv->hw = NULL;
3085                        dev_info(
3086                                &spi_device->dev,
3087                                "Unregistered & freed ieee802154_hw.\n"
3088                        );
3089                }
3090                if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS))
3091                        ca8210_test_interface_clear(priv);
3092        }
3093
3094        return 0;
3095}
3096
3097/**
3098 * ca8210_probe() - Set up a connected ca8210 upon being detected by the system
3099 * @spi_device:  Pointer to spi device data structure
3100 *
3101 * Return: 0 or linux error code
3102 */
3103static int ca8210_probe(struct spi_device *spi_device)
3104{
3105        struct ca8210_priv *priv;
3106        struct ieee802154_hw *hw;
3107        struct ca8210_platform_data *pdata;
3108        int ret;
3109
3110        dev_info(&spi_device->dev, "Inserting ca8210\n");
3111
3112        /* allocate ieee802154_hw and private data */
3113        hw = ieee802154_alloc_hw(sizeof(struct ca8210_priv), &ca8210_phy_ops);
3114        if (!hw) {
3115                dev_crit(&spi_device->dev, "ieee802154_alloc_hw failed\n");
3116                ret = -ENOMEM;
3117                goto error;
3118        }
3119
3120        priv = hw->priv;
3121        priv->hw = hw;
3122        priv->spi = spi_device;
3123        hw->parent = &spi_device->dev;
3124        spin_lock_init(&priv->lock);
3125        priv->async_tx_pending = false;
3126        priv->hw_registered = false;
3127        priv->sync_up = 0;
3128        priv->sync_down = 0;
3129        priv->promiscuous = false;
3130        priv->retries = 0;
3131        init_completion(&priv->ca8210_is_awake);
3132        init_completion(&priv->spi_transfer_complete);
3133        init_completion(&priv->sync_exchange_complete);
3134        spi_set_drvdata(priv->spi, priv);
3135        if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) {
3136                cascoda_api_upstream = ca8210_test_int_driver_write;
3137                ca8210_test_interface_init(priv);
3138        } else {
3139                cascoda_api_upstream = NULL;
3140        }
3141        ca8210_hw_setup(hw);
3142        ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
3143
3144        pdata = kmalloc(sizeof(*pdata), GFP_KERNEL);
3145        if (!pdata) {
3146                ret = -ENOMEM;
3147                goto error;
3148        }
3149
3150        priv->spi->dev.platform_data = pdata;
3151        ret = ca8210_get_platform_data(priv->spi, pdata);
3152        if (ret) {
3153                dev_crit(&spi_device->dev, "ca8210_get_platform_data failed\n");
3154                goto error;
3155        }
3156
3157        ret = ca8210_dev_com_init(priv);
3158        if (ret) {
3159                dev_crit(&spi_device->dev, "ca8210_dev_com_init failed\n");
3160                goto error;
3161        }
3162        ret = ca8210_reset_init(priv->spi);
3163        if (ret) {
3164                dev_crit(&spi_device->dev, "ca8210_reset_init failed\n");
3165                goto error;
3166        }
3167
3168        ret = ca8210_interrupt_init(priv->spi);
3169        if (ret) {
3170                dev_crit(&spi_device->dev, "ca8210_interrupt_init failed\n");
3171                goto error;
3172        }
3173
3174        msleep(100);
3175
3176        ca8210_reset_send(priv->spi, 1);
3177
3178        ret = tdme_chipinit(priv->spi);
3179        if (ret) {
3180                dev_crit(&spi_device->dev, "tdme_chipinit failed\n");
3181                goto error;
3182        }
3183
3184        if (pdata->extclockenable) {
3185                ret = ca8210_config_extern_clk(pdata, priv->spi, 1);
3186                if (ret) {
3187                        dev_crit(
3188                                &spi_device->dev,
3189                                "ca8210_config_extern_clk failed\n"
3190                        );
3191                        goto error;
3192                }
3193                ret = ca8210_register_ext_clock(priv->spi);
3194                if (ret) {
3195                        dev_crit(
3196                                &spi_device->dev,
3197                                "ca8210_register_ext_clock failed\n"
3198                        );
3199                        goto error;
3200                }
3201        }
3202
3203        ret = ieee802154_register_hw(hw);
3204        if (ret) {
3205                dev_crit(&spi_device->dev, "ieee802154_register_hw failed\n");
3206                goto error;
3207        }
3208        priv->hw_registered = true;
3209
3210        return 0;
3211error:
3212        msleep(100); /* wait for pending spi transfers to complete */
3213        ca8210_remove(spi_device);
3214        return link_to_linux_err(ret);
3215}
3216
3217static const struct of_device_id ca8210_of_ids[] = {
3218        {.compatible = "cascoda,ca8210", },
3219        {},
3220};
3221MODULE_DEVICE_TABLE(of, ca8210_of_ids);
3222
3223static struct spi_driver ca8210_spi_driver = {
3224        .driver = {
3225                .name =                 DRIVER_NAME,
3226                .owner =                THIS_MODULE,
3227                .of_match_table =       of_match_ptr(ca8210_of_ids),
3228        },
3229        .probe  =                       ca8210_probe,
3230        .remove =                       ca8210_remove
3231};
3232
3233module_spi_driver(ca8210_spi_driver);
3234
3235MODULE_AUTHOR("Harry Morris <h.morris@cascoda.com>");
3236MODULE_DESCRIPTION("CA-8210 SoftMAC driver");
3237MODULE_LICENSE("Dual BSD/GPL");
3238MODULE_VERSION("1.0");
3239