From d9def184b39b966b7496dfbfad126808d3cd701b Mon Sep 17 00:00:00 2001 From: Jacek Danecki Date: Wed, 23 Feb 2011 00:08:58 -0800 Subject: [PATCH] isci: Add support for user parameters in SCIC layer Add support for the following parameters in SCIC: /** * This field specifies the NOTIFY (ENABLE SPIN UP) primitive * insertion frequency for this phy index. */ u32 notify_enable_spin_up_insertion_frequency; /** * This method specifies the number of transmitted DWORDs within which * to transmit a single ALIGN primitive. This value applies regardless * of what type of device is attached or connection state. A value of * 0 indicates that no ALIGN primitives will be inserted. */ u16 align_insertion_frequency; /** * This method specifies the number of transmitted DWORDs within which * to transmit 2 ALIGN primitives. This applies for SAS connections * only. A minimum value of 3 is required for this field. */ u16 in_connection_align_insertion_frequency; Signed-off-by: Krzysztof Wierzbicki Signed-off-by: Dan Williams --- drivers/scsi/isci/core/scic_sds_controller.c | 58 +++++++++++++++---------- drivers/scsi/isci/core/scic_sds_phy.c | 16 ++++++- drivers/scsi/isci/core/scic_sds_phy_registers.h | 8 ++++ drivers/scsi/isci/core/scu_registers.h | 7 +++ 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/drivers/scsi/isci/core/scic_sds_controller.c b/drivers/scsi/isci/core/scic_sds_controller.c index e597c6b..d9fca99 100644 --- a/drivers/scsi/isci/core/scic_sds_controller.c +++ b/drivers/scsi/isci/core/scic_sds_controller.c @@ -616,7 +616,6 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) scu_afe_register_write(scic, afe_bias_control, 0x00005500); else scu_afe_register_write(scic, afe_bias_control, 0x00005A00); - scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); @@ -625,7 +624,7 @@ void scic_sds_controller_afe_initialization(struct scic_sds_controller *scic) scu_afe_register_write(scic, afe_pll_control0, 0x80040A08); else scu_afe_register_write(scic, afe_pll_control0, 0x80040908); - + scic_cb_stall_execution(AFE_REGISTER_WRITE_DELAY); /* Wait for the PLL to lock */ @@ -1962,17 +1961,16 @@ void scic_sds_controller_release_frame( * configuration parameters to their default values. * */ -static void scic_sds_controller_set_default_config_parameters( - struct scic_sds_controller *this_controller) +static void scic_sds_controller_set_default_config_parameters(struct scic_sds_controller *scic) { u16 index; /* Default to no SSC operation. */ - this_controller->oem_parameters.sds1.controller.do_enable_ssc = false; + scic->oem_parameters.sds1.controller.do_enable_ssc = false; /* Initialize all of the port parameter information to narrow ports. */ for (index = 0; index < SCI_MAX_PORTS; index++) { - this_controller->oem_parameters.sds1.ports[index].phy_mask = 0; + scic->oem_parameters.sds1.ports[index].phy_mask = 0; } /* Initialize all of the phy parameter information. */ @@ -1980,24 +1978,27 @@ static void scic_sds_controller_set_default_config_parameters( /* * Default to 3G (i.e. Gen 2) for now. User can override if * they choose. */ - this_controller->user_parameters.sds1.phys[index].max_speed_generation = 2; + scic->user_parameters.sds1.phys[index].max_speed_generation = 2; + + /* the frequencies cannot be 0 */ + scic->user_parameters.sds1.phys[index].align_insertion_frequency = 0x7f; + scic->user_parameters.sds1.phys[index].in_connection_align_insertion_frequency = 0xff; + scic->user_parameters.sds1.phys[index].notify_enable_spin_up_insertion_frequency = 0x33; /* * Previous Vitesse based expanders had a arbitration issue that * is worked around by having the upper 32-bits of SAS address * with a value greater then the Vitesse company identifier. * Hence, usage of 0x5FCFFFFF. */ - this_controller->oem_parameters.sds1.phys[index].sas_address.low - = 0x00000001; - this_controller->oem_parameters.sds1.phys[index].sas_address.high - = 0x5FCFFFFF; + scic->oem_parameters.sds1.phys[index].sas_address.low = 0x00000001; + scic->oem_parameters.sds1.phys[index].sas_address.high = 0x5FCFFFFF; } - this_controller->user_parameters.sds1.stp_inactivity_timeout = 5; - this_controller->user_parameters.sds1.ssp_inactivity_timeout = 5; - this_controller->user_parameters.sds1.stp_max_occupancy_timeout = 5; - this_controller->user_parameters.sds1.ssp_max_occupancy_timeout = 20; - this_controller->user_parameters.sds1.no_outbound_task_timeout = 20; + scic->user_parameters.sds1.stp_inactivity_timeout = 5; + scic->user_parameters.sds1.ssp_inactivity_timeout = 5; + scic->user_parameters.sds1.stp_max_occupancy_timeout = 5; + scic->user_parameters.sds1.ssp_max_occupancy_timeout = 20; + scic->user_parameters.sds1.no_outbound_task_timeout = 20; } @@ -2103,9 +2104,9 @@ u32 scic_controller_get_suggested_start_timeout( * per interval - 1 (once OEM parameters are supported). * Currently we assume only 1 phy per interval. */ - return (SCIC_SDS_SIGNATURE_FIS_TIMEOUT + return SCIC_SDS_SIGNATURE_FIS_TIMEOUT + SCIC_SDS_CONTROLLER_PHY_START_TIMEOUT - + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL)); + + ((SCI_MAX_PHYS - 1) * SCIC_SDS_CONTROLLER_POWER_CONTROL_INTERVAL); } /* --------------------------------------------------------------------------- */ @@ -2489,16 +2490,29 @@ enum sci_status scic_user_parameters_set( * Validate the user parameters. If they are not legal, then * return a failure. */ for (index = 0; index < SCI_MAX_PHYS; index++) { - if (! - (scic_parms->sds1.phys[index].max_speed_generation + if (!(scic_parms->sds1.phys[index].max_speed_generation <= SCIC_SDS_PARM_MAX_SPEED && scic_parms->sds1.phys[index].max_speed_generation - > SCIC_SDS_PARM_NO_SPEED - ) + > SCIC_SDS_PARM_NO_SPEED)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + + if (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + if ( + (scic_parms->sds1.phys[index].in_connection_align_insertion_frequency < 3) || + (scic_parms->sds1.phys[index].align_insertion_frequency == 0) || + (scic_parms->sds1.phys[index].notify_enable_spin_up_insertion_frequency == 0) ) return SCI_FAILURE_INVALID_PARAMETER_VALUE; } + if ((scic_parms->sds1.stp_inactivity_timeout == 0) || + (scic_parms->sds1.ssp_inactivity_timeout == 0) || + (scic_parms->sds1.stp_max_occupancy_timeout == 0) || + (scic_parms->sds1.ssp_max_occupancy_timeout == 0) || + (scic_parms->sds1.no_outbound_task_timeout == 0)) + return SCI_FAILURE_INVALID_PARAMETER_VALUE; + memcpy(&scic->user_parameters, scic_parms, sizeof(*scic_parms)); return SCI_SUCCESS; diff --git a/drivers/scsi/isci/core/scic_sds_phy.c b/drivers/scsi/isci/core/scic_sds_phy.c index bd0a6ba..ecd7cc6 100644 --- a/drivers/scsi/isci/core/scic_sds_phy.c +++ b/drivers/scsi/isci/core/scic_sds_phy.c @@ -125,6 +125,7 @@ static enum sci_status scic_sds_phy_link_layer_initialization( u32 parity_check = 0; u32 parity_count = 0; u32 link_layer_control; + u32 clksm_value = 0; this_phy->link_layer_registers = link_layer_registers; @@ -199,7 +200,20 @@ static enum sci_status scic_sds_phy_link_layer_initialization( SCU_SAS_PHYCAP_WRITE(this_phy, phy_capabilities.u.all); /* Set the enable spinup period but disable the ability to send notify enable spinup */ - SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, 0x33)); + SCU_SAS_ENSPINUP_WRITE(this_phy, SCU_ENSPINUP_GEN_VAL(COUNT, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].notify_enable_spin_up_insertion_frequency)); + + /* Write the ALIGN Insertion Ferequency for connected phy and inpendent of connected state */ + clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].in_connection_align_insertion_frequency); + + clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL, + this_phy->owning_port->owning_controller->user_parameters.sds1. + phys[this_phy->phy_index].align_insertion_frequency); + + SCU_SAS_CLKSM_WRITE(this_phy, clksm_value); #if defined(CONFIG_PBG_HBA_A0) || defined(CONFIG_PBG_HBA_A2) || defined(CONFIG_PBG_HBA_BETA) /* / @todo Provide a way to write this register correctly */ diff --git a/drivers/scsi/isci/core/scic_sds_phy_registers.h b/drivers/scsi/isci/core/scic_sds_phy_registers.h index 2842176..ddbb236 100644 --- a/drivers/scsi/isci/core/scic_sds_phy_registers.h +++ b/drivers/scsi/isci/core/scic_sds_phy_registers.h @@ -217,6 +217,14 @@ #define SCU_SAS_ENSPINUP_WRITE(phy, value) \ scu_link_layer_register_write(phy, notify_enable_spinup_control, value) +/* This macro reads the CLKSM register */ +#define SCU_SAS_CLKSM_READ(phy) \ + scu_link_layer_register_read(phy, clock_skew_management) + +/* This macro writes the CLKSM register */ +#define SCU_SAS_CLKSM_WRITE(phy, value) \ + scu_link_layer_register_write(phy, clock_skew_management, value) + /* / This macro reads the PHY Capacity register */ #define SCU_SAS_PHYCAP_READ(phy) \ scu_link_layer_register_read(phy, phy_capabilities) diff --git a/drivers/scsi/isci/core/scu_registers.h b/drivers/scsi/isci/core/scu_registers.h index de2ce93..05a1411 100644 --- a/drivers/scsi/isci/core/scu_registers.h +++ b/drivers/scsi/isci/core/scu_registers.h @@ -611,6 +611,13 @@ #define SCU_SAS_PCFG_GEN_BIT(name) \ SCU_GEN_BIT(SCU_SAS_PHY_CONFIGURATION_ ## name) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_SHIFT (0) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_GENERAL_MASK (0x000007FF) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_SHIFT (16) +#define SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_CONNECTED_MASK (0x00ff0000) + +#define SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(name, value) \ + SCU_GEN_VALUE(SCU_LINK_LAYER_ALIGN_INSERTION_FREQUENCY_##name, value) #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_SHIFT (0) #define SCU_LINK_LAYER_ENABLE_SPINUP_CONTROL_COUNT_MASK (0x0003FFFF) -- 2.7.4