Skip to content

Commit af14288

Browse files
hayesorzJakub Kicinski
authored andcommitted
r8152: support firmware of PHY NC for RTL8153A
Support the firmware of PHY NC which is used to fix the issue found for PHY. Currently, only RTL_VER_04, RTL_VER_05, and RTL_VER_06 need it. The order of loading PHY firmware would be RTL_FW_PHY_START RTL_FW_PHY_NC RTL_FW_PHY_STOP The RTL_FW_PHY_START/RTL_FW_PHY_STOP are used to lock/unlock the PHY, and set/clear the patch key from the firmware file. Signed-off-by: Hayes Wang <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 470e391 commit af14288

File tree

1 file changed

+282
-2
lines changed

1 file changed

+282
-2
lines changed

drivers/net/usb/r8152.c

Lines changed: 282 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
#define OCP_PHY_STATE 0xa708 /* nway state for 8153 */
188188
#define OCP_PHY_PATCH_STAT 0xb800
189189
#define OCP_PHY_PATCH_CMD 0xb820
190+
#define OCP_PHY_LOCK 0xb82e
190191
#define OCP_ADC_IOFFSET 0xbcfc
191192
#define OCP_ADC_CFG 0xbc06
192193
#define OCP_SYSCLK_CFG 0xc416
@@ -197,6 +198,7 @@
197198
#define SRAM_10M_AMP1 0x8080
198199
#define SRAM_10M_AMP2 0x8082
199200
#define SRAM_IMPEDANCE 0x8084
201+
#define SRAM_PHY_LOCK 0xb82e
200202

201203
/* PLA_RCR */
202204
#define RCR_AAP 0x00000001
@@ -577,6 +579,9 @@ enum spd_duplex {
577579
/* OCP_PHY_PATCH_CMD */
578580
#define PATCH_REQUEST BIT(4)
579581

582+
/* OCP_PHY_LOCK */
583+
#define PATCH_LOCK BIT(0)
584+
580585
/* OCP_ADC_CFG */
581586
#define CKADSEL_L 0x0100
582587
#define ADC_EN 0x0080
@@ -601,6 +606,9 @@ enum spd_duplex {
601606
/* SRAM_IMPEDANCE */
602607
#define RX_DRIVING_MASK 0x6000
603608

609+
/* SRAM_PHY_LOCK */
610+
#define PHY_PATCH_LOCK 0x0001
611+
604612
/* MAC PASSTHRU */
605613
#define AD_MASK 0xfee0
606614
#define BND_MASK 0x0004
@@ -905,10 +913,65 @@ struct fw_mac {
905913
char info[0];
906914
} __packed;
907915

916+
/**
917+
* struct fw_phy_patch_key - a firmware block used by RTL_FW_PHY_START.
918+
* This is used to set patch key when loading the firmware of PHY.
919+
* @key_reg: the register to write the patch key.
920+
* @key_data: patch key.
921+
*/
922+
struct fw_phy_patch_key {
923+
struct fw_block blk_hdr;
924+
__le16 key_reg;
925+
__le16 key_data;
926+
__le32 reserved;
927+
} __packed;
928+
929+
/**
930+
* struct fw_phy_nc - a firmware block used by RTL_FW_PHY_NC.
931+
* The layout of the firmware block is:
932+
* <struct fw_phy_nc> + <info> + <firmware data>.
933+
* @fw_offset: offset of the firmware binary data. The start address of
934+
* the data would be the address of struct fw_phy_nc + @fw_offset.
935+
* @fw_reg: the register to load the firmware. Depends on chip.
936+
* @ba_reg: the register to write the base address. Depends on chip.
937+
* @ba_data: base address. Depends on chip.
938+
* @patch_en_addr: the register of enabling patch mode. Depends on chip.
939+
* @patch_en_value: patch mode enabled mask. Depends on the firmware.
940+
* @mode_reg: the regitster of switching the mode.
941+
* @mod_pre: the mode needing to be set before loading the firmware.
942+
* @mod_post: the mode to be set when finishing to load the firmware.
943+
* @bp_start: the start register of break points. Depends on chip.
944+
* @bp_num: the break point number which needs to be set for this firmware.
945+
* Depends on the firmware.
946+
* @bp: break points. Depends on firmware.
947+
* @info: additional information for debugging, and is followed by the
948+
* binary data of firmware.
949+
*/
950+
struct fw_phy_nc {
951+
struct fw_block blk_hdr;
952+
__le16 fw_offset;
953+
__le16 fw_reg;
954+
__le16 ba_reg;
955+
__le16 ba_data;
956+
__le16 patch_en_addr;
957+
__le16 patch_en_value;
958+
__le16 mode_reg;
959+
__le16 mode_pre;
960+
__le16 mode_post;
961+
__le16 reserved;
962+
__le16 bp_start;
963+
__le16 bp_num;
964+
__le16 bp[4];
965+
char info[0];
966+
} __packed;
967+
908968
enum rtl_fw_type {
909969
RTL_FW_END = 0,
910970
RTL_FW_PLA,
911971
RTL_FW_USB,
972+
RTL_FW_PHY_START,
973+
RTL_FW_PHY_STOP,
974+
RTL_FW_PHY_NC,
912975
};
913976

914977
enum rtl_version {
@@ -3424,6 +3487,114 @@ static int r8153_patch_request(struct r8152 *tp, bool request)
34243487
}
34253488
}
34263489

3490+
static int r8153_pre_ram_code(struct r8152 *tp, u16 key_addr, u16 patch_key)
3491+
{
3492+
if (r8153_patch_request(tp, true)) {
3493+
dev_err(&tp->intf->dev, "patch request fail\n");
3494+
return -ETIME;
3495+
}
3496+
3497+
sram_write(tp, key_addr, patch_key);
3498+
sram_write(tp, SRAM_PHY_LOCK, PHY_PATCH_LOCK);
3499+
3500+
return 0;
3501+
}
3502+
3503+
static int r8153_post_ram_code(struct r8152 *tp, u16 key_addr)
3504+
{
3505+
u16 data;
3506+
3507+
sram_write(tp, 0x0000, 0x0000);
3508+
3509+
data = ocp_reg_read(tp, OCP_PHY_LOCK);
3510+
data &= ~PATCH_LOCK;
3511+
ocp_reg_write(tp, OCP_PHY_LOCK, data);
3512+
3513+
sram_write(tp, key_addr, 0x0000);
3514+
3515+
r8153_patch_request(tp, false);
3516+
3517+
ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, tp->ocp_base);
3518+
3519+
return 0;
3520+
}
3521+
3522+
static bool rtl8152_is_fw_phy_nc_ok(struct r8152 *tp, struct fw_phy_nc *phy)
3523+
{
3524+
u32 length;
3525+
u16 fw_offset, fw_reg, ba_reg, patch_en_addr, mode_reg, bp_start;
3526+
bool rc = false;
3527+
3528+
switch (tp->version) {
3529+
case RTL_VER_04:
3530+
case RTL_VER_05:
3531+
case RTL_VER_06:
3532+
fw_reg = 0xa014;
3533+
ba_reg = 0xa012;
3534+
patch_en_addr = 0xa01a;
3535+
mode_reg = 0xb820;
3536+
bp_start = 0xa000;
3537+
break;
3538+
default:
3539+
goto out;
3540+
}
3541+
3542+
fw_offset = __le16_to_cpu(phy->fw_offset);
3543+
if (fw_offset < sizeof(*phy)) {
3544+
dev_err(&tp->intf->dev, "fw_offset too small\n");
3545+
goto out;
3546+
}
3547+
3548+
length = __le32_to_cpu(phy->blk_hdr.length);
3549+
if (length < fw_offset) {
3550+
dev_err(&tp->intf->dev, "invalid fw_offset\n");
3551+
goto out;
3552+
}
3553+
3554+
length -= __le16_to_cpu(phy->fw_offset);
3555+
if (!length || (length & 1)) {
3556+
dev_err(&tp->intf->dev, "invalid block length\n");
3557+
goto out;
3558+
}
3559+
3560+
if (__le16_to_cpu(phy->fw_reg) != fw_reg) {
3561+
dev_err(&tp->intf->dev, "invalid register to load firmware\n");
3562+
goto out;
3563+
}
3564+
3565+
if (__le16_to_cpu(phy->ba_reg) != ba_reg) {
3566+
dev_err(&tp->intf->dev, "invalid base address register\n");
3567+
goto out;
3568+
}
3569+
3570+
if (__le16_to_cpu(phy->patch_en_addr) != patch_en_addr) {
3571+
dev_err(&tp->intf->dev,
3572+
"invalid patch mode enabled register\n");
3573+
goto out;
3574+
}
3575+
3576+
if (__le16_to_cpu(phy->mode_reg) != mode_reg) {
3577+
dev_err(&tp->intf->dev,
3578+
"invalid register to switch the mode\n");
3579+
goto out;
3580+
}
3581+
3582+
if (__le16_to_cpu(phy->bp_start) != bp_start) {
3583+
dev_err(&tp->intf->dev,
3584+
"invalid start register of break point\n");
3585+
goto out;
3586+
}
3587+
3588+
if (__le16_to_cpu(phy->bp_num) > 4) {
3589+
dev_err(&tp->intf->dev, "invalid break point number\n");
3590+
goto out;
3591+
}
3592+
3593+
rc = true;
3594+
out:
3595+
return rc;
3596+
}
3597+
34273598
static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
34283599
{
34293600
u16 fw_reg, bp_ba_addr, bp_en_addr, bp_start, fw_offset;
@@ -3600,6 +3771,9 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw)
36003771
const struct firmware *fw = rtl_fw->fw;
36013772
struct fw_header *fw_hdr = (struct fw_header *)fw->data;
36023773
struct fw_mac *pla = NULL, *usb = NULL;
3774+
struct fw_phy_patch_key *start = NULL;
3775+
struct fw_phy_nc *phy_nc = NULL;
3776+
struct fw_block *stop = NULL;
36033777
long ret = -EFAULT;
36043778
int i;
36053779

@@ -3626,7 +3800,7 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw)
36263800
case RTL_FW_END:
36273801
if (__le32_to_cpu(block->length) != sizeof(*block))
36283802
goto fail;
3629-
goto success;
3803+
goto fw_end;
36303804
case RTL_FW_PLA:
36313805
if (pla) {
36323806
dev_err(&tp->intf->dev,
@@ -3654,6 +3828,57 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw)
36543828
"check USB firmware failed\n");
36553829
goto fail;
36563830
}
3831+
break;
3832+
case RTL_FW_PHY_START:
3833+
if (start || phy_nc || stop) {
3834+
dev_err(&tp->intf->dev,
3835+
"check PHY_START fail\n");
3836+
goto fail;
3837+
}
3838+
3839+
if (__le32_to_cpu(block->length) != sizeof(*start)) {
3840+
dev_err(&tp->intf->dev,
3841+
"Invalid length for PHY_START\n");
3842+
goto fail;
3843+
}
3844+
3845+
start = (struct fw_phy_patch_key *)block;
3846+
break;
3847+
case RTL_FW_PHY_STOP:
3848+
if (stop || !start) {
3849+
dev_err(&tp->intf->dev,
3850+
"Check PHY_STOP fail\n");
3851+
goto fail;
3852+
}
3853+
3854+
if (__le32_to_cpu(block->length) != sizeof(*block)) {
3855+
dev_err(&tp->intf->dev,
3856+
"Invalid length for PHY_STOP\n");
3857+
goto fail;
3858+
}
3859+
3860+
stop = block;
3861+
break;
3862+
case RTL_FW_PHY_NC:
3863+
if (!start || stop) {
3864+
dev_err(&tp->intf->dev,
3865+
"check PHY_NC fail\n");
3866+
goto fail;
3867+
}
3868+
3869+
if (phy_nc) {
3870+
dev_err(&tp->intf->dev,
3871+
"multiple PHY NC encountered\n");
3872+
goto fail;
3873+
}
3874+
3875+
phy_nc = (struct fw_phy_nc *)block;
3876+
if (!rtl8152_is_fw_phy_nc_ok(tp, phy_nc)) {
3877+
dev_err(&tp->intf->dev,
3878+
"check PHY NC firmware failed\n");
3879+
goto fail;
3880+
}
3881+
36573882
break;
36583883
default:
36593884
dev_warn(&tp->intf->dev, "Unknown type %u is found\n",
@@ -3665,12 +3890,52 @@ static long rtl8152_check_firmware(struct r8152 *tp, struct rtl_fw *rtl_fw)
36653890
i += ALIGN(__le32_to_cpu(block->length), 8);
36663891
}
36673892

3668-
success:
3893+
fw_end:
3894+
if ((phy_nc || start) && !stop) {
3895+
dev_err(&tp->intf->dev, "without PHY_STOP\n");
3896+
goto fail;
3897+
}
3898+
36693899
return 0;
36703900
fail:
36713901
return ret;
36723902
}
36733903

3904+
static void rtl8152_fw_phy_nc_apply(struct r8152 *tp, struct fw_phy_nc *phy)
3905+
{
3906+
u16 mode_reg, bp_index;
3907+
u32 length, i, num;
3908+
__le16 *data;
3909+
3910+
mode_reg = __le16_to_cpu(phy->mode_reg);
3911+
sram_write(tp, mode_reg, __le16_to_cpu(phy->mode_pre));
3912+
sram_write(tp, __le16_to_cpu(phy->ba_reg),
3913+
__le16_to_cpu(phy->ba_data));
3914+
3915+
length = __le32_to_cpu(phy->blk_hdr.length);
3916+
length -= __le16_to_cpu(phy->fw_offset);
3917+
num = length / 2;
3918+
data = (__le16 *)((u8 *)phy + __le16_to_cpu(phy->fw_offset));
3919+
3920+
ocp_reg_write(tp, OCP_SRAM_ADDR, __le16_to_cpu(phy->fw_reg));
3921+
for (i = 0; i < num; i++)
3922+
ocp_reg_write(tp, OCP_SRAM_DATA, __le16_to_cpu(data[i]));
3923+
3924+
sram_write(tp, __le16_to_cpu(phy->patch_en_addr),
3925+
__le16_to_cpu(phy->patch_en_value));
3926+
3927+
bp_index = __le16_to_cpu(phy->bp_start);
3928+
num = __le16_to_cpu(phy->bp_num);
3929+
for (i = 0; i < num; i++) {
3930+
sram_write(tp, bp_index, __le16_to_cpu(phy->bp[i]));
3931+
bp_index += 2;
3932+
}
3933+
3934+
sram_write(tp, mode_reg, __le16_to_cpu(phy->mode_post));
3935+
3936+
dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info);
3937+
}
3938+
36743939
static void rtl8152_fw_mac_apply(struct r8152 *tp, struct fw_mac *mac)
36753940
{
36763941
u16 bp_en_addr, bp_index, type, bp_num, fw_ver_reg;
@@ -3737,6 +4002,8 @@ static void rtl8152_apply_firmware(struct r8152 *tp)
37374002
struct rtl_fw *rtl_fw = &tp->rtl_fw;
37384003
const struct firmware *fw = rtl_fw->fw;
37394004
struct fw_header *fw_hdr = (struct fw_header *)fw->data;
4005+
struct fw_phy_patch_key *key;
4006+
u16 key_addr = 0;
37404007
int i;
37414008

37424009
if (IS_ERR_OR_NULL(rtl_fw->fw))
@@ -3755,6 +4022,19 @@ static void rtl8152_apply_firmware(struct r8152 *tp)
37554022
case RTL_FW_USB:
37564023
rtl8152_fw_mac_apply(tp, (struct fw_mac *)block);
37574024
break;
4025+
case RTL_FW_PHY_START:
4026+
key = (struct fw_phy_patch_key *)block;
4027+
key_addr = __le16_to_cpu(key->key_reg);
4028+
r8153_pre_ram_code(tp, key_addr,
4029+
__le16_to_cpu(key->key_data));
4030+
break;
4031+
case RTL_FW_PHY_STOP:
4032+
WARN_ON(!key_addr);
4033+
r8153_post_ram_code(tp, key_addr);
4034+
break;
4035+
case RTL_FW_PHY_NC:
4036+
rtl8152_fw_phy_nc_apply(tp, (struct fw_phy_nc *)block);
4037+
break;
37584038
default:
37594039
break;
37604040
}

0 commit comments

Comments
 (0)