/* In promiscuous mode we disable AUTOCRC so we can get the raw CRC *valuesonRX.ThismeansweneedtomanuallyaddtheCRConTX.
*/ if (priv->promiscuous) {
u16 crc = crc_ccitt(0, skb->data, skb->len);
/* In promiscuous mode, we configure the radio to include the *CRC(AUTOCRC==0)andwepassonthepacketunconditionally.Ifnot *inpromiscuousmode,wechecktheCRChere,butleavethe *RSSI/LQI/CRC_OKbytesastheywillgetremovedinthemaclayer.
*/ if (!priv->promiscuous) { bool crc_ok;
/* Check if the CRC is valid. With AUTOCRC set, the most *significantbitofthelastbytereturnedfromtheCC2520 *isCRC_OKflag.Seesection20.3.4ofthedatasheet.
*/
crc_ok = skb->data[len - 1] & BIT(7);
/* If we failed CRC drop the packet in the driver layer. */ if (!crc_ok) {
dev_dbg(&priv->spi->dev, "CRC check failed\n");
kfree_skb(skb); return -EINVAL;
}
/* To calculate LQI, the lower 7 bits of the last byte (the *correlationvalueprovidedbytheradio)mustbescaledto *therange0-255.Accordingtosection20.6,thecorrelation *valuerangesfrom50-110.Ideallythiswouldbecalibrated *perhardwaredesign,butweuseroughlythedatasheetvalues *togetcloseenoughwhileavoidingfloatingpoint.
*/
lqi = skb->data[len - 1] & 0x7f; if (lqi < 50)
lqi = 50; elseif (lqi > 113)
lqi = 113;
lqi = (lqi - 50) * 4;
}
staticint
cc2520_filter(struct ieee802154_hw *hw, struct ieee802154_hw_addr_filt *filt, unsignedlong changed)
{ struct cc2520_private *priv = hw->priv; int ret = 0;
if (changed & IEEE802154_AFILT_PANID_CHANGED) {
u16 panid = le16_to_cpu(filt->pan_id);
dev_vdbg(&priv->spi->dev, "%s called for pan id\n", __func__);
ret = cc2520_write_ram(priv, CC2520RAM_PANID, sizeof(panid), (u8 *)&panid);
}
if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
dev_vdbg(&priv->spi->dev, "%s called for IEEE addr\n", __func__);
ret = cc2520_write_ram(priv, CC2520RAM_IEEEADDR, sizeof(filt->ieee_addr),
(u8 *)&filt->ieee_addr);
}
if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
u16 addr = le16_to_cpu(filt->short_addr);
dev_vdbg(&priv->spi->dev, "%s called for saddr\n", __func__);
ret = cc2520_write_ram(priv, CC2520RAM_SHORTADDR, sizeof(addr), (u8 *)&addr);
}
if (changed & IEEE802154_AFILT_PANC_CHANGED) {
u8 frmfilt0;
dev_vdbg(&priv->spi->dev, "%s called for panc change\n", __func__);
switch (mbm) { case500:
power = 0xF7; break; case300:
power = 0xF2; break; case200:
power = 0xAB; break; case100:
power = 0x13; break; case0:
power = 0x32; break; case -200:
power = 0x81; break; case -400:
power = 0x88; break; case -700:
power = 0x2C; break; case -1800:
power = 0x03; break; default: return -EINVAL;
}
switch (mbm) { case1700:
power = 0xF9; break; case1600:
power = 0xF0; break; case1400:
power = 0xA0; break; case1100:
power = 0x2C; break; case -100:
power = 0x03; break; case -800:
power = 0x01; break; default: return -EINVAL;
}
/* We do support only 2.4 Ghz */
priv->hw->phy->supported.channels[0] = 0x7FFF800;
priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
IEEE802154_HW_PROMISCUOUS;
/* If the CC2520 is connected to a CC2591 amplifier, we must both *configureGPIOsontheCC2520tocorrectlyconfiguretheCC2591 *andchangeacouplesettingsoftheCC2520toworkwiththe *amplifier.Seesection8page17ofTIapplicationnoteAN065. *http://www.ti.com/lit/an/swra229a/swra229a.pdf
*/ if (priv->amplified) {
ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x16); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_GPIOCTRL0, 0x46); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_GPIOCTRL5, 0x47); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_GPIOPOLARITY, 0x1e); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_TXCTRL, 0xc1); if (ret) goto err_ret;
} else {
ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11); if (ret) goto err_ret;
}
/* Registers default value: section 28.1 in Datasheet */
/* Set the CCA threshold to -50 dBm. This seems to have been copied *fromtheTinyOSCC2520driverandismuchhigherthanthe-84dBm *thresholdsuggestedinthedatasheet.
*/
ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03); if (ret) goto err_ret;
/* Configure registers correctly for this driver. */
ret = cc2520_write_register(priv, CC2520_FRMCTRL1,
FRMCTRL1_SET_RXENMASK_ON_TX |
FRMCTRL1_IGNORE_TX_UNDERF); if (ret) goto err_ret;
ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127); if (ret) goto err_ret;
priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM;
spi_set_drvdata(spi, priv);
/* CC2591 front end for CC2520 */ /* Assumption that CC2591 is not connected */
priv->amplified = false; if (device_property_read_bool(&spi->dev, "amplified"))
priv->amplified = true;
priv->spi = spi;
priv->buf = devm_kzalloc(&spi->dev,
SPI_COMMAND_BUFFER, GFP_KERNEL); if (!priv->buf) return -ENOMEM;
/* Request all the gpio's */
priv->fifo_pin = devm_gpiod_get(&spi->dev, "fifo", GPIOD_IN); if (IS_ERR(priv->fifo_pin)) {
dev_err(&spi->dev, "fifo gpio is not valid\n");
ret = PTR_ERR(priv->fifo_pin); goto err_hw_init;
}
cca = devm_gpiod_get(&spi->dev, "cca", GPIOD_IN); if (IS_ERR(cca)) {
dev_err(&spi->dev, "cca gpio is not valid\n");
ret = PTR_ERR(cca); goto err_hw_init;
}
fifop = devm_gpiod_get(&spi->dev, "fifop", GPIOD_IN); if (IS_ERR(fifop)) {
dev_err(&spi->dev, "fifop gpio is not valid\n");
ret = PTR_ERR(fifop); goto err_hw_init;
}
sfd = devm_gpiod_get(&spi->dev, "sfd", GPIOD_IN); if (IS_ERR(sfd)) {
dev_err(&spi->dev, "sfd gpio is not valid\n");
ret = PTR_ERR(sfd); goto err_hw_init;
}
reset = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset)) {
dev_err(&spi->dev, "reset gpio is not valid\n");
ret = PTR_ERR(reset); goto err_hw_init;
}
vreg = devm_gpiod_get(&spi->dev, "vreg", GPIOD_OUT_LOW); if (IS_ERR(vreg)) {
dev_err(&spi->dev, "vreg gpio is not valid\n");
ret = PTR_ERR(vreg); goto err_hw_init;
}
ret = cc2520_hw_init(priv); if (ret) goto err_hw_init;
/* Set up fifop interrupt */
ret = devm_request_irq(&spi->dev,
gpiod_to_irq(fifop),
cc2520_fifop_isr,
IRQF_TRIGGER_RISING,
dev_name(&spi->dev),
priv); if (ret) {
dev_err(&spi->dev, "could not get fifop irq\n"); goto err_hw_init;
}
/* Set up sfd interrupt */
ret = devm_request_irq(&spi->dev,
gpiod_to_irq(sfd),
cc2520_sfd_isr,
IRQF_TRIGGER_FALLING,
dev_name(&spi->dev),
priv); if (ret) {
dev_err(&spi->dev, "could not get sfd irq\n"); goto err_hw_init;
}
ret = cc2520_register(priv); if (ret) goto err_hw_init;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.