1483 lines · c
1/*2 * This file is provided under a dual BSD/GPLv2 license. When using or3 * redistributing this file, you may do so under either license.4 *5 * GPL LICENSE SUMMARY6 *7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.8 *9 * This program is free software; you can redistribute it and/or modify10 * it under the terms of version 2 of the GNU General Public License as11 * published by the Free Software Foundation.12 *13 * This program is distributed in the hope that it will be useful, but14 * WITHOUT ANY WARRANTY; without even the implied warranty of15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU16 * General Public License for more details.17 *18 * You should have received a copy of the GNU General Public License19 * along with this program; if not, write to the Free Software20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.21 * The full GNU General Public License is included in this distribution22 * in the file called LICENSE.GPL.23 *24 * BSD LICENSE25 *26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.27 * All rights reserved.28 *29 * Redistribution and use in source and binary forms, with or without30 * modification, are permitted provided that the following conditions31 * are met:32 *33 * * Redistributions of source code must retain the above copyright34 * notice, this list of conditions and the following disclaimer.35 * * Redistributions in binary form must reproduce the above copyright36 * notice, this list of conditions and the following disclaimer in37 * the documentation and/or other materials provided with the38 * distribution.39 * * Neither the name of Intel Corporation nor the names of its40 * contributors may be used to endorse or promote products derived41 * from this software without specific prior written permission.42 *43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.54 */55 56#include "isci.h"57#include "host.h"58#include "phy.h"59#include "scu_event_codes.h"60#include "probe_roms.h"61 62#undef C63#define C(a) (#a)64static const char *phy_state_name(enum sci_phy_states state)65{66 static const char * const strings[] = PHY_STATES;67 68 return strings[state];69}70#undef C71 72/* Maximum arbitration wait time in micro-seconds */73#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700)74 75enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy)76{77 return iphy->max_negotiated_speed;78}79 80static struct isci_host *phy_to_host(struct isci_phy *iphy)81{82 struct isci_phy *table = iphy - iphy->phy_index;83 struct isci_host *ihost = container_of(table, typeof(*ihost), phys[0]);84 85 return ihost;86}87 88static struct device *sciphy_to_dev(struct isci_phy *iphy)89{90 return &phy_to_host(iphy)->pdev->dev;91}92 93static enum sci_status94sci_phy_transport_layer_initialization(struct isci_phy *iphy,95 struct scu_transport_layer_registers __iomem *reg)96{97 u32 tl_control;98 99 iphy->transport_layer_registers = reg;100 101 writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX,102 &iphy->transport_layer_registers->stp_rni);103 104 /*105 * Hardware team recommends that we enable the STP prefetch for all106 * transports107 */108 tl_control = readl(&iphy->transport_layer_registers->control);109 tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);110 writel(tl_control, &iphy->transport_layer_registers->control);111 112 return SCI_SUCCESS;113}114 115static enum sci_status116sci_phy_link_layer_initialization(struct isci_phy *iphy,117 struct scu_link_layer_registers __iomem *llr)118{119 struct isci_host *ihost = iphy->owning_port->owning_controller;120 struct sci_phy_user_params *phy_user;121 struct sci_phy_oem_params *phy_oem;122 int phy_idx = iphy->phy_index;123 struct sci_phy_cap phy_cap;124 u32 phy_configuration;125 u32 parity_check = 0;126 u32 parity_count = 0;127 u32 llctl, link_rate;128 u32 clksm_value = 0;129 u32 sp_timeouts = 0;130 131 phy_user = &ihost->user_parameters.phys[phy_idx];132 phy_oem = &ihost->oem_parameters.phys[phy_idx];133 iphy->link_layer_registers = llr;134 135 /* Set our IDENTIFY frame data */136 #define SCI_END_DEVICE 0x01137 138 writel(SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) |139 SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) |140 SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |141 SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |142 SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),143 &llr->transmit_identification);144 145 /* Write the device SAS Address */146 writel(0xFEDCBA98, &llr->sas_device_name_high);147 writel(phy_idx, &llr->sas_device_name_low);148 149 /* Write the source SAS Address */150 writel(phy_oem->sas_address.high, &llr->source_sas_address_high);151 writel(phy_oem->sas_address.low, &llr->source_sas_address_low);152 153 /* Clear and Set the PHY Identifier */154 writel(0, &llr->identify_frame_phy_id);155 writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx), &llr->identify_frame_phy_id);156 157 /* Change the initial state of the phy configuration register */158 phy_configuration = readl(&llr->phy_configuration);159 160 /* Hold OOB state machine in reset */161 phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);162 writel(phy_configuration, &llr->phy_configuration);163 164 /* Configure the SNW capabilities */165 phy_cap.all = 0;166 phy_cap.start = 1;167 phy_cap.gen3_no_ssc = 1;168 phy_cap.gen2_no_ssc = 1;169 phy_cap.gen1_no_ssc = 1;170 if (ihost->oem_parameters.controller.do_enable_ssc) {171 struct scu_afe_registers __iomem *afe = &ihost->scu_registers->afe;172 struct scu_afe_transceiver __iomem *xcvr = &afe->scu_afe_xcvr[phy_idx];173 struct isci_pci_info *pci_info = to_pci_info(ihost->pdev);174 bool en_sas = false;175 bool en_sata = false;176 u32 sas_type = 0;177 u32 sata_spread = 0x2;178 u32 sas_spread = 0x2;179 180 phy_cap.gen3_ssc = 1;181 phy_cap.gen2_ssc = 1;182 phy_cap.gen1_ssc = 1;183 184 if (pci_info->orom->hdr.version < ISCI_ROM_VER_1_1)185 en_sas = en_sata = true;186 else {187 sata_spread = ihost->oem_parameters.controller.ssc_sata_tx_spread_level;188 sas_spread = ihost->oem_parameters.controller.ssc_sas_tx_spread_level;189 190 if (sata_spread)191 en_sata = true;192 193 if (sas_spread) {194 en_sas = true;195 sas_type = ihost->oem_parameters.controller.ssc_sas_tx_type;196 }197 198 }199 200 if (en_sas) {201 u32 reg;202 203 reg = readl(&xcvr->afe_xcvr_control0);204 reg |= (0x00100000 | (sas_type << 19));205 writel(reg, &xcvr->afe_xcvr_control0);206 207 reg = readl(&xcvr->afe_tx_ssc_control);208 reg |= sas_spread << 8;209 writel(reg, &xcvr->afe_tx_ssc_control);210 }211 212 if (en_sata) {213 u32 reg;214 215 reg = readl(&xcvr->afe_tx_ssc_control);216 reg |= sata_spread;217 writel(reg, &xcvr->afe_tx_ssc_control);218 219 reg = readl(&llr->stp_control);220 reg |= 1 << 12;221 writel(reg, &llr->stp_control);222 }223 }224 225 /* The SAS specification indicates that the phy_capabilities that226 * are transmitted shall have an even parity. Calculate the parity.227 */228 parity_check = phy_cap.all;229 while (parity_check != 0) {230 if (parity_check & 0x1)231 parity_count++;232 parity_check >>= 1;233 }234 235 /* If parity indicates there are an odd number of bits set, then236 * set the parity bit to 1 in the phy capabilities.237 */238 if ((parity_count % 2) != 0)239 phy_cap.parity = 1;240 241 writel(phy_cap.all, &llr->phy_capabilities);242 243 /* Set the enable spinup period but disable the ability to send244 * notify enable spinup245 */246 writel(SCU_ENSPINUP_GEN_VAL(COUNT,247 phy_user->notify_enable_spin_up_insertion_frequency),248 &llr->notify_enable_spinup_control);249 250 /* Write the ALIGN Insertion Ferequency for connected phy and251 * inpendent of connected state252 */253 clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED,254 phy_user->in_connection_align_insertion_frequency);255 256 clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,257 phy_user->align_insertion_frequency);258 259 writel(clksm_value, &llr->clock_skew_management);260 261 if (is_c0(ihost->pdev) || is_c1(ihost->pdev)) {262 writel(0x04210400, &llr->afe_lookup_table_control);263 writel(0x020A7C05, &llr->sas_primitive_timeout);264 } else265 writel(0x02108421, &llr->afe_lookup_table_control);266 267 llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,268 (u8)ihost->user_parameters.no_outbound_task_timeout);269 270 switch (phy_user->max_speed_generation) {271 case SCIC_SDS_PARM_GEN3_SPEED:272 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3;273 break;274 case SCIC_SDS_PARM_GEN2_SPEED:275 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2;276 break;277 default:278 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1;279 break;280 }281 llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);282 writel(llctl, &llr->link_layer_control);283 284 sp_timeouts = readl(&llr->sas_phy_timeouts);285 286 /* Clear the default 0x36 (54us) RATE_CHANGE timeout value. */287 sp_timeouts &= ~SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0xFF);288 289 /* Set RATE_CHANGE timeout value to 0x3B (59us). This ensures SCU can290 * lock with 3Gb drive when SCU max rate is set to 1.5Gb.291 */292 sp_timeouts |= SCU_SAS_PHYTOV_GEN_VAL(RATE_CHANGE, 0x3B);293 294 writel(sp_timeouts, &llr->sas_phy_timeouts);295 296 if (is_a2(ihost->pdev)) {297 /* Program the max ARB time for the PHY to 700us so we298 * inter-operate with the PMC expander which shuts down299 * PHYs if the expander PHY generates too many breaks.300 * This time value will guarantee that the initiator PHY301 * will generate the break.302 */303 writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,304 &llr->maximum_arbitration_wait_timer_timeout);305 }306 307 /* Disable link layer hang detection, rely on the OS timeout for308 * I/O timeouts.309 */310 writel(0, &llr->link_layer_hang_detection_timeout);311 312 /* We can exit the initial state to the stopped state */313 sci_change_state(&iphy->sm, SCI_PHY_STOPPED);314 315 return SCI_SUCCESS;316}317 318static void phy_sata_timeout(struct timer_list *t)319{320 struct sci_timer *tmr = from_timer(tmr, t, timer);321 struct isci_phy *iphy = container_of(tmr, typeof(*iphy), sata_timer);322 struct isci_host *ihost = iphy->owning_port->owning_controller;323 unsigned long flags;324 325 spin_lock_irqsave(&ihost->scic_lock, flags);326 327 if (tmr->cancel)328 goto done;329 330 dev_dbg(sciphy_to_dev(iphy),331 "%s: SCIC SDS Phy 0x%p did not receive signature fis before "332 "timeout.\n",333 __func__,334 iphy);335 336 sci_change_state(&iphy->sm, SCI_PHY_STARTING);337done:338 spin_unlock_irqrestore(&ihost->scic_lock, flags);339}340 341/**342 * phy_get_non_dummy_port() - This method returns the port currently containing343 * this phy. If the phy is currently contained by the dummy port, then the phy344 * is considered to not be part of a port.345 *346 * @iphy: This parameter specifies the phy for which to retrieve the347 * containing port.348 *349 * This method returns a handle to a port that contains the supplied phy.350 * NULL This value is returned if the phy is not part of a real351 * port (i.e. it's contained in the dummy port). !NULL All other352 * values indicate a handle/pointer to the port containing the phy.353 */354struct isci_port *phy_get_non_dummy_port(struct isci_phy *iphy)355{356 struct isci_port *iport = iphy->owning_port;357 358 if (iport->physical_port_index == SCIC_SDS_DUMMY_PORT)359 return NULL;360 361 return iphy->owning_port;362}363 364/*365 * sci_phy_set_port() - This method will assign a port to the phy object.366 */367void sci_phy_set_port(368 struct isci_phy *iphy,369 struct isci_port *iport)370{371 iphy->owning_port = iport;372 373 if (iphy->bcn_received_while_port_unassigned) {374 iphy->bcn_received_while_port_unassigned = false;375 sci_port_broadcast_change_received(iphy->owning_port, iphy);376 }377}378 379enum sci_status sci_phy_initialize(struct isci_phy *iphy,380 struct scu_transport_layer_registers __iomem *tl,381 struct scu_link_layer_registers __iomem *ll)382{383 /* Perfrom the initialization of the TL hardware */384 sci_phy_transport_layer_initialization(iphy, tl);385 386 /* Perofrm the initialization of the PE hardware */387 sci_phy_link_layer_initialization(iphy, ll);388 389 /* There is nothing that needs to be done in this state just390 * transition to the stopped state391 */392 sci_change_state(&iphy->sm, SCI_PHY_STOPPED);393 394 return SCI_SUCCESS;395}396 397/**398 * sci_phy_setup_transport() - This method assigns the direct attached device ID for this phy.399 *400 * @iphy: The phy for which the direct attached device id is to401 * be assigned.402 * @device_id: The direct attached device ID to assign to the phy.403 * This will either be the RNi for the device or an invalid RNi if there404 * is no current device assigned to the phy.405 */406void sci_phy_setup_transport(struct isci_phy *iphy, u32 device_id)407{408 u32 tl_control;409 410 writel(device_id, &iphy->transport_layer_registers->stp_rni);411 412 /*413 * The read should guarantee that the first write gets posted414 * before the next write415 */416 tl_control = readl(&iphy->transport_layer_registers->control);417 tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);418 writel(tl_control, &iphy->transport_layer_registers->control);419}420 421static void sci_phy_suspend(struct isci_phy *iphy)422{423 u32 scu_sas_pcfg_value;424 425 scu_sas_pcfg_value =426 readl(&iphy->link_layer_registers->phy_configuration);427 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);428 writel(scu_sas_pcfg_value,429 &iphy->link_layer_registers->phy_configuration);430 431 sci_phy_setup_transport(iphy, SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);432}433 434void sci_phy_resume(struct isci_phy *iphy)435{436 u32 scu_sas_pcfg_value;437 438 scu_sas_pcfg_value =439 readl(&iphy->link_layer_registers->phy_configuration);440 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);441 writel(scu_sas_pcfg_value,442 &iphy->link_layer_registers->phy_configuration);443}444 445void sci_phy_get_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas)446{447 sas->high = readl(&iphy->link_layer_registers->source_sas_address_high);448 sas->low = readl(&iphy->link_layer_registers->source_sas_address_low);449}450 451void sci_phy_get_attached_sas_address(struct isci_phy *iphy, struct sci_sas_address *sas)452{453 struct sas_identify_frame *iaf;454 455 iaf = &iphy->frame_rcvd.iaf;456 memcpy(sas, iaf->sas_addr, SAS_ADDR_SIZE);457}458 459void sci_phy_get_protocols(struct isci_phy *iphy, struct sci_phy_proto *proto)460{461 proto->all = readl(&iphy->link_layer_registers->transmit_identification);462}463 464enum sci_status sci_phy_start(struct isci_phy *iphy)465{466 enum sci_phy_states state = iphy->sm.current_state_id;467 468 if (state != SCI_PHY_STOPPED) {469 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",470 __func__, phy_state_name(state));471 return SCI_FAILURE_INVALID_STATE;472 }473 474 sci_change_state(&iphy->sm, SCI_PHY_STARTING);475 return SCI_SUCCESS;476}477 478enum sci_status sci_phy_stop(struct isci_phy *iphy)479{480 enum sci_phy_states state = iphy->sm.current_state_id;481 482 switch (state) {483 case SCI_PHY_SUB_INITIAL:484 case SCI_PHY_SUB_AWAIT_OSSP_EN:485 case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN:486 case SCI_PHY_SUB_AWAIT_SAS_POWER:487 case SCI_PHY_SUB_AWAIT_SATA_POWER:488 case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:489 case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:490 case SCI_PHY_SUB_AWAIT_SIG_FIS_UF:491 case SCI_PHY_SUB_FINAL:492 case SCI_PHY_READY:493 break;494 default:495 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",496 __func__, phy_state_name(state));497 return SCI_FAILURE_INVALID_STATE;498 }499 500 sci_change_state(&iphy->sm, SCI_PHY_STOPPED);501 return SCI_SUCCESS;502}503 504enum sci_status sci_phy_reset(struct isci_phy *iphy)505{506 enum sci_phy_states state = iphy->sm.current_state_id;507 508 if (state != SCI_PHY_READY) {509 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",510 __func__, phy_state_name(state));511 return SCI_FAILURE_INVALID_STATE;512 }513 514 sci_change_state(&iphy->sm, SCI_PHY_RESETTING);515 return SCI_SUCCESS;516}517 518enum sci_status sci_phy_consume_power_handler(struct isci_phy *iphy)519{520 enum sci_phy_states state = iphy->sm.current_state_id;521 522 switch (state) {523 case SCI_PHY_SUB_AWAIT_SAS_POWER: {524 u32 enable_spinup;525 526 enable_spinup = readl(&iphy->link_layer_registers->notify_enable_spinup_control);527 enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);528 writel(enable_spinup, &iphy->link_layer_registers->notify_enable_spinup_control);529 530 /* Change state to the final state this substate machine has run to completion */531 sci_change_state(&iphy->sm, SCI_PHY_SUB_FINAL);532 533 return SCI_SUCCESS;534 }535 case SCI_PHY_SUB_AWAIT_SATA_POWER: {536 u32 scu_sas_pcfg_value;537 538 /* Release the spinup hold state and reset the OOB state machine */539 scu_sas_pcfg_value =540 readl(&iphy->link_layer_registers->phy_configuration);541 scu_sas_pcfg_value &=542 ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));543 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);544 writel(scu_sas_pcfg_value,545 &iphy->link_layer_registers->phy_configuration);546 547 /* Now restart the OOB operation */548 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);549 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);550 writel(scu_sas_pcfg_value,551 &iphy->link_layer_registers->phy_configuration);552 553 /* Change state to the final state this substate machine has run to completion */554 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_PHY_EN);555 556 return SCI_SUCCESS;557 }558 default:559 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",560 __func__, phy_state_name(state));561 return SCI_FAILURE_INVALID_STATE;562 }563}564 565static void sci_phy_start_sas_link_training(struct isci_phy *iphy)566{567 /* continue the link training for the phy as if it were a SAS PHY568 * instead of a SATA PHY. This is done because the completion queue had a SAS569 * PHY DETECTED event when the state machine was expecting a SATA PHY event.570 */571 u32 phy_control;572 573 phy_control = readl(&iphy->link_layer_registers->phy_configuration);574 phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);575 writel(phy_control,576 &iphy->link_layer_registers->phy_configuration);577 578 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SAS_SPEED_EN);579 580 iphy->protocol = SAS_PROTOCOL_SSP;581}582 583static void sci_phy_start_sata_link_training(struct isci_phy *iphy)584{585 /* This method continues the link training for the phy as if it were a SATA PHY586 * instead of a SAS PHY. This is done because the completion queue had a SATA587 * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none588 */589 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_POWER);590 591 iphy->protocol = SAS_PROTOCOL_SATA;592}593 594/**595 * sci_phy_complete_link_training - perform processing common to596 * all protocols upon completion of link training.597 * @iphy: This parameter specifies the phy object for which link training598 * has completed.599 * @max_link_rate: This parameter specifies the maximum link rate to be600 * associated with this phy.601 * @next_state: This parameter specifies the next state for the phy's starting602 * sub-state machine.603 *604 */605static void sci_phy_complete_link_training(struct isci_phy *iphy,606 enum sas_linkrate max_link_rate,607 u32 next_state)608{609 iphy->max_negotiated_speed = max_link_rate;610 611 sci_change_state(&iphy->sm, next_state);612}613 614static const char *phy_event_name(u32 event_code)615{616 switch (scu_get_event_code(event_code)) {617 case SCU_EVENT_PORT_SELECTOR_DETECTED:618 return "port selector";619 case SCU_EVENT_SENT_PORT_SELECTION:620 return "port selection";621 case SCU_EVENT_HARD_RESET_TRANSMITTED:622 return "tx hard reset";623 case SCU_EVENT_HARD_RESET_RECEIVED:624 return "rx hard reset";625 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:626 return "identify timeout";627 case SCU_EVENT_LINK_FAILURE:628 return "link fail";629 case SCU_EVENT_SATA_SPINUP_HOLD:630 return "sata spinup hold";631 case SCU_EVENT_SAS_15_SSC:632 case SCU_EVENT_SAS_15:633 return "sas 1.5";634 case SCU_EVENT_SAS_30_SSC:635 case SCU_EVENT_SAS_30:636 return "sas 3.0";637 case SCU_EVENT_SAS_60_SSC:638 case SCU_EVENT_SAS_60:639 return "sas 6.0";640 case SCU_EVENT_SATA_15_SSC:641 case SCU_EVENT_SATA_15:642 return "sata 1.5";643 case SCU_EVENT_SATA_30_SSC:644 case SCU_EVENT_SATA_30:645 return "sata 3.0";646 case SCU_EVENT_SATA_60_SSC:647 case SCU_EVENT_SATA_60:648 return "sata 6.0";649 case SCU_EVENT_SAS_PHY_DETECTED:650 return "sas detect";651 case SCU_EVENT_SATA_PHY_DETECTED:652 return "sata detect";653 default:654 return "unknown";655 }656}657 658#define phy_event_dbg(iphy, state, code) \659 dev_dbg(sciphy_to_dev(iphy), "phy-%d:%d: %s event: %s (%x)\n", \660 phy_to_host(iphy)->id, iphy->phy_index, \661 phy_state_name(state), phy_event_name(code), code)662 663#define phy_event_warn(iphy, state, code) \664 dev_warn(sciphy_to_dev(iphy), "phy-%d:%d: %s event: %s (%x)\n", \665 phy_to_host(iphy)->id, iphy->phy_index, \666 phy_state_name(state), phy_event_name(code), code)667 668 669static void scu_link_layer_set_txcomsas_timeout(struct isci_phy *iphy, u32 timeout)670{671 u32 val;672 673 /* Extend timeout */674 val = readl(&iphy->link_layer_registers->transmit_comsas_signal);675 val &= ~SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_MASK);676 val |= SCU_SAS_LLTXCOMSAS_GEN_VAL(NEGTIME, timeout);677 678 writel(val, &iphy->link_layer_registers->transmit_comsas_signal);679}680 681enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code)682{683 enum sci_phy_states state = iphy->sm.current_state_id;684 685 switch (state) {686 case SCI_PHY_SUB_AWAIT_OSSP_EN:687 switch (scu_get_event_code(event_code)) {688 case SCU_EVENT_SAS_PHY_DETECTED:689 sci_phy_start_sas_link_training(iphy);690 iphy->is_in_link_training = true;691 break;692 case SCU_EVENT_SATA_SPINUP_HOLD:693 sci_phy_start_sata_link_training(iphy);694 iphy->is_in_link_training = true;695 break;696 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:697 /* Extend timeout value */698 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);699 700 /* Start the oob/sn state machine over again */701 sci_change_state(&iphy->sm, SCI_PHY_STARTING);702 break;703 default:704 phy_event_dbg(iphy, state, event_code);705 return SCI_FAILURE;706 }707 return SCI_SUCCESS;708 case SCI_PHY_SUB_AWAIT_SAS_SPEED_EN:709 switch (scu_get_event_code(event_code)) {710 case SCU_EVENT_SAS_PHY_DETECTED:711 /*712 * Why is this being reported again by the controller?713 * We would re-enter this state so just stay here */714 break;715 case SCU_EVENT_SAS_15:716 case SCU_EVENT_SAS_15_SSC:717 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_1_5_GBPS,718 SCI_PHY_SUB_AWAIT_IAF_UF);719 break;720 case SCU_EVENT_SAS_30:721 case SCU_EVENT_SAS_30_SSC:722 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_3_0_GBPS,723 SCI_PHY_SUB_AWAIT_IAF_UF);724 break;725 case SCU_EVENT_SAS_60:726 case SCU_EVENT_SAS_60_SSC:727 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_6_0_GBPS,728 SCI_PHY_SUB_AWAIT_IAF_UF);729 break;730 case SCU_EVENT_SATA_SPINUP_HOLD:731 /*732 * We were doing SAS PHY link training and received a SATA PHY event733 * continue OOB/SN as if this were a SATA PHY */734 sci_phy_start_sata_link_training(iphy);735 break;736 case SCU_EVENT_LINK_FAILURE:737 /* Change the timeout value to default */738 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);739 740 /* Link failure change state back to the starting state */741 sci_change_state(&iphy->sm, SCI_PHY_STARTING);742 break;743 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:744 /* Extend the timeout value */745 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);746 747 /* Start the oob/sn state machine over again */748 sci_change_state(&iphy->sm, SCI_PHY_STARTING);749 break;750 default:751 phy_event_warn(iphy, state, event_code);752 return SCI_FAILURE;753 }754 return SCI_SUCCESS;755 case SCI_PHY_SUB_AWAIT_IAF_UF:756 switch (scu_get_event_code(event_code)) {757 case SCU_EVENT_SAS_PHY_DETECTED:758 /* Backup the state machine */759 sci_phy_start_sas_link_training(iphy);760 break;761 case SCU_EVENT_SATA_SPINUP_HOLD:762 /* We were doing SAS PHY link training and received a763 * SATA PHY event continue OOB/SN as if this were a764 * SATA PHY765 */766 sci_phy_start_sata_link_training(iphy);767 break;768 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:769 /* Extend the timeout value */770 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_EXTENDED);771 772 /* Start the oob/sn state machine over again */773 sci_change_state(&iphy->sm, SCI_PHY_STARTING);774 break;775 case SCU_EVENT_LINK_FAILURE:776 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);777 fallthrough;778 case SCU_EVENT_HARD_RESET_RECEIVED:779 /* Start the oob/sn state machine over again */780 sci_change_state(&iphy->sm, SCI_PHY_STARTING);781 break;782 default:783 phy_event_warn(iphy, state, event_code);784 return SCI_FAILURE;785 }786 return SCI_SUCCESS;787 case SCI_PHY_SUB_AWAIT_SAS_POWER:788 switch (scu_get_event_code(event_code)) {789 case SCU_EVENT_LINK_FAILURE:790 /* Change the timeout value to default */791 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);792 793 /* Link failure change state back to the starting state */794 sci_change_state(&iphy->sm, SCI_PHY_STARTING);795 break;796 default:797 phy_event_warn(iphy, state, event_code);798 return SCI_FAILURE;799 }800 return SCI_SUCCESS;801 case SCI_PHY_SUB_AWAIT_SATA_POWER:802 switch (scu_get_event_code(event_code)) {803 case SCU_EVENT_LINK_FAILURE:804 /* Change the timeout value to default */805 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);806 807 /* Link failure change state back to the starting state */808 sci_change_state(&iphy->sm, SCI_PHY_STARTING);809 break;810 case SCU_EVENT_SATA_SPINUP_HOLD:811 /* These events are received every 10ms and are812 * expected while in this state813 */814 break;815 816 case SCU_EVENT_SAS_PHY_DETECTED:817 /* There has been a change in the phy type before OOB/SN for the818 * SATA finished start down the SAS link traning path.819 */820 sci_phy_start_sas_link_training(iphy);821 break;822 823 default:824 phy_event_warn(iphy, state, event_code);825 return SCI_FAILURE;826 }827 return SCI_SUCCESS;828 case SCI_PHY_SUB_AWAIT_SATA_PHY_EN:829 switch (scu_get_event_code(event_code)) {830 case SCU_EVENT_LINK_FAILURE:831 /* Change the timeout value to default */832 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);833 834 /* Link failure change state back to the starting state */835 sci_change_state(&iphy->sm, SCI_PHY_STARTING);836 break;837 case SCU_EVENT_SATA_SPINUP_HOLD:838 /* These events might be received since we dont know how many may be in839 * the completion queue while waiting for power840 */841 break;842 case SCU_EVENT_SATA_PHY_DETECTED:843 iphy->protocol = SAS_PROTOCOL_SATA;844 845 /* We have received the SATA PHY notification change state */846 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN);847 break;848 case SCU_EVENT_SAS_PHY_DETECTED:849 /* There has been a change in the phy type before OOB/SN for the850 * SATA finished start down the SAS link traning path.851 */852 sci_phy_start_sas_link_training(iphy);853 break;854 default:855 phy_event_warn(iphy, state, event_code);856 return SCI_FAILURE;857 }858 return SCI_SUCCESS;859 case SCI_PHY_SUB_AWAIT_SATA_SPEED_EN:860 switch (scu_get_event_code(event_code)) {861 case SCU_EVENT_SATA_PHY_DETECTED:862 /*863 * The hardware reports multiple SATA PHY detected events864 * ignore the extras */865 break;866 case SCU_EVENT_SATA_15:867 case SCU_EVENT_SATA_15_SSC:868 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_1_5_GBPS,869 SCI_PHY_SUB_AWAIT_SIG_FIS_UF);870 break;871 case SCU_EVENT_SATA_30:872 case SCU_EVENT_SATA_30_SSC:873 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_3_0_GBPS,874 SCI_PHY_SUB_AWAIT_SIG_FIS_UF);875 break;876 case SCU_EVENT_SATA_60:877 case SCU_EVENT_SATA_60_SSC:878 sci_phy_complete_link_training(iphy, SAS_LINK_RATE_6_0_GBPS,879 SCI_PHY_SUB_AWAIT_SIG_FIS_UF);880 break;881 case SCU_EVENT_LINK_FAILURE:882 /* Change the timeout value to default */883 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);884 885 /* Link failure change state back to the starting state */886 sci_change_state(&iphy->sm, SCI_PHY_STARTING);887 break;888 case SCU_EVENT_SAS_PHY_DETECTED:889 /*890 * There has been a change in the phy type before OOB/SN for the891 * SATA finished start down the SAS link traning path. */892 sci_phy_start_sas_link_training(iphy);893 break;894 default:895 phy_event_warn(iphy, state, event_code);896 return SCI_FAILURE;897 }898 899 return SCI_SUCCESS;900 case SCI_PHY_SUB_AWAIT_SIG_FIS_UF:901 switch (scu_get_event_code(event_code)) {902 case SCU_EVENT_SATA_PHY_DETECTED:903 /* Backup the state machine */904 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_SATA_SPEED_EN);905 break;906 907 case SCU_EVENT_LINK_FAILURE:908 /* Change the timeout value to default */909 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);910 911 /* Link failure change state back to the starting state */912 sci_change_state(&iphy->sm, SCI_PHY_STARTING);913 break;914 915 default:916 phy_event_warn(iphy, state, event_code);917 return SCI_FAILURE;918 }919 return SCI_SUCCESS;920 case SCI_PHY_READY:921 switch (scu_get_event_code(event_code)) {922 case SCU_EVENT_LINK_FAILURE:923 /* Set default timeout */924 scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT);925 926 /* Link failure change state back to the starting state */927 sci_change_state(&iphy->sm, SCI_PHY_STARTING);928 break;929 case SCU_EVENT_BROADCAST_CHANGE:930 case SCU_EVENT_BROADCAST_SES:931 case SCU_EVENT_BROADCAST_RESERVED0:932 case SCU_EVENT_BROADCAST_RESERVED1:933 case SCU_EVENT_BROADCAST_EXPANDER:934 case SCU_EVENT_BROADCAST_AEN:935 /* Broadcast change received. Notify the port. */936 if (phy_get_non_dummy_port(iphy) != NULL)937 sci_port_broadcast_change_received(iphy->owning_port, iphy);938 else939 iphy->bcn_received_while_port_unassigned = true;940 break;941 case SCU_EVENT_BROADCAST_RESERVED3:942 case SCU_EVENT_BROADCAST_RESERVED4:943 default:944 phy_event_warn(iphy, state, event_code);945 return SCI_FAILURE_INVALID_STATE;946 }947 return SCI_SUCCESS;948 case SCI_PHY_RESETTING:949 switch (scu_get_event_code(event_code)) {950 case SCU_EVENT_HARD_RESET_TRANSMITTED:951 /* Link failure change state back to the starting state */952 sci_change_state(&iphy->sm, SCI_PHY_STARTING);953 break;954 default:955 phy_event_warn(iphy, state, event_code);956 return SCI_FAILURE_INVALID_STATE;957 }958 return SCI_SUCCESS;959 default:960 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",961 __func__, phy_state_name(state));962 return SCI_FAILURE_INVALID_STATE;963 }964}965 966enum sci_status sci_phy_frame_handler(struct isci_phy *iphy, u32 frame_index)967{968 enum sci_phy_states state = iphy->sm.current_state_id;969 struct isci_host *ihost = iphy->owning_port->owning_controller;970 enum sci_status result;971 unsigned long flags;972 973 switch (state) {974 case SCI_PHY_SUB_AWAIT_IAF_UF: {975 u32 *frame_words;976 struct sas_identify_frame iaf;977 978 result = sci_unsolicited_frame_control_get_header(&ihost->uf_control,979 frame_index,980 (void **)&frame_words);981 982 if (result != SCI_SUCCESS)983 return result;984 985 sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32));986 if (iaf.frame_type == 0) {987 u32 state;988 989 spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags);990 memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf));991 spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags);992 if (iaf.smp_tport) {993 /* We got the IAF for an expander PHY go to the final994 * state since there are no power requirements for995 * expander phys.996 */997 state = SCI_PHY_SUB_FINAL;998 } else {999 /* We got the IAF we can now go to the await spinup1000 * semaphore state1001 */1002 state = SCI_PHY_SUB_AWAIT_SAS_POWER;1003 }1004 sci_change_state(&iphy->sm, state);1005 result = SCI_SUCCESS;1006 } else1007 dev_warn(sciphy_to_dev(iphy),1008 "%s: PHY starting substate machine received "1009 "unexpected frame id %x\n",1010 __func__, frame_index);1011 1012 sci_controller_release_frame(ihost, frame_index);1013 return result;1014 }1015 case SCI_PHY_SUB_AWAIT_SIG_FIS_UF: {1016 struct dev_to_host_fis *frame_header;1017 u32 *fis_frame_data;1018 1019 result = sci_unsolicited_frame_control_get_header(&ihost->uf_control,1020 frame_index,1021 (void **)&frame_header);1022 1023 if (result != SCI_SUCCESS)1024 return result;1025 1026 if ((frame_header->fis_type == FIS_REGD2H) &&1027 !(frame_header->status & ATA_BUSY)) {1028 sci_unsolicited_frame_control_get_buffer(&ihost->uf_control,1029 frame_index,1030 (void **)&fis_frame_data);1031 1032 spin_lock_irqsave(&iphy->sas_phy.frame_rcvd_lock, flags);1033 sci_controller_copy_sata_response(&iphy->frame_rcvd.fis,1034 frame_header,1035 fis_frame_data);1036 spin_unlock_irqrestore(&iphy->sas_phy.frame_rcvd_lock, flags);1037 1038 /* got IAF we can now go to the await spinup semaphore state */1039 sci_change_state(&iphy->sm, SCI_PHY_SUB_FINAL);1040 1041 result = SCI_SUCCESS;1042 } else1043 dev_warn(sciphy_to_dev(iphy),1044 "%s: PHY starting substate machine received "1045 "unexpected frame id %x\n",1046 __func__, frame_index);1047 1048 /* Regardless of the result we are done with this frame with it */1049 sci_controller_release_frame(ihost, frame_index);1050 1051 return result;1052 }1053 default:1054 dev_dbg(sciphy_to_dev(iphy), "%s: in wrong state: %s\n",1055 __func__, phy_state_name(state));1056 return SCI_FAILURE_INVALID_STATE;1057 }1058 1059}1060 1061static void sci_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm)1062{1063 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1064 1065 /* This is just an temporary state go off to the starting state */1066 sci_change_state(&iphy->sm, SCI_PHY_SUB_AWAIT_OSSP_EN);1067}1068 1069static void sci_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm)1070{1071 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1072 struct isci_host *ihost = iphy->owning_port->owning_controller;1073 1074 sci_controller_power_control_queue_insert(ihost, iphy);1075}1076 1077static void sci_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm)1078{1079 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1080 struct isci_host *ihost = iphy->owning_port->owning_controller;1081 1082 sci_controller_power_control_queue_remove(ihost, iphy);1083}1084 1085static void sci_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm)1086{1087 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1088 struct isci_host *ihost = iphy->owning_port->owning_controller;1089 1090 sci_controller_power_control_queue_insert(ihost, iphy);1091}1092 1093static void sci_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm)1094{1095 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1096 struct isci_host *ihost = iphy->owning_port->owning_controller;1097 1098 sci_controller_power_control_queue_remove(ihost, iphy);1099}1100 1101static void sci_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm)1102{1103 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1104 1105 sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT);1106}1107 1108static void sci_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm)1109{1110 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1111 1112 sci_del_timer(&iphy->sata_timer);1113}1114 1115static void sci_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm)1116{1117 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1118 1119 sci_mod_timer(&iphy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT);1120}1121 1122static void sci_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm)1123{1124 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1125 1126 sci_del_timer(&iphy->sata_timer);1127}1128 1129static void sci_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm)1130{1131 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1132 1133 if (sci_port_link_detected(iphy->owning_port, iphy)) {1134 1135 /*1136 * Clear the PE suspend condition so we can actually1137 * receive SIG FIS1138 * The hardware will not respond to the XRDY until the PE1139 * suspend condition is cleared.1140 */1141 sci_phy_resume(iphy);1142 1143 sci_mod_timer(&iphy->sata_timer,1144 SCIC_SDS_SIGNATURE_FIS_TIMEOUT);1145 } else1146 iphy->is_in_link_training = false;1147}1148 1149static void sci_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm)1150{1151 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1152 1153 sci_del_timer(&iphy->sata_timer);1154}1155 1156static void sci_phy_starting_final_substate_enter(struct sci_base_state_machine *sm)1157{1158 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1159 1160 /* State machine has run to completion so exit out and change1161 * the base state machine to the ready state1162 */1163 sci_change_state(&iphy->sm, SCI_PHY_READY);1164}1165 1166/**1167 * scu_link_layer_stop_protocol_engine()1168 * @iphy: This is the struct isci_phy object to stop.1169 *1170 * This method will stop the struct isci_phy object. This does not reset the1171 * protocol engine it just suspends it and places it in a state where it will1172 * not cause the end device to power up. none1173 */1174static void scu_link_layer_stop_protocol_engine(1175 struct isci_phy *iphy)1176{1177 u32 scu_sas_pcfg_value;1178 u32 enable_spinup_value;1179 1180 /* Suspend the protocol engine and place it in a sata spinup hold state */1181 scu_sas_pcfg_value =1182 readl(&iphy->link_layer_registers->phy_configuration);1183 scu_sas_pcfg_value |=1184 (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |1185 SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) |1186 SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD));1187 writel(scu_sas_pcfg_value,1188 &iphy->link_layer_registers->phy_configuration);1189 1190 /* Disable the notify enable spinup primitives */1191 enable_spinup_value = readl(&iphy->link_layer_registers->notify_enable_spinup_control);1192 enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);1193 writel(enable_spinup_value, &iphy->link_layer_registers->notify_enable_spinup_control);1194}1195 1196static void scu_link_layer_start_oob(struct isci_phy *iphy)1197{1198 struct scu_link_layer_registers __iomem *ll = iphy->link_layer_registers;1199 u32 val;1200 1201 /** Reset OOB sequence - start */1202 val = readl(&ll->phy_configuration);1203 val &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |1204 SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE) |1205 SCU_SAS_PCFG_GEN_BIT(HARD_RESET));1206 writel(val, &ll->phy_configuration);1207 readl(&ll->phy_configuration); /* flush */1208 /** Reset OOB sequence - end */1209 1210 /** Start OOB sequence - start */1211 val = readl(&ll->phy_configuration);1212 val |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);1213 writel(val, &ll->phy_configuration);1214 readl(&ll->phy_configuration); /* flush */1215 /** Start OOB sequence - end */1216}1217 1218/**1219 * scu_link_layer_tx_hard_reset()1220 * @iphy: This is the struct isci_phy object to stop.1221 *1222 * This method will transmit a hard reset request on the specified phy. The SCU1223 * hardware requires that we reset the OOB state machine and set the hard reset1224 * bit in the phy configuration register. We then must start OOB over with the1225 * hard reset bit set.1226 */1227static void scu_link_layer_tx_hard_reset(1228 struct isci_phy *iphy)1229{1230 u32 phy_configuration_value;1231 1232 /*1233 * SAS Phys must wait for the HARD_RESET_TX event notification to transition1234 * to the starting state. */1235 phy_configuration_value =1236 readl(&iphy->link_layer_registers->phy_configuration);1237 phy_configuration_value &= ~(SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));1238 phy_configuration_value |=1239 (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) |1240 SCU_SAS_PCFG_GEN_BIT(OOB_RESET));1241 writel(phy_configuration_value,1242 &iphy->link_layer_registers->phy_configuration);1243 1244 /* Now take the OOB state machine out of reset */1245 phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);1246 phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);1247 writel(phy_configuration_value,1248 &iphy->link_layer_registers->phy_configuration);1249}1250 1251static void sci_phy_stopped_state_enter(struct sci_base_state_machine *sm)1252{1253 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1254 struct isci_port *iport = iphy->owning_port;1255 struct isci_host *ihost = iport->owning_controller;1256 1257 /*1258 * @todo We need to get to the controller to place this PE in a1259 * reset state1260 */1261 sci_del_timer(&iphy->sata_timer);1262 1263 scu_link_layer_stop_protocol_engine(iphy);1264 1265 if (iphy->sm.previous_state_id != SCI_PHY_INITIAL)1266 sci_controller_link_down(ihost, phy_get_non_dummy_port(iphy), iphy);1267}1268 1269static void sci_phy_starting_state_enter(struct sci_base_state_machine *sm)1270{1271 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1272 struct isci_port *iport = iphy->owning_port;1273 struct isci_host *ihost = iport->owning_controller;1274 1275 scu_link_layer_stop_protocol_engine(iphy);1276 scu_link_layer_start_oob(iphy);1277 1278 /* We don't know what kind of phy we are going to be just yet */1279 iphy->protocol = SAS_PROTOCOL_NONE;1280 iphy->bcn_received_while_port_unassigned = false;1281 1282 if (iphy->sm.previous_state_id == SCI_PHY_READY)1283 sci_controller_link_down(ihost, phy_get_non_dummy_port(iphy), iphy);1284 1285 sci_change_state(&iphy->sm, SCI_PHY_SUB_INITIAL);1286}1287 1288static void sci_phy_ready_state_enter(struct sci_base_state_machine *sm)1289{1290 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1291 struct isci_port *iport = iphy->owning_port;1292 struct isci_host *ihost = iport->owning_controller;1293 1294 sci_controller_link_up(ihost, phy_get_non_dummy_port(iphy), iphy);1295}1296 1297static void sci_phy_ready_state_exit(struct sci_base_state_machine *sm)1298{1299 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1300 1301 sci_phy_suspend(iphy);1302}1303 1304static void sci_phy_resetting_state_enter(struct sci_base_state_machine *sm)1305{1306 struct isci_phy *iphy = container_of(sm, typeof(*iphy), sm);1307 1308 /* The phy is being reset, therefore deactivate it from the port. In1309 * the resetting state we don't notify the user regarding link up and1310 * link down notifications1311 */1312 sci_port_deactivate_phy(iphy->owning_port, iphy, false);1313 1314 if (iphy->protocol == SAS_PROTOCOL_SSP) {1315 scu_link_layer_tx_hard_reset(iphy);1316 } else {1317 /* The SCU does not need to have a discrete reset state so1318 * just go back to the starting state.1319 */1320 sci_change_state(&iphy->sm, SCI_PHY_STARTING);1321 }1322}1323 1324static const struct sci_base_state sci_phy_state_table[] = {1325 [SCI_PHY_INITIAL] = { },1326 [SCI_PHY_STOPPED] = {1327 .enter_state = sci_phy_stopped_state_enter,1328 },1329 [SCI_PHY_STARTING] = {1330 .enter_state = sci_phy_starting_state_enter,1331 },1332 [SCI_PHY_SUB_INITIAL] = {1333 .enter_state = sci_phy_starting_initial_substate_enter,1334 },1335 [SCI_PHY_SUB_AWAIT_OSSP_EN] = { },1336 [SCI_PHY_SUB_AWAIT_SAS_SPEED_EN] = { },1337 [SCI_PHY_SUB_AWAIT_IAF_UF] = { },1338 [SCI_PHY_SUB_AWAIT_SAS_POWER] = {1339 .enter_state = sci_phy_starting_await_sas_power_substate_enter,1340 .exit_state = sci_phy_starting_await_sas_power_substate_exit,1341 },1342 [SCI_PHY_SUB_AWAIT_SATA_POWER] = {1343 .enter_state = sci_phy_starting_await_sata_power_substate_enter,1344 .exit_state = sci_phy_starting_await_sata_power_substate_exit1345 },1346 [SCI_PHY_SUB_AWAIT_SATA_PHY_EN] = {1347 .enter_state = sci_phy_starting_await_sata_phy_substate_enter,1348 .exit_state = sci_phy_starting_await_sata_phy_substate_exit1349 },1350 [SCI_PHY_SUB_AWAIT_SATA_SPEED_EN] = {1351 .enter_state = sci_phy_starting_await_sata_speed_substate_enter,1352 .exit_state = sci_phy_starting_await_sata_speed_substate_exit1353 },1354 [SCI_PHY_SUB_AWAIT_SIG_FIS_UF] = {1355 .enter_state = sci_phy_starting_await_sig_fis_uf_substate_enter,1356 .exit_state = sci_phy_starting_await_sig_fis_uf_substate_exit1357 },1358 [SCI_PHY_SUB_FINAL] = {1359 .enter_state = sci_phy_starting_final_substate_enter,1360 },1361 [SCI_PHY_READY] = {1362 .enter_state = sci_phy_ready_state_enter,1363 .exit_state = sci_phy_ready_state_exit,1364 },1365 [SCI_PHY_RESETTING] = {1366 .enter_state = sci_phy_resetting_state_enter,1367 },1368 [SCI_PHY_FINAL] = { },1369};1370 1371void sci_phy_construct(struct isci_phy *iphy,1372 struct isci_port *iport, u8 phy_index)1373{1374 sci_init_sm(&iphy->sm, sci_phy_state_table, SCI_PHY_INITIAL);1375 1376 /* Copy the rest of the input data to our locals */1377 iphy->owning_port = iport;1378 iphy->phy_index = phy_index;1379 iphy->bcn_received_while_port_unassigned = false;1380 iphy->protocol = SAS_PROTOCOL_NONE;1381 iphy->link_layer_registers = NULL;1382 iphy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;1383 1384 /* Create the SIGNATURE FIS Timeout timer for this phy */1385 sci_init_timer(&iphy->sata_timer, phy_sata_timeout);1386}1387 1388void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index)1389{1390 struct sci_oem_params *oem = &ihost->oem_parameters;1391 u64 sci_sas_addr;1392 __be64 sas_addr;1393 1394 sci_sas_addr = oem->phys[index].sas_address.high;1395 sci_sas_addr <<= 32;1396 sci_sas_addr |= oem->phys[index].sas_address.low;1397 sas_addr = cpu_to_be64(sci_sas_addr);1398 memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr));1399 1400 iphy->sas_phy.enabled = 0;1401 iphy->sas_phy.id = index;1402 iphy->sas_phy.sas_addr = &iphy->sas_addr[0];1403 iphy->sas_phy.frame_rcvd = (u8 *)&iphy->frame_rcvd;1404 iphy->sas_phy.ha = &ihost->sas_ha;1405 iphy->sas_phy.lldd_phy = iphy;1406 iphy->sas_phy.enabled = 1;1407 iphy->sas_phy.iproto = SAS_PROTOCOL_ALL;1408 iphy->sas_phy.tproto = 0;1409 iphy->sas_phy.role = PHY_ROLE_INITIATOR;1410 iphy->sas_phy.oob_mode = OOB_NOT_CONNECTED;1411 iphy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;1412 memset(&iphy->frame_rcvd, 0, sizeof(iphy->frame_rcvd));1413}1414 1415 1416/**1417 * isci_phy_control() - This function is one of the SAS Domain Template1418 * functions. This is a phy management function.1419 * @sas_phy: This parameter specifies the sphy being controlled.1420 * @func: This parameter specifies the phy control function being invoked.1421 * @buf: This parameter is specific to the phy function being invoked.1422 *1423 * status, zero indicates success.1424 */1425int isci_phy_control(struct asd_sas_phy *sas_phy,1426 enum phy_func func,1427 void *buf)1428{1429 int ret = 0;1430 struct isci_phy *iphy = sas_phy->lldd_phy;1431 struct asd_sas_port *port = sas_phy->port;1432 struct isci_host *ihost = sas_phy->ha->lldd_ha;1433 unsigned long flags;1434 1435 dev_dbg(&ihost->pdev->dev,1436 "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",1437 __func__, sas_phy, func, buf, iphy, port);1438 1439 switch (func) {1440 case PHY_FUNC_DISABLE:1441 spin_lock_irqsave(&ihost->scic_lock, flags);1442 scu_link_layer_start_oob(iphy);1443 sci_phy_stop(iphy);1444 spin_unlock_irqrestore(&ihost->scic_lock, flags);1445 break;1446 1447 case PHY_FUNC_LINK_RESET:1448 spin_lock_irqsave(&ihost->scic_lock, flags);1449 scu_link_layer_start_oob(iphy);1450 sci_phy_stop(iphy);1451 sci_phy_start(iphy);1452 spin_unlock_irqrestore(&ihost->scic_lock, flags);1453 break;1454 1455 case PHY_FUNC_HARD_RESET:1456 if (!port)1457 return -ENODEV;1458 1459 ret = isci_port_perform_hard_reset(ihost, port->lldd_port, iphy);1460 1461 break;1462 case PHY_FUNC_GET_EVENTS: {1463 struct scu_link_layer_registers __iomem *r;1464 struct sas_phy *phy = sas_phy->phy;1465 1466 r = iphy->link_layer_registers;1467 phy->running_disparity_error_count = readl(&r->running_disparity_error_count);1468 phy->loss_of_dword_sync_count = readl(&r->loss_of_sync_error_count);1469 phy->phy_reset_problem_count = readl(&r->phy_reset_problem_count);1470 phy->invalid_dword_count = readl(&r->invalid_dword_counter);1471 break;1472 }1473 1474 default:1475 dev_dbg(&ihost->pdev->dev,1476 "%s: phy %p; func %d NOT IMPLEMENTED!\n",1477 __func__, sas_phy, func);1478 ret = -ENOSYS;1479 break;1480 }1481 return ret;1482}1483