spi: sprd: adi: Add a reset reason for watchdog mode
[linux/fpc-iii.git] / drivers / pci / hotplug / pciehp_ctrl.c
blob631ced0ab28a0be5fd83f7bedeb279ca3bbc1988
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * PCI Express Hot Plug Controller Driver
5 * Copyright (C) 1995,2001 Compaq Computer Corporation
6 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
7 * Copyright (C) 2001 IBM Corp.
8 * Copyright (C) 2003-2004 Intel Corporation
10 * All rights reserved.
12 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
16 #define dev_fmt(fmt) "pciehp: " fmt
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/pci.h>
22 #include "pciehp.h"
24 /* The following routines constitute the bulk of the
25 hotplug controller logic
28 #define SAFE_REMOVAL true
29 #define SURPRISE_REMOVAL false
31 static void set_slot_off(struct controller *ctrl)
33 /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
34 if (POWER_CTRL(ctrl)) {
35 pciehp_power_off_slot(ctrl);
38 * After turning power off, we must wait for at least 1 second
39 * before taking any action that relies on power having been
40 * removed from the slot/adapter.
42 msleep(1000);
45 pciehp_green_led_off(ctrl);
46 pciehp_set_attention_status(ctrl, 1);
49 /**
50 * board_added - Called after a board has been added to the system.
51 * @ctrl: PCIe hotplug controller where board is added
53 * Turns power on for the board.
54 * Configures board.
56 static int board_added(struct controller *ctrl)
58 int retval = 0;
59 struct pci_bus *parent = ctrl->pcie->port->subordinate;
61 if (POWER_CTRL(ctrl)) {
62 /* Power on slot */
63 retval = pciehp_power_on_slot(ctrl);
64 if (retval)
65 return retval;
68 pciehp_green_led_blink(ctrl);
70 /* Check link training status */
71 retval = pciehp_check_link_status(ctrl);
72 if (retval) {
73 ctrl_err(ctrl, "Failed to check link status\n");
74 goto err_exit;
77 /* Check for a power fault */
78 if (ctrl->power_fault_detected || pciehp_query_power_fault(ctrl)) {
79 ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
80 retval = -EIO;
81 goto err_exit;
84 retval = pciehp_configure_device(ctrl);
85 if (retval) {
86 if (retval != -EEXIST) {
87 ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",
88 pci_domain_nr(parent), parent->number);
89 goto err_exit;
93 pciehp_green_led_on(ctrl);
94 pciehp_set_attention_status(ctrl, 0);
95 return 0;
97 err_exit:
98 set_slot_off(ctrl);
99 return retval;
103 * remove_board - Turns off slot and LEDs
104 * @ctrl: PCIe hotplug controller where board is being removed
105 * @safe_removal: whether the board is safely removed (versus surprise removed)
107 static void remove_board(struct controller *ctrl, bool safe_removal)
109 pciehp_unconfigure_device(ctrl, safe_removal);
111 if (POWER_CTRL(ctrl)) {
112 pciehp_power_off_slot(ctrl);
115 * After turning power off, we must wait for at least 1 second
116 * before taking any action that relies on power having been
117 * removed from the slot/adapter.
119 msleep(1000);
121 /* Ignore link or presence changes caused by power off */
122 atomic_and(~(PCI_EXP_SLTSTA_DLLSC | PCI_EXP_SLTSTA_PDC),
123 &ctrl->pending_events);
126 /* turn off Green LED */
127 pciehp_green_led_off(ctrl);
130 static int pciehp_enable_slot(struct controller *ctrl);
131 static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal);
133 void pciehp_request(struct controller *ctrl, int action)
135 atomic_or(action, &ctrl->pending_events);
136 if (!pciehp_poll_mode)
137 irq_wake_thread(ctrl->pcie->irq, ctrl);
140 void pciehp_queue_pushbutton_work(struct work_struct *work)
142 struct controller *ctrl = container_of(work, struct controller,
143 button_work.work);
145 mutex_lock(&ctrl->state_lock);
146 switch (ctrl->state) {
147 case BLINKINGOFF_STATE:
148 pciehp_request(ctrl, DISABLE_SLOT);
149 break;
150 case BLINKINGON_STATE:
151 pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);
152 break;
153 default:
154 break;
156 mutex_unlock(&ctrl->state_lock);
159 void pciehp_handle_button_press(struct controller *ctrl)
161 mutex_lock(&ctrl->state_lock);
162 switch (ctrl->state) {
163 case OFF_STATE:
164 case ON_STATE:
165 if (ctrl->state == ON_STATE) {
166 ctrl->state = BLINKINGOFF_STATE;
167 ctrl_info(ctrl, "Slot(%s): Powering off due to button press\n",
168 slot_name(ctrl));
169 } else {
170 ctrl->state = BLINKINGON_STATE;
171 ctrl_info(ctrl, "Slot(%s) Powering on due to button press\n",
172 slot_name(ctrl));
174 /* blink green LED and turn off amber */
175 pciehp_green_led_blink(ctrl);
176 pciehp_set_attention_status(ctrl, 0);
177 schedule_delayed_work(&ctrl->button_work, 5 * HZ);
178 break;
179 case BLINKINGOFF_STATE:
180 case BLINKINGON_STATE:
182 * Cancel if we are still blinking; this means that we
183 * press the attention again before the 5 sec. limit
184 * expires to cancel hot-add or hot-remove
186 ctrl_info(ctrl, "Slot(%s): Button cancel\n", slot_name(ctrl));
187 cancel_delayed_work(&ctrl->button_work);
188 if (ctrl->state == BLINKINGOFF_STATE) {
189 ctrl->state = ON_STATE;
190 pciehp_green_led_on(ctrl);
191 } else {
192 ctrl->state = OFF_STATE;
193 pciehp_green_led_off(ctrl);
195 pciehp_set_attention_status(ctrl, 0);
196 ctrl_info(ctrl, "Slot(%s): Action canceled due to button press\n",
197 slot_name(ctrl));
198 break;
199 default:
200 ctrl_err(ctrl, "Slot(%s): Ignoring invalid state %#x\n",
201 slot_name(ctrl), ctrl->state);
202 break;
204 mutex_unlock(&ctrl->state_lock);
207 void pciehp_handle_disable_request(struct controller *ctrl)
209 mutex_lock(&ctrl->state_lock);
210 switch (ctrl->state) {
211 case BLINKINGON_STATE:
212 case BLINKINGOFF_STATE:
213 cancel_delayed_work(&ctrl->button_work);
214 break;
216 ctrl->state = POWEROFF_STATE;
217 mutex_unlock(&ctrl->state_lock);
219 ctrl->request_result = pciehp_disable_slot(ctrl, SAFE_REMOVAL);
222 void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
224 bool present, link_active;
227 * If the slot is on and presence or link has changed, turn it off.
228 * Even if it's occupied again, we cannot assume the card is the same.
230 mutex_lock(&ctrl->state_lock);
231 switch (ctrl->state) {
232 case BLINKINGOFF_STATE:
233 cancel_delayed_work(&ctrl->button_work);
234 /* fall through */
235 case ON_STATE:
236 ctrl->state = POWEROFF_STATE;
237 mutex_unlock(&ctrl->state_lock);
238 if (events & PCI_EXP_SLTSTA_DLLSC)
239 ctrl_info(ctrl, "Slot(%s): Link Down\n",
240 slot_name(ctrl));
241 if (events & PCI_EXP_SLTSTA_PDC)
242 ctrl_info(ctrl, "Slot(%s): Card not present\n",
243 slot_name(ctrl));
244 pciehp_disable_slot(ctrl, SURPRISE_REMOVAL);
245 break;
246 default:
247 mutex_unlock(&ctrl->state_lock);
248 break;
251 /* Turn the slot on if it's occupied or link is up */
252 mutex_lock(&ctrl->state_lock);
253 present = pciehp_card_present(ctrl);
254 link_active = pciehp_check_link_active(ctrl);
255 if (!present && !link_active) {
256 mutex_unlock(&ctrl->state_lock);
257 return;
260 switch (ctrl->state) {
261 case BLINKINGON_STATE:
262 cancel_delayed_work(&ctrl->button_work);
263 /* fall through */
264 case OFF_STATE:
265 ctrl->state = POWERON_STATE;
266 mutex_unlock(&ctrl->state_lock);
267 if (present)
268 ctrl_info(ctrl, "Slot(%s): Card present\n",
269 slot_name(ctrl));
270 if (link_active)
271 ctrl_info(ctrl, "Slot(%s): Link Up\n",
272 slot_name(ctrl));
273 ctrl->request_result = pciehp_enable_slot(ctrl);
274 break;
275 default:
276 mutex_unlock(&ctrl->state_lock);
277 break;
281 static int __pciehp_enable_slot(struct controller *ctrl)
283 u8 getstatus = 0;
285 if (MRL_SENS(ctrl)) {
286 pciehp_get_latch_status(ctrl, &getstatus);
287 if (getstatus) {
288 ctrl_info(ctrl, "Slot(%s): Latch open\n",
289 slot_name(ctrl));
290 return -ENODEV;
294 if (POWER_CTRL(ctrl)) {
295 pciehp_get_power_status(ctrl, &getstatus);
296 if (getstatus) {
297 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
298 slot_name(ctrl));
299 return 0;
303 return board_added(ctrl);
306 static int pciehp_enable_slot(struct controller *ctrl)
308 int ret;
310 pm_runtime_get_sync(&ctrl->pcie->port->dev);
311 ret = __pciehp_enable_slot(ctrl);
312 if (ret && ATTN_BUTTN(ctrl))
313 pciehp_green_led_off(ctrl); /* may be blinking */
314 pm_runtime_put(&ctrl->pcie->port->dev);
316 mutex_lock(&ctrl->state_lock);
317 ctrl->state = ret ? OFF_STATE : ON_STATE;
318 mutex_unlock(&ctrl->state_lock);
320 return ret;
323 static int __pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
325 u8 getstatus = 0;
327 if (POWER_CTRL(ctrl)) {
328 pciehp_get_power_status(ctrl, &getstatus);
329 if (!getstatus) {
330 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
331 slot_name(ctrl));
332 return -EINVAL;
336 remove_board(ctrl, safe_removal);
337 return 0;
340 static int pciehp_disable_slot(struct controller *ctrl, bool safe_removal)
342 int ret;
344 pm_runtime_get_sync(&ctrl->pcie->port->dev);
345 ret = __pciehp_disable_slot(ctrl, safe_removal);
346 pm_runtime_put(&ctrl->pcie->port->dev);
348 mutex_lock(&ctrl->state_lock);
349 ctrl->state = OFF_STATE;
350 mutex_unlock(&ctrl->state_lock);
352 return ret;
355 int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot)
357 struct controller *ctrl = to_ctrl(hotplug_slot);
359 mutex_lock(&ctrl->state_lock);
360 switch (ctrl->state) {
361 case BLINKINGON_STATE:
362 case OFF_STATE:
363 mutex_unlock(&ctrl->state_lock);
365 * The IRQ thread becomes a no-op if the user pulls out the
366 * card before the thread wakes up, so initialize to -ENODEV.
368 ctrl->request_result = -ENODEV;
369 pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);
370 wait_event(ctrl->requester,
371 !atomic_read(&ctrl->pending_events));
372 return ctrl->request_result;
373 case POWERON_STATE:
374 ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
375 slot_name(ctrl));
376 break;
377 case BLINKINGOFF_STATE:
378 case ON_STATE:
379 case POWEROFF_STATE:
380 ctrl_info(ctrl, "Slot(%s): Already enabled\n",
381 slot_name(ctrl));
382 break;
383 default:
384 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
385 slot_name(ctrl), ctrl->state);
386 break;
388 mutex_unlock(&ctrl->state_lock);
390 return -ENODEV;
393 int pciehp_sysfs_disable_slot(struct hotplug_slot *hotplug_slot)
395 struct controller *ctrl = to_ctrl(hotplug_slot);
397 mutex_lock(&ctrl->state_lock);
398 switch (ctrl->state) {
399 case BLINKINGOFF_STATE:
400 case ON_STATE:
401 mutex_unlock(&ctrl->state_lock);
402 pciehp_request(ctrl, DISABLE_SLOT);
403 wait_event(ctrl->requester,
404 !atomic_read(&ctrl->pending_events));
405 return ctrl->request_result;
406 case POWEROFF_STATE:
407 ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
408 slot_name(ctrl));
409 break;
410 case BLINKINGON_STATE:
411 case OFF_STATE:
412 case POWERON_STATE:
413 ctrl_info(ctrl, "Slot(%s): Already disabled\n",
414 slot_name(ctrl));
415 break;
416 default:
417 ctrl_err(ctrl, "Slot(%s): Invalid state %#x\n",
418 slot_name(ctrl), ctrl->state);
419 break;
421 mutex_unlock(&ctrl->state_lock);
423 return -ENODEV;