Lines Matching +full:filt +full:- +full:disable
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Driver for TI CC2520 802.15.4 Wireless-PAN Networking controller
18 #include <linux/crc-ccitt.h>
47 /* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
203 struct ieee802154_hw *hw; /* IEEE-802.15.4 device */
223 .tx_buf = priv->buf, in cc2520_cmd_strobe()
224 .rx_buf = priv->buf, in cc2520_cmd_strobe()
230 mutex_lock(&priv->buffer_mutex); in cc2520_cmd_strobe()
231 priv->buf[xfer.len++] = cmd; in cc2520_cmd_strobe()
232 dev_vdbg(&priv->spi->dev, in cc2520_cmd_strobe()
234 priv->buf[0]); in cc2520_cmd_strobe()
236 ret = spi_sync(priv->spi, &msg); in cc2520_cmd_strobe()
237 dev_vdbg(&priv->spi->dev, in cc2520_cmd_strobe()
238 "buf[0] = %02x\n", priv->buf[0]); in cc2520_cmd_strobe()
239 mutex_unlock(&priv->buffer_mutex); in cc2520_cmd_strobe()
251 .tx_buf = priv->buf, in cc2520_get_status()
252 .rx_buf = priv->buf, in cc2520_get_status()
258 mutex_lock(&priv->buffer_mutex); in cc2520_get_status()
259 priv->buf[xfer.len++] = CC2520_CMD_SNOP; in cc2520_get_status()
260 dev_vdbg(&priv->spi->dev, in cc2520_get_status()
261 "get status command buf[0] = %02x\n", priv->buf[0]); in cc2520_get_status()
263 ret = spi_sync(priv->spi, &msg); in cc2520_get_status()
265 *status = priv->buf[0]; in cc2520_get_status()
266 dev_vdbg(&priv->spi->dev, in cc2520_get_status()
267 "buf[0] = %02x\n", priv->buf[0]); in cc2520_get_status()
268 mutex_unlock(&priv->buffer_mutex); in cc2520_get_status()
280 .tx_buf = priv->buf, in cc2520_write_register()
281 .rx_buf = priv->buf, in cc2520_write_register()
287 mutex_lock(&priv->buffer_mutex); in cc2520_write_register()
290 priv->buf[xfer.len++] = CC2520_CMD_REGISTER_WRITE | reg; in cc2520_write_register()
291 priv->buf[xfer.len++] = value; in cc2520_write_register()
293 priv->buf[xfer.len++] = CC2520_CMD_MEMORY_WRITE; in cc2520_write_register()
294 priv->buf[xfer.len++] = reg; in cc2520_write_register()
295 priv->buf[xfer.len++] = value; in cc2520_write_register()
297 status = spi_sync(priv->spi, &msg); in cc2520_write_register()
301 mutex_unlock(&priv->buffer_mutex); in cc2520_write_register()
313 .tx_buf = priv->buf, in cc2520_write_ram()
314 .rx_buf = priv->buf, in cc2520_write_ram()
322 mutex_lock(&priv->buffer_mutex); in cc2520_write_ram()
323 priv->buf[xfer_head.len++] = (CC2520_CMD_MEMORY_WRITE | in cc2520_write_ram()
325 priv->buf[xfer_head.len++] = reg & 0xff; in cc2520_write_ram()
331 status = spi_sync(priv->spi, &msg); in cc2520_write_ram()
332 dev_dbg(&priv->spi->dev, "spi status = %d\n", status); in cc2520_write_ram()
336 mutex_unlock(&priv->buffer_mutex); in cc2520_write_ram()
347 .tx_buf = priv->buf, in cc2520_read_register()
348 .rx_buf = priv->buf, in cc2520_read_register()
360 mutex_lock(&priv->buffer_mutex); in cc2520_read_register()
361 priv->buf[xfer1.len++] = CC2520_CMD_MEMORY_READ; in cc2520_read_register()
362 priv->buf[xfer1.len++] = reg; in cc2520_read_register()
364 status = spi_sync(priv->spi, &msg); in cc2520_read_register()
365 dev_dbg(&priv->spi->dev, in cc2520_read_register()
370 mutex_unlock(&priv->buffer_mutex); in cc2520_read_register()
389 .tx_buf = priv->buf, in cc2520_write_txfifo()
390 .rx_buf = priv->buf, in cc2520_write_txfifo()
406 mutex_lock(&priv->buffer_mutex); in cc2520_write_txfifo()
407 priv->buf[xfer_head.len++] = CC2520_CMD_TXBUF; in cc2520_write_txfifo()
408 dev_vdbg(&priv->spi->dev, in cc2520_write_txfifo()
409 "TX_FIFO cmd buf[0] = %02x\n", priv->buf[0]); in cc2520_write_txfifo()
411 status = spi_sync(priv->spi, &msg); in cc2520_write_txfifo()
412 dev_vdbg(&priv->spi->dev, "status = %d\n", status); in cc2520_write_txfifo()
415 dev_vdbg(&priv->spi->dev, "status = %d\n", status); in cc2520_write_txfifo()
416 dev_vdbg(&priv->spi->dev, "buf[0] = %02x\n", priv->buf[0]); in cc2520_write_txfifo()
417 mutex_unlock(&priv->buffer_mutex); in cc2520_write_txfifo()
430 .tx_buf = priv->buf, in cc2520_read_rxfifo()
431 .rx_buf = priv->buf, in cc2520_read_rxfifo()
442 mutex_lock(&priv->buffer_mutex); in cc2520_read_rxfifo()
443 priv->buf[xfer_head.len++] = CC2520_CMD_RXBUF; in cc2520_read_rxfifo()
445 dev_vdbg(&priv->spi->dev, "read rxfifo buf[0] = %02x\n", priv->buf[0]); in cc2520_read_rxfifo()
446 dev_vdbg(&priv->spi->dev, "buf[1] = %02x\n", priv->buf[1]); in cc2520_read_rxfifo()
448 status = spi_sync(priv->spi, &msg); in cc2520_read_rxfifo()
449 dev_vdbg(&priv->spi->dev, "status = %d\n", status); in cc2520_read_rxfifo()
452 dev_vdbg(&priv->spi->dev, "status = %d\n", status); in cc2520_read_rxfifo()
453 dev_vdbg(&priv->spi->dev, in cc2520_read_rxfifo()
454 "return status buf[0] = %02x\n", priv->buf[0]); in cc2520_read_rxfifo()
455 dev_vdbg(&priv->spi->dev, "length buf[1] = %02x\n", priv->buf[1]); in cc2520_read_rxfifo()
457 mutex_unlock(&priv->buffer_mutex); in cc2520_read_rxfifo()
464 return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON); in cc2520_start()
469 cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF); in cc2520_stop()
475 struct cc2520_private *priv = hw->priv; in cc2520_tx()
481 /* In promiscuous mode we disable AUTOCRC so we can get the raw CRC in cc2520_tx()
484 if (priv->promiscuous) { in cc2520_tx()
485 u16 crc = crc_ccitt(0, skb->data, skb->len); in cc2520_tx()
488 pkt_len = skb->len; in cc2520_tx()
490 pkt_len = skb->len + 2; in cc2520_tx()
497 rc = cc2520_write_txfifo(priv, pkt_len, skb->data, skb->len); in cc2520_tx()
506 rc = -EINVAL; in cc2520_tx()
507 dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n"); in cc2520_tx()
511 spin_lock_irqsave(&priv->lock, flags); in cc2520_tx()
512 WARN_ON(priv->is_tx); in cc2520_tx()
513 priv->is_tx = 1; in cc2520_tx()
514 spin_unlock_irqrestore(&priv->lock, flags); in cc2520_tx()
520 rc = wait_for_completion_interruptible(&priv->tx_complete); in cc2520_tx()
529 spin_lock_irqsave(&priv->lock, flags); in cc2520_tx()
530 priv->is_tx = 0; in cc2520_tx()
531 spin_unlock_irqrestore(&priv->lock, flags); in cc2520_tx()
548 dev_dbg(&priv->spi->dev, "corrupted frame received\n"); in cc2520_rx()
554 return -ENOMEM; in cc2520_rx()
557 dev_dbg(&priv->spi->dev, "frame reception failed\n"); in cc2520_rx()
559 return -EINVAL; in cc2520_rx()
567 if (!priv->promiscuous) { in cc2520_rx()
574 crc_ok = skb->data[len - 1] & BIT(7); in cc2520_rx()
578 dev_dbg(&priv->spi->dev, "CRC check failed\n"); in cc2520_rx()
580 return -EINVAL; in cc2520_rx()
585 * the range 0-255. According to section 20.6, the correlation in cc2520_rx()
586 * value ranges from 50-110. Ideally this would be calibrated in cc2520_rx()
590 lqi = skb->data[len - 1] & 0x7f; in cc2520_rx()
595 lqi = (lqi - 50) * 4; in cc2520_rx()
598 ieee802154_rx_irqsafe(priv->hw, skb, lqi); in cc2520_rx()
600 dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi); in cc2520_rx()
608 struct cc2520_private *priv = hw->priv; in cc2520_ed()
618 return -EINVAL; in cc2520_ed()
624 /* level = RSSI(rssi) - OFFSET [dBm] : offset is 76dBm */ in cc2520_ed()
625 *level = rssi - RSSI_OFFSET; in cc2520_ed()
633 struct cc2520_private *priv = hw->priv; in cc2520_set_channel()
636 dev_dbg(&priv->spi->dev, "trying to set channel\n"); in cc2520_set_channel()
643 11 + 5 * (channel - 11)); in cc2520_set_channel()
650 struct ieee802154_hw_addr_filt *filt, unsigned long changed) in cc2520_filter() argument
652 struct cc2520_private *priv = hw->priv; in cc2520_filter()
656 u16 panid = le16_to_cpu(filt->pan_id); in cc2520_filter()
658 dev_vdbg(&priv->spi->dev, "%s called for pan id\n", __func__); in cc2520_filter()
664 dev_vdbg(&priv->spi->dev, in cc2520_filter()
667 sizeof(filt->ieee_addr), in cc2520_filter()
668 (u8 *)&filt->ieee_addr); in cc2520_filter()
672 u16 addr = le16_to_cpu(filt->short_addr); in cc2520_filter()
674 dev_vdbg(&priv->spi->dev, "%s called for saddr\n", __func__); in cc2520_filter()
682 dev_vdbg(&priv->spi->dev, in cc2520_filter()
687 if (filt->pan_coord) in cc2520_filter()
718 case -200: in cc2520_set_tx_power()
721 case -400: in cc2520_set_tx_power()
724 case -700: in cc2520_set_tx_power()
727 case -1800: in cc2520_set_tx_power()
731 return -EINVAL; in cc2520_set_tx_power()
755 case -100: in cc2520_cc2591_set_tx_power()
758 case -800: in cc2520_cc2591_set_tx_power()
762 return -EINVAL; in cc2520_cc2591_set_tx_power()
770 500, 300, 200, 100, 0, -200, -400, -700, -1800,
775 1700, 1600, 1400, 1100, -100, -800,
781 struct cc2520_private *priv = hw->priv; in cc2520_set_txpower()
783 if (!priv->amplified) in cc2520_set_txpower()
792 struct cc2520_private *priv = hw->priv; in cc2520_set_promiscuous_mode()
795 dev_dbg(&priv->spi->dev, "%s : mode %d\n", __func__, on); in cc2520_set_promiscuous_mode()
797 priv->promiscuous = on; in cc2520_set_promiscuous_mode()
802 /* Disable automatic ACK, automatic CRC, and frame filtering. */ in cc2520_set_promiscuous_mode()
827 int ret = -ENOMEM; in cc2520_register()
829 priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops); in cc2520_register()
830 if (!priv->hw) in cc2520_register()
833 priv->hw->priv = priv; in cc2520_register()
834 priv->hw->parent = &priv->spi->dev; in cc2520_register()
835 priv->hw->extra_tx_headroom = 0; in cc2520_register()
836 ieee802154_random_extended_addr(&priv->hw->phy->perm_extended_addr); in cc2520_register()
839 priv->hw->phy->supported.channels[0] = 0x7FFF800; in cc2520_register()
840 priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | in cc2520_register()
843 priv->hw->phy->flags = WPAN_PHY_FLAG_TXPOWER; in cc2520_register()
845 if (!priv->amplified) { in cc2520_register()
846 priv->hw->phy->supported.tx_powers = cc2520_powers; in cc2520_register()
847 priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_powers); in cc2520_register()
848 priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[4]; in cc2520_register()
850 priv->hw->phy->supported.tx_powers = cc2520_cc2591_powers; in cc2520_register()
851 priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_cc2591_powers); in cc2520_register()
852 priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[0]; in cc2520_register()
855 priv->hw->phy->current_channel = 11; in cc2520_register()
857 dev_vdbg(&priv->spi->dev, "registered cc2520\n"); in cc2520_register()
858 ret = ieee802154_register_hw(priv->hw); in cc2520_register()
865 ieee802154_free_hw(priv->hw); in cc2520_register()
875 dev_dbg(&priv->spi->dev, "fifop interrupt received\n"); in cc2520_fifop_irqwork()
877 if (gpiod_get_value(priv->fifo_pin)) in cc2520_fifop_irqwork()
880 dev_dbg(&priv->spi->dev, "rxfifo overflow\n"); in cc2520_fifop_irqwork()
890 schedule_work(&priv->fifop_irqwork); in cc2520_fifop_isr()
900 spin_lock_irqsave(&priv->lock, flags); in cc2520_sfd_isr()
901 if (priv->is_tx) { in cc2520_sfd_isr()
902 priv->is_tx = 0; in cc2520_sfd_isr()
903 spin_unlock_irqrestore(&priv->lock, flags); in cc2520_sfd_isr()
904 dev_dbg(&priv->spi->dev, "SFD for TX\n"); in cc2520_sfd_isr()
905 complete(&priv->tx_complete); in cc2520_sfd_isr()
907 spin_unlock_irqrestore(&priv->lock, flags); in cc2520_sfd_isr()
908 dev_dbg(&priv->spi->dev, "SFD for RX\n"); in cc2520_sfd_isr()
925 return -EINVAL; in cc2520_hw_init()
932 if (timeout-- <= 0) { in cc2520_hw_init()
933 dev_err(&priv->spi->dev, "oscillator start failed!\n"); in cc2520_hw_init()
934 return -ETIMEDOUT; in cc2520_hw_init()
939 dev_vdbg(&priv->spi->dev, "oscillator brought up\n"); in cc2520_hw_init()
947 if (priv->amplified) { in cc2520_hw_init()
975 /* Set the CCA threshold to -50 dBm. This seems to have been copied in cc2520_hw_init()
976 * from the TinyOS CC2520 driver and is much higher than the -84 dBm in cc2520_hw_init()
1042 priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); in cc2520_probe()
1044 return -ENOMEM; in cc2520_probe()
1050 priv->amplified = false; in cc2520_probe()
1051 if (device_property_read_bool(&spi->dev, "amplified")) in cc2520_probe()
1052 priv->amplified = true; in cc2520_probe()
1054 priv->spi = spi; in cc2520_probe()
1056 priv->buf = devm_kzalloc(&spi->dev, in cc2520_probe()
1058 if (!priv->buf) in cc2520_probe()
1059 return -ENOMEM; in cc2520_probe()
1061 mutex_init(&priv->buffer_mutex); in cc2520_probe()
1062 INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork); in cc2520_probe()
1063 spin_lock_init(&priv->lock); in cc2520_probe()
1064 init_completion(&priv->tx_complete); in cc2520_probe()
1067 priv->fifo_pin = devm_gpiod_get(&spi->dev, "fifo", GPIOD_IN); in cc2520_probe()
1068 if (IS_ERR(priv->fifo_pin)) { in cc2520_probe()
1069 dev_err(&spi->dev, "fifo gpio is not valid\n"); in cc2520_probe()
1070 ret = PTR_ERR(priv->fifo_pin); in cc2520_probe()
1074 cca = devm_gpiod_get(&spi->dev, "cca", GPIOD_IN); in cc2520_probe()
1076 dev_err(&spi->dev, "cca gpio is not valid\n"); in cc2520_probe()
1081 fifop = devm_gpiod_get(&spi->dev, "fifop", GPIOD_IN); in cc2520_probe()
1083 dev_err(&spi->dev, "fifop gpio is not valid\n"); in cc2520_probe()
1088 sfd = devm_gpiod_get(&spi->dev, "sfd", GPIOD_IN); in cc2520_probe()
1090 dev_err(&spi->dev, "sfd gpio is not valid\n"); in cc2520_probe()
1095 reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); in cc2520_probe()
1097 dev_err(&spi->dev, "reset gpio is not valid\n"); in cc2520_probe()
1102 vreg = devm_gpiod_get(&spi->dev, "vreg", GPIOD_OUT_LOW); in cc2520_probe()
1104 dev_err(&spi->dev, "vreg gpio is not valid\n"); in cc2520_probe()
1120 ret = devm_request_irq(&spi->dev, in cc2520_probe()
1124 dev_name(&spi->dev), in cc2520_probe()
1127 dev_err(&spi->dev, "could not get fifop irq\n"); in cc2520_probe()
1132 ret = devm_request_irq(&spi->dev, in cc2520_probe()
1136 dev_name(&spi->dev), in cc2520_probe()
1139 dev_err(&spi->dev, "could not get sfd irq\n"); in cc2520_probe()
1150 mutex_destroy(&priv->buffer_mutex); in cc2520_probe()
1151 flush_work(&priv->fifop_irqwork); in cc2520_probe()
1159 mutex_destroy(&priv->buffer_mutex); in cc2520_remove()
1160 flush_work(&priv->fifop_irqwork); in cc2520_remove()
1162 ieee802154_unregister_hw(priv->hw); in cc2520_remove()
1163 ieee802154_free_hw(priv->hw); in cc2520_remove()