2021-10-27 19:25:11

by Shayne Chen

[permalink] [raw]
Subject: [PATCH] mt76: mt7915: add default calibrated data support

Load the default eeprom data when the content of flash/efuse is invalid.
This could help to eliminate some issues due to incorrect or
insufficient rf values.

Co-developed-by: Bo Jiao <[email protected]>
Signed-off-by: Bo Jiao <[email protected]>
Signed-off-by: Shayne Chen <[email protected]>
Reviewed-by: Ryder Lee <[email protected]>
---
.../wireless/mediatek/mt76/mt7915/eeprom.c | 83 +++++++++++++++----
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 24 ++++++
.../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 +
.../wireless/mediatek/mt76/mt7915/mt7915.h | 4 +
4 files changed, 98 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index ee3d644..626ea4a 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: ISC
/* Copyright (C) 2020 MediaTek Inc. */

+#include <linux/firmware.h>
#include "mt7915.h"
#include "eeprom.h"

@@ -10,6 +11,9 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
u8 *eeprom = mdev->eeprom.data;
u32 val = eeprom[MT_EE_DO_PRE_CAL];

+ if (!dev->flash_mode)
+ return 0;
+
if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
return 0;

@@ -21,6 +25,49 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val);
}

+static int mt7915_check_eeprom(struct mt7915_dev *dev)
+{
+ u8 *eeprom = dev->mt76.eeprom.data;
+ u16 val = get_unaligned_le16(eeprom);
+
+ switch (val) {
+ case 0x7915:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int
+mt7915_eeprom_load_default(struct mt7915_dev *dev)
+{
+ char *default_bin = MT7915_EEPROM_DEFAULT;
+ u8 *eeprom = dev->mt76.eeprom.data;
+ const struct firmware *fw = NULL;
+ int ret;
+
+ if (dev->dbdc_support)
+ default_bin = MT7915_EEPROM_DEFAULT_DBDC;
+
+ ret = request_firmware(&fw, default_bin, dev->mt76.dev);
+ if (ret)
+ goto out;
+
+ if (!fw || !fw->data) {
+ dev_err(dev->mt76.dev, "Invalid default bin\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ memcpy(eeprom, fw->data, MT7915_EEPROM_SIZE);
+ dev->flash_mode = true;
+
+out:
+ release_firmware(fw);
+
+ return ret;
+}
+
static int mt7915_eeprom_load(struct mt7915_dev *dev)
{
int ret;
@@ -31,8 +78,8 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)

if (ret) {
dev->flash_mode = true;
- ret = mt7915_eeprom_load_precal(dev);
} else {
+ /* read eeprom data from efuse */
u32 block_num, i;

block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE,
@@ -42,20 +89,28 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
i * MT7915_EEPROM_BLOCK_SIZE);
}

- return ret;
-}
-
-static int mt7915_check_eeprom(struct mt7915_dev *dev)
-{
- u8 *eeprom = dev->mt76.eeprom.data;
- u16 val = get_unaligned_le16(eeprom);
+ if (!dev->flash_mode) {
+ u8 free_block_num;
+
+ mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
+ if (free_block_num >= 29) {
+ dev_warn(dev->mt76.dev,
+ "efuse info not enough, use default bin\n");
+ ret = mt7915_eeprom_load_default(dev);
+ if (ret)
+ return ret;
+ }
+ }

- switch (val) {
- case 0x7915:
- return 0;
- default:
- return -EINVAL;
+ ret = mt7915_check_eeprom(dev);
+ if (ret) {
+ dev_warn(dev->mt76.dev, "eeprom check fail, use default bin\n");
+ ret = mt7915_eeprom_load_default(dev);
+ if (ret)
+ return ret;
}
+
+ return ret;
}

void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
@@ -120,7 +175,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
if (ret < 0)
return ret;

- ret = mt7915_check_eeprom(dev);
+ ret = mt7915_eeprom_load_precal(dev);
if (ret)
return ret;

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index b054663..ee9952d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3580,6 +3580,30 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
return 0;
}

+int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num)
+{
+ struct {
+ u8 _rsv;
+ u8 version;
+ u8 die_idx;
+ u8 _rsv2;
+ } __packed req = {
+ .version = 1,
+ };
+ struct sk_buff *skb;
+ int ret;
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_FREE_BLOCK), &req,
+ sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ *block_num = *(u8 *)skb->data;
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
u8 *data, u32 len, int cmd)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index b563e7c..e9f39ed 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -278,6 +278,7 @@ enum {
MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a,
MCU_EXT_CMD_SET_RX_PATH = 0x4e,
+ MCU_EXT_CMD_EFUSE_FREE_BLOCK = 0x4f,
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index e69b4c8..c6c846d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -30,6 +30,9 @@
#define MT7915_FIRMWARE_WM "mediatek/mt7915_wm.bin"
#define MT7915_ROM_PATCH "mediatek/mt7915_rom_patch.bin"

+#define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin"
+#define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin"
+
#define MT7915_EEPROM_SIZE 3584
#define MT7915_EEPROM_BLOCK_SIZE 16
#define MT7915_TOKEN_SIZE 8192
@@ -423,6 +426,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
void *data, u32 field);
int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
+int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
bool hdr_trans);
int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
--
2.25.1


2021-10-28 08:49:09

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH] mt76: mt7915: add default calibrated data support

> Load the default eeprom data when the content of flash/efuse is invalid.
> This could help to eliminate some issues due to incorrect or
> insufficient rf values.
>
> Co-developed-by: Bo Jiao <[email protected]>
> Signed-off-by: Bo Jiao <[email protected]>
> Signed-off-by: Shayne Chen <[email protected]>
> Reviewed-by: Ryder Lee <[email protected]>
> ---
> .../wireless/mediatek/mt76/mt7915/eeprom.c | 83 +++++++++++++++----
> .../net/wireless/mediatek/mt76/mt7915/mcu.c | 24 ++++++
> .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 +
> .../wireless/mediatek/mt76/mt7915/mt7915.h | 4 +
> 4 files changed, 98 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> index ee3d644..626ea4a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: ISC
> /* Copyright (C) 2020 MediaTek Inc. */
>
> +#include <linux/firmware.h>
> #include "mt7915.h"
> #include "eeprom.h"
>
> @@ -10,6 +11,9 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
> u8 *eeprom = mdev->eeprom.data;
> u32 val = eeprom[MT_EE_DO_PRE_CAL];
>
> + if (!dev->flash_mode)
> + return 0;
> +
> if (val != (MT_EE_WIFI_CAL_DPD | MT_EE_WIFI_CAL_GROUP))
> return 0;
>
> @@ -21,6 +25,49 @@ static int mt7915_eeprom_load_precal(struct mt7915_dev *dev)
> return mt76_get_of_eeprom(mdev, dev->cal, MT_EE_PRECAL, val);
> }
>
> +static int mt7915_check_eeprom(struct mt7915_dev *dev)
> +{
> + u8 *eeprom = dev->mt76.eeprom.data;
> + u16 val = get_unaligned_le16(eeprom);
> +
> + switch (val) {
> + case 0x7915:
> + return 0;
> + default:
> + return -EINVAL;
> + }
> +}
> +
> +static int
> +mt7915_eeprom_load_default(struct mt7915_dev *dev)
> +{
> + char *default_bin = MT7915_EEPROM_DEFAULT;
> + u8 *eeprom = dev->mt76.eeprom.data;
> + const struct firmware *fw = NULL;
> + int ret;
> +
> + if (dev->dbdc_support)
> + default_bin = MT7915_EEPROM_DEFAULT_DBDC;
> +
> + ret = request_firmware(&fw, default_bin, dev->mt76.dev);
> + if (ret)
> + goto out;

nit: you can just drop goto and return ret here

> +
> + if (!fw || !fw->data) {
> + dev_err(dev->mt76.dev, "Invalid default bin\n");
> + ret = -EINVAL;
> + goto out;
> + }
> +
> + memcpy(eeprom, fw->data, MT7915_EEPROM_SIZE);
> + dev->flash_mode = true;
> +
> +out:
> + release_firmware(fw);
> +
> + return ret;
> +}
> +
> static int mt7915_eeprom_load(struct mt7915_dev *dev)
> {
> int ret;
> @@ -31,8 +78,8 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
>
> if (ret) {
> dev->flash_mode = true;
> - ret = mt7915_eeprom_load_precal(dev);
> } else {
> + /* read eeprom data from efuse */
> u32 block_num, i;
>
> block_num = DIV_ROUND_UP(MT7915_EEPROM_SIZE,
> @@ -42,20 +89,28 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
> i * MT7915_EEPROM_BLOCK_SIZE);
> }
>
> - return ret;
> -}
> -
> -static int mt7915_check_eeprom(struct mt7915_dev *dev)
> -{
> - u8 *eeprom = dev->mt76.eeprom.data;
> - u16 val = get_unaligned_le16(eeprom);
> + if (!dev->flash_mode) {
> + u8 free_block_num;
> +
> + mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
> + if (free_block_num >= 29) {
> + dev_warn(dev->mt76.dev,
> + "efuse info not enough, use default bin\n");
> + ret = mt7915_eeprom_load_default(dev);
> + if (ret)
> + return ret;
> + }
> + }
>
> - switch (val) {
> - case 0x7915:
> - return 0;
> - default:
> - return -EINVAL;
> + ret = mt7915_check_eeprom(dev);
> + if (ret) {
> + dev_warn(dev->mt76.dev, "eeprom check fail, use default bin\n");
> + ret = mt7915_eeprom_load_default(dev);
> + if (ret)
> + return ret;

nit: drop return here or just return 0 at the end

> }
> +
> + return ret;
> }
>
> void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
> @@ -120,7 +175,7 @@ int mt7915_eeprom_init(struct mt7915_dev *dev)
> if (ret < 0)
> return ret;
>
> - ret = mt7915_check_eeprom(dev);
> + ret = mt7915_eeprom_load_precal(dev);
> if (ret)
> return ret;
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> index b054663..ee9952d 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
> @@ -3580,6 +3580,30 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
> return 0;
> }
>
> +int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num)
> +{
> + struct {
> + u8 _rsv;
> + u8 version;
> + u8 die_idx;
> + u8 _rsv2;
> + } __packed req = {
> + .version = 1,
> + };
> + struct sk_buff *skb;
> + int ret;
> +
> + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_QUERY(EFUSE_FREE_BLOCK), &req,
> + sizeof(req), true, &skb);
> + if (ret)
> + return ret;
> +
> + *block_num = *(u8 *)skb->data;
> + dev_kfree_skb(skb);
> +
> + return 0;
> +}
> +
> static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
> u8 *data, u32 len, int cmd)
> {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> index b563e7c..e9f39ed 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
> @@ -278,6 +278,7 @@ enum {
> MCU_EXT_CMD_MUAR_UPDATE = 0x48,
> MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a,
> MCU_EXT_CMD_SET_RX_PATH = 0x4e,
> + MCU_EXT_CMD_EFUSE_FREE_BLOCK = 0x4f,
> MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
> MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
> MCU_EXT_CMD_MWDS_SUPPORT = 0x80,
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> index e69b4c8..c6c846d 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
> @@ -30,6 +30,9 @@
> #define MT7915_FIRMWARE_WM "mediatek/mt7915_wm.bin"
> #define MT7915_ROM_PATCH "mediatek/mt7915_rom_patch.bin"
>
> +#define MT7915_EEPROM_DEFAULT "mediatek/mt7915_eeprom.bin"
> +#define MT7915_EEPROM_DEFAULT_DBDC "mediatek/mt7915_eeprom_dbdc.bin"
> +
> #define MT7915_EEPROM_SIZE 3584
> #define MT7915_EEPROM_BLOCK_SIZE 16
> #define MT7915_TOKEN_SIZE 8192
> @@ -423,6 +426,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
> void *data, u32 field);
> int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
> int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
> +int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
> int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
> bool hdr_trans);
> int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_mode,
> --
> 2.25.1
>


Attachments:
(No filename) (6.94 kB)
signature.asc (235.00 B)
Download all attachments

2021-10-29 00:56:38

by Julian Calaby

[permalink] [raw]
Subject: Re: [PATCH] mt76: mt7915: add default calibrated data support

Hi Shayne,

On Thu, Oct 28, 2021 at 6:25 AM Shayne Chen <[email protected]> wrote:
>
> Load the default eeprom data when the content of flash/efuse is invalid.
> This could help to eliminate some issues due to incorrect or
> insufficient rf values.
>
> Co-developed-by: Bo Jiao <[email protected]>
> Signed-off-by: Bo Jiao <[email protected]>
> Signed-off-by: Shayne Chen <[email protected]>
> Reviewed-by: Ryder Lee <[email protected]>
> ---
> .../wireless/mediatek/mt76/mt7915/eeprom.c | 83 +++++++++++++++----
> .../net/wireless/mediatek/mt76/mt7915/mcu.c | 24 ++++++
> .../net/wireless/mediatek/mt76/mt7915/mcu.h | 1 +
> .../wireless/mediatek/mt76/mt7915/mt7915.h | 4 +
> 4 files changed, 98 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> index ee3d644..626ea4a 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
> @@ -42,20 +89,28 @@ static int mt7915_eeprom_load(struct mt7915_dev *dev)
> i * MT7915_EEPROM_BLOCK_SIZE);
> }
>
> - return ret;
> -}
> -
> -static int mt7915_check_eeprom(struct mt7915_dev *dev)
> -{
> - u8 *eeprom = dev->mt76.eeprom.data;
> - u16 val = get_unaligned_le16(eeprom);
> + if (!dev->flash_mode) {
> + u8 free_block_num;
> +
> + mt7915_mcu_get_eeprom_free_block(dev, &free_block_num);
> + if (free_block_num >= 29) {
> + dev_warn(dev->mt76.dev,
> + "efuse info not enough, use default bin\n");
> + ret = mt7915_eeprom_load_default(dev);
> + if (ret)
> + return ret;

You've got two instances of the code where it tries to load the
default if the EEPROM data isn't valid.

You could potentially simplify this by structuring the code that calls
this function so it's something like:

ret = mt7915_eeprom_load();

if (!ret) {
ret = mt7915_eeprom_load_default();
}

return ret;

with mt7915_eeprom_load() just returning -EINVAL if the EEPROM
contents aren't valid instead of trying to fix it itself.

This would also make the code simpler if there ends up being another
way to get EEPROM data in the future, e.g. an NVRAM partition
referenced through the device tree, etc.

> + }
> + }
>
> - switch (val) {
> - case 0x7915:
> - return 0;
> - default:
> - return -EINVAL;
> + ret = mt7915_check_eeprom(dev);
> + if (ret) {
> + dev_warn(dev->mt76.dev, "eeprom check fail, use default bin\n");
> + ret = mt7915_eeprom_load_default(dev);
> + if (ret)
> + return ret;
> }
> +
> + return ret;
> }
>
> void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)

Thanks,

--
Julian Calaby

Email: [email protected]
Profile: http://www.google.com/profiles/julian.calaby/