Skip to content

Commit

Permalink
[SCSI] isci: cleanup oem parameter and recipe handling
Browse files Browse the repository at this point in the history
Before updating the code to support the latest platform updates and
silicon revision cleanup some of the long deref chains.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Dan Williams authored and James Bottomley committed Jan 16, 2012
1 parent 7d99b3a commit 2e5da88
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 102 deletions.
107 changes: 47 additions & 60 deletions drivers/scsi/isci/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1910,160 +1910,147 @@ void sci_controller_power_control_queue_remove(struct isci_host *ihost,

#define AFE_REGISTER_WRITE_DELAY 10

/* Initialize the AFE for this phy index. We need to read the AFE setup from
* the OEM parameters
*/
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;
struct pci_dev *pdev = ihost->pdev;
u32 afe_status;
u32 phy_id;

/* Clear DFX Status registers */
writel(0x0081000f, &ihost->scu_registers->afe.afe_dfx_master_control0);
writel(0x0081000f, &afe->afe_dfx_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

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

/* Configure bias currents to normal */
if (is_a2(pdev))
writel(0x00005A00, &ihost->scu_registers->afe.afe_bias_control);
writel(0x00005A00, &afe->afe_bias_control);
else if (is_b0(pdev) || is_c0(pdev))
writel(0x00005F00, &ihost->scu_registers->afe.afe_bias_control);
writel(0x00005F00, &afe->afe_bias_control);

udelay(AFE_REGISTER_WRITE_DELAY);

/* Enable PLL */
if (is_b0(pdev) || is_c0(pdev))
writel(0x80040A08, &ihost->scu_registers->afe.afe_pll_control0);
writel(0x80040A08, &afe->afe_pll_control0);
else
writel(0x80040908, &ihost->scu_registers->afe.afe_pll_control0);
writel(0x80040908, &afe->afe_pll_control0);

udelay(AFE_REGISTER_WRITE_DELAY);

/* Wait for the PLL to lock */
do {
afe_status = readl(&ihost->scu_registers->afe.afe_common_block_status);
afe_status = readl(&afe->afe_common_block_status);
udelay(AFE_REGISTER_WRITE_DELAY);
} while ((afe_status & 0x00001000) == 0);

if (is_a2(pdev)) {
/* Shorten SAS SNW lock time (RxLock timer value from 76 us to 50 us) */
writel(0x7bcc96ad, &ihost->scu_registers->afe.afe_pmsn_master_control0);
/* Shorten SAS SNW lock time (RxLock timer value from 76
* us to 50 us)
*/
writel(0x7bcc96ad, &afe->afe_pmsn_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}

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];

if (is_b0(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x00030000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
writel(0x00030000, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);
} else if (is_c0(pdev)) {
/* Configure transmitter SSC parameters */
writel(0x0003000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_ssc_control);
writel(0x0003000, &xcvr->afe_tx_ssc_control);
udelay(AFE_REGISTER_WRITE_DELAY);

/*
* All defaults, except the Receive Word Alignament/Comma Detect
* Enable....(0xe800) */
writel(0x00004500, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
/* All defaults, except the Receive Word
* Alignament/Comma Detect Enable....(0xe800)
*/
writel(0x00004500, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
} else {
/*
* All defaults, except the Receive Word Alignament/Comma Detect
* Enable....(0xe800) */
writel(0x00004512, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
/* All defaults, except the Receive Word
* Alignament/Comma Detect Enable....(0xe800)
*/
writel(0x00004512, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x0050100F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control1);
writel(0x0050100F, &xcvr->afe_xcvr_control1);
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, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
writel(0x000003F0, &xcvr->afe_channel_control);
else if (is_b0(pdev)) {
/* Power down TX and RX (PWRDNTX and PWRDNRX) */
writel(0x000003D7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
writel(0x000003D7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);

/*
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
* & increase TX int & ext bias 20%....(0xe85c) */
writel(0x000003D4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
writel(0x000003D4, &xcvr->afe_channel_control);
} else {
writel(0x000001E7, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
writel(0x000001E7, &xcvr->afe_channel_control);
udelay(AFE_REGISTER_WRITE_DELAY);

/*
* Power up TX and RX out from power down (PWRDNTX and PWRDNRX)
* & increase TX int & ext bias 20%....(0xe85c) */
writel(0x000001E4, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_channel_control);
writel(0x000001E4, &xcvr->afe_channel_control);
}
udelay(AFE_REGISTER_WRITE_DELAY);

if (is_a2(pdev)) {
/* Enable TX equalization (0xe824) */
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
writel(0x00040000, &xcvr->afe_tx_control);
udelay(AFE_REGISTER_WRITE_DELAY);
}

/*
* RDPI=0x0(RX Power On), RXOOBDETPDNC=0x0, TPD=0x0(TX Power On),
* RDD=0x0(RX Detect Enabled) ....(0xe800) */
writel(0x00004100, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_xcvr_control0);
writel(0x00004100, &xcvr->afe_xcvr_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

/* Leave DFE/FFE on */
if (is_a2(pdev))
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
else if (is_b0(pdev)) {
writel(0x3F11103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
writel(0x3F11103F, &xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
/* Enable TX equalization (0xe824) */
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
writel(0x00040000, &xcvr->afe_tx_control);
} else {
writel(0x0140DF0F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control1);
writel(0x0140DF0F, &xcvr->afe_rx_ssc_control1);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(0x3F6F103F, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_rx_ssc_control0);
writel(0x3F6F103F, &xcvr->afe_rx_ssc_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

/* Enable TX equalization (0xe824) */
writel(0x00040000, &ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_control);
writel(0x00040000, &xcvr->afe_tx_control);
}

udelay(AFE_REGISTER_WRITE_DELAY);

writel(oem_phy->afe_tx_amp_control0,
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control0);
writel(oem_phy->afe_tx_amp_control0, &xcvr->afe_tx_amp_control0);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(oem_phy->afe_tx_amp_control1,
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control1);
writel(oem_phy->afe_tx_amp_control1, &xcvr->afe_tx_amp_control1);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(oem_phy->afe_tx_amp_control2,
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control2);
writel(oem_phy->afe_tx_amp_control2, &xcvr->afe_tx_amp_control2);
udelay(AFE_REGISTER_WRITE_DELAY);

writel(oem_phy->afe_tx_amp_control3,
&ihost->scu_registers->afe.scu_afe_xcvr[phy_id].afe_tx_amp_control3);
writel(oem_phy->afe_tx_amp_control3, &xcvr->afe_tx_amp_control3);
udelay(AFE_REGISTER_WRITE_DELAY);
}

/* Transfer control to the PEs */
writel(0x00010f00, &ihost->scu_registers->afe.afe_dfx_master_control0);
writel(0x00010f00, &afe->afe_dfx_master_control0);
udelay(AFE_REGISTER_WRITE_DELAY);
}

Expand Down
81 changes: 39 additions & 42 deletions drivers/scsi/isci/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,23 @@ sci_phy_transport_layer_initialization(struct isci_phy *iphy,

static enum sci_status
sci_phy_link_layer_initialization(struct isci_phy *iphy,
struct scu_link_layer_registers __iomem *reg)
struct scu_link_layer_registers __iomem *llr)
{
struct isci_host *ihost = iphy->owning_port->owning_controller;
struct sci_phy_user_params *phy_user;
struct sci_phy_oem_params *phy_oem;
int phy_idx = iphy->phy_index;
struct sci_phy_user_params *phy_user = &ihost->user_parameters.phys[phy_idx];
struct sci_phy_oem_params *phy_oem =
&ihost->oem_parameters.phys[phy_idx];
u32 phy_configuration;
struct sci_phy_cap phy_cap;
u32 phy_configuration;
u32 parity_check = 0;
u32 parity_count = 0;
u32 llctl, link_rate;
u32 clksm_value = 0;
u32 sp_timeouts = 0;

iphy->link_layer_registers = reg;
phy_user = &ihost->user_parameters.phys[phy_idx];
phy_oem = &ihost->oem_parameters.phys[phy_idx];
iphy->link_layer_registers = llr;

/* Set our IDENTIFY frame data */
#define SCI_END_DEVICE 0x01
Expand All @@ -116,32 +117,26 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),
&iphy->link_layer_registers->transmit_identification);
&llr->transmit_identification);

/* Write the device SAS Address */
writel(0xFEDCBA98,
&iphy->link_layer_registers->sas_device_name_high);
writel(phy_idx, &iphy->link_layer_registers->sas_device_name_low);
writel(0xFEDCBA98, &llr->sas_device_name_high);
writel(phy_idx, &llr->sas_device_name_low);

/* Write the source SAS Address */
writel(phy_oem->sas_address.high,
&iphy->link_layer_registers->source_sas_address_high);
writel(phy_oem->sas_address.low,
&iphy->link_layer_registers->source_sas_address_low);
writel(phy_oem->sas_address.high, &llr->source_sas_address_high);
writel(phy_oem->sas_address.low, &llr->source_sas_address_low);

/* Clear and Set the PHY Identifier */
writel(0, &iphy->link_layer_registers->identify_frame_phy_id);
writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx),
&iphy->link_layer_registers->identify_frame_phy_id);
writel(0, &llr->identify_frame_phy_id);
writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id);

/* Change the initial state of the phy configuration register */
phy_configuration =
readl(&iphy->link_layer_registers->phy_configuration);
phy_configuration = readl(&llr->phy_configuration);

/* Hold OOB state machine in reset */
phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
writel(phy_configuration,
&iphy->link_layer_registers->phy_configuration);
writel(phy_configuration, &llr->phy_configuration);

/* Configure the SNW capabilities */
phy_cap.all = 0;
Expand All @@ -155,30 +150,30 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
phy_cap.gen1_ssc = 1;
}

/*
* The SAS specification indicates that the phy_capabilities that
* are transmitted shall have an even parity. Calculate the parity. */
/* The SAS specification indicates that the phy_capabilities that
* are transmitted shall have an even parity. Calculate the parity.
*/
parity_check = phy_cap.all;
while (parity_check != 0) {
if (parity_check & 0x1)
parity_count++;
parity_check >>= 1;
}

/*
* If parity indicates there are an odd number of bits set, then
* set the parity bit to 1 in the phy capabilities. */
/* If parity indicates there are an odd number of bits set, then
* set the parity bit to 1 in the phy capabilities.
*/
if ((parity_count % 2) != 0)
phy_cap.parity = 1;

writel(phy_cap.all, &iphy->link_layer_registers->phy_capabilities);
writel(phy_cap.all, &llr->phy_capabilities);

/* Set the enable spinup period but disable the ability to send
* notify enable spinup
*/
writel(SCU_ENSPINUP_GEN_VAL(COUNT,
phy_user->notify_enable_spin_up_insertion_frequency),
&iphy->link_layer_registers->notify_enable_spinup_control);
&llr->notify_enable_spinup_control);

/* Write the ALIGN Insertion Ferequency for connected phy and
* inpendent of connected state
Expand All @@ -189,11 +184,10 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
phy_user->align_insertion_frequency);

writel(clksm_value, &iphy->link_layer_registers->clock_skew_management);
writel(clksm_value, &llr->clock_skew_management);

/* @todo Provide a way to write this register correctly */
writel(0x02108421,
&iphy->link_layer_registers->afe_lookup_table_control);
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 All @@ -210,9 +204,9 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
break;
}
llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
writel(llctl, &iphy->link_layer_registers->link_layer_control);
writel(llctl, &llr->link_layer_control);

sp_timeouts = readl(&iphy->link_layer_registers->sas_phy_timeouts);
sp_timeouts = readl(&llr->sas_phy_timeouts);

/* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */
sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);
Expand All @@ -222,20 +216,23 @@ sci_phy_link_layer_initialization(struct isci_phy *iphy,
*/
sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);

writel(sp_timeouts, &iphy->link_layer_registers->sas_phy_timeouts);
writel(sp_timeouts, &llr->sas_phy_timeouts);

if (is_a2(ihost->pdev)) {
/* Program the max ARB time for the PHY to 700us so we inter-operate with
* the PMC expander which shuts down PHYs if the expander PHY generates too
* many breaks. This time value will guarantee that the initiator PHY will
* generate the break.
/* Program the max ARB time for the PHY to 700us so we
* inter-operate with the PMC expander which shuts down
* PHYs if the expander PHY generates too many breaks.
* This time value will guarantee that the initiator PHY
* will generate the break.
*/
writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,
&iphy->link_layer_registers->maximum_arbitration_wait_timer_timeout);
&llr->maximum_arbitration_wait_timer_timeout);
}

/* Disable link layer hang detection, rely on the OS timeout for I/O timeouts. */
writel(0, &iphy->link_layer_registers->link_layer_hang_detection_timeout);
/* Disable link layer hang detection, rely on the OS timeout for
* I/O timeouts.
*/
writel(0, &llr->link_layer_hang_detection_timeout);

/* We can exit the initial state to the stopped state */
sci_change_state(&iphy->sm, SCI_PHY_STOPPED);
Expand Down

0 comments on commit 2e5da88

Please sign in to comment.