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