/* The datasheet indicates the theoretical maximum for SCK to be 10MHz */ #define MAX_SPI_SPEED_HZ 10000000
#define printdev(X) (&X->spi->dev)
staticbool
mrf24j40_short_reg_writeable(struct device *dev, unsignedint reg)
{ switch (reg) { case REG_RXMCR: case REG_PANIDL: case REG_PANIDH: case REG_SADRL: case REG_SADRH: case REG_EADR0: case REG_EADR1: case REG_EADR2: case REG_EADR3: case REG_EADR4: case REG_EADR5: case REG_EADR6: case REG_EADR7: case REG_RXFLUSH: case REG_ORDER: case REG_TXMCR: case REG_ACKTMOUT: case REG_ESLOTG1: case REG_SYMTICKL: case REG_SYMTICKH: case REG_PACON0: case REG_PACON1: case REG_PACON2: case REG_TXBCON0: case REG_TXNCON: case REG_TXG1CON: case REG_TXG2CON: case REG_ESLOTG23: case REG_ESLOTG45: case REG_ESLOTG67: case REG_TXPEND: case REG_WAKECON: case REG_FROMOFFSET: case REG_TXBCON1: case REG_GATECLK: case REG_TXTIME: case REG_HSYMTMRL: case REG_HSYMTMRH: case REG_SOFTRST: case REG_SECCON0: case REG_SECCON1: case REG_TXSTBL: case REG_RXSR: case REG_INTCON: case REG_TRISGPIO: case REG_GPIO: case REG_RFCTL: case REG_SECCR2: case REG_SLPACK: case REG_BBREG0: case REG_BBREG1: case REG_BBREG2: case REG_BBREG3: case REG_BBREG4: case REG_BBREG6: case REG_CCAEDTH: returntrue; default: returnfalse;
}
}
/* all writeable are also readable */
rc = mrf24j40_short_reg_writeable(dev, reg); if (rc) return rc;
/* readonly regs */ switch (reg) { case REG_TXSTAT: case REG_INTSTAT: returntrue; default: returnfalse;
}
}
staticbool
mrf24j40_short_reg_volatile(struct device *dev, unsignedint reg)
{ /* can be changed during runtime */ switch (reg) { case REG_TXSTAT: case REG_INTSTAT: case REG_RXFLUSH: case REG_TXNCON: case REG_SOFTRST: case REG_RFCTL: case REG_TXBCON0: case REG_TXG1CON: case REG_TXG2CON: case REG_TXBCON1: case REG_SECCON0: case REG_RXSR: case REG_SLPACK: case REG_SECCR2: case REG_BBREG6: /* use them in spi_async and regmap so it's volatile */ case REG_BBREG1: returntrue; default: returnfalse;
}
}
staticbool
mrf24j40_short_reg_precious(struct device *dev, unsignedint reg)
{ /* don't clear irq line on read */ switch (reg) { case REG_INTSTAT: returntrue; default: returnfalse;
}
}
staticbool
mrf24j40_long_reg_writeable(struct device *dev, unsignedint reg)
{ switch (reg) { case REG_RFCON0: case REG_RFCON1: case REG_RFCON2: case REG_RFCON3: case REG_RFCON5: case REG_RFCON6: case REG_RFCON7: case REG_RFCON8: case REG_SLPCAL2: case REG_SLPCON0: case REG_SLPCON1: case REG_WAKETIMEL: case REG_WAKETIMEH: case REG_REMCNTL: case REG_REMCNTH: case REG_MAINCNT0: case REG_MAINCNT1: case REG_MAINCNT2: case REG_MAINCNT3: case REG_TESTMODE: case REG_ASSOEAR0: case REG_ASSOEAR1: case REG_ASSOEAR2: case REG_ASSOEAR3: case REG_ASSOEAR4: case REG_ASSOEAR5: case REG_ASSOEAR6: case REG_ASSOEAR7: case REG_ASSOSAR0: case REG_ASSOSAR1: case REG_UNONCE0: case REG_UNONCE1: case REG_UNONCE2: case REG_UNONCE3: case REG_UNONCE4: case REG_UNONCE5: case REG_UNONCE6: case REG_UNONCE7: case REG_UNONCE8: case REG_UNONCE9: case REG_UNONCE10: case REG_UNONCE11: case REG_UNONCE12: returntrue; default: returnfalse;
}
}
/* all writeable are also readable */
rc = mrf24j40_long_reg_writeable(dev, reg); if (rc) return rc;
/* readonly regs */ switch (reg) { case REG_SLPCAL0: case REG_SLPCAL1: case REG_RFSTATE: case REG_RSSI: returntrue; default: returnfalse;
}
}
staticbool
mrf24j40_long_reg_volatile(struct device *dev, unsignedint reg)
{ /* can be changed during runtime */ switch (reg) { case REG_SLPCAL0: case REG_SLPCAL1: case REG_SLPCAL2: case REG_RFSTATE: case REG_RSSI: case REG_MAINCNT3: returntrue; default: returnfalse;
}
}
/* regmap supports read/write mask only in frist byte * long write access need to set the 12th bit, so we * make special handling for write.
*/
memcpy(buf, data, count);
buf[1] |= (1 << 4);
ret = spi_async(devrec->spi, &devrec->tx_post_msg); if (ret)
dev_err(printdev(devrec), "SPI write Failed for transmit buf\n");
}
/* This function relies on an undocumented write method. Once a write command and address is set, as many bytes of data as desired can be clocked into
the device. The datasheet only shows setting one byte at a time. */ staticint write_tx_buf(struct mrf24j40 *devrec, u16 reg, const u8 *data, size_t length)
{
u16 cmd; int ret;
/* Range check the length. 2 bytes are used for the length fields.*/ if (length > TX_FIFO_SIZE-2) {
dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n");
length = TX_FIFO_SIZE-2;
}
cmd = MRF24J40_WRITELONG(reg);
devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff;
devrec->tx_hdr_buf[1] = cmd & 0xff;
devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
devrec->tx_len_buf[1] = length; /* Total length */
devrec->tx_buf_trx.tx_buf = data;
devrec->tx_buf_trx.len = length;
ret = spi_async(devrec->spi, &devrec->tx_msg); if (ret)
dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
/* Set Channel TODO */
val = (channel - 11) << RFCON0_CH_SHIFT | RFOPT_RECOMMEND;
ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0,
RFCON0_CH_MASK, val); if (ret) return ret;
/* RF Reset */
ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST,
BIT_RFRST); if (ret) return ret;
ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, 0); if (!ret)
udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
}
if (changed & IEEE802154_AFILT_PANC_CHANGED) { /* Pan Coordinator */
u8 val; int ret;
if (filt->pan_coord)
val = BIT_PANCOORD; else
val = 0;
ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
BIT_PANCOORD, val); if (ret) return ret;
/* REG_SLOTTED is maintained as default (unslotted/CSMA-CA). * REG_ORDER is maintained as default (no beacon/superframe).
*/
dev_dbg(printdev(devrec), "Set Pan Coord to %s\n",
filt->pan_coord ? "on" : "off");
}
return 0;
}
staticvoid mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec)
{ int ret;
/* Turn back on reception of packets off the air. */
devrec->rx_msg.complete = NULL;
devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */
ret = spi_async(devrec->spi, &devrec->rx_msg); if (ret)
dev_err(printdev(devrec), "failed to unlock rx buffer\n");
}
/* read the length of received frame */
devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf;
devrec->rx_trx.len = 3;
cmd = MRF24J40_READLONG(REG_RX_FIFO);
devrec->rx_buf[0] = cmd >> 8 & 0xff;
devrec->rx_buf[1] = cmd & 0xff;
ret = spi_async(devrec->spi, &devrec->rx_msg); if (ret) {
dev_err(printdev(devrec), "failed to read rx buffer length\n");
mrf24j40_handle_rx_read_buf_unlock(devrec);
}
}
staticint mrf24j40_handle_rx(struct mrf24j40 *devrec)
{ /* Turn off reception of packets off the air. This prevents the * device from overwriting the buffer while we're reading it.
*/
devrec->rx_msg.complete = mrf24j40_handle_rx_read_len;
devrec->rx_trx.len = 2;
devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
devrec->rx_buf[1] = BIT_RXDECINV; /* SET RXDECINV */
for (i = 0; i < ARRAY_SIZE(mrf24j40_ed_levels_map); i++) { if (mrf24j40_ed_levels_map[i][0] == mbm) return regmap_write(devrec->regmap_short, REG_CCAEDTH,
mrf24j40_ed_levels_map[i][1]);
}
switch (small_scale) { case 0:
val |= (TXPWRS_0 << TXPWRS_SHIFT); break; case -50:
val |= (TXPWRS_0_5 << TXPWRS_SHIFT); break; case -120:
val |= (TXPWRS_1_2 << TXPWRS_SHIFT); break; case -190:
val |= (TXPWRS_1_9 << TXPWRS_SHIFT); break; case -280:
val |= (TXPWRS_2_8 << TXPWRS_SHIFT); break; case -370:
val |= (TXPWRS_3_7 << TXPWRS_SHIFT); break; case -490:
val |= (TXPWRS_4_9 << TXPWRS_SHIFT); break; case -630:
val |= (TXPWRS_6_3 << TXPWRS_SHIFT); break; default: return -EINVAL;
}
/* Read the interrupt status */
ret = spi_async(devrec->spi, &devrec->irq_msg); if (ret) {
enable_irq(irq); return IRQ_NONE;
}
return IRQ_HANDLED;
}
staticint mrf24j40_hw_init(struct mrf24j40 *devrec)
{
u32 irq_type; int ret;
/* Initialize the device.
From datasheet section 3.2: Initialization. */
ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04); if (ret) goto err_ret;
ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0); if (ret) goto err_ret;
udelay(192);
/* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00); if (ret) goto err_ret;
/* Set GPIO3 as output. */
regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08,
0x08);
/* Set GPIO3 HIGH to enable U5 voltage regulator */
regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08);
/* Reduce TX pwr to meet FCC requirements. * From MRF24J40MC datasheet section 3.1.1
*/
regmap_write(devrec->regmap_long, REG_RFCON3, 0x28);
}
irq_type = irq_get_trigger_type(devrec->spi->irq); if (irq_type == IRQ_TYPE_EDGE_RISING ||
irq_type == IRQ_TYPE_EDGE_FALLING)
dev_warn(&devrec->spi->dev, "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n"); switch (irq_type) { case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_LEVEL_HIGH: /* set interrupt polarity to rising */
ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0,
BIT_INTEDGE, BIT_INTEDGE); if (ret) goto err_ret; break; default: /* default is falling edge */ break;
}
/* mrf24j40 supports max_minbe 0 - 3 */
devrec->hw->phy->supported.max_minbe = 3; /* datasheet doesn't say anything about max_be, but we have min_be * So we assume the max_be default.
*/
devrec->hw->phy->supported.min_maxbe = 5;
devrec->hw->phy->supported.max_maxbe = 5;
devrec->regmap_short = devm_regmap_init_spi(spi,
&mrf24j40_short_regmap); if (IS_ERR(devrec->regmap_short)) {
ret = PTR_ERR(devrec->regmap_short);
dev_err(&spi->dev, "Failed to allocate short register map: %d\n",
ret); goto err_register_device;
}
devrec->regmap_long = devm_regmap_init(&spi->dev,
&mrf24j40_long_regmap_bus,
spi, &mrf24j40_long_regmap); if (IS_ERR(devrec->regmap_long)) {
ret = PTR_ERR(devrec->regmap_long);
dev_err(&spi->dev, "Failed to allocate long register map: %d\n",
ret); goto err_register_device;
}
if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) {
dev_warn(&spi->dev, "spi clock above possible maximum: %d",
MAX_SPI_SPEED_HZ);
ret = -EINVAL; goto err_register_device;
}
ret = mrf24j40_hw_init(devrec); if (ret) goto err_register_device;
mrf24j40_phy_setup(devrec);
/* request IRQF_TRIGGER_LOW as fallback default */
irq_type = irq_get_trigger_type(spi->irq); if (!irq_type)
irq_type = IRQF_TRIGGER_LOW;
ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr,
irq_type, dev_name(&spi->dev), devrec); if (ret) {
dev_err(printdev(devrec), "Unable to get IRQ"); goto err_register_device;
}
dev_dbg(printdev(devrec), "registered mrf24j40\n");
ret = ieee802154_register_hw(devrec->hw); if (ret) goto err_register_device;
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.