/* * http://www.cascoda.com/products/ca-821x/ * Copyright (c) 2016, Cascoda, Ltd. * All rights reserved. * * This code is dual-licensed under both GPLv2 and 3-clause BSD. What follows is * the license notice for both respectively. * ******************************************************************************* * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * ******************************************************************************* * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <linux/cdev.h> #include <linux/clk-provider.h> #include <linux/debugfs.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/gpio.h> #include <linux/ieee802154.h> #include <linux/io.h> #include <linux/kfifo.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/poll.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/spi/spi.h> #include <linux/spinlock.h> #include <linux/string.h> #include <linux/workqueue.h> #include <linux/interrupt.h> #include <net/ieee802154_netdev.h> #include <net/mac802154.h> #define DRIVER_NAME … /* external clock frequencies */ #define ONE_MHZ … #define TWO_MHZ … #define FOUR_MHZ … #define EIGHT_MHZ … #define SIXTEEN_MHZ … /* spi constants */ #define CA8210_SPI_BUF_SIZE … #define CA8210_SYNC_TIMEOUT … /* test interface constants */ #define CA8210_TEST_INT_FILE_NAME … #define CA8210_TEST_INT_FIFO_SIZE … /* HWME attribute IDs */ #define HWME_EDTHRESHOLD … #define HWME_EDVALUE … #define HWME_SYSCLKOUT … #define HWME_LQILIMIT … /* TDME attribute IDs */ #define TDME_CHANNEL … #define TDME_ATM_CONFIG … #define MAX_HWME_ATTRIBUTE_SIZE … #define MAX_TDME_ATTRIBUTE_SIZE … /* PHY/MAC PIB Attribute Enumerations */ #define PHY_CURRENT_CHANNEL … #define PHY_TRANSMIT_POWER … #define PHY_CCA_MODE … #define MAC_ASSOCIATION_PERMIT … #define MAC_AUTO_REQUEST … #define MAC_BATT_LIFE_EXT … #define MAC_BATT_LIFE_EXT_PERIODS … #define MAC_BEACON_PAYLOAD … #define MAC_BEACON_PAYLOAD_LENGTH … #define MAC_BEACON_ORDER … #define MAC_GTS_PERMIT … #define MAC_MAX_CSMA_BACKOFFS … #define MAC_MIN_BE … #define MAC_PAN_ID … #define MAC_PROMISCUOUS_MODE … #define MAC_RX_ON_WHEN_IDLE … #define MAC_SHORT_ADDRESS … #define MAC_SUPERFRAME_ORDER … #define MAC_ASSOCIATED_PAN_COORD … #define MAC_MAX_BE … #define MAC_MAX_FRAME_RETRIES … #define MAC_RESPONSE_WAIT_TIME … #define MAC_SECURITY_ENABLED … #define MAC_AUTO_REQUEST_SECURITY_LEVEL … #define MAC_AUTO_REQUEST_KEY_ID_MODE … #define NS_IEEE_ADDRESS … /* MAC Address Mode Definitions */ #define MAC_MODE_NO_ADDR … #define MAC_MODE_SHORT_ADDR … #define MAC_MODE_LONG_ADDR … /* MAC constants */ #define MAX_BEACON_OVERHEAD … #define MAX_BEACON_PAYLOAD_LENGTH … #define MAX_ATTRIBUTE_SIZE … #define MAX_DATA_SIZE … #define CA8210_VALID_CHANNELS … /* MAC workarounds for V1.1 and MPW silicon (V0.x) */ #define CA8210_MAC_WORKAROUNDS … #define CA8210_MAC_MPW … /* memory manipulation macros */ #define LS_BYTE(x) … #define MS_BYTE(x) … /* message ID codes in SPI commands */ /* downstream */ #define MCPS_DATA_REQUEST … #define MLME_ASSOCIATE_REQUEST … #define MLME_ASSOCIATE_RESPONSE … #define MLME_DISASSOCIATE_REQUEST … #define MLME_GET_REQUEST … #define MLME_ORPHAN_RESPONSE … #define MLME_RESET_REQUEST … #define MLME_RX_ENABLE_REQUEST … #define MLME_SCAN_REQUEST … #define MLME_SET_REQUEST … #define MLME_START_REQUEST … #define MLME_POLL_REQUEST … #define HWME_SET_REQUEST … #define HWME_GET_REQUEST … #define TDME_SETSFR_REQUEST … #define TDME_GETSFR_REQUEST … #define TDME_SET_REQUEST … /* upstream */ #define MCPS_DATA_INDICATION … #define MCPS_DATA_CONFIRM … #define MLME_RESET_CONFIRM … #define MLME_SET_CONFIRM … #define MLME_START_CONFIRM … #define HWME_SET_CONFIRM … #define HWME_GET_CONFIRM … #define HWME_WAKEUP_INDICATION … #define TDME_SETSFR_CONFIRM … /* SPI command IDs */ /* bit indicating a confirm or indication from slave to master */ #define SPI_S2M … /* bit indicating a synchronous message */ #define SPI_SYN … /* SPI command definitions */ #define SPI_IDLE … #define SPI_NACK … #define SPI_MCPS_DATA_REQUEST … #define SPI_MCPS_DATA_INDICATION … #define SPI_MCPS_DATA_CONFIRM … #define SPI_MLME_ASSOCIATE_REQUEST … #define SPI_MLME_RESET_REQUEST … #define SPI_MLME_SET_REQUEST … #define SPI_MLME_START_REQUEST … #define SPI_MLME_RESET_CONFIRM … #define SPI_MLME_SET_CONFIRM … #define SPI_MLME_START_CONFIRM … #define SPI_HWME_SET_REQUEST … #define SPI_HWME_GET_REQUEST … #define SPI_HWME_SET_CONFIRM … #define SPI_HWME_GET_CONFIRM … #define SPI_HWME_WAKEUP_INDICATION … #define SPI_TDME_SETSFR_REQUEST … #define SPI_TDME_SET_REQUEST … #define SPI_TDME_SETSFR_CONFIRM … /* TDME SFR addresses */ /* Page 0 */ #define CA8210_SFR_PACFG … #define CA8210_SFR_MACCON … #define CA8210_SFR_PACFGIB … /* Page 1 */ #define CA8210_SFR_LOTXCAL … #define CA8210_SFR_PTHRH … #define CA8210_SFR_PRECFG … #define CA8210_SFR_LNAGX40 … #define CA8210_SFR_LNAGX41 … #define CA8210_SFR_LNAGX42 … #define CA8210_SFR_LNAGX43 … #define CA8210_SFR_LNAGX44 … #define CA8210_SFR_LNAGX45 … #define CA8210_SFR_LNAGX46 … #define CA8210_SFR_LNAGX47 … #define PACFGIB_DEFAULT_CURRENT … #define PTHRH_DEFAULT_THRESHOLD … #define LNAGX40_DEFAULT_GAIN … #define LNAGX41_DEFAULT_GAIN … #define LNAGX42_DEFAULT_GAIN … #define LNAGX43_DEFAULT_GAIN … #define LNAGX44_DEFAULT_GAIN … #define LNAGX45_DEFAULT_GAIN … #define LNAGX46_DEFAULT_GAIN … #define LNAGX47_DEFAULT_GAIN … #define CA8210_IOCTL_HARD_RESET … /* Structs/Enums */ /** * struct cas_control - spi transfer structure * @msg: spi_message for each exchange * @transfer: spi_transfer for each exchange * @tx_buf: source array for transmission * @tx_in_buf: array storing bytes received during transmission * @priv: pointer to private data * * This structure stores all the necessary data passed around during a single * spi exchange. */ struct cas_control { … }; /** * struct ca8210_test - ca8210 test interface structure * @ca8210_dfs_spi_int: pointer to the entry in the debug fs for this device * @up_fifo: fifo for upstream messages * @readq: read wait queue * * This structure stores all the data pertaining to the debug interface */ struct ca8210_test { … }; /** * struct ca8210_priv - ca8210 private data structure * @spi: pointer to the ca8210 spi device object * @hw: pointer to the ca8210 ieee802154_hw object * @hw_registered: true if hw has been registered with ieee802154 * @lock: spinlock protecting the private data area * @mlme_workqueue: workqueue for triggering MLME Reset * @irq_workqueue: workqueue for irq processing * @tx_skb: current socket buffer to transmit * @nextmsduhandle: msdu handle to pass to the 15.4 MAC layer for the * next transmission * @clk: external clock provided by the ca8210 * @last_dsn: sequence number of last data packet received, for * resend detection * @test: test interface data section for this instance * @async_tx_pending: true if an asynchronous transmission was started and * is not complete * @sync_command_response: pointer to buffer to fill with sync response * @ca8210_is_awake: nonzero if ca8210 is initialised, ready for comms * @sync_down: counts number of downstream synchronous commands * @sync_up: counts number of upstream synchronous commands * @spi_transfer_complete: completion object for a single spi_transfer * @sync_exchange_complete: completion object for a complete synchronous API * exchange * @promiscuous: whether the ca8210 is in promiscuous mode or not * @retries: records how many times the current pending spi * transfer has been retried */ struct ca8210_priv { … }; /** * struct work_priv_container - link between a work object and the relevant * device's private data * @work: work object being executed * @priv: device's private data section * */ struct work_priv_container { … }; /** * struct ca8210_platform_data - ca8210 platform data structure * @extclockenable: true if the external clock is to be enabled * @extclockfreq: frequency of the external clock * @extclockgpio: ca8210 output gpio of the external clock * @gpio_reset: gpio number of ca8210 reset line * @gpio_irq: gpio number of ca8210 interrupt line * @irq_id: identifier for the ca8210 irq * */ struct ca8210_platform_data { … }; /** * struct fulladdr - full MAC addressing information structure * @mode: address mode (none, short, extended) * @pan_id: 16-bit LE pan id * @address: LE address, variable length as specified by mode * */ struct fulladdr { … }; /** * union macaddr: generic MAC address container * @short_address: 16-bit short address * @ieee_address: 64-bit extended address as LE byte array * */ macaddr; /** * struct secspec: security specification for SAP commands * @security_level: 0-7, controls level of authentication & encryption * @key_id_mode: 0-3, specifies how to obtain key * @key_source: extended key retrieval data * @key_index: single-byte key identifier * */ struct secspec { … }; /* downlink functions parameter set definitions */ struct mcps_data_request_pset { … }; struct mlme_set_request_pset { … }; struct hwme_set_request_pset { … }; struct hwme_get_request_pset { … }; struct tdme_setsfr_request_pset { … }; /* uplink functions parameter set definitions */ struct hwme_set_confirm_pset { … }; struct hwme_get_confirm_pset { … }; struct tdme_setsfr_confirm_pset { … }; struct mac_message { … }; pa_cfg_sfr; struct preamble_cfg_sfr { … }; static int (*cascoda_api_upstream)( const u8 *buf, size_t len, void *device_ref ); /** * link_to_linux_err() - Translates an 802.15.4 return code into the closest * linux error * @link_status: 802.15.4 status code * * Return: 0 or Linux error code */ static int link_to_linux_err(int link_status) { … } /** * ca8210_test_int_driver_write() - Writes a message to the test interface to be * read by the userspace * @buf: Buffer containing upstream message * @len: length of message to write * @spi: SPI device of message originator * * Return: 0 or linux error code */ static int ca8210_test_int_driver_write( const u8 *buf, size_t len, void *spi ) { … } /* SPI Operation */ static int ca8210_net_rx( struct ieee802154_hw *hw, u8 *command, size_t len ); static u8 mlme_reset_request_sync( u8 set_default_pib, void *device_ref ); static int ca8210_spi_transfer( struct spi_device *spi, const u8 *buf, size_t len ); /** * ca8210_reset_send() - Hard resets the ca8210 for a given time * @spi: Pointer to target ca8210 spi device * @ms: Milliseconds to hold the reset line low for */ static void ca8210_reset_send(struct spi_device *spi, unsigned int ms) { … } /** * ca8210_mlme_reset_worker() - Resets the MLME, Called when the MAC OVERFLOW * condition happens. * @work: Pointer to work being executed */ static void ca8210_mlme_reset_worker(struct work_struct *work) { … } /** * ca8210_rx_done() - Calls various message dispatches responding to a received * command * @cas_ctl: Pointer to the cas_control object for the relevant spi transfer * * Presents a received SAP command from the ca8210 to the Cascoda EVBME, test * interface and network driver. */ static void ca8210_rx_done(struct cas_control *cas_ctl) { … } static void ca8210_remove(struct spi_device *spi_device); /** * ca8210_spi_transfer_complete() - Called when a single spi transfer has * completed * @context: Pointer to the cas_control object for the finished transfer */ static void ca8210_spi_transfer_complete(void *context) { … } /** * ca8210_spi_transfer() - Initiate duplex spi transfer with ca8210 * @spi: Pointer to spi device for transfer * @buf: Octet array to send * @len: length of the buffer being sent * * Return: 0 or linux error code */ static int ca8210_spi_transfer( struct spi_device *spi, const u8 *buf, size_t len ) { … } /** * ca8210_spi_exchange() - Exchange API/SAP commands with the radio * @buf: Octet array of command being sent downstream * @len: length of buf * @response: buffer for storing synchronous response * @device_ref: spi_device pointer for ca8210 * * Effectively calls ca8210_spi_transfer to write buf[] to the spi, then for * synchronous commands waits for the corresponding response to be read from * the spi before returning. The response is written to the response parameter. * * Return: 0 or linux error code */ static int ca8210_spi_exchange( const u8 *buf, size_t len, u8 *response, void *device_ref ) { … } /** * ca8210_interrupt_handler() - Called when an irq is received from the ca8210 * @irq: Id of the irq being handled * @dev_id: Pointer passed by the system, pointing to the ca8210's private data * * This function is called when the irq line from the ca8210 is asserted, * signifying that the ca8210 has a message to send upstream to us. Starts the * asynchronous spi read. * * Return: irq return code */ static irqreturn_t ca8210_interrupt_handler(int irq, void *dev_id) { … } static int (*cascoda_api_downstream)( const u8 *buf, size_t len, u8 *response, void *device_ref ) = …; /* Cascoda API / 15.4 SAP Primitives */ /** * tdme_setsfr_request_sync() - TDME_SETSFR_request/confirm according to API * @sfr_page: SFR Page * @sfr_address: SFR Address * @sfr_value: SFR Value * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of TDME-SETSFR.confirm */ static u8 tdme_setsfr_request_sync( u8 sfr_page, u8 sfr_address, u8 sfr_value, void *device_ref ) { … } /** * tdme_chipinit() - TDME Chip Register Default Initialisation Macro * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of API calls */ static u8 tdme_chipinit(void *device_ref) { … } /** * tdme_channelinit() - TDME Channel Register Default Initialisation Macro (Tx) * @channel: 802.15.4 channel to initialise chip for * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of API calls */ static u8 tdme_channelinit(u8 channel, void *device_ref) { … } /** * tdme_checkpibattribute() - Checks Attribute Values that are not checked in * MAC * @pib_attribute: Attribute Number * @pib_attribute_length: Attribute length * @pib_attribute_value: Pointer to Attribute Value * * Return: 802.15.4 status code of checks */ static u8 tdme_checkpibattribute( u8 pib_attribute, u8 pib_attribute_length, const void *pib_attribute_value ) { … } /** * tdme_settxpower() - Sets the tx power for MLME_SET phyTransmitPower * @txp: Transmit Power * @device_ref: Nondescript pointer to target device * * Normalised to 802.15.4 Definition (6-bit, signed): * Bit 7-6: not used * Bit 5-0: tx power (-32 - +31 dB) * * Return: 802.15.4 status code of api calls */ static u8 tdme_settxpower(u8 txp, void *device_ref) { … } /** * mcps_data_request() - mcps_data_request (Send Data) according to API Spec * @src_addr_mode: Source Addressing Mode * @dst_address_mode: Destination Addressing Mode * @dst_pan_id: Destination PAN ID * @dst_addr: Pointer to Destination Address * @msdu_length: length of Data * @msdu: Pointer to Data * @msdu_handle: Handle of Data * @tx_options: Tx Options Bit Field * @security: Pointer to Security Structure or NULL * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of action */ static u8 mcps_data_request( u8 src_addr_mode, u8 dst_address_mode, u16 dst_pan_id, union macaddr *dst_addr, u8 msdu_length, u8 *msdu, u8 msdu_handle, u8 tx_options, struct secspec *security, void *device_ref ) { … } /** * mlme_reset_request_sync() - MLME_RESET_request/confirm according to API Spec * @set_default_pib: Set defaults in PIB * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of MLME-RESET.confirm */ static u8 mlme_reset_request_sync( u8 set_default_pib, void *device_ref ) { … } /** * mlme_set_request_sync() - MLME_SET_request/confirm according to API Spec * @pib_attribute: Attribute Number * @pib_attribute_index: Index within Attribute if an Array * @pib_attribute_length: Attribute length * @pib_attribute_value: Pointer to Attribute Value * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of MLME-SET.confirm */ static u8 mlme_set_request_sync( u8 pib_attribute, u8 pib_attribute_index, u8 pib_attribute_length, const void *pib_attribute_value, void *device_ref ) { … } /** * hwme_set_request_sync() - HWME_SET_request/confirm according to API Spec * @hw_attribute: Attribute Number * @hw_attribute_length: Attribute length * @hw_attribute_value: Pointer to Attribute Value * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of HWME-SET.confirm */ static u8 hwme_set_request_sync( u8 hw_attribute, u8 hw_attribute_length, u8 *hw_attribute_value, void *device_ref ) { … } /** * hwme_get_request_sync() - HWME_GET_request/confirm according to API Spec * @hw_attribute: Attribute Number * @hw_attribute_length: Attribute length * @hw_attribute_value: Pointer to Attribute Value * @device_ref: Nondescript pointer to target device * * Return: 802.15.4 status code of HWME-GET.confirm */ static u8 hwme_get_request_sync( u8 hw_attribute, u8 *hw_attribute_length, u8 *hw_attribute_value, void *device_ref ) { … } /* Network driver operation */ /** * ca8210_async_xmit_complete() - Called to announce that an asynchronous * transmission has finished * @hw: ieee802154_hw of ca8210 that has finished exchange * @msduhandle: Identifier of transmission that has completed * @status: Returned 802.15.4 status code of the transmission * * Return: 0 or linux error code */ static int ca8210_async_xmit_complete( struct ieee802154_hw *hw, u8 msduhandle, u8 status) { … } /** * ca8210_skb_rx() - Contructs a properly framed socket buffer from a received * MCPS_DATA_indication * @hw: ieee802154_hw that MCPS_DATA_indication was received by * @len: length of MCPS_DATA_indication * @data_ind: Octet array of MCPS_DATA_indication * * Called by the spi driver whenever a SAP command is received, this function * will ascertain whether the command is of interest to the network driver and * take necessary action. * * Return: 0 or linux error code */ static int ca8210_skb_rx( struct ieee802154_hw *hw, size_t len, u8 *data_ind ) { … } /** * ca8210_net_rx() - Acts upon received SAP commands relevant to the network * driver * @hw: ieee802154_hw that command was received by * @command: Octet array of received command * @len: length of the received command * * Called by the spi driver whenever a SAP command is received, this function * will ascertain whether the command is of interest to the network driver and * take necessary action. * * Return: 0 or linux error code */ static int ca8210_net_rx(struct ieee802154_hw *hw, u8 *command, size_t len) { … } /** * ca8210_skb_tx() - Transmits a given socket buffer using the ca8210 * @skb: Socket buffer to transmit * @msduhandle: Data identifier to pass to the 802.15.4 MAC * @priv: Pointer to private data section of target ca8210 * * Return: 0 or linux error code */ static int ca8210_skb_tx( struct sk_buff *skb, u8 msduhandle, struct ca8210_priv *priv ) { … } /** * ca8210_start() - Starts the network driver * @hw: ieee802154_hw of ca8210 being started * * Return: 0 or linux error code */ static int ca8210_start(struct ieee802154_hw *hw) { … } /** * ca8210_stop() - Stops the network driver * @hw: ieee802154_hw of ca8210 being stopped * * Return: 0 or linux error code */ static void ca8210_stop(struct ieee802154_hw *hw) { … } /** * ca8210_xmit_async() - Asynchronously transmits a given socket buffer using * the ca8210 * @hw: ieee802154_hw of ca8210 to transmit from * @skb: Socket buffer to transmit * * Return: 0 or linux error code */ static int ca8210_xmit_async(struct ieee802154_hw *hw, struct sk_buff *skb) { … } /** * ca8210_get_ed() - Returns the measured energy on the current channel at this * instant in time * @hw: ieee802154_hw of target ca8210 * @level: Measured Energy Detect level * * Return: 0 or linux error code */ static int ca8210_get_ed(struct ieee802154_hw *hw, u8 *level) { … } /** * ca8210_set_channel() - Sets the current operating 802.15.4 channel of the * ca8210 * @hw: ieee802154_hw of target ca8210 * @page: Channel page to set * @channel: Channel number to set * * Return: 0 or linux error code */ static int ca8210_set_channel( struct ieee802154_hw *hw, u8 page, u8 channel ) { … } /** * ca8210_set_hw_addr_filt() - Sets the address filtering parameters of the * ca8210 * @hw: ieee802154_hw of target ca8210 * @filt: Filtering parameters * @changed: Bitmap representing which parameters to change * * Effectively just sets the actual addressing information identifying this node * as all filtering is performed by the ca8210 as detailed in the IEEE 802.15.4 * 2006 specification. * * Return: 0 or linux error code */ static int ca8210_set_hw_addr_filt( struct ieee802154_hw *hw, struct ieee802154_hw_addr_filt *filt, unsigned long changed ) { … } /** * ca8210_set_tx_power() - Sets the transmit power of the ca8210 * @hw: ieee802154_hw of target ca8210 * @mbm: Transmit power in mBm (dBm*100) * * Return: 0 or linux error code */ static int ca8210_set_tx_power(struct ieee802154_hw *hw, s32 mbm) { … } /** * ca8210_set_cca_mode() - Sets the clear channel assessment mode of the ca8210 * @hw: ieee802154_hw of target ca8210 * @cca: CCA mode to set * * Return: 0 or linux error code */ static int ca8210_set_cca_mode( struct ieee802154_hw *hw, const struct wpan_phy_cca *cca ) { … } /** * ca8210_set_cca_ed_level() - Sets the CCA ED level of the ca8210 * @hw: ieee802154_hw of target ca8210 * @level: ED level to set (in mbm) * * Sets the minimum threshold of measured energy above which the ca8210 will * back off and retry a transmission. * * Return: 0 or linux error code */ static int ca8210_set_cca_ed_level(struct ieee802154_hw *hw, s32 level) { … } /** * ca8210_set_csma_params() - Sets the CSMA parameters of the ca8210 * @hw: ieee802154_hw of target ca8210 * @min_be: Minimum backoff exponent when backing off a transmission * @max_be: Maximum backoff exponent when backing off a transmission * @retries: Number of times to retry after backing off * * Return: 0 or linux error code */ static int ca8210_set_csma_params( struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries ) { … } /** * ca8210_set_frame_retries() - Sets the maximum frame retries of the ca8210 * @hw: ieee802154_hw of target ca8210 * @retries: Number of retries * * Sets the number of times to retry a transmission if no acknowledgment was * received from the other end when one was requested. * * Return: 0 or linux error code */ static int ca8210_set_frame_retries(struct ieee802154_hw *hw, s8 retries) { … } static int ca8210_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on) { … } static const struct ieee802154_ops ca8210_phy_ops = …; /* Test/EVBME Interface */ /** * ca8210_test_int_open() - Opens the test interface to the userspace * @inodp: inode representation of file interface * @filp: file interface * * Return: 0 or linux error code */ static int ca8210_test_int_open(struct inode *inodp, struct file *filp) { … } /** * ca8210_test_check_upstream() - Checks a command received from the upstream * testing interface for required action * @buf: Buffer containing command to check * @device_ref: Nondescript pointer to target device * * Return: 0 or linux error code */ static int ca8210_test_check_upstream(u8 *buf, void *device_ref) { … } /* End of EVBMECheckSerialCommand() */ /** * ca8210_test_int_user_write() - Called by a process in userspace to send a * message to the ca8210 drivers * @filp: file interface * @in_buf: Buffer containing message to write * @len: length of message * @off: file offset * * Return: 0 or linux error code */ static ssize_t ca8210_test_int_user_write( struct file *filp, const char __user *in_buf, size_t len, loff_t *off ) { … } /** * ca8210_test_int_user_read() - Called by a process in userspace to read a * message from the ca8210 drivers * @filp: file interface * @buf: Buffer to write message to * @len: length of message to read (ignored) * @offp: file offset * * If the O_NONBLOCK flag was set when opening the file then this function will * not block, i.e. it will return if the fifo is empty. Otherwise the function * will block, i.e. wait until new data arrives. * * Return: number of bytes read */ static ssize_t ca8210_test_int_user_read( struct file *filp, char __user *buf, size_t len, loff_t *offp ) { … } /** * ca8210_test_int_ioctl() - Called by a process in userspace to enact an * arbitrary action * @filp: file interface * @ioctl_num: which action to enact * @ioctl_param: arbitrary parameter for the action * * Return: status */ static long ca8210_test_int_ioctl( struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param ) { … } /** * ca8210_test_int_poll() - Called by a process in userspace to determine which * actions are currently possible for the file * @filp: file interface * @ptable: poll table * * Return: set of poll return flags */ static __poll_t ca8210_test_int_poll( struct file *filp, struct poll_table_struct *ptable ) { … } static const struct file_operations test_int_fops = …; /* Init/Deinit */ /** * ca8210_get_platform_data() - Populate a ca8210_platform_data object * @spi_device: Pointer to ca8210 spi device object to get data for * @pdata: Pointer to ca8210_platform_data object to populate * * Return: 0 or linux error code */ static int ca8210_get_platform_data( struct spi_device *spi_device, struct ca8210_platform_data *pdata ) { … } /** * ca8210_config_extern_clk() - Configure the external clock provided by the * ca8210 * @pdata: Pointer to ca8210_platform_data containing clock parameters * @spi: Pointer to target ca8210 spi device * @on: True to turn the clock on, false to turn off * * The external clock is configured with a frequency and output pin taken from * the platform data. * * Return: 0 or linux error code */ static int ca8210_config_extern_clk( struct ca8210_platform_data *pdata, struct spi_device *spi, bool on ) { … } /** * ca8210_register_ext_clock() - Register ca8210's external clock with kernel * @spi: Pointer to target ca8210 spi device * * Return: 0 or linux error code */ static int ca8210_register_ext_clock(struct spi_device *spi) { … } /** * ca8210_unregister_ext_clock() - Unregister ca8210's external clock with * kernel * @spi: Pointer to target ca8210 spi device */ static void ca8210_unregister_ext_clock(struct spi_device *spi) { … } /** * ca8210_reset_init() - Initialise the reset input to the ca8210 * @spi: Pointer to target ca8210 spi device * * Return: 0 or linux error code */ static int ca8210_reset_init(struct spi_device *spi) { … } /** * ca8210_interrupt_init() - Initialise the irq output from the ca8210 * @spi: Pointer to target ca8210 spi device * * Return: 0 or linux error code */ static int ca8210_interrupt_init(struct spi_device *spi) { … } /** * ca8210_dev_com_init() - Initialise the spi communication component * @priv: Pointer to private data structure * * Return: 0 or linux error code */ static int ca8210_dev_com_init(struct ca8210_priv *priv) { … } /** * ca8210_dev_com_clear() - Deinitialise the spi communication component * @priv: Pointer to private data structure */ static void ca8210_dev_com_clear(struct ca8210_priv *priv) { … } #define CA8210_MAX_TX_POWERS … static const s32 ca8210_tx_powers[CA8210_MAX_TX_POWERS] = …; #define CA8210_MAX_ED_LEVELS … static const s32 ca8210_ed_levels[CA8210_MAX_ED_LEVELS] = …; /** * ca8210_hw_setup() - Populate the ieee802154_hw phy attributes with the * ca8210's defaults * @ca8210_hw: Pointer to ieee802154_hw to populate */ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) { … } /** * ca8210_test_interface_init() - Initialise the test file interface * @priv: Pointer to private data structure * * Provided as an alternative to the standard linux network interface, the test * interface exposes a file in the filesystem (ca8210_test) that allows * 802.15.4 SAP Commands and Cascoda EVBME commands to be sent directly to * the stack. * * Return: 0 or linux error code */ static int ca8210_test_interface_init(struct ca8210_priv *priv) { … } /** * ca8210_test_interface_clear() - Deinitialise the test file interface * @priv: Pointer to private data structure */ static void ca8210_test_interface_clear(struct ca8210_priv *priv) { … } /** * ca8210_remove() - Shut down a ca8210 upon being disconnected * @spi_device: Pointer to spi device data structure * * Return: 0 or linux error code */ static void ca8210_remove(struct spi_device *spi_device) { … } /** * ca8210_probe() - Set up a connected ca8210 upon being detected by the system * @spi_device: Pointer to spi device data structure * * Return: 0 or linux error code */ static int ca8210_probe(struct spi_device *spi_device) { … } static const struct of_device_id ca8210_of_ids[] = …; MODULE_DEVICE_TABLE(of, ca8210_of_ids); static struct spi_driver ca8210_spi_driver = …; module_spi_driver(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; MODULE_VERSION(…) …;