isci: remove isci_timer interface
[deliverable/linux.git] / drivers / scsi / isci / phy.c
CommitLineData
6f231dda
DW
1/*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
23 *
24 * BSD LICENSE
25 *
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 without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55
56#include "isci.h"
ce2b3261 57#include "host.h"
6f231dda 58#include "phy.h"
d35bc1bd 59#include "scu_event_codes.h"
e2f8db50 60#include "probe_roms.h"
6f231dda 61
d35bc1bd
DW
62/* Maximum arbitration wait time in micro-seconds */
63#define SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME (700)
64
65enum sas_linkrate sci_phy_linkrate(struct scic_sds_phy *sci_phy)
66{
67 return sci_phy->max_negotiated_speed;
68}
69
70/*
71 * *****************************************************************************
72 * * SCIC SDS PHY Internal Methods
73 * ***************************************************************************** */
74
75/**
76 * This method will initialize the phy transport layer registers
77 * @sci_phy:
78 * @transport_layer_registers
79 *
80 * enum sci_status
81 */
82static enum sci_status scic_sds_phy_transport_layer_initialization(
83 struct scic_sds_phy *sci_phy,
84 struct scu_transport_layer_registers __iomem *transport_layer_registers)
85{
86 u32 tl_control;
87
88 sci_phy->transport_layer_registers = transport_layer_registers;
89
90 writel(SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX,
91 &sci_phy->transport_layer_registers->stp_rni);
92
93 /*
94 * Hardware team recommends that we enable the STP prefetch for all
95 * transports
96 */
97 tl_control = readl(&sci_phy->transport_layer_registers->control);
98 tl_control |= SCU_TLCR_GEN_BIT(STP_WRITE_DATA_PREFETCH);
99 writel(tl_control, &sci_phy->transport_layer_registers->control);
100
101 return SCI_SUCCESS;
102}
103
104/**
105 * This method will initialize the phy link layer registers
106 * @sci_phy:
107 * @link_layer_registers:
108 *
109 * enum sci_status
110 */
111static enum sci_status
112scic_sds_phy_link_layer_initialization(struct scic_sds_phy *sci_phy,
113 struct scu_link_layer_registers __iomem *link_layer_registers)
114{
115 struct scic_sds_controller *scic =
116 sci_phy->owning_port->owning_controller;
117 int phy_idx = sci_phy->phy_index;
118 struct sci_phy_user_params *phy_user =
119 &scic->user_parameters.sds1.phys[phy_idx];
120 struct sci_phy_oem_params *phy_oem =
121 &scic->oem_parameters.sds1.phys[phy_idx];
122 u32 phy_configuration;
123 struct scic_phy_cap phy_cap;
124 u32 parity_check = 0;
125 u32 parity_count = 0;
126 u32 llctl, link_rate;
127 u32 clksm_value = 0;
128
129 sci_phy->link_layer_registers = link_layer_registers;
130
131 /* Set our IDENTIFY frame data */
132 #define SCI_END_DEVICE 0x01
133
134 writel(SCU_SAS_TIID_GEN_BIT(SMP_INITIATOR) |
135 SCU_SAS_TIID_GEN_BIT(SSP_INITIATOR) |
136 SCU_SAS_TIID_GEN_BIT(STP_INITIATOR) |
137 SCU_SAS_TIID_GEN_BIT(DA_SATA_HOST) |
138 SCU_SAS_TIID_GEN_VAL(DEVICE_TYPE, SCI_END_DEVICE),
139 &sci_phy->link_layer_registers->transmit_identification);
140
141 /* Write the device SAS Address */
142 writel(0xFEDCBA98,
143 &sci_phy->link_layer_registers->sas_device_name_high);
144 writel(phy_idx, &sci_phy->link_layer_registers->sas_device_name_low);
145
146 /* Write the source SAS Address */
147 writel(phy_oem->sas_address.high,
148 &sci_phy->link_layer_registers->source_sas_address_high);
149 writel(phy_oem->sas_address.low,
150 &sci_phy->link_layer_registers->source_sas_address_low);
151
152 /* Clear and Set the PHY Identifier */
153 writel(0, &sci_phy->link_layer_registers->identify_frame_phy_id);
154 writel(SCU_SAS_TIPID_GEN_VALUE(ID, phy_idx),
155 &sci_phy->link_layer_registers->identify_frame_phy_id);
156
157 /* Change the initial state of the phy configuration register */
158 phy_configuration =
159 readl(&sci_phy->link_layer_registers->phy_configuration);
160
161 /* Hold OOB state machine in reset */
162 phy_configuration |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
163 writel(phy_configuration,
164 &sci_phy->link_layer_registers->phy_configuration);
165
166 /* Configure the SNW capabilities */
167 phy_cap.all = 0;
168 phy_cap.start = 1;
169 phy_cap.gen3_no_ssc = 1;
170 phy_cap.gen2_no_ssc = 1;
171 phy_cap.gen1_no_ssc = 1;
172 if (scic->oem_parameters.sds1.controller.do_enable_ssc == true) {
173 phy_cap.gen3_ssc = 1;
174 phy_cap.gen2_ssc = 1;
175 phy_cap.gen1_ssc = 1;
176 }
177
178 /*
179 * The SAS specification indicates that the phy_capabilities that
180 * are transmitted shall have an even parity. Calculate the parity. */
181 parity_check = phy_cap.all;
182 while (parity_check != 0) {
183 if (parity_check & 0x1)
184 parity_count++;
185 parity_check >>= 1;
186 }
187
188 /*
189 * If parity indicates there are an odd number of bits set, then
190 * set the parity bit to 1 in the phy capabilities. */
191 if ((parity_count % 2) != 0)
192 phy_cap.parity = 1;
193
194 writel(phy_cap.all, &sci_phy->link_layer_registers->phy_capabilities);
195
196 /* Set the enable spinup period but disable the ability to send
197 * notify enable spinup
198 */
199 writel(SCU_ENSPINUP_GEN_VAL(COUNT,
200 phy_user->notify_enable_spin_up_insertion_frequency),
201 &sci_phy->link_layer_registers->notify_enable_spinup_control);
202
203 /* Write the ALIGN Insertion Ferequency for connected phy and
204 * inpendent of connected state
205 */
206 clksm_value = SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(CONNECTED,
207 phy_user->in_connection_align_insertion_frequency);
208
209 clksm_value |= SCU_ALIGN_INSERTION_FREQUENCY_GEN_VAL(GENERAL,
210 phy_user->align_insertion_frequency);
211
212 writel(clksm_value, &sci_phy->link_layer_registers->clock_skew_management);
213
214 /* @todo Provide a way to write this register correctly */
215 writel(0x02108421,
216 &sci_phy->link_layer_registers->afe_lookup_table_control);
217
218 llctl = SCU_SAS_LLCTL_GEN_VAL(NO_OUTBOUND_TASK_TIMEOUT,
219 (u8)scic->user_parameters.sds1.no_outbound_task_timeout);
220
221 switch(phy_user->max_speed_generation) {
222 case SCIC_SDS_PARM_GEN3_SPEED:
223 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN3;
224 break;
225 case SCIC_SDS_PARM_GEN2_SPEED:
226 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN2;
227 break;
228 default:
229 link_rate = SCU_SAS_LINK_LAYER_CONTROL_MAX_LINK_RATE_GEN1;
230 break;
231 }
232 llctl |= SCU_SAS_LLCTL_GEN_VAL(MAX_LINK_RATE, link_rate);
233 writel(llctl, &sci_phy->link_layer_registers->link_layer_control);
234
235 if (is_a0() || is_a2()) {
236 /* Program the max ARB time for the PHY to 700us so we inter-operate with
237 * the PMC expander which shuts down PHYs if the expander PHY generates too
238 * many breaks. This time value will guarantee that the initiator PHY will
239 * generate the break.
240 */
241 writel(SCIC_SDS_PHY_MAX_ARBITRATION_WAIT_TIME,
242 &sci_phy->link_layer_registers->maximum_arbitration_wait_timer_timeout);
243 }
244
245 /*
246 * Set the link layer hang detection to 500ms (0x1F4) from its default
247 * value of 128ms. Max value is 511 ms.
248 */
249 writel(0x1F4, &sci_phy->link_layer_registers->link_layer_hang_detection_timeout);
250
251 /* We can exit the initial state to the stopped state */
252 sci_base_state_machine_change_state(&sci_phy->state_machine,
253 SCI_BASE_PHY_STATE_STOPPED);
254
255 return SCI_SUCCESS;
256}
257
a628d478 258static void phy_sata_timeout(unsigned long data)
d35bc1bd 259{
a628d478
EN
260 struct sci_timer *tmr = (struct sci_timer *)data;
261 struct scic_sds_phy *sci_phy = container_of(tmr, typeof(*sci_phy), sata_timer);
262 struct isci_host *ihost = scic_to_ihost(sci_phy->owning_port->owning_controller);
263 unsigned long flags;
264
265 spin_lock_irqsave(&ihost->scic_lock, flags);
266
267 if (tmr->cancel)
268 goto done;
d35bc1bd
DW
269
270 dev_dbg(sciphy_to_dev(sci_phy),
271 "%s: SCIC SDS Phy 0x%p did not receive signature fis before "
272 "timeout.\n",
273 __func__,
274 sci_phy);
275
d35bc1bd
DW
276 sci_base_state_machine_change_state(&sci_phy->state_machine,
277 SCI_BASE_PHY_STATE_STARTING);
a628d478
EN
278done:
279 spin_unlock_irqrestore(&ihost->scic_lock, flags);
d35bc1bd
DW
280}
281
282/**
283 * This method returns the port currently containing this phy. If the phy is
284 * currently contained by the dummy port, then the phy is considered to not
285 * be part of a port.
286 * @sci_phy: This parameter specifies the phy for which to retrieve the
287 * containing port.
288 *
289 * This method returns a handle to a port that contains the supplied phy.
290 * NULL This value is returned if the phy is not part of a real
291 * port (i.e. it's contained in the dummy port). !NULL All other
292 * values indicate a handle/pointer to the port containing the phy.
293 */
4f20ef4f 294struct scic_sds_port *phy_get_non_dummy_port(
d35bc1bd
DW
295 struct scic_sds_phy *sci_phy)
296{
297 if (scic_sds_port_get_index(sci_phy->owning_port) == SCIC_SDS_DUMMY_PORT)
298 return NULL;
299
300 return sci_phy->owning_port;
301}
302
303/**
304 * This method will assign a port to the phy object.
305 * @out]: sci_phy This parameter specifies the phy for which to assign a port
306 * object.
307 *
308 *
309 */
310void scic_sds_phy_set_port(
311 struct scic_sds_phy *sci_phy,
312 struct scic_sds_port *sci_port)
313{
314 sci_phy->owning_port = sci_port;
315
316 if (sci_phy->bcn_received_while_port_unassigned) {
317 sci_phy->bcn_received_while_port_unassigned = false;
318 scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy);
319 }
320}
321
322/**
323 * This method will initialize the constructed phy
324 * @sci_phy:
325 * @link_layer_registers:
326 *
327 * enum sci_status
328 */
329enum sci_status scic_sds_phy_initialize(
330 struct scic_sds_phy *sci_phy,
331 struct scu_transport_layer_registers __iomem *transport_layer_registers,
332 struct scu_link_layer_registers __iomem *link_layer_registers)
333{
d35bc1bd
DW
334 /* Perfrom the initialization of the TL hardware */
335 scic_sds_phy_transport_layer_initialization(
336 sci_phy,
337 transport_layer_registers);
338
339 /* Perofrm the initialization of the PE hardware */
340 scic_sds_phy_link_layer_initialization(sci_phy, link_layer_registers);
341
342 /*
343 * There is nothing that needs to be done in this state just
344 * transition to the stopped state. */
345 sci_base_state_machine_change_state(&sci_phy->state_machine,
346 SCI_BASE_PHY_STATE_STOPPED);
347
348 return SCI_SUCCESS;
349}
350
351/**
352 * This method assigns the direct attached device ID for this phy.
353 *
354 * @sci_phy The phy for which the direct attached device id is to
355 * be assigned.
356 * @device_id The direct attached device ID to assign to the phy.
357 * This will either be the RNi for the device or an invalid RNi if there
358 * is no current device assigned to the phy.
359 */
360void scic_sds_phy_setup_transport(
361 struct scic_sds_phy *sci_phy,
362 u32 device_id)
363{
364 u32 tl_control;
365
366 writel(device_id, &sci_phy->transport_layer_registers->stp_rni);
367
368 /*
369 * The read should guarantee that the first write gets posted
370 * before the next write
371 */
372 tl_control = readl(&sci_phy->transport_layer_registers->control);
373 tl_control |= SCU_TLCR_GEN_BIT(CLEAR_TCI_NCQ_MAPPING_TABLE);
374 writel(tl_control, &sci_phy->transport_layer_registers->control);
375}
376
377/**
378 *
379 * @sci_phy: The phy object to be suspended.
380 *
381 * This function will perform the register reads/writes to suspend the SCU
382 * hardware protocol engine. none
383 */
384static void scic_sds_phy_suspend(
385 struct scic_sds_phy *sci_phy)
386{
387 u32 scu_sas_pcfg_value;
388
389 scu_sas_pcfg_value =
390 readl(&sci_phy->link_layer_registers->phy_configuration);
391 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
392 writel(scu_sas_pcfg_value,
393 &sci_phy->link_layer_registers->phy_configuration);
394
395 scic_sds_phy_setup_transport(
396 sci_phy,
397 SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX);
398}
399
400void scic_sds_phy_resume(struct scic_sds_phy *sci_phy)
401{
402 u32 scu_sas_pcfg_value;
403
404 scu_sas_pcfg_value =
405 readl(&sci_phy->link_layer_registers->phy_configuration);
406 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE);
407 writel(scu_sas_pcfg_value,
408 &sci_phy->link_layer_registers->phy_configuration);
409}
410
411void scic_sds_phy_get_sas_address(struct scic_sds_phy *sci_phy,
412 struct sci_sas_address *sas_address)
413{
414 sas_address->high = readl(&sci_phy->link_layer_registers->source_sas_address_high);
415 sas_address->low = readl(&sci_phy->link_layer_registers->source_sas_address_low);
416}
417
418void scic_sds_phy_get_attached_sas_address(struct scic_sds_phy *sci_phy,
419 struct sci_sas_address *sas_address)
420{
421 struct sas_identify_frame *iaf;
422 struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
423
424 iaf = &iphy->frame_rcvd.iaf;
425 memcpy(sas_address, iaf->sas_addr, SAS_ADDR_SIZE);
426}
427
428void scic_sds_phy_get_protocols(struct scic_sds_phy *sci_phy,
429 struct scic_phy_proto *protocols)
430{
431 protocols->all =
432 (u16)(readl(&sci_phy->
433 link_layer_registers->transmit_identification) &
434 0x0000FFFF);
435}
436
d35bc1bd
DW
437enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy)
438{
966699b5 439 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
966699b5
DW
440
441 if (state != SCI_BASE_PHY_STATE_STOPPED) {
442 dev_dbg(sciphy_to_dev(sci_phy),
443 "%s: in wrong state: %d\n", __func__, state);
444 return SCI_FAILURE_INVALID_STATE;
445 }
446
a628d478
EN
447 sci_base_state_machine_change_state(&sci_phy->state_machine,
448 SCI_BASE_PHY_STATE_STARTING);
966699b5 449 return SCI_SUCCESS;
d35bc1bd
DW
450}
451
d35bc1bd
DW
452enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy)
453{
93153236
DW
454 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
455
456 switch (state) {
457 case SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL:
458 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN:
459 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN:
460 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER:
461 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER:
462 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN:
463 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN:
464 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF:
465 case SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL:
466 case SCI_BASE_PHY_STATE_READY:
467 break;
468 default:
469 dev_dbg(sciphy_to_dev(sci_phy),
470 "%s: in wrong state: %d\n", __func__, state);
471 return SCI_FAILURE_INVALID_STATE;
472 }
473
474 sci_base_state_machine_change_state(&sci_phy->state_machine,
475 SCI_BASE_PHY_STATE_STOPPED);
476 return SCI_SUCCESS;
d35bc1bd
DW
477}
478
0cf36fa9 479enum sci_status scic_sds_phy_reset(struct scic_sds_phy *sci_phy)
d35bc1bd 480{
0cf36fa9
DW
481 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
482
483 if (state != SCI_BASE_PHY_STATE_READY) {
484 dev_dbg(sciphy_to_dev(sci_phy),
485 "%s: in wrong state: %d\n", __func__, state);
486 return SCI_FAILURE_INVALID_STATE;
487 }
488
489 sci_base_state_machine_change_state(&sci_phy->state_machine,
490 SCI_BASE_PHY_STATE_RESETTING);
491 return SCI_SUCCESS;
d35bc1bd
DW
492}
493
5b1d4af2 494enum sci_status scic_sds_phy_consume_power_handler(struct scic_sds_phy *sci_phy)
d35bc1bd 495{
5b1d4af2
DW
496 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
497
498 switch (state) {
499 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER: {
500 u32 enable_spinup;
501
502 enable_spinup = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control);
503 enable_spinup |= SCU_ENSPINUP_GEN_BIT(ENABLE);
504 writel(enable_spinup, &sci_phy->link_layer_registers->notify_enable_spinup_control);
505
506 /* Change state to the final state this substate machine has run to completion */
507 sci_base_state_machine_change_state(&sci_phy->state_machine,
508 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL);
509
510 return SCI_SUCCESS;
511 }
512 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER: {
513 u32 scu_sas_pcfg_value;
514
515 /* Release the spinup hold state and reset the OOB state machine */
516 scu_sas_pcfg_value =
517 readl(&sci_phy->link_layer_registers->phy_configuration);
518 scu_sas_pcfg_value &=
519 ~(SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD) | SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE));
520 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
521 writel(scu_sas_pcfg_value,
522 &sci_phy->link_layer_registers->phy_configuration);
523
524 /* Now restart the OOB operation */
525 scu_sas_pcfg_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
526 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
527 writel(scu_sas_pcfg_value,
528 &sci_phy->link_layer_registers->phy_configuration);
529
530 /* Change state to the final state this substate machine has run to completion */
531 sci_base_state_machine_change_state(&sci_phy->state_machine,
532 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN);
533
534 return SCI_SUCCESS;
535 }
536 default:
537 dev_dbg(sciphy_to_dev(sci_phy),
538 "%s: in wrong state: %d\n", __func__, state);
539 return SCI_FAILURE_INVALID_STATE;
540 }
d35bc1bd
DW
541}
542
543/*
544 * *****************************************************************************
545 * * SCIC SDS PHY HELPER FUNCTIONS
546 * ***************************************************************************** */
547
548
549/**
550 *
551 * @sci_phy: The phy object that received SAS PHY DETECTED.
552 *
553 * This method continues the link training for the phy as if it were a SAS PHY
554 * instead of a SATA PHY. This is done because the completion queue had a SAS
555 * PHY DETECTED event when the state machine was expecting a SATA PHY event.
556 * none
557 */
558static void scic_sds_phy_start_sas_link_training(
559 struct scic_sds_phy *sci_phy)
560{
561 u32 phy_control;
562
563 phy_control =
564 readl(&sci_phy->link_layer_registers->phy_configuration);
565 phy_control |= SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD);
566 writel(phy_control,
567 &sci_phy->link_layer_registers->phy_configuration);
568
569 sci_base_state_machine_change_state(
4a33c525 570 &sci_phy->state_machine,
d35bc1bd
DW
571 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN
572 );
573
574 sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SAS;
575}
576
577/**
578 *
579 * @sci_phy: The phy object that received a SATA SPINUP HOLD event
580 *
581 * This method continues the link training for the phy as if it were a SATA PHY
582 * instead of a SAS PHY. This is done because the completion queue had a SATA
583 * SPINUP HOLD event when the state machine was expecting a SAS PHY event. none
584 */
585static void scic_sds_phy_start_sata_link_training(
586 struct scic_sds_phy *sci_phy)
587{
588 sci_base_state_machine_change_state(
4a33c525 589 &sci_phy->state_machine,
d35bc1bd
DW
590 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER
591 );
592
593 sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
594}
595
596/**
597 * scic_sds_phy_complete_link_training - perform processing common to
598 * all protocols upon completion of link training.
599 * @sci_phy: This parameter specifies the phy object for which link training
600 * has completed.
601 * @max_link_rate: This parameter specifies the maximum link rate to be
602 * associated with this phy.
603 * @next_state: This parameter specifies the next state for the phy's starting
604 * sub-state machine.
605 *
606 */
607static void scic_sds_phy_complete_link_training(
608 struct scic_sds_phy *sci_phy,
609 enum sas_linkrate max_link_rate,
610 u32 next_state)
611{
612 sci_phy->max_negotiated_speed = max_link_rate;
613
4a33c525 614 sci_base_state_machine_change_state(&sci_phy->state_machine,
d35bc1bd
DW
615 next_state);
616}
617
23506a69
DW
618enum sci_status scic_sds_phy_event_handler(struct scic_sds_phy *sci_phy,
619 u32 event_code)
4a33c525 620{
23506a69 621 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
4a33c525 622
23506a69
DW
623 switch (state) {
624 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN:
625 switch (scu_get_event_code(event_code)) {
626 case SCU_EVENT_SAS_PHY_DETECTED:
627 scic_sds_phy_start_sas_link_training(sci_phy);
628 sci_phy->is_in_link_training = true;
629 break;
630 case SCU_EVENT_SATA_SPINUP_HOLD:
631 scic_sds_phy_start_sata_link_training(sci_phy);
632 sci_phy->is_in_link_training = true;
633 break;
634 default:
635 dev_dbg(sciphy_to_dev(sci_phy),
636 "%s: PHY starting substate machine received "
637 "unexpected event_code %x\n",
638 __func__,
639 event_code);
640 return SCI_FAILURE;
641 }
642 return SCI_SUCCESS;
643 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN:
644 switch (scu_get_event_code(event_code)) {
645 case SCU_EVENT_SAS_PHY_DETECTED:
646 /*
647 * Why is this being reported again by the controller?
648 * We would re-enter this state so just stay here */
649 break;
650 case SCU_EVENT_SAS_15:
651 case SCU_EVENT_SAS_15_SSC:
652 scic_sds_phy_complete_link_training(
653 sci_phy,
654 SAS_LINK_RATE_1_5_GBPS,
655 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF);
656 break;
657 case SCU_EVENT_SAS_30:
658 case SCU_EVENT_SAS_30_SSC:
659 scic_sds_phy_complete_link_training(
660 sci_phy,
661 SAS_LINK_RATE_3_0_GBPS,
662 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF);
663 break;
664 case SCU_EVENT_SAS_60:
665 case SCU_EVENT_SAS_60_SSC:
666 scic_sds_phy_complete_link_training(
667 sci_phy,
668 SAS_LINK_RATE_6_0_GBPS,
669 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF);
670 break;
671 case SCU_EVENT_SATA_SPINUP_HOLD:
672 /*
673 * We were doing SAS PHY link training and received a SATA PHY event
674 * continue OOB/SN as if this were a SATA PHY */
675 scic_sds_phy_start_sata_link_training(sci_phy);
676 break;
677 case SCU_EVENT_LINK_FAILURE:
678 /* Link failure change state back to the starting state */
679 sci_base_state_machine_change_state(&sci_phy->state_machine,
680 SCI_BASE_PHY_STATE_STARTING);
681 break;
682 default:
683 dev_warn(sciphy_to_dev(sci_phy),
684 "%s: PHY starting substate machine received "
685 "unexpected event_code %x\n",
686 __func__, event_code);
687
688 return SCI_FAILURE;
689 break;
690 }
691 return SCI_SUCCESS;
692 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF:
693 switch (scu_get_event_code(event_code)) {
694 case SCU_EVENT_SAS_PHY_DETECTED:
695 /* Backup the state machine */
696 scic_sds_phy_start_sas_link_training(sci_phy);
697 break;
698 case SCU_EVENT_SATA_SPINUP_HOLD:
699 /* We were doing SAS PHY link training and received a
700 * SATA PHY event continue OOB/SN as if this were a
701 * SATA PHY
702 */
703 scic_sds_phy_start_sata_link_training(sci_phy);
704 break;
705 case SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT:
706 case SCU_EVENT_LINK_FAILURE:
707 case SCU_EVENT_HARD_RESET_RECEIVED:
708 /* Start the oob/sn state machine over again */
709 sci_base_state_machine_change_state(&sci_phy->state_machine,
710 SCI_BASE_PHY_STATE_STARTING);
711 break;
712 default:
713 dev_warn(sciphy_to_dev(sci_phy),
714 "%s: PHY starting substate machine received "
715 "unexpected event_code %x\n",
716 __func__, event_code);
717 return SCI_FAILURE;
718 }
719 return SCI_SUCCESS;
720 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER:
721 switch (scu_get_event_code(event_code)) {
722 case SCU_EVENT_LINK_FAILURE:
723 /* Link failure change state back to the starting state */
724 sci_base_state_machine_change_state(&sci_phy->state_machine,
725 SCI_BASE_PHY_STATE_STARTING);
726 break;
727 default:
728 dev_warn(sciphy_to_dev(sci_phy),
729 "%s: PHY starting substate machine received unexpected "
730 "event_code %x\n",
731 __func__,
732 event_code);
733 return SCI_FAILURE;
734 }
735 return SCI_SUCCESS;
736 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER:
737 switch (scu_get_event_code(event_code)) {
738 case SCU_EVENT_LINK_FAILURE:
739 /* Link failure change state back to the starting state */
740 sci_base_state_machine_change_state(&sci_phy->state_machine,
741 SCI_BASE_PHY_STATE_STARTING);
742 break;
743 case SCU_EVENT_SATA_SPINUP_HOLD:
744 /* These events are received every 10ms and are
745 * expected while in this state
746 */
747 break;
748
749 case SCU_EVENT_SAS_PHY_DETECTED:
750 /* There has been a change in the phy type before OOB/SN for the
751 * SATA finished start down the SAS link traning path.
752 */
753 scic_sds_phy_start_sas_link_training(sci_phy);
754 break;
755
756 default:
757 dev_warn(sciphy_to_dev(sci_phy),
758 "%s: PHY starting substate machine received "
759 "unexpected event_code %x\n",
760 __func__, event_code);
4a33c525 761
23506a69
DW
762 return SCI_FAILURE;
763 }
764 return SCI_SUCCESS;
765 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN:
766 switch (scu_get_event_code(event_code)) {
767 case SCU_EVENT_LINK_FAILURE:
768 /* Link failure change state back to the starting state */
769 sci_base_state_machine_change_state(&sci_phy->state_machine,
770 SCI_BASE_PHY_STATE_STARTING);
771 break;
772 case SCU_EVENT_SATA_SPINUP_HOLD:
773 /* These events might be received since we dont know how many may be in
774 * the completion queue while waiting for power
775 */
776 break;
777 case SCU_EVENT_SATA_PHY_DETECTED:
778 sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_SATA;
779
780 /* We have received the SATA PHY notification change state */
781 sci_base_state_machine_change_state(&sci_phy->state_machine,
782 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN);
783 break;
784 case SCU_EVENT_SAS_PHY_DETECTED:
785 /* There has been a change in the phy type before OOB/SN for the
786 * SATA finished start down the SAS link traning path.
787 */
788 scic_sds_phy_start_sas_link_training(sci_phy);
789 break;
790 default:
791 dev_warn(sciphy_to_dev(sci_phy),
792 "%s: PHY starting substate machine received "
793 "unexpected event_code %x\n",
794 __func__,
795 event_code);
4a33c525 796
23506a69
DW
797 return SCI_FAILURE;;
798 }
799 return SCI_SUCCESS;
800 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN:
801 switch (scu_get_event_code(event_code)) {
802 case SCU_EVENT_SATA_PHY_DETECTED:
803 /*
804 * The hardware reports multiple SATA PHY detected events
805 * ignore the extras */
806 break;
807 case SCU_EVENT_SATA_15:
808 case SCU_EVENT_SATA_15_SSC:
809 scic_sds_phy_complete_link_training(
810 sci_phy,
811 SAS_LINK_RATE_1_5_GBPS,
812 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF);
813 break;
814 case SCU_EVENT_SATA_30:
815 case SCU_EVENT_SATA_30_SSC:
816 scic_sds_phy_complete_link_training(
817 sci_phy,
818 SAS_LINK_RATE_3_0_GBPS,
819 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF);
820 break;
821 case SCU_EVENT_SATA_60:
822 case SCU_EVENT_SATA_60_SSC:
823 scic_sds_phy_complete_link_training(
824 sci_phy,
825 SAS_LINK_RATE_6_0_GBPS,
826 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF);
827 break;
828 case SCU_EVENT_LINK_FAILURE:
829 /* Link failure change state back to the starting state */
830 sci_base_state_machine_change_state(&sci_phy->state_machine,
831 SCI_BASE_PHY_STATE_STARTING);
832 break;
833 case SCU_EVENT_SAS_PHY_DETECTED:
834 /*
835 * There has been a change in the phy type before OOB/SN for the
836 * SATA finished start down the SAS link traning path. */
837 scic_sds_phy_start_sas_link_training(sci_phy);
838 break;
839 default:
840 dev_warn(sciphy_to_dev(sci_phy),
841 "%s: PHY starting substate machine received "
842 "unexpected event_code %x\n",
843 __func__, event_code);
4a33c525 844
23506a69
DW
845 return SCI_FAILURE;
846 }
847
848 return SCI_SUCCESS;
849 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF:
850 switch (scu_get_event_code(event_code)) {
851 case SCU_EVENT_SATA_PHY_DETECTED:
852 /* Backup the state machine */
853 sci_base_state_machine_change_state(&sci_phy->state_machine,
854 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN);
855 break;
4a33c525 856
23506a69
DW
857 case SCU_EVENT_LINK_FAILURE:
858 /* Link failure change state back to the starting state */
859 sci_base_state_machine_change_state(&sci_phy->state_machine,
860 SCI_BASE_PHY_STATE_STARTING);
861 break;
862
863 default:
864 dev_warn(sciphy_to_dev(sci_phy),
865 "%s: PHY starting substate machine received "
866 "unexpected event_code %x\n",
867 __func__,
868 event_code);
869
870 return SCI_FAILURE;
871 }
872 return SCI_SUCCESS;
873 case SCI_BASE_PHY_STATE_READY:
874 switch (scu_get_event_code(event_code)) {
875 case SCU_EVENT_LINK_FAILURE:
876 /* Link failure change state back to the starting state */
877 sci_base_state_machine_change_state(&sci_phy->state_machine,
878 SCI_BASE_PHY_STATE_STARTING);
879 break;
880 case SCU_EVENT_BROADCAST_CHANGE:
881 /* Broadcast change received. Notify the port. */
4f20ef4f 882 if (phy_get_non_dummy_port(sci_phy) != NULL)
23506a69
DW
883 scic_sds_port_broadcast_change_received(sci_phy->owning_port, sci_phy);
884 else
885 sci_phy->bcn_received_while_port_unassigned = true;
886 break;
887 default:
888 dev_warn(sciphy_to_dev(sci_phy),
889 "%sP SCIC PHY 0x%p ready state machine received "
890 "unexpected event_code %x\n",
891 __func__, sci_phy, event_code);
892 return SCI_FAILURE_INVALID_STATE;
893 }
894 return SCI_SUCCESS;
895 case SCI_BASE_PHY_STATE_RESETTING:
896 switch (scu_get_event_code(event_code)) {
897 case SCU_EVENT_HARD_RESET_TRANSMITTED:
898 /* Link failure change state back to the starting state */
899 sci_base_state_machine_change_state(&sci_phy->state_machine,
900 SCI_BASE_PHY_STATE_STARTING);
901 break;
902 default:
903 dev_warn(sciphy_to_dev(sci_phy),
904 "%s: SCIC PHY 0x%p resetting state machine received "
905 "unexpected event_code %x\n",
906 __func__, sci_phy, event_code);
907
908 return SCI_FAILURE_INVALID_STATE;
909 break;
910 }
911 return SCI_SUCCESS;
912 default:
913 dev_dbg(sciphy_to_dev(sci_phy),
914 "%s: in wrong state: %d\n", __func__, state);
915 return SCI_FAILURE_INVALID_STATE;
916 }
4a33c525
AG
917}
918
23506a69
DW
919enum sci_status scic_sds_phy_frame_handler(struct scic_sds_phy *sci_phy,
920 u32 frame_index)
4a33c525 921{
23506a69
DW
922 enum scic_sds_phy_states state = sci_phy->state_machine.current_state_id;
923 struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
924 enum sci_status result;
4a33c525 925
23506a69
DW
926 switch (state) {
927 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF: {
928 u32 *frame_words;
929 struct sas_identify_frame iaf;
930 struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
4a33c525 931
23506a69
DW
932 result = scic_sds_unsolicited_frame_control_get_header(&scic->uf_control,
933 frame_index,
934 (void **)&frame_words);
4a33c525 935
23506a69
DW
936 if (result != SCI_SUCCESS)
937 return result;
938
939 sci_swab32_cpy(&iaf, frame_words, sizeof(iaf) / sizeof(u32));
940 if (iaf.frame_type == 0) {
941 u32 state;
942
943 memcpy(&iphy->frame_rcvd.iaf, &iaf, sizeof(iaf));
944 if (iaf.smp_tport) {
945 /* We got the IAF for an expander PHY go to the final
946 * state since there are no power requirements for
947 * expander phys.
948 */
949 state = SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL;
950 } else {
951 /* We got the IAF we can now go to the await spinup
952 * semaphore state
953 */
954 state = SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER;
955 }
956 sci_base_state_machine_change_state(&sci_phy->state_machine,
957 state);
958 result = SCI_SUCCESS;
959 } else
960 dev_warn(sciphy_to_dev(sci_phy),
961 "%s: PHY starting substate machine received "
962 "unexpected frame id %x\n",
963 __func__, frame_index);
964
965 scic_sds_controller_release_frame(scic, frame_index);
966 return result;
4a33c525 967 }
23506a69
DW
968 case SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF: {
969 struct dev_to_host_fis *frame_header;
970 u32 *fis_frame_data;
971 struct isci_phy *iphy = sci_phy_to_iphy(sci_phy);
972
973 result = scic_sds_unsolicited_frame_control_get_header(
974 &(scic_sds_phy_get_controller(sci_phy)->uf_control),
975 frame_index,
976 (void **)&frame_header);
977
978 if (result != SCI_SUCCESS)
979 return result;
4a33c525 980
23506a69
DW
981 if ((frame_header->fis_type == FIS_REGD2H) &&
982 !(frame_header->status & ATA_BUSY)) {
983 scic_sds_unsolicited_frame_control_get_buffer(&scic->uf_control,
984 frame_index,
985 (void **)&fis_frame_data);
986
987 scic_sds_controller_copy_sata_response(&iphy->frame_rcvd.fis,
988 frame_header,
989 fis_frame_data);
990
991 /* got IAF we can now go to the await spinup semaphore state */
992 sci_base_state_machine_change_state(&sci_phy->state_machine,
993 SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL);
994
995 result = SCI_SUCCESS;
996 } else
997 dev_warn(sciphy_to_dev(sci_phy),
998 "%s: PHY starting substate machine received "
999 "unexpected frame id %x\n",
1000 __func__, frame_index);
1001
1002 /* Regardless of the result we are done with this frame with it */
1003 scic_sds_controller_release_frame(scic, frame_index);
1004
1005 return result;
1006 }
1007 default:
1008 dev_dbg(sciphy_to_dev(sci_phy),
1009 "%s: in wrong state: %d\n", __func__, state);
1010 return SCI_FAILURE_INVALID_STATE;
1011 }
1012
4a33c525
AG
1013}
1014
9269e0e8 1015static void scic_sds_phy_starting_initial_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1016{
9269e0e8 1017 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1018
d35bc1bd 1019 /* This is just an temporary state go off to the starting state */
4a33c525 1020 sci_base_state_machine_change_state(&sci_phy->state_machine,
d35bc1bd
DW
1021 SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN);
1022}
1023
9269e0e8 1024static void scic_sds_phy_starting_await_sas_power_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1025{
9269e0e8 1026 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
5b1d4af2 1027 struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
d35bc1bd 1028
5b1d4af2 1029 scic_sds_controller_power_control_queue_insert(scic, sci_phy);
d35bc1bd
DW
1030}
1031
9269e0e8 1032static void scic_sds_phy_starting_await_sas_power_substate_exit(struct sci_base_state_machine *sm)
d35bc1bd 1033{
9269e0e8 1034 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
5b1d4af2 1035 struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
d35bc1bd 1036
5b1d4af2 1037 scic_sds_controller_power_control_queue_remove(scic, sci_phy);
d35bc1bd
DW
1038}
1039
9269e0e8 1040static void scic_sds_phy_starting_await_sata_power_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1041{
9269e0e8 1042 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
5b1d4af2 1043 struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
d35bc1bd 1044
5b1d4af2 1045 scic_sds_controller_power_control_queue_insert(scic, sci_phy);
d35bc1bd
DW
1046}
1047
9269e0e8 1048static void scic_sds_phy_starting_await_sata_power_substate_exit(struct sci_base_state_machine *sm)
d35bc1bd 1049{
9269e0e8 1050 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
5b1d4af2 1051 struct scic_sds_controller *scic = sci_phy->owning_port->owning_controller;
d35bc1bd 1052
5b1d4af2 1053 scic_sds_controller_power_control_queue_remove(scic, sci_phy);
d35bc1bd
DW
1054}
1055
9269e0e8 1056static void scic_sds_phy_starting_await_sata_phy_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1057{
9269e0e8 1058 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1059
a628d478 1060 sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT);
d35bc1bd
DW
1061}
1062
9269e0e8 1063static void scic_sds_phy_starting_await_sata_phy_substate_exit(struct sci_base_state_machine *sm)
d35bc1bd 1064{
9269e0e8 1065 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1066
a628d478 1067 sci_del_timer(&sci_phy->sata_timer);
d35bc1bd
DW
1068}
1069
9269e0e8 1070static void scic_sds_phy_starting_await_sata_speed_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1071{
9269e0e8 1072 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1073
a628d478 1074 sci_mod_timer(&sci_phy->sata_timer, SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT);
d35bc1bd
DW
1075}
1076
9269e0e8 1077static void scic_sds_phy_starting_await_sata_speed_substate_exit(struct sci_base_state_machine *sm)
d35bc1bd 1078{
9269e0e8 1079 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1080
a628d478 1081 sci_del_timer(&sci_phy->sata_timer);
d35bc1bd
DW
1082}
1083
9269e0e8 1084static void scic_sds_phy_starting_await_sig_fis_uf_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1085{
9269e0e8 1086 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1087
5b1d4af2 1088 if (scic_sds_port_link_detected(sci_phy->owning_port, sci_phy)) {
d35bc1bd 1089
d35bc1bd
DW
1090 /*
1091 * Clear the PE suspend condition so we can actually
1092 * receive SIG FIS
1093 * The hardware will not respond to the XRDY until the PE
1094 * suspend condition is cleared.
1095 */
1096 scic_sds_phy_resume(sci_phy);
1097
a628d478
EN
1098 sci_mod_timer(&sci_phy->sata_timer,
1099 SCIC_SDS_SIGNATURE_FIS_TIMEOUT);
d35bc1bd
DW
1100 } else
1101 sci_phy->is_in_link_training = false;
1102}
1103
9269e0e8 1104static void scic_sds_phy_starting_await_sig_fis_uf_substate_exit(struct sci_base_state_machine *sm)
d35bc1bd 1105{
9269e0e8 1106 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1107
a628d478 1108 sci_del_timer(&sci_phy->sata_timer);
d35bc1bd
DW
1109}
1110
9269e0e8 1111static void scic_sds_phy_starting_final_substate_enter(struct sci_base_state_machine *sm)
d35bc1bd 1112{
9269e0e8 1113 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1114
d35bc1bd
DW
1115 /* State machine has run to completion so exit out and change
1116 * the base state machine to the ready state
1117 */
1118 sci_base_state_machine_change_state(&sci_phy->state_machine,
1119 SCI_BASE_PHY_STATE_READY);
1120}
1121
d35bc1bd
DW
1122/**
1123 *
1124 * @sci_phy: This is the struct scic_sds_phy object to stop.
1125 *
1126 * This method will stop the struct scic_sds_phy object. This does not reset the
1127 * protocol engine it just suspends it and places it in a state where it will
1128 * not cause the end device to power up. none
1129 */
1130static void scu_link_layer_stop_protocol_engine(
1131 struct scic_sds_phy *sci_phy)
1132{
1133 u32 scu_sas_pcfg_value;
1134 u32 enable_spinup_value;
1135
1136 /* Suspend the protocol engine and place it in a sata spinup hold state */
1137 scu_sas_pcfg_value =
1138 readl(&sci_phy->link_layer_registers->phy_configuration);
1139 scu_sas_pcfg_value |=
1140 (SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
1141 SCU_SAS_PCFG_GEN_BIT(SUSPEND_PROTOCOL_ENGINE) |
1142 SCU_SAS_PCFG_GEN_BIT(SATA_SPINUP_HOLD));
1143 writel(scu_sas_pcfg_value,
1144 &sci_phy->link_layer_registers->phy_configuration);
1145
1146 /* Disable the notify enable spinup primitives */
1147 enable_spinup_value = readl(&sci_phy->link_layer_registers->notify_enable_spinup_control);
1148 enable_spinup_value &= ~SCU_ENSPINUP_GEN_BIT(ENABLE);
1149 writel(enable_spinup_value, &sci_phy->link_layer_registers->notify_enable_spinup_control);
1150}
1151
1152/**
1153 *
1154 *
1155 * This method will start the OOB/SN state machine for this struct scic_sds_phy object.
1156 */
1157static void scu_link_layer_start_oob(
1158 struct scic_sds_phy *sci_phy)
1159{
1160 u32 scu_sas_pcfg_value;
1161
1162 scu_sas_pcfg_value =
1163 readl(&sci_phy->link_layer_registers->phy_configuration);
1164 scu_sas_pcfg_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
1165 scu_sas_pcfg_value &=
1166 ~(SCU_SAS_PCFG_GEN_BIT(OOB_RESET) |
1167 SCU_SAS_PCFG_GEN_BIT(HARD_RESET));
1168 writel(scu_sas_pcfg_value,
1169 &sci_phy->link_layer_registers->phy_configuration);
1170}
1171
1172/**
1173 *
1174 *
1175 * This method will transmit a hard reset request on the specified phy. The SCU
1176 * hardware requires that we reset the OOB state machine and set the hard reset
1177 * bit in the phy configuration register. We then must start OOB over with the
1178 * hard reset bit set.
1179 */
1180static void scu_link_layer_tx_hard_reset(
1181 struct scic_sds_phy *sci_phy)
1182{
1183 u32 phy_configuration_value;
1184
1185 /*
1186 * SAS Phys must wait for the HARD_RESET_TX event notification to transition
1187 * to the starting state. */
1188 phy_configuration_value =
1189 readl(&sci_phy->link_layer_registers->phy_configuration);
1190 phy_configuration_value |=
1191 (SCU_SAS_PCFG_GEN_BIT(HARD_RESET) |
1192 SCU_SAS_PCFG_GEN_BIT(OOB_RESET));
1193 writel(phy_configuration_value,
1194 &sci_phy->link_layer_registers->phy_configuration);
1195
1196 /* Now take the OOB state machine out of reset */
1197 phy_configuration_value |= SCU_SAS_PCFG_GEN_BIT(OOB_ENABLE);
1198 phy_configuration_value &= ~SCU_SAS_PCFG_GEN_BIT(OOB_RESET);
1199 writel(phy_configuration_value,
1200 &sci_phy->link_layer_registers->phy_configuration);
1201}
1202
9269e0e8 1203static void scic_sds_phy_stopped_state_enter(struct sci_base_state_machine *sm)
d35bc1bd 1204{
9269e0e8 1205 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd
DW
1206
1207 /*
1208 * @todo We need to get to the controller to place this PE in a
1209 * reset state
1210 */
a628d478 1211 sci_del_timer(&sci_phy->sata_timer);
d35bc1bd
DW
1212
1213 scu_link_layer_stop_protocol_engine(sci_phy);
1214
5b1d4af2
DW
1215 if (sci_phy->state_machine.previous_state_id != SCI_BASE_PHY_STATE_INITIAL)
1216 scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy),
4f20ef4f 1217 phy_get_non_dummy_port(sci_phy),
5b1d4af2 1218 sci_phy);
d35bc1bd
DW
1219}
1220
9269e0e8 1221static void scic_sds_phy_starting_state_enter(struct sci_base_state_machine *sm)
d35bc1bd 1222{
9269e0e8 1223 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1224
d35bc1bd
DW
1225 scu_link_layer_stop_protocol_engine(sci_phy);
1226 scu_link_layer_start_oob(sci_phy);
1227
1228 /* We don't know what kind of phy we are going to be just yet */
1229 sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
1230 sci_phy->bcn_received_while_port_unassigned = false;
1231
5b1d4af2
DW
1232 if (sci_phy->state_machine.previous_state_id == SCI_BASE_PHY_STATE_READY)
1233 scic_sds_controller_link_down(scic_sds_phy_get_controller(sci_phy),
4f20ef4f 1234 phy_get_non_dummy_port(sci_phy),
5b1d4af2 1235 sci_phy);
4a33c525
AG
1236
1237 sci_base_state_machine_change_state(&sci_phy->state_machine,
1238 SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL);
d35bc1bd
DW
1239}
1240
9269e0e8 1241static void scic_sds_phy_ready_state_enter(struct sci_base_state_machine *sm)
d35bc1bd 1242{
9269e0e8 1243 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1244
5b1d4af2 1245 scic_sds_controller_link_up(scic_sds_phy_get_controller(sci_phy),
4f20ef4f 1246 phy_get_non_dummy_port(sci_phy),
5b1d4af2 1247 sci_phy);
d35bc1bd 1248
d35bc1bd
DW
1249}
1250
9269e0e8 1251static void scic_sds_phy_ready_state_exit(struct sci_base_state_machine *sm)
d35bc1bd 1252{
9269e0e8 1253 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd
DW
1254
1255 scic_sds_phy_suspend(sci_phy);
1256}
1257
9269e0e8 1258static void scic_sds_phy_resetting_state_enter(struct sci_base_state_machine *sm)
d35bc1bd 1259{
9269e0e8 1260 struct scic_sds_phy *sci_phy = container_of(sm, typeof(*sci_phy), state_machine);
d35bc1bd 1261
5b1d4af2
DW
1262 /* The phy is being reset, therefore deactivate it from the port. In
1263 * the resetting state we don't notify the user regarding link up and
1264 * link down notifications
1265 */
d35bc1bd
DW
1266 scic_sds_port_deactivate_phy(sci_phy->owning_port, sci_phy, false);
1267
1268 if (sci_phy->protocol == SCIC_SDS_PHY_PROTOCOL_SAS) {
1269 scu_link_layer_tx_hard_reset(sci_phy);
1270 } else {
5b1d4af2 1271 /* The SCU does not need to have a discrete reset state so
d35bc1bd
DW
1272 * just go back to the starting state.
1273 */
5b1d4af2
DW
1274 sci_base_state_machine_change_state(&sci_phy->state_machine,
1275 SCI_BASE_PHY_STATE_STARTING);
d35bc1bd
DW
1276 }
1277}
1278
d35bc1bd 1279static const struct sci_base_state scic_sds_phy_state_table[] = {
5b1d4af2 1280 [SCI_BASE_PHY_STATE_INITIAL] = { },
d35bc1bd
DW
1281 [SCI_BASE_PHY_STATE_STOPPED] = {
1282 .enter_state = scic_sds_phy_stopped_state_enter,
1283 },
1284 [SCI_BASE_PHY_STATE_STARTING] = {
1285 .enter_state = scic_sds_phy_starting_state_enter,
1286 },
4a33c525
AG
1287 [SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL] = {
1288 .enter_state = scic_sds_phy_starting_initial_substate_enter,
1289 },
5b1d4af2
DW
1290 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN] = { },
1291 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN] = { },
1292 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF] = { },
4a33c525
AG
1293 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER] = {
1294 .enter_state = scic_sds_phy_starting_await_sas_power_substate_enter,
1295 .exit_state = scic_sds_phy_starting_await_sas_power_substate_exit,
1296 },
1297 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER] = {
1298 .enter_state = scic_sds_phy_starting_await_sata_power_substate_enter,
1299 .exit_state = scic_sds_phy_starting_await_sata_power_substate_exit
1300 },
1301 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN] = {
1302 .enter_state = scic_sds_phy_starting_await_sata_phy_substate_enter,
1303 .exit_state = scic_sds_phy_starting_await_sata_phy_substate_exit
1304 },
1305 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN] = {
1306 .enter_state = scic_sds_phy_starting_await_sata_speed_substate_enter,
1307 .exit_state = scic_sds_phy_starting_await_sata_speed_substate_exit
1308 },
1309 [SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF] = {
1310 .enter_state = scic_sds_phy_starting_await_sig_fis_uf_substate_enter,
1311 .exit_state = scic_sds_phy_starting_await_sig_fis_uf_substate_exit
1312 },
1313 [SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL] = {
1314 .enter_state = scic_sds_phy_starting_final_substate_enter,
1315 },
d35bc1bd
DW
1316 [SCI_BASE_PHY_STATE_READY] = {
1317 .enter_state = scic_sds_phy_ready_state_enter,
1318 .exit_state = scic_sds_phy_ready_state_exit,
1319 },
1320 [SCI_BASE_PHY_STATE_RESETTING] = {
1321 .enter_state = scic_sds_phy_resetting_state_enter,
1322 },
5b1d4af2 1323 [SCI_BASE_PHY_STATE_FINAL] = { },
d35bc1bd
DW
1324};
1325
1326void scic_sds_phy_construct(struct scic_sds_phy *sci_phy,
1327 struct scic_sds_port *owning_port, u8 phy_index)
1328{
1329 sci_base_state_machine_construct(&sci_phy->state_machine,
d35bc1bd
DW
1330 scic_sds_phy_state_table,
1331 SCI_BASE_PHY_STATE_INITIAL);
1332
1333 sci_base_state_machine_start(&sci_phy->state_machine);
1334
1335 /* Copy the rest of the input data to our locals */
1336 sci_phy->owning_port = owning_port;
1337 sci_phy->phy_index = phy_index;
1338 sci_phy->bcn_received_while_port_unassigned = false;
1339 sci_phy->protocol = SCIC_SDS_PHY_PROTOCOL_UNKNOWN;
1340 sci_phy->link_layer_registers = NULL;
1341 sci_phy->max_negotiated_speed = SAS_LINK_RATE_UNKNOWN;
a628d478
EN
1342
1343 /* Create the SIGNATURE FIS Timeout timer for this phy */
1344 sci_init_timer(&sci_phy->sata_timer, phy_sata_timeout);
d35bc1bd 1345}
6f231dda 1346
4b33981a 1347void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index)
6f231dda 1348{
150fc6fc 1349 union scic_oem_parameters oem;
4b33981a
DW
1350 u64 sci_sas_addr;
1351 __be64 sas_addr;
1352
1353 scic_oem_parameters_get(&ihost->sci, &oem);
1354 sci_sas_addr = oem.sds1.phys[index].sas_address.high;
1355 sci_sas_addr <<= 32;
1356 sci_sas_addr |= oem.sds1.phys[index].sas_address.low;
1357 sas_addr = cpu_to_be64(sci_sas_addr);
1358 memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr));
1359
1360 iphy->isci_port = NULL;
1361 iphy->sas_phy.enabled = 0;
1362 iphy->sas_phy.id = index;
1363 iphy->sas_phy.sas_addr = &iphy->sas_addr[0];
1364 iphy->sas_phy.frame_rcvd = (u8 *)&iphy->frame_rcvd;
1365 iphy->sas_phy.ha = &ihost->sas_ha;
1366 iphy->sas_phy.lldd_phy = iphy;
1367 iphy->sas_phy.enabled = 1;
1368 iphy->sas_phy.class = SAS;
1369 iphy->sas_phy.iproto = SAS_PROTOCOL_ALL;
1370 iphy->sas_phy.tproto = 0;
1371 iphy->sas_phy.type = PHY_TYPE_PHYSICAL;
1372 iphy->sas_phy.role = PHY_ROLE_INITIATOR;
1373 iphy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
1374 iphy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
1375 memset(&iphy->frame_rcvd, 0, sizeof(iphy->frame_rcvd));
6f231dda
DW
1376}
1377
1378
1379/**
1380 * isci_phy_control() - This function is one of the SAS Domain Template
1381 * functions. This is a phy management function.
1382 * @phy: This parameter specifies the sphy being controlled.
1383 * @func: This parameter specifies the phy control function being invoked.
1384 * @buf: This parameter is specific to the phy function being invoked.
1385 *
1386 * status, zero indicates success.
1387 */
4d07f7f3
DJ
1388int isci_phy_control(struct asd_sas_phy *sas_phy,
1389 enum phy_func func,
1390 void *buf)
6f231dda 1391{
4d07f7f3
DJ
1392 int ret = 0;
1393 struct isci_phy *iphy = sas_phy->lldd_phy;
1394 struct isci_port *iport = iphy->isci_port;
1395 struct isci_host *ihost = sas_phy->ha->lldd_ha;
1396 unsigned long flags;
6f231dda 1397
4d07f7f3
DJ
1398 dev_dbg(&ihost->pdev->dev,
1399 "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
1400 __func__, sas_phy, func, buf, iphy, iport);
6f231dda
DW
1401
1402 switch (func) {
4d07f7f3
DJ
1403 case PHY_FUNC_DISABLE:
1404 spin_lock_irqsave(&ihost->scic_lock, flags);
4b33981a 1405 scic_sds_phy_stop(&iphy->sci);
4d07f7f3
DJ
1406 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1407 break;
1408
6f231dda 1409 case PHY_FUNC_LINK_RESET:
4d07f7f3 1410 spin_lock_irqsave(&ihost->scic_lock, flags);
4b33981a
DW
1411 scic_sds_phy_stop(&iphy->sci);
1412 scic_sds_phy_start(&iphy->sci);
4d07f7f3
DJ
1413 spin_unlock_irqrestore(&ihost->scic_lock, flags);
1414 break;
1415
1416 case PHY_FUNC_HARD_RESET:
1417 if (!iport)
1418 return -ENODEV;
6f231dda
DW
1419
1420 /* Perform the port reset. */
4393aa4e 1421 ret = isci_port_perform_hard_reset(ihost, iport, iphy);
6f231dda
DW
1422
1423 break;
1424
6f231dda 1425 default:
4d07f7f3
DJ
1426 dev_dbg(&ihost->pdev->dev,
1427 "%s: phy %p; func %d NOT IMPLEMENTED!\n",
1428 __func__, sas_phy, func);
1429 ret = -ENOSYS;
6f231dda
DW
1430 break;
1431 }
1432 return ret;
1433}
This page took 0.119086 seconds and 5 git commands to generate.