1a10e763bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
27490b008SAlexander Aring /*
37490b008SAlexander Aring * atusb.c - Driver for the ATUSB IEEE 802.15.4 dongle
47490b008SAlexander Aring *
57490b008SAlexander Aring * Written 2013 by Werner Almesberger <werner@almesberger.net>
67490b008SAlexander Aring *
7151c37bcSStefan Schmidt * Copyright (c) 2015 - 2016 Stefan Schmidt <stefan@datenfreihafen.org>
8151c37bcSStefan Schmidt *
97490b008SAlexander Aring * Based on at86rf230.c and spi_atusb.c.
107490b008SAlexander Aring * at86rf230.c is
117490b008SAlexander Aring * Copyright (C) 2009 Siemens AG
127490b008SAlexander Aring * Written by: Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
137490b008SAlexander Aring *
147490b008SAlexander Aring * spi_atusb.c is
157490b008SAlexander Aring * Copyright (c) 2011 Richard Sharpe <realrichardsharpe@gmail.com>
167490b008SAlexander Aring * Copyright (c) 2011 Stefan Schmidt <stefan@datenfreihafen.org>
177490b008SAlexander Aring * Copyright (c) 2011 Werner Almesberger <werner@almesberger.net>
187490b008SAlexander Aring *
197490b008SAlexander Aring * USB initialization is
207490b008SAlexander Aring * Copyright (c) 2013 Alexander Aring <alex.aring@gmail.com>
21d5dd29e4SJosef Filzmaier *
22d5dd29e4SJosef Filzmaier * Busware HUL support is
23d5dd29e4SJosef Filzmaier * Copyright (c) 2017 Josef Filzmaier <j.filzmaier@gmx.at>
247490b008SAlexander Aring */
257490b008SAlexander Aring
267490b008SAlexander Aring #include <linux/kernel.h>
277490b008SAlexander Aring #include <linux/slab.h>
287490b008SAlexander Aring #include <linux/module.h>
297490b008SAlexander Aring #include <linux/jiffies.h>
307490b008SAlexander Aring #include <linux/usb.h>
317490b008SAlexander Aring #include <linux/skbuff.h>
327490b008SAlexander Aring
337490b008SAlexander Aring #include <net/cfg802154.h>
347490b008SAlexander Aring #include <net/mac802154.h>
357490b008SAlexander Aring
367490b008SAlexander Aring #include "at86rf230.h"
377490b008SAlexander Aring #include "atusb.h"
387490b008SAlexander Aring
397490b008SAlexander Aring #define ATUSB_JEDEC_ATMEL 0x1f /* JEDEC manufacturer ID */
407490b008SAlexander Aring
417490b008SAlexander Aring #define ATUSB_NUM_RX_URBS 4 /* allow for a bit of local latency */
427490b008SAlexander Aring #define ATUSB_ALLOC_DELAY_MS 100 /* delay after failed allocation */
437490b008SAlexander Aring #define ATUSB_TX_TIMEOUT_MS 200 /* on the air timeout */
447490b008SAlexander Aring
457490b008SAlexander Aring struct atusb {
467490b008SAlexander Aring struct ieee802154_hw *hw;
477490b008SAlexander Aring struct usb_device *usb_dev;
48d5dd29e4SJosef Filzmaier struct atusb_chip_data *data;
497490b008SAlexander Aring int shutdown; /* non-zero if shutting down */
507490b008SAlexander Aring int err; /* set by first error */
517490b008SAlexander Aring
527490b008SAlexander Aring /* RX variables */
537490b008SAlexander Aring struct delayed_work work; /* memory allocations */
547490b008SAlexander Aring struct usb_anchor idle_urbs; /* URBs waiting to be submitted */
557490b008SAlexander Aring struct usb_anchor rx_urbs; /* URBs waiting for reception */
567490b008SAlexander Aring
577490b008SAlexander Aring /* TX variables */
587490b008SAlexander Aring struct usb_ctrlrequest tx_dr;
597490b008SAlexander Aring struct urb *tx_urb;
607490b008SAlexander Aring struct sk_buff *tx_skb;
61909dcf9bSStefan Schmidt u8 tx_ack_seq; /* current TX ACK sequence number */
6246551564SStefan Schmidt
6346551564SStefan Schmidt /* Firmware variable */
6446551564SStefan Schmidt unsigned char fw_ver_maj; /* Firmware major version number */
6546551564SStefan Schmidt unsigned char fw_ver_min; /* Firmware minor version number */
6646551564SStefan Schmidt unsigned char fw_hw_type; /* Firmware hardware type */
677490b008SAlexander Aring };
687490b008SAlexander Aring
69d5dd29e4SJosef Filzmaier struct atusb_chip_data {
70d5dd29e4SJosef Filzmaier u16 t_channel_switch;
71d5dd29e4SJosef Filzmaier int rssi_base_val;
72d5dd29e4SJosef Filzmaier
73d5dd29e4SJosef Filzmaier int (*set_channel)(struct ieee802154_hw*, u8, u8);
74d5dd29e4SJosef Filzmaier int (*set_txpower)(struct ieee802154_hw*, s32);
75d5dd29e4SJosef Filzmaier };
76d5dd29e4SJosef Filzmaier
atusb_write_subreg(struct atusb * atusb,u8 reg,u8 mask,u8 shift,u8 value)77909dcf9bSStefan Schmidt static int atusb_write_subreg(struct atusb *atusb, u8 reg, u8 mask,
78909dcf9bSStefan Schmidt u8 shift, u8 value)
79bdc78737SStefan Schmidt {
80bdc78737SStefan Schmidt struct usb_device *usb_dev = atusb->usb_dev;
81909dcf9bSStefan Schmidt u8 orig, tmp;
82bdc78737SStefan Schmidt int ret = 0;
83bdc78737SStefan Schmidt
845f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s: 0x%02x <- 0x%02x\n", __func__, reg, value);
85bdc78737SStefan Schmidt
86416abf4fSPavel Skripkin ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
87416abf4fSPavel Skripkin 0, reg, &orig, 1, 1000, GFP_KERNEL);
88416abf4fSPavel Skripkin if (ret < 0)
89416abf4fSPavel Skripkin return ret;
90bdc78737SStefan Schmidt
91bdc78737SStefan Schmidt /* Write the value only into that part of the register which is allowed
92bdc78737SStefan Schmidt * by the mask. All other bits stay as before.
93bdc78737SStefan Schmidt */
94bdc78737SStefan Schmidt tmp = orig & ~mask;
95bdc78737SStefan Schmidt tmp |= (value << shift) & mask;
96bdc78737SStefan Schmidt
97bdc78737SStefan Schmidt if (tmp != orig)
98416abf4fSPavel Skripkin ret = usb_control_msg_send(usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
99416abf4fSPavel Skripkin tmp, reg, NULL, 0, 1000, GFP_KERNEL);
100bdc78737SStefan Schmidt
101bdc78737SStefan Schmidt return ret;
102bdc78737SStefan Schmidt }
103bdc78737SStefan Schmidt
atusb_read_subreg(struct atusb * lp,unsigned int addr,unsigned int mask,unsigned int shift)104d5dd29e4SJosef Filzmaier static int atusb_read_subreg(struct atusb *lp,
105d5dd29e4SJosef Filzmaier unsigned int addr, unsigned int mask,
106d5dd29e4SJosef Filzmaier unsigned int shift)
107d5dd29e4SJosef Filzmaier {
108416abf4fSPavel Skripkin int reg, ret;
109d5dd29e4SJosef Filzmaier
110416abf4fSPavel Skripkin ret = usb_control_msg_recv(lp->usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
111416abf4fSPavel Skripkin 0, addr, ®, 1, 1000, GFP_KERNEL);
112416abf4fSPavel Skripkin if (ret < 0)
113416abf4fSPavel Skripkin return ret;
114d5dd29e4SJosef Filzmaier
115416abf4fSPavel Skripkin reg = (reg & mask) >> shift;
116416abf4fSPavel Skripkin
117416abf4fSPavel Skripkin return reg;
118d5dd29e4SJosef Filzmaier }
119d5dd29e4SJosef Filzmaier
atusb_get_and_clear_error(struct atusb * atusb)1207490b008SAlexander Aring static int atusb_get_and_clear_error(struct atusb *atusb)
1217490b008SAlexander Aring {
1227490b008SAlexander Aring int err = atusb->err;
1237490b008SAlexander Aring
1247490b008SAlexander Aring atusb->err = 0;
1257490b008SAlexander Aring return err;
1267490b008SAlexander Aring }
1277490b008SAlexander Aring
1287490b008SAlexander Aring /* ----- skb allocation ---------------------------------------------------- */
1297490b008SAlexander Aring
1307490b008SAlexander Aring #define MAX_PSDU 127
1317490b008SAlexander Aring #define MAX_RX_XFER (1 + MAX_PSDU + 2 + 1) /* PHR+PSDU+CRC+LQI */
1327490b008SAlexander Aring
1337490b008SAlexander Aring #define SKB_ATUSB(skb) (*(struct atusb **)(skb)->cb)
1347490b008SAlexander Aring
1357490b008SAlexander Aring static void atusb_in(struct urb *urb);
1367490b008SAlexander Aring
atusb_submit_rx_urb(struct atusb * atusb,struct urb * urb)1377490b008SAlexander Aring static int atusb_submit_rx_urb(struct atusb *atusb, struct urb *urb)
1387490b008SAlexander Aring {
1397490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
1407490b008SAlexander Aring struct sk_buff *skb = urb->context;
1417490b008SAlexander Aring int ret;
1427490b008SAlexander Aring
1437490b008SAlexander Aring if (!skb) {
1447490b008SAlexander Aring skb = alloc_skb(MAX_RX_XFER, GFP_KERNEL);
1457490b008SAlexander Aring if (!skb) {
1467490b008SAlexander Aring dev_warn_ratelimited(&usb_dev->dev,
1477490b008SAlexander Aring "atusb_in: can't allocate skb\n");
1487490b008SAlexander Aring return -ENOMEM;
1497490b008SAlexander Aring }
1507490b008SAlexander Aring skb_put(skb, MAX_RX_XFER);
1517490b008SAlexander Aring SKB_ATUSB(skb) = atusb;
1527490b008SAlexander Aring }
1537490b008SAlexander Aring
1547490b008SAlexander Aring usb_fill_bulk_urb(urb, usb_dev, usb_rcvbulkpipe(usb_dev, 1),
1557490b008SAlexander Aring skb->data, MAX_RX_XFER, atusb_in, skb);
1567490b008SAlexander Aring usb_anchor_urb(urb, &atusb->rx_urbs);
1577490b008SAlexander Aring
1587490b008SAlexander Aring ret = usb_submit_urb(urb, GFP_KERNEL);
1597490b008SAlexander Aring if (ret) {
1607490b008SAlexander Aring usb_unanchor_urb(urb);
1617490b008SAlexander Aring kfree_skb(skb);
1627490b008SAlexander Aring urb->context = NULL;
1637490b008SAlexander Aring }
1647490b008SAlexander Aring return ret;
1657490b008SAlexander Aring }
1667490b008SAlexander Aring
atusb_work_urbs(struct work_struct * work)1677490b008SAlexander Aring static void atusb_work_urbs(struct work_struct *work)
1687490b008SAlexander Aring {
1697490b008SAlexander Aring struct atusb *atusb =
1707490b008SAlexander Aring container_of(to_delayed_work(work), struct atusb, work);
1717490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
1727490b008SAlexander Aring struct urb *urb;
1737490b008SAlexander Aring int ret;
1747490b008SAlexander Aring
1757490b008SAlexander Aring if (atusb->shutdown)
1767490b008SAlexander Aring return;
1777490b008SAlexander Aring
1787490b008SAlexander Aring do {
1797490b008SAlexander Aring urb = usb_get_from_anchor(&atusb->idle_urbs);
1807490b008SAlexander Aring if (!urb)
1817490b008SAlexander Aring return;
1827490b008SAlexander Aring ret = atusb_submit_rx_urb(atusb, urb);
1837490b008SAlexander Aring } while (!ret);
1847490b008SAlexander Aring
1857490b008SAlexander Aring usb_anchor_urb(urb, &atusb->idle_urbs);
1867490b008SAlexander Aring dev_warn_ratelimited(&usb_dev->dev,
1877490b008SAlexander Aring "atusb_in: can't allocate/submit URB (%d)\n", ret);
1887490b008SAlexander Aring schedule_delayed_work(&atusb->work,
1897490b008SAlexander Aring msecs_to_jiffies(ATUSB_ALLOC_DELAY_MS) + 1);
1907490b008SAlexander Aring }
1917490b008SAlexander Aring
1927490b008SAlexander Aring /* ----- Asynchronous USB -------------------------------------------------- */
1937490b008SAlexander Aring
atusb_tx_done(struct atusb * atusb,u8 seq,int reason)194*f8be91fbSAlexander Aring static void atusb_tx_done(struct atusb *atusb, u8 seq, int reason)
1957490b008SAlexander Aring {
1967490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
197909dcf9bSStefan Schmidt u8 expect = atusb->tx_ack_seq;
1987490b008SAlexander Aring
1995f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s (0x%02x/0x%02x)\n", __func__, seq, expect);
2007490b008SAlexander Aring if (seq == expect) {
2017490b008SAlexander Aring /* TODO check for ifs handling in firmware */
202*f8be91fbSAlexander Aring if (reason == IEEE802154_SUCCESS)
2037490b008SAlexander Aring ieee802154_xmit_complete(atusb->hw, atusb->tx_skb, false);
204*f8be91fbSAlexander Aring else
205*f8be91fbSAlexander Aring ieee802154_xmit_error(atusb->hw, atusb->tx_skb, reason);
2067490b008SAlexander Aring } else {
2077490b008SAlexander Aring /* TODO I experience this case when atusb has a tx complete
2087490b008SAlexander Aring * irq before probing, we should fix the firmware it's an
2097490b008SAlexander Aring * unlikely case now that seq == expect is then true, but can
2107490b008SAlexander Aring * happen and fail with a tx_skb = NULL;
2117490b008SAlexander Aring */
21235f34ee1SMiquel Raynal ieee802154_xmit_hw_error(atusb->hw, atusb->tx_skb);
2137490b008SAlexander Aring }
2147490b008SAlexander Aring }
2157490b008SAlexander Aring
atusb_in_good(struct urb * urb)2167490b008SAlexander Aring static void atusb_in_good(struct urb *urb)
2177490b008SAlexander Aring {
2187490b008SAlexander Aring struct usb_device *usb_dev = urb->dev;
2197490b008SAlexander Aring struct sk_buff *skb = urb->context;
2207490b008SAlexander Aring struct atusb *atusb = SKB_ATUSB(skb);
221*f8be91fbSAlexander Aring int result = IEEE802154_SUCCESS;
222*f8be91fbSAlexander Aring u8 len, lqi, trac;
2237490b008SAlexander Aring
2247490b008SAlexander Aring if (!urb->actual_length) {
2257490b008SAlexander Aring dev_dbg(&usb_dev->dev, "atusb_in: zero-sized URB ?\n");
2267490b008SAlexander Aring return;
2277490b008SAlexander Aring }
2287490b008SAlexander Aring
2297490b008SAlexander Aring len = *skb->data;
2307490b008SAlexander Aring
231*f8be91fbSAlexander Aring switch (urb->actual_length) {
232*f8be91fbSAlexander Aring case 2:
233*f8be91fbSAlexander Aring trac = TRAC_MASK(*(skb->data + 1));
234*f8be91fbSAlexander Aring switch (trac) {
235*f8be91fbSAlexander Aring case TRAC_SUCCESS:
236*f8be91fbSAlexander Aring case TRAC_SUCCESS_DATA_PENDING:
237*f8be91fbSAlexander Aring /* already IEEE802154_SUCCESS */
238*f8be91fbSAlexander Aring break;
239*f8be91fbSAlexander Aring case TRAC_CHANNEL_ACCESS_FAILURE:
240*f8be91fbSAlexander Aring result = IEEE802154_CHANNEL_ACCESS_FAILURE;
241*f8be91fbSAlexander Aring break;
242*f8be91fbSAlexander Aring case TRAC_NO_ACK:
243*f8be91fbSAlexander Aring result = IEEE802154_NO_ACK;
244*f8be91fbSAlexander Aring break;
245*f8be91fbSAlexander Aring default:
246*f8be91fbSAlexander Aring result = IEEE802154_SYSTEM_ERROR;
247*f8be91fbSAlexander Aring }
248*f8be91fbSAlexander Aring
249*f8be91fbSAlexander Aring fallthrough;
250*f8be91fbSAlexander Aring case 1:
251*f8be91fbSAlexander Aring atusb_tx_done(atusb, len, result);
2527490b008SAlexander Aring return;
2537490b008SAlexander Aring }
2547490b008SAlexander Aring
2557490b008SAlexander Aring if (len + 1 > urb->actual_length - 1) {
2567490b008SAlexander Aring dev_dbg(&usb_dev->dev, "atusb_in: frame len %d+1 > URB %u-1\n",
2577490b008SAlexander Aring len, urb->actual_length);
2587490b008SAlexander Aring return;
2597490b008SAlexander Aring }
2607490b008SAlexander Aring
2617490b008SAlexander Aring if (!ieee802154_is_valid_psdu_len(len)) {
2627490b008SAlexander Aring dev_dbg(&usb_dev->dev, "atusb_in: frame corrupted\n");
2637490b008SAlexander Aring return;
2647490b008SAlexander Aring }
2657490b008SAlexander Aring
2667490b008SAlexander Aring lqi = skb->data[len + 1];
2677490b008SAlexander Aring dev_dbg(&usb_dev->dev, "atusb_in: rx len %d lqi 0x%02x\n", len, lqi);
2687490b008SAlexander Aring skb_pull(skb, 1); /* remove PHR */
2697490b008SAlexander Aring skb_trim(skb, len); /* get payload only */
2707490b008SAlexander Aring ieee802154_rx_irqsafe(atusb->hw, skb, lqi);
2717490b008SAlexander Aring urb->context = NULL; /* skb is gone */
2727490b008SAlexander Aring }
2737490b008SAlexander Aring
atusb_in(struct urb * urb)2747490b008SAlexander Aring static void atusb_in(struct urb *urb)
2757490b008SAlexander Aring {
2767490b008SAlexander Aring struct usb_device *usb_dev = urb->dev;
2777490b008SAlexander Aring struct sk_buff *skb = urb->context;
2787490b008SAlexander Aring struct atusb *atusb = SKB_ATUSB(skb);
2797490b008SAlexander Aring
2805f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s: status %d len %d\n", __func__,
2817490b008SAlexander Aring urb->status, urb->actual_length);
2827490b008SAlexander Aring if (urb->status) {
2837490b008SAlexander Aring if (urb->status == -ENOENT) { /* being killed */
2847490b008SAlexander Aring kfree_skb(skb);
2857490b008SAlexander Aring urb->context = NULL;
2867490b008SAlexander Aring return;
2877490b008SAlexander Aring }
2885f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s: URB error %d\n", __func__, urb->status);
2897490b008SAlexander Aring } else {
2907490b008SAlexander Aring atusb_in_good(urb);
2917490b008SAlexander Aring }
2927490b008SAlexander Aring
2937490b008SAlexander Aring usb_anchor_urb(urb, &atusb->idle_urbs);
2947490b008SAlexander Aring if (!atusb->shutdown)
2957490b008SAlexander Aring schedule_delayed_work(&atusb->work, 0);
2967490b008SAlexander Aring }
2977490b008SAlexander Aring
2987490b008SAlexander Aring /* ----- URB allocation/deallocation --------------------------------------- */
2997490b008SAlexander Aring
atusb_free_urbs(struct atusb * atusb)3007490b008SAlexander Aring static void atusb_free_urbs(struct atusb *atusb)
3017490b008SAlexander Aring {
3027490b008SAlexander Aring struct urb *urb;
3037490b008SAlexander Aring
3047490b008SAlexander Aring while (1) {
3057490b008SAlexander Aring urb = usb_get_from_anchor(&atusb->idle_urbs);
3067490b008SAlexander Aring if (!urb)
3077490b008SAlexander Aring break;
3087490b008SAlexander Aring kfree_skb(urb->context);
3097490b008SAlexander Aring usb_free_urb(urb);
3107490b008SAlexander Aring }
3117490b008SAlexander Aring }
3127490b008SAlexander Aring
atusb_alloc_urbs(struct atusb * atusb,int n)3137490b008SAlexander Aring static int atusb_alloc_urbs(struct atusb *atusb, int n)
3147490b008SAlexander Aring {
3157490b008SAlexander Aring struct urb *urb;
3167490b008SAlexander Aring
3177490b008SAlexander Aring while (n) {
3187490b008SAlexander Aring urb = usb_alloc_urb(0, GFP_KERNEL);
3197490b008SAlexander Aring if (!urb) {
3207490b008SAlexander Aring atusb_free_urbs(atusb);
3217490b008SAlexander Aring return -ENOMEM;
3227490b008SAlexander Aring }
3237490b008SAlexander Aring usb_anchor_urb(urb, &atusb->idle_urbs);
3246b9fbe16SPavel Skripkin usb_free_urb(urb);
3257490b008SAlexander Aring n--;
3267490b008SAlexander Aring }
3277490b008SAlexander Aring return 0;
3287490b008SAlexander Aring }
3297490b008SAlexander Aring
3307490b008SAlexander Aring /* ----- IEEE 802.15.4 interface operations -------------------------------- */
3317490b008SAlexander Aring
atusb_xmit_complete(struct urb * urb)3327490b008SAlexander Aring static void atusb_xmit_complete(struct urb *urb)
3337490b008SAlexander Aring {
3347490b008SAlexander Aring dev_dbg(&urb->dev->dev, "atusb_xmit urb completed");
3357490b008SAlexander Aring }
3367490b008SAlexander Aring
atusb_xmit(struct ieee802154_hw * hw,struct sk_buff * skb)3377490b008SAlexander Aring static int atusb_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
3387490b008SAlexander Aring {
3397490b008SAlexander Aring struct atusb *atusb = hw->priv;
3407490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
3417490b008SAlexander Aring int ret;
3427490b008SAlexander Aring
3435f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s (%d)\n", __func__, skb->len);
3447490b008SAlexander Aring atusb->tx_skb = skb;
3457490b008SAlexander Aring atusb->tx_ack_seq++;
3467490b008SAlexander Aring atusb->tx_dr.wIndex = cpu_to_le16(atusb->tx_ack_seq);
3477490b008SAlexander Aring atusb->tx_dr.wLength = cpu_to_le16(skb->len);
3487490b008SAlexander Aring
3497490b008SAlexander Aring usb_fill_control_urb(atusb->tx_urb, usb_dev,
3507490b008SAlexander Aring usb_sndctrlpipe(usb_dev, 0),
3517490b008SAlexander Aring (unsigned char *)&atusb->tx_dr, skb->data,
3527490b008SAlexander Aring skb->len, atusb_xmit_complete, NULL);
3537490b008SAlexander Aring ret = usb_submit_urb(atusb->tx_urb, GFP_ATOMIC);
3545f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s done (%d)\n", __func__, ret);
3557490b008SAlexander Aring return ret;
3567490b008SAlexander Aring }
3577490b008SAlexander Aring
atusb_ed(struct ieee802154_hw * hw,u8 * level)3587490b008SAlexander Aring static int atusb_ed(struct ieee802154_hw *hw, u8 *level)
3597490b008SAlexander Aring {
360bd910a96SStefan Schmidt WARN_ON(!level);
3612d8cbd31SStefan Schmidt *level = 0xbe;
3627490b008SAlexander Aring return 0;
3637490b008SAlexander Aring }
3647490b008SAlexander Aring
atusb_set_hw_addr_filt(struct ieee802154_hw * hw,struct ieee802154_hw_addr_filt * filt,unsigned long changed)3657490b008SAlexander Aring static int atusb_set_hw_addr_filt(struct ieee802154_hw *hw,
3667490b008SAlexander Aring struct ieee802154_hw_addr_filt *filt,
3677490b008SAlexander Aring unsigned long changed)
3687490b008SAlexander Aring {
3697490b008SAlexander Aring struct atusb *atusb = hw->priv;
3707490b008SAlexander Aring struct device *dev = &atusb->usb_dev->dev;
3717490b008SAlexander Aring
3727490b008SAlexander Aring if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
3737490b008SAlexander Aring u16 addr = le16_to_cpu(filt->short_addr);
3747490b008SAlexander Aring
3755f0cbf4eSStefan Schmidt dev_vdbg(dev, "%s called for saddr\n", __func__);
376416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
377416abf4fSPavel Skripkin addr, RG_SHORT_ADDR_0, NULL, 0, 1000, GFP_KERNEL);
378416abf4fSPavel Skripkin
379416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
380416abf4fSPavel Skripkin addr >> 8, RG_SHORT_ADDR_1, NULL, 0, 1000, GFP_KERNEL);
3817490b008SAlexander Aring }
3827490b008SAlexander Aring
3837490b008SAlexander Aring if (changed & IEEE802154_AFILT_PANID_CHANGED) {
3847490b008SAlexander Aring u16 pan = le16_to_cpu(filt->pan_id);
3857490b008SAlexander Aring
3865f0cbf4eSStefan Schmidt dev_vdbg(dev, "%s called for pan id\n", __func__);
387416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
388416abf4fSPavel Skripkin pan, RG_PAN_ID_0, NULL, 0, 1000, GFP_KERNEL);
389416abf4fSPavel Skripkin
390416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
391416abf4fSPavel Skripkin pan >> 8, RG_PAN_ID_1, NULL, 0, 1000, GFP_KERNEL);
3927490b008SAlexander Aring }
3937490b008SAlexander Aring
3947490b008SAlexander Aring if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
3957490b008SAlexander Aring u8 i, addr[IEEE802154_EXTENDED_ADDR_LEN];
3967490b008SAlexander Aring
3977490b008SAlexander Aring memcpy(addr, &filt->ieee_addr, IEEE802154_EXTENDED_ADDR_LEN);
3985f0cbf4eSStefan Schmidt dev_vdbg(dev, "%s called for IEEE addr\n", __func__);
3997490b008SAlexander Aring for (i = 0; i < 8; i++)
400416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
401416abf4fSPavel Skripkin addr[i], RG_IEEE_ADDR_0 + i, NULL, 0,
402416abf4fSPavel Skripkin 1000, GFP_KERNEL);
4037490b008SAlexander Aring }
4047490b008SAlexander Aring
4057490b008SAlexander Aring if (changed & IEEE802154_AFILT_PANC_CHANGED) {
4065f0cbf4eSStefan Schmidt dev_vdbg(dev, "%s called for panc change\n", __func__);
4077490b008SAlexander Aring if (filt->pan_coord)
408bdc78737SStefan Schmidt atusb_write_subreg(atusb, SR_AACK_I_AM_COORD, 1);
4097490b008SAlexander Aring else
410bdc78737SStefan Schmidt atusb_write_subreg(atusb, SR_AACK_I_AM_COORD, 0);
4117490b008SAlexander Aring }
4127490b008SAlexander Aring
4137490b008SAlexander Aring return atusb_get_and_clear_error(atusb);
4147490b008SAlexander Aring }
4157490b008SAlexander Aring
atusb_start(struct ieee802154_hw * hw)4167490b008SAlexander Aring static int atusb_start(struct ieee802154_hw *hw)
4177490b008SAlexander Aring {
4187490b008SAlexander Aring struct atusb *atusb = hw->priv;
4197490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
4207490b008SAlexander Aring int ret;
4217490b008SAlexander Aring
4225f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s\n", __func__);
4237490b008SAlexander Aring schedule_delayed_work(&atusb->work, 0);
424416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RX_MODE, ATUSB_REQ_TO_DEV, 1, 0,
425416abf4fSPavel Skripkin NULL, 0, 1000, GFP_KERNEL);
4267490b008SAlexander Aring ret = atusb_get_and_clear_error(atusb);
4277490b008SAlexander Aring if (ret < 0)
4287490b008SAlexander Aring usb_kill_anchored_urbs(&atusb->idle_urbs);
4297490b008SAlexander Aring return ret;
4307490b008SAlexander Aring }
4317490b008SAlexander Aring
atusb_stop(struct ieee802154_hw * hw)4327490b008SAlexander Aring static void atusb_stop(struct ieee802154_hw *hw)
4337490b008SAlexander Aring {
4347490b008SAlexander Aring struct atusb *atusb = hw->priv;
4357490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
4367490b008SAlexander Aring
4375f0cbf4eSStefan Schmidt dev_dbg(&usb_dev->dev, "%s\n", __func__);
4387490b008SAlexander Aring usb_kill_anchored_urbs(&atusb->idle_urbs);
439416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RX_MODE, ATUSB_REQ_TO_DEV, 0, 0,
440416abf4fSPavel Skripkin NULL, 0, 1000, GFP_KERNEL);
4417490b008SAlexander Aring atusb_get_and_clear_error(atusb);
4427490b008SAlexander Aring }
4437490b008SAlexander Aring
4448702cb0fSStefan Schmidt #define ATUSB_MAX_TX_POWERS 0xF
4458702cb0fSStefan Schmidt static const s32 atusb_powers[ATUSB_MAX_TX_POWERS + 1] = {
4468702cb0fSStefan Schmidt 300, 280, 230, 180, 130, 70, 0, -100, -200, -300, -400, -500, -700,
4478702cb0fSStefan Schmidt -900, -1200, -1700,
4488702cb0fSStefan Schmidt };
4498702cb0fSStefan Schmidt
4508702cb0fSStefan Schmidt static int
atusb_txpower(struct ieee802154_hw * hw,s32 mbm)451d5dd29e4SJosef Filzmaier atusb_txpower(struct ieee802154_hw *hw, s32 mbm)
452d5dd29e4SJosef Filzmaier {
453d5dd29e4SJosef Filzmaier struct atusb *atusb = hw->priv;
454d5dd29e4SJosef Filzmaier
455d5dd29e4SJosef Filzmaier if (atusb->data)
456d5dd29e4SJosef Filzmaier return atusb->data->set_txpower(hw, mbm);
457d5dd29e4SJosef Filzmaier else
458d5dd29e4SJosef Filzmaier return -ENOTSUPP;
459d5dd29e4SJosef Filzmaier }
460d5dd29e4SJosef Filzmaier
461d5dd29e4SJosef Filzmaier static int
atusb_set_txpower(struct ieee802154_hw * hw,s32 mbm)4628702cb0fSStefan Schmidt atusb_set_txpower(struct ieee802154_hw *hw, s32 mbm)
4638702cb0fSStefan Schmidt {
4648702cb0fSStefan Schmidt struct atusb *atusb = hw->priv;
4658702cb0fSStefan Schmidt u32 i;
4668702cb0fSStefan Schmidt
4678702cb0fSStefan Schmidt for (i = 0; i < hw->phy->supported.tx_powers_size; i++) {
4688702cb0fSStefan Schmidt if (hw->phy->supported.tx_powers[i] == mbm)
4698702cb0fSStefan Schmidt return atusb_write_subreg(atusb, SR_TX_PWR_23X, i);
4708702cb0fSStefan Schmidt }
4718702cb0fSStefan Schmidt
4728702cb0fSStefan Schmidt return -EINVAL;
4738702cb0fSStefan Schmidt }
4748702cb0fSStefan Schmidt
475d5dd29e4SJosef Filzmaier static int
hulusb_set_txpower(struct ieee802154_hw * hw,s32 mbm)476d5dd29e4SJosef Filzmaier hulusb_set_txpower(struct ieee802154_hw *hw, s32 mbm)
477d5dd29e4SJosef Filzmaier {
478d5dd29e4SJosef Filzmaier u32 i;
479d5dd29e4SJosef Filzmaier
480d5dd29e4SJosef Filzmaier for (i = 0; i < hw->phy->supported.tx_powers_size; i++) {
481d5dd29e4SJosef Filzmaier if (hw->phy->supported.tx_powers[i] == mbm)
482d5dd29e4SJosef Filzmaier return atusb_write_subreg(hw->priv, SR_TX_PWR_212, i);
483d5dd29e4SJosef Filzmaier }
484d5dd29e4SJosef Filzmaier
485d5dd29e4SJosef Filzmaier return -EINVAL;
486d5dd29e4SJosef Filzmaier }
487d5dd29e4SJosef Filzmaier
4880f4715c8SStefan Schmidt #define ATUSB_MAX_ED_LEVELS 0xF
4890f4715c8SStefan Schmidt static const s32 atusb_ed_levels[ATUSB_MAX_ED_LEVELS + 1] = {
4900f4715c8SStefan Schmidt -9100, -8900, -8700, -8500, -8300, -8100, -7900, -7700, -7500, -7300,
4910f4715c8SStefan Schmidt -7100, -6900, -6700, -6500, -6300, -6100,
4920f4715c8SStefan Schmidt };
4930f4715c8SStefan Schmidt
494d5dd29e4SJosef Filzmaier #define AT86RF212_MAX_TX_POWERS 0x1F
495d5dd29e4SJosef Filzmaier static const s32 at86rf212_powers[AT86RF212_MAX_TX_POWERS + 1] = {
496d5dd29e4SJosef Filzmaier 500, 400, 300, 200, 100, 0, -100, -200, -300, -400, -500, -600, -700,
497d5dd29e4SJosef Filzmaier -800, -900, -1000, -1100, -1200, -1300, -1400, -1500, -1600, -1700,
498d5dd29e4SJosef Filzmaier -1800, -1900, -2000, -2100, -2200, -2300, -2400, -2500, -2600,
499d5dd29e4SJosef Filzmaier };
500d5dd29e4SJosef Filzmaier
501d5dd29e4SJosef Filzmaier #define AT86RF2XX_MAX_ED_LEVELS 0xF
502d5dd29e4SJosef Filzmaier static const s32 at86rf212_ed_levels_100[AT86RF2XX_MAX_ED_LEVELS + 1] = {
503d5dd29e4SJosef Filzmaier -10000, -9800, -9600, -9400, -9200, -9000, -8800, -8600, -8400, -8200,
504d5dd29e4SJosef Filzmaier -8000, -7800, -7600, -7400, -7200, -7000,
505d5dd29e4SJosef Filzmaier };
506d5dd29e4SJosef Filzmaier
507d5dd29e4SJosef Filzmaier static const s32 at86rf212_ed_levels_98[AT86RF2XX_MAX_ED_LEVELS + 1] = {
508d5dd29e4SJosef Filzmaier -9800, -9600, -9400, -9200, -9000, -8800, -8600, -8400, -8200, -8000,
509d5dd29e4SJosef Filzmaier -7800, -7600, -7400, -7200, -7000, -6800,
510d5dd29e4SJosef Filzmaier };
511d5dd29e4SJosef Filzmaier
5120f4715c8SStefan Schmidt static int
atusb_set_cca_mode(struct ieee802154_hw * hw,const struct wpan_phy_cca * cca)513308dbb7aSStefan Schmidt atusb_set_cca_mode(struct ieee802154_hw *hw, const struct wpan_phy_cca *cca)
514308dbb7aSStefan Schmidt {
515308dbb7aSStefan Schmidt struct atusb *atusb = hw->priv;
516308dbb7aSStefan Schmidt u8 val;
517308dbb7aSStefan Schmidt
518308dbb7aSStefan Schmidt /* mapping 802.15.4 to driver spec */
519308dbb7aSStefan Schmidt switch (cca->mode) {
520308dbb7aSStefan Schmidt case NL802154_CCA_ENERGY:
521308dbb7aSStefan Schmidt val = 1;
522308dbb7aSStefan Schmidt break;
523308dbb7aSStefan Schmidt case NL802154_CCA_CARRIER:
524308dbb7aSStefan Schmidt val = 2;
525308dbb7aSStefan Schmidt break;
526308dbb7aSStefan Schmidt case NL802154_CCA_ENERGY_CARRIER:
527308dbb7aSStefan Schmidt switch (cca->opt) {
528308dbb7aSStefan Schmidt case NL802154_CCA_OPT_ENERGY_CARRIER_AND:
529308dbb7aSStefan Schmidt val = 3;
530308dbb7aSStefan Schmidt break;
531308dbb7aSStefan Schmidt case NL802154_CCA_OPT_ENERGY_CARRIER_OR:
532308dbb7aSStefan Schmidt val = 0;
533308dbb7aSStefan Schmidt break;
534308dbb7aSStefan Schmidt default:
535308dbb7aSStefan Schmidt return -EINVAL;
536308dbb7aSStefan Schmidt }
537308dbb7aSStefan Schmidt break;
538308dbb7aSStefan Schmidt default:
539308dbb7aSStefan Schmidt return -EINVAL;
540308dbb7aSStefan Schmidt }
541308dbb7aSStefan Schmidt
542308dbb7aSStefan Schmidt return atusb_write_subreg(atusb, SR_CCA_MODE, val);
543308dbb7aSStefan Schmidt }
544308dbb7aSStefan Schmidt
hulusb_set_cca_ed_level(struct atusb * lp,int rssi_base_val)545d5dd29e4SJosef Filzmaier static int hulusb_set_cca_ed_level(struct atusb *lp, int rssi_base_val)
546d5dd29e4SJosef Filzmaier {
547416abf4fSPavel Skripkin int cca_ed_thres;
548d5dd29e4SJosef Filzmaier
549d5dd29e4SJosef Filzmaier cca_ed_thres = atusb_read_subreg(lp, SR_CCA_ED_THRES);
550416abf4fSPavel Skripkin if (cca_ed_thres < 0)
551416abf4fSPavel Skripkin return cca_ed_thres;
552d5dd29e4SJosef Filzmaier
553d5dd29e4SJosef Filzmaier switch (rssi_base_val) {
554d5dd29e4SJosef Filzmaier case -98:
555d5dd29e4SJosef Filzmaier lp->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_98;
556d5dd29e4SJosef Filzmaier lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_98);
557d5dd29e4SJosef Filzmaier lp->hw->phy->cca_ed_level = at86rf212_ed_levels_98[cca_ed_thres];
558d5dd29e4SJosef Filzmaier break;
559d5dd29e4SJosef Filzmaier case -100:
560d5dd29e4SJosef Filzmaier lp->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_100;
561d5dd29e4SJosef Filzmaier lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_100);
562d5dd29e4SJosef Filzmaier lp->hw->phy->cca_ed_level = at86rf212_ed_levels_100[cca_ed_thres];
563d5dd29e4SJosef Filzmaier break;
564d5dd29e4SJosef Filzmaier default:
565d5dd29e4SJosef Filzmaier WARN_ON(1);
566d5dd29e4SJosef Filzmaier }
567d5dd29e4SJosef Filzmaier
568d5dd29e4SJosef Filzmaier return 0;
569d5dd29e4SJosef Filzmaier }
570d5dd29e4SJosef Filzmaier
571308dbb7aSStefan Schmidt static int
atusb_set_cca_ed_level(struct ieee802154_hw * hw,s32 mbm)5720f4715c8SStefan Schmidt atusb_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
5730f4715c8SStefan Schmidt {
5740f4715c8SStefan Schmidt struct atusb *atusb = hw->priv;
5750f4715c8SStefan Schmidt u32 i;
5760f4715c8SStefan Schmidt
5770f4715c8SStefan Schmidt for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) {
5780f4715c8SStefan Schmidt if (hw->phy->supported.cca_ed_levels[i] == mbm)
5790f4715c8SStefan Schmidt return atusb_write_subreg(atusb, SR_CCA_ED_THRES, i);
5800f4715c8SStefan Schmidt }
5810f4715c8SStefan Schmidt
5820f4715c8SStefan Schmidt return -EINVAL;
5830f4715c8SStefan Schmidt }
5840f4715c8SStefan Schmidt
atusb_channel(struct ieee802154_hw * hw,u8 page,u8 channel)585d5dd29e4SJosef Filzmaier static int atusb_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
586d5dd29e4SJosef Filzmaier {
587d5dd29e4SJosef Filzmaier struct atusb *atusb = hw->priv;
588d5dd29e4SJosef Filzmaier int ret = -ENOTSUPP;
589d5dd29e4SJosef Filzmaier
590d5dd29e4SJosef Filzmaier if (atusb->data) {
591d5dd29e4SJosef Filzmaier ret = atusb->data->set_channel(hw, page, channel);
592d5dd29e4SJosef Filzmaier /* @@@ ugly synchronization */
593d5dd29e4SJosef Filzmaier msleep(atusb->data->t_channel_switch);
594d5dd29e4SJosef Filzmaier }
595d5dd29e4SJosef Filzmaier
596d5dd29e4SJosef Filzmaier return ret;
597d5dd29e4SJosef Filzmaier }
598d5dd29e4SJosef Filzmaier
atusb_set_channel(struct ieee802154_hw * hw,u8 page,u8 channel)599d5dd29e4SJosef Filzmaier static int atusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
600d5dd29e4SJosef Filzmaier {
601d5dd29e4SJosef Filzmaier struct atusb *atusb = hw->priv;
602d5dd29e4SJosef Filzmaier int ret;
603d5dd29e4SJosef Filzmaier
604d5dd29e4SJosef Filzmaier ret = atusb_write_subreg(atusb, SR_CHANNEL, channel);
605d5dd29e4SJosef Filzmaier if (ret < 0)
606d5dd29e4SJosef Filzmaier return ret;
607d5dd29e4SJosef Filzmaier return 0;
608d5dd29e4SJosef Filzmaier }
609d5dd29e4SJosef Filzmaier
hulusb_set_channel(struct ieee802154_hw * hw,u8 page,u8 channel)610d5dd29e4SJosef Filzmaier static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
611d5dd29e4SJosef Filzmaier {
612d5dd29e4SJosef Filzmaier int rc;
613d5dd29e4SJosef Filzmaier int rssi_base_val;
614d5dd29e4SJosef Filzmaier
615d5dd29e4SJosef Filzmaier struct atusb *lp = hw->priv;
616d5dd29e4SJosef Filzmaier
617d5dd29e4SJosef Filzmaier if (channel == 0)
618d5dd29e4SJosef Filzmaier rc = atusb_write_subreg(lp, SR_SUB_MODE, 0);
619d5dd29e4SJosef Filzmaier else
620d5dd29e4SJosef Filzmaier rc = atusb_write_subreg(lp, SR_SUB_MODE, 1);
621d5dd29e4SJosef Filzmaier if (rc < 0)
622d5dd29e4SJosef Filzmaier return rc;
623d5dd29e4SJosef Filzmaier
624d5dd29e4SJosef Filzmaier if (page == 0) {
625d5dd29e4SJosef Filzmaier rc = atusb_write_subreg(lp, SR_BPSK_QPSK, 0);
626d5dd29e4SJosef Filzmaier rssi_base_val = -100;
627d5dd29e4SJosef Filzmaier } else {
628d5dd29e4SJosef Filzmaier rc = atusb_write_subreg(lp, SR_BPSK_QPSK, 1);
629d5dd29e4SJosef Filzmaier rssi_base_val = -98;
630d5dd29e4SJosef Filzmaier }
631d5dd29e4SJosef Filzmaier if (rc < 0)
632d5dd29e4SJosef Filzmaier return rc;
633d5dd29e4SJosef Filzmaier
634d5dd29e4SJosef Filzmaier rc = hulusb_set_cca_ed_level(lp, rssi_base_val);
635d5dd29e4SJosef Filzmaier if (rc < 0)
636d5dd29e4SJosef Filzmaier return rc;
637d5dd29e4SJosef Filzmaier
638d5dd29e4SJosef Filzmaier return atusb_write_subreg(lp, SR_CHANNEL, channel);
639d5dd29e4SJosef Filzmaier }
640d5dd29e4SJosef Filzmaier
641c61c9bd8SStefan Schmidt static int
atusb_set_csma_params(struct ieee802154_hw * hw,u8 min_be,u8 max_be,u8 retries)642fb7c579aSStefan Schmidt atusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be, u8 retries)
643fb7c579aSStefan Schmidt {
644fb7c579aSStefan Schmidt struct atusb *atusb = hw->priv;
645fb7c579aSStefan Schmidt int ret;
646fb7c579aSStefan Schmidt
647fb7c579aSStefan Schmidt ret = atusb_write_subreg(atusb, SR_MIN_BE, min_be);
648fb7c579aSStefan Schmidt if (ret)
649fb7c579aSStefan Schmidt return ret;
650fb7c579aSStefan Schmidt
651fb7c579aSStefan Schmidt ret = atusb_write_subreg(atusb, SR_MAX_BE, max_be);
652fb7c579aSStefan Schmidt if (ret)
653fb7c579aSStefan Schmidt return ret;
654fb7c579aSStefan Schmidt
655fb7c579aSStefan Schmidt return atusb_write_subreg(atusb, SR_MAX_CSMA_RETRIES, retries);
656fb7c579aSStefan Schmidt }
657fb7c579aSStefan Schmidt
658fb7c579aSStefan Schmidt static int
hulusb_set_lbt(struct ieee802154_hw * hw,bool on)659d5dd29e4SJosef Filzmaier hulusb_set_lbt(struct ieee802154_hw *hw, bool on)
660d5dd29e4SJosef Filzmaier {
661d5dd29e4SJosef Filzmaier struct atusb *atusb = hw->priv;
662d5dd29e4SJosef Filzmaier
663d5dd29e4SJosef Filzmaier return atusb_write_subreg(atusb, SR_CSMA_LBT_MODE, on);
664d5dd29e4SJosef Filzmaier }
665d5dd29e4SJosef Filzmaier
666d5dd29e4SJosef Filzmaier static int
atusb_set_frame_retries(struct ieee802154_hw * hw,s8 retries)6675d82288bSStefan Schmidt atusb_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
6685d82288bSStefan Schmidt {
6695d82288bSStefan Schmidt struct atusb *atusb = hw->priv;
6705d82288bSStefan Schmidt
6715d82288bSStefan Schmidt return atusb_write_subreg(atusb, SR_MAX_FRAME_RETRIES, retries);
6725d82288bSStefan Schmidt }
6735d82288bSStefan Schmidt
6745d82288bSStefan Schmidt static int
atusb_set_promiscuous_mode(struct ieee802154_hw * hw,const bool on)675c61c9bd8SStefan Schmidt atusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
676c61c9bd8SStefan Schmidt {
677c61c9bd8SStefan Schmidt struct atusb *atusb = hw->priv;
678c61c9bd8SStefan Schmidt int ret;
679c61c9bd8SStefan Schmidt
680c61c9bd8SStefan Schmidt if (on) {
681c61c9bd8SStefan Schmidt ret = atusb_write_subreg(atusb, SR_AACK_DIS_ACK, 1);
682c61c9bd8SStefan Schmidt if (ret < 0)
683c61c9bd8SStefan Schmidt return ret;
684c61c9bd8SStefan Schmidt
685c61c9bd8SStefan Schmidt ret = atusb_write_subreg(atusb, SR_AACK_PROM_MODE, 1);
686c61c9bd8SStefan Schmidt if (ret < 0)
687c61c9bd8SStefan Schmidt return ret;
688c61c9bd8SStefan Schmidt } else {
689c61c9bd8SStefan Schmidt ret = atusb_write_subreg(atusb, SR_AACK_PROM_MODE, 0);
690c61c9bd8SStefan Schmidt if (ret < 0)
691c61c9bd8SStefan Schmidt return ret;
692c61c9bd8SStefan Schmidt
693c61c9bd8SStefan Schmidt ret = atusb_write_subreg(atusb, SR_AACK_DIS_ACK, 0);
694c61c9bd8SStefan Schmidt if (ret < 0)
695c61c9bd8SStefan Schmidt return ret;
696c61c9bd8SStefan Schmidt }
697c61c9bd8SStefan Schmidt
698c61c9bd8SStefan Schmidt return 0;
699c61c9bd8SStefan Schmidt }
700c61c9bd8SStefan Schmidt
70106ff5dadSColin Ian King static struct atusb_chip_data atusb_chip_data = {
702d5dd29e4SJosef Filzmaier .t_channel_switch = 1,
703d5dd29e4SJosef Filzmaier .rssi_base_val = -91,
704d5dd29e4SJosef Filzmaier .set_txpower = atusb_set_txpower,
705d5dd29e4SJosef Filzmaier .set_channel = atusb_set_channel,
706d5dd29e4SJosef Filzmaier };
707d5dd29e4SJosef Filzmaier
70806ff5dadSColin Ian King static struct atusb_chip_data hulusb_chip_data = {
709d5dd29e4SJosef Filzmaier .t_channel_switch = 11,
710d5dd29e4SJosef Filzmaier .rssi_base_val = -100,
711d5dd29e4SJosef Filzmaier .set_txpower = hulusb_set_txpower,
712d5dd29e4SJosef Filzmaier .set_channel = hulusb_set_channel,
713d5dd29e4SJosef Filzmaier };
714d5dd29e4SJosef Filzmaier
715e796f49dSBhumika Goyal static const struct ieee802154_ops atusb_ops = {
7167490b008SAlexander Aring .owner = THIS_MODULE,
7177490b008SAlexander Aring .xmit_async = atusb_xmit,
7187490b008SAlexander Aring .ed = atusb_ed,
7197490b008SAlexander Aring .set_channel = atusb_channel,
7207490b008SAlexander Aring .start = atusb_start,
7217490b008SAlexander Aring .stop = atusb_stop,
7227490b008SAlexander Aring .set_hw_addr_filt = atusb_set_hw_addr_filt,
723d5dd29e4SJosef Filzmaier .set_txpower = atusb_txpower,
724d5dd29e4SJosef Filzmaier .set_lbt = hulusb_set_lbt,
725308dbb7aSStefan Schmidt .set_cca_mode = atusb_set_cca_mode,
7260f4715c8SStefan Schmidt .set_cca_ed_level = atusb_set_cca_ed_level,
727fb7c579aSStefan Schmidt .set_csma_params = atusb_set_csma_params,
7285d82288bSStefan Schmidt .set_frame_retries = atusb_set_frame_retries,
729c61c9bd8SStefan Schmidt .set_promiscuous_mode = atusb_set_promiscuous_mode,
7307490b008SAlexander Aring };
7317490b008SAlexander Aring
7327490b008SAlexander Aring /* ----- Firmware and chip version information ----------------------------- */
7337490b008SAlexander Aring
atusb_get_and_show_revision(struct atusb * atusb)7347490b008SAlexander Aring static int atusb_get_and_show_revision(struct atusb *atusb)
7357490b008SAlexander Aring {
7367490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
737d5dd29e4SJosef Filzmaier char *hw_name;
738416abf4fSPavel Skripkin unsigned char buffer[3];
7397490b008SAlexander Aring int ret;
7407490b008SAlexander Aring
7417490b008SAlexander Aring /* Get a couple of the ATMega Firmware values */
742416abf4fSPavel Skripkin ret = usb_control_msg_recv(atusb->usb_dev, 0, ATUSB_ID, ATUSB_REQ_FROM_DEV, 0, 0,
743416abf4fSPavel Skripkin buffer, 3, 1000, GFP_KERNEL);
744416abf4fSPavel Skripkin if (!ret) {
74546551564SStefan Schmidt atusb->fw_ver_maj = buffer[0];
74646551564SStefan Schmidt atusb->fw_ver_min = buffer[1];
74746551564SStefan Schmidt atusb->fw_hw_type = buffer[2];
74846551564SStefan Schmidt
749d5dd29e4SJosef Filzmaier switch (atusb->fw_hw_type) {
750d5dd29e4SJosef Filzmaier case ATUSB_HW_TYPE_100813:
751d5dd29e4SJosef Filzmaier case ATUSB_HW_TYPE_101216:
752d5dd29e4SJosef Filzmaier case ATUSB_HW_TYPE_110131:
753d5dd29e4SJosef Filzmaier hw_name = "ATUSB";
754d5dd29e4SJosef Filzmaier atusb->data = &atusb_chip_data;
755d5dd29e4SJosef Filzmaier break;
756d5dd29e4SJosef Filzmaier case ATUSB_HW_TYPE_RZUSB:
757d5dd29e4SJosef Filzmaier hw_name = "RZUSB";
758d5dd29e4SJosef Filzmaier atusb->data = &atusb_chip_data;
759d5dd29e4SJosef Filzmaier break;
760d5dd29e4SJosef Filzmaier case ATUSB_HW_TYPE_HULUSB:
761d5dd29e4SJosef Filzmaier hw_name = "HULUSB";
762d5dd29e4SJosef Filzmaier atusb->data = &hulusb_chip_data;
763d5dd29e4SJosef Filzmaier break;
764d5dd29e4SJosef Filzmaier default:
765d5dd29e4SJosef Filzmaier hw_name = "UNKNOWN";
766d5dd29e4SJosef Filzmaier atusb->err = -ENOTSUPP;
767d5dd29e4SJosef Filzmaier ret = -ENOTSUPP;
768d5dd29e4SJosef Filzmaier break;
769d5dd29e4SJosef Filzmaier }
770d5dd29e4SJosef Filzmaier
7717490b008SAlexander Aring dev_info(&usb_dev->dev,
772d5dd29e4SJosef Filzmaier "Firmware: major: %u, minor: %u, hardware type: %s (%d)\n",
7732f150344SStefan Schmidt atusb->fw_ver_maj, atusb->fw_ver_min, hw_name,
7742f150344SStefan Schmidt atusb->fw_hw_type);
77546551564SStefan Schmidt }
77646551564SStefan Schmidt if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 2) {
77733a238aeSStefan Schmidt dev_info(&usb_dev->dev,
77846551564SStefan Schmidt "Firmware version (%u.%u) predates our first public release.",
77946551564SStefan Schmidt atusb->fw_ver_maj, atusb->fw_ver_min);
78033a238aeSStefan Schmidt dev_info(&usb_dev->dev, "Please update to version 0.2 or newer");
78133a238aeSStefan Schmidt }
7827490b008SAlexander Aring
7837490b008SAlexander Aring return ret;
7847490b008SAlexander Aring }
7857490b008SAlexander Aring
atusb_get_and_show_build(struct atusb * atusb)7867490b008SAlexander Aring static int atusb_get_and_show_build(struct atusb *atusb)
7877490b008SAlexander Aring {
7887490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
78905a974efSStefan Schmidt char *build;
7907490b008SAlexander Aring int ret;
7917490b008SAlexander Aring
79205a974efSStefan Schmidt build = kmalloc(ATUSB_BUILD_SIZE + 1, GFP_KERNEL);
79305a974efSStefan Schmidt if (!build)
79405a974efSStefan Schmidt return -ENOMEM;
79505a974efSStefan Schmidt
796754e4382SPavel Skripkin ret = usb_control_msg(atusb->usb_dev, usb_rcvctrlpipe(usb_dev, 0), ATUSB_BUILD,
797754e4382SPavel Skripkin ATUSB_REQ_FROM_DEV, 0, 0, build, ATUSB_BUILD_SIZE, 1000);
7987490b008SAlexander Aring if (ret >= 0) {
7997490b008SAlexander Aring build[ret] = 0;
8007490b008SAlexander Aring dev_info(&usb_dev->dev, "Firmware: build %s\n", build);
8017490b008SAlexander Aring }
8027490b008SAlexander Aring
80305a974efSStefan Schmidt kfree(build);
8047490b008SAlexander Aring return ret;
8057490b008SAlexander Aring }
8067490b008SAlexander Aring
atusb_get_and_conf_chip(struct atusb * atusb)807d5dd29e4SJosef Filzmaier static int atusb_get_and_conf_chip(struct atusb *atusb)
8087490b008SAlexander Aring {
8097490b008SAlexander Aring struct usb_device *usb_dev = atusb->usb_dev;
810909dcf9bSStefan Schmidt u8 man_id_0, man_id_1, part_num, version_num;
8119def9afdSAlexander Aring const char *chip;
812d5dd29e4SJosef Filzmaier struct ieee802154_hw *hw = atusb->hw;
813416abf4fSPavel Skripkin int ret;
8147490b008SAlexander Aring
815416abf4fSPavel Skripkin ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
816416abf4fSPavel Skripkin 0, RG_MAN_ID_0, &man_id_0, 1, 1000, GFP_KERNEL);
817416abf4fSPavel Skripkin if (ret < 0)
818416abf4fSPavel Skripkin return ret;
8197490b008SAlexander Aring
820416abf4fSPavel Skripkin ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
821416abf4fSPavel Skripkin 0, RG_MAN_ID_1, &man_id_1, 1, 1000, GFP_KERNEL);
822416abf4fSPavel Skripkin if (ret < 0)
823416abf4fSPavel Skripkin return ret;
824416abf4fSPavel Skripkin
825416abf4fSPavel Skripkin ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
826416abf4fSPavel Skripkin 0, RG_PART_NUM, &part_num, 1, 1000, GFP_KERNEL);
827416abf4fSPavel Skripkin if (ret < 0)
828416abf4fSPavel Skripkin return ret;
829416abf4fSPavel Skripkin
830416abf4fSPavel Skripkin ret = usb_control_msg_recv(usb_dev, 0, ATUSB_REG_READ, ATUSB_REQ_FROM_DEV,
831416abf4fSPavel Skripkin 0, RG_VERSION_NUM, &version_num, 1, 1000, GFP_KERNEL);
832416abf4fSPavel Skripkin if (ret < 0)
833416abf4fSPavel Skripkin return ret;
8347490b008SAlexander Aring
835d5dd29e4SJosef Filzmaier hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
836d5dd29e4SJosef Filzmaier IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_CSMA_PARAMS;
837d5dd29e4SJosef Filzmaier
838d5dd29e4SJosef Filzmaier hw->phy->flags = WPAN_PHY_FLAG_TXPOWER | WPAN_PHY_FLAG_CCA_ED_LEVEL |
839d5dd29e4SJosef Filzmaier WPAN_PHY_FLAG_CCA_MODE;
840d5dd29e4SJosef Filzmaier
841d5dd29e4SJosef Filzmaier hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) |
842d5dd29e4SJosef Filzmaier BIT(NL802154_CCA_CARRIER) |
843d5dd29e4SJosef Filzmaier BIT(NL802154_CCA_ENERGY_CARRIER);
844d5dd29e4SJosef Filzmaier hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) |
845d5dd29e4SJosef Filzmaier BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR);
846d5dd29e4SJosef Filzmaier
847d5dd29e4SJosef Filzmaier hw->phy->cca.mode = NL802154_CCA_ENERGY;
848d5dd29e4SJosef Filzmaier
849d5dd29e4SJosef Filzmaier hw->phy->current_page = 0;
850d5dd29e4SJosef Filzmaier
8517490b008SAlexander Aring if ((man_id_1 << 8 | man_id_0) != ATUSB_JEDEC_ATMEL) {
8527490b008SAlexander Aring dev_err(&usb_dev->dev,
8537490b008SAlexander Aring "non-Atmel transceiver xxxx%02x%02x\n",
8547490b008SAlexander Aring man_id_1, man_id_0);
8557490b008SAlexander Aring goto fail;
8567490b008SAlexander Aring }
8579def9afdSAlexander Aring
8589def9afdSAlexander Aring switch (part_num) {
8599def9afdSAlexander Aring case 2:
8609def9afdSAlexander Aring chip = "AT86RF230";
861d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.channels[0] = 0x7FFF800;
862d5dd29e4SJosef Filzmaier atusb->hw->phy->current_channel = 11; /* reset default */
863d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers = atusb_powers;
864d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
865d5dd29e4SJosef Filzmaier hw->phy->supported.cca_ed_levels = atusb_ed_levels;
866d5dd29e4SJosef Filzmaier hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(atusb_ed_levels);
8679def9afdSAlexander Aring break;
8689def9afdSAlexander Aring case 3:
8699def9afdSAlexander Aring chip = "AT86RF231";
870d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.channels[0] = 0x7FFF800;
871d5dd29e4SJosef Filzmaier atusb->hw->phy->current_channel = 11; /* reset default */
872d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers = atusb_powers;
873d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers);
874d5dd29e4SJosef Filzmaier hw->phy->supported.cca_ed_levels = atusb_ed_levels;
875d5dd29e4SJosef Filzmaier hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(atusb_ed_levels);
876d5dd29e4SJosef Filzmaier break;
877d5dd29e4SJosef Filzmaier case 7:
878d5dd29e4SJosef Filzmaier chip = "AT86RF212";
879d5dd29e4SJosef Filzmaier atusb->hw->flags |= IEEE802154_HW_LBT;
880d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.channels[0] = 0x00007FF;
881d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.channels[2] = 0x00007FF;
882d5dd29e4SJosef Filzmaier atusb->hw->phy->current_channel = 5;
883d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
884d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers = at86rf212_powers;
885d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
886d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_100;
887d5dd29e4SJosef Filzmaier atusb->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_100);
8889def9afdSAlexander Aring break;
8899def9afdSAlexander Aring default:
8907490b008SAlexander Aring dev_err(&usb_dev->dev,
8917490b008SAlexander Aring "unexpected transceiver, part 0x%02x version 0x%02x\n",
8927490b008SAlexander Aring part_num, version_num);
8937490b008SAlexander Aring goto fail;
8947490b008SAlexander Aring }
8957490b008SAlexander Aring
896d5dd29e4SJosef Filzmaier hw->phy->transmit_power = hw->phy->supported.tx_powers[0];
897d5dd29e4SJosef Filzmaier hw->phy->cca_ed_level = hw->phy->supported.cca_ed_levels[7];
898d5dd29e4SJosef Filzmaier
8999def9afdSAlexander Aring dev_info(&usb_dev->dev, "ATUSB: %s version %d\n", chip, version_num);
9007490b008SAlexander Aring
9017490b008SAlexander Aring return 0;
9027490b008SAlexander Aring
9037490b008SAlexander Aring fail:
9047490b008SAlexander Aring atusb->err = -ENODEV;
9057490b008SAlexander Aring return -ENODEV;
9067490b008SAlexander Aring }
9077490b008SAlexander Aring
atusb_set_extended_addr(struct atusb * atusb)9086cc33ebaSStefan Schmidt static int atusb_set_extended_addr(struct atusb *atusb)
9096cc33ebaSStefan Schmidt {
9106cc33ebaSStefan Schmidt struct usb_device *usb_dev = atusb->usb_dev;
911416abf4fSPavel Skripkin unsigned char buffer[IEEE802154_EXTENDED_ADDR_LEN];
9126cc33ebaSStefan Schmidt __le64 extended_addr;
9136cc33ebaSStefan Schmidt u64 addr;
9146cc33ebaSStefan Schmidt int ret;
9156cc33ebaSStefan Schmidt
9166cc33ebaSStefan Schmidt /* Firmware versions before 0.3 do not support the EUI64_READ command.
9172f150344SStefan Schmidt * Just use a random address and be done.
9182f150344SStefan Schmidt */
9196cc33ebaSStefan Schmidt if (atusb->fw_ver_maj == 0 && atusb->fw_ver_min < 3) {
9206cc33ebaSStefan Schmidt ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
9216cc33ebaSStefan Schmidt return 0;
9226cc33ebaSStefan Schmidt }
9236cc33ebaSStefan Schmidt
9246cc33ebaSStefan Schmidt /* Firmware is new enough so we fetch the address from EEPROM */
925416abf4fSPavel Skripkin ret = usb_control_msg_recv(atusb->usb_dev, 0, ATUSB_EUI64_READ, ATUSB_REQ_FROM_DEV, 0, 0,
926416abf4fSPavel Skripkin buffer, IEEE802154_EXTENDED_ADDR_LEN, 1000, GFP_KERNEL);
9272fd2b550SStefan Schmidt if (ret < 0) {
9282fd2b550SStefan Schmidt dev_err(&usb_dev->dev, "failed to fetch extended address, random address set\n");
9292fd2b550SStefan Schmidt ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
9302fd2b550SStefan Schmidt return ret;
9312fd2b550SStefan Schmidt }
9326cc33ebaSStefan Schmidt
9336cc33ebaSStefan Schmidt memcpy(&extended_addr, buffer, IEEE802154_EXTENDED_ADDR_LEN);
9346cc33ebaSStefan Schmidt /* Check if read address is not empty and the unicast bit is set correctly */
9356cc33ebaSStefan Schmidt if (!ieee802154_is_valid_extended_unicast_addr(extended_addr)) {
9366cc33ebaSStefan Schmidt dev_info(&usb_dev->dev, "no permanent extended address found, random address set\n");
9376cc33ebaSStefan Schmidt ieee802154_random_extended_addr(&atusb->hw->phy->perm_extended_addr);
9386cc33ebaSStefan Schmidt } else {
9396cc33ebaSStefan Schmidt atusb->hw->phy->perm_extended_addr = extended_addr;
9406cc33ebaSStefan Schmidt addr = swab64((__force u64)atusb->hw->phy->perm_extended_addr);
9416cc33ebaSStefan Schmidt dev_info(&usb_dev->dev, "Read permanent extended address %8phC from device\n",
9426cc33ebaSStefan Schmidt &addr);
9436cc33ebaSStefan Schmidt }
9446cc33ebaSStefan Schmidt
9456cc33ebaSStefan Schmidt return ret;
9466cc33ebaSStefan Schmidt }
9476cc33ebaSStefan Schmidt
9487490b008SAlexander Aring /* ----- Setup ------------------------------------------------------------- */
9497490b008SAlexander Aring
atusb_probe(struct usb_interface * interface,const struct usb_device_id * id)9507490b008SAlexander Aring static int atusb_probe(struct usb_interface *interface,
9517490b008SAlexander Aring const struct usb_device_id *id)
9527490b008SAlexander Aring {
9537490b008SAlexander Aring struct usb_device *usb_dev = interface_to_usbdev(interface);
9547490b008SAlexander Aring struct ieee802154_hw *hw;
9557490b008SAlexander Aring struct atusb *atusb = NULL;
9567490b008SAlexander Aring int ret = -ENOMEM;
9577490b008SAlexander Aring
9587490b008SAlexander Aring hw = ieee802154_alloc_hw(sizeof(struct atusb), &atusb_ops);
9597490b008SAlexander Aring if (!hw)
9607490b008SAlexander Aring return -ENOMEM;
9617490b008SAlexander Aring
9627490b008SAlexander Aring atusb = hw->priv;
9637490b008SAlexander Aring atusb->hw = hw;
9647490b008SAlexander Aring atusb->usb_dev = usb_get_dev(usb_dev);
9657490b008SAlexander Aring usb_set_intfdata(interface, atusb);
9667490b008SAlexander Aring
9677490b008SAlexander Aring atusb->shutdown = 0;
9687490b008SAlexander Aring atusb->err = 0;
9697490b008SAlexander Aring INIT_DELAYED_WORK(&atusb->work, atusb_work_urbs);
9707490b008SAlexander Aring init_usb_anchor(&atusb->idle_urbs);
9717490b008SAlexander Aring init_usb_anchor(&atusb->rx_urbs);
9727490b008SAlexander Aring
9737490b008SAlexander Aring if (atusb_alloc_urbs(atusb, ATUSB_NUM_RX_URBS))
9747490b008SAlexander Aring goto fail;
9757490b008SAlexander Aring
9767490b008SAlexander Aring atusb->tx_dr.bRequestType = ATUSB_REQ_TO_DEV;
9777490b008SAlexander Aring atusb->tx_dr.bRequest = ATUSB_TX;
9787490b008SAlexander Aring atusb->tx_dr.wValue = cpu_to_le16(0);
9797490b008SAlexander Aring
980f9e628a6SJia-Ju Bai atusb->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
9817490b008SAlexander Aring if (!atusb->tx_urb)
9827490b008SAlexander Aring goto fail;
9837490b008SAlexander Aring
9847490b008SAlexander Aring hw->parent = &usb_dev->dev;
9857490b008SAlexander Aring
986416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_RF_RESET, ATUSB_REQ_TO_DEV, 0, 0,
987416abf4fSPavel Skripkin NULL, 0, 1000, GFP_KERNEL);
988d5dd29e4SJosef Filzmaier atusb_get_and_conf_chip(atusb);
9897490b008SAlexander Aring atusb_get_and_show_revision(atusb);
9907490b008SAlexander Aring atusb_get_and_show_build(atusb);
9916cc33ebaSStefan Schmidt atusb_set_extended_addr(atusb);
9926cc33ebaSStefan Schmidt
99376355698SStefan Schmidt if ((atusb->fw_ver_maj == 0 && atusb->fw_ver_min >= 3) || atusb->fw_ver_maj > 0)
9948e38b7d4SStefan Schmidt hw->flags |= IEEE802154_HW_FRAME_RETRIES;
9958e38b7d4SStefan Schmidt
9967490b008SAlexander Aring ret = atusb_get_and_clear_error(atusb);
9977490b008SAlexander Aring if (ret) {
9987490b008SAlexander Aring dev_err(&atusb->usb_dev->dev,
9997490b008SAlexander Aring "%s: initialization failed, error = %d\n",
10007490b008SAlexander Aring __func__, ret);
10017490b008SAlexander Aring goto fail;
10027490b008SAlexander Aring }
10037490b008SAlexander Aring
10047490b008SAlexander Aring ret = ieee802154_register_hw(hw);
10057490b008SAlexander Aring if (ret)
10067490b008SAlexander Aring goto fail;
10077490b008SAlexander Aring
10087490b008SAlexander Aring /* If we just powered on, we're now in P_ON and need to enter TRX_OFF
10097490b008SAlexander Aring * explicitly. Any resets after that will send us straight to TRX_OFF,
10107490b008SAlexander Aring * making the command below redundant.
10117490b008SAlexander Aring */
1012416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
1013416abf4fSPavel Skripkin STATE_FORCE_TRX_OFF, RG_TRX_STATE, NULL, 0, 1000, GFP_KERNEL);
1014416abf4fSPavel Skripkin
10157490b008SAlexander Aring msleep(1); /* reset => TRX_OFF, tTR13 = 37 us */
10167490b008SAlexander Aring
10177490b008SAlexander Aring #if 0
10187490b008SAlexander Aring /* Calculating the maximum time available to empty the frame buffer
10197490b008SAlexander Aring * on reception:
10207490b008SAlexander Aring *
10217490b008SAlexander Aring * According to [1], the inter-frame gap is
10227490b008SAlexander Aring * R * 20 * 16 us + 128 us
10237490b008SAlexander Aring * where R is a random number from 0 to 7. Furthermore, we have 20 bit
10247490b008SAlexander Aring * times (80 us at 250 kbps) of SHR of the next frame before the
10257490b008SAlexander Aring * transceiver begins storing data in the frame buffer.
10267490b008SAlexander Aring *
10277490b008SAlexander Aring * This yields a minimum time of 208 us between the last data of a
10287490b008SAlexander Aring * frame and the first data of the next frame. This time is further
10297490b008SAlexander Aring * reduced by interrupt latency in the atusb firmware.
10307490b008SAlexander Aring *
10317490b008SAlexander Aring * atusb currently needs about 500 us to retrieve a maximum-sized
10327490b008SAlexander Aring * frame. We therefore have to allow reception of a new frame to begin
10337490b008SAlexander Aring * while we retrieve the previous frame.
10347490b008SAlexander Aring *
10357490b008SAlexander Aring * [1] "JN-AN-1035 Calculating data rates in an IEEE 802.15.4-based
10367490b008SAlexander Aring * network", Jennic 2006.
10377490b008SAlexander Aring * http://www.jennic.com/download_file.php?supportFile=JN-AN-1035%20Calculating%20802-15-4%20Data%20Rates-1v0.pdf
10387490b008SAlexander Aring */
10397490b008SAlexander Aring
1040bdc78737SStefan Schmidt atusb_write_subreg(atusb, SR_RX_SAFE_MODE, 1);
10417490b008SAlexander Aring #endif
1042416abf4fSPavel Skripkin usb_control_msg_send(atusb->usb_dev, 0, ATUSB_REG_WRITE, ATUSB_REQ_TO_DEV,
1043416abf4fSPavel Skripkin 0xff, RG_IRQ_MASK, NULL, 0, 1000, GFP_KERNEL);
10447490b008SAlexander Aring
10457490b008SAlexander Aring ret = atusb_get_and_clear_error(atusb);
10467490b008SAlexander Aring if (!ret)
10477490b008SAlexander Aring return 0;
10487490b008SAlexander Aring
10497490b008SAlexander Aring dev_err(&atusb->usb_dev->dev,
10507490b008SAlexander Aring "%s: setup failed, error = %d\n",
10517490b008SAlexander Aring __func__, ret);
10527490b008SAlexander Aring
10537490b008SAlexander Aring ieee802154_unregister_hw(hw);
10547490b008SAlexander Aring fail:
10557490b008SAlexander Aring atusb_free_urbs(atusb);
10567490b008SAlexander Aring usb_kill_urb(atusb->tx_urb);
10577490b008SAlexander Aring usb_free_urb(atusb->tx_urb);
10587490b008SAlexander Aring usb_put_dev(usb_dev);
10597490b008SAlexander Aring ieee802154_free_hw(hw);
10607490b008SAlexander Aring return ret;
10617490b008SAlexander Aring }
10627490b008SAlexander Aring
atusb_disconnect(struct usb_interface * interface)10637490b008SAlexander Aring static void atusb_disconnect(struct usb_interface *interface)
10647490b008SAlexander Aring {
10657490b008SAlexander Aring struct atusb *atusb = usb_get_intfdata(interface);
10667490b008SAlexander Aring
10675f0cbf4eSStefan Schmidt dev_dbg(&atusb->usb_dev->dev, "%s\n", __func__);
10687490b008SAlexander Aring
10697490b008SAlexander Aring atusb->shutdown = 1;
10707490b008SAlexander Aring cancel_delayed_work_sync(&atusb->work);
10717490b008SAlexander Aring
10727490b008SAlexander Aring usb_kill_anchored_urbs(&atusb->rx_urbs);
10737490b008SAlexander Aring atusb_free_urbs(atusb);
10747490b008SAlexander Aring usb_kill_urb(atusb->tx_urb);
10757490b008SAlexander Aring usb_free_urb(atusb->tx_urb);
10767490b008SAlexander Aring
10777490b008SAlexander Aring ieee802154_unregister_hw(atusb->hw);
10787490b008SAlexander Aring
10797fd25e6fSJohan Hovold usb_put_dev(atusb->usb_dev);
10807fd25e6fSJohan Hovold
10817490b008SAlexander Aring ieee802154_free_hw(atusb->hw);
10827490b008SAlexander Aring
10837490b008SAlexander Aring usb_set_intfdata(interface, NULL);
10847490b008SAlexander Aring
10855f0cbf4eSStefan Schmidt pr_debug("%s done\n", __func__);
10867490b008SAlexander Aring }
10877490b008SAlexander Aring
10887490b008SAlexander Aring /* The devices we work with */
10897490b008SAlexander Aring static const struct usb_device_id atusb_device_table[] = {
10907490b008SAlexander Aring {
10917490b008SAlexander Aring .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
10927490b008SAlexander Aring USB_DEVICE_ID_MATCH_INT_INFO,
10937490b008SAlexander Aring .idVendor = ATUSB_VENDOR_ID,
10947490b008SAlexander Aring .idProduct = ATUSB_PRODUCT_ID,
10957490b008SAlexander Aring .bInterfaceClass = USB_CLASS_VENDOR_SPEC
10967490b008SAlexander Aring },
10977490b008SAlexander Aring /* end with null element */
10987490b008SAlexander Aring {}
10997490b008SAlexander Aring };
11007490b008SAlexander Aring MODULE_DEVICE_TABLE(usb, atusb_device_table);
11017490b008SAlexander Aring
11027490b008SAlexander Aring static struct usb_driver atusb_driver = {
11037490b008SAlexander Aring .name = "atusb",
11047490b008SAlexander Aring .probe = atusb_probe,
11057490b008SAlexander Aring .disconnect = atusb_disconnect,
11067490b008SAlexander Aring .id_table = atusb_device_table,
11077490b008SAlexander Aring };
11087490b008SAlexander Aring module_usb_driver(atusb_driver);
11097490b008SAlexander Aring
11107490b008SAlexander Aring MODULE_AUTHOR("Alexander Aring <alex.aring@gmail.com>");
11117490b008SAlexander Aring MODULE_AUTHOR("Richard Sharpe <realrichardsharpe@gmail.com>");
11127490b008SAlexander Aring MODULE_AUTHOR("Stefan Schmidt <stefan@datenfreihafen.org>");
11137490b008SAlexander Aring MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
1114d5dd29e4SJosef Filzmaier MODULE_AUTHOR("Josef Filzmaier <j.filzmaier@gmx.at>");
11157490b008SAlexander Aring MODULE_DESCRIPTION("ATUSB IEEE 802.15.4 Driver");
11167490b008SAlexander Aring MODULE_LICENSE("GPL");
1117