mrf24j40: add tx power support
authorAlexander Aring <alex.aring@gmail.com>
Mon, 21 Sep 2015 09:24:40 +0000 (11:24 +0200)
committerMarcel Holtmann <marcel@holtmann.org>
Tue, 22 Sep 2015 09:51:23 +0000 (11:51 +0200)
This patch supports setting of transmit power for the mrf24j40ma
transceiver only. The mrf24j40mc has some amplifier to change the
transmit power, I am currently not sure how the mapping for this
amplifier looks like.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
drivers/net/ieee802154/mrf24j40.c

index c23936e3dd4f1d4d320416fce6fe47a9298d3aa4..91687c1a56ce73786bacd366fd60669e4a49ed22 100644 (file)
@@ -864,6 +864,65 @@ static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
        return -EINVAL;
 }
 
+static const s32 mrf24j40ma_powers[] = {
+       0, -50, -120, -190, -280, -370, -490, -630, -1000, -1050, -1120, -1190,
+       -1280, -1370, -1490, -1630, -2000, -2050, -2120, -2190, -2280, -2370,
+       -2490, -2630, -3000, -3050, -3120, -3190, -3280, -3370, -3490, -3630,
+};
+
+static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm)
+{
+       struct mrf24j40 *devrec = hw->priv;
+       s32 small_scale;
+       u8 val;
+
+       if (0 >= mbm && mbm > -1000) {
+               val = 0;
+               small_scale = mbm;
+       } else if (-1000 >= mbm && mbm > -2000) {
+               val = 0x40;
+               small_scale = mbm + 1000;
+       } else if (-2000 >= mbm && mbm > -3000) {
+               val = 0x80;
+               small_scale = mbm + 2000;
+       } else if (-3000 >= mbm && mbm > -4000) {
+               val = 0xc0;
+               small_scale = mbm + 3000;
+       } else {
+               return -EINVAL;
+       }
+
+       switch (small_scale) {
+       case 0:
+               break;
+       case -50:
+               val |= 0x08;
+               break;
+       case -120:
+               val |= 0x10;
+               break;
+       case -190:
+               val |= 0x18;
+               break;
+       case -280:
+               val |= 0x20;
+               break;
+       case -370:
+               val |= 0x28;
+               break;
+       case -490:
+               val |= 0x30;
+               break;
+       case -630:
+               val |= 0x38;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(devrec->regmap_long, REG_RFCON3, 0xf8, val);
+}
+
 static const struct ieee802154_ops mrf24j40_ops = {
        .owner = THIS_MODULE,
        .xmit_async = mrf24j40_tx,
@@ -875,6 +934,7 @@ static const struct ieee802154_ops mrf24j40_ops = {
        .set_csma_params = mrf24j40_csma_params,
        .set_cca_mode = mrf24j40_set_cca_mode,
        .set_cca_ed_level = mrf24j40_set_cca_ed_level,
+       .set_txpower = mrf24j40_set_txpower,
 };
 
 static void mrf24j40_intstat_complete(void *context)
@@ -1088,6 +1148,17 @@ static void  mrf24j40_phy_setup(struct mrf24j40 *devrec)
        devrec->hw->phy->cca_ed_level = -6900;
        devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels;
        devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels);
+
+       switch (spi_get_device_id(devrec->spi)->driver_data) {
+       case MRF24J40:
+       case MRF24J40MA:
+               devrec->hw->phy->supported.tx_powers = mrf24j40ma_powers;
+               devrec->hw->phy->supported.tx_powers_size = ARRAY_SIZE(mrf24j40ma_powers);
+               devrec->hw->phy->flags |= WPAN_PHY_FLAG_TXPOWER;
+               break;
+       default:
+               break;
+       }
 }
 
 static int mrf24j40_probe(struct spi_device *spi)