Skip to content

Commit

Permalink
[SCSI] isci: update afe (analog-front-end) recipe for C1
Browse files Browse the repository at this point in the history
C1 silicon requires updates to the phy tuning recipe and also support
for user provided cable selects (per-phy) for short, medium, and long
cables.  Default to 'short' awaiting support for selecting the cable via
oem parameters.

Reviewed-by: Jiangbi Liu <jiangbi.liu@intel.com>
Signed-off-by: Marcin Tomczak <marcin.tomczak@intel.com>
Signed-off-by: Jeff Skirvin <jeffrey.d.skirvin@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Jeff Skirvin authored and James Bottomley committed Jan 16, 2012
1 parent 2e5da88 commit afd13a1
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 26 deletions.
111 changes: 89 additions & 22 deletions drivers/scsi/isci/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1908,12 +1908,23 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,
ihost->power_control.requesters[iphy->phy_index] = NULL;
}

static int is_long_cable(int phy, unsigned char selection_byte)
{
return 0;
}

static int is_medium_cable(int phy, unsigned char selection_byte)
{
return 0;
}

#define AFE_REGISTER_WRITE_DELAY 10

static void sci_controller_afe_initialization(struct isci_host *ihost)
{
struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;
const struct sci_oem_params *oem = &ihost->oem_parameters;
unsigned char cable_selection_mask = 0;
struct pci_dev *pdev = ihost->pdev;
u32 afe_status;
u32 phy_id;
Expand All @@ -1922,11 +1933,11 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
writel(0x0081000f, &afe->afe_dfx_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

if (is_b0(pdev)) {
if (is_b0(pdev) || is_c0(pdev) || is_c1(pdev)) {
/* PM Rx Equalization Save, PM SPhy Rx Acknowledgement
* Timer, PM Stagger Timer
*/
writel(0x0007BFFF, &afe->afe_pmsn_master_control2);
writel(0x0007FFFF, &afe->afe_pmsn_master_control2);
udelay(AFE_REGISTER_WRITE_DELAY);
}

Expand All @@ -1935,14 +1946,23 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
writel(0x00005A00, &afe->afe_bias_control);
else if (is_b0(pdev) || is_c0(pdev))
writel(0x00005F00, &afe->afe_bias_control);
else if (is_c1(pdev))
writel(0x00005500, &afe->afe_bias_control);

udelay(AFE_REGISTER_WRITE_DELAY);

/* Enable PLL */
if (is_b0(pdev) || is_c0(pdev))
writel(0x80040A08, &afe->afe_pll_control0);
else
if (is_a2(pdev))
writel(0x80040908, &afe->afe_pll_control0);
else if (is_b0(pdev) || is_c0(pdev))
writel(0x80040A08, &afe->afe_pll_control0);
else if (is_c1(pdev)) {
writel(0x80000B08, &afe->afe_pll_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
writel(0x00000B08, &afe->afe_pll_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
writel(0x80000B08, &afe->afe_pll_control0);
}

udelay(AFE_REGISTER_WRITE_DELAY);

Expand All @@ -1963,46 +1983,68 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
for (phy_id = 0; phy_id < SCI_MAX_PHYS; phy_id++) {
struct scu_afe_transceiver *xcvr = &afe->scu_afe_xcvr[phy_id];
const struct sci_phy_oem_params *oem_phy = &oem->phys[phy_id];
int cable_length_long =
is_long_cable(phy_id, cable_selection_mask);
int cable_length_medium =
is_medium_cable(phy_id, cable_selection_mask);

if (is_a2(pdev)) {
/* All defaults, except the Receive Word
* Alignament/Comma Detect Enable....(0xe800)
*/
writel(0x00004512, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

if (is_b0(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x0050100F, &xcvr->afe_xcvr_control1);
udelay(AFE_REGISTER_WRITE_DELAY);
} else if (is_b0(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x00030000, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);
} else if (is_c0(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x0003000, &xcvr->afe_tx_ssc_control);
/* Configure transmitter SSC parameters */
writel(0x00010202, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);

/* All defaults, except the Receive Word
* Alignament/Comma Detect Enable....(0xe800)
*/
writel(0x00004500, &xcvr->afe_xcvr_control0);
writel(0x00014500, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
} else {
} else if (is_c1(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x00010202, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);

/* All defaults, except the Receive Word
* Alignament/Comma Detect Enable....(0xe800)
*/
writel(0x00004512, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x0050100F, &xcvr->afe_xcvr_control1);
writel(0x0001C500, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}

/* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
* & increase TX int & ext bias 20%....(0xe85c)
/* Power up TX and RX out from power down (PWRDNTX and
* PWRDNRX) & increase TX int & ext bias 20%....(0xe85c)
*/
if (is_a2(pdev))
writel(0x000003F0, &xcvr->afe_channel_control);
else if (is_b0(pdev)) {
/* Power down TX and RX (PWRDNTX and PWRDNRX) */
writel(0x000003D7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x000003D4, &xcvr->afe_channel_control);
} else {
} else if (is_c0(pdev)) {
writel(0x000001E7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x000001E4, &xcvr->afe_channel_control);
} else if (is_c1(pdev)) {
writel(cable_length_long ? 0x000002F7 : 0x000001F7,
&xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(cable_length_long ? 0x000002F4 : 0x000001F4,
&xcvr->afe_channel_control);
}
udelay(AFE_REGISTER_WRITE_DELAY);

Expand All @@ -2012,7 +2054,16 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
udelay(AFE_REGISTER_WRITE_DELAY);
}

writel(0x00004100, &xcvr->afe_xcvr_control0);
if (is_a2(pdev) || is_b0(pdev))
/* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0,
* TPD=0x0(TX Power On), RDD=0x0(RX Detect
* Enabled) ....(0xe800)
*/
writel(0x00004100, &xcvr->afe_xcvr_control0);
else if (is_c0(pdev))
writel(0x00014100, &xcvr->afe_xcvr_control0);
else if (is_c1(pdev))
writel(0x0001C100, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

/* Leave DFE/FFE on */
Expand All @@ -2023,13 +2074,29 @@ static void sci_controller_afe_initialization(struct isci_host *ihost)
udelay(AFE_REGISTER_WRITE_DELAY);
/* Enable TX equalization (0xe824) */
writel(0x00040000, &xcvr->afe_tx_control);
} else {
writel(0x0140DF0F, &xcvr->afe_rx_ssc_control1);
} else if (is_c0(pdev)) {
writel(0x01400C0F, &xcvr->afe_rx_ssc_control1);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

/* Enable TX equalization (0xe824) */
writel(0x00040000, &xcvr->afe_tx_control);
} else if (is_c1(pdev)) {
writel(cable_length_long ? 0x01500C0C :
cable_length_medium ? 0x01400C0D : 0x02400C0D,
&xcvr->afe_xcvr_control1);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x000003E0, &xcvr->afe_dfx_rx_control1);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(cable_length_long ? 0x33091C1F :
cable_length_medium ? 0x3315181F : 0x2B17161F,
&xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

/* Enable TX equalization (0xe824) */
writel(0x00040000, &xcvr->afe_tx_control);
}
Expand Down
9 changes: 8 additions & 1 deletion drivers/scsi/isci/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,14 @@ static inline bool is_b0(struct pci_dev *pdev)

static inline bool is_c0(struct pci_dev *pdev)
{
if (pdev->revision >= 5)
if (pdev->revision == 5)
return true;
return false;
}

static inline bool is_c1(struct pci_dev *pdev)
{
if (pdev->revision >= 6)
return true;
return false;
}
Expand Down
7 changes: 5 additions & 2 deletions drivers/scsi/isci/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,11 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,

writel(clksm_value, &llr->clock_skew_management);

/* @todo Provide a way to write this register correctly */
writel(0x02108421, &llr->afe_lookup_table_control);
if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) {
writel(0x04210400, &llr->afe_lookup_table_control);
writel(0x020A7C05, &llr->sas_primitive_timeout);
} else
writel(0x02108421, &llr->afe_lookup_table_control);

llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
(u8)ihost->user_parameters.no_outbound_task_timeout);
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/isci/probe_roms.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmw

memcpy(orom, fw->data, fw->size);

if (is_c0(pdev))
if (is_c0(pdev) || is_c1(pdev))
goto out;

/*
Expand Down

0 comments on commit afd13a1

Please sign in to comment.