Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07373a5c authored by Henryk Dembkowski's avatar Henryk Dembkowski Committed by Dan Williams
Browse files

isci: add support for 2 more oem parmeters



1/ add OEM paramater support for mode_type (MPC vs APC)
2/ add OEM parameter support for max_number_concurrent_device_spin_up
3/ cleanup scic_sds_controller_start_next_phy

todo: hook up the amp control afe parameters into the afe init code

Signed-off-by: default avatarHenryk Dembkowski <henryk.dembkowski@intel.com>
Signed-off-by: default avatarJacek Danecki <Jacek.Danecki@intel.com>
[cleaned up scic_sds_controller_start_next_phy]
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 8db37aab
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -224,6 +224,8 @@ union scic_user_parameters {
 */
#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF

#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4

/**
 * This structure/union specifies the various different OEM parameter sets
 *    available.  Each type is specific to a hardware controller version.
@@ -237,7 +239,6 @@ union scic_oem_parameters {
	 * 1.
	 */
	struct scic_sds_oem_params sds1;

};

/**
+148 −123
Original line number Diff line number Diff line
@@ -293,6 +293,7 @@ void scic_sds_controller_initialize_power_control(
		);

	this_controller->power_control.phys_waiting = 0;
	this_controller->power_control.phys_granted_power = 0;
}

/* --------------------------------------------------------------------------- */
@@ -770,31 +771,6 @@ void scic_sds_controller_timeout_handler(
			__func__);
}

/**
 * scic_sds_controller_get_port_configuration_mode
 * @this_controller: This is the controller to use to determine if we are using
 *    manual or automatic port configuration.
 *
 * SCIC_PORT_CONFIGURATION_MODE
 */
enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
	struct scic_sds_controller *this_controller)
{
	u32 index;
	enum SCIC_PORT_CONFIGURATION_MODE mode;

	mode = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;

	for (index = 0; index < SCI_MAX_PORTS; index++) {
		if (this_controller->oem_parameters.sds1.ports[index].phy_mask != 0) {
			mode = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
			break;
		}
	}

	return mode;
}

enum sci_status scic_sds_controller_stop_ports(struct scic_sds_controller *scic)
{
	u32 index;
@@ -859,7 +835,7 @@ void scic_sds_controller_phy_timer_stop(

/**
 * This method is called internally by the controller object to start the next
 *    phy on the controller.  If all the phys have been starte, then this
 *    phy on the controller.  If all the phys have been started, then this
 *    method will attempt to transition the controller to the READY state and
 *    inform the user (scic_cb_controller_start_complete()).
 * @this_controller: This parameter specifies the controller object for which
@@ -867,101 +843,88 @@ void scic_sds_controller_phy_timer_stop(
 *
 * enum sci_status
 */
enum sci_status scic_sds_controller_start_next_phy(
	struct scic_sds_controller *this_controller)
enum sci_status scic_sds_controller_start_next_phy(struct scic_sds_controller *scic)
{
	struct scic_sds_oem_params *oem = &scic->oem_parameters.sds1;
	struct scic_sds_phy *sci_phy;
	enum sci_status status;

	status = SCI_SUCCESS;

	if (this_controller->phy_startup_timer_pending == false) {
		if (this_controller->next_phy_to_start == SCI_MAX_PHYS) {
	if (scic->phy_startup_timer_pending)
		return status;

	if (scic->next_phy_to_start >= SCI_MAX_PHYS) {
		bool is_controller_start_complete = true;
			struct scic_sds_phy *the_phy;
		u32 state;
		u8 index;

		for (index = 0; index < SCI_MAX_PHYS; index++) {
				the_phy = &this_controller->phy_table[index];
			sci_phy = &scic->phy_table[index];
			state = sci_phy->parent.state_machine.current_state_id;

				if (scic_sds_phy_get_port(the_phy) != NULL) {
					/**
					 * The controller start operation is complete if and only
					 * if:
			if (!scic_sds_phy_get_port(sci_phy))
				continue;

			/* The controller start operation is complete iff:
			 * - all links have been given an opportunity to start
			 * - have no indication of a connected device
			 * - have an indication of a connected device and it has
			 *   finished the link training process.
			 */
					if (
						(
							(the_phy->is_in_link_training == false)
							&& (the_phy->parent.state_machine.current_state_id
							    == SCI_BASE_PHY_STATE_INITIAL)
						)
						|| (
							(the_phy->is_in_link_training == false)
							&& (the_phy->parent.state_machine.current_state_id
							    == SCI_BASE_PHY_STATE_STOPPED)
							)
						|| (
							(the_phy->is_in_link_training == true)
							&& (the_phy->parent.state_machine.current_state_id
							    == SCI_BASE_PHY_STATE_STARTING)
							)
						) {
			if ((sci_phy->is_in_link_training == false &&
			     state == SCI_BASE_PHY_STATE_INITIAL) ||
			    (sci_phy->is_in_link_training == false &&
			     state == SCI_BASE_PHY_STATE_STOPPED) ||
			    (sci_phy->is_in_link_training == true &&
			     state == SCI_BASE_PHY_STATE_STARTING)) {
				is_controller_start_complete = false;
				break;
			}
		}
			}

		/*
		 * The controller has successfully finished the start process.
		 * Inform the SCI Core user and transition to the READY state. */
		if (is_controller_start_complete == true) {
				scic_sds_controller_transition_to_ready(
					this_controller, SCI_SUCCESS
					);
				scic_sds_controller_phy_timer_stop(this_controller);
			scic_sds_controller_transition_to_ready(scic, SCI_SUCCESS);
			scic_sds_controller_phy_timer_stop(scic);
		}
	} else {
			struct scic_sds_phy *the_phy;
		sci_phy = &scic->phy_table[scic->next_phy_to_start];

			the_phy = &this_controller->phy_table[this_controller->next_phy_to_start];
		if (oem->controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
			if (scic_sds_phy_get_port(sci_phy) == NULL) {
				scic->next_phy_to_start++;

			if (
				scic_sds_controller_get_port_configuration_mode(this_controller)
				== SCIC_PORT_MANUAL_CONFIGURATION_MODE
				) {
				if (scic_sds_phy_get_port(the_phy) == NULL) {
					this_controller->next_phy_to_start++;

					/*
					 * Caution recursion ahead be forwarned
				/* Caution recursion ahead be forwarned
				 *
					 * The PHY was never added to a PORT in MPC mode so start the next phy in sequence
					 * This phy will never go link up and will not draw power the OEM parameters either
					 * configured the phy incorrectly for the PORT or it was never assigned to a PORT */
					return scic_sds_controller_start_next_phy(this_controller);
				 * The PHY was never added to a PORT in MPC mode
				 * so start the next phy in sequence This phy
				 * will never go link up and will not draw power
				 * the OEM parameters either configured the phy
				 * incorrectly for the PORT or it was never
				 * assigned to a PORT
				 */
				return scic_sds_controller_start_next_phy(scic);
			}
		}

			status = scic_sds_phy_start(the_phy);
		status = scic_sds_phy_start(sci_phy);

		if (status == SCI_SUCCESS) {
				scic_sds_controller_phy_timer_start(this_controller);
			scic_sds_controller_phy_timer_start(scic);
		} else {
				dev_warn(scic_to_dev(this_controller),
			dev_warn(scic_to_dev(scic),
				 "%s: Controller stop operation failed "
				 "to stop phy %d because of status "
				 "%d.\n",
				 __func__,
					 this_controller->phy_table[this_controller->next_phy_to_start].phy_index,
				 scic->phy_table[scic->next_phy_to_start].phy_index,
				 status);
		}

			this_controller->next_phy_to_start++;
		}
		scic->next_phy_to_start++;
	}

	return status;
@@ -1058,6 +1021,31 @@ static void scic_sds_controller_power_control_timer_start(
	this_controller->power_control.timer_started = true;
}

/**
 * This method stops the power control timer for this controller object.
 *
 * @param scic
 */
void scic_sds_controller_power_control_timer_stop(struct scic_sds_controller *scic)
{
	if (scic->power_control.timer_started) {
		isci_event_timer_stop(scic, scic->power_control.timer);
		scic->power_control.timer_started = false;
	}
}

/**
 * This method stops and starts the power control timer for this controller object.
 *
 * @param scic
 */
void scic_sds_controller_power_control_timer_restart(
	struct scic_sds_controller *scic)
{
	scic_sds_controller_power_control_timer_stop(scic);
	scic_sds_controller_power_control_timer_start(scic);
}

/**
 *
 *
@@ -1070,6 +1058,8 @@ static void scic_sds_controller_power_control_timer_handler(

	this_controller = (struct scic_sds_controller *)controller;

	this_controller->power_control.phys_granted_power = 0;

	if (this_controller->power_control.phys_waiting == 0) {
		this_controller->power_control.timer_started = false;
	} else {
@@ -1081,19 +1071,24 @@ static void scic_sds_controller_power_control_timer_handler(
		     && (this_controller->power_control.phys_waiting != 0);
		     i++) {
			if (this_controller->power_control.requesters[i] != NULL) {
				if (this_controller->power_control.phys_granted_power <
				    this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
					the_phy = this_controller->power_control.requesters[i];
					this_controller->power_control.requesters[i] = NULL;
					this_controller->power_control.phys_waiting--;
					this_controller->power_control.phys_granted_power++;
					scic_sds_phy_consume_power_handler(the_phy);
				} else {
					break;
				}
			}
		}

		/*
		 * It doesn't matter if the power list is empty, we need to start the
		 * timer in case another phy becomes ready. */
		 * timer in case another phy becomes ready.
		 */
		scic_sds_controller_power_control_timer_start(this_controller);

		scic_sds_phy_consume_power_handler(the_phy);
	}
}

@@ -1109,15 +1104,20 @@ void scic_sds_controller_power_control_queue_insert(
{
	BUG_ON(the_phy == NULL);

	if (
		(this_controller->power_control.timer_started)
		&& (this_controller->power_control.requesters[the_phy->phy_index] == NULL)
		) {
	if (this_controller->power_control.phys_granted_power <
	    this_controller->oem_parameters.sds1.controller.max_concurrent_dev_spin_up) {
		this_controller->power_control.phys_granted_power++;
		scic_sds_phy_consume_power_handler(the_phy);

		/*
		 * stop and start the power_control timer. When the timer fires, the
		 * no_of_phys_granted_power will be set to 0
		 */
		scic_sds_controller_power_control_timer_restart(this_controller);
	} else {
		/* Add the phy in the waiting list */
		this_controller->power_control.requesters[the_phy->phy_index] = the_phy;
		this_controller->power_control.phys_waiting++;
	} else {
		scic_sds_controller_power_control_timer_start(this_controller);
		scic_sds_phy_consume_power_handler(the_phy);
	}
}

@@ -2021,7 +2021,7 @@ void scic_sds_controller_release_frame(
 * This method sets user parameters and OEM parameters to default values.
 *    Users can override these values utilizing the scic_user_parameters_set()
 *    and scic_oem_parameters_set() methods.
 * @controller: This parameter specifies the controller for which to set the
 * @scic: This parameter specifies the controller for which to set the
 *    configuration parameters to their default values.
 *
 */
@@ -2029,6 +2029,12 @@ static void scic_sds_controller_set_default_config_parameters(struct scic_sds_co
{
	u16 index;

	/* Default to APC mode. */
	scic->oem_parameters.sds1.controller.mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;

	/* Default to APC mode. */
	scic->oem_parameters.sds1.controller.max_concurrent_dev_spin_up = 1;

	/* Default to no SSC operation. */
	scic->oem_parameters.sds1.controller.do_enable_ssc = false;

@@ -2607,6 +2613,7 @@ enum sci_status scic_oem_parameters_set(
		    == SCI_BASE_CONTROLLER_STATE_INITIALIZED)
		) {
		u16 index;
		u8  combined_phy_mask = 0;

		/*
		 * Validate the oem parameters.  If they are not legal, then
@@ -2626,6 +2633,24 @@ enum sci_status scic_oem_parameters_set(
			}
		}

		if (scic_parms->sds1.controller.mode_type == SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE) {
			for (index = 0; index < SCI_MAX_PHYS; index++) {
				if (scic_parms->sds1.ports[index].phy_mask != 0)
					return SCI_FAILURE_INVALID_PARAMETER_VALUE;
			}
		} else if (scic_parms->sds1.controller.mode_type == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
			for (index = 0; index < SCI_MAX_PHYS; index++)
				combined_phy_mask |= scic_parms->sds1.ports[index].phy_mask;

			if (combined_phy_mask == 0)
				return SCI_FAILURE_INVALID_PARAMETER_VALUE;
		} else {
			return SCI_FAILURE_INVALID_PARAMETER_VALUE;
		}

		if (scic_parms->sds1.controller.max_concurrent_dev_spin_up > MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT)
			return SCI_FAILURE_INVALID_PARAMETER_VALUE;

		memcpy(&scic->oem_parameters, scic_parms, sizeof(*scic_parms));
		return SCI_SUCCESS;
	}
+5 −25
Original line number Diff line number Diff line
@@ -121,23 +121,6 @@ enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS {
};


/**
 *
 *
 * 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.
 * MPC Manual PORT configuration mode is defined by the OEM configuration
 * parameters providing a PHY_MASK value for any PORT.  It is assumed that any
 * PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
 * A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
 * being assigned is sufficient to declare manual PORT configuration.
 */
enum SCIC_PORT_CONFIGURATION_MODE {
	SCIC_PORT_MANUAL_CONFIGURATION_MODE,
	SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
};

/**
 * struct scic_power_control -
 *
@@ -163,6 +146,11 @@ struct scic_power_control {
	 */
	u8 phys_waiting;

	/**
	 * This field is used to keep track of how many phys have been granted to consume power
	 */
	u8 phys_granted_power;

	/**
	 * This field is an array of phys that we are waiting on. The phys are direct
	 * mapped into requesters via struct scic_sds_phy.phy_index
@@ -560,14 +548,6 @@ u32 scic_sds_controller_get_object_size(void);

/* --------------------------------------------------------------------------- */


/* --------------------------------------------------------------------------- */

enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
	struct scic_sds_controller *this_controller);

/* --------------------------------------------------------------------------- */

void scic_sds_controller_post_request(
	struct scic_sds_controller *this_controller,
	u32 request);
+1 −1
Original line number Diff line number Diff line
@@ -822,7 +822,7 @@ enum sci_status scic_sds_port_configuration_agent_initialize(
	enum sci_status status = SCI_SUCCESS;
	enum SCIC_PORT_CONFIGURATION_MODE mode;

	mode = scic_sds_controller_get_port_configuration_mode(controller);
	mode = controller->oem_parameters.sds1.controller.mode_type;

	if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
		status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
+4 −3
Original line number Diff line number Diff line
#ifndef _CREATE_FW_H_
#define _CREATE_FW_H_
#include "../probe_roms.h"


/* we are configuring for 2 SCUs */
@@ -24,16 +25,16 @@ static const int num_elements = 2;
 * if there is a port/phy on which you do not wish to override the default
 * values, use the value assigned to UNINIT_PARAM (255).
 */
/* discovery mode type (port auto config mode by default ) */
#ifdef MPC
static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
				     {1, 2, 4, 8} };
#else	/* APC (default) */
static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
static const __u8 phy_mask[2][4];
#endif

/* discovery mode type (port auto config mode by default ) */
static const int mode_type;

/* Maximum number of concurrent device spin up */
static const int max_num_concurrent_dev_spin_up = 1;

Loading