/* Number of Interrupt Request Status Register */ #define MCR20A_IRQSTS_NUM 2 /* only IRQ_STS1 and IRQ_STS2 */
/* MCR20A CCA Type */ enum {
MCR20A_CCA_ED, // energy detect - CCA bit not active, // not to be used for T and CCCA sequences
MCR20A_CCA_MODE1, // energy detect - CCA bit ACTIVE
MCR20A_CCA_MODE2, // 802.15.4 compliant signal detect - CCA bit ACTIVE
MCR20A_CCA_MODE3
};
/* Type definitions for link configuration of instantiable layers */ #define MCR20A_PHY_INDIRECT_QUEUE_SIZE (12)
staticbool
mcr20a_dar_writeable(struct device *dev, unsignedint reg)
{ switch (reg) { case DAR_IRQ_STS1: case DAR_IRQ_STS2: case DAR_IRQ_STS3: case DAR_PHY_CTRL1: case DAR_PHY_CTRL2: case DAR_PHY_CTRL3: case DAR_PHY_CTRL4: case DAR_SRC_CTRL: case DAR_SRC_ADDRS_SUM_LSB: case DAR_SRC_ADDRS_SUM_MSB: case DAR_T3CMP_LSB: case DAR_T3CMP_MSB: case DAR_T3CMP_USB: case DAR_T2PRIMECMP_LSB: case DAR_T2PRIMECMP_MSB: case DAR_T1CMP_LSB: case DAR_T1CMP_MSB: case DAR_T1CMP_USB: case DAR_T2CMP_LSB: case DAR_T2CMP_MSB: case DAR_T2CMP_USB: case DAR_T4CMP_LSB: case DAR_T4CMP_MSB: case DAR_T4CMP_USB: case DAR_PLL_INT0: case DAR_PLL_FRAC0_LSB: case DAR_PLL_FRAC0_MSB: case DAR_PA_PWR: /* no DAR_ACM */ case DAR_OVERWRITE_VER: case DAR_CLK_OUT_CTRL: case DAR_PWR_MODES: returntrue; default: returnfalse;
}
}
/* all writeable are also readable */
rc = mcr20a_dar_writeable(dev, reg); if (rc) return rc;
/* readonly regs */ switch (reg) { case DAR_RX_FRM_LEN: case DAR_CCA1_ED_FNL: case DAR_EVENT_TMR_LSB: case DAR_EVENT_TMR_MSB: case DAR_EVENT_TMR_USB: case DAR_TIMESTAMP_LSB: case DAR_TIMESTAMP_MSB: case DAR_TIMESTAMP_USB: case DAR_SEQ_STATE: case DAR_LQI_VALUE: case DAR_RSSI_CCA_CONT: returntrue; default: returnfalse;
}
}
staticbool
mcr20a_dar_volatile(struct device *dev, unsignedint reg)
{ /* can be changed during runtime */ switch (reg) { case DAR_IRQ_STS1: case DAR_IRQ_STS2: case DAR_IRQ_STS3: /* use them in spi_async and regmap so it's volatile */ returntrue; default: returnfalse;
}
}
staticbool
mcr20a_dar_precious(struct device *dev, unsignedint reg)
{ /* don't clear irq line on read */ switch (reg) { case DAR_IRQ_STS1: case DAR_IRQ_STS2: case DAR_IRQ_STS3: returntrue; default: returnfalse;
}
}
staticbool
mcr20a_iar_writeable(struct device *dev, unsignedint reg)
{ switch (reg) { case IAR_XTAL_TRIM: case IAR_PMC_LP_TRIM: case IAR_MACPANID0_LSB: case IAR_MACPANID0_MSB: case IAR_MACSHORTADDRS0_LSB: case IAR_MACSHORTADDRS0_MSB: case IAR_MACLONGADDRS0_0: case IAR_MACLONGADDRS0_8: case IAR_MACLONGADDRS0_16: case IAR_MACLONGADDRS0_24: case IAR_MACLONGADDRS0_32: case IAR_MACLONGADDRS0_40: case IAR_MACLONGADDRS0_48: case IAR_MACLONGADDRS0_56: case IAR_RX_FRAME_FILTER: case IAR_PLL_INT1: case IAR_PLL_FRAC1_LSB: case IAR_PLL_FRAC1_MSB: case IAR_MACPANID1_LSB: case IAR_MACPANID1_MSB: case IAR_MACSHORTADDRS1_LSB: case IAR_MACSHORTADDRS1_MSB: case IAR_MACLONGADDRS1_0: case IAR_MACLONGADDRS1_8: case IAR_MACLONGADDRS1_16: case IAR_MACLONGADDRS1_24: case IAR_MACLONGADDRS1_32: case IAR_MACLONGADDRS1_40: case IAR_MACLONGADDRS1_48: case IAR_MACLONGADDRS1_56: case IAR_DUAL_PAN_CTRL: case IAR_DUAL_PAN_DWELL: case IAR_CCA1_THRESH: case IAR_CCA1_ED_OFFSET_COMP: case IAR_LQI_OFFSET_COMP: case IAR_CCA_CTRL: case IAR_CCA2_CORR_PEAKS: case IAR_CCA2_CORR_THRESH: case IAR_TMR_PRESCALE: case IAR_ANT_PAD_CTRL: case IAR_MISC_PAD_CTRL: case IAR_BSM_CTRL: case IAR_RNG: case IAR_RX_WTR_MARK: case IAR_SOFT_RESET: case IAR_TXDELAY: case IAR_ACKDELAY: case IAR_CORR_NVAL: case IAR_ANT_AGC_CTRL: case IAR_AGC_THR1: case IAR_AGC_THR2: case IAR_PA_CAL: case IAR_ATT_RSSI1: case IAR_ATT_RSSI2: case IAR_RSSI_OFFSET: case IAR_XTAL_CTRL: case IAR_CHF_PMA_GAIN: case IAR_CHF_IBUF: case IAR_CHF_QBUF: case IAR_CHF_IRIN: case IAR_CHF_QRIN: case IAR_CHF_IL: case IAR_CHF_QL: case IAR_CHF_CC1: case IAR_CHF_CCL: case IAR_CHF_CC2: case IAR_CHF_IROUT: case IAR_CHF_QROUT: case IAR_PA_TUNING: case IAR_VCO_CTRL1: case IAR_VCO_CTRL2: returntrue; default: returnfalse;
}
}
/* all writeable are also readable */
rc = mcr20a_iar_writeable(dev, reg); if (rc) return rc;
/* readonly regs */ switch (reg) { case IAR_PART_ID: case IAR_DUAL_PAN_STS: case IAR_RX_BYTE_COUNT: case IAR_FILTERFAIL_CODE1: case IAR_FILTERFAIL_CODE2: case IAR_RSSI: returntrue; default: returnfalse;
}
}
staticbool
mcr20a_iar_volatile(struct device *dev, unsignedint reg)
{ /* can be changed during runtime */ switch (reg) { case IAR_DUAL_PAN_STS: case IAR_RX_BYTE_COUNT: case IAR_FILTERFAIL_CODE1: case IAR_FILTERFAIL_CODE2: case IAR_RSSI: returntrue; default: returnfalse;
}
}
for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) { if (hw->phy->supported.cca_ed_levels[i] == mbm) return regmap_write(lp->regmap_iar, IAR_CCA1_THRESH, i);
}
/* Disable Tristate on COCO MISO for SPI reads */
ret = regmap_write(lp->regmap_iar, IAR_MISC_PAD_CTRL, 0x02); if (ret) goto err_ret;
/* Clear all PP IRQ bits in IRQSTS1 to avoid unexpected interrupts * immediately after init
*/
ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS1, 0xEF); if (ret) goto err_ret;
/* Clear all PP IRQ bits in IRQSTS2 */
ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS2,
DAR_IRQSTS2_ASM_IRQ | DAR_IRQSTS2_PB_ERR_IRQ |
DAR_IRQSTS2_WAKE_IRQ); if (ret) goto err_ret;
/* Disable all timer interrupts */
ret = regmap_write(lp->regmap_dar, DAR_IRQ_STS3, 0xFF); if (ret) goto err_ret;
/* Assign HW Indirect hash table to PAN0 */
ret = regmap_read(lp->regmap_iar, IAR_DUAL_PAN_CTRL, &phy_reg); if (ret) goto err_ret;
/* Clear current lvl */
phy_reg &= ~IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_MSK;
/* Set new lvl */
phy_reg |= MCR20A_PHY_INDIRECT_QUEUE_SIZE <<
IAR_DUAL_PAN_CTRL_DUAL_PAN_SAM_LVL_SHIFT;
ret = regmap_write(lp->regmap_iar, IAR_DUAL_PAN_CTRL, phy_reg); if (ret) goto err_ret;
/* Set CCA threshold to -75 dBm */
ret = regmap_write(lp->regmap_iar, IAR_CCA1_THRESH, 0x4B); if (ret) goto err_ret;
/* Set prescaller to obtain 1 symbol (16us) timebase */
ret = regmap_write(lp->regmap_iar, IAR_TMR_PRESCALE, 0x05); if (ret) goto err_ret;
/* Enable autodoze mode. */
ret = regmap_update_bits(lp->regmap_dar, DAR_PWR_MODES,
DAR_PWR_MODES_AUTODOZE,
DAR_PWR_MODES_AUTODOZE); if (ret) goto err_ret;
/* Disable clk_out */
ret = regmap_update_bits(lp->regmap_dar, DAR_CLK_OUT_CTRL,
DAR_CLK_OUT_CTRL_EN, 0x0); if (ret) goto err_ret;
return 0;
err_ret: return ret;
}
staticint
mcr20a_probe(struct spi_device *spi)
{ struct ieee802154_hw *hw; struct mcr20a_local *lp; struct gpio_desc *rst_b; int irq_type; int ret = -ENOMEM;
dev_dbg(&spi->dev, "%s\n", __func__);
if (!spi->irq) {
dev_err(&spi->dev, "no IRQ specified\n"); return -EINVAL;
}
rst_b = devm_gpiod_get(&spi->dev, "rst_b", GPIOD_OUT_HIGH); if (IS_ERR(rst_b)) return dev_err_probe(&spi->dev, PTR_ERR(rst_b), "Failed to get 'rst_b' gpio");
/* setup regmap */
lp->regmap_dar = devm_regmap_init_spi(spi, &mcr20a_dar_regmap); if (IS_ERR(lp->regmap_dar)) {
ret = PTR_ERR(lp->regmap_dar);
dev_err(&spi->dev, "Failed to allocate dar map: %d\n",
ret); goto free_dev;
}
lp->regmap_iar = devm_regmap_init_spi(spi, &mcr20a_iar_regmap); if (IS_ERR(lp->regmap_iar)) {
ret = PTR_ERR(lp->regmap_iar);
dev_err(&spi->dev, "Failed to allocate iar map: %d\n", ret); goto free_dev;
}
mcr20a_hw_setup(lp);
spi_set_drvdata(spi, lp);
ret = mcr20a_phy_init(lp); if (ret < 0) {
dev_crit(&spi->dev, "mcr20a_phy_init failed\n"); goto free_dev;
}
irq_type = irq_get_trigger_type(spi->irq); if (!irq_type)
irq_type = IRQF_TRIGGER_FALLING;
ret = devm_request_irq(&spi->dev, spi->irq, mcr20a_irq_isr,
irq_type | IRQF_NO_AUTOEN, dev_name(&spi->dev), lp); if (ret) {
dev_err(&spi->dev, "could not request_irq for mcr20a\n");
ret = -ENODEV; goto free_dev;
}
ret = ieee802154_register_hw(hw); if (ret) {
dev_crit(&spi->dev, "ieee802154_register_hw failed\n"); goto free_dev;
}
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.