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