int rssi_base_val;
int (*set_channel)(struct at86rf230_local *, u8, u8);
- int (*get_desense_steps)(struct at86rf230_local *, s32);
int (*set_txpower)(struct at86rf230_local *, s32);
};
return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
}
+#define AT86RF2XX_MAX_ED_LEVELS 0xF
+static const s32 at86rf23x_ed_levels[AT86RF2XX_MAX_ED_LEVELS + 1] = {
+ -9100, -8900, -8700, -8500, -8300, -8100, -7900, -7700, -7500, -7300,
+ -7100, -6900, -6700, -6500, -6300, -6100,
+};
+
+static const s32 at86rf212_ed_levels_100[AT86RF2XX_MAX_ED_LEVELS + 1] = {
+ -10000, -9800, -9600, -9400, -9200, -9000, -8800, -8600, -8400, -8200,
+ -8000, -7800, -7600, -7400, -7200,
+};
+
+static const s32 at86rf212_ed_levels_98[AT86RF2XX_MAX_ED_LEVELS + 1] = {
+ -9800, -9600, -9400, -9200, -9000, -8800, -8600, -8400, -8200, -8000,
+ -7800, -7600, -7400, -7200, -7000,
+};
+
+static inline int
+at86rf212_update_cca_ed_level(struct at86rf230_local *lp, int rssi_base_val)
+{
+ unsigned int cca_ed_thres;
+ int rc;
+
+ rc = at86rf230_read_subreg(lp, SR_CCA_ED_THRES, &cca_ed_thres);
+ if (rc < 0)
+ return rc;
+
+ switch (rssi_base_val) {
+ case -98:
+ lp->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_98;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_98);
+ lp->hw->phy->cca_ed_level = at86rf212_ed_levels_98[cca_ed_thres];
+ break;
+ case -100:
+ lp->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_100;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_100);
+ lp->hw->phy->cca_ed_level = at86rf212_ed_levels_100[cca_ed_thres];
+ break;
+ default:
+ WARN_ON(1);
+ }
+
+ return 0;
+}
+
static int
at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
{
if (rc < 0)
return rc;
+ rc = at86rf212_update_cca_ed_level(lp, lp->data->rssi_base_val);
+ if (rc < 0)
+ return rc;
+
/* This sets the symbol_duration according frequency on the 212.
* TODO move this handling while set channel and page in cfg802154.
* We can do that, this timings are according 802.15.4 standard.
return at86rf230_write_subreg(lp, SR_CCA_MODE, val);
}
-static int
-at86rf212_get_desens_steps(struct at86rf230_local *lp, s32 level)
-{
- return (level - lp->data->rssi_base_val) * 100 / 207;
-}
-
-static int
-at86rf23x_get_desens_steps(struct at86rf230_local *lp, s32 level)
-{
- return (level - lp->data->rssi_base_val) / 2;
-}
static int
at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
{
struct at86rf230_local *lp = hw->priv;
- s32 level = mbm / 100;
+ u32 i;
- if (level < lp->data->rssi_base_val || level > 30)
- return -EINVAL;
+ for (i = 0; i < hw->phy->supported.cca_ed_levels_size; i++) {
+ if (hw->phy->supported.cca_ed_levels[i] == mbm)
+ return at86rf230_write_subreg(lp, SR_CCA_ED_THRES, i);
+ }
- return at86rf230_write_subreg(lp, SR_CCA_ED_THRES,
- lp->data->get_desense_steps(lp, level));
+ return -EINVAL;
}
static int
.t_p_ack = 545,
.rssi_base_val = -91,
.set_channel = at86rf23x_set_channel,
- .get_desense_steps = at86rf23x_get_desens_steps,
.set_txpower = at86rf23x_set_txpower,
};
.t_p_ack = 545,
.rssi_base_val = -91,
.set_channel = at86rf23x_set_channel,
- .get_desense_steps = at86rf23x_get_desens_steps,
.set_txpower = at86rf23x_set_txpower,
};
.t_p_ack = 545,
.rssi_base_val = -100,
.set_channel = at86rf212_set_channel,
- .get_desense_steps = at86rf212_get_desens_steps,
.set_txpower = at86rf212_set_txpower,
};
lp->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND) |
BIT(NL802154_CCA_OPT_ENERGY_CARRIER_OR);
+ lp->hw->phy->supported.cca_ed_levels = at86rf23x_ed_levels;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf23x_ed_levels);
+
lp->hw->phy->cca.mode = NL802154_CCA_ENERGY;
switch (part) {
lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH;
lp->hw->phy->supported.tx_powers = at86rf212_powers;
lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers);
+ lp->hw->phy->supported.cca_ed_levels = at86rf212_ed_levels_100;
+ lp->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(at86rf212_ed_levels_100);
break;
case 11:
chip = "at86rf233";