mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
synced 2024-12-17 20:55:27 +00:00
firmware/isci: update to oem parameter format v1.3
v1.1 allows finer grained tuning of the SSC (spread-spectrum-clocking) settings for SAS and SATA. See notes in probe_roms.h v1.3 allows the attenuation of the attached cables to be specified to the driver in terms of 'short', 'medium', and 'long' (see probe_roms.h). These settings (per phy) are retrieved from the platform oem-parameters (BIOS rom), the fallback firmware blob, or via a module parameter override. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
This commit is contained in:
parent
81ee454d09
commit
a2995d38c2
@ -31,6 +31,6 @@ Header Type - u8: 0xf
|
||||
|
||||
==============================================================================
|
||||
|
||||
Place isci_firmware.bin in /lib/firmware
|
||||
Place isci_firmware.bin in /lib/firmware/isci
|
||||
Be sure to recreate the initramfs image to include the firmware.
|
||||
|
||||
|
@ -39,7 +39,7 @@ int write_blob(struct isci_orom *isci_orom)
|
||||
|
||||
void set_binary_values(struct isci_orom *isci_orom)
|
||||
{
|
||||
int ctrl_idx, phy_idx, port_idx;
|
||||
int c, phy_idx, port_idx;
|
||||
|
||||
/* setting OROM signature */
|
||||
strncpy(isci_orom->hdr.signature, sig, strlen(sig));
|
||||
@ -48,32 +48,33 @@ void set_binary_values(struct isci_orom *isci_orom)
|
||||
isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
|
||||
isci_orom->hdr.num_elements = num_elements;
|
||||
|
||||
for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
|
||||
isci_orom->ctrl[ctrl_idx].controller.max_concurr_spin_up =
|
||||
max_num_concurrent_dev_spin_up;
|
||||
isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
|
||||
enable_ssc;
|
||||
for (c = 0; c < 2; c++) {
|
||||
struct sci_oem_params *ctrl = &isci_orom->ctrl[c];
|
||||
__u8 cable_selection_mask = 0;
|
||||
|
||||
for (port_idx = 0; port_idx < 4; port_idx++)
|
||||
isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
|
||||
phy_mask[ctrl_idx][port_idx];
|
||||
ctrl->controller.mode_type = mode_type;
|
||||
ctrl->controller.max_concurr_spin_up = max_num_concurrent_dev_spin_up;
|
||||
ctrl->controller.do_enable_ssc = enable_ssc;
|
||||
|
||||
for (phy_idx = 0; phy_idx < 4; phy_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx]);
|
||||
for (port_idx = 0; port_idx < SCI_MAX_PORTS; port_idx++)
|
||||
ctrl->ports[port_idx].phy_mask = phy_mask[c][port_idx];
|
||||
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
|
||||
afe_tx_amp_control0;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
|
||||
afe_tx_amp_control1;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
|
||||
afe_tx_amp_control2;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
|
||||
afe_tx_amp_control3;
|
||||
for (phy_idx = 0; phy_idx < SCI_MAX_PHYS; phy_idx++) {
|
||||
struct sci_phy_oem_params *phy = &ctrl->phys[phy_idx];
|
||||
__u8 cable_phy = cable_selection[c][phy_idx];
|
||||
|
||||
phy->sas_address.high = sas_addr[c][phy_idx] >> 32;
|
||||
phy->sas_address.low = sas_addr[c][phy_idx];
|
||||
|
||||
phy->afe_tx_amp_control0 = afe_tx_amp_control0;
|
||||
phy->afe_tx_amp_control1 = afe_tx_amp_control1;
|
||||
phy->afe_tx_amp_control2 = afe_tx_amp_control2;
|
||||
phy->afe_tx_amp_control3 = afe_tx_amp_control3;
|
||||
|
||||
cable_selection_mask |= (cable_phy & 1) << phy_idx;
|
||||
cable_selection_mask |= (cable_phy & 2) << (phy_idx + 3);
|
||||
}
|
||||
ctrl->controller.cable_selection_mask = cable_selection_mask;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,11 +58,20 @@ static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000002ULL } };
|
||||
#endif
|
||||
|
||||
static const int cable_selection[2][4];
|
||||
|
||||
/* Maximum number of concurrent device spin up */
|
||||
static const int max_num_concurrent_dev_spin_up = 1;
|
||||
|
||||
/* enable of ssc operation */
|
||||
static const int enable_ssc;
|
||||
/*
|
||||
* NOTE: also see probe_roms.h. This value can be set for ssc values.
|
||||
* Values can be set for:
|
||||
* ssc_sata_tx_spread_level
|
||||
* ssc_sas_tx_spread_level
|
||||
* ssc_sas_tx_type
|
||||
*/
|
||||
static const __u8 enable_ssc;
|
||||
|
||||
/* AFE_TX_AMP_CONTROL */
|
||||
static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
|
||||
@ -72,6 +81,6 @@ static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
|
||||
|
||||
static const char blob_name[] = "isci_firmware.bin";
|
||||
static const char sig[] = "ISCUOEMB";
|
||||
static const unsigned char version = 0x10;
|
||||
static const unsigned char version = ISCI_ROM_VER_LATEST;
|
||||
|
||||
#endif
|
||||
|
Binary file not shown.
@ -152,7 +152,7 @@ struct sci_user_parameters {
|
||||
#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
|
||||
|
||||
struct sci_oem_params;
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem);
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem, u8 version);
|
||||
|
||||
struct isci_orom;
|
||||
struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
|
||||
@ -191,6 +191,11 @@ struct isci_oem_hdr {
|
||||
0x1a, 0x04, 0xc6)
|
||||
#define ISCI_EFI_VAR_NAME "RstScuO"
|
||||
|
||||
#define ISCI_ROM_VER_1_0 0x10
|
||||
#define ISCI_ROM_VER_1_1 0x11
|
||||
#define ISCI_ROM_VER_1_3 0x13
|
||||
#define ISCI_ROM_VER_LATEST ISCI_ROM_VER_1_3
|
||||
|
||||
/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
|
||||
* defined by the OEM configuration parameters providing no PHY_MASK parameters
|
||||
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
|
||||
@ -220,8 +225,86 @@ struct sci_oem_params {
|
||||
struct {
|
||||
uint8_t mode_type;
|
||||
uint8_t max_concurr_spin_up;
|
||||
uint8_t do_enable_ssc;
|
||||
uint8_t reserved;
|
||||
/*
|
||||
* This bitfield indicates the OEM's desired default Tx
|
||||
* Spread Spectrum Clocking (SSC) settings for SATA and SAS.
|
||||
* NOTE: Default SSC Modulation Frequency is 31.5KHz.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/*
|
||||
* NOTE: Max spread for SATA is +0 / -5000 PPM.
|
||||
* Down-spreading SSC (only method allowed for SATA):
|
||||
* SATA SSC Tx Disabled = 0x0
|
||||
* SATA SSC Tx at +0 / -1419 PPM Spread = 0x2
|
||||
* SATA SSC Tx at +0 / -2129 PPM Spread = 0x3
|
||||
* SATA SSC Tx at +0 / -4257 PPM Spread = 0x6
|
||||
* SATA SSC Tx at +0 / -4967 PPM Spread = 0x7
|
||||
*/
|
||||
uint8_t ssc_sata_tx_spread_level:4;
|
||||
/*
|
||||
* SAS SSC Tx Disabled = 0x0
|
||||
*
|
||||
* NOTE: Max spread for SAS down-spreading +0 /
|
||||
* -2300 PPM
|
||||
* Down-spreading SSC:
|
||||
* SAS SSC Tx at +0 / -1419 PPM Spread = 0x2
|
||||
* SAS SSC Tx at +0 / -2129 PPM Spread = 0x3
|
||||
*
|
||||
* NOTE: Max spread for SAS center-spreading +2300 /
|
||||
* -2300 PPM
|
||||
* Center-spreading SSC:
|
||||
* SAS SSC Tx at +1064 / -1064 PPM Spread = 0x3
|
||||
* SAS SSC Tx at +2129 / -2129 PPM Spread = 0x6
|
||||
*/
|
||||
uint8_t ssc_sas_tx_spread_level:3;
|
||||
/*
|
||||
* NOTE: Refer to the SSC section of the SAS 2.x
|
||||
* Specification for proper setting of this field.
|
||||
* For standard SAS Initiator SAS PHY operation it
|
||||
* should be 0 for Down-spreading.
|
||||
* SAS SSC Tx spread type:
|
||||
* Down-spreading SSC = 0
|
||||
* Center-spreading SSC = 1
|
||||
*/
|
||||
uint8_t ssc_sas_tx_type:1;
|
||||
};
|
||||
uint8_t do_enable_ssc;
|
||||
};
|
||||
/*
|
||||
* This field indicates length of the SAS/SATA cable between
|
||||
* host and device.
|
||||
* This field is used make relationship between analog
|
||||
* parameters of the phy in the silicon and length of the cable.
|
||||
* Supported cable attenuation levels:
|
||||
* "short"- up to 3m, "medium"-3m to 6m, and "long"- more than
|
||||
* 6m.
|
||||
*
|
||||
* This is bit mask field:
|
||||
*
|
||||
* BIT: (MSB) 7 6 5 4
|
||||
* ASSIGNMENT: <phy3><phy2><phy1><phy0> - Medium cable
|
||||
* length assignment
|
||||
* BIT: 3 2 1 0 (LSB)
|
||||
* ASSIGNMENT: <phy3><phy2><phy1><phy0> - Long cable length
|
||||
* assignment
|
||||
*
|
||||
* BITS 7-4 are set when the cable length is assigned to medium
|
||||
* BITS 3-0 are set when the cable length is assigned to long
|
||||
*
|
||||
* The BIT positions are clear when the cable length is
|
||||
* assigned to short.
|
||||
*
|
||||
* Setting the bits for both long and medium cable length is
|
||||
* undefined.
|
||||
*
|
||||
* A value of 0x84 would assign
|
||||
* phy3 - medium
|
||||
* phy2 - long
|
||||
* phy1 - short
|
||||
* phy0 - short
|
||||
*/
|
||||
uint8_t cable_selection_mask;
|
||||
} controller;
|
||||
|
||||
struct {
|
||||
|
Loading…
Reference in New Issue
Block a user