xref: /freebsd/sys/dev/isci/scil/scic_sds_sgpio.c (revision fed1ca4b719c56c930f2259d80663cd34be812bb)
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  *
40  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
43  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
44  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
47  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
48  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
49  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
50  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51  */
52 
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
55 
56 /**
57 * @file
58 *
59 * @brief This file contains the implementation of the SGPIO register inteface
60 *        methods.
61 */
62 
63 #include <dev/isci/scil/scic_sgpio.h>
64 #include <dev/isci/scil/scic_sds_controller_registers.h>
65 #include <dev/isci/scil/scic_user_callback.h>
66 
67 /**
68  * @brief Function writes Value to the
69  *        SGPIO Output Data Select Register (SGODSR) for phys specified by
70  *        phy_mask paremeter
71  *
72  * @param[in] SCIC_SDS_CONTROLLER_T controller
73  * @param[in] phy_mask - This field is a bit mask that specifies the phys
74  *                       to be updated.
75  * @param[in] value - Value for write
76  *
77  * @return none
78  */
79 static
80 void scic_sgpio_write_SGODSR_register(
81    SCIC_SDS_CONTROLLER_T *controller,
82    U32 phy_mask,
83    U32 value
84 )
85 {
86    U8 phy_index;
87 
88    for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++)
89    {
90       if (phy_mask >> phy_index & 1)
91       {
92           scu_sgpio_peg0_register_write(
93              controller, output_data_select[phy_index], value
94           );
95       }
96    }
97 }
98 
99 void scic_sgpio_set_vendor_code(
100    SCI_CONTROLLER_HANDLE_T controller,
101    U8 vendor_specific_sequence
102 )
103 {
104    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
105 
106    scu_sgpio_peg0_register_write(
107       core_controller, vendor_specific_code, vendor_specific_sequence);
108 }
109 
110 void scic_sgpio_set_blink_patterns(
111    SCI_CONTROLLER_HANDLE_T controller,
112    U8 pattern_a_low,
113    U8 pattern_a_high,
114    U8 pattern_b_low,
115    U8 pattern_b_high
116 )
117 {
118    U32 value;
119    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
120 
121    value = (pattern_b_high << 12) + (pattern_b_low << 8) + (pattern_a_high << 4) + pattern_a_low;
122 
123    scu_sgpio_peg0_register_write(
124       core_controller, blink_rate, value);
125 }
126 
127 void scic_sgpio_set_functionality(
128    SCI_CONTROLLER_HANDLE_T controller,
129    BOOL sgpio_mode
130 )
131 {
132    U32 value = DISABLE_SGPIO_FUNCTIONALITY;
133    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
134 
135    if(sgpio_mode)
136    {
137       value = ENABLE_SGPIO_FUNCTIONALITY;
138    }
139 
140    scu_sgpio_peg0_register_write(
141       core_controller, interface_control, value);
142 }
143 
144 void scic_sgpio_apply_led_blink_pattern(
145    SCI_CONTROLLER_HANDLE_T controller,
146    U32 phy_mask,
147    BOOL error,
148    BOOL locate,
149    BOOL activity,
150    U8 pattern_selection
151 )
152 {
153    U32 output_value = 0;
154 
155    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
156 
157    // Start with all LEDs turned off
158    output_value = (SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT)
159                      | (SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT)
160                      | (SGODSR_INVERT_BIT << SGODSR_ACTIVITY_LED_SHIFT);
161 
162    if(error)
163    {  //apply pattern to error LED
164       output_value |= pattern_selection << SGODSR_ERROR_LED_SHIFT;
165       output_value &= ~(SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT);
166    }
167    if(locate)
168    {  //apply pattern to locate LED
169       output_value |= pattern_selection << SGODSR_LOCATE_LED_SHIFT;
170       output_value &= ~(SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT);
171    }
172    if(activity)
173    {  //apply pattern to activity LED
174       output_value |= pattern_selection << SGODSR_ACTIVITY_LED_SHIFT;
175       output_value &= ~(SGODSR_INVERT_BIT << SGODSR_ACTIVITY_LED_SHIFT);
176    }
177 
178    scic_sgpio_write_SGODSR_register(core_controller, phy_mask, output_value);
179 }
180 
181 void scic_sgpio_set_led_blink_pattern(
182    SCI_CONTROLLER_HANDLE_T controller,
183    SCI_PORT_HANDLE_T port_handle,
184    BOOL error,
185    BOOL locate,
186    BOOL activity,
187    U8 pattern_selection
188 )
189 {
190    U32 phy_mask;
191 
192    SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *) port_handle;
193 
194    phy_mask = scic_sds_port_get_phys(port);
195 
196    scic_sgpio_apply_led_blink_pattern(
197            controller, phy_mask, error, locate, activity, pattern_selection);
198 }
199 
200 void scic_sgpio_update_led_state(
201    SCI_CONTROLLER_HANDLE_T controller,
202    U32 phy_mask,
203    BOOL error,
204    BOOL locate,
205    BOOL activity
206 )
207 {
208    U32 output_value;
209 
210    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
211 
212    // Start with all LEDs turned on
213    output_value = 0x00000000;
214 
215    if(!error)
216    {  //turn off error LED
217       output_value |= SGODSR_INVERT_BIT <<  SGODSR_ERROR_LED_SHIFT;
218    }
219    if(!locate)
220    {  //turn off locate LED
221       output_value |= SGODSR_INVERT_BIT <<  SGODSR_LOCATE_LED_SHIFT;
222    }
223    if(!activity)
224    {  //turn off activity LED
225       output_value |= SGODSR_INVERT_BIT <<  SGODSR_ACTIVITY_LED_SHIFT;
226    }
227 
228    scic_sgpio_write_SGODSR_register(core_controller, phy_mask, output_value);
229 }
230 
231 void scic_sgpio_set_led_state(
232    SCI_CONTROLLER_HANDLE_T controller,
233    SCI_PORT_HANDLE_T port_handle,
234    BOOL error,
235    BOOL locate,
236    BOOL activity
237 )
238 {
239    U32 phy_mask;
240 
241    SCIC_SDS_PORT_T * port = (SCIC_SDS_PORT_T *) port_handle;
242 
243    phy_mask = scic_sds_port_get_phys(port);
244 
245    scic_sgpio_update_led_state(controller, phy_mask, error, locate, activity);
246 }
247 
248 void scic_sgpio_set_to_hardware_control(
249    SCI_CONTROLLER_HANDLE_T controller,
250    BOOL is_hardware_controlled
251 )
252 {
253    SCIC_SDS_CONTROLLER_T * core_controller = (SCIC_SDS_CONTROLLER_T *) controller;
254    U8 i;
255    U32 output_value;
256 
257    //turn on hardware control for LED's
258    if(is_hardware_controlled)
259    {
260       output_value = SGPIO_HARDWARE_CONTROL;
261    }
262    else //turn off hardware control
263    {
264       output_value = SGPIO_SOFTWARE_CONTROL;
265    }
266 
267    for(i = 0; i < SCI_MAX_PHYS; i++)
268    {
269       scu_sgpio_peg0_register_write(
270          core_controller, output_data_select[i], output_value);
271    }
272 }
273 
274 U32 scic_sgpio_read(
275    SCI_CONTROLLER_HANDLE_T controller
276 )
277 {
278    //Not supported in the SCU hardware returning 0xFFFFFFFF
279    return 0xffffffff;
280 }
281 
282 void scic_sgpio_hardware_initialize(
283    SCI_CONTROLLER_HANDLE_T controller
284 )
285 {
286    scic_sgpio_set_functionality(controller, TRUE);
287    scic_sgpio_set_to_hardware_control(controller, TRUE);
288    scic_sgpio_set_vendor_code(controller, 0x00);
289 }
290 
291 void scic_sgpio_initialize(
292    SCI_CONTROLLER_HANDLE_T controller
293 )
294 {
295    scic_sgpio_set_functionality(controller, TRUE);
296    scic_sgpio_set_to_hardware_control(controller, FALSE);
297    scic_sgpio_set_vendor_code(controller, 0x00);
298 }
299