Commit 01b69614 authored by Hariprasad Shenai's avatar Hariprasad Shenai Committed by David S. Miller

cxgb4: Add PHY firmware support for T420-BT cards

Add support for flashing 10GBaseT adapter with BCM 84834 PHY and
Aquantia AQ1202 PHY.

Updating of the PHY firmware must happen before the INITIALIZE_CMD.
Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3b529602
......@@ -1101,6 +1101,19 @@ static inline int is_bypass_device(int device)
}
}
static inline int is_10gbt_device(int device)
{
/* this should be set based upon device capabilities */
switch (device) {
case 0x4409:
case 0x4486:
return 1;
default:
return 0;
}
}
static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
{
return adap->params.vpd.cclk / 1000;
......@@ -1123,9 +1136,19 @@ static inline unsigned int core_ticks_to_us(const struct adapter *adapter,
void t4_set_reg_field(struct adapter *adap, unsigned int addr, u32 mask,
u32 val);
int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
int size, void *rpl, bool sleep_ok, int timeout);
int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
void *rpl, bool sleep_ok);
static inline int t4_wr_mbox_timeout(struct adapter *adap, int mbox,
const void *cmd, int size, void *rpl,
int timeout)
{
return t4_wr_mbox_meat_timeout(adap, mbox, cmd, size, rpl, true,
timeout);
}
static inline int t4_wr_mbox(struct adapter *adap, int mbox, const void *cmd,
int size, void *rpl)
{
......@@ -1179,6 +1202,11 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p);
int t4_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t4_load_fw(struct adapter *adapter, const u8 *fw_data, unsigned int size);
int t4_load_phy_fw(struct adapter *adap,
int win, spinlock_t *lock,
int (*phy_fw_version)(const u8 *, size_t),
const u8 *phy_fw_data, size_t phy_fw_size);
int t4_phy_fw_ver(struct adapter *adap, int *phy_fw_ver);
int t4_fwcache(struct adapter *adap, enum fw_params_param_dev_fwcache op);
int t4_fw_upgrade(struct adapter *adap, unsigned int mbox,
const u8 *fw_data, unsigned int size, int force);
......@@ -1269,13 +1297,16 @@ int t4_fw_initialize(struct adapter *adap, unsigned int mbox);
int t4_query_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int nparams, const u32 *params,
u32 *val);
int t4_query_params_rw(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int nparams, const u32 *params,
u32 *val, int rw);
int t4_set_params_timeout(struct adapter *adap, unsigned int mbox,
unsigned int pf, unsigned int vf,
unsigned int nparams, const u32 *params,
const u32 *val, int timeout);
int t4_set_params(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int nparams, const u32 *params,
const u32 *val);
int t4_set_params_nosleep(struct adapter *adap, unsigned int mbox,
unsigned int pf, unsigned int vf,
unsigned int nparams, const u32 *params,
const u32 *val);
int t4_cfg_pfvf(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int txq, unsigned int txq_eth_ctrl,
unsigned int rxqi, unsigned int rxq, unsigned int tc,
......
......@@ -137,6 +137,10 @@ struct filter_entry {
#define FW5_FNAME "cxgb4/t5fw.bin"
#define FW4_CFNAME "cxgb4/t4-config.txt"
#define FW5_CFNAME "cxgb4/t5-config.txt"
#define PHY_AQ1202_FIRMWARE "cxgb4/aq1202_fw.cld"
#define PHY_BCM84834_FIRMWARE "cxgb4/bcm8483.bin"
#define PHY_AQ1202_DEVICEID 0x4409
#define PHY_BCM84834_DEVICEID 0x4486
MODULE_DESCRIPTION(DRV_DESC);
MODULE_AUTHOR("Chelsio Communications");
......@@ -318,8 +322,9 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable)
* level") we need to issue the Set Parameters Commannd
* without sleeping (timeout < 0).
*/
err = t4_set_params_nosleep(adap, adap->mbox, adap->fn, 0, 1,
&name, &value);
err = t4_set_params_timeout(adap, adap->mbox, adap->fn, 0, 1,
&name, &value,
-FW_CMD_MAX_TIMEOUT);
if (err)
dev_err(adap->pdev_dev,
......@@ -3222,6 +3227,142 @@ static int adap_init0_tweaks(struct adapter *adapter)
return 0;
}
/* 10Gb/s-BT PHY Support. chip-external 10Gb/s-BT PHYs are complex chips
* unto themselves and they contain their own firmware to perform their
* tasks ...
*/
static int phy_aq1202_version(const u8 *phy_fw_data,
size_t phy_fw_size)
{
int offset;
/* At offset 0x8 you're looking for the primary image's
* starting offset which is 3 Bytes wide
*
* At offset 0xa of the primary image, you look for the offset
* of the DRAM segment which is 3 Bytes wide.
*
* The FW version is at offset 0x27e of the DRAM and is 2 Bytes
* wide
*/
#define be16(__p) (((__p)[0] << 8) | (__p)[1])
#define le16(__p) ((__p)[0] | ((__p)[1] << 8))
#define le24(__p) (le16(__p) | ((__p)[2] << 16))
offset = le24(phy_fw_data + 0x8) << 12;
offset = le24(phy_fw_data + offset + 0xa);
return be16(phy_fw_data + offset + 0x27e);
#undef be16
#undef le16
#undef le24
}
static struct info_10gbt_phy_fw {
unsigned int phy_fw_id; /* PCI Device ID */
char *phy_fw_file; /* /lib/firmware/ PHY Firmware file */
int (*phy_fw_version)(const u8 *phy_fw_data, size_t phy_fw_size);
int phy_flash; /* Has FLASH for PHY Firmware */
} phy_info_array[] = {
{
PHY_AQ1202_DEVICEID,
PHY_AQ1202_FIRMWARE,
phy_aq1202_version,
1,
},
{
PHY_BCM84834_DEVICEID,
PHY_BCM84834_FIRMWARE,
NULL,
0,
},
{ 0, NULL, NULL },
};
static struct info_10gbt_phy_fw *find_phy_info(int devid)
{
int i;
for (i = 0; i < ARRAY_SIZE(phy_info_array); i++) {
if (phy_info_array[i].phy_fw_id == devid)
return &phy_info_array[i];
}
return NULL;
}
/* Handle updating of chip-external 10Gb/s-BT PHY firmware. This needs to
* happen after the FW_RESET_CMD but before the FW_INITIALIZE_CMD. On error
* we return a negative error number. If we transfer new firmware we return 1
* (from t4_load_phy_fw()). If we don't do anything we return 0.
*/
static int adap_init0_phy(struct adapter *adap)
{
const struct firmware *phyf;
int ret;
struct info_10gbt_phy_fw *phy_info;
/* Use the device ID to determine which PHY file to flash.
*/
phy_info = find_phy_info(adap->pdev->device);
if (!phy_info) {
dev_warn(adap->pdev_dev,
"No PHY Firmware file found for this PHY\n");
return -EOPNOTSUPP;
}
/* If we have a T4 PHY firmware file under /lib/firmware/cxgb4/, then
* use that. The adapter firmware provides us with a memory buffer
* where we can load a PHY firmware file from the host if we want to
* override the PHY firmware File in flash.
*/
ret = request_firmware_direct(&phyf, phy_info->phy_fw_file,
adap->pdev_dev);
if (ret < 0) {
/* For adapters without FLASH attached to PHY for their
* firmware, it's obviously a fatal error if we can't get the
* firmware to the adapter. For adapters with PHY firmware
* FLASH storage, it's worth a warning if we can't find the
* PHY Firmware but we'll neuter the error ...
*/
dev_err(adap->pdev_dev, "unable to find PHY Firmware image "
"/lib/firmware/%s, error %d\n",
phy_info->phy_fw_file, -ret);
if (phy_info->phy_flash) {
int cur_phy_fw_ver = 0;
t4_phy_fw_ver(adap, &cur_phy_fw_ver);
dev_warn(adap->pdev_dev, "continuing with, on-adapter "
"FLASH copy, version %#x\n", cur_phy_fw_ver);
ret = 0;
}
return ret;
}
/* Load PHY Firmware onto adapter.
*/
ret = t4_load_phy_fw(adap, MEMWIN_NIC, &adap->win0_lock,
phy_info->phy_fw_version,
(u8 *)phyf->data, phyf->size);
if (ret < 0)
dev_err(adap->pdev_dev, "PHY Firmware transfer error %d\n",
-ret);
else if (ret > 0) {
int new_phy_fw_ver = 0;
if (phy_info->phy_fw_version)
new_phy_fw_ver = phy_info->phy_fw_version(phyf->data,
phyf->size);
dev_info(adap->pdev_dev, "Successfully transferred PHY "
"Firmware /lib/firmware/%s, version %#x\n",
phy_info->phy_fw_file, new_phy_fw_ver);
}
release_firmware(phyf);
return ret;
}
/*
* Attempt to initialize the adapter via a Firmware Configuration File.
*/
......@@ -3246,6 +3387,16 @@ static int adap_init0_config(struct adapter *adapter, int reset)
goto bye;
}
/* If this is a 10Gb/s-BT adapter make sure the chip-external
* 10Gb/s-BT PHYs have up-to-date firmware. Note that this step needs
* to be performed after any global adapter RESET above since some
* PHYs only have local RAM copies of the PHY firmware.
*/
if (is_10gbt_device(adapter->pdev->device)) {
ret = adap_init0_phy(adapter);
if (ret < 0)
goto bye;
}
/*
* If we have a T4 configuration file under /lib/firmware/cxgb4/,
* then use that. Otherwise, use the configuration file stored
......
This diff is collapsed.
......@@ -1061,6 +1061,7 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
FW_PARAMS_PARAM_DEV_CF = 0x0D,
FW_PARAMS_PARAM_DEV_PHYFW = 0x0F,
FW_PARAMS_PARAM_DEV_DIAG = 0x11,
FW_PARAMS_PARAM_DEV_MAXORDIRD_QP = 0x13, /* max supported QP IRD/ORD */
FW_PARAMS_PARAM_DEV_MAXIRD_ADAPTER = 0x14, /* max supported adap IRD */
......@@ -1126,6 +1127,11 @@ enum fw_params_param_dmaq {
FW_PARAMS_PARAM_DMAQ_CONM_CTXT = 0x20,
};
enum fw_params_param_dev_phyfw {
FW_PARAMS_PARAM_DEV_PHYFW_DOWNLOAD = 0x00,
FW_PARAMS_PARAM_DEV_PHYFW_VERSION = 0x01,
};
enum fw_params_param_dev_diag {
FW_PARAM_DEV_DIAG_TMP = 0x00,
FW_PARAM_DEV_DIAG_VDD = 0x01,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment